diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2023-05-02 16:02:32 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2023-05-02 16:15:34 +0300 |
commit | 15874b30207fa29faf8ce9e64add011b5afa8e05 (patch) | |
tree | e0a36792cdbcdd822bcaa41fae9cf991b310f7a2 | |
parent | 5ba0926fabd419e51f777f138389e3588bbd1ce9 (diff) | |
download | wydawca-master.tar.gz wydawca-master.tar.bz2 |
-rw-r--r-- | am/ax_closefrom.m4 | 64 | ||||
-rw-r--r-- | configure.ac | 3 | ||||
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/closefrom.c | 135 | ||||
-rw-r--r-- | src/directive.c | 10 | ||||
-rw-r--r-- | src/exec.c | 3 | ||||
-rw-r--r-- | src/wydawca.h | 3 |
7 files changed, 212 insertions, 7 deletions
diff --git a/am/ax_closefrom.m4 b/am/ax_closefrom.m4 new file mode 100644 index 0000000..959e767 --- /dev/null +++ b/am/ax_closefrom.m4 | |||
@@ -0,0 +1,64 @@ | |||
1 | # SYNOPSIS | ||
2 | # | ||
3 | # AX_CLOSEFROM | ||
4 | # | ||
5 | # DESCRIPTION | ||
6 | # | ||
7 | # This macro figures out the best way to close all file descriptors | ||
8 | # greater than or equal to the given one. It evaluates the following | ||
9 | # variants: | ||
10 | # | ||
11 | # 1. closefrom call (FreeBSD) | ||
12 | # 2. F_CLOSEM fcntl (NetBSD, AIX, IRIX) | ||
13 | # 3. proc_pidinfo call (Darwin) | ||
14 | # 4. /proc/self/fd filesystem (Linux) | ||
15 | # | ||
16 | # If none of these is applicable, brute force approach will be used. | ||
17 | # | ||
18 | # LICENSE | ||
19 | # | ||
20 | # This file is part of Wydawca | ||
21 | # Copyright (C) 2021-2023 Sergey Poznyakoff | ||
22 | # | ||
23 | # Wydawca is free software; you can redistribute it and/or modify | ||
24 | # it under the terms of the GNU General Public License as published by | ||
25 | # the Free Software Foundation; either version 3, or (at your option) | ||
26 | # any later version. | ||
27 | # | ||
28 | # Wydawca is distributed in the hope that it will be useful, | ||
29 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
30 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
31 | # GNU General Public License for more details. | ||
32 | # | ||
33 | # You should have received a copy of the GNU General Public License | ||
34 | # along with wydawca. If not, see <http://www.gnu.org/licenses/>. | ||
35 | |||
36 | AC_DEFUN([AX_CLOSEFROM], | ||
37 | [ | ||
38 | AC_CHECK_FUNCS([sysconf getdtablesize closefrom proc_pidinfo]) | ||
39 | |||
40 | AC_CHECK_DECL([F_CLOSEM], | ||
41 | AC_DEFINE([HAVE_FCNTL_CLOSEM], [1], | ||
42 | [Use F_CLOSEM fcntl for wy_close_fds_from]), | ||
43 | [], | ||
44 | [#include <limits.h> | ||
45 | #include <fcntl.h> | ||
46 | ]) | ||
47 | |||
48 | AC_CHECK_HEADERS([libproc.h]) | ||
49 | |||
50 | AC_MSG_CHECKING([for closefrom interface]) | ||
51 | if test "$ac_cv_func_closefrom" = yes; then | ||
52 | closefrom_api=closefrom | ||
53 | elif test "$ac_cv_have_decl_F_CLOSEM" = yes; then | ||
54 | closefrom_api=F_CLOSEM | ||
55 | elif test "${ac_cv_header_libproc_h}-$ac_cv_func_proc_pidinfo" = "yes-yes"; then | ||
56 | closefrom_api=proc_pidinfo | ||
57 | elif test -d "/proc/self/fd" ; then | ||
58 | AC_DEFINE([HAVE_PROC_SELF_FD], [1], [Define if you have /proc/self/fd]) | ||
59 | closefrom_api=proc | ||
60 | else | ||
61 | closefrom_api=bruteforce | ||
62 | fi | ||
63 | AC_MSG_RESULT([$closefrom_api]) | ||
64 | ]) | ||
diff --git a/configure.ac b/configure.ac index 963fc05..b08fcb1 100644 --- a/configure.ac +++ b/configure.ac | |||
@@ -52,13 +52,14 @@ AC_CHECK_MEMBERS([struct tm.tm_gmtoff],,, | |||
52 | # Checks for library functions. | 52 | # Checks for library functions. |
53 | AC_FUNC_VPRINTF | 53 | AC_FUNC_VPRINTF |
54 | AC_CHECK_FUNCS([setegid setregid setresgid setresuid seteuid \ | 54 | AC_CHECK_FUNCS([setegid setregid setresgid setresuid seteuid \ |
55 | setreuid vsyslog sysconf getdtablesize]) | 55 | setreuid vsyslog]) |
56 | 56 | ||
57 | # Check for POSIX threads support | 57 | # Check for POSIX threads support |
58 | AX_PTHREAD([], | 58 | AX_PTHREAD([], |
59 | [AC_MSG_ERROR([POSIX threads support is required, but not available])]) | 59 | [AC_MSG_ERROR([POSIX threads support is required, but not available])]) |
60 | 60 | ||
61 | AX_THREAD_NAMES | 61 | AX_THREAD_NAMES |
62 | AX_CLOSEFROM | ||
62 | 63 | ||
63 | # ********************** | 64 | # ********************** |
64 | # Mailutils | 65 | # Mailutils |
diff --git a/src/Makefile.am b/src/Makefile.am index 46bdcc7..3d32d59 100644 --- a/src/Makefile.am +++ b/src/Makefile.am | |||
@@ -20,6 +20,7 @@ wydawca_SOURCES=\ | |||
20 | backup.c\ | 20 | backup.c\ |
21 | builtin.c\ | 21 | builtin.c\ |
22 | builtin.h\ | 22 | builtin.h\ |
23 | closefrom.c\ | ||
23 | cmdline.h\ | 24 | cmdline.h\ |
24 | config.c\ | 25 | config.c\ |
25 | dictionary.c\ | 26 | dictionary.c\ |
diff --git a/src/closefrom.c b/src/closefrom.c new file mode 100644 index 0000000..a7a144c --- /dev/null +++ b/src/closefrom.c | |||
@@ -0,0 +1,135 @@ | |||
1 | /* This file is part of Wydawca | ||
2 | Copyright (C) 2021-2023 Sergey Poznyakoff | ||
3 | |||
4 | Wydawca is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 3, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | Wydawca is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with wydawca. If not, see <http://www.gnu.org/licenses/>. */ | ||
16 | #include <config.h> | ||
17 | #include <stdlib.h> | ||
18 | #include <unistd.h> | ||
19 | |||
20 | #if defined (HAVE_FUNC_CLOSEFROM) | ||
21 | static int | ||
22 | close_fds_sys(int minfd) | ||
23 | { | ||
24 | closefrom(minfd); | ||
25 | return 0; | ||
26 | } | ||
27 | |||
28 | #elif defined (HAVE_FCNTL_CLOSEM) | ||
29 | # include <fcntl.h> | ||
30 | |||
31 | static int | ||
32 | close_fds_sys(int minfd) | ||
33 | { | ||
34 | fcntl(minfd, F_CLOSEM, 0); | ||
35 | return 0; | ||
36 | } | ||
37 | |||
38 | #elif defined (HAVE_LIBPROC_H) && defined (HAVE_FUNC_PROC_PIDINFO) | ||
39 | #include <libproc.h> | ||
40 | |||
41 | static int | ||
42 | close_fds_sys(int minfd) | ||
43 | { | ||
44 | pid_t pid = getpid(); | ||
45 | struct proc_fdinfo *fdinfo; | ||
46 | int i, n, size; | ||
47 | |||
48 | size = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0); | ||
49 | if (size == 0) | ||
50 | return 0; | ||
51 | else if (size < 0) | ||
52 | return -1; | ||
53 | |||
54 | fdinfo = calloc(size, sizeof(fdinfo[0])); | ||
55 | if (!fdinfo) | ||
56 | return -1; | ||
57 | |||
58 | n = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fdinfo, size); | ||
59 | if (n <= 0) { | ||
60 | free(fdinfo); | ||
61 | return -1; | ||
62 | } | ||
63 | |||
64 | n /= PROC_PIDLISTFD_SIZE; | ||
65 | |||
66 | for (i = minfd; i < n; i++) | ||
67 | close(fdinfo_buf[i].proc_fd); | ||
68 | |||
69 | free(fdinfo); | ||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | #elif defined (HAVE_PROC_SELF_FD) | ||
74 | # include <sys/types.h> | ||
75 | # include <dirent.h> | ||
76 | # include <limits.h> | ||
77 | |||
78 | static int | ||
79 | close_fds_sys(int minfd) | ||
80 | { | ||
81 | DIR *dir; | ||
82 | struct dirent *ent; | ||
83 | |||
84 | dir = opendir("/proc/self/fd"); | ||
85 | if (!dir) | ||
86 | return -1; | ||
87 | while ((ent = readdir(dir)) != NULL) { | ||
88 | if (ent->d_name[0] != '.') { | ||
89 | char *p; | ||
90 | long n = strtol(ent->d_name, &p, 10); | ||
91 | if (n >= minfd && n < INT_MAX && *p == 0) | ||
92 | close((int) n); | ||
93 | } | ||
94 | } | ||
95 | closedir(dir); | ||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | #else | ||
100 | # define close_fds_sys(fd) (-1) | ||
101 | #endif | ||
102 | |||
103 | #if defined (HAVE_SYSCONF) && defined (_SC_OPEN_MAX) | ||
104 | # define __getmaxfd() sysconf(_SC_OPEN_MAX) | ||
105 | #elif defined (HAVE_GETDTABLESIZE) | ||
106 | # define __getmaxfd() getdtablesize() | ||
107 | #elif defined OPEN_MAX | ||
108 | # define __getmaxfd() OPEN_MAX | ||
109 | #else | ||
110 | # define __getmaxfd() 256 | ||
111 | #endif | ||
112 | |||
113 | static int | ||
114 | close_fds_bruteforce(int minfd) | ||
115 | { | ||
116 | int i, n = __getmaxfd(); | ||
117 | |||
118 | for (i = minfd; i < n; i++) | ||
119 | close(i); | ||
120 | |||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | void | ||
125 | wy_close_fds_from(int minfd) | ||
126 | { | ||
127 | if (close_fds_sys(minfd)) | ||
128 | close_fds_bruteforce(minfd); | ||
129 | } | ||
130 | |||
131 | void | ||
132 | wy_close_fds_above(int fd) | ||
133 | { | ||
134 | wy_close_fds_from(fd + 1); | ||
135 | } | ||
diff --git a/src/directive.c b/src/directive.c index e69888b..0df6611 100644 --- a/src/directive.c +++ b/src/directive.c | |||
@@ -558,10 +558,12 @@ run_check_script(const char *script, struct wy_triplet *trp, | |||
558 | if (efd == -1) | 558 | if (efd == -1) |