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