Branch data Line data Source code
1 : : /* SPDX-License-Identifier: LGPL-2.1+ */
2 : :
3 : : #include <errno.h>
4 : : #include <stdarg.h>
5 : : #include <stdio.h>
6 : :
7 : : #include "macro.h"
8 : : #include "parse-util.h"
9 : : #include "signal-util.h"
10 : : #include "stdio-util.h"
11 : : #include "string-table.h"
12 : : #include "string-util.h"
13 : :
14 : 28 : int reset_all_signal_handlers(void) {
15 : : static const struct sigaction sa = {
16 : : .sa_handler = SIG_DFL,
17 : : .sa_flags = SA_RESTART,
18 : : };
19 : 28 : int sig, r = 0;
20 : :
21 [ + + ]: 1820 : for (sig = 1; sig < _NSIG; sig++) {
22 : :
23 : : /* These two cannot be caught... */
24 [ + + + + ]: 1792 : if (IN_SET(sig, SIGKILL, SIGSTOP))
25 : 56 : continue;
26 : :
27 : : /* On Linux the first two RT signals are reserved by
28 : : * glibc, and sigaction() will return EINVAL for them. */
29 [ + + ]: 1736 : if ((sigaction(sig, &sa, NULL) < 0))
30 [ - + # # ]: 56 : if (errno != EINVAL && r >= 0)
31 : 0 : r = -errno;
32 : : }
33 : :
34 : 28 : return r;
35 : : }
36 : :
37 : 28 : int reset_signal_mask(void) {
38 : : sigset_t ss;
39 : :
40 [ - + ]: 28 : if (sigemptyset(&ss) < 0)
41 : 0 : return -errno;
42 : :
43 [ - + ]: 28 : if (sigprocmask(SIG_SETMASK, &ss, NULL) < 0)
44 : 0 : return -errno;
45 : :
46 : 28 : return 0;
47 : : }
48 : :
49 : 12 : static int sigaction_many_ap(const struct sigaction *sa, int sig, va_list ap) {
50 : 12 : int r = 0;
51 : :
52 : : /* negative signal ends the list. 0 signal is skipped. */
53 : :
54 [ - + ]: 12 : if (sig < 0)
55 : 0 : return 0;
56 : :
57 [ + - ]: 12 : if (sig > 0) {
58 [ - + ]: 12 : if (sigaction(sig, sa, NULL) < 0)
59 : 0 : r = -errno;
60 : : }
61 : :
62 [ + + ]: 40 : while ((sig = va_arg(ap, int)) >= 0) {
63 : :
64 [ - + ]: 28 : if (sig == 0)
65 : 0 : continue;
66 : :
67 [ - + ]: 28 : if (sigaction(sig, sa, NULL) < 0) {
68 [ # # ]: 0 : if (r >= 0)
69 : 0 : r = -errno;
70 : : }
71 : : }
72 : :
73 : 12 : return r;
74 : : }
75 : :
76 : 0 : int sigaction_many(const struct sigaction *sa, ...) {
77 : : va_list ap;
78 : : int r;
79 : :
80 : 0 : va_start(ap, sa);
81 : 0 : r = sigaction_many_ap(sa, 0, ap);
82 : 0 : va_end(ap);
83 : :
84 : 0 : return r;
85 : : }
86 : :
87 : 8 : int ignore_signals(int sig, ...) {
88 : :
89 : : static const struct sigaction sa = {
90 : : .sa_handler = SIG_IGN,
91 : : .sa_flags = SA_RESTART,
92 : : };
93 : :
94 : : va_list ap;
95 : : int r;
96 : :
97 : 8 : va_start(ap, sig);
98 : 8 : r = sigaction_many_ap(&sa, sig, ap);
99 : 8 : va_end(ap);
100 : :
101 : 8 : return r;
102 : : }
103 : :
104 : 4 : int default_signals(int sig, ...) {
105 : :
106 : : static const struct sigaction sa = {
107 : : .sa_handler = SIG_DFL,
108 : : .sa_flags = SA_RESTART,
109 : : };
110 : :
111 : : va_list ap;
112 : : int r;
113 : :
114 : 4 : va_start(ap, sig);
115 : 4 : r = sigaction_many_ap(&sa, sig, ap);
116 : 4 : va_end(ap);
117 : :
118 : 4 : return r;
119 : : }
120 : :
121 : 68 : static int sigset_add_many_ap(sigset_t *ss, va_list ap) {
122 : 68 : int sig, r = 0;
123 : :
124 [ - + ]: 68 : assert(ss);
125 : :
126 [ + + ]: 1336 : while ((sig = va_arg(ap, int)) >= 0) {
127 : :
128 [ - + ]: 1268 : if (sig == 0)
129 : 0 : continue;
130 : :
131 [ - + ]: 1268 : if (sigaddset(ss, sig) < 0) {
132 [ # # ]: 0 : if (r >= 0)
133 : 0 : r = -errno;
134 : : }
135 : : }
136 : :
137 : 68 : return r;
138 : : }
139 : :
140 : 44 : int sigset_add_many(sigset_t *ss, ...) {
141 : : va_list ap;
142 : : int r;
143 : :
144 : 44 : va_start(ap, ss);
145 : 44 : r = sigset_add_many_ap(ss, ap);
146 : 44 : va_end(ap);
147 : :
148 : 44 : return r;
149 : : }
150 : :
151 : 24 : int sigprocmask_many(int how, sigset_t *old, ...) {
152 : : va_list ap;
153 : : sigset_t ss;
154 : : int r;
155 : :
156 [ - + ]: 24 : if (sigemptyset(&ss) < 0)
157 : 0 : return -errno;
158 : :
159 : 24 : va_start(ap, old);
160 : 24 : r = sigset_add_many_ap(&ss, ap);
161 : 24 : va_end(ap);
162 : :
163 [ - + ]: 24 : if (r < 0)
164 : 0 : return r;
165 : :
166 [ - + ]: 24 : if (sigprocmask(how, &ss, old) < 0)
167 : 0 : return -errno;
168 : :
169 : 24 : return 0;
170 : : }
171 : :
172 : : static const char *const __signal_table[] = {
173 : : [SIGHUP] = "HUP",
174 : : [SIGINT] = "INT",
175 : : [SIGQUIT] = "QUIT",
176 : : [SIGILL] = "ILL",
177 : : [SIGTRAP] = "TRAP",
178 : : [SIGABRT] = "ABRT",
179 : : [SIGBUS] = "BUS",
180 : : [SIGFPE] = "FPE",
181 : : [SIGKILL] = "KILL",
182 : : [SIGUSR1] = "USR1",
183 : : [SIGSEGV] = "SEGV",
184 : : [SIGUSR2] = "USR2",
185 : : [SIGPIPE] = "PIPE",
186 : : [SIGALRM] = "ALRM",
187 : : [SIGTERM] = "TERM",
188 : : #ifdef SIGSTKFLT
189 : : [SIGSTKFLT] = "STKFLT", /* Linux on SPARC doesn't know SIGSTKFLT */
190 : : #endif
191 : : [SIGCHLD] = "CHLD",
192 : : [SIGCONT] = "CONT",
193 : : [SIGSTOP] = "STOP",
194 : : [SIGTSTP] = "TSTP",
195 : : [SIGTTIN] = "TTIN",
196 : : [SIGTTOU] = "TTOU",
197 : : [SIGURG] = "URG",
198 : : [SIGXCPU] = "XCPU",
199 : : [SIGXFSZ] = "XFSZ",
200 : : [SIGVTALRM] = "VTALRM",
201 : : [SIGPROF] = "PROF",
202 : : [SIGWINCH] = "WINCH",
203 : : [SIGIO] = "IO",
204 : : [SIGPWR] = "PWR",
205 : : [SIGSYS] = "SYS"
206 : : };
207 : :
208 [ + - + + ]: 1732 : DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int);
209 : :
210 : 1448 : const char *signal_to_string(int signo) {
211 : : static thread_local char buf[STRLEN("RTMIN+") + DECIMAL_STR_MAX(int) + 1];
212 : : const char *name;
213 : :
214 : 1448 : name = __signal_to_string(signo);
215 [ + + ]: 1448 : if (name)
216 : 1424 : return name;
217 : :
218 [ + - + - ]: 24 : if (signo >= SIGRTMIN && signo <= SIGRTMAX)
219 [ - + ]: 24 : xsprintf(buf, "RTMIN+%d", signo - SIGRTMIN);
220 : : else
221 [ # # ]: 0 : xsprintf(buf, "%d", signo);
222 : :
223 : 24 : return buf;
224 : : }
225 : :
226 : 304 : int signal_from_string(const char *s) {
227 : : const char *p;
228 : : int signo, r;
229 : :
230 : : /* Check that the input is a signal number. */
231 [ + + ]: 304 : if (safe_atoi(s, &signo) >= 0) {
232 [ + + ]: 20 : if (SIGNAL_VALID(signo))
233 : 12 : return signo;
234 : : else
235 : 8 : return -ERANGE;
236 : : }
237 : :
238 : : /* Drop "SIG" prefix. */
239 [ + + ]: 284 : if (startswith(s, "SIG"))
240 : 152 : s += 3;
241 : :
242 : : /* Check that the input is a signal name. */
243 : 284 : signo = __signal_from_string(s);
244 [ + + ]: 284 : if (signo > 0)
245 : 16 : return signo;
246 : :
247 : : /* Check that the input is RTMIN or
248 : : * RTMIN+n (0 <= n <= SIGRTMAX-SIGRTMIN). */
249 : 268 : p = startswith(s, "RTMIN");
250 [ + + ]: 268 : if (p) {
251 [ + + ]: 128 : if (*p == '\0')
252 : 8 : return SIGRTMIN;
253 [ + + ]: 120 : if (*p != '+')
254 : 40 : return -EINVAL;
255 : :
256 : 80 : r = safe_atoi(p, &signo);
257 [ + + ]: 80 : if (r < 0)
258 : 32 : return r;
259 : :
260 [ + - + + ]: 48 : if (signo < 0 || signo > SIGRTMAX - SIGRTMIN)
261 : 16 : return -ERANGE;
262 : :
263 : 32 : return signo + SIGRTMIN;
264 : : }
265 : :
266 : : /* Check that the input is RTMAX or
267 : : * RTMAX-n (0 <= n <= SIGRTMAX-SIGRTMIN). */
268 : 140 : p = startswith(s, "RTMAX");
269 [ + + ]: 140 : if (p) {
270 [ + + ]: 96 : if (*p == '\0')
271 : 8 : return SIGRTMAX;
272 [ + + ]: 88 : if (*p != '-')
273 : 32 : return -EINVAL;
274 : :
275 : 56 : r = safe_atoi(p, &signo);
276 [ + + ]: 56 : if (r < 0)
277 : 32 : return r;
278 : :
279 [ + - + + ]: 24 : if (signo > 0 || signo < SIGRTMIN - SIGRTMAX)
280 : 16 : return -ERANGE;
281 : :
282 : 8 : return signo + SIGRTMAX;
283 : : }
284 : :
285 : 44 : return -EINVAL;
286 : : }
287 : :
288 : 0 : void nop_signal_handler(int sig) {
289 : : /* nothing here */
290 : 0 : }
|