Update closefrom() function Import from sudo. Adapt the build system to detect the required features.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
diff --git a/configure.ac b/configure.ac
index 14bf306..97a606a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -40,7 +40,7 @@ fi
# Checks for libraries.
# Checks for header files.
-AC_CHECK_HEADERS([sys/ndir.h sys/dir.h dir.h dirent.h])
+AC_CHECK_HEADERS([sys/ndir.h sys/dir.h ndir.h dirent.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_UID_T
@@ -123,7 +123,8 @@ AC_LINK_IFELSE(
AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])])
-AC_CHECK_FUNCS([clearenv dirfd fopencookie __fpurge getexecname getline sysconf])
+AC_CHECK_FUNCS([clearenv dirfd fopencookie __fpurge getexecname getline \
+ pstat_getproc sysconf])
AC_CONFIG_FILES([
Makefile
diff --git a/src/closefrom.c b/src/closefrom.c
index b7e2ad5..423a004 100644
--- a/src/closefrom.c
+++ b/src/closefrom.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004-2005, 2007, 2010
+ * Copyright (c) 2004-2005, 2007, 2010, 2012-2014
* Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -18,7 +18,6 @@
#include <config.h>
#include <sys/types.h>
-#include <sys/param.h>
#include <unistd.h>
#include <stdio.h>
#ifdef STDC_HEADERS
@@ -30,20 +29,26 @@
# endif
#endif /* STDC_HEADERS */
#include <fcntl.h>
-#ifdef HAVE_DIRENT_H
-# include <dirent.h>
-# define NAMLEN(dirent) strlen((dirent)->d_name)
+#include <limits.h>
+#ifdef HAVE_PSTAT_GETPROC
+# include <sys/param.h>
+# include <sys/pstat.h>
#else
-# define dirent direct
-# define NAMLEN(dirent) (dirent)->d_namlen
-# ifdef HAVE_SYS_NDIR_H
-# include <sys/ndir.h>
-# endif
-# ifdef HAVE_SYS_DIR_H
-# include <sys/dir.h>
-# endif
-# ifdef HAVE_NDIR_H
-# include <ndir.h>
+# ifdef HAVE_DIRENT_H
+# include <dirent.h>
+# define NAMLEN(dirent) strlen((dirent)->d_name)
+# else
+# define dirent direct
+# define NAMLEN(dirent) (dirent)->d_namlen
+# ifdef HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+# endif
+# ifdef HAVE_SYS_DIR_H
+# include <sys/dir.h>
+# endif
+# ifdef HAVE_NDIR_H
+# include <ndir.h>
+# endif
# endif
#endif
@@ -51,15 +56,13 @@
# define OPEN_MAX 256
#endif
-#ifndef HAVE_FCNTL_CLOSEM
-# ifndef HAVE_DIRFD
-# define closefrom_fallback closefrom
-# endif
+#if defined(HAVE_FCNTL_CLOSEM) && !defined(HAVE_DIRFD)
+# define closefrom closefrom_fallback
#endif
/*
* Close all file descriptors greater than or equal to lowfd.
- * This is the expensive (ballback) method.
+ * This is the expensive (fallback) method.
*/
void
closefrom_fallback(int lowfd)
@@ -79,44 +82,74 @@ closefrom_fallback(int lowfd)
if (maxfd < 0)
maxfd = OPEN_MAX;
- for (fd = lowfd; fd < maxfd; fd++)
+ for (fd = lowfd; fd < maxfd; fd++) {
+#ifdef __APPLE__
+ /* Avoid potential libdispatch crash when we close its fds. */
+ (void)fcntl((int)fd, F_SETFD, FD_CLOEXEC);
+#else
(void)close((int)fd);
+#endif
+ }
}
/*
* Close all file descriptors greater than or equal to lowfd.
* We try the fast way first, falling back on the slow method.
*/
-#ifdef HAVE_FCNTL_CLOSEM
+#if defined(HAVE_FCNTL_CLOSEM)
void
closefrom(int lowfd)
{
if (fcntl(lowfd, F_CLOSEM, 0) == -1)
closefrom_fallback(lowfd);
}
-#else
-# ifdef HAVE_DIRFD
+#elif defined(HAVE_PSTAT_GETPROC)
+void
+closefrom(int lowfd)
+{
+ struct pst_status pstat;
+ int fd;
+
+ if (pstat_getproc(&pstat, sizeof(pstat), 0, getpid()) != -1) {
+ for (fd = lowfd; fd <= pstat.pst_highestfd; fd++)
+ (void)close(fd);
+ } else {
+ closefrom_fallback(lowfd);
+ }
+}
+#elif defined(HAVE_DIRFD)
void
closefrom(int lowfd)
{
- struct dirent *dent;
+ const char *path;
DIR *dirp;
- char *endp;
- long fd;
- /* Use /proc/self/fd directory if it exists. */
- dirp = opendir("/proc/self/fd");
- if (dirp != NULL) {
+ /* Use /proc/self/fd (or /dev/fd on FreeBSD) if it exists. */
+# if defined(__FreeBSD__) || defined(__APPLE__)
+ path = "/dev/fd";
+# else
+ path = "/proc/self/fd";
+# endif
+ if ((dirp = opendir(path)) != NULL) {
+ struct dirent *dent;
+
while ((dent = readdir(dirp)) != NULL) {
- fd = strtol(dent->d_name, &endp, 10);
- if (dent->d_name != endp && *endp == '\0' &&
- fd >= 0 && fd < INT_MAX && fd >= lowfd &&
- fd != dirfd(dirp))
- (void)close((int)fd);
+ const char *errstr;
+ int fd;
+
+ fd = strtonum(dent->d_name, lowfd, INT_MAX, &errstr);
+ if (errstr == NULL && fd != dirfd(dirp)) {
+# ifdef __APPLE__
+ /* Avoid potential libdispatch crash when we
+ * close its fds. */
+ (void)fcntl(fd, F_SETFD, FD_CLOEXEC);
+# else
+ (void)close(fd);
+# endif
+ }
}
(void)closedir(dirp);
} else
closefrom_fallback(lowfd);
}
-#endif /* HAVE_DIRFD */
#endif /* HAVE_FCNTL_CLOSEM */