X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fpassfd.c;h=5388ca567c2e4fc982d0b0d1f5bc0be0ab847ca6;hb=beae0bdcf7fe30f2415c16f6b8c1368d469e519c;hp=573b80e450aa9475e8ad46f6f3f0a1da1465e131;hpb=b24d8be2672089058c92924326da82a05a703d1d;p=gnulib.git diff --git a/lib/passfd.c b/lib/passfd.c index 573b80e45..5388ca567 100644 --- a/lib/passfd.c +++ b/lib/passfd.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2011 Free Software Foundation, Inc. +/* Copyright (C) 2011-2013 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,16 +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. @@ -42,57 +49,73 @@ int sendfd (int sock, int fd) { - char send = 0; - struct iovec iov[1]; + 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 */ - iov[0].iov_base = &send; - iov[0].iov_len = 1; - msg.msg_iov = iov; + memset (&msg, 0, sizeof msg); + iov.iov_base = &byte; + iov.iov_len = 1; + msg.msg_iov = &iov; msg.msg_iovlen = 1; - msg.msg_name = 0; + 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 (int)); - /* Initialize the payload: */ - memcpy (CMSG_DATA (cmsg), &fd, sizeof (fd)); - msg.msg_controllen = cmsg->cmsg_len; -#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[0].iov_len) + 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; - struct iovec iov[1]; + 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) { @@ -101,91 +124,81 @@ recvfd (int sock, int flags) } /* send at least one char */ - iov[0].iov_base = &recv; - iov[0].iov_len = 1; - msg.msg_iov = iov; + memset (&msg, 0, sizeof msg); + iov.iov_base = &byte; + iov.iov_len = 1; + msg.msg_iov = &iov; msg.msg_iovlen = 1; - msg.msg_name = 0; + 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; -# if HAVE_MSG_CMSG_CLOEXEC - int flags_recvmsg = (flags & O_CLOEXEC ? MSG_CMSG_CLOEXEC : 0); -# else - int flags_recvmsg = 0; -# 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); + msg.msg_controllen = cmsg->cmsg_len; + + len = recvmsg (sock, &msg, flags_recvmsg); + if (len < 0) + return -1; - 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 (int)); - /* Initialize the payload: */ - memcpy (CMSG_DATA (cmsg), &mone, sizeof (mone)); - msg.msg_controllen = cmsg->cmsg_len; - - if (recvmsg (sock, &msg, flags_recvmsg) < 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; + } - cmsg = CMSG_FIRSTHDR (&msg); - /* be paranoiac */ - if (cmsg == NULL || cmsg->cmsg_len != CMSG_LEN (sizeof (int)) - || 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)); - -# if !HAVE_MSG_CMSG_CLOEXEC - /* set close-on-exec flag */ - if (flags & O_CLOEXEC) - { - if (set_cloexec_flag (fd, true) < 0) - { - int saved_errno = errno; - (void) close (fd); - errno = saved_errno; - return -1; - } - } -# endif - - return fd; - -#elif HAVE_UNIXSOCKET_SCM_RIGHTS_BSD43_WAY - int fd; + memcpy (&fd, CMSG_DATA (cmsg), sizeof fd); - msg.msg_accrights = &fd; - msg.msg_accrightslen = sizeof (fd); - if (recvmsg (sock, &msg, 0) < 0) - return -1; + /* 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; + } + } - /* set close-on-exec flag */ - if (flags & O_CLOEXEC) - { - if (set_cloexec_flag (fd, true) < 0) - { - int saved_errno = errno; - (void) close (fd); - errno = saved_errno; - return -1; - } - } +# elif HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS + msg.msg_accrights = &fd; + msg.msg_accrightslen = sizeof fd; + if (recvmsg (sock, &msg, 0) < 0) + return -1; - return fd; + /* 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 - errno = ENOSYS; - return -1; -#endif - } +int +recvfd (int sock _GL_UNUSED, int flags _GL_UNUSED) +{ + errno = ENOSYS; + return -1; } +#endif