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