1 /* NAME:
2 * sigact.c - fake sigaction(2)
3 *
4 * SYNOPSIS:
5 * #include "sigact.h"
6 *
7 * int sigaction(int sig, struct sigaction *act,
8 * struct sigaction *oact);
9 * int sigaddset(sigset_t *mask, int sig);
10 * int sigdelset(sigset_t *mask, int sig);
11 * int sigemptyset(sigset_t *mask);
12 * int sigfillset(sigset_t *mask);
13 * int sigismember(sigset_t *mask, int sig);
14 * int sigpending(sigset_t *set);
15 * int sigprocmask(int how, sigset_t *set, sigset_t *oset);
16 * int sigsuspend(sigset_t *mask);
17 *
18 * SIG_HDLR (*Signal(int sig, SIG_HDLR (*disp)(int)))(int);
19 *
20 * DESCRIPTION:
21 * This is a fake sigaction implementation. It uses
22 * sigsetmask(2) et al or sigset(2) and friends if
23 * available, otherwise it just uses signal(2). If it
24 * thinks sigaction(2) really exists it compiles to "almost"
25 * nothing.
26 *
27 * In any case it provides a Signal() function that is
28 * implemented in terms of sigaction().
29 * If not using signal(2) as part of the underlying
30 * implementation (USE_SIGNAL or USE_SIGMASK), and
31 * NO_SIGNAL is not defined, it also provides a signal()
32 * function that calls Signal().
33 *
34 * The need for all this mucking about is the problems
35 * caused by mixing various signal handling mechanisms in
36 * the one process. This module allows for a consistent
37 * POSIX compliant interface to whatever is actually
38 * available.
39 *
40 * sigaction() allows the caller to examine and/or set the
41 * action to be associated with a given signal. "act" and
42 * "oact" are pointers to 'sigaction structs':
43 *.nf
44 *
45 * struct sigaction
46 * {
47 * SIG_HDLR (*sa_handler)();
48 * sigset_t sa_mask;
49 * int sa_flags;
50 * };
51 *.fi
52 *
53 * SIG_HDLR is normally 'void' in the POSIX implementation
54 * and for most current systems. On some older UNIX
55 * systems, signal handlers do not return 'void', so
56 * this implementation keeps 'sa_handler' inline with the
57 * hosts normal signal handling conventions.
58 * 'sa_mask' controls which signals will be blocked while
59 * the selected signal handler is active. It is not used
60 * in this implementation.
61 * 'sa_flags' controls various semantics such as whether
62 * system calls should be automagically restarted
63 * (SA_RESTART) etc. It is not used in this
64 * implementation.
65 * Either "act" or "oact" may be NULL in which case the
66 * appropriate operation is skipped.
67 *
68 * sigaddset() adds "sig" to the sigset_t pointed to by "mask".
69 *
70 * sigdelset() removes "sig" from the sigset_t pointed to
71 * by "mask".
72 *
73 * sigemptyset() makes the sigset_t pointed to by "mask" empty.
74 *
75 * sigfillset() makes the sigset_t pointed to by "mask"
76 * full ie. match all signals.
77 *
78 * sigismember() returns true if "sig" is found in "*mask".
79 *
80 * sigpending() is supposed to return "set" loaded with the
81 * set of signals that are blocked and pending for the
82 * calling process. It does nothing in this impementation.
83 *
84 * sigprocmask() is used to examine and/or change the
85 * signal mask for the calling process. Either "set" or
86 * "oset" may be NULL in which case the appropriate
87 * operation is skipped. "how" may be one of SIG_BLOCK,
88 * SIG_UNBLOCK or SIG_SETMASK. If this package is built
89 * with USE_SIGNAL, then this routine achieves nothing.
90 *
91 * sigsuspend() sets the signal mask to "*mask" and waits
92 * for a signal to be delivered after which the previous
93 * mask is restored.
94 *
95 *
96 * RETURN VALUE:
97 * 0==success, -1==failure
98 *
99 * BUGS:
100 * Since we fake most of this, don't expect fancy usage to
101 * work.
102 *
103 * AUTHOR:
104 * Simon J. Gerraty <sjg@crufty.net>
105 */
106 /* COPYRIGHT:
107 * @(#)Copyright (c) 1992-2025, Simon J. Gerraty
108 *
109 * SPDX-License-Identifier: BSD-2-Clause
110 *
111 * Please send copies of changes and bug-fixes to:
112 * sjg@crufty.net
113 *
114 */
115 #ifndef lint
116 static char *RCSid = "$Id: sigact.c,v 1.9 2025/08/09 22:11:45 sjg Exp $";
117 #endif
118
119 #undef _ANSI_SOURCE /* causes problems */
120
121 #include <signal.h>
122 #include <sys/cdefs.h>
123
124 #ifdef HAVE_CONFIG_H
125 # include "config.h"
126 # ifdef NO_SIGSET
127 # undef HAVE_SIGSET
128 # endif
129 # ifndef HAVE_SIGACTION
130 # ifdef HAVE_SIGSETMASK
131 # define USE_SIGMASK
132 # else
133 # ifdef HAVE_SIGSET
134 # define USE_SIGSET
135 # else
136 # define USE_SIGNAL
137 # endif
138 # endif
139 # endif
140 #endif
141
142 /*
143 * some systems have a faulty sigaction() implementation!
144 * Allow us to bypass it.
145 * Or they may have installed sigact.h as signal.h which is why
146 * we have SA_NOCLDSTOP defined.
147 */
148 #if !defined(SA_NOCLDSTOP) || defined(_SIGACT_H) || defined(USE_SIGNAL) || defined(USE_SIGSET) || defined(USE_SIGMASK)
149
150 /*
151 * if we haven't been told,
152 * try and guess what we should implement with.
153 */
154 #if !defined(USE_SIGSET) && !defined(USE_SIGMASK) && !defined(USE_SIGNAL)
155 # if defined(sigmask) || defined(BSD) || defined(_BSD) && !defined(BSD41)
156 # define USE_SIGMASK
157 # else
158 # ifndef NO_SIGSET
159 # define USE_SIGSET
160 # else
161 # define USE_SIGNAL
162 # endif
163 # endif
164 #endif
165 /*
166 * if we still don't know, we're in trouble
167 */
168 #if !defined(USE_SIGSET) && !defined(USE_SIGMASK) && !defined(USE_SIGNAL)
169 error must know what to implement with
170 #endif
171
172 #include "sigact.h"
173
174 /*
175 * in case signal() has been mapped to our Signal().
176 */
177 #undef signal
178
179
180 int
sigaction(int sig,const struct sigaction * act,struct sigaction * oact)181 sigaction(int sig,
182 const struct sigaction *act,
183 struct sigaction *oact)
184 {
185 SIG_HDLR(*oldh) ();
186
187 if (act) {
188 #ifdef USE_SIGSET
189 oldh = sigset(sig, act->sa_handler);
190 #else
191 oldh = signal(sig, act->sa_handler);
192 #endif
193 } else {
194 if (oact) {
195 #ifdef USE_SIGSET
196 oldh = sigset(sig, SIG_IGN);
197 #else
198 oldh = signal(sig, SIG_IGN);
199 #endif
200 if (oldh != SIG_IGN && oldh != SIG_ERR) {
201 #ifdef USE_SIGSET
202 (void) sigset(sig, oldh);
203 #else
204 (void) signal(sig, oldh);
205 #endif
206 }
207 }
208 }
209 if (oact) {
210 oact->sa_handler = oldh;
211 }
212 return 0; /* hey we're faking it */
213 }
214
215 #ifndef HAVE_SIGADDSET
216 int
sigaddset(sigset_t * mask,int sig)217 sigaddset(sigset_t *mask, int sig)
218 {
219 *mask |= sigmask(sig);
220 return 0;
221 }
222
223
224 int
sigdelset(sigset_t * mask,int sig)225 sigdelset(sigset_t *mask, int sig)
226 {
227 *mask &= ~(sigmask(sig));
228 return 0;
229 }
230
231
232 int
sigemptyset(sigset_t * mask)233 sigemptyset(sigset_t *mask)
234 {
235 *mask = 0;
236 return 0;
237 }
238
239
240 int
sigfillset(sigset_t * mask)241 sigfillset(sigset_t *mask)
242 {
243 *mask = ~0;
244 return 0;
245 }
246
247
248 int
sigismember(const sigset_t * mask,int sig)249 sigismember(const sigset_t *mask, int sig)
250 {
251 return ((*mask) & sigmask(sig));
252 }
253 #endif
254
255 #ifndef HAVE_SIGPENDING
256 int
sigpending(sigset_t * set)257 sigpending(sigset_t *set)
258 {
259 return 0; /* faking it! */
260 }
261 #endif
262
263 #ifndef HAVE_SIGPROCMASK
264 int
sigprocmask(int how,const sigset_t * set,sigset_t * oset)265 sigprocmask(int how, const sigset_t *set, sigset_t *oset)
266 {
267 #ifdef USE_SIGSET
268 int i;
269 #endif
270 static sigset_t sm;
271 static int once = 0;
272
273 if (!once) {
274 /*
275 * initally we clear sm,
276 * there after, it represents the last
277 * thing we did.
278 */
279 once++;
280 #ifdef USE_SIGMASK
281 sm = sigblock(0);
282 #else
283 sm = 0;
284 #endif
285 }
286 if (oset)
287 *oset = sm;
288 if (set) {
289 switch (how) {
290 case SIG_BLOCK:
291 sm |= *set;
292 break;
293 case SIG_UNBLOCK:
294 sm &= ~(*set);
295 break;
296 case SIG_SETMASK:
297 sm = *set;
298 break;
299 }
300 #ifdef USE_SIGMASK
301 (void) sigsetmask(sm);
302 #else
303 #ifdef USE_SIGSET
304 for (i = 1; i < NSIG; i++) {
305 if (how == SIG_UNBLOCK) {
306 if (*set & sigmask(i))
307 sigrelse(i);
308 } else
309 if (sm & sigmask(i)) {
310 sighold(i);
311 }
312 }
313 #endif
314 #endif
315 }
316 return 0;
317 }
318 #endif
319
320 #ifndef HAVE_SIGSUSPEND
321 int
sigsuspend(sigset_t * mask)322 sigsuspend(sigset_t *mask)
323 {
324 #ifdef USE_SIGMASK
325 sigpause(*mask);
326 #else
327 int i;
328
329 #ifdef USE_SIGSET
330
331 for (i = 1; i < NSIG; i++) {
332 if (*mask & sigmask(i)) {
333 /* not the same sigpause() as above! */
334 sigpause(i);
335 break;
336 }
337 }
338 #else /* signal(2) only */
339 SIG_HDLR(*oldh) ();
340
341 /*
342 * make sure that signals in mask will not
343 * be ignored.
344 */
345 for (i = 1; i < NSIG; i++) {
346 if (*mask & sigmask(i)) {
347 if ((oldh = signal(i, SIG_DFL)) != SIG_ERR &&
348 oldh != SIG_IGN &&
349 oldh != SIG_DFL)
350 (void) signal(i, oldh); /* restore handler */
351 }
352 }
353 pause(); /* wait for a signal */
354 #endif
355 #endif
356 return 0;
357 }
358 #endif
359 #endif /* ! SA_NOCLDSTOP */
360
361 #if 0
362 #if !defined(SIG_HDLR)
363 #define SIG_HDLR void
364 #endif
365 #if !defined(SIG_ERR)
366 #define SIG_ERR (SIG_HDLR (*)())-1
367 #endif
368
369 #if !defined(USE_SIGNAL) && !defined(USE_SIGMASK) && !defined(NO_SIGNAL)
370 /*
371 * ensure we avoid signal mayhem
372 */
373
374 extern void (*Signal (int sig, void (*handler) (int)))(int);
375
376 SIG_HDLR(*signal(int sig, SIG_HDLR(*handler)(int))
377 {
378 return (Signal(sig, handler));
379 }
380 #endif
381 #endif
382
383 /* This lot (for GNU-Emacs) goes at the end of the file. */
384 /*
385 * Local Variables:
386 * version-control:t
387 * comment-column:40
388 * End:
389 */
390