unistd-safer: allow preservation of cloexec status via flag
authorEric Blake <ebb9@byu.net>
Sat, 5 Dec 2009 13:36:33 +0000 (06:36 -0700)
committerEric Blake <ebb9@byu.net>
Sat, 5 Dec 2009 21:36:40 +0000 (14:36 -0700)
If cloexec is in use, allow the ability to preserve cloexec
flag across *_safer functions.

* lib/unistd-safer.h (dup_safer_flag, fd_safer_flag): New
prototypes.
* lib/dup-safer.c (dup_safer_flag): New function.
* lib/fd-safer.c (fd_safer_flag): Likewise.
* modules/cloexec (configure.ac): Set witness.

Signed-off-by: Eric Blake <ebb9@byu.net>
ChangeLog
lib/dup-safer.c
lib/fd-safer.c
lib/unistd-safer.h
modules/cloexec

index 0c1c870..20535a0 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2009-12-05  Eric Blake  <ebb9@byu.net>
 
+       unistd-safer: allow preservation of cloexec status via flag
+       * lib/unistd-safer.h (dup_safer_flag, fd_safer_flag): New
+       prototypes.
+       * lib/dup-safer.c (dup_safer_flag): New function.
+       * lib/fd-safer.c (fd_safer_flag): Likewise.
+       * modules/cloexec (configure.ac): Set witness.
+
        test-dup2: enhance test
        * modules/dup2-tests (Depends-on): Add cloexec.
        * tests/test-dup2.c (main): Enhance test.
index 22b96ba..2af8b6a 100644 (file)
@@ -23,7 +23,6 @@
 #include "unistd-safer.h"
 
 #include <fcntl.h>
-
 #include <unistd.h>
 
 /* Like dup, but do not return STDIN_FILENO, STDOUT_FILENO, or
@@ -40,3 +39,34 @@ dup_safer (int fd)
   return fd_safer (dup (fd));
 #endif
 }
+
+#if GNULIB_CLOEXEC
+
+# include "cloexec.h"
+
+# ifndef O_CLOEXEC
+#  define O_CLOEXEC 0
+# endif
+
+/* Like dup, but do not return STDIN_FILENO, STDOUT_FILENO, or
+   STDERR_FILENO.  If FLAG contains O_CLOEXEC, behave like
+   fcntl(F_DUPFD_CLOEXEC) rather than fcntl(F_DUPFD).  */
+
+int
+dup_safer_flag (int fd, int flag)
+{
+  if (flag & O_CLOEXEC)
+    {
+# if defined F_DUPFD_CLOEXEC && !REPLACE_FCHDIR
+      return fcntl (fd, F_DUPFD_CLOEXEC, STDERR_FILENO + 1);
+# else
+      /* fd_safer_flag calls us back, but eventually the recursion
+         unwinds and does the right thing.  */
+      fd = dup_cloexec (fd);
+      return fd_safer_flag (fd, flag);
+# endif
+    }
+  return dup_safer (fd);
+}
+
+#endif
index fb99001..d2e1309 100644 (file)
@@ -48,3 +48,32 @@ fd_safer (int fd)
 
   return fd;
 }
+
+#if GNULIB_CLOEXEC
+
+/* Return FD, unless FD would be a copy of standard input, output, or
+   error; in that case, return a duplicate of FD, closing FD.  If FLAG
+   contains O_CLOEXEC, the returned FD will have close-on-exec
+   semantics.  On failure to duplicate, close FD, set errno, and
+   return -1.  Preserve errno if FD is negative, so that the caller
+   can always inspect errno when the returned value is negative.
+
+   This function is usefully wrapped around functions that return file
+   descriptors, e.g., fd_safer_flag (open ("file", O_RDONLY | flag), flag).  */
+
+int
+fd_safer_flag (int fd, int flag)
+{
+  if (STDIN_FILENO <= fd && fd <= STDERR_FILENO)
+    {
+      int f = dup_safer_flag (fd, flag);
+      int e = errno;
+      close (fd);
+      errno = e;
+      fd = f;
+    }
+
+  return fd;
+}
+
+#endif /* GNULIB_CLOEXEC */
index 033e857..af7d4ea 100644 (file)
@@ -1,6 +1,6 @@
 /* Invoke unistd-like functions, but avoid some glitches.
 
-   Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2003, 2005, 2009 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
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
-/* Written by Paul Eggert.  */
+/* Written by Paul Eggert and Eric Blake.  */
 
 int dup_safer (int);
 int fd_safer (int);
 int pipe_safer (int[2]);
+
+#if GNULIB_CLOEXEC
+int dup_safer_flag (int, int);
+int fd_safer_flag (int, int);
+#endif
index 7e41fec..7d987de 100644 (file)
@@ -12,6 +12,7 @@ stdbool
 
 configure.ac:
 gl_CLOEXEC
+gl_MODULE_INDICATOR([cloexec])
 
 Makefile.am: