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