Merge from vendor branch DHCP:
[dragonfly.git] / contrib / tcsh / tc.sig.c
1 /* $Header: /src/pub/tcsh/tc.sig.c,v 3.26 2002/03/08 17:36:47 christos Exp $ */
2 /*
3  * tc.sig.c: Signal routine emulations
4  */
5 /*-
6  * Copyright (c) 1980, 1991 The Regents of the University of California.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 #include "sh.h"
34
35 RCSID("$Id: tc.sig.c,v 3.26 2002/03/08 17:36:47 christos Exp $")
36
37 #include "tc.wait.h"
38
39 #ifndef BSDSIGS
40
41 /* this stack is used to queue signals
42  * we can handle up to MAX_CHLD outstanding children now;
43  */
44 #define MAX_CHLD 50
45
46 # ifdef UNRELSIGS
47 static struct mysigstack {
48     int     s_w;                /* wait report                   */
49     int     s_errno;            /* errno returned;               */
50     pid_t   s_pid;              /* pid returned                  */
51 }       stk[MAX_CHLD];
52 static int stk_ptr = -1;
53
54
55 /* queue child signals
56  */
57 static sigret_t
58 sig_ch_queue()
59 {
60 #  ifdef JOBDEBUG
61     xprintf("queue SIGCHLD\n");
62     flush();
63 #  endif /* JOBDEBUG */
64     stk_ptr++;
65     stk[stk_ptr].s_pid = (pid_t) wait(&stk[stk_ptr].s_w);
66     stk[stk_ptr].s_errno = errno;
67     (void) signal(SIGCHLD, sig_ch_queue);
68 #  ifndef SIGVOID
69     return(0);
70 #  endif /* SIGVOID */
71 }
72
73 /* process all awaiting child signals
74  */
75 static sigret_t
76 sig_ch_rel()
77 {
78     while (stk_ptr > -1)
79         pchild(SIGCHLD);
80 #  ifdef JOBDEBUG
81     xprintf("signal(SIGCHLD, pchild);\n");
82 #  endif /* JOBDEBUG */
83     (void) signal(SIGCHLD, pchild);
84 #  ifndef SIGVOID
85     return(0);
86 #  endif /* SIGVOID */
87 }
88
89
90 /* libc.a contains these functions in SYSVREL >= 3. */
91 sigret_t
92 (*xsigset(a, b)) ()
93     int     a;
94     signalfun_t  b;
95 {
96     return (signal(a, b));
97 }
98
99 /* release signal
100  *      release all queued signals and
101  *      set the default signal handler
102  */
103 void
104 sigrelse(what)
105     int     what;
106 {
107     if (what == SIGCHLD)
108         sig_ch_rel();
109
110 #  ifdef COHERENT
111     (void) signal(what, what == SIGINT ? pintr : SIG_DFL);
112 #  endif /* COHERENT */
113 }
114
115 /* hold signal
116  * only works with child and interrupt
117  */
118 void
119 xsighold(what)
120     int     what;
121 {
122     if (what == SIGCHLD)
123         (void) signal(SIGCHLD, sig_ch_queue);
124
125 #  ifdef COHERENT
126     (void) signal(what, SIG_IGN);
127 #  endif /* COHERENT */
128 }
129
130 /* ignore signal
131  */
132 void
133 xsigignore(a)
134     int     a;
135 {
136     (void) signal(a, SIG_IGN);
137 }
138
139 /* atomically release one signal
140  */
141 void
142 xsigpause(what)
143     int     what;
144 {
145     /* From: Jim Mattson <mattson%cs@ucsd.edu> */
146     if (what == SIGCHLD)
147         pchild(SIGCHLD);
148 }
149
150
151 /* return either awaiting processes or do a wait now
152  */
153 pid_t
154 ourwait(w)
155     int    *w;
156 {
157     pid_t pid;
158
159 #  ifdef JOBDEBUG
160     xprintf(CGETS(25, 1, "our wait %d\n"), stk_ptr);
161     flush();
162 #  endif /* JOBDEBUG */
163
164     if (stk_ptr == -1) {
165         /* stack empty return signal from stack */
166         pid = (pid_t) wait(w);
167 #  ifdef JOBDEBUG
168         xprintf("signal(SIGCHLD, pchild);\n");
169 #  endif /* JOBDEBUG */
170         (void) signal(SIGCHLD, pchild);
171         return (pid);
172     }
173     else {
174         /* return signal from stack */
175         errno = stk[stk_ptr].s_errno;
176         *w = stk[stk_ptr].s_w;
177         stk_ptr--;
178         return (stk[stk_ptr + 1].s_pid);
179     }
180 } /* end ourwait */
181
182 #  ifdef COHERENT
183 #   undef signal
184 sigret_t
185 (*xsignal(a, b)) ()
186     int     a;
187     signalfun_t  b;
188 {
189     if (a == SIGCHLD)
190         return SIG_DFL;
191     else
192         return (signal(a, b));
193 }
194 #  endif /* COHERENT */
195
196 # endif /* UNRELSIGS */
197
198 # ifdef SXA
199 /*
200  * SX/A is SYSVREL3 but does not have sys5-sigpause().
201  * I've heard that sigpause() is not defined in SYSVREL3.
202  */
203 /* This is not need if you make tcsh by BSD option's cc. */
204 void
205 sigpause(what)
206 {
207     if (what == SIGCHLD) {
208         (void) bsd_sigpause(bsd_sigblock((sigmask_t) 0) & ~sigmask(SIGBSDCHLD));
209     }
210     else if (what == 0) {
211         pause();
212     }
213     else {
214         xprintf("sigpause(%d)\n", what);
215         pause();
216     }
217 }
218 # endif /* SXA */
219
220 #endif /* !BSDSIGS */
221
222 #ifdef NEEDsignal
223 /* turn into bsd signals */
224 sigret_t
225 (*xsignal(s, a)) ()
226     int     s;
227     signalfun_t a;
228 {
229     sigvec_t osv, sv;
230
231     (void) mysigvec(s, NULL, &osv);
232     sv = osv;
233     sv.sv_handler = a;
234 #ifdef SIG_STK
235     sv.sv_onstack = SIG_STK;
236 #endif /* SIG_STK */
237 #ifdef SV_BSDSIG
238     sv.sv_flags = SV_BSDSIG;
239 #endif /* SV_BSDSIG */
240
241     if (mysigvec(s, &sv, NULL) < 0)
242         return (BADSIG);
243     return (osv.sv_handler);
244 }
245
246 #endif /* NEEDsignal */
247
248 #ifdef POSIXSIGS
249 /*
250  * Support for signals.
251  */
252
253 extern int errno;
254
255 /* Set and test a bit.  Bits numbered 1 to 32 */
256
257 #define SETBIT(x, y)    x |= sigmask(y)
258 #define ISSET(x, y)     ((x & sigmask(y)) != 0)
259
260 #ifdef DEBUG
261 # define SHOW_SIGNALS   1       /* to assist in debugging signals */
262 #endif /* DEBUG */
263
264 #ifdef SHOW_SIGNALS
265 char   *show_sig_mask();
266 #endif /* SHOW_SIGNALS */
267
268 #ifndef __PARAGON__
269 /*
270  * sigsetmask(mask)
271  *
272  * Set a new signal mask.  Return old mask.
273  */
274 sigmask_t
275 sigsetmask(mask)
276     sigmask_t     mask;
277 {
278     sigset_t set, oset;
279     int     m;
280     register int i;
281
282     (void) sigemptyset(&set);
283     (void) sigemptyset(&oset);
284
285     for (i = 1; i <= MAXSIG; i++)
286         if (ISSET(mask, i))
287             (void) sigaddset(&set, i);
288
289     if ((sigprocmask(SIG_SETMASK, &set, &oset)) == -1) {
290         xprintf("sigsetmask(0x%x) - sigprocmask failed, errno %d",
291                 mask, errno);
292     }
293
294     m = 0;
295     for (i = 1; i <= MAXSIG; i++)
296         if (sigismember(&oset, i))
297             SETBIT(m, i);
298
299     return (m);
300 }
301 #endif /* __PARAGON__ */
302
303 #ifndef __DGUX__
304 /*
305  * sigblock(mask)
306  *
307  * Add "mask" set of signals to the present signal mask.
308  * Return old mask.
309  */
310 sigmask_t
311 sigblock(mask)
312     sigmask_t     mask;
313 {
314     sigset_t set, oset;
315     int     m;
316     register int i;
317
318     (void) sigemptyset(&set);
319     (void) sigemptyset(&oset);
320
321     /* Get present set of signals. */
322     if ((sigprocmask(SIG_SETMASK, NULL, &set)) == -1)
323         stderror(ERR_SYSTEM, "sigprocmask", strerror(errno));
324
325     /* Add in signals from mask. */
326     for (i = 1; i <= MAXSIG; i++)
327         if (ISSET(mask, i))
328             (void) sigaddset(&set, i);
329
330     if ((sigprocmask(SIG_SETMASK, &set, &oset)) == -1)
331         stderror(ERR_SYSTEM, "sigprocmask", strerror(errno));
332
333     /* Return old mask to user. */
334     m = 0;
335     for (i = 1; i <= MAXSIG; i++)
336         if (sigismember(&oset, i))
337             SETBIT(m, i);
338
339     return (m);
340 }
341 #endif /* __DGUX__ */
342
343
344 /*
345  * bsd_sigpause(mask)
346  *
347  * Set new signal mask and wait for signal;
348  * Old mask is restored on signal.
349  */
350 void
351 bsd_sigpause(mask)
352     sigmask_t     mask;
353 {
354     sigset_t set;
355     register int i;
356
357     (void) sigemptyset(&set);
358
359     for (i = 1; i <= MAXSIG; i++)
360         if (ISSET(mask, i))
361             (void) sigaddset(&set, i);
362     (void) sigsuspend(&set);
363 }
364
365 /*
366  * bsd_signal(sig, func)
367  *
368  * Emulate bsd style signal()
369  */
370 sigret_t (*bsd_signal(sig, func)) ()
371         int sig;
372         signalfun_t func;
373 {
374         struct sigaction act, oact;
375         sigset_t set;
376         signalfun_t r_func;
377
378         if (sig < 0 || sig > MAXSIG) {
379                 xprintf(CGETS(25, 2,
380                         "error: bsd_signal(%d) signal out of range\n"), sig);
381                 return((signalfun_t) SIG_IGN);
382         }
383
384         (void) sigemptyset(&set);
385
386         act.sa_handler = (signalfun_t) func; /* user function */
387         act.sa_mask = set;                      /* signal mask */
388         act.sa_flags = 0;                       /* no special actions */
389
390         if (sigaction(sig, &act, &oact)) {
391                 xprintf(CGETS(25, 3,
392                         "error: bsd_signal(%d) - sigaction failed, errno %d\n"),
393                         sig, errno);
394                 return((signalfun_t) SIG_IGN);
395         }
396
397         r_func = (signalfun_t) oact.sa_handler;
398         return(r_func);
399 }
400 #endif /* POSIXSIG */
401
402
403 #ifdef SIGSYNCH
404 static long Synch_Cnt = 0;
405
406 sigret_t
407 synch_handler(sno)
408 int sno;
409 {
410     if (sno != SIGSYNCH)
411         abort();
412     Synch_Cnt++;
413 }
414 #endif /* SIGSYNCH */