bsd-closefrom.c revision 137015
1328653Shselasky/*
2328653Shselasky * Copyright (c) 2004 Todd C. Miller <Todd.Miller@courtesan.com>
3328653Shselasky *
4328653Shselasky * Permission to use, copy, modify, and distribute this software for any
5328653Shselasky * purpose with or without fee is hereby granted, provided that the above
6328653Shselasky * copyright notice and this permission notice appear in all copies.
7328653Shselasky *
8328653Shselasky * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9328653Shselasky * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10328653Shselasky * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11328653Shselasky * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12328653Shselasky * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13328653Shselasky * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14328653Shselasky * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15328653Shselasky */
16328653Shselasky
17328653Shselasky#include "includes.h"
18328653Shselasky
19328653Shselasky#ifndef HAVE_CLOSEFROM
20328653Shselasky
21328653Shselasky#include <sys/types.h>
22328653Shselasky#include <sys/param.h>
23328653Shselasky#include <unistd.h>
24328653Shselasky#include <stdio.h>
25328653Shselasky#include <limits.h>
26328653Shselasky#include <stdlib.h>
27328653Shselasky#include <stddef.h>
28328653Shselasky#ifdef HAVE_DIRENT_H
29328653Shselasky# include <dirent.h>
30328653Shselasky# define NAMLEN(dirent) strlen((dirent)->d_name)
31328653Shselasky#else
32328653Shselasky# define dirent direct
33328653Shselasky# define NAMLEN(dirent) (dirent)->d_namlen
34328653Shselasky# ifdef HAVE_SYS_NDIR_H
35328653Shselasky#  include <sys/ndir.h>
36328653Shselasky# endif
37328653Shselasky# ifdef HAVE_SYS_DIR_H
38328653Shselasky#  include <sys/dir.h>
39328653Shselasky# endif
40328653Shselasky# ifdef HAVE_NDIR_H
41328653Shselasky#  include <ndir.h>
42328653Shselasky# endif
43328653Shselasky#endif
44328653Shselasky
45328653Shselasky#ifndef OPEN_MAX
46328653Shselasky# define OPEN_MAX	256
47328653Shselasky#endif
48328653Shselasky
49328653ShselaskyRCSID("$Id: bsd-closefrom.c,v 1.1 2004/08/15 08:41:00 djm Exp $");
50328653Shselasky
51328653Shselasky#ifndef lint
52330853Shselaskystatic const char sudorcsid[] = "$Sudo: closefrom.c,v 1.6 2004/06/01 20:51:56 millert Exp $";
53328653Shselasky#endif /* lint */
54328653Shselasky
55328653Shselasky/*
56328653Shselasky * Close all file descriptors greater than or equal to lowfd.
57328653Shselasky */
58328653Shselaskyvoid
59328653Shselaskyclosefrom(int lowfd)
60328653Shselasky{
61328653Shselasky    long fd, maxfd;
62328653Shselasky#if defined(HAVE_DIRFD) && defined(HAVE_PROC_PID)
63328653Shselasky    char fdpath[PATH_MAX], *endp;
64328653Shselasky    struct dirent *dent;
65328653Shselasky    DIR *dirp;
66328653Shselasky    int len;
67328653Shselasky
68328653Shselasky    /* Check for a /proc/$$/fd directory. */
69328653Shselasky    len = snprintf(fdpath, sizeof(fdpath), "/proc/%ld/fd", (long)getpid());
70328653Shselasky    if (len != -1 && len <= sizeof(fdpath) && (dirp = opendir(fdpath))) {
71328653Shselasky	while ((dent = readdir(dirp)) != NULL) {
72328653Shselasky	    fd = strtol(dent->d_name, &endp, 10);
73328653Shselasky	    if (dent->d_name != endp && *endp == '\0' &&
74328653Shselasky		fd >= 0 && fd < INT_MAX && fd >= lowfd && fd != dirfd(dirp))
75328653Shselasky		(void) close((int) fd);
76328653Shselasky	}
77328653Shselasky	(void) closedir(dirp);
78328653Shselasky    } else
79328653Shselasky#endif
80328653Shselasky    {
81328653Shselasky	/*
82328653Shselasky	 * Fall back on sysconf() or getdtablesize().  We avoid checking
83328653Shselasky	 * resource limits since it is possible to open a file descriptor
84328653Shselasky	 * and then drop the rlimit such that it is below the open fd.
85328653Shselasky	 */
86328653Shselasky#ifdef HAVE_SYSCONF
87328653Shselasky	maxfd = sysconf(_SC_OPEN_MAX);
88330853Shselasky#else
89328653Shselasky	maxfd = getdtablesize();
90328653Shselasky#endif /* HAVE_SYSCONF */
91328653Shselasky	if (maxfd < 0)
92328653Shselasky	    maxfd = OPEN_MAX;
93328653Shselasky
94328653Shselasky	for (fd = lowfd; fd < maxfd; fd++)
95328653Shselasky	    (void) close((int) fd);
96328653Shselasky    }
97328653Shselasky}
98328653Shselasky
99328653Shselasky#endif /* HAVE_CLOSEFROM */
100328653Shselasky
101328653Shselasky