diff options
author | Ron Yorston <rmy@pobox.com> | 2020-02-17 08:51:09 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2020-02-17 08:51:09 +0000 |
commit | 56d1d4639c705537a8661ff0005392b82b0ee039 (patch) | |
tree | 80634fd2384a461fdb203752eb483a0e51b0ac5e | |
parent | e4446487d16118ebfcc88b168607073385a71e8a (diff) | |
parent | 3f4847b6d9198a359e98933271af4630b3c41f0a (diff) | |
download | busybox-w32-56d1d4639c705537a8661ff0005392b82b0ee039.tar.gz busybox-w32-56d1d4639c705537a8661ff0005392b82b0ee039.tar.bz2 busybox-w32-56d1d4639c705537a8661ff0005392b82b0ee039.zip |
Merge branch 'busybox' into merge
-rw-r--r-- | shell/ash.c | 95 | ||||
-rw-r--r-- | shell/ash_test/ash-misc/exitcode_trap1.right | 2 | ||||
-rwxr-xr-x | shell/ash_test/ash-misc/exitcode_trap1.tests | 6 |
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 | ||
874 | static void | 877 | static void |
@@ -4572,12 +4575,11 @@ fg_bgcmd(int argc UNUSED_PARAM, char **argv) | |||
4572 | #endif | 4575 | #endif |
4573 | 4576 | ||
4574 | static int | 4577 | static int |
4575 | sprint_status48(char *s, int status, int sigonly) | 4578 | sprint_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 | ||
11554 | static int | ||
11555 | pgetc_top(struct synstack *stack) | ||
11556 | { | ||
11557 | return stack->syntax == SQSYNTAX ? pgetc() : pgetc_eatbnl(); | ||
11558 | } | ||
11559 | |||
11543 | static void | 11560 | static void |
11544 | synstack_push(struct synstack **stack, struct synstack *next, int syntax) | 11561 | synstack_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 @@ | |||
1 | Trapped | ||
2 | One: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 | ) | ||
6 | echo One:$? | ||