The passfd module still doesn't pass mingw (no struct msghdr), but at least now it compiles and gives a sensible ENOSYS.
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. Signed-off-by: Eric Blake <[email protected]> --- ChangeLog | 12 ++++++++++++ lib/passfd.c | 44 +++++++++++++++++++++++++++++++------------- lib/sys_socket.in.h | 14 +++++++++++++- m4/afunix.m4 | 3 ++- modules/passfd-tests | 3 ++- modules/sys_socket | 1 + tests/test-passfd.c | 19 +++++++++++++++++-- tests/test-sys_socket.c | 14 +++++++++----- 8 files changed, 87 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4f8321a..ffc7bd7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,17 @@ 2011-04-21 Eric Blake <[email protected]> + 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. + sys_uio: new module * modules/sys_uio: New module. * modules/sys_uio-tests: Likewise. diff --git a/lib/passfd.c b/lib/passfd.c index 1ab94b4..5d4c6a7 100644 --- a/lib/passfd.c +++ b/lib/passfd.c @@ -24,7 +24,6 @@ #include <stdlib.h> #include <string.h> #include <sys/types.h> -#include <sys/uio.h> #include <unistd.h> #include <sys/socket.h> @@ -38,6 +37,7 @@ # 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. @@ -49,10 +49,10 @@ sendfd (int sock, int fd) 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); @@ -63,7 +63,7 @@ sendfd (int sock, int fd) 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); @@ -72,19 +72,29 @@ sendfd (int sock, int fd) 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>). @@ -97,11 +107,11 @@ recvfd (int sock, int flags) 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) { @@ -118,7 +128,7 @@ recvfd (int sock, int flags) 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); @@ -156,7 +166,7 @@ recvfd (int sock, int flags) } } -#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) @@ -173,9 +183,17 @@ recvfd (int sock, int flags) 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 diff --git a/lib/sys_socket.in.h b/lib/sys_socket.in.h index b60789f..f9e368b 100644 --- a/lib/sys_socket.in.h +++ b/lib/sys_socket.in.h @@ -146,7 +146,6 @@ struct sockaddr_storage suggests that getaddrinfo should be available on all Windows releases. */ - # if @HAVE_WINSOCK2_H@ # include <winsock2.h> # endif @@ -177,6 +176,19 @@ typedef int socklen_t; # 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@ diff --git a/m4/afunix.m4 b/m4/afunix.m4 index 13f7583..3f5eb44 100644 --- a/m4/afunix.m4 +++ b/m4/afunix.m4 @@ -1,4 +1,4 @@ -# 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, @@ -8,6 +8,7 @@ AC_DEFUN([gl_SOCKET_AFUNIX], [ 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], diff --git a/modules/passfd-tests b/modules/passfd-tests index 477754b..29e3ad9 100644 --- a/modules/passfd-tests +++ b/modules/passfd-tests @@ -3,9 +3,10 @@ tests/test-passfd.c 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 diff --git a/modules/sys_socket b/modules/sys_socket index 0e9fb4e..f5cd1f7 100644 --- a/modules/sys_socket +++ b/modules/sys_socket @@ -13,6 +13,7 @@ c++defs errno include_next socklen +sys_uio warn-on-use configure.ac: diff --git a/tests/test-passfd.c b/tests/test-passfd.c index d657ad9..315e6c2 100644 --- a/tests/test-passfd.c +++ b/tests/test-passfd.c @@ -18,6 +18,7 @@ #include "passfd.h" +#include <errno.h> #include <fcntl.h> #include <signal.h> #include <stdlib.h> @@ -33,6 +34,7 @@ int main () { +#if HAVE_SOCKETPAIR int pair[2]; int ret; pid_t pid; @@ -41,11 +43,11 @@ main () 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) @@ -115,4 +117,17 @@ main () } 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 } diff --git a/tests/test-sys_socket.c b/tests/test-sys_socket.c index 8f323ca..a6e99d6 100644 --- a/tests/test-sys_socket.c +++ b/tests/test-sys_socket.c @@ -30,6 +30,12 @@ int a[] = { SHUT_RD, SHUT_WR, SHUT_RDWR }; /* 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) { @@ -51,10 +57,8 @@ 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); } -- 1.7.4.4
