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