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