tc.sig.c revision 69408
169408Sache/* $Header: /src/pub/tcsh/tc.sig.c,v 3.25 2000/07/04 19:46:24 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 3969408SacheRCSID("$Id: tc.sig.c,v 3.25 2000/07/04 19:46:24 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 16469408Sache 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