]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcsh/tc.sig.c
This commit was generated by cvs2svn to compensate for changes in r160157,
[FreeBSD/FreeBSD.git] / contrib / tcsh / tc.sig.c
1 /* $Header: /src/pub/tcsh/tc.sig.c,v 3.29 2005/01/18 20:24:51 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.29 2005/01/18 20:24:51 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 RETSIGTYPE
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 }
69
70 /* process all awaiting child signals
71  */
72 static RETSIGTYPE
73 sig_ch_rel()
74 {
75     while (stk_ptr > -1)
76         pchild(SIGCHLD);
77 #  ifdef JOBDEBUG
78     xprintf("signal(SIGCHLD, pchild);\n");
79 #  endif /* JOBDEBUG */
80     (void) signal(SIGCHLD, pchild);
81 }
82
83
84 /* libc.a contains these functions in SYSVREL >= 3. */
85 RETSIGTYPE
86 (*xsigset(a, b)) ()
87     int     a;
88     signalfun_t  b;
89 {
90     return (signal(a, b));
91 }
92
93 /* release signal
94  *      release all queued signals and
95  *      set the default signal handler
96  */
97 void
98 sigrelse(what)
99     int     what;
100 {
101     if (what == SIGCHLD)
102         sig_ch_rel();
103
104 #  ifdef COHERENT
105     (void) signal(what, what == SIGINT ? pintr : SIG_DFL);
106 #  endif /* COHERENT */
107 }
108
109 /* hold signal
110  * only works with child and interrupt
111  */
112 void
113 xsighold(what)
114     int     what;
115 {
116     if (what == SIGCHLD)
117         (void) signal(SIGCHLD, sig_ch_queue);
118
119 #  ifdef COHERENT
120     (void) signal(what, SIG_IGN);
121 #  endif /* COHERENT */
122 }
123
124 /* ignore signal
125  */
126 void
127 xsigignore(a)
128     int     a;
129 {
130     (void) signal(a, SIG_IGN);
131 }
132
133 /* atomically release one signal
134  */
135 void
136 xsigpause(what)
137     int     what;
138 {
139     /* From: Jim Mattson <mattson%cs@ucsd.edu> */
140     if (what == SIGCHLD)
141         pchild(SIGCHLD);
142 }
143
144
145 /* return either awaiting processes or do a wait now
146  */
147 pid_t
148 ourwait(w)
149     int    *w;
150 {
151     pid_t pid;
152
153 #  ifdef JOBDEBUG
154     xprintf(CGETS(25, 1, "our wait %d\n"), stk_ptr);
155     flush();
156 #  endif /* JOBDEBUG */
157
158     if (stk_ptr == -1) {
159         /* stack empty return signal from stack */
160         pid = (pid_t) wait(w);
161 #  ifdef JOBDEBUG
162         xprintf("signal(SIGCHLD, pchild);\n");
163 #  endif /* JOBDEBUG */
164         (void) signal(SIGCHLD, pchild);
165         return (pid);
166     }
167     else {
168         /* return signal from stack */
169         errno = stk[stk_ptr].s_errno;
170         *w = stk[stk_ptr].s_w;
171         stk_ptr--;
172         return (stk[stk_ptr + 1].s_pid);
173     }
174 } /* end ourwait */
175
176 #  ifdef COHERENT
177 #   undef signal
178 RETSIGTYPE
179 (*xsignal(a, b)) ()
180     int     a;
181     signalfun_t  b;
182 {
183     if (a == SIGCHLD)
184         return SIG_DFL;
185     else
186         return (signal(a, b));
187 }
188 #  endif /* COHERENT */
189
190 # endif /* UNRELSIGS */
191
192 # ifdef SXA
193 /*
194  * SX/A is SYSVREL3 but does not have sys5-sigpause().
195  * I've heard that sigpause() is not defined in SYSVREL3.
196  */
197 /* This is not need if you make tcsh by BSD option's cc. */
198 void
199 sigpause(what)
200 {
201     if (what == SIGCHLD) {
202         (void) bsd_sigpause(bsd_sigblock((sigmask_t) 0) & ~sigmask(SIGBSDCHLD));
203     }
204     else if (what == 0) {
205         pause();
206     }
207     else {
208         xprintf("sigpause(%d)\n", what);
209         pause();
210     }
211 }
212 # endif /* SXA */
213
214 #endif /* !BSDSIGS */
215
216 #ifdef NEEDsignal
217 /* turn into bsd signals */
218 RETSIGTYPE
219 (*xsignal(s, a)) ()
220     int     s;
221     signalfun_t a;
222 {
223     sigvec_t osv, sv;
224
225     (void) mysigvec(s, NULL, &osv);
226     sv = osv;
227     sv.sv_handler = a;
228 #ifdef SIG_STK
229     sv.sv_onstack = SIG_STK;
230 #endif /* SIG_STK */
231 #ifdef SV_BSDSIG
232     sv.sv_flags = SV_BSDSIG;
233 #endif /* SV_BSDSIG */
234
235     if (mysigvec(s, &sv, NULL) < 0)
236         return (BADSIG);
237     return (osv.sv_handler);
238 }
239
240 #endif /* NEEDsignal */
241
242 #ifdef POSIXSIGS
243 /*
244  * Support for signals.
245  */
246
247 extern int errno;
248
249 /* Set and test a bit.  Bits numbered 1 to 32 */
250
251 #define SETBIT(x, y)    x |= sigmask(y)
252 #define ISSET(x, y)     ((x & sigmask(y)) != 0)
253
254 #ifdef DEBUG
255 # define SHOW_SIGNALS   1       /* to assist in debugging signals */
256 #endif /* DEBUG */
257
258 #ifdef SHOW_SIGNALS
259 char   *show_sig_mask();
260 #endif /* SHOW_SIGNALS */
261
262 #ifndef __PARAGON__
263 /*
264  * sigsetmask(mask)
265  *
266  * Set a new signal mask.  Return old mask.
267  */
268 sigmask_t
269 sigsetmask(mask)
270     sigmask_t     mask;
271 {
272     sigset_t set, oset;
273     int     m;
274     int i;
275
276     (void) sigemptyset(&set);
277     (void) sigemptyset(&oset);
278
279     for (i = 1; i <= MAXSIG; i++)
280         if (ISSET(mask, i))
281             (void) sigaddset(&set, i);
282
283     if ((sigprocmask(SIG_SETMASK, &set, &oset)) == -1) {
284         xprintf("sigsetmask(0x%x) - sigprocmask failed, errno %d",
285                 mask, errno);
286     }
287
288     m = 0;
289     for (i = 1; i <= MAXSIG; i++)
290         if (sigismember(&oset, i) == 1)
291             SETBIT(m, i);
292
293     return (m);
294 }
295 #endif /* __PARAGON__ */
296
297 #ifndef __DGUX__
298 /*
299  * sigblock(mask)
300  *
301  * Add "mask" set of signals to the present signal mask.
302  * Return old mask.
303  */
304 sigmask_t
305 sigblock(mask)
306     sigmask_t     mask;
307 {
308     sigset_t set, oset;
309     int     m;
310     int i;
311
312     (void) sigemptyset(&set);
313     (void) sigemptyset(&oset);
314
315     /* Get present set of signals. */
316     if ((sigprocmask(SIG_SETMASK, NULL, &set)) == -1)
317         stderror(ERR_SYSTEM, "sigprocmask", strerror(errno));
318
319     /* Add in signals from mask. */
320     for (i = 1; i <= MAXSIG; i++)
321         if (ISSET(mask, i))
322             (void) sigaddset(&set, i);
323
324     if ((sigprocmask(SIG_SETMASK, &set, &oset)) == -1)
325         stderror(ERR_SYSTEM, "sigprocmask", strerror(errno));
326
327     /* Return old mask to user. */
328     m = 0;
329     for (i = 1; i <= MAXSIG; i++)
330         if (sigismember(&oset, i) == 1)
331             SETBIT(m, i);
332
333     return (m);
334 }
335 #endif /* __DGUX__ */
336
337
338 /*
339  * bsd_sigpause(mask)
340  *
341  * Set new signal mask and wait for signal;
342  * Old mask is restored on signal.
343  */
344 void
345 bsd_sigpause(mask)
346     sigmask_t     mask;
347 {
348     sigset_t set;
349     int i;
350
351     (void) sigemptyset(&set);
352
353     for (i = 1; i <= MAXSIG; i++)
354         if (ISSET(mask, i))
355             (void) sigaddset(&set, i);
356     (void) sigsuspend(&set);
357 }
358
359 /*
360  * bsd_signal(sig, func)
361  *
362  * Emulate bsd style signal()
363  */
364 RETSIGTYPE (*bsd_signal(sig, func)) ()
365         int sig;
366         signalfun_t func;
367 {
368         struct sigaction act, oact;
369         sigset_t set;
370         signalfun_t r_func;
371
372         if (sig < 0 || sig > MAXSIG) {
373                 xprintf(CGETS(25, 2,
374                         "error: bsd_signal(%d) signal out of range\n"), sig);
375                 return((signalfun_t) SIG_IGN);
376         }
377
378         (void) sigemptyset(&set);
379
380         act.sa_handler = (signalfun_t) func; /* user function */
381         act.sa_mask = set;                      /* signal mask */
382         act.sa_flags = 0;                       /* no special actions */
383
384         if (sigaction(sig, &act, &oact)) {
385                 xprintf(CGETS(25, 3,
386                         "error: bsd_signal(%d) - sigaction failed, errno %d\n"),
387                         sig, errno);
388                 return((signalfun_t) SIG_IGN);
389         }
390
391         r_func = (signalfun_t) oact.sa_handler;
392         return(r_func);
393 }
394 #endif /* POSIXSIG */
395
396
397 #ifdef SIGSYNCH
398 static long Synch_Cnt = 0;
399
400 RETSIGTYPE
401 synch_handler(sno)
402 int sno;
403 {
404     if (sno != SIGSYNCH)
405         abort();
406     Synch_Cnt++;
407 }
408 #endif /* SIGSYNCH */