1/* 2 * Copyright (c) 2004-2005, 2007, 2010 3 * Todd C. Miller <Todd.Miller@courtesan.com> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18#include <config.h> 19 20#include <sys/types.h> 21#include <sys/param.h> 22#include <unistd.h> 23#include <stdio.h> 24#ifdef STDC_HEADERS 25# include <stdlib.h> 26# include <stddef.h> 27#else 28# ifdef HAVE_STDLIB_H 29# include <stdlib.h> 30# endif 31#endif /* STDC_HEADERS */ 32#include <fcntl.h> 33#ifdef HAVE_DIRENT_H 34# include <dirent.h> 35# define NAMLEN(dirent) strlen((dirent)->d_name) 36#else 37# define dirent direct 38# define NAMLEN(dirent) (dirent)->d_namlen 39# ifdef HAVE_SYS_NDIR_H 40# include <sys/ndir.h> 41# endif 42# ifdef HAVE_SYS_DIR_H 43# include <sys/dir.h> 44# endif 45# ifdef HAVE_NDIR_H 46# include <ndir.h> 47# endif 48#endif 49 50#include "missing.h" 51 52#ifndef HAVE_FCNTL_CLOSEM 53# ifndef HAVE_DIRFD 54# define closefrom_fallback closefrom 55# endif 56#endif 57 58/* 59 * Close all file descriptors greater than or equal to lowfd. 60 * This is the expensive (ballback) method. 61 */ 62void 63closefrom_fallback(lowfd) 64 int lowfd; 65{ 66 long fd, maxfd; 67 68 /* 69 * Fall back on sysconf() or getdtablesize(). We avoid checking 70 * resource limits since it is possible to open a file descriptor 71 * and then drop the rlimit such that it is below the open fd. 72 */ 73#ifdef HAVE_SYSCONF 74 maxfd = sysconf(_SC_OPEN_MAX); 75#else 76 maxfd = getdtablesize(); 77#endif /* HAVE_SYSCONF */ 78 if (maxfd < 0) 79 maxfd = OPEN_MAX; 80 81 for (fd = lowfd; fd < maxfd; fd++) 82#if 6497333 83 (void) fcntl((int) fd, F_SETFD, 1); 84#else 85 (void) close((int) fd); 86#endif 87} 88 89/* 90 * Close all file descriptors greater than or equal to lowfd. 91 * We try the fast way first, falling back on the slow method. 92 */ 93#ifdef HAVE_FCNTL_CLOSEM 94void 95closefrom(lowfd) 96 int lowfd; 97{ 98 if (fcntl(lowfd, F_CLOSEM, 0) == -1) 99 closefrom_fallback(lowfd); 100} 101#else 102# ifdef HAVE_DIRFD 103void 104closefrom(lowfd) 105 int lowfd; 106{ 107 struct dirent *dent; 108 DIR *dirp; 109 char *endp; 110 long fd; 111 112 /* Use /dev/fd directory if it exists. */ 113 if ((dirp = opendir("/dev/fd")) != NULL) { 114 while ((dent = readdir(dirp)) != NULL) { 115 fd = strtol(dent->d_name, &endp, 10); 116 if (dent->d_name != endp && *endp == '\0' && 117 fd >= 0 && fd < INT_MAX && fd >= lowfd && fd != dirfd(dirp)) 118 (void) close((int) fd); 119 } 120 (void) closedir(dirp); 121 } else 122 closefrom_fallback(lowfd); 123} 124#endif /* HAVE_DIRFD */ 125#endif /* HAVE_FCNTL_CLOSEM */ 126