Skip to content

Commit

Permalink
trap: Preserve parent traps for trap-only command substitution
Browse files Browse the repository at this point in the history
Traps are reset when a subshell is started.  When a subshell is
started for command substitution with a simple command whose first
word is "trap", preserve the parent trap text so that they can be
printed.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
  • Loading branch information
herbertx committed Apr 28, 2024
1 parent 7a11b3e commit 94b1e82
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 20 deletions.
4 changes: 2 additions & 2 deletions src/eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -491,11 +491,11 @@ evalsubshell(union node *n, int flags)
expredir(n->nredir.redirect);
INTOFF;
if (!backgnd && flags & EV_EXIT && !have_traps()) {
forkreset();
forkreset(NULL);
goto nofork;
}
jp = makejob(1);
if (forkshell(jp, n, backgnd) == 0) {
if (forkshell(jp, n->nredir.n, backgnd) == 0) {
flags |= EV_EXIT;
if (backgnd)
flags &=~ EV_TESTED;
Expand Down
4 changes: 3 additions & 1 deletion src/init.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@
* @(#)init.h 8.2 (Berkeley) 5/4/95
*/

union node;

void init(void);
void exitreset(void);
void forkreset(void);
void forkreset(union node *);
void reset(void);
2 changes: 1 addition & 1 deletion src/jobs.c
Original file line number Diff line number Diff line change
Expand Up @@ -872,7 +872,7 @@ static void forkchild(struct job *jp, union node *n, int mode)
if (!lvforked) {
shlvl++;

forkreset();
forkreset(mode == FORK_NOJOB ? n : NULL);

#if JOBS
/* do job control only in root shell */
Expand Down
5 changes: 3 additions & 2 deletions src/mkinit.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ struct event {
char *name; /* name of event (e.g. INIT) */
char *routine; /* name of routine called on event */
char *comment; /* comment describing routine */
char *args; /* arguments to routine */
struct text code; /* code for handling event */
};

Expand Down Expand Up @@ -128,7 +129,7 @@ char reset[] = "\
struct event event[] = {
{"INIT", "init", init},
{"EXITRESET", "exitreset", exitreset},
{"FORKRESET", "forkreset", forkreset},
{"FORKRESET", "forkreset", forkreset, "union node *n"},
{"RESET", "reset", reset},
{NULL, NULL}
};
Expand Down Expand Up @@ -388,7 +389,7 @@ output(void)
for (ep = event ; ep->name ; ep++) {
fputs("\n\n\n", fp);
fputs(ep->comment, fp);
fprintf(fp, "\nvoid\n%s() {\n", ep->routine);
fprintf(fp, "\nvoid\n%s(%s) {\n", ep->routine, ep->args ?: "");
writetext(&ep->code, fp);
fprintf(fp, "}\n");
}
Expand Down
57 changes: 43 additions & 14 deletions src/trap.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@


/* trap handler commands */
MKINIT char *trap[NSIG];
static char *trap[NSIG];
/* traps have not been fully cleared */
static int ptrap;
/* number of non-null traps */
int trapcnt;
/* current value of signal */
Expand All @@ -81,6 +83,7 @@ volatile sig_atomic_t gotsigchld;
extern char *signal_names[];

static int decode_signum(const char *);
MKINIT void clear_traps(union node *);

#ifdef mkinit
INCLUDE "memalloc.h"
Expand All @@ -92,19 +95,7 @@ INIT {
}

FORKRESET {
char **tp;

INTOFF;
for (tp = trap ; tp < &trap[NSIG] ; tp++) {
if (*tp && **tp) { /* trap not NULL or SIG_IGN */
ckfree(*tp);
*tp = NULL;
if (tp != &trap[0])
setsignal(tp - trap);
}
}
trapcnt = 0;
INTON;
clear_traps(n);
}
#endif

Expand Down Expand Up @@ -133,6 +124,8 @@ trapcmd(int argc, char **argv)
}
return 0;
}
if (ptrap)
clear_traps(NULL);
if (!ap[1] || decode_signum(*ap) >= 0)
action = NULL;
else
Expand Down Expand Up @@ -168,6 +161,40 @@ trapcmd(int argc, char **argv)



/*
* Clear traps on a fork.
*/

void clear_traps(union node *n)
{
int simplecmd;
char **tp;

simplecmd = n && n->type == NCMD && n->ncmd.args &&
equal(n->ncmd.args->narg.text, "trap");

INTOFF;
for (tp = trap ; tp < &trap[NSIG] ; tp++) {
if (*tp && **tp) { /* trap not NULL or SIG_IGN */
char *otp = *tp;

*tp = NULL;
if (tp != &trap[0])
setsignal(tp - trap);

if (simplecmd)
*tp = otp;
else
ckfree(*tp);
}
}
trapcnt = 0;
ptrap = simplecmd;
INTON;
}



/*
* Set the signal handler for the specified signal. The routine figures
* out what it should be set to.
Expand Down Expand Up @@ -390,6 +417,8 @@ exitshell(void)
handler = &loc;
if ((p = trap[0])) {
trap[0] = NULL;
if (ptrap)
goto out;
evalskip = 0;
evalstring(p, 0);
evalskip = SKIPFUNCDEF;
Expand Down

0 comments on commit 94b1e82

Please sign in to comment.