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