1 | // SPDX-License-Identifier: GPL-2.0 |
2 | #include <signal.h> |
3 | #include "subcmd-util.h" |
4 | #include "sigchain.h" |
5 | |
6 | #define SIGCHAIN_MAX_SIGNALS 32 |
7 | |
8 | struct sigchain_signal { |
9 | sigchain_fun *old; |
10 | int n; |
11 | int alloc; |
12 | }; |
13 | static struct sigchain_signal signals[SIGCHAIN_MAX_SIGNALS]; |
14 | |
15 | static void check_signum(int sig) |
16 | { |
17 | if (sig < 1 || sig >= SIGCHAIN_MAX_SIGNALS) |
18 | die(err: "BUG: signal out of range: %d" , sig); |
19 | } |
20 | |
21 | static int sigchain_push(int sig, sigchain_fun f) |
22 | { |
23 | struct sigchain_signal *s = signals + sig; |
24 | check_signum(sig); |
25 | |
26 | ALLOC_GROW(s->old, s->n + 1, s->alloc); |
27 | s->old[s->n] = signal(sig, f); |
28 | if (s->old[s->n] == SIG_ERR) |
29 | return -1; |
30 | s->n++; |
31 | return 0; |
32 | } |
33 | |
34 | int sigchain_pop(int sig) |
35 | { |
36 | struct sigchain_signal *s = signals + sig; |
37 | check_signum(sig); |
38 | if (s->n < 1) |
39 | return 0; |
40 | |
41 | if (signal(sig, s->old[s->n - 1]) == SIG_ERR) |
42 | return -1; |
43 | s->n--; |
44 | return 0; |
45 | } |
46 | |
47 | void sigchain_push_common(sigchain_fun f) |
48 | { |
49 | sigchain_push(sig: SIGINT, f); |
50 | sigchain_push(sig: SIGHUP, f); |
51 | sigchain_push(sig: SIGTERM, f); |
52 | sigchain_push(sig: SIGQUIT, f); |
53 | sigchain_push(sig: SIGPIPE, f); |
54 | } |
55 | |