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