aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2023-05-02 16:02:32 +0300
committerSergey Poznyakoff <gray@gnu.org>2023-05-02 16:15:34 +0300
commit15874b30207fa29faf8ce9e64add011b5afa8e05 (patch)
treee0a36792cdbcdd822bcaa41fae9cf991b310f7a2
parent5ba0926fabd419e51f777f138389e3588bbd1ce9 (diff)
downloadwydawca-master.tar.gz
wydawca-master.tar.bz2
Add interface for closing file descriptors greater than or equal to the given one.HEADmaster
-rw-r--r--am/ax_closefrom.m464
-rw-r--r--configure.ac3
-rw-r--r--src/Makefile.am1
-rw-r--r--src/closefrom.c135
-rw-r--r--src/directive.c10
-rw-r--r--src/exec.c3
-rw-r--r--src/wydawca.h3
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
36AC_DEFUN([AX_CLOSEFROM],
37[
38AC_CHECK_FUNCS([sysconf getdtablesize closefrom proc_pidinfo])
39
40AC_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
48AC_CHECK_HEADERS([libproc.h])
49
50AC_MSG_CHECKING([for closefrom interface])
51if test "$ac_cv_func_closefrom" = yes; then
52 closefrom_api=closefrom
53elif test "$ac_cv_have_decl_F_CLOSEM" = yes; then
54 closefrom_api=F_CLOSEM
55elif test "${ac_cv_header_libproc_h}-$ac_cv_func_proc_pidinfo" = "yes-yes"; then
56 closefrom_api=proc_pidinfo
57elif 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
60else
61 closefrom_api=bruteforce
62fi
63AC_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.
53AC_FUNC_VPRINTF 53AC_FUNC_VPRINTF
54AC_CHECK_FUNCS([setegid setregid setresgid setresuid seteuid \ 54AC_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
58AX_PTHREAD([], 58AX_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
61AX_THREAD_NAMES 61AX_THREAD_NAMES
62AX_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)
21static int
22close_fds_sys(int minfd)
23{
24 closefrom(minfd);
25 return 0;
26}
27
28#elif defined (HAVE_FCNTL_CLOSEM)
29# include <fcntl.h>
30
31static int
32close_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
41static int
42close_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
78static int
79close_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
113static int
114close_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
124void
125wy_close_fds_from(int minfd)
126{
127 if (close_fds_sys(minfd))
128 close_fds_bruteforce(minfd);
129}
130
131void
132wy_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)