From cbc9273ec1e59a3ce05cd9423b326e9d258e6a5a Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Wed, 20 Feb 2013 11:50:25 +0100 Subject: 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. --- common/compat.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ common/compat.h | 7 ++++++ configure.ac | 3 +++ 3 files changed, 83 insertions(+) diff --git a/common/compat.c b/common/compat.c index 85a33c8..fd4e137 100644 --- a/common/compat.c +++ b/common/compat.c @@ -37,6 +37,7 @@ #include "compat.h" #include +#include #include #include #include @@ -81,6 +82,8 @@ #ifdef OS_UNIX +#include + #if defined (HAVE_PROGRAM_INVOCATION_SHORT_NAME) && !HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME extern char *program_invocation_short_name; #endif @@ -851,3 +854,73 @@ strerror_r (int errnum, } #endif /* HAVE_STRERROR_R */ + +#ifdef OS_UNIX + +#include + +#ifndef HAVE_FDWALK + +#ifdef HAVE_SYS_RESOURCE_H +#include +#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__ */ diff --git a/configure.ac b/configure.ac index 79693a2..8109e2c 100644 --- a/configure.ac +++ b/configure.ac @@ -85,11 +85,14 @@ if test "$os_unix" = "yes"; then ]) # These are thngs we can work around + AC_CHECK_HEADERS([sys/resource.h]) + AC_CHECK_MEMBERS([struct dirent.d_type],,,[#include ]) AC_CHECK_FUNCS([getprogname getexecname basename mkstemp mkdtemp]) AC_CHECK_FUNCS([getauxval issetugid getresuid]) AC_CHECK_FUNCS([strnstr memdup strndup strerror_r]) AC_CHECK_FUNCS([asprintf vasprintf vsnprintf]) AC_CHECK_FUNCS([timegm]) + AC_CHECK_FUNCS([fdwalk]) AC_CHECK_DECLS([asprintf, vasprintf], [], [], [[#include ]]) -- cgit v1.2.1