X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=lib%2Fpassfd.c;h=52e115e3c9a0865491a2e69fce583a803f561de9;hb=458c944ddbb41cd6ba34416db2867eb6f17bf61a;hp=6784659414f1521dcefa5bb9ed78d714138d9a58;hpb=2f681c52f62c1bb9c9dd3fe5cd7a32ec384c34c7;p=gnulib.git diff --git a/lib/passfd.c b/lib/passfd.c index 678465941..52e115e3c 100644 --- a/lib/passfd.c +++ b/lib/passfd.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2011 Free Software Foundation, Inc. +/* Copyright (C) 2011-2014 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,20 +24,23 @@ #include #include #include -#include #include #include -#if HAVE_SYS_UN_H -# include -#endif #include "cloexec.h" +/* The code that uses CMSG_FIRSTHDR is enabled on + Linux, Mac OS X, FreeBSD, OpenBSD, NetBSD, AIX, OSF/1, Cygwin. + The code that uses HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS is enabled on + HP-UX, IRIX, Solaris. */ + +/* MSG_CMSG_CLOEXEC is defined only on Linux, as of 2011. */ #ifndef MSG_CMSG_CLOEXEC # 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. @@ -46,57 +49,73 @@ int sendfd (int sock, int fd) { - char send = 0; + char byte = 0; struct iovec iov; struct msghdr msg; +# ifdef CMSG_FIRSTHDR + struct cmsghdr *cmsg; + char buf[CMSG_SPACE (sizeof fd)]; +# endif /* send at least one char */ memset (&msg, 0, sizeof msg); - iov.iov_base = &send; + iov.iov_base = &byte; iov.iov_len = 1; msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_name = NULL; msg.msg_namelen = 0; - { -#if HAVE_UNIXSOCKET_SCM_RIGHTS_BSD44_WAY - struct cmsghdr *cmsg; - char buf[CMSG_SPACE (sizeof fd)]; - - msg.msg_control = buf; - msg.msg_controllen = sizeof buf; - cmsg = CMSG_FIRSTHDR (&msg); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN (sizeof fd); - /* Initialize the payload: */ - memcpy (CMSG_DATA (cmsg), &fd, sizeof fd); -#elif HAVE_UNIXSOCKET_SCM_RIGHTS_BSD43_WAY - msg.msg_accrights = &fd; - msg.msg_accrightslen = sizeof fd; -#else - errno = ENOSYS; - return -1; -#endif - } +# ifdef CMSG_FIRSTHDR + msg.msg_control = buf; + msg.msg_controllen = sizeof buf; + cmsg = CMSG_FIRSTHDR (&msg); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN (sizeof fd); + /* Initialize the payload: */ + memcpy (CMSG_DATA (cmsg), &fd, sizeof fd); +# elif HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS + msg.msg_accrights = &fd; + msg.msg_accrightslen = sizeof fd; +# else + errno = ENOSYS; + return -1; +# 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 ). - Return 0 on success, or -1 with errno set in case of error. + Return the fd on success, or -1 with errno set in case of error. */ int recvfd (int sock, int flags) { - char recv = 0; + char byte = 0; struct iovec iov; struct msghdr msg; + int fd = -1; + ssize_t len; +# ifdef CMSG_FIRSTHDR + struct cmsghdr *cmsg; + char buf[CMSG_SPACE (sizeof fd)]; + int flags_recvmsg = flags & O_CLOEXEC ? MSG_CMSG_CLOEXEC : 0; +# endif if ((flags & ~O_CLOEXEC) != 0) { @@ -105,85 +124,81 @@ recvfd (int sock, int flags) } /* send at least one char */ - iov.iov_base = &recv; + memset (&msg, 0, sizeof msg); + iov.iov_base = &byte; iov.iov_len = 1; msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_name = NULL; msg.msg_namelen = 0; - { -#if HAVE_UNIXSOCKET_SCM_RIGHTS_BSD44_WAY - int fd; - struct cmsghdr *cmsg; - char buf[CMSG_SPACE (sizeof fd)]; - const int mone = -1; - int flags_recvmsg = flags & O_CLOEXEC ? MSG_CMSG_CLOEXEC : 0; - - msg.msg_control = buf; - msg.msg_controllen = sizeof buf; - cmsg = CMSG_FIRSTHDR (&msg); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN (sizeof mone); - /* Initialize the payload: */ - memcpy (CMSG_DATA (cmsg), &mone, sizeof mone); - msg.msg_controllen = cmsg->cmsg_len; - - if (recvmsg (sock, &msg, flags_recvmsg) < 0) - return -1; +# ifdef CMSG_FIRSTHDR + msg.msg_control = buf; + msg.msg_controllen = sizeof buf; + cmsg = CMSG_FIRSTHDR (&msg); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN (sizeof fd); + /* Initialize the payload: */ + memcpy (CMSG_DATA (cmsg), &fd, sizeof fd); + msg.msg_controllen = cmsg->cmsg_len; + + len = recvmsg (sock, &msg, flags_recvmsg); + if (len < 0) + return -1; - cmsg = CMSG_FIRSTHDR (&msg); - /* be paranoiac */ - if (cmsg == NULL || cmsg->cmsg_len != CMSG_LEN (sizeof fd) - || cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) - { - /* fake errno: at end the file is not available */ - errno = EACCES; - return -1; - } - - memcpy (&fd, CMSG_DATA (cmsg), sizeof fd); - - /* set close-on-exec flag */ - if (!MSG_CMSG_CLOEXEC && (flags & O_CLOEXEC)) - { - if (set_cloexec_flag (fd, true) < 0) - { - int saved_errno = errno; - (void) close (fd); - errno = saved_errno; - return -1; - } - } - - return fd; - -#elif HAVE_UNIXSOCKET_SCM_RIGHTS_BSD43_WAY - int fd; - - msg.msg_accrights = &fd; - msg.msg_accrightslen = sizeof fd; - if (recvmsg (sock, &msg, 0) < 0) + cmsg = CMSG_FIRSTHDR (&msg); + /* be paranoiac */ + if (len == 0 || cmsg == NULL || cmsg->cmsg_len != CMSG_LEN (sizeof fd) + || cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) + { + /* fake errno: at end the file is not available */ + errno = len ? EACCES : ENOTCONN; return -1; + } - /* set close-on-exec flag */ - if (flags & O_CLOEXEC) - { - if (set_cloexec_flag (fd, true) < 0) - { - int saved_errno = errno; - close (fd); - errno = saved_errno; - return -1; - } - } + memcpy (&fd, CMSG_DATA (cmsg), sizeof fd); - return fd; + /* set close-on-exec flag */ + if (!MSG_CMSG_CLOEXEC && (flags & O_CLOEXEC)) + { + if (set_cloexec_flag (fd, true) < 0) + { + int saved_errno = errno; + (void) close (fd); + errno = saved_errno; + return -1; + } + } -#else - errno = ENOSYS; +# elif HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS + msg.msg_accrights = &fd; + msg.msg_accrightslen = sizeof fd; + if (recvmsg (sock, &msg, 0) < 0) return -1; -#endif - } + + /* set close-on-exec flag */ + if (flags & O_CLOEXEC) + { + if (set_cloexec_flag (fd, true) < 0) + { + int saved_errno = errno; + close (fd); + errno = saved_errno; + return -1; + } + } +# else + errno = ENOSYS; +# endif + + return fd; } +#else +int +recvfd (int sock _GL_UNUSED, int flags _GL_UNUSED) +{ + errno = ENOSYS; + return -1; +} +#endif