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