1 /* $NetBSD: sigact.c,v 1.4 2003/06/23 11:39:03 agc Exp $ */
2
3 /* NAME:
4 * sigact.c - fake sigaction(2)
5 *
6 * SYNOPSIS:
7 * #include "sigact.h"
8 *
9 * int sigaction(int sig, struct sigaction *act,
10 * struct sigaction *oact);
11 * int sigaddset(sigset_t *mask, int sig);
12 * int sigdelset(sigset_t *mask, int sig);
13 * int sigemptyset(sigset_t *mask);
14 * int sigfillset(sigset_t *mask);
15 * int sigismember(sigset_t *mask, int sig);
16 * int sigpending(sigset_t *set);
17 * int sigprocmask(int how, sigset_t *set, sigset_t *oset);
18 * int sigsuspend(sigset_t *mask);
19 *
20 * RETSIGTYPE (*Signal(int sig, RETSIGTYPE (*disp)(int)))(int);
21 *
22 * DESCRIPTION:
23 * This is a fake sigaction implementation. It uses
24 * sigsetmask(2) et al or sigset(2) and friends if
25 * available, otherwise it just uses signal(2). If it
26 * thinks sigaction(2) really exists it compiles to "almost"
27 * nothing.
28 *
29 * In any case it provides a Signal() function that is
30 * implemented in terms of sigaction().
31 * If not using signal(2) as part of the underlying
32 * implementation (USE_SIGNAL or USE_SIGMASK), and
33 * NO_SIGNAL is not defined, it also provides a signal()
34 * function that calls Signal().
35 *
36 * The need for all this mucking about is the problems
37 * caused by mixing various signal handling mechanisms in
38 * the one process. This module allows for a consistent
39 * POSIX compliant interface to whatever is actually
40 * available.
41 *
42 * sigaction() allows the caller to examine and/or set the
43 * action to be associated with a given signal. "act" and
44 * "oact" are pointers to 'sigaction structs':
45 *.nf
46 *
47 * struct sigaction
48 * {
49 * RETSIGTYPE (*sa_handler)();
50 * sigset_t sa_mask;
51 * int sa_flags;
52 * };
53 *.fi
54 *
55 * RETSIGTYPE is normally 'void' in the POSIX implementation
56 * and for most current systems. On some older UNIX
57 * systems, signal handlers do not return 'void', so
58 * this implementation keeps 'sa_handler' inline with the
59 * hosts normal signal handling conventions.
60 * 'sa_mask' controls which signals will be blocked while
61 * the selected signal handler is active. It is not used
62 * in this implementation.
63 * 'sa_flags' controls various semantics such as whether
64 * system calls should be automagically restarted
65 * (SA_RESTART) etc. It is not used in this
66 * implementation.
67 * Either "act" or "oact" may be NULL in which case the
68 * appropriate operation is skipped.
69 *
70 * sigaddset() adds "sig" to the sigset_t pointed to by "mask".
71 *
72 * sigdelset() removes "sig" from the sigset_t pointed to
73 * by "mask".
74 *
75 * sigemptyset() makes the sigset_t pointed to by "mask" empty.
76 *
77 * sigfillset() makes the sigset_t pointed to by "mask"
78 * full ie. match all signals.
79 *
80 * sigismember() returns true if "sig" is found in "*mask".
81 *
82 * sigpending() is supposed to return "set" loaded with the
83 * set of signals that are blocked and pending for the
84 * calling process. It does nothing in this impementation.
85 *
86 * sigprocmask() is used to examine and/or change the
87 * signal mask for the calling process. Either "set" or
88 * "oset" may be NULL in which case the appropriate
89 * operation is skipped. "how" may be one of SIG_BLOCK,
90 * SIG_UNBLOCK or SIG_SETMASK. If this package is built
91 * with USE_SIGNAL, then this routine achieves nothing.
92 *
93 * sigsuspend() sets the signal mask to "*mask" and waits
94 * for a signal to be delivered after which the previous
95 * mask is restored.
96 *
97 *
98 * RETURN VALUE:
99 * 0==success, -1==failure
100 *
101 * BUGS:
102 * Since we fake most of this, don't expect fancy usage to
103 * work.
104 *
105 * AUTHOR:
106 * Simon J. Gerraty <sjg@zen.void.oz.au>
107 */
108 /* COPYRIGHT:
109 * @(#)Copyright (c) 1992 Simon J. Gerraty
110 *
111 * This is free software. It comes with NO WARRANTY.
112 * Permission to use, modify and distribute this source code
113 * is granted subject to the following conditions.
114 * 1/ that that the above copyright notice and this notice
115 * are preserved in all copies and that due credit be given
116 * to the author.
117 * 2/ that any changes to this code are clearly commented
118 * as such so that the author does get blamed for bugs
119 * other than his own.
120 *
121 * Please send copies of changes and bug-fixes to:
122 * sjg@zen.void.oz.au
123 *
124 */
125 /* Changes to sigact.c for pdksh, Michael Rendell <michael@cs.mun.ca>:
126 * - sigsuspend(): pass *mask to bsd4.2 sigpause instead of mask.
127 * - changed SIG_HDLR to RETSIGTYPE for use with GNU autoconf
128 * - added and used RETSIGVAL
129 * - include sh.h instead of signal.h (to get *_SIGNALS macros)
130 * - changed if !SA_NOCLDSTOP ... to USE_FAKE_SIGACT to avoid confusion
131 * - set the USE_* defines using the *_SIGNALS defines from autoconf
132 * - sigaction(): if using BSD signals, use sigvec() (used to use
133 * signal()) and set the SV_INTERRUPT flag (POSIX says syscalls
134 * are interrupted and pdksh needs this behaviour).
135 * - define IS_KSH before including anything; ifdef out routines
136 * not used in ksh if IS_KSH is defined (same in sigact.h).
137 * - use ARGS() instead of __P()
138 * - sigaction(),sigsuspend(),Signal(),signal(): use handler_t typedef
139 * instead of explicit type.
140 */
141 #include <sys/cdefs.h>
142
143 #ifndef lint
144 __RCSID("$NetBSD: sigact.c,v 1.4 2003/06/23 11:39:03 agc Exp $");
145 #endif
146
147
148 /*
149 #include <signal.h>
150 */
151 #define IS_KSH
152 #include "sh.h"
153
154 /*
155 #ifndef __P
156 # define __P(p) p
157 #endif
158 */
159
160
161 /*
162 * some systems have a faulty sigaction() implementation!
163 * Allow us to bypass it.
164 * Or they may have installed sigact.h as signal.h which is why
165 * we have SA_NOCLDSTOP defined.
166 */
167 #ifdef USE_FAKE_SIGACT /* let autoconf decide.. */
168 /* #if !defined(SA_NOCLDSTOP) || defined(_SIGACT_H) || defined(USE_SIGNAL) || defined(USE_SIGSET) || defined(USE_SIGMASK) */
169
170 /* Let autoconf decide which to use */
171 #ifdef BSD42_SIGNALS
172 # define USE_SIGMASK
173 #else
174 # ifdef BSD41_SIGNALS
175 # define USE_SIGSET
176 # else
177 # define USE_SIGNAL
178 # endif
179 #endif /* BSD42_SIGNALS */
180
181 /*
182 * if we haven't been told,
183 * try and guess what we should implement with.
184 */
185 #if !defined(USE_SIGSET) && !defined(USE_SIGMASK) && !defined(USE_SIGNAL)
186 # if defined(sigmask) || defined(BSD) || defined(_BSD) && !defined(BSD41)
187 # define USE_SIGMASK
188 # else
189 # ifndef NO_SIGSET
190 # define USE_SIGSET
191 # else
192 # define USE_SIGNAL
193 # endif
194 # endif
195 #endif
196 /*
197 * if we still don't know, we're in trouble
198 */
199 #if !defined(USE_SIGSET) && !defined(USE_SIGMASK) && !defined(USE_SIGNAL)
200 error must know what to implement with
201 #endif
202
203 #include "sigact.h"
204
205 /*
206 * in case signal() has been mapped to our Signal().
207 */
208 #undef signal
209
210
211 int
sigaction(sig,act,oact)212 sigaction(sig, act, oact)
213 int sig;
214 struct sigaction *act, *oact;
215 {
216 handler_t oldh;
217
218 if (act)
219 {
220 #ifdef USE_SIGSET
221 oldh = sigset(sig, act->sa_handler);
222 #else
223 # ifdef USE_SIGMASK
224 struct sigvec nsv,osv;
225
226 nsv.sv_handler = act->sa_handler;
227 nsv.sv_mask = 0; /* punt */
228 nsv.sv_flags = SV_INTERRUPT; /* punt */
229 sigvec(sig, &nsv, &osv);
230 oldh = osv.sv_handler;
231 # else /* USE_SIGMASK */
232 oldh = signal(sig, act->sa_handler);
233 # endif /* USE_SIGMASK */
234 #endif
235 }
236 else
237 {
238 if (oact)
239 {
240 #ifdef USE_SIGSET
241 oldh = sigset(sig, SIG_IGN);
242 #else
243 oldh = signal(sig, SIG_IGN);
244 #endif
245 if (oldh != SIG_IGN && oldh != SIG_ERR)
246 {
247 #ifdef USE_SIGSET
248 (void) sigset(sig, oldh);
249 #else
250 (void) signal(sig, oldh);
251 #endif
252 }
253 }
254 }
255 if (oact)
256 {
257 oact->sa_handler = oldh;
258 }
259 return 0; /* hey we're faking it */
260 }
261
262
263 int
sigaddset(mask,sig)264 sigaddset(mask, sig)
265 sigset_t *mask;
266 int sig;
267 {
268 *mask |= sigmask(sig);
269 return 0;
270 }
271
272
273 #ifndef IS_KSH
274 int
sigdelset(mask,sig)275 sigdelset(mask, sig)
276 sigset_t *mask;
277 int sig;
278 {
279 *mask &= ~(sigmask(sig));
280 return 0;
281 }
282 #endif /* IS_KSH */
283
284
285 int
sigemptyset(mask)286 sigemptyset(mask)
287 sigset_t *mask;
288 {
289 *mask = 0;
290 return 0;
291 }
292
293
294 #ifndef IS_KSH
295 int
sigfillset(mask)296 sigfillset(mask)
297 sigset_t *mask;
298 {
299 *mask = ~0;
300 return 0;
301 }
302 #endif /* IS_KSH */
303
304
305 #ifndef IS_KSH
306 int
sigismember(mask,sig)307 sigismember(mask, sig)
308 sigset_t *mask;
309 int sig;
310 {
311 return ((*mask) & sigmask(sig));
312 }
313 #endif /* IS_KSH */
314
315
316 #ifndef IS_KSH
317 int
sigpending(set)318 sigpending(set)
319 sigset_t *set;
320 {
321 return 0; /* faking it! */
322 }
323 #endif /* IS_KSH */
324
325
326 int
sigprocmask(how,set,oset)327 sigprocmask(how, set, oset)
328 int how;
329 sigset_t *set, *oset;
330 {
331 #ifdef USE_SIGSET
332 register int i;
333 #endif
334 static sigset_t sm;
335 static int once = 0;
336
337 if (!once)
338 {
339 /*
340 * initally we clear sm,
341 * there after, it represents the last
342 * thing we did.
343 */
344 once++;
345 #ifdef USE_SIGMASK
346 sm = sigblock(0);
347 #else
348 sm = 0;
349 #endif
350 }
351
352 if (oset)
353 *oset = sm;
354 if (set)
355 {
356 switch (how)
357 {
358 case SIG_BLOCK:
359 sm |= *set;
360 break;
361 case SIG_UNBLOCK:
362 sm &= ~(*set);
363 break;
364 case SIG_SETMASK:
365 sm = *set;
366 break;
367 }
368 #ifdef USE_SIGMASK
369 (void) sigsetmask(sm);
370 #else
371 # ifdef USE_SIGSET
372 for (i = 1; i < NSIG; i++)
373 {
374 if (how == SIG_UNBLOCK)
375 {
376 if (*set & sigmask(i))
377 sigrelse(i);
378 }
379 else
380 if (sm & sigmask(i))
381 {
382 sighold(i);
383 }
384 }
385 # endif
386 #endif
387 }
388 return 0;
389 }
390
391
392 int
sigsuspend(mask)393 sigsuspend(mask)
394 sigset_t *mask;
395 {
396 #ifdef USE_SIGMASK
397 sigpause(*mask);
398 #else
399 register int i;
400
401 # ifdef USE_SIGSET
402
403 for (i = 1; i < NSIG; i++)
404 {
405 if (*mask & sigmask(i))
406 {
407 /* not the same sigpause() as above! */
408 sigpause(i);
409 break;
410 }
411 }
412 # else /* signal(2) only */
413 handler_t oldh;
414
415 /*
416 * make sure that signals in mask will not
417 * be ignored.
418 */
419 for (i = 1; i < NSIG; i++)
420 {
421 if (*mask & sigmask(i))
422 {
423 if ((oldh = signal(i, SIG_DFL)) != SIG_ERR &&
424 oldh != SIG_IGN &&
425 oldh != SIG_DFL)
426 (void) signal(i, oldh); /* restore handler */
427 }
428 }
429 pause(); /* wait for a signal */
430 # endif
431 #endif
432 return 0;
433 }
434
435 #endif /* USE_FAKE_SIGACT (was ! SA_NOCLDSTOP) */
436
437 #if !defined(RETSIGTYPE)
438 # define RETSIGTYPE void
439 # define RETSIGVAL
440 #endif
441 #if !defined(SIG_ERR)
442 # define SIG_ERR (RETSIGTYPE (*)())-1
443 #endif
444
445 /*
446 * an implementation of signal() using sigaction().
447 */
448
449 #ifndef IS_KSH
Signal(sig,handler)450 handler_t Signal(sig, handler)
451 int sig;
452 handler_t handler;
453 {
454 struct sigaction act, oact;
455
456 act.sa_handler = handler;
457 sigemptyset(&act.sa_mask);
458 act.sa_flags = 0;
459 if (sigaction(sig, &act, &oact) < 0)
460 return (SIG_ERR);
461 return (oact.sa_handler);
462 }
463 #endif /* IS_KSH */
464
465 #ifndef IS_KSH
466 #if !defined(USE_SIGNAL) && !defined(USE_SIGMASK) && !defined(NO_SIGNAL)
467 /*
468 * ensure we avoid signal mayhem
469 */
470
signal(sig,handler)471 handler_t signal(sig, handler)
472 int sig;
473 handler_t handler;
474 {
475 return (Signal(sig, handler));
476 }
477 #endif
478 #endif /* IS_KSH */
479
480 /* This lot (for GNU-Emacs) goes at the end of the file. */
481 /*
482 * Local Variables:
483 * version-control:t
484 * comment-column:40
485 * End:
486 */
487