trap.c revision 8855
11556Srgrimes/*- 21556Srgrimes * Copyright (c) 1991, 1993 31556Srgrimes * The Regents of the University of California. All rights reserved. 41556Srgrimes * 51556Srgrimes * This code is derived from software contributed to Berkeley by 61556Srgrimes * Kenneth Almquist. 71556Srgrimes * 81556Srgrimes * Redistribution and use in source and binary forms, with or without 91556Srgrimes * modification, are permitted provided that the following conditions 101556Srgrimes * are met: 111556Srgrimes * 1. Redistributions of source code must retain the above copyright 121556Srgrimes * notice, this list of conditions and the following disclaimer. 131556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141556Srgrimes * notice, this list of conditions and the following disclaimer in the 151556Srgrimes * documentation and/or other materials provided with the distribution. 161556Srgrimes * 3. All advertising materials mentioning features or use of this software 171556Srgrimes * must display the following acknowledgement: 181556Srgrimes * This product includes software developed by the University of 191556Srgrimes * California, Berkeley and its contributors. 201556Srgrimes * 4. Neither the name of the University nor the names of its contributors 211556Srgrimes * may be used to endorse or promote products derived from this software 221556Srgrimes * without specific prior written permission. 231556Srgrimes * 241556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 251556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 261556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 271556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 281556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 291556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 301556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 311556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 321556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 331556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 341556Srgrimes * SUCH DAMAGE. 353044Sdg * 368855Srgrimes * $Id: trap.c,v 1.2 1994/09/24 02:58:18 davidg Exp $ 371556Srgrimes */ 381556Srgrimes 391556Srgrimes#ifndef lint 401556Srgrimesstatic char sccsid[] = "@(#)trap.c 8.1 (Berkeley) 5/31/93"; 411556Srgrimes#endif /* not lint */ 421556Srgrimes 431556Srgrimes#include "shell.h" 441556Srgrimes#include "main.h" 451556Srgrimes#include "nodes.h" /* for other headers */ 461556Srgrimes#include "eval.h" 471556Srgrimes#include "jobs.h" 481556Srgrimes#include "options.h" 491556Srgrimes#include "syntax.h" 501556Srgrimes#include "signames.h" 511556Srgrimes#include "output.h" 521556Srgrimes#include "memalloc.h" 531556Srgrimes#include "error.h" 541556Srgrimes#include "trap.h" 551556Srgrimes#include "mystring.h" 561556Srgrimes#include <signal.h> 571556Srgrimes 581556Srgrimes 591556Srgrimes/* 601556Srgrimes * Sigmode records the current value of the signal handlers for the various 611556Srgrimes * modes. A value of zero means that the current handler is not known. 621556Srgrimes * S_HARD_IGN indicates that the signal was ignored on entry to the shell, 631556Srgrimes */ 641556Srgrimes 651556Srgrimes#define S_DFL 1 /* default signal handling (SIG_DFL) */ 661556Srgrimes#define S_CATCH 2 /* signal is caught */ 671556Srgrimes#define S_IGN 3 /* signal is ignored (SIG_IGN) */ 681556Srgrimes#define S_HARD_IGN 4 /* signal is ignored permenantly */ 691556Srgrimes#define S_RESET 5 /* temporary - to reset a hard ignored sig */ 701556Srgrimes 711556Srgrimes 721556Srgrimesextern char nullstr[1]; /* null string */ 731556Srgrimes 741556Srgrimeschar *trap[MAXSIG+1]; /* trap handler commands */ 751556SrgrimesMKINIT char sigmode[MAXSIG]; /* current value of signal */ 761556Srgrimeschar gotsig[MAXSIG]; /* indicates specified signal received */ 771556Srgrimesint pendingsigs; /* indicates some signal received */ 781556Srgrimes 791556Srgrimes/* 801556Srgrimes * The trap builtin. 811556Srgrimes */ 821556Srgrimes 831556Srgrimestrapcmd(argc, argv) char **argv; { 841556Srgrimes char *action; 851556Srgrimes char **ap; 861556Srgrimes int signo; 871556Srgrimes 881556Srgrimes if (argc <= 1) { 891556Srgrimes for (signo = 0 ; signo <= MAXSIG ; signo++) { 901556Srgrimes if (trap[signo] != NULL) 911556Srgrimes out1fmt("%d: %s\n", signo, trap[signo]); 921556Srgrimes } 931556Srgrimes return 0; 941556Srgrimes } 951556Srgrimes ap = argv + 1; 961556Srgrimes if (is_number(*ap)) 971556Srgrimes action = NULL; 981556Srgrimes else 991556Srgrimes action = *ap++; 1001556Srgrimes while (*ap) { 1011556Srgrimes if ((signo = number(*ap)) < 0 || signo > MAXSIG) 1021556Srgrimes error("%s: bad trap", *ap); 1031556Srgrimes INTOFF; 1041556Srgrimes if (action) 1051556Srgrimes action = savestr(action); 1061556Srgrimes if (trap[signo]) 1071556Srgrimes ckfree(trap[signo]); 1081556Srgrimes trap[signo] = action; 1091556Srgrimes if (signo != 0) 1101556Srgrimes setsignal(signo); 1111556Srgrimes INTON; 1121556Srgrimes ap++; 1131556Srgrimes } 1141556Srgrimes return 0; 1151556Srgrimes} 1161556Srgrimes 1171556Srgrimes 1181556Srgrimes 1191556Srgrimes/* 1201556Srgrimes * Clear traps on a fork. 1211556Srgrimes */ 1221556Srgrimes 1231556Srgrimesvoid 1241556Srgrimesclear_traps() { 1251556Srgrimes char **tp; 1261556Srgrimes 1271556Srgrimes for (tp = trap ; tp <= &trap[MAXSIG] ; tp++) { 1281556Srgrimes if (*tp && **tp) { /* trap not NULL or SIG_IGN */ 1291556Srgrimes INTOFF; 1301556Srgrimes ckfree(*tp); 1311556Srgrimes *tp = NULL; 1321556Srgrimes if (tp != &trap[0]) 1331556Srgrimes setsignal(tp - trap); 1341556Srgrimes INTON; 1351556Srgrimes } 1361556Srgrimes } 1371556Srgrimes} 1381556Srgrimes 1391556Srgrimes 1401556Srgrimes 1411556Srgrimes/* 1421556Srgrimes * Set the signal handler for the specified signal. The routine figures 1431556Srgrimes * out what it should be set to. 1441556Srgrimes */ 1451556Srgrimes 1461556Srgrimesint 1471556Srgrimessetsignal(signo) { 1481556Srgrimes int action; 1491556Srgrimes sig_t sigact; 1501556Srgrimes char *t; 1511556Srgrimes extern void onsig(); 1521556Srgrimes extern sig_t getsigaction(); 1531556Srgrimes 1541556Srgrimes if ((t = trap[signo]) == NULL) 1551556Srgrimes action = S_DFL; 1561556Srgrimes else if (*t != '\0') 1571556Srgrimes action = S_CATCH; 1581556Srgrimes else 1591556Srgrimes action = S_IGN; 1601556Srgrimes if (rootshell && action == S_DFL) { 1611556Srgrimes switch (signo) { 1621556Srgrimes case SIGINT: 1631556Srgrimes if (iflag) 1641556Srgrimes action = S_CATCH; 1651556Srgrimes break; 1661556Srgrimes case SIGQUIT: 1671556Srgrimes#ifdef DEBUG 1681556Srgrimes { 1691556Srgrimes extern int debug; 1701556Srgrimes 1711556Srgrimes if (debug) 1721556Srgrimes break; 1731556Srgrimes } 1741556Srgrimes#endif 1751556Srgrimes /* FALLTHROUGH */ 1761556Srgrimes case SIGTERM: 1771556Srgrimes if (iflag) 1781556Srgrimes action = S_IGN; 1791556Srgrimes break; 1801556Srgrimes#if JOBS 1811556Srgrimes case SIGTSTP: 1821556Srgrimes case SIGTTOU: 1831556Srgrimes if (mflag) 1841556Srgrimes action = S_IGN; 1851556Srgrimes break; 1861556Srgrimes#endif 1871556Srgrimes } 1881556Srgrimes } 1891556Srgrimes t = &sigmode[signo - 1]; 1908855Srgrimes if (*t == 0) { 1918855Srgrimes /* 1928855Srgrimes * current setting unknown 1931556Srgrimes */ 1941556Srgrimes sigact = getsigaction(signo); 1951556Srgrimes if (sigact == SIG_IGN) { 1968855Srgrimes if (mflag && (signo == SIGTSTP || 1971556Srgrimes signo == SIGTTIN || signo == SIGTTOU)) { 1981556Srgrimes *t = S_IGN; /* don't hard ignore these */ 1991556Srgrimes } else 2001556Srgrimes *t = S_HARD_IGN; 2011556Srgrimes } else { 2021556Srgrimes *t = S_RESET; /* force to be set */ 2031556Srgrimes } 2041556Srgrimes } 2051556Srgrimes if (*t == S_HARD_IGN || *t == action) 2061556Srgrimes return 0; 2071556Srgrimes switch (action) { 2081556Srgrimes case S_DFL: sigact = SIG_DFL; break; 2091556Srgrimes case S_CATCH: sigact = onsig; break; 2101556Srgrimes case S_IGN: sigact = SIG_IGN; break; 2111556Srgrimes } 2121556Srgrimes *t = action; 2131556Srgrimes return (int)signal(signo, sigact); 2141556Srgrimes} 2151556Srgrimes 2161556Srgrimes/* 2171556Srgrimes * Return the current setting for sig w/o changing it. 2181556Srgrimes */ 2191556Srgrimessig_t 2201556Srgrimesgetsigaction(signo) { 2211556Srgrimes struct sigaction sa; 2221556Srgrimes 2231556Srgrimes if (sigaction(signo, (struct sigaction *)0, &sa) == -1) 2241556Srgrimes error("Sigaction system call failed"); 2251556Srgrimes 2261556Srgrimes return sa.sa_handler; 2271556Srgrimes} 2281556Srgrimes 2291556Srgrimes/* 2301556Srgrimes * Ignore a signal. 2311556Srgrimes */ 2321556Srgrimes 2331556Srgrimesvoid 2341556Srgrimesignoresig(signo) { 2351556Srgrimes if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) { 2361556Srgrimes signal(signo, SIG_IGN); 2371556Srgrimes } 2381556Srgrimes sigmode[signo - 1] = S_HARD_IGN; 2391556Srgrimes} 2401556Srgrimes 2411556Srgrimes 2421556Srgrimes#ifdef mkinit 2431556SrgrimesINCLUDE "signames.h" 2441556SrgrimesINCLUDE "trap.h" 2451556Srgrimes 2461556SrgrimesSHELLPROC { 2471556Srgrimes char *sm; 2481556Srgrimes 2491556Srgrimes clear_traps(); 2501556Srgrimes for (sm = sigmode ; sm < sigmode + MAXSIG ; sm++) { 2511556Srgrimes if (*sm == S_IGN) 2521556Srgrimes *sm = S_HARD_IGN; 2531556Srgrimes } 2541556Srgrimes} 2551556Srgrimes#endif 2561556Srgrimes 2571556Srgrimes 2581556Srgrimes 2591556Srgrimes/* 2601556Srgrimes * Signal handler. 2611556Srgrimes */ 2621556Srgrimes 2631556Srgrimesvoid 2641556Srgrimesonsig(signo) { 2651556Srgrimes signal(signo, onsig); 2661556Srgrimes if (signo == SIGINT && trap[SIGINT] == NULL) { 2671556Srgrimes onint(); 2681556Srgrimes return; 2691556Srgrimes } 2701556Srgrimes gotsig[signo - 1] = 1; 2711556Srgrimes pendingsigs++; 2721556Srgrimes} 2731556Srgrimes 2741556Srgrimes 2751556Srgrimes 2761556Srgrimes/* 2771556Srgrimes * Called to execute a trap. Perhaps we should avoid entering new trap 2781556Srgrimes * handlers while we are executing a trap handler. 2791556Srgrimes */ 2801556Srgrimes 2811556Srgrimesvoid 2821556Srgrimesdotrap() { 2831556Srgrimes int i; 2841556Srgrimes int savestatus; 2851556Srgrimes 2861556Srgrimes for (;;) { 2871556Srgrimes for (i = 1 ; ; i++) { 2881556Srgrimes if (gotsig[i - 1]) 2891556Srgrimes break; 2901556Srgrimes if (i >= MAXSIG) 2911556Srgrimes goto done; 2921556Srgrimes } 2931556Srgrimes gotsig[i - 1] = 0; 2941556Srgrimes savestatus=exitstatus; 2951556Srgrimes evalstring(trap[i]); 2961556Srgrimes exitstatus=savestatus; 2971556Srgrimes } 2981556Srgrimesdone: 2991556Srgrimes pendingsigs = 0; 3001556Srgrimes} 3011556Srgrimes 3021556Srgrimes 3031556Srgrimes 3041556Srgrimes/* 3051556Srgrimes * Controls whether the shell is interactive or not. 3061556Srgrimes */ 3071556Srgrimes 3081556Srgrimes 3091556Srgrimesvoid 3101556Srgrimessetinteractive(on) { 3111556Srgrimes static int is_interactive; 3121556Srgrimes 3131556Srgrimes if (on == is_interactive) 3141556Srgrimes return; 3151556Srgrimes setsignal(SIGINT); 3161556Srgrimes setsignal(SIGQUIT); 3171556Srgrimes setsignal(SIGTERM); 3181556Srgrimes is_interactive = on; 3191556Srgrimes} 3201556Srgrimes 3211556Srgrimes 3221556Srgrimes 3231556Srgrimes/* 3241556Srgrimes * Called to exit the shell. 3251556Srgrimes */ 3261556Srgrimes 3271556Srgrimesvoid 3281556Srgrimesexitshell(status) { 3291556Srgrimes struct jmploc loc1, loc2; 3301556Srgrimes char *p; 3311556Srgrimes 3321556Srgrimes TRACE(("exitshell(%d) pid=%d\n", status, getpid())); 3331556Srgrimes if (setjmp(loc1.loc)) { 3341556Srgrimes goto l1; 3351556Srgrimes } 3361556Srgrimes if (setjmp(loc2.loc)) { 3371556Srgrimes goto l2; 3381556Srgrimes } 3391556Srgrimes handler = &loc1; 3401556Srgrimes if ((p = trap[0]) != NULL && *p != '\0') { 3411556Srgrimes trap[0] = NULL; 3421556Srgrimes evalstring(p); 3431556Srgrimes } 3441556Srgrimesl1: handler = &loc2; /* probably unnecessary */ 3451556Srgrimes flushall(); 3461556Srgrimes#if JOBS 3471556Srgrimes setjobctl(0); 3481556Srgrimes#endif 3491556Srgrimesl2: _exit(status); 3501556Srgrimes} 351