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.
#include "unistd-safer.h"
#include <fcntl.h>
-
#include <unistd.h>
/* Like dup, but do not return STDIN_FILENO, STDOUT_FILENO, or
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
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 */
/* 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
configure.ac:
gl_CLOEXEC
+gl_MODULE_INDICATOR([cloexec])
Makefile.am: