1137015Sdes/*
2162852Sdes * Copyright (c) 2004-2005 Todd C. Miller <Todd.Miller@courtesan.com>
3137015Sdes *
4137015Sdes * Permission to use, copy, modify, and distribute this software for any
5137015Sdes * purpose with or without fee is hereby granted, provided that the above
6137015Sdes * copyright notice and this permission notice appear in all copies.
7137015Sdes *
8137015Sdes * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9137015Sdes * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10137015Sdes * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11137015Sdes * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12137015Sdes * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13137015Sdes * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14137015Sdes * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15137015Sdes */
16137015Sdes
17137015Sdes#include "includes.h"
18137015Sdes
19137015Sdes#ifndef HAVE_CLOSEFROM
20137015Sdes
21137015Sdes#include <sys/types.h>
22137015Sdes#include <sys/param.h>
23137015Sdes#include <unistd.h>
24137015Sdes#include <stdio.h>
25162852Sdes#ifdef HAVE_FCNTL_H
26162852Sdes# include <fcntl.h>
27162852Sdes#endif
28137015Sdes#include <limits.h>
29137015Sdes#include <stdlib.h>
30137015Sdes#include <stddef.h>
31162852Sdes#include <string.h>
32162852Sdes#include <unistd.h>
33137015Sdes#ifdef HAVE_DIRENT_H
34137015Sdes# include <dirent.h>
35137015Sdes# define NAMLEN(dirent) strlen((dirent)->d_name)
36137015Sdes#else
37137015Sdes# define dirent direct
38137015Sdes# define NAMLEN(dirent) (dirent)->d_namlen
39137015Sdes# ifdef HAVE_SYS_NDIR_H
40137015Sdes#  include <sys/ndir.h>
41137015Sdes# endif
42137015Sdes# ifdef HAVE_SYS_DIR_H
43137015Sdes#  include <sys/dir.h>
44137015Sdes# endif
45137015Sdes# ifdef HAVE_NDIR_H
46137015Sdes#  include <ndir.h>
47137015Sdes# endif
48137015Sdes#endif
49137015Sdes
50137015Sdes#ifndef OPEN_MAX
51137015Sdes# define OPEN_MAX	256
52137015Sdes#endif
53137015Sdes
54162852Sdes#if 0
55162852Sdes__unused static const char rcsid[] = "$Sudo: closefrom.c,v 1.11 2006/08/17 15:26:54 millert Exp $";
56137015Sdes#endif /* lint */
57137015Sdes
58137015Sdes/*
59137015Sdes * Close all file descriptors greater than or equal to lowfd.
60137015Sdes */
61162852Sdes#ifdef HAVE_FCNTL_CLOSEM
62137015Sdesvoid
63137015Sdesclosefrom(int lowfd)
64137015Sdes{
65162852Sdes    (void) fcntl(lowfd, F_CLOSEM, 0);
66162852Sdes}
67162852Sdes#else
68162852Sdesvoid
69162852Sdesclosefrom(int lowfd)
70162852Sdes{
71137015Sdes    long fd, maxfd;
72137015Sdes#if defined(HAVE_DIRFD) && defined(HAVE_PROC_PID)
73137015Sdes    char fdpath[PATH_MAX], *endp;
74137015Sdes    struct dirent *dent;
75137015Sdes    DIR *dirp;
76137015Sdes    int len;
77137015Sdes
78137015Sdes    /* Check for a /proc/$$/fd directory. */
79137015Sdes    len = snprintf(fdpath, sizeof(fdpath), "/proc/%ld/fd", (long)getpid());
80162852Sdes    if (len > 0 && (size_t)len <= sizeof(fdpath) && (dirp = opendir(fdpath))) {
81137015Sdes	while ((dent = readdir(dirp)) != NULL) {
82137015Sdes	    fd = strtol(dent->d_name, &endp, 10);
83137015Sdes	    if (dent->d_name != endp && *endp == '\0' &&
84137015Sdes		fd >= 0 && fd < INT_MAX && fd >= lowfd && fd != dirfd(dirp))
85137015Sdes		(void) close((int) fd);
86137015Sdes	}
87137015Sdes	(void) closedir(dirp);
88137015Sdes    } else
89137015Sdes#endif
90137015Sdes    {
91137015Sdes	/*
92137015Sdes	 * Fall back on sysconf() or getdtablesize().  We avoid checking
93137015Sdes	 * resource limits since it is possible to open a file descriptor
94137015Sdes	 * and then drop the rlimit such that it is below the open fd.
95137015Sdes	 */
96137015Sdes#ifdef HAVE_SYSCONF
97137015Sdes	maxfd = sysconf(_SC_OPEN_MAX);
98137015Sdes#else
99137015Sdes	maxfd = getdtablesize();
100137015Sdes#endif /* HAVE_SYSCONF */
101137015Sdes	if (maxfd < 0)
102137015Sdes	    maxfd = OPEN_MAX;
103137015Sdes
104137015Sdes	for (fd = lowfd; fd < maxfd; fd++)
105137015Sdes	    (void) close((int) fd);
106137015Sdes    }
107137015Sdes}
108162852Sdes#endif /* !HAVE_FCNTL_CLOSEM */
109137015Sdes#endif /* HAVE_CLOSEFROM */
110