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