Drop main() prototype. Syncs with NetBSD-8
[minix.git] / bin / ksh / sigact.c
blob80ff9a8e27d7b6641fc062064e6ea65995f09178
1 /* $NetBSD: sigact.c,v 1.4 2003/06/23 11:39:03 agc Exp $ */
3 /* NAME:
4 * sigact.c - fake sigaction(2)
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);
20 * RETSIGTYPE (*Signal(int sig, RETSIGTYPE (*disp)(int)))(int);
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.
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
40 * available.
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
47 * struct sigaction
48 * {
49 * RETSIGTYPE (*sa_handler)();
50 * sigset_t sa_mask;
51 * int sa_flags;
52 * };
53 *.fi
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.
70 * sigaddset() adds "sig" to the sigset_t pointed to by "mask".
72 * sigdelset() removes "sig" from the sigset_t pointed to
73 * by "mask".
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
95 * mask is restored.
98 * RETURN VALUE:
99 * 0==success, -1==failure
101 * BUGS:
102 * Since we fake most of this, don't expect fancy usage to
103 * work.
105 * AUTHOR:
106 * Simon J. Gerraty <sjg@zen.void.oz.au>
108 /* COPYRIGHT:
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
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.
121 * Please send copies of changes and bug-fixes to:
122 * sjg@zen.void.oz.au
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>
143 #ifndef lint
144 __RCSID("$NetBSD: sigact.c,v 1.4 2003/06/23 11:39:03 agc Exp $");
145 #endif
149 #include <signal.h>
151 #define IS_KSH
152 #include "sh.h"
155 #ifndef __P
156 # define __P(p) p
157 #endif
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 */
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 */
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)
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
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
201 #endif
203 #include "sigact.h"
206 * in case signal() has been mapped to our Signal().
208 #undef signal
212 sigaction(sig, act, oact)
213 int sig;
214 struct sigaction *act, *oact;
216 handler_t oldh;
218 if (act)
220 #ifdef USE_SIGSET
221 oldh = sigset(sig, act->sa_handler);
222 #else
223 # ifdef USE_SIGMASK
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 */
234 #endif
236 else
238 if (oact)
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)
247 #ifdef USE_SIGSET
248 (void) sigset(sig, oldh);
249 #else
250 (void) signal(sig, oldh);
251 #endif
255 if (oact)
257 oact->sa_handler = oldh;
259 return 0; /* hey we're faking it */
264 sigaddset(mask, sig)
265 sigset_t *mask;
266 int sig;
268 *mask |= sigmask(sig);
269 return 0;
273 #ifndef IS_KSH
275 sigdelset(mask, sig)
276 sigset_t *mask;
277 int sig;
279 *mask &= ~(sigmask(sig));
280 return 0;
282 #endif /* IS_KSH */
286 sigemptyset(mask)
287 sigset_t *mask;
289 *mask = 0;
290 return 0;
294 #ifndef IS_KSH
296 sigfillset(mask)
297 sigset_t *mask;
299 *mask = ~0;
300 return 0;
302 #endif /* IS_KSH */
305 #ifndef IS_KSH
307 sigismember(mask, sig)
308 sigset_t *mask;
309 int sig;
311 return ((*mask) & sigmask(sig));
313 #endif /* IS_KSH */
316 #ifndef IS_KSH
318 sigpending(set)
319 sigset_t *set;
321 return 0; /* faking it! */
323 #endif /* IS_KSH */
327 sigprocmask(how, set, oset)
328 int how;
329 sigset_t *set, *oset;
331 #ifdef USE_SIGSET
332 register int i;
333 #endif
334 static sigset_t sm;
335 static int once = 0;
337 if (!once)
340 * initally we clear sm,
341 * there after, it represents the last
342 * thing we did.
344 once++;
345 #ifdef USE_SIGMASK
346 sm = sigblock(0);
347 #else
348 sm = 0;
349 #endif
352 if (oset)
353 *oset = sm;
354 if (set)
356 switch (how)
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;
368 #ifdef USE_SIGMASK
369 (void) sigsetmask(sm);
370 #else
371 # ifdef USE_SIGSET
372 for (i = 1; i < NSIG; i++)
374 if (how == SIG_UNBLOCK)
376 if (*set & sigmask(i))
377 sigrelse(i);
379 else
380 if (sm & sigmask(i))
382 sighold(i);
385 # endif
386 #endif
388 return 0;
393 sigsuspend(mask)
394 sigset_t *mask;
396 #ifdef USE_SIGMASK
397 sigpause(*mask);
398 #else
399 register int i;
401 # ifdef USE_SIGSET
403 for (i = 1; i < NSIG; i++)
405 if (*mask & sigmask(i))
407 /* not the same sigpause() as above! */
408 sigpause(i);
409 break;
412 # else /* signal(2) only */
413 handler_t oldh;
416 * make sure that signals in mask will not
417 * be ignored.
419 for (i = 1; i < NSIG; i++)
421 if (*mask & sigmask(i))
423 if ((oldh = signal(i, SIG_DFL)) != SIG_ERR &&
424 oldh != SIG_IGN &&
425 oldh != SIG_DFL)
426 (void) signal(i, oldh); /* restore handler */
429 pause(); /* wait for a signal */
430 # endif
431 #endif
432 return 0;
435 #endif /* USE_FAKE_SIGACT (was ! SA_NOCLDSTOP) */
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
446 * an implementation of signal() using sigaction().
449 #ifndef IS_KSH
450 handler_t Signal(sig, handler)
451 int sig;
452 handler_t handler;
454 struct sigaction act, oact;
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);
463 #endif /* IS_KSH */
465 #ifndef IS_KSH
466 #if !defined(USE_SIGNAL) && !defined(USE_SIGMASK) && !defined(NO_SIGNAL)
468 * ensure we avoid signal mayhem
471 handler_t signal(sig, handler)
472 int sig;
473 handler_t handler;
475 return (Signal(sig, handler));
477 #endif
478 #endif /* IS_KSH */
480 /* This lot (for GNU-Emacs) goes at the end of the file. */
482 * Local Variables:
483 * version-control:t
484 * comment-column:40
485 * End: