Line data Source code
1 : /*
2 : * This program is free software; you can redistribute it and/or modify
3 : * it under the terms of the GNU General Public License as published by
4 : * the Free Software Foundation; either version 3 of the License, or
5 : * (at your option) any later version.
6 : *
7 : * This program is distributed in the hope that it will be useful,
8 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 : * GNU General Public License for more details.
11 : *
12 : * You should have received a copy of the GNU General Public License
13 : * along with this program; if not, see <http://www.gnu.org/licenses/>.
14 : */
15 :
16 : #include "replace.h"
17 : #include "closefrom_except.h"
18 : #include <popt.h>
19 :
20 30 : int closefrom_except(int lower, int *fds, size_t num_fds)
21 : {
22 : size_t i;
23 30 : int max_keep = -1;
24 : int fd, ret;
25 :
26 61 : for (i=0; i<num_fds; i++) {
27 31 : max_keep = MAX(max_keep, fds[i]);
28 : }
29 30 : if (max_keep == -1) {
30 8 : return 0;
31 : }
32 :
33 833 : for (fd = lower; fd < max_keep; fd++) {
34 811 : bool keep = false;
35 :
36 : /*
37 : * O(num_fds*max_keep), but we expect the number of
38 : * fds to keep to be very small, typically 0,1,2 and
39 : * very few more.
40 : */
41 1640 : for (i=0; i<num_fds; i++) {
42 829 : if (fd == fds[i]) {
43 0 : keep = true;
44 0 : break;
45 : }
46 : }
47 811 : if (keep) {
48 0 : continue;
49 : }
50 811 : ret = close(fd);
51 811 : if ((ret == -1) && (errno != EBADF)) {
52 0 : return errno;
53 : }
54 : }
55 :
56 22 : closefrom(MAX(lower, max_keep+1));
57 22 : return 0;
58 : }
59 :
60 30 : int closefrom_except_fd_params(
61 : int lower,
62 : size_t num_fd_params,
63 : const char *fd_params[],
64 : int argc,
65 : const char *argv[])
66 30 : {
67 30 : int fds[num_fd_params];
68 : size_t i;
69 30 : struct poptOption long_options[num_fd_params + 1];
70 : poptContext pc;
71 : int ret;
72 :
73 61 : for (i=0; i<num_fd_params; i++) {
74 31 : fds[i] = -1;
75 31 : long_options[i] = (struct poptOption) {
76 31 : .longName = fd_params[i],
77 : .argInfo = POPT_ARG_INT,
78 31 : .arg = &fds[i],
79 : };
80 : }
81 30 : long_options[num_fd_params] = (struct poptOption) { .longName=NULL, };
82 :
83 30 : pc = poptGetContext(argv[0], argc, argv, long_options, 0);
84 :
85 48 : while ((ret = poptGetNextOpt(pc)) != -1) {
86 : /* do nothing */
87 : }
88 :
89 30 : poptFreeContext(pc);
90 :
91 30 : ret = closefrom_except(lower, fds, ARRAY_SIZE(fds));
92 30 : return ret;
93 : }
|