tc.sig.c revision 145479
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
35RCSID("$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
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 RETSIGTYPE
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}
69
70/* process all awaiting child signals
71 */
72static RETSIGTYPE
73sig_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. */
85RETSIGTYPE
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 */
97void
98sigrelse(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 */
112void
113xsighold(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 */
126void
127xsigignore(a)
128    int     a;
129{
130    (void) signal(a, SIG_IGN);
131}
132
133/* atomically release one signal
134 */
135void
136xsigpause(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 */
147pid_t
148ourwait(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
178RETSIGTYPE
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. */
198void
199sigpause(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 */
218RETSIGTYPE
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
247extern 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
259char   *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 */
268sigmask_t
269sigsetmask(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 */
304sigmask_t
305sigblock(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 */
344void
345bsd_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 */
364RETSIGTYPE (*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
398static long Synch_Cnt = 0;
399
400RETSIGTYPE
401synch_handler(sno)
402int sno;
403{
404    if (sno != SIGSYNCH)
405	abort();
406    Synch_Cnt++;
407}
408#endif /* SIGSYNCH */
409