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