]> git.armaanb.net Git - opendoas.git/blob - libopenbsd/closefrom.c
use config.h and link objects instead of libopenbsd.a
[opendoas.git] / libopenbsd / closefrom.c
1 /*
2  * SPDX-License-Identifier: ISC
3  *
4  * Copyright (c) 2004-2005, 2007, 2010, 2012-2015, 2017-2018
5  *      Todd C. Miller <Todd.Miller@sudo.ws>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19
20 /*
21  * This is an open source non-commercial project. Dear PVS-Studio, please check it.
22  * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
23  */
24
25 #include "config.h"
26
27 #include <sys/types.h>
28 #include <unistd.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <fcntl.h>
32 #include <limits.h>
33 #ifdef HAVE_PSTAT_GETPROC
34 # include <sys/pstat.h>
35 #else
36 # include <dirent.h>
37 #endif
38
39 #include "openbsd.h"
40
41 #ifndef _POSIX_OPEN_MAX
42 # define _POSIX_OPEN_MAX        20
43 #endif
44
45 /*
46  * Close all file descriptors greater than or equal to lowfd.
47  * This is the expensive (fallback) method.
48  */
49 static void
50 closefrom_fallback(int lowfd)
51 {
52     long fd, maxfd;
53
54     /*
55      * Fall back on sysconf(_SC_OPEN_MAX).  We avoid checking
56      * resource limits since it is possible to open a file descriptor
57      * and then drop the rlimit such that it is below the open fd.
58      */
59     maxfd = sysconf(_SC_OPEN_MAX);
60     if (maxfd < 0)
61         maxfd = _POSIX_OPEN_MAX;
62
63     for (fd = lowfd; fd < maxfd; fd++) {
64 #ifdef __APPLE__
65         /* Avoid potential libdispatch crash when we close its fds. */
66         (void) fcntl((int) fd, F_SETFD, FD_CLOEXEC);
67 #else
68         (void) close((int) fd);
69 #endif
70     }
71 }
72
73 /*
74  * Close all file descriptors greater than or equal to lowfd.
75  * We try the fast way first, falling back on the slow method.
76  */
77 void
78 closefrom(int lowfd)
79 {
80 #if defined(HAVE_PSTAT_GETPROC)
81     struct pst_status pstat;
82 #elif defined(HAVE_DIRFD)
83     const char *path;
84     DIR *dirp;
85 #endif
86
87     /* Try the fast method first, if possible. */
88 #if defined(HAVE_FCNTL_CLOSEM)
89     if (fcntl(lowfd, F_CLOSEM, 0) != -1)
90         return;
91 #endif
92 #if defined(HAVE_PSTAT_GETPROC)
93     /*
94      * EOVERFLOW is not a fatal error for the fields we use.
95      * See the "EOVERFLOW Error" section of pstat_getvminfo(3).
96      */
97     if (pstat_getproc(&pstat, sizeof(pstat), 0, getpid()) != -1 ||
98         errno == EOVERFLOW) {
99         int fd;
100
101         for (fd = lowfd; fd <= pstat.pst_highestfd; fd++)
102             (void) close(fd);
103         return;
104     }
105 #elif defined(HAVE_DIRFD)
106     /* Use /proc/self/fd (or /dev/fd on macOS) if it exists. */
107 # ifdef __APPLE__
108     path = _PATH_DEV "fd";
109 # else
110     path = "/proc/self/fd";
111 # endif
112     if ((dirp = opendir(path)) != NULL) {
113         struct dirent *dent;
114         while ((dent = readdir(dirp)) != NULL) {
115             const char *errstr;
116             int fd = strtonum(dent->d_name, lowfd, INT_MAX, &errstr);
117             if (errstr == NULL && fd != dirfd(dirp)) {
118 # ifdef __APPLE__
119                 /* Avoid potential libdispatch crash when we close its fds. */
120                 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
121 # else
122                 (void) close(fd);
123 # endif
124             }
125         }
126         (void) closedir(dirp);
127         return;
128     }
129 #endif /* HAVE_DIRFD */
130
131     /* Do things the slow way. */
132     closefrom_fallback(lowfd);
133 }