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-2021, Simon J. Gerraty
108 *
109 * This is free software. It comes with NO WARRANTY.
110 * Permission to use, modify and distribute this source code
111 * is granted subject to the following conditions.
112 * 1/ that that the above copyright notice and this notice
113 * are preserved in all copies and that due credit be given
114 * to the author.
115 * 2/ that any changes to this code are clearly commented
116 * as such so that the author does get blamed for bugs
117 * other than his own.
118 *
119 * Please send copies of changes and bug-fixes to:
120 * sjg@crufty.net
121 *
122 */
123 #ifndef lint
124 static char *RCSid = "$Id: sigact.c,v 1.8 2021/10/14 19:39:17 sjg Exp $";
125 #endif
126
127 #undef _ANSI_SOURCE /* causes problems */
128
129 #include <signal.h>
130 #include <sys/cdefs.h>
131
132 #ifdef HAVE_CONFIG_H
133 # include "config.h"
134 # ifdef NO_SIGSET
135 # undef HAVE_SIGSET
136 # endif
137 # ifndef HAVE_SIGACTION
138 # ifdef HAVE_SIGSETMASK
139 # define USE_SIGMASK
140 # else
141 # ifdef HAVE_SIGSET
142 # define USE_SIGSET
143 # else
144 # define USE_SIGNAL
145 # endif
146 # endif
147 # endif
148 #endif
149
150 /*
151 * some systems have a faulty sigaction() implementation!
152 * Allow us to bypass it.
153 * Or they may have installed sigact.h as signal.h which is why
154 * we have SA_NOCLDSTOP defined.
155 */
156 #if !defined(SA_NOCLDSTOP) || defined(_SIGACT_H) || defined(USE_SIGNAL) || defined(USE_SIGSET) || defined(USE_SIGMASK)
157
158 /*
159 * if we haven't been told,
160 * try and guess what we should implement with.
161 */
162 #if !defined(USE_SIGSET) && !defined(USE_SIGMASK) && !defined(USE_SIGNAL)
163 # if defined(sigmask) || defined(BSD) || defined(_BSD) && !defined(BSD41)
164 # define USE_SIGMASK
165 # else
166 # ifndef NO_SIGSET
167 # define USE_SIGSET
168 # else
169 # define USE_SIGNAL
170 # endif
171 # endif
172 #endif
173 /*
174 * if we still don't know, we're in trouble
175 */
176 #if !defined(USE_SIGSET) && !defined(USE_SIGMASK) && !defined(USE_SIGNAL)
177 error must know what to implement with
178 #endif
179
180 #include "sigact.h"
181
182 /*
183 * in case signal() has been mapped to our Signal().
184 */
185 #undef signal
186
187
188 int
sigaction(int sig,const struct sigaction * act,struct sigaction * oact)189 sigaction(int sig,
190 const struct sigaction *act,
191 struct sigaction *oact)
192 {
193 SIG_HDLR(*oldh) ();
194
195 if (act) {
196 #ifdef USE_SIGSET
197 oldh = sigset(sig, act->sa_handler);
198 #else
199 oldh = signal(sig, act->sa_handler);
200 #endif
201 } else {
202 if (oact) {
203 #ifdef USE_SIGSET
204 oldh = sigset(sig, SIG_IGN);
205 #else
206 oldh = signal(sig, SIG_IGN);
207 #endif
208 if (oldh != SIG_IGN && oldh != SIG_ERR) {
209 #ifdef USE_SIGSET
210 (void) sigset(sig, oldh);
211 #else
212 (void) signal(sig, oldh);
213 #endif
214 }
215 }
216 }
217 if (oact) {
218 oact->sa_handler = oldh;
219 }
220 return 0; /* hey we're faking it */
221 }
222
223 #ifndef HAVE_SIGADDSET
224 int
sigaddset(sigset_t * mask,int sig)225 sigaddset(sigset_t *mask, int sig)
226 {
227 *mask |= sigmask(sig);
228 return 0;
229 }
230
231
232 int
sigdelset(sigset_t * mask,int sig)233 sigdelset(sigset_t *mask, int sig)
234 {
235 *mask &= ~(sigmask(sig));
236 return 0;
237 }
238
239
240 int
sigemptyset(sigset_t * mask)241 sigemptyset(sigset_t *mask)
242 {
243 *mask = 0;
244 return 0;
245 }
246
247
248 int
sigfillset(sigset_t * mask)249 sigfillset(sigset_t *mask)
250 {
251 *mask = ~0;
252 return 0;
253 }
254
255
256 int
sigismember(const sigset_t * mask,int sig)257 sigismember(const sigset_t *mask, int sig)
258 {
259 return ((*mask) & sigmask(sig));
260 }
261 #endif
262
263 #ifndef HAVE_SIGPENDING
264 int
sigpending(sigset_t * set)265 sigpending(sigset_t *set)
266 {
267 return 0; /* faking it! */
268 }
269 #endif
270
271 #ifndef HAVE_SIGPROCMASK
272 int
sigprocmask(int how,const sigset_t * set,sigset_t * oset)273 sigprocmask(int how, const sigset_t *set, sigset_t *oset)
274 {
275 #ifdef USE_SIGSET
276 int i;
277 #endif
278 static sigset_t sm;
279 static int once = 0;
280
281 if (!once) {
282 /*
283 * initally we clear sm,
284 * there after, it represents the last
285 * thing we did.
286 */
287 once++;
288 #ifdef USE_SIGMASK
289 sm = sigblock(0);
290 #else
291 sm = 0;
292 #endif
293 }
294 if (oset)
295 *oset = sm;
296 if (set) {
297 switch (how) {
298 case SIG_BLOCK:
299 sm |= *set;
300 break;
301 case SIG_UNBLOCK:
302 sm &= ~(*set);
303 break;
304 case SIG_SETMASK:
305 sm = *set;
306 break;
307 }
308 #ifdef USE_SIGMASK
309 (void) sigsetmask(sm);
310 #else
311 #ifdef USE_SIGSET
312 for (i = 1; i < NSIG; i++) {
313 if (how == SIG_UNBLOCK) {
314 if (*set & sigmask(i))
315 sigrelse(i);
316 } else
317 if (sm & sigmask(i)) {
318 sighold(i);
319 }
320 }
321 #endif
322 #endif
323 }
324 return 0;
325 }
326 #endif
327
328 #ifndef HAVE_SIGSUSPEND
329 int
sigsuspend(sigset_t * mask)330 sigsuspend(sigset_t *mask)
331 {
332 #ifdef USE_SIGMASK
333 sigpause(*mask);
334 #else
335 int i;
336
337 #ifdef USE_SIGSET
338
339 for (i = 1; i < NSIG; i++) {
340 if (*mask & sigmask(i)) {
341 /* not the same sigpause() as above! */
342 sigpause(i);
343 break;
344 }
345 }
346 #else /* signal(2) only */
347 SIG_HDLR(*oldh) ();
348
349 /*
350 * make sure that signals in mask will not
351 * be ignored.
352 */
353 for (i = 1; i < NSIG; i++) {
354 if (*mask & sigmask(i)) {
355 if ((oldh = signal(i, SIG_DFL)) != SIG_ERR &&
356 oldh != SIG_IGN &&
357 oldh != SIG_DFL)
358 (void) signal(i, oldh); /* restore handler */
359 }
360 }
361 pause(); /* wait for a signal */
362 #endif
363 #endif
364 return 0;
365 }
366 #endif
367 #endif /* ! SA_NOCLDSTOP */
368
369 #if 0
370 #if !defined(SIG_HDLR)
371 #define SIG_HDLR void
372 #endif
373 #if !defined(SIG_ERR)
374 #define SIG_ERR (SIG_HDLR (*)())-1
375 #endif
376
377 #if !defined(USE_SIGNAL) && !defined(USE_SIGMASK) && !defined(NO_SIGNAL)
378 /*
379 * ensure we avoid signal mayhem
380 */
381
382 extern void (*Signal (int sig, void (*handler) (int)))(int);
383
384 SIG_HDLR(*signal(int sig, SIG_HDLR(*handler)(int))
385 {
386 return (Signal(sig, handler));
387 }
388 #endif
389 #endif
390
391 /* This lot (for GNU-Emacs) goes at the end of the file. */
392 /*
393 * Local Variables:
394 * version-control:t
395 * comment-column:40
396 * End:
397 */
398