aboutsummaryrefslogtreecommitdiff
path: root/shell/ash.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2020-02-14 17:27:18 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2020-02-16 19:14:45 +0100
commit4ccddc8fb37b7f585c2d62f6e61ad17295399aff (patch)
tree5a7b60334c1be7f7d32ca7d589b4171fc1eea28a /shell/ash.c
parentf7eea8c235dea6699a21c7b26c218e6c0dc1bf95 (diff)
downloadbusybox-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.c43
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();