summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog12
-rw-r--r--lib/passfd.c49
-rw-r--r--lib/passfd.h2
-rw-r--r--m4/afunix.m429
-rw-r--r--modules/passfd1
5 files changed, 89 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index ebef64b538..74afdbb3b6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2011-03-13 Bastien Roucariès <roucaries.bastien@gmail.com>
+ Bruno Haible <bruno@clisp.org>
+
+ passfd module, part 3.
+ * lib/passfd.h (recvfd): Add a flags argument.
+ * lib/passfd.c: Include <fcntl.h>, cloexec.h.
+ (recvfd): Add a flags argument.
+ * m4/afunix.m4 (gl_SOCKET_AFUNIX): Test whether MSG_CMSG_CLOEXEC
+ exists.
+ * modules/passfd (Depends-on): Add cloexec.
+ Suggested by Eric Blake.
+
2011-03-13 Bruno Haible <bruno@clisp.org>
passfd module, part 2, tweaks.
diff --git a/lib/passfd.c b/lib/passfd.c
index 127fc42cda..d694ba6e0c 100644
--- a/lib/passfd.c
+++ b/lib/passfd.c
@@ -19,6 +19,7 @@
#include "passfd.h"
#include <errno.h>
+#include <fcntl.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
@@ -30,6 +31,8 @@
# include <sys/un.h>
#endif
+#include "cloexec.h"
+
/* sendfd sends the file descriptor fd along the socket
to a process calling recvfd on the other end.
@@ -79,16 +82,23 @@ sendfd (int sock, int fd)
}
/* 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.
*/
int
-recvfd (int sock)
+recvfd (int sock, int flags)
{
char recv = 0;
struct iovec iov[1];
struct msghdr msg;
+ if ((flags & ~O_CLOEXEC) != 0)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
/* send at least one char */
iov[0].iov_base = &recv;
iov[0].iov_len = 1;
@@ -103,6 +113,11 @@ recvfd (int sock)
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
msg.msg_control = buf;
msg.msg_controllen = sizeof (buf);
@@ -114,7 +129,7 @@ recvfd (int sock)
memcpy (CMSG_DATA (cmsg), &mone, sizeof (mone));
msg.msg_controllen = cmsg->cmsg_len;
- if (recvmsg (sock, &msg, 0) < 0)
+ if (recvmsg (sock, &msg, flags_recvmsg) < 0)
return -1;
cmsg = CMSG_FIRSTHDR (&msg);
@@ -128,7 +143,23 @@ recvfd (int sock)
}
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;
@@ -136,7 +167,21 @@ recvfd (int sock)
msg.msg_accrightslen = sizeof (fd);
if (recvmsg (sock, &msg, 0) < 0)
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;
+ }
+ }
+
return fd;
+
#else
errno = ENOSYS;
return -1;
diff --git a/lib/passfd.h b/lib/passfd.h
index 1fef2ddf23..048d9c8fc3 100644
--- a/lib/passfd.h
+++ b/lib/passfd.h
@@ -23,7 +23,7 @@ extern "C" {
#endif
extern int sendfd (int sock, int fd);
-extern int recvfd (int sock);
+extern int recvfd (int sock, int flags);
#ifdef __cplusplus
}
diff --git a/m4/afunix.m4 b/m4/afunix.m4
index 8095ae921d..fdedeba673 100644
--- a/m4/afunix.m4
+++ b/m4/afunix.m4
@@ -1,4 +1,4 @@
-# afunix.m4 serial 2
+# afunix.m4 serial 3
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,
@@ -109,4 +109,31 @@ AC_DEFUN([gl_SOCKET_AFUNIX],
AC_DEFINE([HAVE_UNIXSOCKET_SCM_RIGHTS_BSD43_WAY], [1],
[Define to 1 if fd can be sent/received in the BSD4.3 way.])
fi
+
+ AC_MSG_CHECKING([for UNIX domain sockets recvmsg() MSG_CMSG_CLOEXEC flag])
+ AC_CACHE_VAL([gl_cv_socket_unix_msg_cmsg_cloexec],
+ [AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <sys/types.h>
+ #ifdef HAVE_SYS_SOCKET_H
+ #include <sys/socket.h>
+ #endif
+ #ifdef HAVE_SYS_UN_H
+ #include <sys/un.h>
+ #endif
+ #ifdef HAVE_WINSOCK2_H
+ #include <winsock2.h>
+ #endif
+ ]],
+ [[int flags = MSG_CMSG_CLOEXEC;
+ if (&flags) return 0;
+ ]])],
+ [gl_cv_socket_unix_msg_cmsg_cloexec=yes],
+ [gl_cv_socket_unix_msg_cmsg_cloexec=no])
+ ])
+ AC_MSG_RESULT([$gl_cv_socket_unix_msg_cmsg_cloexec])
+ if test $gl_cv_socket_unix_msg_cmsg_cloexec = yes; then
+ AC_DEFINE([HAVE_MSG_CMSG_CLOEXEC], [1],
+ [Define to 1 if recvmsg could be specified with MSG_CMSG_CLOEXEC.])
+ fi
])
diff --git a/modules/passfd b/modules/passfd
index dc1e68cf01..bdcd9c5c68 100644
--- a/modules/passfd
+++ b/modules/passfd
@@ -8,6 +8,7 @@ m4/afunix.m4
m4/sockpfaf.m4
Depends-on:
+cloexec
sys_socket
extensions