* Copyright (c) 1991 The Regents of the University of California.
* This code is derived from software contributed to Berkeley by
* %sccs.include.redist.c%
static char sccsid
[] = "@(#)trap.c 5.2 (Berkeley) %G%";
#include "nodes.h" /* for other headers */
* Sigmode records the current value of the signal handlers for the various
* modes. A value of zero means that the current handler is not known.
* S_HARD_IGN indicates that the signal was ignored on entry to the shell,
#define S_DFL 1 /* default signal handling (SIG_DFL) */
#define S_CATCH 2 /* signal is caught */
#define S_IGN 3 /* signal is ignored (SIG_IGN) */
#define S_HARD_IGN 4 /* signal is ignored permenantly */
extern char nullstr
[1]; /* null string */
char *trap
[MAXSIG
+1]; /* trap handler commands */
MKINIT
char sigmode
[MAXSIG
]; /* current value of signal */
char gotsig
[MAXSIG
]; /* indicates specified signal received */
int pendingsigs
; /* indicates some signal received */
trapcmd(argc
, argv
) char **argv
; {
for (signo
= 0 ; signo
<= MAXSIG
; signo
++) {
out1fmt("%d: %s\n", signo
, trap
[signo
]);
if ((signo
= number(*ap
)) < 0 || signo
> MAXSIG
)
error("%s: bad trap", *ap
);
action
= savestr(action
);
for (tp
= trap
; tp
<= &trap
[MAXSIG
] ; tp
++) {
if (*tp
&& **tp
) { /* trap not NULL or SIG_IGN */
* Set the signal handler for the specified signal. The routine figures
* out what it should be set to.
if ((t
= trap
[signo
]) == NULL
)
if (rootshell
&& action
== S_DFL
) {
if (*t
== 0) { /* current setting unknown */
* There is a race condition here if action is not S_IGN.
* A signal can be ignored that shouldn't be.
if ((int)(sigact
= signal(signo
, SIG_IGN
)) == -1)
error("Signal system call failed");
if (*t
== S_HARD_IGN
|| *t
== action
)
case S_DFL
: sigact
= SIG_DFL
; break;
case S_CATCH
: sigact
= onsig
; break;
case S_IGN
: sigact
= SIG_IGN
; break;
return (int)signal(signo
, sigact
);
if (sigmode
[signo
- 1] != S_IGN
&& sigmode
[signo
- 1] != S_HARD_IGN
) {
sigmode
[signo
- 1] = S_HARD_IGN
;
for (sm
= sigmode
; sm
< sigmode
+ MAXSIG
; sm
++) {
if (signo
== SIGINT
&& trap
[SIGINT
] == NULL
) {
* Called to execute a trap. Perhaps we should avoid entering new trap
* handlers while we are executing a trap handler.
* Controls whether the shell is interactive or not.
if (on
== is_interactive
)
* Called to exit the shell.
struct jmploc loc1
, loc2
;
TRACE(("exitshell(%d) pid=%d\n", status
, getpid()));
if (setjmp(loc1
.loc
)) goto l1
;
if (setjmp(loc2
.loc
)) goto l2
;
if ((p
= trap
[0]) != NULL
&& *p
!= '\0') {
l1
: handler
= &loc2
; /* probably unnecessary */