The passfd module now skips on mingw, rather than failing to compile.
It may be nice to add a sendmsg and recvmsg module in the future,
but for now passfd is the only client that cares.
* modules/sys_socket (Depends-on): Add sys_uio.
* lib/sys_socket.in.h [!@HAVE_SYS_SOCKET_H@]: Use it for struct
iovec and a minimal struct msghdr.
* tests/test-sys_socket.c (main): Enhance test.
* m4/afunix.m4 (gl_SOCKET_AFUNIX): Detect recvmsg/sendmsg.
* lib/passfd.c (include): Drop <sys/uio.h>; <sys/sockets.h> is
guaranteed to provide what we need.
(sendmsg, recvmsg): Declare fallbacks if we lack sendmsg.
* modules/passfd-tests (Depends-on): Add sys_wait.
* tests/test-passfd.c (main): Skip test on mingw, for now.
* doc/posix-headers/sys_socket.texi (sys/socket.h): Document the
partial 'struct msghdr' implementation.
Signed-off-by: Eric Blake <eblake@redhat.com>
2011-04-21 Eric Blake <eblake@redhat.com>
+ passfd: allow compilation on mingw
+ * modules/sys_socket (Depends-on): Add sys_uio.
+ * lib/sys_socket.in.h [!@HAVE_SYS_SOCKET_H@]: Use it for struct
+ iovec and a minimal struct msghdr.
+ * m4/afunix.m4 (gl_SOCKET_AFUNIX): Detect recvmsg/sendmsg.
+ * tests/test-sys_socket.c (main): Enhance test.
+ * lib/passfd.c (include): Drop <sys/uio.h>; <sys/sockets.h> is
+ guaranteed to provide what we need.
+ (sendmsg, recvmsg): Declare fallbacks if we lack sendmsg.
+ * modules/passfd-tests (Depends-on): Add sys_wait.
+ * tests/test-passfd.c (main): Skip test on mingw, for now.
+ * doc/posix-headers/sys_socket.texi (sys/socket.h): Document the
+ partial 'struct msghdr' implementation.
+
sys_uio: new module
* modules/sys_uio: New module.
* modules/sys_uio-tests: Likewise.
Portability problems not fixed by Gnulib:
@itemize
+@item
+This header file does not declare the @code{msg_control} and
+@code{msg_controllen} members of @code{struct msghdr} on some
+platforms. This can be detected by the absence of the
+@code{CMSG_FIRSTHDR} macro:
+gnulib replacement header, old BSD
@end itemize
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
-#include <sys/uio.h>
#include <unistd.h>
#include <sys/socket.h>
# define MSG_CMSG_CLOEXEC 0
#endif
+#if HAVE_SENDMSG
/* sendfd sends the file descriptor fd along the socket
to a process calling recvfd on the other end.
char send = 0;
struct iovec iov;
struct msghdr msg;
-#if HAVE_UNIXSOCKET_SCM_RIGHTS_BSD44_WAY
+# if HAVE_UNIXSOCKET_SCM_RIGHTS_BSD44_WAY
struct cmsghdr *cmsg;
char buf[CMSG_SPACE (sizeof fd)];
-#endif
+# endif
/* send at least one char */
memset (&msg, 0, sizeof msg);
msg.msg_name = NULL;
msg.msg_namelen = 0;
-#if HAVE_UNIXSOCKET_SCM_RIGHTS_BSD44_WAY
+# if HAVE_UNIXSOCKET_SCM_RIGHTS_BSD44_WAY
msg.msg_control = buf;
msg.msg_controllen = sizeof buf;
cmsg = CMSG_FIRSTHDR (&msg);
cmsg->cmsg_len = CMSG_LEN (sizeof fd);
/* Initialize the payload: */
memcpy (CMSG_DATA (cmsg), &fd, sizeof fd);
-#elif HAVE_UNIXSOCKET_SCM_RIGHTS_BSD43_WAY
+# elif HAVE_UNIXSOCKET_SCM_RIGHTS_BSD43_WAY
msg.msg_accrights = &fd;
msg.msg_accrightslen = sizeof fd;
-#else
+# else
errno = ENOSYS;
return -1;
-#endif
+# endif
if (sendmsg (sock, &msg, 0) != iov.iov_len)
return -1;
return 0;
}
+#else
+int
+sendfd (int sock _GL_UNUSED, int fd _GL_UNUSED)
+{
+ errno = ENOSYS;
+ return -1;
+}
+#endif
+
+#if HAVE_RECVMSG
/* recvfd receives a file descriptor through the socket.
The flags are a bitmask, possibly including O_CLOEXEC (defined in <fcntl.h>).
struct iovec iov;
struct msghdr msg;
int fd = -1;
-#if HAVE_UNIXSOCKET_SCM_RIGHTS_BSD44_WAY
+# if HAVE_UNIXSOCKET_SCM_RIGHTS_BSD44_WAY
struct cmsghdr *cmsg;
char buf[CMSG_SPACE (sizeof fd)];
int flags_recvmsg = flags & O_CLOEXEC ? MSG_CMSG_CLOEXEC : 0;
-#endif
+# endif
if ((flags & ~O_CLOEXEC) != 0)
{
msg.msg_name = NULL;
msg.msg_namelen = 0;
-#if HAVE_UNIXSOCKET_SCM_RIGHTS_BSD44_WAY
+# if HAVE_UNIXSOCKET_SCM_RIGHTS_BSD44_WAY
msg.msg_control = buf;
msg.msg_controllen = sizeof buf;
cmsg = CMSG_FIRSTHDR (&msg);
}
}
-#elif HAVE_UNIXSOCKET_SCM_RIGHTS_BSD43_WAY
+# elif HAVE_UNIXSOCKET_SCM_RIGHTS_BSD43_WAY
msg.msg_accrights = &fd;
msg.msg_accrightslen = sizeof fd;
if (recvmsg (sock, &msg, 0) < 0)
return -1;
}
}
-#else
+# else
errno = ENOSYS;
-#endif
+# endif
return fd;
}
+#else
+int
+recvfd (int sock _GL_UNUSED, int flags _GL_UNUSED)
+{
+ errno = ENOSYS;
+ return -1;
+}
+#endif
suggests that getaddrinfo should be available on all Windows
releases. */
-
# if @HAVE_WINSOCK2_H@
# include <winsock2.h>
# endif
# endif
+/* For struct iovec */
+# include <sys/uio.h>
+
+/* Rudimentary 'struct msghdr'; this works as long as you don't try to
+ access msg_control or msg_controllen. */
+struct msghdr {
+ void *msg_name;
+ socklen_t msg_namelen;
+ struct iovec *msg_iov;
+ int msg_iovlen;
+ int msg_flags;
+};
+
#endif
#if @HAVE_WINSOCK2_H@
-# afunix.m4 serial 6
+# afunix.m4 serial 7
dnl Copyright (C) 2011 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
[
AC_REQUIRE([gl_HEADER_SYS_SOCKET])
AC_REQUIRE([gl_SOCKET_FAMILY_UNIX])
+ AC_CHECK_FUNCS_ONCE([recvmsg sendmsg])
AC_MSG_CHECKING([for UNIX domain sockets SCM_RIGHTS])
AC_CACHE_VAL([gl_cv_socket_unix_scm_rights],
tests/macros.h
Depends-on:
+sys_wait
configure.ac:
-AC_CHECK_DECLS_ONCE([alarm])
+AC_CHECK_DECLS_ONCE([alarm socketpair])
Makefile.am:
TESTS += test-passfd
errno
include_next
socklen
+sys_uio
warn-on-use
configure.ac:
#include "passfd.h"
+#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdlib.h>
int
main ()
{
+#if HAVE_SOCKETPAIR
int pair[2];
int ret;
pid_t pid;
int fd;
struct stat st;
-#if HAVE_DECL_ALARM
+# if HAVE_DECL_ALARM
/* Avoid hanging on failure. */
signal (SIGALRM, SIG_DFL);
alarm (5);
-#endif
+# endif
fdnull = open ("/dev/null", O_RDWR);
if (fdnull < 0)
}
return 0;
}
+#else
+ errno = 0;
+ ASSERT(sendfd (0, 0) == -1);
+ ASSERT(errno == ENOSYS);
+
+ errno = 0;
+ ASSERT(recvfd (0, 0) == -1);
+ ASSERT(errno == ENOSYS);
+
+ fputs ("skipping test: socketpair not supported on this system\n",
+ stderr);
+ return 77;
+#endif
}
/* Check that the 'socklen_t' type is defined. */
socklen_t t1;
+/* Check that 'struct iovec' is defined. */
+struct iovec io;
+
+/* Check that a minimal set of 'struct msghdr' is defined. */
+struct msghdr msg;
+
int
main (void)
{
x.ss_family = 42;
i = 42;
+ msg.msg_iov = &io;
- /* Tell the compiler that these variables are used. */
- (void) x;
- (void) i;
-
- return 0;
+ return (x.ss_family - i + msg.msg_namelen + msg.msg_iov->iov_len
+ + msg.msg_iovlen);
}