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 7 : int reset_all_signal_handlers(void) {
15 : static const struct sigaction sa = {
16 : .sa_handler = SIG_DFL,
17 : .sa_flags = SA_RESTART,
18 : };
19 7 : int sig, r = 0;
20 :
21 455 : for (sig = 1; sig < _NSIG; sig++) {
22 :
23 : /* These two cannot be caught... */
24 448 : if (IN_SET(sig, SIGKILL, SIGSTOP))
25 14 : continue;
26 :
27 : /* On Linux the first two RT signals are reserved by
28 : * glibc, and sigaction() will return EINVAL for them. */
29 434 : if ((sigaction(sig, &sa, NULL) < 0))
30 14 : if (errno != EINVAL && r >= 0)
31 0 : r = -errno;
32 : }
33 :
34 7 : return r;
35 : }
36 :
37 7 : int reset_signal_mask(void) {
38 : sigset_t ss;
39 :
40 7 : if (sigemptyset(&ss) < 0)
41 0 : return -errno;
42 :
43 7 : if (sigprocmask(SIG_SETMASK, &ss, NULL) < 0)
44 0 : return -errno;
45 :
46 7 : return 0;
47 : }
48 :
49 3 : static int sigaction_many_ap(const struct sigaction *sa, int sig, va_list ap) {
50 3 : int r = 0;
51 :
52 : /* negative signal ends the list. 0 signal is skipped. */
53 :
54 3 : if (sig < 0)
55 0 : return 0;
56 :
57 3 : if (sig > 0) {
58 3 : if (sigaction(sig, sa, NULL) < 0)
59 0 : r = -errno;
60 : }
61 :
62 10 : while ((sig = va_arg(ap, int)) >= 0) {
63 :
64 7 : if (sig == 0)
65 0 : continue;
66 :
67 7 : if (sigaction(sig, sa, NULL) < 0) {
68 0 : if (r >= 0)
69 0 : r = -errno;
70 : }
71 : }
72 :
73 3 : 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 2 : 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 2 : va_start(ap, sig);
98 2 : r = sigaction_many_ap(&sa, sig, ap);
99 2 : va_end(ap);
100 :
101 2 : return r;
102 : }
103 :
104 1 : 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 1 : va_start(ap, sig);
115 1 : r = sigaction_many_ap(&sa, sig, ap);
116 1 : va_end(ap);
117 :
118 1 : return r;
119 : }
120 :
121 17 : static int sigset_add_many_ap(sigset_t *ss, va_list ap) {
122 17 : int sig, r = 0;
123 :
124 17 : assert(ss);
125 :
126 334 : while ((sig = va_arg(ap, int)) >= 0) {
127 :
128 317 : if (sig == 0)
129 0 : continue;
130 :
131 317 : if (sigaddset(ss, sig) < 0) {
132 0 : if (r >= 0)
133 0 : r = -errno;
134 : }
135 : }
136 :
137 17 : return r;
138 : }
139 :
140 11 : int sigset_add_many(sigset_t *ss, ...) {
141 : va_list ap;
142 : int r;
143 :
144 11 : va_start(ap, ss);
145 11 : r = sigset_add_many_ap(ss, ap);
146 11 : va_end(ap);
147 :
148 11 : return r;
149 : }
150 :
151 6 : int sigprocmask_many(int how, sigset_t *old, ...) {
152 : va_list ap;
153 : sigset_t ss;
154 : int r;
155 :
156 6 : if (sigemptyset(&ss) < 0)
157 0 : return -errno;
158 :
159 6 : va_start(ap, old);
160 6 : r = sigset_add_many_ap(&ss, ap);
161 6 : va_end(ap);
162 :
163 6 : if (r < 0)
164 0 : return r;
165 :
166 6 : if (sigprocmask(how, &ss, old) < 0)
167 0 : return -errno;
168 :
169 6 : 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 433 : DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int);
209 :
210 362 : 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 362 : name = __signal_to_string(signo);
215 362 : if (name)
216 356 : return name;
217 :
218 6 : if (signo >= SIGRTMIN && signo <= SIGRTMAX)
219 6 : xsprintf(buf, "RTMIN+%d", signo - SIGRTMIN);
220 : else
221 0 : xsprintf(buf, "%d", signo);
222 :
223 6 : return buf;
224 : }
225 :
226 76 : 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 76 : if (safe_atoi(s, &signo) >= 0) {
232 5 : if (SIGNAL_VALID(signo))
233 3 : return signo;
234 : else
235 2 : return -ERANGE;
236 : }
237 :
238 : /* Drop "SIG" prefix. */
239 71 : if (startswith(s, "SIG"))
240 38 : s += 3;
241 :
242 : /* Check that the input is a signal name. */
243 71 : signo = __signal_from_string(s);
244 71 : if (signo > 0)
245 4 : return signo;
246 :
247 : /* Check that the input is RTMIN or
248 : * RTMIN+n (0 <= n <= SIGRTMAX-SIGRTMIN). */
249 67 : p = startswith(s, "RTMIN");
250 67 : if (p) {
251 32 : if (*p == '\0')
252 2 : return SIGRTMIN;
253 30 : if (*p != '+')
254 10 : return -EINVAL;
255 :
256 20 : r = safe_atoi(p, &signo);
257 20 : if (r < 0)
258 8 : return r;
259 :
260 12 : if (signo < 0 || signo > SIGRTMAX - SIGRTMIN)
261 4 : return -ERANGE;
262 :
263 8 : return signo + SIGRTMIN;
264 : }
265 :
266 : /* Check that the input is RTMAX or
267 : * RTMAX-n (0 <= n <= SIGRTMAX-SIGRTMIN). */
268 35 : p = startswith(s, "RTMAX");
269 35 : if (p) {
270 24 : if (*p == '\0')
271 2 : return SIGRTMAX;
272 22 : if (*p != '-')
273 8 : return -EINVAL;
274 :
275 14 : r = safe_atoi(p, &signo);
276 14 : if (r < 0)
277 8 : return r;
278 :
279 6 : if (signo > 0 || signo < SIGRTMIN - SIGRTMAX)
280 4 : return -ERANGE;
281 :
282 2 : return signo + SIGRTMAX;
283 : }
284 :
285 11 : return -EINVAL;
286 : }
287 :
288 0 : void nop_signal_handler(int sig) {
289 : /* nothing here */
290 0 : }
|