2
* Copyright (c) 1991, 1993
3
* The Regents of the University of California. All rights reserved.
4
* Copyright (c) 1997-2005
5
* Herbert Xu <herbert@gondor.apana.org.au>. All rights reserved.
7
* This code is derived from software contributed to Berkeley by
10
* Redistribution and use in source and binary forms, with or without
11
* modification, are permitted provided that the following conditions
13
* 1. Redistributions of source code must retain the above copyright
14
* notice, this list of conditions and the following disclaimer.
15
* 2. Redistributions in binary form must reproduce the above copyright
16
* notice, this list of conditions and the following disclaimer in the
17
* documentation and/or other materials provided with the distribution.
18
* 3. Neither the name of the University nor the names of its contributors
19
* may be used to endorse or promote products derived from this software
20
* without specific prior written permission.
22
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43
#include "nodes.h" /* for other headers */
60
* Sigmode records the current value of the signal handlers for the various
61
* modes. A value of zero means that the current handler is not known.
62
* S_HARD_IGN indicates that the signal was ignored on entry to the shell,
65
#define S_DFL 1 /* default signal handling (SIG_DFL) */
66
#define S_CATCH 2 /* signal is caught */
67
#define S_IGN 3 /* signal is ignored (SIG_IGN) */
68
#define S_HARD_IGN 4 /* signal is ignored permenantly */
69
#define S_RESET 5 /* temporary - to reset a hard ignored sig */
72
/* trap handler commands */
74
/* current value of signal */
75
static char sigmode[NSIG - 1];
76
/* indicates specified signal received */
77
char gotsig[NSIG - 1];
78
/* last pending signal */
79
volatile sig_atomic_t pendingsigs;
80
/* do we generate EXSIG events */
86
signal(SIGCHLD, SIG_DFL);
95
trapcmd(int argc, char **argv)
104
for (signo = 0 ; signo < NSIG ; signo++) {
105
if (trap[signo] != NULL) {
108
single_quote(trap[signo]),
120
if ((signo = decode_signal(*ap, 0)) < 0)
121
sh_error("%s: bad trap", *ap);
124
if (action[0] == '-' && action[1] == '\0')
127
action = savestr(action);
131
trap[signo] = action;
143
* Clear traps on a fork.
151
for (tp = trap ; tp < &trap[NSIG] ; tp++) {
152
if (*tp && **tp) { /* trap not NULL or SIG_IGN */
157
setsignal(tp - trap);
166
* Set the signal handler for the specified signal. The routine figures
167
* out what it should be set to.
175
struct sigaction act;
177
if ((t = trap[signo]) == NULL)
183
if (rootshell && action == S_DFL) {
186
if (iflag || minusc || sflag == 0)
209
t = &sigmode[signo - 1];
213
* current setting unknown
215
if (sigaction(signo, 0, &act) == -1) {
217
* Pretend it worked; maybe we should give a warning
218
* here, but other shells don't. We don't alter
219
* sigmode, so that we retry every time.
223
if (act.sa_handler == SIG_IGN) {
224
if (mflag && (signo == SIGTSTP ||
225
signo == SIGTTIN || signo == SIGTTOU)) {
226
tsig = S_IGN; /* don't hard ignore these */
230
tsig = S_RESET; /* force to be set */
233
if (tsig == S_HARD_IGN || tsig == action)
237
act.sa_handler = onsig;
240
act.sa_handler = SIG_IGN;
243
act.sa_handler = SIG_DFL;
247
sigfillset(&act.sa_mask);
248
sigaction(signo, &act, 0);
258
if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
259
signal(signo, SIG_IGN);
261
sigmode[signo - 1] = S_HARD_IGN;
273
gotsig[signo - 1] = 1;
276
if (exsig || (signo == SIGINT && !trap[SIGINT])) {
286
* Called to execute a trap. Perhaps we should avoid entering new trap
287
* handlers while we are executing a trap handler.
299
savestatus = exitstatus;
303
for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
311
skip = evalstring(p, SKIPEVAL);
312
exitstatus = savestatus;
323
* Controls whether the shell is interactive or not.
328
setinteractive(int on)
330
static int is_interactive;
332
if (++on == is_interactive)
343
* Called to exit the shell.
357
TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
358
if (setjmp(loc.loc)) {
359
if (exception == EXEXIT)
375
* Decode a signal name
377
int decode_signal(const char *string, int minsig)
381
if (is_number(string)) {
389
for ( i = minsig ; i < NSIG ; i++ ) {
390
if ( sys_sigabbrev[i] &&
391
!strcasecmp(string, sys_sigabbrev[i]) )
396
if ( !strncasecmp(string, "RTMIN", 5) ) {
399
if ( string[5] && string[5] != '+' )
401
i = SIGRTMIN + strtol(string+5, &ep, 10);
402
if ( *ep || i < SIGRTMIN || i > SIGRTMAX )
407
if ( !strncasecmp(string, "RTMAX", 5) ) {
410
if ( string[5] && string[5] != '-' )
412
i = SIGRTMAX + strtol(string+5, &ep, 10);
413
if ( *ep || i < SIGRTMIN || i > SIGRTMAX )
423
* Human-readable signal name
430
if ( sig < 0 || sig >= NSIG ) {
432
} else if ( sys_sigabbrev[sig] ) {
433
return sys_sigabbrev[sig];
435
} else if ( sig >= SIGRTMIN && sig <= SIGRTMAX ) {
436
snprintf(buf, sizeof buf, "RTMIN+%d", sig-SIGRTMIN);
440
snprintf(buf, sizeof buf, "%d", sig);