summaryrefslogtreecommitdiffstats
path: root/bin/sh/trap.c
diff options
context:
space:
mode:
Diffstat (limited to 'bin/sh/trap.c')
-rw-r--r--bin/sh/trap.c27
1 files changed, 23 insertions, 4 deletions
diff --git a/bin/sh/trap.c b/bin/sh/trap.c
index d2e5308..048c75c 100644
--- a/bin/sh/trap.c
+++ b/bin/sh/trap.c
@@ -79,6 +79,7 @@ static volatile sig_atomic_t gotsig[NSIG];
/* indicates specified signal received */
static int ignore_sigchld; /* Used while handling SIGCHLD traps. */
volatile sig_atomic_t gotwinch;
+static int last_trapsig;
static int exiting; /* exitshell() has been called */
static int exiting_exitstatus; /* value passed to exitshell() */
@@ -441,6 +442,7 @@ dotrap(void)
*/
if (i == SIGCHLD)
ignore_sigchld++;
+ last_trapsig = i;
savestatus = exitstatus;
evalstring(trap[i], 0);
exitstatus = savestatus;
@@ -495,9 +497,16 @@ exitshell_savedstatus(void)
{
struct jmploc loc1, loc2;
char *p;
-
- if (!exiting)
- exiting_exitstatus = oexitstatus;
+ int sig = 0;
+ sigset_t sigs;
+
+ if (!exiting) {
+ if (in_dotrap && last_trapsig) {
+ sig = last_trapsig;
+ exiting_exitstatus = sig + 128;
+ } else
+ exiting_exitstatus = oexitstatus;
+ }
exitstatus = oexitstatus = exiting_exitstatus;
if (setjmp(loc1.loc)) {
goto l1;
@@ -515,5 +524,15 @@ l1: handler = &loc2; /* probably unnecessary */
#if JOBS
setjobctl(0);
#endif
-l2: _exit(exiting_exitstatus);
+l2:
+ if (sig != 0 && sig != SIGSTOP && sig != SIGTSTP && sig != SIGTTIN &&
+ sig != SIGTTOU) {
+ signal(sig, SIG_DFL);
+ sigemptyset(&sigs);
+ sigaddset(&sigs, sig);
+ sigprocmask(SIG_UNBLOCK, &sigs, NULL);
+ kill(getpid(), sig);
+ /* If the default action is to ignore, fall back to _exit(). */
+ }
+ _exit(exiting_exitstatus);
}
OpenPOWER on IntegriCloud