xref: /minix3/bin/ksh/sigact.c (revision 2718b5688b1550d32bf379153192626eee37752d)
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