tc.sig.c revision 59243
159243Sobrien/* $Header: /src/pub/tcsh/tc.sig.c,v 3.24 1998/04/08 17:57:36 christos Exp $ */
259243Sobrien/*
359243Sobrien * tc.sig.c: Signal routine emulations
459243Sobrien */
559243Sobrien/*-
659243Sobrien * Copyright (c) 1980, 1991 The Regents of the University of California.
759243Sobrien * All rights reserved.
859243Sobrien *
959243Sobrien * Redistribution and use in source and binary forms, with or without
1059243Sobrien * modification, are permitted provided that the following conditions
1159243Sobrien * are met:
1259243Sobrien * 1. Redistributions of source code must retain the above copyright
1359243Sobrien *    notice, this list of conditions and the following disclaimer.
1459243Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1559243Sobrien *    notice, this list of conditions and the following disclaimer in the
1659243Sobrien *    documentation and/or other materials provided with the distribution.
1759243Sobrien * 3. All advertising materials mentioning features or use of this software
1859243Sobrien *    must display the following acknowledgement:
1959243Sobrien *	This product includes software developed by the University of
2059243Sobrien *	California, Berkeley and its contributors.
2159243Sobrien * 4. Neither the name of the University nor the names of its contributors
2259243Sobrien *    may be used to endorse or promote products derived from this software
2359243Sobrien *    without specific prior written permission.
2459243Sobrien *
2559243Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2659243Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2759243Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2859243Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2959243Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3059243Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3159243Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3259243Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3359243Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3459243Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3559243Sobrien * SUCH DAMAGE.
3659243Sobrien */
3759243Sobrien#include "sh.h"
3859243Sobrien
3959243SobrienRCSID("$Id: tc.sig.c,v 3.24 1998/04/08 17:57:36 christos Exp $")
4059243Sobrien
4159243Sobrien#include "tc.wait.h"
4259243Sobrien
4359243Sobrien#ifndef BSDSIGS
4459243Sobrien
4559243Sobrien/* this stack is used to queue signals
4659243Sobrien * we can handle up to MAX_CHLD outstanding children now;
4759243Sobrien */
4859243Sobrien#define MAX_CHLD 50
4959243Sobrien
5059243Sobrien# ifdef UNRELSIGS
5159243Sobrienstatic struct mysigstack {
5259243Sobrien    int     s_w;		/* wait report			 */
5359243Sobrien    int     s_errno;		/* errno returned;		 */
5459243Sobrien    pid_t   s_pid;		/* pid returned			 */
5559243Sobrien}       stk[MAX_CHLD];
5659243Sobrienstatic int stk_ptr = -1;
5759243Sobrien
5859243Sobrien
5959243Sobrien/* queue child signals
6059243Sobrien */
6159243Sobrienstatic sigret_t
6259243Sobriensig_ch_queue()
6359243Sobrien{
6459243Sobrien#  ifdef JOBDEBUG
6559243Sobrien    xprintf("queue SIGCHLD\n");
6659243Sobrien    flush();
6759243Sobrien#  endif /* JOBDEBUG */
6859243Sobrien    stk_ptr++;
6959243Sobrien    stk[stk_ptr].s_pid = (pid_t) wait(&stk[stk_ptr].s_w);
7059243Sobrien    stk[stk_ptr].s_errno = errno;
7159243Sobrien    (void) signal(SIGCHLD, sig_ch_queue);
7259243Sobrien#  ifndef SIGVOID
7359243Sobrien    return(0);
7459243Sobrien#  endif /* SIGVOID */
7559243Sobrien}
7659243Sobrien
7759243Sobrien/* process all awaiting child signals
7859243Sobrien */
7959243Sobrienstatic sigret_t
8059243Sobriensig_ch_rel()
8159243Sobrien{
8259243Sobrien    while (stk_ptr > -1)
8359243Sobrien	pchild(SIGCHLD);
8459243Sobrien#  ifdef JOBDEBUG
8559243Sobrien    xprintf("signal(SIGCHLD, pchild);\n");
8659243Sobrien#  endif /* JOBDEBUG */
8759243Sobrien    (void) signal(SIGCHLD, pchild);
8859243Sobrien#  ifndef SIGVOID
8959243Sobrien    return(0);
9059243Sobrien#  endif /* SIGVOID */
9159243Sobrien}
9259243Sobrien
9359243Sobrien
9459243Sobrien/* libc.a contains these functions in SYSVREL >= 3. */
9559243Sobriensigret_t
9659243Sobrien(*xsigset(a, b)) ()
9759243Sobrien    int     a;
9859243Sobrien    signalfun_t  b;
9959243Sobrien{
10059243Sobrien    return (signal(a, b));
10159243Sobrien}
10259243Sobrien
10359243Sobrien/* release signal
10459243Sobrien *	release all queued signals and
10559243Sobrien *	set the default signal handler
10659243Sobrien */
10759243Sobrienvoid
10859243Sobriensigrelse(what)
10959243Sobrien    int     what;
11059243Sobrien{
11159243Sobrien    if (what == SIGCHLD)
11259243Sobrien	sig_ch_rel();
11359243Sobrien
11459243Sobrien#  ifdef COHERENT
11559243Sobrien    (void) signal(what, what == SIGINT ? pintr : SIG_DFL);
11659243Sobrien#  endif /* COHERENT */
11759243Sobrien}
11859243Sobrien
11959243Sobrien/* hold signal
12059243Sobrien * only works with child and interrupt
12159243Sobrien */
12259243Sobrienvoid
12359243Sobrienxsighold(what)
12459243Sobrien    int     what;
12559243Sobrien{
12659243Sobrien    if (what == SIGCHLD)
12759243Sobrien	(void) signal(SIGCHLD, sig_ch_queue);
12859243Sobrien
12959243Sobrien#  ifdef COHERENT
13059243Sobrien    (void) signal(what, SIG_IGN);
13159243Sobrien#  endif /* COHERENT */
13259243Sobrien}
13359243Sobrien
13459243Sobrien/* ignore signal
13559243Sobrien */
13659243Sobrienvoid
13759243Sobrienxsigignore(a)
13859243Sobrien    int     a;
13959243Sobrien{
14059243Sobrien    (void) signal(a, SIG_IGN);
14159243Sobrien}
14259243Sobrien
14359243Sobrien/* atomically release one signal
14459243Sobrien */
14559243Sobrienvoid
14659243Sobrienxsigpause(what)
14759243Sobrien    int     what;
14859243Sobrien{
14959243Sobrien    /* From: Jim Mattson <mattson%cs@ucsd.edu> */
15059243Sobrien    if (what == SIGCHLD)
15159243Sobrien	pchild(SIGCHLD);
15259243Sobrien}
15359243Sobrien
15459243Sobrien
15559243Sobrien/* return either awaiting processes or do a wait now
15659243Sobrien */
15759243Sobrienpid_t
15859243Sobrienourwait(w)
15959243Sobrien    int    *w;
16059243Sobrien{
16159243Sobrien    pid_t pid;
16259243Sobrien
16359243Sobrien#  ifdef JOBDEBUG
16459243Sobrien    xprintf(CGETS(25, 1, "our wait %d\n", stk_ptr));
16559243Sobrien    flush();
16659243Sobrien#  endif /* JOBDEBUG */
16759243Sobrien
16859243Sobrien    if (stk_ptr == -1) {
16959243Sobrien	/* stack empty return signal from stack */
17059243Sobrien	pid = (pid_t) wait(w);
17159243Sobrien#  ifdef JOBDEBUG
17259243Sobrien	xprintf("signal(SIGCHLD, pchild);\n");
17359243Sobrien#  endif /* JOBDEBUG */
17459243Sobrien	(void) signal(SIGCHLD, pchild);
17559243Sobrien	return (pid);
17659243Sobrien    }
17759243Sobrien    else {
17859243Sobrien	/* return signal from stack */
17959243Sobrien	errno = stk[stk_ptr].s_errno;
18059243Sobrien	*w = stk[stk_ptr].s_w;
18159243Sobrien	stk_ptr--;
18259243Sobrien	return (stk[stk_ptr + 1].s_pid);
18359243Sobrien    }
18459243Sobrien} /* end ourwait */
18559243Sobrien
18659243Sobrien#  ifdef COHERENT
18759243Sobrien#   undef signal
18859243Sobriensigret_t
18959243Sobrien(*xsignal(a, b)) ()
19059243Sobrien    int     a;
19159243Sobrien    signalfun_t  b;
19259243Sobrien{
19359243Sobrien    if (a == SIGCHLD)
19459243Sobrien	return SIG_DFL;
19559243Sobrien    else
19659243Sobrien	return (signal(a, b));
19759243Sobrien}
19859243Sobrien#  endif /* COHERENT */
19959243Sobrien
20059243Sobrien# endif /* UNRELSIGS */
20159243Sobrien
20259243Sobrien# ifdef SXA
20359243Sobrien/*
20459243Sobrien * SX/A is SYSVREL3 but does not have sys5-sigpause().
20559243Sobrien * I've heard that sigpause() is not defined in SYSVREL3.
20659243Sobrien */
20759243Sobrien/* This is not need if you make tcsh by BSD option's cc. */
20859243Sobrienvoid
20959243Sobriensigpause(what)
21059243Sobrien{
21159243Sobrien    if (what == SIGCHLD) {
21259243Sobrien	(void) bsd_sigpause(bsd_sigblock((sigmask_t) 0) & ~sigmask(SIGBSDCHLD));
21359243Sobrien    }
21459243Sobrien    else if (what == 0) {
21559243Sobrien	pause();
21659243Sobrien    }
21759243Sobrien    else {
21859243Sobrien	xprintf("sigpause(%d)\n", what);
21959243Sobrien	pause();
22059243Sobrien    }
22159243Sobrien}
22259243Sobrien# endif /* SXA */
22359243Sobrien
22459243Sobrien#endif /* !BSDSIGS */
22559243Sobrien
22659243Sobrien#ifdef NEEDsignal
22759243Sobrien/* turn into bsd signals */
22859243Sobriensigret_t
22959243Sobrien(*xsignal(s, a)) ()
23059243Sobrien    int     s;
23159243Sobrien    signalfun_t a;
23259243Sobrien{
23359243Sobrien    sigvec_t osv, sv;
23459243Sobrien
23559243Sobrien    (void) mysigvec(s, NULL, &osv);
23659243Sobrien    sv = osv;
23759243Sobrien    sv.sv_handler = a;
23859243Sobrien#ifdef SIG_STK
23959243Sobrien    sv.sv_onstack = SIG_STK;
24059243Sobrien#endif /* SIG_STK */
24159243Sobrien#ifdef SV_BSDSIG
24259243Sobrien    sv.sv_flags = SV_BSDSIG;
24359243Sobrien#endif /* SV_BSDSIG */
24459243Sobrien
24559243Sobrien    if (mysigvec(s, &sv, NULL) < 0)
24659243Sobrien	return (BADSIG);
24759243Sobrien    return (osv.sv_handler);
24859243Sobrien}
24959243Sobrien
25059243Sobrien#endif /* NEEDsignal */
25159243Sobrien
25259243Sobrien#ifdef POSIXSIGS
25359243Sobrien/*
25459243Sobrien * Support for signals.
25559243Sobrien */
25659243Sobrien
25759243Sobrienextern int errno;
25859243Sobrien
25959243Sobrien/* Set and test a bit.  Bits numbered 1 to 32 */
26059243Sobrien
26159243Sobrien#define SETBIT(x, y)	x |= sigmask(y)
26259243Sobrien#define ISSET(x, y)	((x & sigmask(y)) != 0)
26359243Sobrien
26459243Sobrien#ifdef DEBUG
26559243Sobrien# define SHOW_SIGNALS	1	/* to assist in debugging signals */
26659243Sobrien#endif /* DEBUG */
26759243Sobrien
26859243Sobrien#ifdef SHOW_SIGNALS
26959243Sobrienchar   *show_sig_mask();
27059243Sobrien#endif /* SHOW_SIGNALS */
27159243Sobrien
27259243Sobrien#ifndef __PARAGON__
27359243Sobrien/*
27459243Sobrien * sigsetmask(mask)
27559243Sobrien *
27659243Sobrien * Set a new signal mask.  Return old mask.
27759243Sobrien */
27859243Sobriensigmask_t
27959243Sobriensigsetmask(mask)
28059243Sobrien    sigmask_t     mask;
28159243Sobrien{
28259243Sobrien    sigset_t set, oset;
28359243Sobrien    int     m;
28459243Sobrien    register int i;
28559243Sobrien
28659243Sobrien    (void) sigemptyset(&set);
28759243Sobrien    (void) sigemptyset(&oset);
28859243Sobrien
28959243Sobrien    for (i = 1; i <= MAXSIG; i++)
29059243Sobrien	if (ISSET(mask, i))
29159243Sobrien	    (void) sigaddset(&set, i);
29259243Sobrien
29359243Sobrien    if ((sigprocmask(SIG_SETMASK, &set, &oset)) == -1) {
29459243Sobrien	xprintf("sigsetmask(0x%x) - sigprocmask failed, errno %d",
29559243Sobrien		mask, errno);
29659243Sobrien    }
29759243Sobrien
29859243Sobrien    m = 0;
29959243Sobrien    for (i = 1; i <= MAXSIG; i++)
30059243Sobrien	if (sigismember(&oset, i))
30159243Sobrien	    SETBIT(m, i);
30259243Sobrien
30359243Sobrien    return (m);
30459243Sobrien}
30559243Sobrien#endif /* __PARAGON__ */
30659243Sobrien
30759243Sobrien#ifndef __DGUX__
30859243Sobrien/*
30959243Sobrien * sigblock(mask)
31059243Sobrien *
31159243Sobrien * Add "mask" set of signals to the present signal mask.
31259243Sobrien * Return old mask.
31359243Sobrien */
31459243Sobriensigmask_t
31559243Sobriensigblock(mask)
31659243Sobrien    sigmask_t     mask;
31759243Sobrien{
31859243Sobrien    sigset_t set, oset;
31959243Sobrien    int     m;
32059243Sobrien    register int i;
32159243Sobrien
32259243Sobrien    (void) sigemptyset(&set);
32359243Sobrien    (void) sigemptyset(&oset);
32459243Sobrien
32559243Sobrien    /* Get present set of signals. */
32659243Sobrien    if ((sigprocmask(SIG_SETMASK, NULL, &set)) == -1)
32759243Sobrien	stderror(ERR_SYSTEM, "sigprocmask", strerror(errno));
32859243Sobrien
32959243Sobrien    /* Add in signals from mask. */
33059243Sobrien    for (i = 1; i <= MAXSIG; i++)
33159243Sobrien	if (ISSET(mask, i))
33259243Sobrien	    (void) sigaddset(&set, i);
33359243Sobrien
33459243Sobrien    if ((sigprocmask(SIG_SETMASK, &set, &oset)) == -1)
33559243Sobrien	stderror(ERR_SYSTEM, "sigprocmask", strerror(errno));
33659243Sobrien
33759243Sobrien    /* Return old mask to user. */
33859243Sobrien    m = 0;
33959243Sobrien    for (i = 1; i <= MAXSIG; i++)
34059243Sobrien	if (sigismember(&oset, i))
34159243Sobrien	    SETBIT(m, i);
34259243Sobrien
34359243Sobrien    return (m);
34459243Sobrien}
34559243Sobrien#endif /* __DGUX__ */
34659243Sobrien
34759243Sobrien
34859243Sobrien/*
34959243Sobrien * bsd_sigpause(mask)
35059243Sobrien *
35159243Sobrien * Set new signal mask and wait for signal;
35259243Sobrien * Old mask is restored on signal.
35359243Sobrien */
35459243Sobrienvoid
35559243Sobrienbsd_sigpause(mask)
35659243Sobrien    sigmask_t     mask;
35759243Sobrien{
35859243Sobrien    sigset_t set;
35959243Sobrien    register int i;
36059243Sobrien
36159243Sobrien    (void) sigemptyset(&set);
36259243Sobrien
36359243Sobrien    for (i = 1; i <= MAXSIG; i++)
36459243Sobrien	if (ISSET(mask, i))
36559243Sobrien	    (void) sigaddset(&set, i);
36659243Sobrien    (void) sigsuspend(&set);
36759243Sobrien}
36859243Sobrien
36959243Sobrien/*
37059243Sobrien * bsd_signal(sig, func)
37159243Sobrien *
37259243Sobrien * Emulate bsd style signal()
37359243Sobrien */
37459243Sobriensigret_t (*bsd_signal(sig, func)) ()
37559243Sobrien        int sig;
37659243Sobrien        signalfun_t func;
37759243Sobrien{
37859243Sobrien        struct sigaction act, oact;
37959243Sobrien        sigset_t set;
38059243Sobrien        signalfun_t r_func;
38159243Sobrien
38259243Sobrien        if (sig < 0 || sig > MAXSIG) {
38359243Sobrien                xprintf(CGETS(25, 2,
38459243Sobrien			"error: bsd_signal(%d) signal out of range\n"), sig);
38559243Sobrien                return((signalfun_t) SIG_IGN);
38659243Sobrien        }
38759243Sobrien
38859243Sobrien        (void) sigemptyset(&set);
38959243Sobrien
39059243Sobrien        act.sa_handler = (signalfun_t) func; /* user function */
39159243Sobrien        act.sa_mask = set;                      /* signal mask */
39259243Sobrien        act.sa_flags = 0;                       /* no special actions */
39359243Sobrien
39459243Sobrien        if (sigaction(sig, &act, &oact)) {
39559243Sobrien                xprintf(CGETS(25, 3,
39659243Sobrien			"error: bsd_signal(%d) - sigaction failed, errno %d\n"),
39759243Sobrien			sig, errno);
39859243Sobrien                return((signalfun_t) SIG_IGN);
39959243Sobrien        }
40059243Sobrien
40159243Sobrien        r_func = (signalfun_t) oact.sa_handler;
40259243Sobrien        return(r_func);
40359243Sobrien}
40459243Sobrien#endif /* POSIXSIG */
40559243Sobrien
40659243Sobrien
40759243Sobrien#ifdef SIGSYNCH
40859243Sobrienstatic long Synch_Cnt = 0;
40959243Sobrien
41059243Sobriensigret_t
41159243Sobriensynch_handler(sno)
41259243Sobrienint sno;
41359243Sobrien{
41459243Sobrien    if (sno != SIGSYNCH)
41559243Sobrien	abort();
41659243Sobrien    Synch_Cnt++;
41759243Sobrien}
41859243Sobrien#endif /* SIGSYNCH */
419