aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2020-02-17 08:51:09 +0000
committerRon Yorston <rmy@pobox.com>2020-02-17 08:51:09 +0000
commit56d1d4639c705537a8661ff0005392b82b0ee039 (patch)
tree80634fd2384a461fdb203752eb483a0e51b0ac5e
parente4446487d16118ebfcc88b168607073385a71e8a (diff)
parent3f4847b6d9198a359e98933271af4630b3c41f0a (diff)
downloadbusybox-w32-56d1d4639c705537a8661ff0005392b82b0ee039.tar.gz
busybox-w32-56d1d4639c705537a8661ff0005392b82b0ee039.tar.bz2
busybox-w32-56d1d4639c705537a8661ff0005392b82b0ee039.zip
Merge branch 'busybox' into merge
-rw-r--r--shell/ash.c95
-rw-r--r--shell/ash_test/ash-misc/exitcode_trap1.right2
-rwxr-xr-xshell/ash_test/ash-misc/exitcode_trap1.tests6
3 files changed, 67 insertions, 36 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 29cdd38f6..c6eb930e4 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -501,6 +501,7 @@ struct globals_misc {
501 uint8_t exitstatus; /* exit status of last command */ 501 uint8_t exitstatus; /* exit status of last command */
502 uint8_t back_exitstatus;/* exit status of backquoted command */ 502 uint8_t back_exitstatus;/* exit status of backquoted command */
503 smallint job_warning; /* user was warned about stopped jobs (can be 2, 1 or 0). */ 503 smallint job_warning; /* user was warned about stopped jobs (can be 2, 1 or 0). */
504 int savestatus; /* exit status of last command outside traps */
504 int rootpid; /* pid of main shell */ 505 int rootpid; /* pid of main shell */
505 /* shell level: 0 for the main shell, 1 for its children, and so on */ 506 /* shell level: 0 for the main shell, 1 for its children, and so on */
506 int shlvl; 507 int shlvl;
@@ -606,6 +607,7 @@ extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc;
606#define exitstatus (G_misc.exitstatus ) 607#define exitstatus (G_misc.exitstatus )
607#define back_exitstatus (G_misc.back_exitstatus ) 608#define back_exitstatus (G_misc.back_exitstatus )
608#define job_warning (G_misc.job_warning) 609#define job_warning (G_misc.job_warning)
610#define savestatus (G_misc.savestatus )
609#define rootpid (G_misc.rootpid ) 611#define rootpid (G_misc.rootpid )
610#define shlvl (G_misc.shlvl ) 612#define shlvl (G_misc.shlvl )
611#define errlinno (G_misc.errlinno ) 613#define errlinno (G_misc.errlinno )
@@ -649,6 +651,7 @@ extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc;
649#define INIT_G_misc() do { \ 651#define INIT_G_misc() do { \
650 (*(struct globals_misc**)not_const_pp(&ash_ptr_to_globals_misc)) = xzalloc(sizeof(G_misc)); \ 652 (*(struct globals_misc**)not_const_pp(&ash_ptr_to_globals_misc)) = xzalloc(sizeof(G_misc)); \
651 barrier(); \ 653 barrier(); \
654 savestatus = -1; \
652 curdir = nullstr; \ 655 curdir = nullstr; \
653 physdir = nullstr; \ 656 physdir = nullstr; \
654 IF_NOT_PLATFORM_MINGW32(trap_ptr = trap;) \ 657 IF_NOT_PLATFORM_MINGW32(trap_ptr = trap;) \
@@ -868,7 +871,7 @@ fmtstr(char *outbuf, size_t length, const char *fmt, ...)
868 ret = vsnprintf(outbuf, length, fmt, ap); 871 ret = vsnprintf(outbuf, length, fmt, ap);
869 va_end(ap); 872 va_end(ap);
870 INT_ON; 873 INT_ON;
871 return ret; 874 return ret > (int)length ? length : ret;
872} 875}
873 876
874static void 877static void
@@ -4572,12 +4575,11 @@ fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4572#endif 4575#endif
4573 4576
4574static int 4577static int
4575sprint_status48(char *s, int status, int sigonly) 4578sprint_status48(char *os, int status, int sigonly)
4576{ 4579{
4577 int col; 4580 char *s = os;
4578 int st; 4581 int st;
4579 4582
4580 col = 0;
4581 if (!WIFEXITED(status)) { 4583 if (!WIFEXITED(status)) {
4582#if JOBS 4584#if JOBS
4583 if (WIFSTOPPED(status)) 4585 if (WIFSTOPPED(status))
@@ -4595,17 +4597,17 @@ sprint_status48(char *s, int status, int sigonly)
4595 } 4597 }
4596 st &= 0x7f; 4598 st &= 0x7f;
4597//TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata 4599//TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4598 col = fmtstr(s, 32, strsignal(st)); 4600 //s = stpncpy(s, strsignal(st), 32); //not all libc have stpncpy()
4601 s += fmtstr(s, 32, strsignal(st));
4599 if (WCOREDUMP(status)) { 4602 if (WCOREDUMP(status)) {
4600 strcpy(s + col, " (core dumped)"); 4603 s = stpcpy(s, " (core dumped)");
4601 col += sizeof(" (core dumped)")-1;
4602 } 4604 }
4603 } else if (!sigonly) { 4605 } else if (!sigonly) {
4604 st = WEXITSTATUS(status); 4606 st = WEXITSTATUS(status);
4605 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st); 4607 s += fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4606 } 4608 }
4607 out: 4609 out:
4608 return col; 4610 return s - os;
4609} 4611}
4610 4612
4611#if ENABLE_PLATFORM_MINGW32 4613#if ENABLE_PLATFORM_MINGW32
@@ -5291,7 +5293,8 @@ cmdputs(const char *s)
5291 str = "${"; 5293 str = "${";
5292 goto dostr; 5294 goto dostr;
5293 case CTLENDVAR: 5295 case CTLENDVAR:
5294 str = "\"}" + !(quoted & 1); 5296 str = "\"}";
5297 str += !(quoted & 1);
5295 quoted >>= 1; 5298 quoted >>= 1;
5296 subtype = 0; 5299 subtype = 0;
5297 goto dostr; 5300 goto dostr;
@@ -6959,7 +6962,7 @@ exptilde(char *startp, char *p, int flags)
6959 goto lose; 6962 goto lose;
6960 home = pw->pw_dir; 6963 home = pw->pw_dir;
6961 } 6964 }
6962 if (!home || !*home) 6965 if (!home)
6963 goto lose; 6966 goto lose;
6964 *p = c; 6967 *p = c;
6965 strtodest(home, SQSYNTAX, quotes); 6968 strtodest(home, SQSYNTAX, quotes);
@@ -8036,6 +8039,8 @@ evalvar(char *p, int flag)
8036 goto record; 8039 goto record;
8037 } 8040 }
8038 8041
8042 varlen = 0;
8043
8039 end: 8044 end:
8040 if (subtype != VSNORMAL) { /* skip to end of alternative */ 8045 if (subtype != VSNORMAL) { /* skip to end of alternative */
8041 int nesting = 1; 8046 int nesting = 1;
@@ -9697,12 +9702,17 @@ dotrap(void)
9697{ 9702{
9698 uint8_t *g; 9703 uint8_t *g;
9699 int sig; 9704 int sig;
9700 uint8_t last_status; 9705 int status, last_status;
9701 9706
9702 if (!pending_sig) 9707 if (!pending_sig)
9703 return; 9708 return;
9704 9709
9705 last_status = exitstatus; 9710 status = savestatus;
9711 last_status = status;
9712 if (status < 0) {
9713 status = exitstatus;
9714 savestatus = status;
9715 }
9706 pending_sig = 0; 9716 pending_sig = 0;
9707 barrier(); 9717 barrier();
9708 9718
@@ -9729,8 +9739,10 @@ dotrap(void)
9729 if (!p) 9739 if (!p)
9730 continue; 9740 continue;
9731 evalstring(p, 0); 9741 evalstring(p, 0);
9742 exitstatus = status;
9732 } 9743 }
9733 exitstatus = last_status; 9744
9745 savestatus = last_status;
9734 TRACE(("dotrap returns\n")); 9746 TRACE(("dotrap returns\n"));
9735} 9747}
9736#else 9748#else
@@ -10089,11 +10101,10 @@ expredir(union node *n)
10089 case NFROMFD: 10101 case NFROMFD:
10090 case NTOFD: /* >& */ 10102 case NTOFD: /* >& */
10091 if (redir->ndup.vname) { 10103 if (redir->ndup.vname) {
10092 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE); 10104 expandarg(redir->ndup.vname, &fn, EXP_TILDE | EXP_REDIR);
10093 if (fn.list == NULL) 10105 if (fn.list == NULL)
10094 ash_msg_and_raise_error("redir error"); 10106 ash_msg_and_raise_error("redir error");
10095#if BASH_REDIR_OUTPUT 10107#if BASH_REDIR_OUTPUT
10096//FIXME: we used expandarg with different args!
10097 if (!isdigit_str9(fn.list->text)) { 10108 if (!isdigit_str9(fn.list->text)) {
10098 /* >&file, not >&fd */ 10109 /* >&file, not >&fd */
10099 if (redir->nfile.fd != 1) /* 123>&file - BAD */ 10110 if (redir->nfile.fd != 1) /* 123>&file - BAD */
@@ -10620,7 +10631,7 @@ static const struct builtincmd builtintab[] = {
10620#if ENABLE_ASH_GETOPTS 10631#if ENABLE_ASH_GETOPTS
10621 { BUILTIN_REGULAR "getopts" , getoptscmd }, 10632 { BUILTIN_REGULAR "getopts" , getoptscmd },
10622#endif 10633#endif
10623 { BUILTIN_NOSPEC "hash" , hashcmd }, 10634 { BUILTIN_REGULAR "hash" , hashcmd },
10624#if ENABLE_ASH_HELP 10635#if ENABLE_ASH_HELP
10625 { BUILTIN_NOSPEC "help" , helpcmd }, 10636 { BUILTIN_NOSPEC "help" , helpcmd },
10626#endif 10637#endif
@@ -10638,7 +10649,7 @@ static const struct builtincmd builtintab[] = {
10638#if ENABLE_ASH_PRINTF 10649#if ENABLE_ASH_PRINTF
10639 { BUILTIN_REGULAR "printf" , printfcmd }, 10650 { BUILTIN_REGULAR "printf" , printfcmd },
10640#endif 10651#endif
10641 { BUILTIN_NOSPEC "pwd" , pwdcmd }, 10652 { BUILTIN_REGULAR "pwd" , pwdcmd },
10642 { BUILTIN_REGULAR "read" , readcmd }, 10653 { BUILTIN_REGULAR "read" , readcmd },
10643 { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd }, 10654 { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
10644 { BUILTIN_SPEC_REG "return" , returncmd }, 10655 { BUILTIN_SPEC_REG "return" , returncmd },
@@ -10653,8 +10664,8 @@ static const struct builtincmd builtintab[] = {
10653 { BUILTIN_SPEC_REG "times" , timescmd }, 10664 { BUILTIN_SPEC_REG "times" , timescmd },
10654 { BUILTIN_SPEC_REG "trap" , trapcmd }, 10665 { BUILTIN_SPEC_REG "trap" , trapcmd },
10655 { BUILTIN_REGULAR "true" , truecmd }, 10666 { BUILTIN_REGULAR "true" , truecmd },
10656 { BUILTIN_NOSPEC "type" , typecmd }, 10667 { BUILTIN_REGULAR "type" , typecmd },
10657 { BUILTIN_NOSPEC "ulimit" , ulimitcmd }, 10668 { BUILTIN_REGULAR "ulimit" , ulimitcmd },
10658 { BUILTIN_REGULAR "umask" , umaskcmd }, 10669 { BUILTIN_REGULAR "umask" , umaskcmd },
10659#if ENABLE_ASH_ALIAS 10670#if ENABLE_ASH_ALIAS
10660 { BUILTIN_REGULAR "unalias" , unaliascmd }, 10671 { BUILTIN_REGULAR "unalias" , unaliascmd },
@@ -11540,6 +11551,12 @@ struct synstack {
11540 struct synstack *next; 11551 struct synstack *next;
11541}; 11552};
11542 11553
11554static int
11555pgetc_top(struct synstack *stack)
11556{
11557 return stack->syntax == SQSYNTAX ? pgetc() : pgetc_eatbnl();
11558}
11559
11543static void 11560static void
11544synstack_push(struct synstack **stack, struct synstack *next, int syntax) 11561synstack_push(struct synstack **stack, struct synstack *next, int syntax)
11545{ 11562{
@@ -12930,7 +12947,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
12930 } 12947 }
12931 USTPUTC(c, out); 12948 USTPUTC(c, out);
12932 nlprompt(); 12949 nlprompt();
12933 c = pgetc(); 12950 c = pgetc_top(synstack);
12934 goto loop; /* continue outer loop */ 12951 goto loop; /* continue outer loop */
12935 case CWORD: 12952 case CWORD:
12936 USTPUTC(c, out); 12953 USTPUTC(c, out);
@@ -12962,8 +12979,6 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
12962 USTPUTC(CTLESC, out); 12979 USTPUTC(CTLESC, out);
12963 USTPUTC('\\', out); 12980 USTPUTC('\\', out);
12964 pungetc(); 12981 pungetc();
12965 } else if (c == '\n') {
12966 nlprompt();
12967 } else { 12982 } else {
12968 if (pssyntax && c == '$') { 12983 if (pssyntax && c == '$') {
12969 USTPUTC(CTLESC, out); 12984 USTPUTC(CTLESC, out);
@@ -13083,7 +13098,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
13083 IF_ASH_ALIAS(if (c != PEOA)) 13098 IF_ASH_ALIAS(if (c != PEOA))
13084 USTPUTC(c, out); 13099 USTPUTC(c, out);
13085 } 13100 }
13086 c = pgetc(); 13101 c = pgetc_top(synstack);
13087 } /* for (;;) */ 13102 } /* for (;;) */
13088 endword: 13103 endword:
13089 13104
@@ -13829,8 +13844,10 @@ parseheredoc(void)
13829 while (here) { 13844 while (here) {
13830 tokpushback = 0; 13845 tokpushback = 0;
13831 setprompt_if(needprompt, 2); 13846 setprompt_if(needprompt, 2);
13832 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX, 13847 if (here->here->type == NHERE)
13833 here->eofmark, here->striptabs); 13848 readtoken1(pgetc(), SQSYNTAX, here->eofmark, here->striptabs);
13849 else
13850 readtoken1(pgetc_eatbnl(), DQSYNTAX, here->eofmark, here->striptabs);
13834 n = stzalloc(sizeof(struct narg)); 13851 n = stzalloc(sizeof(struct narg));
13835 n->narg.type = NARG; 13852 n->narg.type = NARG;
13836 /*n->narg.next = NULL; - stzalloc did it */ 13853 /*n->narg.next = NULL; - stzalloc did it */
@@ -14026,8 +14043,12 @@ cmdloop(int top)
14026 if (!top || numeof >= 50) 14043 if (!top || numeof >= 50)
14027 break; 14044 break;
14028 if (!stoppedjobs()) { 14045 if (!stoppedjobs()) {
14029 if (!Iflag) 14046 if (!Iflag) {
14047 if (iflag) {
14048 newline_and_flush(stderr);
14049 }
14030 break; 14050 break;
14051 }
14031 out2str("\nUse \"exit\" to leave shell.\n"); 14052 out2str("\nUse \"exit\" to leave shell.\n");
14032 } 14053 }
14033 numeof++; 14054 numeof++;
@@ -14149,8 +14170,10 @@ exitcmd(int argc UNUSED_PARAM, char **argv)
14149{ 14170{
14150 if (stoppedjobs()) 14171 if (stoppedjobs())
14151 return 0; 14172 return 0;
14173
14152 if (argv[1]) 14174 if (argv[1])
14153 exitstatus = number(argv[1]); 14175 savestatus = number(argv[1]);
14176
14154 raise_exception(EXEXIT); 14177 raise_exception(EXEXIT);
14155 /* NOTREACHED */ 14178 /* NOTREACHED */
14156} 14179}
@@ -14837,19 +14860,15 @@ exitshell(void)
14837{ 14860{
14838 struct jmploc loc; 14861 struct jmploc loc;
14839 char *p; 14862 char *p;
14840 int status;
14841 14863
14842#if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT 14864#if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
14843 if (line_input_state) 14865 if (line_input_state)
14844 save_history(line_input_state); 14866 save_history(line_input_state);
14845#endif 14867#endif
14846 status = exitstatus; 14868 savestatus = exitstatus;
14847 TRACE(("pid %d, exitshell(%d)\n", getpid(), status)); 14869 TRACE(("pid %d, exitshell(%d)\n", getpid(), savestatus));
14848 if (setjmp(loc.loc)) { 14870 if (setjmp(loc.loc))
14849 if (exception_type == EXEXIT)
14850 status = exitstatus;
14851 goto out; 14871 goto out;
14852 }
14853 exception_handler = &loc; 14872 exception_handler = &loc;
14854 p = trap[0]; 14873 p = trap[0];
14855 if (p) { 14874 if (p) {
@@ -14864,7 +14883,7 @@ exitshell(void)
14864 */ 14883 */
14865 setjobctl(0); 14884 setjobctl(0);
14866 flush_stdout_stderr(); 14885 flush_stdout_stderr();
14867 _exit(status); 14886 _exit(savestatus);
14868 /* NOTREACHED */ 14887 /* NOTREACHED */
14869} 14888}
14870 14889
@@ -15135,6 +15154,10 @@ reset(void)
15135 /* from eval.c: */ 15154 /* from eval.c: */
15136 evalskip = 0; 15155 evalskip = 0;
15137 loopnest = 0; 15156 loopnest = 0;
15157 if (savestatus >= 0) {
15158 exitstatus = savestatus;
15159 savestatus = -1;
15160 }
15138 15161
15139 /* from expand.c: */ 15162 /* from expand.c: */
15140 ifsfree(); 15163 ifsfree();
diff --git a/shell/ash_test/ash-misc/exitcode_trap1.right b/shell/ash_test/ash-misc/exitcode_trap1.right
new file mode 100644
index 000000000..5f76f68da
--- /dev/null
+++ b/shell/ash_test/ash-misc/exitcode_trap1.right
@@ -0,0 +1,2 @@
1Trapped
2One:1
diff --git a/shell/ash_test/ash-misc/exitcode_trap1.tests b/shell/ash_test/ash-misc/exitcode_trap1.tests
new file mode 100755
index 000000000..c35b6b391
--- /dev/null
+++ b/shell/ash_test/ash-misc/exitcode_trap1.tests
@@ -0,0 +1,6 @@
1# "exit" in trap should not use last command's exitcode,
2# but exitcode on entering the trap.
3(trap "echo Trapped; exit" EXIT
4 (exit 1)
5)
6echo One:$?