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 29 : int closefrom_except(int lower, int *fds, size_t num_fds)
21 : {
22 : size_t i;
23 29 : int max_keep = -1;
24 : int fd, ret;
25 :
26 58 : for (i=0; i<num_fds; i++) {
27 29 : max_keep = MAX(max_keep, fds[i]);
28 : }
29 29 : if (max_keep == -1) {
30 8 : return 0;
31 : }
32 :
33 814 : for (fd = lower; fd < max_keep; fd++) {
34 793 : 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 1586 : for (i=0; i<num_fds; i++) {
42 793 : if (fd == fds[i]) {
43 0 : keep = true;
44 0 : break;
45 : }
46 : }
47 793 : if (keep) {
48 0 : continue;
49 : }
50 793 : ret = close(fd);
51 793 : if ((ret == -1) && (errno != EBADF)) {
52 0 : return errno;
53 : }
54 : }
55 :
56 21 : closefrom(MAX(lower, max_keep+1));
57 21 : return 0;
58 : }
59 :
60 29 : 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 29 : {
67 29 : int fds[num_fd_params];
68 : size_t i;
69 29 : struct poptOption long_options[num_fd_params + 1];
70 : poptContext pc;
71 : int ret;
72 :
73 58 : for (i=0; i<num_fd_params; i++) {
74 29 : fds[i] = -1;
75 29 : long_options[i] = (struct poptOption) {
76 29 : .longName = fd_params[i],
77 : .argInfo = POPT_ARG_INT,
78 29 : .arg = &fds[i],
79 : };
80 : }
81 29 : long_options[num_fd_params] = (struct poptOption) { .longName=NULL, };
82 :
83 29 : pc = poptGetContext(argv[0], argc, argv, long_options, 0);
84 :
85 47 : while ((ret = poptGetNextOpt(pc)) != -1) {
86 : /* do nothing */
87 : }
88 :
89 29 : poptFreeContext(pc);
90 :
91 29 : ret = closefrom_except(lower, fds, ARRAY_SIZE(fds));
92 29 : return ret;
93 : }
|