1 /* $NetBSD: sigact.c,v 1.3 2002/05/25 23:29:17 wiz Exp $ */
4 * sigact.c - fake sigaction(2)
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);
20 * RETSIGTYPE (*Signal(int sig, RETSIGTYPE (*disp)(int)))(int);
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"
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().
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
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':
49 * RETSIGTYPE (*sa_handler)();
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
67 * Either "act" or "oact" may be NULL in which case the
68 * appropriate operation is skipped.
70 * sigaddset() adds "sig" to the sigset_t pointed to by "mask".
72 * sigdelset() removes "sig" from the sigset_t pointed to
75 * sigemptyset() makes the sigset_t pointed to by "mask" empty.
77 * sigfillset() makes the sigset_t pointed to by "mask"
78 * full ie. match all signals.
80 * sigismember() returns true if "sig" is found in "*mask".
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.
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.
93 * sigsuspend() sets the signal mask to "*mask" and waits
94 * for a signal to be delivered after which the previous
99 * 0==success, -1==failure
102 * Since we fake most of this, don't expect fancy usage to
106 * Simon J. Gerraty <sjg@zen.void.oz.au>
109 * @(#)Copyright (c) 1992 Simon J. Gerraty
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
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.
121 * Please send copies of changes and bug-fixes to:
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.
141 #include <sys/cdefs.h>
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.
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) */
170 /* Let autoconf decide which to use */
174 # ifdef BSD41_SIGNALS
179 #endif /* BSD42_SIGNALS */
182 * if we haven't been told,
183 * try and guess what we should implement with.
185 #if !defined(USE_SIGSET) && !defined(USE_SIGMASK) && !defined(USE_SIGNAL)
186 # if defined(sigmask) || defined(BSD) || defined(_BSD) && !defined(BSD41)
197 * if we still don't know, we're in trouble
199 #if !defined(USE_SIGSET) && !defined(USE_SIGMASK) && !defined(USE_SIGNAL)
200 error must know what to implement with
206 * in case signal() has been mapped to our Signal().
212 sigaction(sig
, act
, oact
)
214 struct sigaction
*act
, *oact
;
221 oldh
= sigset(sig
, act
->sa_handler
);
224 struct sigvec nsv
,osv
;
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 */
241 oldh
= sigset(sig
, SIG_IGN
);
243 oldh
= signal(sig
, SIG_IGN
);
245 if (oldh
!= SIG_IGN
&& oldh
!= SIG_ERR
)
248 (void) sigset(sig
, oldh
);
250 (void) signal(sig
, oldh
);
257 oact
->sa_handler
= oldh
;
259 return 0; /* hey we're faking it */
268 *mask
|= sigmask(sig
);
279 *mask
&= ~(sigmask(sig
));
307 sigismember(mask
, sig
)
311 return ((*mask
) & sigmask(sig
));
321 return 0; /* faking it! */
327 sigprocmask(how
, set
, oset
)
329 sigset_t
*set
, *oset
;
340 * initally we clear sm,
341 * there after, it represents the last
369 (void) sigsetmask(sm
);
372 for (i
= 1; i
< NSIG
; i
++)
374 if (how
== SIG_UNBLOCK
)
376 if (*set
& sigmask(i
))
403 for (i
= 1; i
< NSIG
; i
++)
405 if (*mask
& sigmask(i
))
407 /* not the same sigpause() as above! */
412 # else /* signal(2) only */
416 * make sure that signals in mask will not
419 for (i
= 1; i
< NSIG
; i
++)
421 if (*mask
& sigmask(i
))
423 if ((oldh
= signal(i
, SIG_DFL
)) != SIG_ERR
&&
426 (void) signal(i
, oldh
); /* restore handler */
429 pause(); /* wait for a signal */
435 #endif /* USE_FAKE_SIGACT (was ! SA_NOCLDSTOP) */
437 #if !defined(RETSIGTYPE)
438 # define RETSIGTYPE void
441 #if !defined(SIG_ERR)
442 # define SIG_ERR (RETSIGTYPE (*)())-1
446 * an implementation of signal() using sigaction().
450 handler_t
Signal(sig
, handler
)
454 struct sigaction act
, oact
;
456 act
.sa_handler
= handler
;
457 sigemptyset(&act
.sa_mask
);
459 if (sigaction(sig
, &act
, &oact
) < 0)
461 return (oact
.sa_handler
);
466 #if !defined(USE_SIGNAL) && !defined(USE_SIGMASK) && !defined(NO_SIGNAL)
468 * ensure we avoid signal mayhem
471 handler_t
signal(sig
, handler
)
475 return (Signal(sig
, handler
));
480 /* This lot (for GNU-Emacs) goes at the end of the file. */