diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2020-02-14 17:27:18 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2020-02-16 19:14:45 +0100 |
commit | 4ccddc8fb37b7f585c2d62f6e61ad17295399aff (patch) | |
tree | 5a7b60334c1be7f7d32ca7d589b4171fc1eea28a /shell/ash.c | |
parent | f7eea8c235dea6699a21c7b26c218e6c0dc1bf95 (diff) | |
download | busybox-w32-4ccddc8fb37b7f585c2d62f6e61ad17295399aff.tar.gz busybox-w32-4ccddc8fb37b7f585c2d62f6e61ad17295399aff.tar.bz2 busybox-w32-4ccddc8fb37b7f585c2d62f6e61ad17295399aff.zip |
ash: [BUILTIN] Exit without arguments in a trap should use status outside traps
Upstream commit:
Date: Mon Oct 6 10:39:47 2014 +0800
[BUILTIN] Exit without arguments in a trap should use status outside traps
POSIX now requires that exit without arguments in a trap should
return the last command status prior to executing traps. This
patch implements this behaviour.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell/ash.c')
-rw-r--r-- | shell/ash.c | 43 |
1 files changed, 30 insertions, 13 deletions
diff --git a/shell/ash.c b/shell/ash.c index a300061a2..270a338d9 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -384,6 +384,7 @@ struct globals_misc { | |||
384 | uint8_t exitstatus; /* exit status of last command */ | 384 | uint8_t exitstatus; /* exit status of last command */ |
385 | uint8_t back_exitstatus;/* exit status of backquoted command */ | 385 | uint8_t back_exitstatus;/* exit status of backquoted command */ |
386 | smallint job_warning; /* user was warned about stopped jobs (can be 2, 1 or 0). */ | 386 | smallint job_warning; /* user was warned about stopped jobs (can be 2, 1 or 0). */ |
387 | int savestatus; /* exit status of last command outside traps */ | ||
387 | int rootpid; /* pid of main shell */ | 388 | int rootpid; /* pid of main shell */ |
388 | /* shell level: 0 for the main shell, 1 for its children, and so on */ | 389 | /* shell level: 0 for the main shell, 1 for its children, and so on */ |
389 | int shlvl; | 390 | int shlvl; |
@@ -466,6 +467,7 @@ extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc; | |||
466 | #define exitstatus (G_misc.exitstatus ) | 467 | #define exitstatus (G_misc.exitstatus ) |
467 | #define back_exitstatus (G_misc.back_exitstatus ) | 468 | #define back_exitstatus (G_misc.back_exitstatus ) |
468 | #define job_warning (G_misc.job_warning) | 469 | #define job_warning (G_misc.job_warning) |
470 | #define savestatus (G_misc.savestatus ) | ||
469 | #define rootpid (G_misc.rootpid ) | 471 | #define rootpid (G_misc.rootpid ) |
470 | #define shlvl (G_misc.shlvl ) | 472 | #define shlvl (G_misc.shlvl ) |
471 | #define errlinno (G_misc.errlinno ) | 473 | #define errlinno (G_misc.errlinno ) |
@@ -491,6 +493,7 @@ extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc; | |||
491 | #define INIT_G_misc() do { \ | 493 | #define INIT_G_misc() do { \ |
492 | (*(struct globals_misc**)not_const_pp(&ash_ptr_to_globals_misc)) = xzalloc(sizeof(G_misc)); \ | 494 | (*(struct globals_misc**)not_const_pp(&ash_ptr_to_globals_misc)) = xzalloc(sizeof(G_misc)); \ |
493 | barrier(); \ | 495 | barrier(); \ |
496 | savestatus = -1; \ | ||
494 | curdir = nullstr; \ | 497 | curdir = nullstr; \ |
495 | physdir = nullstr; \ | 498 | physdir = nullstr; \ |
496 | trap_ptr = trap; \ | 499 | trap_ptr = trap; \ |
@@ -9055,12 +9058,17 @@ dotrap(void) | |||
9055 | { | 9058 | { |
9056 | uint8_t *g; | 9059 | uint8_t *g; |
9057 | int sig; | 9060 | int sig; |
9058 | uint8_t last_status; | 9061 | int status, last_status; |
9059 | 9062 | ||
9060 | if (!pending_sig) | 9063 | if (!pending_sig) |
9061 | return; | 9064 | return; |
9062 | 9065 | ||
9063 | last_status = exitstatus; | 9066 | status = savestatus; |
9067 | last_status = status; | ||
9068 | if (status < 0) { | ||
9069 | status = exitstatus; | ||
9070 | savestatus = status; | ||
9071 | } | ||
9064 | pending_sig = 0; | 9072 | pending_sig = 0; |
9065 | barrier(); | 9073 | barrier(); |
9066 | 9074 | ||
@@ -9087,8 +9095,10 @@ dotrap(void) | |||
9087 | if (!p) | 9095 | if (!p) |
9088 | continue; | 9096 | continue; |
9089 | evalstring(p, 0); | 9097 | evalstring(p, 0); |
9098 | exitstatus = status; | ||
9090 | } | 9099 | } |
9091 | exitstatus = last_status; | 9100 | |
9101 | savestatus = last_status; | ||
9092 | TRACE(("dotrap returns\n")); | 9102 | TRACE(("dotrap returns\n")); |
9093 | } | 9103 | } |
9094 | 9104 | ||
@@ -13416,8 +13426,15 @@ exitcmd(int argc UNUSED_PARAM, char **argv) | |||
13416 | { | 13426 | { |
13417 | if (stoppedjobs()) | 13427 | if (stoppedjobs()) |
13418 | return 0; | 13428 | return 0; |
13419 | if (argv[1]) | 13429 | |
13420 | exitstatus = number(argv[1]); | 13430 | if (argv[1]) { |
13431 | int status = number(argv[1]); | ||
13432 | |||
13433 | exitstatus = status; | ||
13434 | if (savestatus >= 0) | ||
13435 | savestatus = status; | ||
13436 | } | ||
13437 | |||
13421 | raise_exception(EXEXIT); | 13438 | raise_exception(EXEXIT); |
13422 | /* NOTREACHED */ | 13439 | /* NOTREACHED */ |
13423 | } | 13440 | } |
@@ -14077,19 +14094,15 @@ exitshell(void) | |||
14077 | { | 14094 | { |
14078 | struct jmploc loc; | 14095 | struct jmploc loc; |
14079 | char *p; | 14096 | char *p; |
14080 | int status; | ||
14081 | 14097 | ||
14082 | #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT | 14098 | #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT |
14083 | if (line_input_state) | 14099 | if (line_input_state) |
14084 | save_history(line_input_state); | 14100 | save_history(line_input_state); |
14085 | #endif | 14101 | #endif |
14086 | status = exitstatus; | 14102 | savestatus = exitstatus; |
14087 | TRACE(("pid %d, exitshell(%d)\n", getpid(), status)); | 14103 | TRACE(("pid %d, exitshell(%d)\n", getpid(), savestatus)); |
14088 | if (setjmp(loc.loc)) { | 14104 | if (setjmp(loc.loc)) |
14089 | if (exception_type == EXEXIT) | ||
14090 | status = exitstatus; | ||
14091 | goto out; | 14105 | goto out; |
14092 | } | ||
14093 | exception_handler = &loc; | 14106 | exception_handler = &loc; |
14094 | p = trap[0]; | 14107 | p = trap[0]; |
14095 | if (p) { | 14108 | if (p) { |
@@ -14104,7 +14117,7 @@ exitshell(void) | |||
14104 | */ | 14117 | */ |
14105 | setjobctl(0); | 14118 | setjobctl(0); |
14106 | flush_stdout_stderr(); | 14119 | flush_stdout_stderr(); |
14107 | _exit(status); | 14120 | _exit(savestatus); |
14108 | /* NOTREACHED */ | 14121 | /* NOTREACHED */ |
14109 | } | 14122 | } |
14110 | 14123 | ||
@@ -14280,6 +14293,10 @@ reset(void) | |||
14280 | /* from eval.c: */ | 14293 | /* from eval.c: */ |
14281 | evalskip = 0; | 14294 | evalskip = 0; |
14282 | loopnest = 0; | 14295 | loopnest = 0; |
14296 | if (savestatus >= 0) { | ||
14297 | exitstatus = savestatus; | ||
14298 | savestatus = -1; | ||
14299 | } | ||
14283 | 14300 | ||
14284 | /* from expand.c: */ | 14301 | /* from expand.c: */ |
14285 | ifsfree(); | 14302 | ifsfree(); |