about summary refs log tree commit diff
path: root/src/libutil
diff options
context:
space:
mode:
Diffstat (limited to 'src/libutil')
-rw-r--r--src/libutil/util.cc22
-rw-r--r--src/libutil/util.hh4
2 files changed, 24 insertions, 2 deletions
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index 4f6c367da8..c28f4e1bb7 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -579,7 +579,14 @@ AutoCloseFD::AutoCloseFD(int fd)
 
 AutoCloseFD::AutoCloseFD(const AutoCloseFD & fd)
 {
-    abort();
+    /* Copying a AutoCloseFD isn't allowed (who should get to close
+       it?).  But as a edge case, allow copying of closed
+       AutoCloseFDs.  This is necessary due to tiresome reasons
+       involving copy constructor use on default object values in STL
+       containers (like when you do `map[value]' where value isn't in
+       the map yet). */
+    this->fd = fd.fd;
+    if (this->fd != -1) abort();
 }
 
 
@@ -832,7 +839,7 @@ string runProgram(Path program, bool searchPath, const Strings & args)
             pipe.readSide.close();
 
             if (dup2(pipe.writeSide, STDOUT_FILENO) == -1)
-                throw SysError("dupping from-hook write side");
+                throw SysError("dupping stdout");
 
             std::vector<const char *> cargs; /* careful with c_str()! */
             cargs.push_back(program.c_str());
@@ -868,6 +875,17 @@ string runProgram(Path program, bool searchPath, const Strings & args)
 }
 
 
+void closeMostFDs(const set<int> & exceptions)
+{
+    int maxFD = 0;
+    maxFD = sysconf(_SC_OPEN_MAX);
+    for (int fd = 0; fd < maxFD; ++fd)
+        if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO
+            && exceptions.find(fd) == exceptions.end())
+            close(fd); /* ignore result */
+}
+
+
 void quickExit(int status)
 {
 #ifdef __CYGWIN__
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index 5d28a8308c..6c67e450b5 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -245,6 +245,10 @@ void killUser(uid_t uid);
 string runProgram(Path program, bool searchPath = false,
     const Strings & args = Strings());
 
+/* Close all file descriptors except stdin, stdout, stderr, and those
+   listed in the given set.  Good practice in child processes. */
+void closeMostFDs(const set<int> & exceptions);
+
 /* Wrapper around _exit() on Unix and ExitProcess() on Windows.  (On
    Cygwin, _exit() doesn't seem to do the right thing.) */
 void quickExit(int status);