]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/signal-util.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / basic / signal-util.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
24882e06
LP
2/***
3 This file is part of systemd.
4
5 Copyright 2015 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
11c3a366
TA
21#include <errno.h>
22#include <stdarg.h>
23#include <stdio.h>
24
93cc7779 25#include "macro.h"
6bedfcbb
LP
26#include "parse-util.h"
27#include "signal-util.h"
d054f0a4 28#include "stdio-util.h"
8b43440b 29#include "string-table.h"
07630cea 30#include "string-util.h"
07630cea 31
24882e06 32int reset_all_signal_handlers(void) {
0c2c2a3a
LP
33 static const struct sigaction sa = {
34 .sa_handler = SIG_DFL,
35 .sa_flags = SA_RESTART,
36 };
24882e06
LP
37 int sig, r = 0;
38
39 for (sig = 1; sig < _NSIG; sig++) {
24882e06
LP
40
41 /* These two cannot be caught... */
3742095b 42 if (IN_SET(sig, SIGKILL, SIGSTOP))
24882e06
LP
43 continue;
44
45 /* On Linux the first two RT signals are reserved by
46 * glibc, and sigaction() will return EINVAL for them. */
47 if ((sigaction(sig, &sa, NULL) < 0))
0c2c2a3a 48 if (errno != EINVAL && r >= 0)
24882e06
LP
49 r = -errno;
50 }
51
52 return r;
53}
54
55int reset_signal_mask(void) {
56 sigset_t ss;
57
58 if (sigemptyset(&ss) < 0)
59 return -errno;
60
61 if (sigprocmask(SIG_SETMASK, &ss, NULL) < 0)
62 return -errno;
63
64 return 0;
65}
66
0c2c2a3a
LP
67static int sigaction_many_ap(const struct sigaction *sa, int sig, va_list ap) {
68 int r = 0;
69
70 /* negative signal ends the list. 0 signal is skipped. */
71
72 if (sig < 0)
73 return 0;
74
75 if (sig > 0) {
76 if (sigaction(sig, sa, NULL) < 0)
77 r = -errno;
78 }
79
80 while ((sig = va_arg(ap, int)) >= 0) {
81
82 if (sig == 0)
83 continue;
84
85 if (sigaction(sig, sa, NULL) < 0) {
86 if (r >= 0)
87 r = -errno;
88 }
89 }
90
91 return r;
92}
93
24882e06
LP
94int sigaction_many(const struct sigaction *sa, ...) {
95 va_list ap;
0c2c2a3a 96 int r;
24882e06
LP
97
98 va_start(ap, sa);
0c2c2a3a 99 r = sigaction_many_ap(sa, 0, ap);
24882e06
LP
100 va_end(ap);
101
102 return r;
103}
104
105int ignore_signals(int sig, ...) {
0c2c2a3a 106
24882e06
LP
107 static const struct sigaction sa = {
108 .sa_handler = SIG_IGN,
109 .sa_flags = SA_RESTART,
110 };
24882e06 111
0c2c2a3a
LP
112 va_list ap;
113 int r;
24882e06
LP
114
115 va_start(ap, sig);
0c2c2a3a 116 r = sigaction_many_ap(&sa, sig, ap);
24882e06
LP
117 va_end(ap);
118
119 return r;
120}
121
122int default_signals(int sig, ...) {
0c2c2a3a 123
24882e06
LP
124 static const struct sigaction sa = {
125 .sa_handler = SIG_DFL,
126 .sa_flags = SA_RESTART,
127 };
24882e06 128
0c2c2a3a
LP
129 va_list ap;
130 int r;
24882e06
LP
131
132 va_start(ap, sig);
0c2c2a3a 133 r = sigaction_many_ap(&sa, sig, ap);
24882e06
LP
134 va_end(ap);
135
136 return r;
137}
138
0c2c2a3a
LP
139static int sigset_add_many_ap(sigset_t *ss, va_list ap) {
140 int sig, r = 0;
24882e06
LP
141
142 assert(ss);
143
0c2c2a3a
LP
144 while ((sig = va_arg(ap, int)) >= 0) {
145
146 if (sig == 0)
147 continue;
148
149 if (sigaddset(ss, sig) < 0) {
150 if (r >= 0)
151 r = -errno;
152 }
153 }
154
155 return r;
156}
157
158int sigset_add_many(sigset_t *ss, ...) {
159 va_list ap;
160 int r;
161
24882e06 162 va_start(ap, ss);
0c2c2a3a 163 r = sigset_add_many_ap(ss, ap);
24882e06 164 va_end(ap);
0c2c2a3a
LP
165
166 return r;
24882e06
LP
167}
168
72c0a2c2 169int sigprocmask_many(int how, sigset_t *old, ...) {
24882e06
LP
170 va_list ap;
171 sigset_t ss;
0c2c2a3a 172 int r;
24882e06 173
0c2c2a3a
LP
174 if (sigemptyset(&ss) < 0)
175 return -errno;
24882e06 176
c59d3e8d 177 va_start(ap, old);
0c2c2a3a 178 r = sigset_add_many_ap(&ss, ap);
24882e06
LP
179 va_end(ap);
180
0c2c2a3a
LP
181 if (r < 0)
182 return r;
183
72c0a2c2 184 if (sigprocmask(how, &ss, old) < 0)
24882e06
LP
185 return -errno;
186
187 return 0;
188}
189
190static const char *const __signal_table[] = {
191 [SIGHUP] = "HUP",
192 [SIGINT] = "INT",
193 [SIGQUIT] = "QUIT",
194 [SIGILL] = "ILL",
195 [SIGTRAP] = "TRAP",
196 [SIGABRT] = "ABRT",
197 [SIGBUS] = "BUS",
198 [SIGFPE] = "FPE",
199 [SIGKILL] = "KILL",
200 [SIGUSR1] = "USR1",
201 [SIGSEGV] = "SEGV",
202 [SIGUSR2] = "USR2",
203 [SIGPIPE] = "PIPE",
204 [SIGALRM] = "ALRM",
205 [SIGTERM] = "TERM",
206#ifdef SIGSTKFLT
207 [SIGSTKFLT] = "STKFLT", /* Linux on SPARC doesn't know SIGSTKFLT */
208#endif
209 [SIGCHLD] = "CHLD",
210 [SIGCONT] = "CONT",
211 [SIGSTOP] = "STOP",
212 [SIGTSTP] = "TSTP",
213 [SIGTTIN] = "TTIN",
214 [SIGTTOU] = "TTOU",
215 [SIGURG] = "URG",
216 [SIGXCPU] = "XCPU",
217 [SIGXFSZ] = "XFSZ",
218 [SIGVTALRM] = "VTALRM",
219 [SIGPROF] = "PROF",
220 [SIGWINCH] = "WINCH",
221 [SIGIO] = "IO",
222 [SIGPWR] = "PWR",
223 [SIGSYS] = "SYS"
224};
225
226DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int);
227
228const char *signal_to_string(int signo) {
229 static thread_local char buf[sizeof("RTMIN+")-1 + DECIMAL_STR_MAX(int) + 1];
230 const char *name;
231
232 name = __signal_to_string(signo);
233 if (name)
234 return name;
235
236 if (signo >= SIGRTMIN && signo <= SIGRTMAX)
d054f0a4 237 xsprintf(buf, "RTMIN+%d", signo - SIGRTMIN);
24882e06 238 else
d054f0a4 239 xsprintf(buf, "%d", signo);
24882e06
LP
240
241 return buf;
242}
243
244int signal_from_string(const char *s) {
245 int signo;
246 int offset = 0;
247 unsigned u;
248
249 signo = __signal_from_string(s);
250 if (signo > 0)
251 return signo;
252
253 if (startswith(s, "RTMIN+")) {
254 s += 6;
255 offset = SIGRTMIN;
256 }
257 if (safe_atou(s, &u) >= 0) {
258 signo = (int) u + offset;
6eb7c172 259 if (SIGNAL_VALID(signo))
24882e06
LP
260 return signo;
261 }
262 return -EINVAL;
263}
264
265int signal_from_string_try_harder(const char *s) {
266 int signo;
267 assert(s);
268
269 signo = signal_from_string(s);
270 if (signo <= 0)
271 if (startswith(s, "SIG"))
272 return signal_from_string(s+3);
273
274 return signo;
275}
6bedfcbb
LP
276
277void nop_signal_handler(int sig) {
278 /* nothing here */
279}