tc.sig.c revision 100616
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
35RCSID("$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
47static 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];
52static int stk_ptr = -1;
53
54
55/* queue child signals
56 */
57static sigret_t
58sig_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 */
75static sigret_t
76sig_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. */
91sigret_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 */
103void
104sigrelse(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 */
118void
119xsighold(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 */
132void
133xsigignore(a)
134    int     a;
135{
136    (void) signal(a, SIG_IGN);
137}
138
139/* atomically release one signal
140 */
141void
142xsigpause(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 */
153pid_t
154ourwait(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
184sigret_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. */
204void
205sigpause(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 */
224sigret_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
253extern 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
265char   *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 */
274sigmask_t
275sigsetmask(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 */
310sigmask_t
311sigblock(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 */
350void
351bsd_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 */
370sigret_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
404static long Synch_Cnt = 0;
405
406sigret_t
407synch_handler(sno)
408int sno;
409{
410    if (sno != SIGSYNCH)
411	abort();
412    Synch_Cnt++;
413}
414#endif /* SIGSYNCH */
415