aboutsummaryrefslogtreecommitdiff
path: root/libbb/signals.c
blob: d3d84ef6a74176f94f84e0e0d9b9389b9f41b6a8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/* vi: set sw=4 ts=4: */
/*
 * Utility routines.
 *
 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
 * Copyright (C) 2006 Rob Landley
 * Copyright (C) 2006 Denys Vlasenko
 *
 * Licensed under GPLv2, see file LICENSE in this source tree.
 */
#include "libbb.h"

/* All known arches use small ints for signals */
smallint bb_got_signal;

void record_signo(int signo)
{
	bb_got_signal = signo;
}

/* Saves 2 bytes on x86! Oh my... */
int FAST_FUNC sigaction_set(int signum, const struct sigaction *act)
{
	return sigaction(signum, act, NULL);
}

int FAST_FUNC sigprocmask_allsigs(int how)
{
	sigset_t set;
	sigfillset(&set);
	return sigprocmask(how, &set, NULL);
}

int FAST_FUNC sigprocmask2(int how, sigset_t *set)
{
	// Grr... gcc 8.1.1:
	// "passing argument 3 to restrict-qualified parameter aliases with argument 2"
	// dance around that...
	sigset_t *oset FIX_ALIASING;
	oset = set;
	return sigprocmask(how, set, oset);
}

void FAST_FUNC bb_signals(int sigs, void (*f)(int))
{
	int sig_no = 0;
	int bit = 1;

	while (sigs) {
		if (sigs & bit) {
			sigs -= bit;
			signal(sig_no, f);
		}
		sig_no++;
		bit <<= 1;
	}
}

void FAST_FUNC bb_signals_recursive_norestart(int sigs, void (*f)(int))
{
	int sig_no = 0;
	int bit = 1;
	struct sigaction sa;

	memset(&sa, 0, sizeof(sa));
	sa.sa_handler = f;
	/*sa.sa_flags = 0;*/
	/*sigemptyset(&sa.sa_mask); - hope memset did it*/

	while (sigs) {
		if (sigs & bit) {
			sigs -= bit;
			sigaction_set(sig_no, &sa);
		}
		sig_no++;
		bit <<= 1;
	}
}

void FAST_FUNC sig_block(int sig)
{
	sigset_t ss;
	sigemptyset(&ss);
	sigaddset(&ss, sig);
	sigprocmask(SIG_BLOCK, &ss, NULL);
}

void FAST_FUNC sig_unblock(int sig)
{
	sigset_t ss;
	sigemptyset(&ss);
	sigaddset(&ss, sig);
	sigprocmask(SIG_UNBLOCK, &ss, NULL);
}

void FAST_FUNC wait_for_any_sig(void)
{
	sigset_t ss;
	sigemptyset(&ss);
	sigsuspend(&ss);
}

/* Assuming the sig is fatal */
void FAST_FUNC kill_myself_with_sig(int sig)
{
	signal(sig, SIG_DFL);
	sig_unblock(sig);
	raise(sig);
	_exit(sig | 128); /* Should not reach it */
}

void FAST_FUNC signal_SA_RESTART_empty_mask(int sig, void (*handler)(int))
{
	struct sigaction sa;
	memset(&sa, 0, sizeof(sa));
	/*sigemptyset(&sa.sa_mask);*/
	sa.sa_flags = SA_RESTART;
	sa.sa_handler = handler;
	sigaction_set(sig, &sa);
}

void FAST_FUNC signal_no_SA_RESTART_empty_mask(int sig, void (*handler)(int))
{
	struct sigaction sa;
	memset(&sa, 0, sizeof(sa));
	/*sigemptyset(&sa.sa_mask);*/
	/*sa.sa_flags = 0;*/
	sa.sa_handler = handler;
	sigaction_set(sig, &sa);
}