xref: /openbmc/linux/tools/lib/subcmd/sigchain.c (revision 498495dba268b20e8eadd7fe93c140c68b6cc9d2)
1*b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
24b6ab94eSJosh Poimboeuf #include <signal.h>
34b6ab94eSJosh Poimboeuf #include "subcmd-util.h"
44b6ab94eSJosh Poimboeuf #include "sigchain.h"
54b6ab94eSJosh Poimboeuf 
64b6ab94eSJosh Poimboeuf #define SIGCHAIN_MAX_SIGNALS 32
74b6ab94eSJosh Poimboeuf 
84b6ab94eSJosh Poimboeuf struct sigchain_signal {
94b6ab94eSJosh Poimboeuf 	sigchain_fun *old;
104b6ab94eSJosh Poimboeuf 	int n;
114b6ab94eSJosh Poimboeuf 	int alloc;
124b6ab94eSJosh Poimboeuf };
134b6ab94eSJosh Poimboeuf static struct sigchain_signal signals[SIGCHAIN_MAX_SIGNALS];
144b6ab94eSJosh Poimboeuf 
check_signum(int sig)154b6ab94eSJosh Poimboeuf static void check_signum(int sig)
164b6ab94eSJosh Poimboeuf {
174b6ab94eSJosh Poimboeuf 	if (sig < 1 || sig >= SIGCHAIN_MAX_SIGNALS)
184b6ab94eSJosh Poimboeuf 		die("BUG: signal out of range: %d", sig);
194b6ab94eSJosh Poimboeuf }
204b6ab94eSJosh Poimboeuf 
sigchain_push(int sig,sigchain_fun f)214b6ab94eSJosh Poimboeuf static int sigchain_push(int sig, sigchain_fun f)
224b6ab94eSJosh Poimboeuf {
234b6ab94eSJosh Poimboeuf 	struct sigchain_signal *s = signals + sig;
244b6ab94eSJosh Poimboeuf 	check_signum(sig);
254b6ab94eSJosh Poimboeuf 
264b6ab94eSJosh Poimboeuf 	ALLOC_GROW(s->old, s->n + 1, s->alloc);
274b6ab94eSJosh Poimboeuf 	s->old[s->n] = signal(sig, f);
284b6ab94eSJosh Poimboeuf 	if (s->old[s->n] == SIG_ERR)
294b6ab94eSJosh Poimboeuf 		return -1;
304b6ab94eSJosh Poimboeuf 	s->n++;
314b6ab94eSJosh Poimboeuf 	return 0;
324b6ab94eSJosh Poimboeuf }
334b6ab94eSJosh Poimboeuf 
sigchain_pop(int sig)344b6ab94eSJosh Poimboeuf int sigchain_pop(int sig)
354b6ab94eSJosh Poimboeuf {
364b6ab94eSJosh Poimboeuf 	struct sigchain_signal *s = signals + sig;
374b6ab94eSJosh Poimboeuf 	check_signum(sig);
384b6ab94eSJosh Poimboeuf 	if (s->n < 1)
394b6ab94eSJosh Poimboeuf 		return 0;
404b6ab94eSJosh Poimboeuf 
414b6ab94eSJosh Poimboeuf 	if (signal(sig, s->old[s->n - 1]) == SIG_ERR)
424b6ab94eSJosh Poimboeuf 		return -1;
434b6ab94eSJosh Poimboeuf 	s->n--;
444b6ab94eSJosh Poimboeuf 	return 0;
454b6ab94eSJosh Poimboeuf }
464b6ab94eSJosh Poimboeuf 
sigchain_push_common(sigchain_fun f)474b6ab94eSJosh Poimboeuf void sigchain_push_common(sigchain_fun f)
484b6ab94eSJosh Poimboeuf {
494b6ab94eSJosh Poimboeuf 	sigchain_push(SIGINT, f);
504b6ab94eSJosh Poimboeuf 	sigchain_push(SIGHUP, f);
514b6ab94eSJosh Poimboeuf 	sigchain_push(SIGTERM, f);
524b6ab94eSJosh Poimboeuf 	sigchain_push(SIGQUIT, f);
534b6ab94eSJosh Poimboeuf 	sigchain_push(SIGPIPE, f);
544b6ab94eSJosh Poimboeuf }
55