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
8struct sigchain_signal {
9	sigchain_fun *old;
10	int n;
11	int alloc;
12};
13static struct sigchain_signal signals[SIGCHAIN_MAX_SIGNALS];
14
15static void check_signum(int sig)
16{
17	if (sig < 1 || sig >= SIGCHAIN_MAX_SIGNALS)
18		die("BUG: signal out of range: %d", sig);
19}
20
21static 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
34int 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
47void sigchain_push_common(sigchain_fun f)
48{
49	sigchain_push(SIGINT, f);
50	sigchain_push(SIGHUP, f);
51	sigchain_push(SIGTERM, f);
52	sigchain_push(SIGQUIT, f);
53	sigchain_push(SIGPIPE, f);
54}
55