#include <config.h>
#ifndef HAVE_CLOSEFROM
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <limits.h>
#ifdef HAVE_PSTAT_GETPROC
# include <sys/pstat.h>
#else
# include <dirent.h>
#endif
#include "sudo_compat.h"
#ifndef _POSIX_OPEN_MAX
# define _POSIX_OPEN_MAX 20
#endif
#if defined(HAVE_FCNTL_CLOSEM) && !defined(HAVE_DIRFD)
# define sudo_closefrom closefrom_fallback
#endif
void
closefrom_fallback(int lowfd)
{
long fd, maxfd;
maxfd = sysconf(_SC_OPEN_MAX);
if (maxfd < 0)
maxfd = _POSIX_OPEN_MAX;
for (fd = lowfd; fd < maxfd; fd++) {
#ifdef __APPLE__
(void) fcntl((int) fd, F_SETFD, FD_CLOEXEC);
#else
(void) close((int) fd);
#endif
}
}
#if defined(HAVE_FCNTL_CLOSEM)
void
sudo_closefrom(int lowfd)
{
if (fcntl(lowfd, F_CLOSEM, 0) == -1)
closefrom_fallback(lowfd);
}
#elif defined(HAVE_PSTAT_GETPROC)
void
sudo_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
sudo_closefrom(int lowfd)
{
const char *path;
DIR *dirp;
# 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) {
const char *errstr;
int fd = strtonum(dent->d_name, lowfd, INT_MAX, &errstr);
if (errstr == NULL && fd != dirfd(dirp)) {
# ifdef __APPLE__
(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
# else
(void) close(fd);
# endif
}
}
(void) closedir(dirp);
} else
closefrom_fallback(lowfd);
}
#endif
#endif