-/* 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
#include <unistd.h>
#include <sys/socket.h>
-#if HAVE_SYS_UN_H
-# include <sys/un.h>
-#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.
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 <fcntl.h>).
- 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;
+# 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)
{
}
/* 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;
+
+ if (recvmsg (sock, &msg, flags_recvmsg) < 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 (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;
+ }
- 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