summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorStef Walter <stefw@gnome.org>2013-02-20 11:50:25 +0100
committerStef Walter <stef@thewalter.net>2014-07-08 08:57:30 +0200
commitccc5e1569b360b54962e7f4cfaded8ab466b021d (patch)
tree8908ce3a797b5f97c5fce134dd1e72dcdbc44aa9 /common
parentc785ab66890ad7b73c556d6afdf2bb8a32dd50e2 (diff)
Add compatibility fdwalk() function
This is used when execing another process to close all open file descriptors that we don't wish to be inherited.
Diffstat (limited to 'common')
-rw-r--r--common/compat.c73
-rw-r--r--common/compat.h7
2 files changed, 80 insertions, 0 deletions
diff --git a/common/compat.c b/common/compat.c
index fef618b..9314d20 100644
--- a/common/compat.c
+++ b/common/compat.c
@@ -37,6 +37,7 @@
#include "compat.h"
#include <assert.h>
+#include <dirent.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
@@ -81,6 +82,8 @@
#ifdef OS_UNIX
+#include <unistd.h>
+
#if defined (HAVE_PROGRAM_INVOCATION_SHORT_NAME) && !HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
extern char *program_invocation_short_name;
#endif
@@ -866,3 +869,73 @@ strerror_r (int errnum,
}
#endif /* HAVE_STRERROR_R */
+
+#ifdef OS_UNIX
+
+#include <unistd.h>
+
+#ifndef HAVE_FDWALK
+
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
+int
+fdwalk (int (* cb) (void *data, int fd),
+ void *data)
+{
+ struct dirent *de;
+ char *end;
+ DIR *dir;
+ int open_max;
+ long num;
+ int res = 0;
+ int fd;
+
+#ifdef HAVE_SYS_RESOURCE_H
+ struct rlimit rl;
+#endif
+
+ dir = opendir ("/proc/self/fd");
+ if (dir != NULL) {
+ while ((de = readdir (dir)) != NULL) {
+ end = NULL;
+ num = (int) strtol (de->d_name, &end, 10);
+
+ /* didn't parse or is the opendir() fd */
+ if (!end || *end != '\0' ||
+ (int)num == dirfd (dir))
+ continue;
+
+ fd = num;
+
+ /* call the callback */
+ res = cb (data, fd);
+ if (res != 0)
+ break;
+ }
+
+ closedir (dir);
+ return res;
+ }
+
+ /* No /proc, brute force */
+#ifdef HAVE_SYS_RESOURCE_H
+ if (getrlimit (RLIMIT_NOFILE, &rl) == 0 && rl.rlim_max != RLIM_INFINITY)
+ open_max = rl.rlim_max;
+ else
+#endif
+ open_max = sysconf (_SC_OPEN_MAX);
+
+ for (fd = 0; fd < open_max; fd++) {
+ res = cb (data, fd);
+ if (res != 0)
+ break;
+ }
+
+ return res;
+}
+
+#endif /* HAVE_FDWALK */
+
+#endif /* OS_UNIX */
diff --git a/common/compat.h b/common/compat.h
index d7fe414..4771370 100644
--- a/common/compat.h
+++ b/common/compat.h
@@ -325,4 +325,11 @@ int strerror_r (int errnum,
#endif /* HAVE_STRERROR_R */
+#ifndef HAVE_FDWALK
+
+int fdwalk (int (* cb) (void *data, int fd),
+ void *data);
+
+#endif
+
#endif /* __COMPAT_H__ */