Module Name: src
Committed By: kre
Date: Mon Dec 3 06:43:19 UTC 2018
Modified Files:
src/bin/sh: eval.c eval.h main.c sh.1 trap.c trap.h
Log Message:
Cleanup traps a bit - attempt to handle weird uses in traps, such
as traps that issue break/continue/return to cause the loop/function
executing when the trap occurred to break/continue/return, and
generating the correct exit code from the shell including when a
signal is caught, but the trap handler for it exits.
All that from FreeBSD.
Also make
T=$(trap)
work as it is supposed to (also trap -p).
For now this is handled by the same technique as $(jobs) - rather
than clearing the traps in subshells, just mark them invalid, and
then whenever they're invalid, clear them before executing anything
other than the special blessed "trap" command. Eventually we will
handle these using non-subshell command substitution instead (not
creating a subshell environ when the commands in a command-sub alter
nothing in the environment).
To generate a diff of this commit:
cvs rdiff -u -r1.167 -r1.168 src/bin/sh/eval.c
cvs rdiff -u -r1.21 -r1.22 src/bin/sh/eval.h
cvs rdiff -u -r1.77 -r1.78 src/bin/sh/main.c
cvs rdiff -u -r1.209 -r1.210 src/bin/sh/sh.1
cvs rdiff -u -r1.46 -r1.47 src/bin/sh/trap.c
cvs rdiff -u -r1.23 -r1.24 src/bin/sh/trap.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/bin/sh/eval.c
diff -u src/bin/sh/eval.c:1.167 src/bin/sh/eval.c:1.168
--- src/bin/sh/eval.c:1.167 Mon Dec 3 06:42:25 2018
+++ src/bin/sh/eval.c Mon Dec 3 06:43:19 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: eval.c,v 1.167 2018/12/03 06:42:25 kre Exp $ */
+/* $NetBSD: eval.c,v 1.168 2018/12/03 06:43:19 kre Exp $ */
/*-
* Copyright (c) 1993
@@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)eval.c 8.9 (Berkeley) 6/8/95";
#else
-__RCSID("$NetBSD: eval.c,v 1.167 2018/12/03 06:42:25 kre Exp $");
+__RCSID("$NetBSD: eval.c,v 1.168 2018/12/03 06:43:19 kre Exp $");
#endif
#endif /* not lint */
@@ -87,8 +87,10 @@ __RCSID("$NetBSD: eval.c,v 1.167 2018/12
#endif
-STATIC enum skipstate evalskip; /* != SKIPNONE if we are skipping commands */
-STATIC int skipcount; /* number of levels to skip */
+STATIC struct skipsave s_k_i_p;
+#define evalskip (s_k_i_p.state)
+#define skipcount (s_k_i_p.count)
+
STATIC int loopnest; /* current loop nesting level */
STATIC int funcnest; /* depth of function calls */
STATIC int builtin_flags; /* evalcommand flags for builtins */
@@ -278,6 +280,8 @@ evaltree(union node *n, int flags)
next = NULL;
CTRACE(DBG_EVAL, ("pid %d, evaltree(%p: %s(%d), %#x) called\n",
getpid(), n, NODETYPENAME(n->type), n->type, flags));
+ if (n->type != NCMD && traps_invalid)
+ free_traps();
switch (n->type) {
case NSEMI:
evaltree(n->nbinary.ch1, sflags);
@@ -1026,6 +1030,9 @@ evalcommand(union node *cmd, int flgs, s
cmdentry.cmdtype = CMDBUILTIN;
}
+ if (traps_invalid && cmdentry.cmdtype != CMDSPLBLTIN)
+ free_traps();
+
/* Fork off a child process if necessary. */
if (cmd->ncmd.backgnd || (have_traps() && (flags & EV_EXIT) != 0)
|| ((cmdentry.cmdtype == CMDNORMAL || cmdentry.cmdtype == CMDUNKNOWN)
@@ -1376,6 +1383,18 @@ current_skipstate(void)
}
void
+save_skipstate(struct skipsave *p)
+{
+ *p = s_k_i_p;
+}
+
+void
+restore_skipstate(const struct skipsave *p)
+{
+ s_k_i_p = *p;
+}
+
+void
stop_skipping(void)
{
evalskip = SKIPNONE;
Index: src/bin/sh/eval.h
diff -u src/bin/sh/eval.h:1.21 src/bin/sh/eval.h:1.22
--- src/bin/sh/eval.h:1.21 Sun Aug 19 11:16:13 2018
+++ src/bin/sh/eval.h Mon Dec 3 06:43:19 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: eval.h,v 1.21 2018/08/19 11:16:13 kre Exp $ */
+/* $NetBSD: eval.h,v 1.22 2018/12/03 06:43:19 kre Exp $ */
/*-
* Copyright (c) 1991, 1993
@@ -66,7 +66,14 @@ enum skipstate {
SKIPFILE /* return in a dot command */
};
+struct skipsave {
+ enum skipstate state; /* skipping or not */
+ int count; /* when break or continue, how many */
+};
+
enum skipstate current_skipstate(void);
+void save_skipstate(struct skipsave *);
+void restore_skipstate(const struct skipsave *);
void stop_skipping(void); /* reset internal skipping state to SKIPNONE */
/*
Index: src/bin/sh/main.c
diff -u src/bin/sh/main.c:1.77 src/bin/sh/main.c:1.78
--- src/bin/sh/main.c:1.77 Mon Dec 3 02:38:30 2018
+++ src/bin/sh/main.c Mon Dec 3 06:43:19 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: main.c,v 1.77 2018/12/03 02:38:30 kre Exp $ */
+/* $NetBSD: main.c,v 1.78 2018/12/03 06:43:19 kre Exp $ */
/*-
* Copyright (c) 1991, 1993
@@ -42,7 +42,7 @@ __COPYRIGHT("@(#) Copyright (c) 1991, 19
#if 0
static char sccsid[] = "@(#)main.c 8.7 (Berkeley) 7/19/95";
#else
-__RCSID("$NetBSD: main.c,v 1.77 2018/12/03 02:38:30 kre Exp $");
+__RCSID("$NetBSD: main.c,v 1.78 2018/12/03 06:43:19 kre Exp $");
#endif
#endif /* not lint */
@@ -378,7 +378,8 @@ exitcmd(int argc, char **argv)
if (stoppedjobs())
return 0;
if (argc > 1)
- exitstatus = number(argv[1]);
- exitshell(exitstatus);
+ exitshell(number(argv[1]));
+ else
+ exitshell_savedstatus();
/* NOTREACHED */
}
Index: src/bin/sh/sh.1
diff -u src/bin/sh/sh.1:1.209 src/bin/sh/sh.1:1.210
--- src/bin/sh/sh.1:1.209 Fri Nov 23 20:40:06 2018
+++ src/bin/sh/sh.1 Mon Dec 3 06:43:19 2018
@@ -1,4 +1,4 @@
-.\" $NetBSD: sh.1,v 1.209 2018/11/23 20:40:06 kre Exp $
+.\" $NetBSD: sh.1,v 1.210 2018/12/03 06:43:19 kre Exp $
.\" Copyright (c) 1991, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
@@ -3307,6 +3307,11 @@ With the
flag, trap prints the same information for the signals specified,
or if none are given, for all signals, including those where the
action is the default.
+These variants of the trap command may be executed in a sub-shell
+.Pq "such as in a command substitution" ,
+provided they appear as the sole, or first, command in that sub-shell,
+in which case the state of traps from the parent of that
+sub-shell is reported.
.Pp
Examples:
.Pp
@@ -4371,21 +4376,6 @@ The characters generated by filename com
to ensure that the filename is still valid after the input line has been
processed.
.Pp
-The
-.Ic trap
-command cannot usefully be used, yet, within a command substitution,
-to obtain the current trap values,
-as all command substitutions are currently executed within a
-sub-shell environment,
-and in sub-shells all non-ignored, non-default, traps are reset.
-As a workaround, it is possible to redirect output from
-.Dq trap
-or
-.Dq trap -p
-to a file, and then read the file later using the
-.Dq \&.
-command.
-.Pp
Job control of compound statements (loops, etc) is a complete mess.
.Pp
Many, many, more.
Index: src/bin/sh/trap.c
diff -u src/bin/sh/trap.c:1.46 src/bin/sh/trap.c:1.47
--- src/bin/sh/trap.c:1.46 Sun Oct 28 18:26:52 2018
+++ src/bin/sh/trap.c Mon Dec 3 06:43:19 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: trap.c,v 1.46 2018/10/28 18:26:52 kre Exp $ */
+/* $NetBSD: trap.c,v 1.47 2018/12/03 06:43:19 kre Exp $ */
/*-
* Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)trap.c 8.5 (Berkeley) 6/5/95";
#else
-__RCSID("$NetBSD: trap.c,v 1.46 2018/10/28 18:26:52 kre Exp $");
+__RCSID("$NetBSD: trap.c,v 1.47 2018/12/03 06:43:19 kre Exp $");
#endif
#endif /* not lint */
@@ -45,6 +45,9 @@ __RCSID("$NetBSD: trap.c,v 1.46 2018/10/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
+#include <errno.h>
+
+#include <sys/resource.h>
#include "shell.h"
#include "main.h"
@@ -76,10 +79,17 @@ __RCSID("$NetBSD: trap.c,v 1.46 2018/10/
#define S_RESET 5 /* temporary - to reset a hard ignored sig */
-char *trap[NSIG]; /* trap handler commands */
MKINIT char sigmode[NSIG]; /* current value of signal */
-static volatile char gotsig[NSIG];/* indicates specified signal received */
-volatile int pendingsigs; /* indicates some signal received */
+static volatile sig_atomic_t gotsig[NSIG];/* indicates specified signal received */
+volatile sig_atomic_t pendingsigs; /* indicates some signal received */
+
+int traps_invalid; /* in a subshell, but trap[] not yet cleared */
+static char * volatile trap[NSIG]; /* trap handler commands */
+static int in_dotrap;
+static int last_trapsig;
+
+static int exiting; /* exitshell() has been done */
+static int exiting_status; /* the status to use for exit() */
static int getsigaction(int, sig_t *);
STATIC const char *trap_signame(int);
@@ -161,12 +171,15 @@ trapcmd(int argc, char **argv)
ap = argv + 1;
+ CTRACE(DBG_TRAP, ("trapcmd: "));
if (argc == 2 && strcmp(*ap, "-l") == 0) {
+ CTRACE(DBG_TRAP, ("-l\n"));
out1str("EXIT");
printsignals(out1, 4);
return 0;
}
if (argc == 2 && strcmp(*ap, "-") == 0) {
+ CTRACE(DBG_TRAP, ("-\n"));
for (signo = 0; signo < NSIG; signo++) {
if (trap[signo] == NULL)
continue;
@@ -177,9 +190,11 @@ trapcmd(int argc, char **argv)
setsignal(signo, 0);
INTON;
}
+ traps_invalid = 0;
return 0;
}
if (argc >= 2 && strcmp(*ap, "-p") == 0) {
+ CTRACE(DBG_TRAP, ("-p "));
printonly = 1;
ap++;
argc--;
@@ -193,6 +208,7 @@ trapcmd(int argc, char **argv)
if (argc <= 1) {
int count;
+ CTRACE(DBG_TRAP, ("*all*\n"));
if (printonly) {
for (count = 0, signo = 0 ; signo < NSIG ; signo++)
if (trap[signo] == NULL) {
@@ -239,9 +255,13 @@ trapcmd(int argc, char **argv)
return 0;
}
+ CTRACE(DBG_TRAP, ("\n"));
action = NULL;
+ if (!printonly && traps_invalid)
+ free_traps();
+
if (!printonly && !is_number(*ap)) {
if ((*ap)[0] == '-' && (*ap)[1] == '\0')
ap++; /* reset to default */
@@ -285,6 +305,11 @@ trapcmd(int argc, char **argv)
if (action)
action = savestr(action);
+ VTRACE(DBG_TRAP, ("trap for %d from %s%s%s to %s%s%s\n", signo,
+ trap[signo] ? "'" : "", trap[signo] ? trap[signo] : "-",
+ trap[signo] ? "'" : "", action ? "'" : "",
+ action ? action : "-", action ? "'" : ""));
+
if (trap[signo])
ckfree(trap[signo]);
@@ -304,24 +329,40 @@ trapcmd(int argc, char **argv)
* Takes one arg vfork, to tell it to not be destructive of
* the parents variables.
*/
-
void
clear_traps(int vforked)
{
- char **tp;
+ char * volatile *tp;
+
+ VTRACE(DBG_TRAP, ("clear_traps(%d)\n", vforked));
+ if (!vforked)
+ traps_invalid = 1;
- for (tp = trap ; tp < &trap[NSIG] ; tp++) {
+ for (tp = &trap[1] ; tp < &trap[NSIG] ; tp++) {
if (*tp && **tp) { /* trap not NULL or SIG_IGN */
INTOFF;
- if (!vforked) {
- ckfree(*tp);
- *tp = NULL;
- }
- if (tp != &trap[0])
- setsignal(tp - trap, vforked);
+ setsignal(tp - trap, vforked == 1);
INTON;
}
}
+ if (vforked == 2)
+ free_traps();
+}
+
+void
+free_traps(void)
+{
+ char * volatile *tp;
+
+ VTRACE(DBG_TRAP, ("free_traps%s\n", traps_invalid ? "(invalid)" : ""));
+ INTOFF;
+ for (tp = trap ; tp < &trap[NSIG] ; tp++)
+ if (*tp && **tp) {
+ ckfree(*tp);
+ *tp = NULL;
+ }
+ traps_invalid = 0;
+ INTON;
}
/*
@@ -330,7 +371,10 @@ clear_traps(int vforked)
int
have_traps(void)
{
- char **tp;
+ char * volatile *tp;
+
+ if (traps_invalid)
+ return 0;
for (tp = trap ; tp < &trap[NSIG] ; tp++)
if (*tp && **tp) /* trap not NULL or SIG_IGN */
@@ -342,8 +386,7 @@ have_traps(void)
* Set the signal handler for the specified signal. The routine figures
* out what it should be set to.
*/
-
-sig_t
+void
setsignal(int signo, int vforked)
{
int action;
@@ -356,6 +399,9 @@ setsignal(int signo, int vforked)
action = S_CATCH;
else
action = S_IGN;
+
+ VTRACE(DBG_TRAP, ("setsignal(%d%s) -> %d", signo,
+ vforked ? ", VF" : "", action));
if (rootshell && !vforked && action == S_DFL) {
switch (signo) {
case SIGINT:
@@ -369,20 +415,30 @@ setsignal(int signo, int vforked)
#endif
/* FALLTHROUGH */
case SIGTERM:
- if (iflag)
+ if (rootshell && iflag)
action = S_IGN;
break;
#if JOBS
case SIGTSTP:
case SIGTTOU:
- if (mflag)
+ if (rootshell && mflag)
action = S_IGN;
break;
#endif
}
}
- t = &sigmode[signo - 1];
+ /*
+ * Never let users futz with SIGCHLD
+ * instead we will give them pseudo SIGCHLD's
+ * when background jobs complete.
+ */
+ if (signo == SIGCHLD)
+ action = S_DFL;
+
+ VTRACE(DBG_TRAP, (" -> %d", action));
+
+ t = &sigmode[signo];
tsig = *t;
if (tsig == 0) {
/*
@@ -394,8 +450,13 @@ setsignal(int signo, int vforked)
* here, but other shells don't. We don't alter
* sigmode, so that we retry every time.
*/
- return 0;
+ VTRACE(DBG_TRAP, (" getsigaction (%d)\n", errno));
+ return;
}
+ VTRACE(DBG_TRAP, (" [%s]%s%s", sigact==SIG_IGN ? "IGN" :
+ sigact==SIG_DFL ? "DFL" : "caught",
+ iflag ? "i" : "", mflag ? "m" : ""));
+
if (sigact == SIG_IGN) {
/*
* POSIX 3.14.13 states that non-interactive shells
@@ -418,18 +479,25 @@ setsignal(int signo, int vforked)
tsig = S_RESET; /* force to be set */
}
}
+ VTRACE(DBG_TRAP, (" tsig=%d\n", tsig));
+
if (tsig == S_HARD_IGN || tsig == action)
- return 0;
+ return;
+
switch (action) {
case S_DFL: sigact = SIG_DFL; break;
case S_CATCH: sigact = onsig; break;
case S_IGN: sigact = SIG_IGN; break;
}
+
sig = signal(signo, sigact);
+
if (sig != SIG_ERR) {
sigset_t ss;
+
if (!vforked)
*t = action;
+
if (action == S_CATCH)
(void)siginterrupt(signo, 1);
/*
@@ -440,7 +508,7 @@ setsignal(int signo, int vforked)
(void)sigaddset(&ss, signo);
(void)sigprocmask(SIG_UNBLOCK, &ss, NULL);
}
- return sig;
+ return;
}
/*
@@ -464,26 +532,50 @@ getsigaction(int signo, sig_t *sigact)
void
ignoresig(int signo, int vforked)
{
- if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
+ if (sigmode[signo] == 0)
+ setsignal(signo, vforked);
+
+ VTRACE(DBG_TRAP, ("ignoresig(%d%s)\n", signo, vforked ? ", VF" : ""));
+ if (sigmode[signo] != S_IGN && sigmode[signo] != S_HARD_IGN) {
signal(signo, SIG_IGN);
+ if (!vforked)
+ sigmode[signo] = S_IGN;
}
- if (!vforked)
- sigmode[signo - 1] = S_HARD_IGN;
+}
+
+char *
+child_trap(void)
+{
+ char * p;
+
+ p = trap[SIGCHLD];
+
+ if (p != NULL && *p == '\0')
+ p = NULL;
+
+ return p;
}
#ifdef mkinit
INCLUDE <signal.h>
INCLUDE "trap.h"
+INCLUDE "shell.h"
+INCLUDE "show.h"
SHELLPROC {
char *sm;
- clear_traps(0);
+ INTOFF;
+ clear_traps(2);
for (sm = sigmode ; sm < sigmode + NSIG ; sm++) {
- if (*sm == S_IGN)
+ if (*sm == S_IGN) {
*sm = S_HARD_IGN;
+ VTRACE(DBG_TRAP, ("SHELLPROC: %d -> hard_ign\n",
+ (sm - sigmode) + 1));
+ }
}
+ INTON;
}
#endif
@@ -499,13 +591,23 @@ onsig(int signo)
CTRACE(DBG_SIG, ("Signal %d, had: pending %d, gotsig[%d]=%d\n",
signo, pendingsigs, signo, gotsig[signo]));
+ /* This should not be needed.
signal(signo, onsig);
+ */
+
if (signo == SIGINT && trap[SIGINT] == NULL) {
onint();
return;
}
- gotsig[signo] = 1;
- pendingsigs++;
+
+ /*
+ * if the signal will do nothing, no point reporting it
+ */
+ if (trap[signo] != NULL && trap[signo][0] != '\0' &&
+ signo != SIGCHLD) {
+ gotsig[signo] = 1;
+ pendingsigs++;
+ }
}
@@ -519,29 +621,50 @@ void
dotrap(void)
{
int i;
- int savestatus;
char *tr;
+ int savestatus;
+ struct skipsave saveskip;
+ in_dotrap++;
+
+ CTRACE(DBG_TRAP, ("dotrap[%d]: %d pending, traps %sinvalid\n",
+ in_dotrap, pendingsigs, traps_invalid ? "" : "not "));
for (;;) {
+ pendingsigs = 0;
for (i = 1 ; ; i++) {
- if (i >= NSIG) {
- pendingsigs = 0;
+ if (i >= NSIG)
return;
- }
if (gotsig[i])
break;
}
gotsig[i] = 0;
- savestatus=exitstatus;
- CTRACE(DBG_TRAP|DBG_SIG, ("dotrap %d: \"%s\"\n", i,
- trap[i] ? trap[i] : "-NULL-"));
- if ((tr = trap[i]) != NULL) {
+
+ if (traps_invalid)
+ continue;
+
+ tr = trap[i];
+
+ CTRACE(DBG_TRAP|DBG_SIG, ("dotrap %d: %s%s%s\n", i,
+ tr ? "\"" : "", tr ? tr : "NULL", tr ? "\"" : ""));
+
+ if (tr != NULL) {
+ last_trapsig = i;
+ save_skipstate(&saveskip);
+ savestatus = exitstatus;
+
tr = savestr(tr); /* trap code may free trap[i] */
evalstring(tr, 0);
ckfree(tr);
+
+ if (current_skipstate() == SKIPNONE ||
+ saveskip.state != SKIPNONE) {
+ restore_skipstate(&saveskip);
+ exitstatus = savestatus;
+ }
}
- exitstatus=savestatus;
}
+
+ in_dotrap--;
}
int
@@ -578,33 +701,78 @@ setinteractive(int on)
/*
* Called to exit the shell.
*/
-
void
exitshell(int status)
{
- struct jmploc loc1, loc2;
+ CTRACE(DBG_ERRS|DBG_PROCS|DBG_CMDS|DBG_TRAP,
+ ("pid %d: exitshell(%d)\n", getpid(), status));
+
+ exiting = 1;
+ exiting_status = status;
+ exitshell_savedstatus();
+}
+
+void
+exitshell_savedstatus(void)
+{
+ struct jmploc loc;
char *p;
+ volatile int sig = 0;
+ int s;
+ sigset_t sigs;
CTRACE(DBG_ERRS|DBG_PROCS|DBG_CMDS|DBG_TRAP,
- ("pid %d, exitshell(%d)\n", getpid(), status));
-
- if (setjmp(loc1.loc)) {
- goto l1;
- }
- if (setjmp(loc2.loc)) {
- goto l2;
- }
- handler = &loc1;
- if ((p = trap[0]) != NULL && *p != '\0') {
- trap[0] = NULL;
- VTRACE(DBG_TRAP, ("exit trap: \"%s\"\n", p));
- evalstring(p, 0);
+ ("pid %d: exitshell_savedstatus()%s $?=%d xs=%d dt=%d ts=%d\n",
+ getpid(), exiting ? " exiting" : "", exitstatus,
+ exiting_status, in_dotrap, last_trapsig));
+
+ if (!exiting) {
+ if (in_dotrap && last_trapsig) {
+ sig = last_trapsig;
+ exiting_status = sig + 128;
+ } else
+ exiting_status = exitstatus;
+ }
+ exitstatus = exiting_status;
+
+ if (!setjmp(loc.loc)) {
+ handler = &loc;
+
+ if (!traps_invalid && (p = trap[0]) != NULL && *p != '\0') {
+ reset_eval();
+ trap[0] = NULL;
+ VTRACE(DBG_TRAP, ("exit trap: \"%s\"\n", p));
+ evalstring(p, 0);
+ }
}
- l1: handler = &loc2; /* probably unnecessary */
- flushall();
+
+ INTOFF; /* we're done, no more interrupts. */
+
+ if (!setjmp(loc.loc)) {
+ handler = &loc; /* probably unnecessary */
+ flushall();
#if JOBS
- setjobctl(0);
+ setjobctl(0);
#endif
- l2: _exit(status);
+ }
+
+ if ((s = sig) != 0 && s != SIGSTOP && s != SIGTSTP && s != SIGTTIN &&
+ s != SIGTTOU) {
+ struct rlimit nocore;
+
+ /*
+ * if the signal is of the core dump variety, don't...
+ */
+ nocore.rlim_cur = nocore.rlim_max = 0;
+ (void) setrlimit(RLIMIT_CORE, &nocore);
+
+ signal(s, SIG_DFL);
+ sigemptyset(&sigs);
+ sigaddset(&sigs, s);
+ sigprocmask(SIG_UNBLOCK, &sigs, NULL);
+
+ kill(getpid(), s);
+ }
+ _exit(exiting_status);
/* NOTREACHED */
}
Index: src/bin/sh/trap.h
diff -u src/bin/sh/trap.h:1.23 src/bin/sh/trap.h:1.24
--- src/bin/sh/trap.h:1.23 Sun Aug 19 23:50:27 2018
+++ src/bin/sh/trap.h Mon Dec 3 06:43:19 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: trap.h,v 1.23 2018/08/19 23:50:27 kre Exp $ */
+/* $NetBSD: trap.h,v 1.24 2018/12/03 06:43:19 kre Exp $ */
/*-
* Copyright (c) 1991, 1993
@@ -36,12 +36,17 @@
extern volatile int pendingsigs;
+extern int traps_invalid;
+
void clear_traps(int);
+void free_traps(void);
int have_traps(void);
-sig_t setsignal(int, int);
+void setsignal(int, int);
void ignoresig(int, int);
void onsig(int);
void dotrap(void);
+char *child_trap(void);
void setinteractive(int);
void exitshell(int) __dead;
+void exitshell_savedstatus(void) __dead;
int lastsig(void);