summaryrefslogtreecommitdiff
path: root/common/compat.c
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/compat.c
parentc785ab66890ad7b73c556d6afdf2bb8a32dd50e2 (diff)
downloadp11-kit-ccc5e1569b360b54962e7f4cfaded8ab466b021d.tar.gz
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/compat.c')
-rw-r--r--common/compat.c73
1 files changed, 73 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 */