diff options
author | Ron Yorston <rmy@pobox.com> | 2022-02-09 09:03:18 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2022-02-09 09:05:39 +0000 |
commit | 492d0a7492a57fe8f02c766e25960b0ce0d88759 (patch) | |
tree | 4f5764a5c2250c031ea05e9aeacbb40d7971f493 /shell | |
parent | 4734416a21312488a5099a297907783bee4ccc22 (diff) | |
parent | caa9c4f707b661cf398f2c2d66f54f5b0d8adfe2 (diff) | |
download | busybox-w32-492d0a7492a57fe8f02c766e25960b0ce0d88759.tar.gz busybox-w32-492d0a7492a57fe8f02c766e25960b0ce0d88759.tar.bz2 busybox-w32-492d0a7492a57fe8f02c766e25960b0ce0d88759.zip |
Merge busybox into merge
Fix conflicts in reset and ash.
Redefine the new safe_read_key() as a reference to read_key().
Disable SHA256_HWACCEL.
Diffstat (limited to 'shell')
-rw-r--r-- | shell/ash.c | 48 | ||||
-rw-r--r-- | shell/hush.c | 79 | ||||
-rw-r--r-- | shell/shell_common.c | 1 |
3 files changed, 90 insertions, 38 deletions
diff --git a/shell/ash.c b/shell/ash.c index a1d01447a..46c4f1675 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -428,7 +428,7 @@ static void forkshell_print(FILE *fp0, struct forkshell *fs, const char **notes) | |||
428 | /* ============ Shell options */ | 428 | /* ============ Shell options */ |
429 | 429 | ||
430 | /* If you add/change options hare, update --help text too */ | 430 | /* If you add/change options hare, update --help text too */ |
431 | static const char *const optletters_optnames[] = { | 431 | static const char *const optletters_optnames[] ALIGN_PTR = { |
432 | "e" "errexit", | 432 | "e" "errexit", |
433 | "f" "noglob", | 433 | "f" "noglob", |
434 | /* bash has '-o ignoreeof', but no short synonym -I for it */ | 434 | /* bash has '-o ignoreeof', but no short synonym -I for it */ |
@@ -845,7 +845,7 @@ raise_exception(int e) | |||
845 | /* | 845 | /* |
846 | * Called when a SIGINT is received. (If the user specifies | 846 | * Called when a SIGINT is received. (If the user specifies |
847 | * that SIGINT is to be trapped or ignored using the trap builtin, then | 847 | * that SIGINT is to be trapped or ignored using the trap builtin, then |
848 | * this routine is not called.) Suppressint is nonzero when interrupts | 848 | * this routine is not called.) suppress_int is nonzero when interrupts |
849 | * are held using the INT_OFF macro. (The test for iflag is just | 849 | * are held using the INT_OFF macro. (The test for iflag is just |
850 | * defensive programming.) | 850 | * defensive programming.) |
851 | */ | 851 | */ |
@@ -882,13 +882,12 @@ raise_interrupt(void) | |||
882 | } while (0) | 882 | } while (0) |
883 | #endif | 883 | #endif |
884 | 884 | ||
885 | static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void | 885 | static IF_NOT_ASH_OPTIMIZE_FOR_SIZE(inline) void |
886 | int_on(void) | 886 | int_on(void) |
887 | { | 887 | { |
888 | barrier(); | 888 | barrier(); |
889 | if (--suppress_int == 0 && pending_int) { | 889 | if (--suppress_int == 0 && pending_int) |
890 | raise_interrupt(); | 890 | raise_interrupt(); |
891 | } | ||
892 | } | 891 | } |
893 | #if DEBUG_INTONOFF | 892 | #if DEBUG_INTONOFF |
894 | # define INT_ON do { \ | 893 | # define INT_ON do { \ |
@@ -898,7 +897,7 @@ int_on(void) | |||
898 | #else | 897 | #else |
899 | # define INT_ON int_on() | 898 | # define INT_ON int_on() |
900 | #endif | 899 | #endif |
901 | static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void | 900 | static IF_NOT_ASH_OPTIMIZE_FOR_SIZE(inline) void |
902 | force_int_on(void) | 901 | force_int_on(void) |
903 | { | 902 | { |
904 | barrier(); | 903 | barrier(); |
@@ -4143,7 +4142,9 @@ signal_handler(int signo) | |||
4143 | if (!trap[SIGCHLD]) | 4142 | if (!trap[SIGCHLD]) |
4144 | return; | 4143 | return; |
4145 | } | 4144 | } |
4146 | 4145 | #if ENABLE_FEATURE_EDITING | |
4146 | bb_got_signal = signo; /* for read_line_input: "we got a signal" */ | ||
4147 | #endif | ||
4147 | gotsig[signo - 1] = 1; | 4148 | gotsig[signo - 1] = 1; |
4148 | pending_sig = signo; | 4149 | pending_sig = signo; |
4149 | 4150 | ||
@@ -11656,33 +11657,56 @@ preadfd(void) | |||
11656 | # endif | 11657 | # endif |
11657 | reinit_unicode_for_ash(); | 11658 | reinit_unicode_for_ash(); |
11658 | again: | 11659 | again: |
11660 | /* For shell, LI_INTERRUPTIBLE is set: | ||
11661 | * read_line_input will abort on either | ||
11662 | * getting EINTR in poll(), or if it sees bb_got_signal != 0 | ||
11663 | * (IOW: if signal arrives before poll() is reached). | ||
11664 | * Interactive testcases: | ||
11665 | * (while kill -INT $$; do sleep 1; done) & | ||
11666 | * #^^^ prints ^C, prints prompt, repeats | ||
11667 | * trap 'echo I' int; (while kill -INT $$; do sleep 1; done) & | ||
11668 | * #^^^ prints ^C, prints "I", prints prompt, repeats | ||
11669 | * trap 'echo T' term; (while kill $$; do sleep 1; done) & | ||
11670 | * #^^^ prints "T", prints prompt, repeats | ||
11671 | * #(bash 5.0.17 exits after first "T", looks like a bug) | ||
11672 | */ | ||
11673 | bb_got_signal = 0; | ||
11674 | INT_OFF; /* no longjmp'ing out of read_line_input please */ | ||
11659 | nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ); | 11675 | nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ); |
11676 | if (bb_got_signal == SIGINT) | ||
11677 | write(STDOUT_FILENO, "^C\n", 3); | ||
11678 | INT_ON; /* here non-blocked SIGINT will longjmp */ | ||
11660 | if (nr == 0) { | 11679 | if (nr == 0) { |
11661 | /* ^C pressed, "convert" to SIGINT */ | 11680 | /* ^C pressed, "convert" to SIGINT */ |
11662 | # if !ENABLE_PLATFORM_MINGW32 | 11681 | # if !ENABLE_PLATFORM_MINGW32 |
11663 | write(STDOUT_FILENO, "^C", 2); | 11682 | write(STDOUT_FILENO, "^C\n", 3); |
11664 | raise(SIGINT); | 11683 | raise(SIGINT); /* here non-blocked SIGINT will longjmp */ |
11665 | /* raise(SIGINT) did not work! (e.g. if SIGINT | 11684 | /* raise(SIGINT) did not work! (e.g. if SIGINT |
11666 | * is SIG_INGed on startup, it stays SIG_IGNed) | 11685 | * is SIG_IGNed on startup, it stays SIG_IGNed) |
11667 | */ | 11686 | */ |
11668 | # else | 11687 | # else |
11669 | raise_interrupt(); | 11688 | raise_interrupt(); |
11670 | # endif | 11689 | # endif |
11671 | if (trap[SIGINT]) { | 11690 | if (trap[SIGINT]) { |
11691 | empty_line_input: | ||
11672 | buf[0] = '\n'; | 11692 | buf[0] = '\n'; |
11673 | buf[1] = '\0'; | 11693 | buf[1] = '\0'; |
11674 | return 1; | 11694 | return 1; |
11675 | } | 11695 | } |
11676 | exitstatus = 128 + SIGINT; | 11696 | exitstatus = 128 + SIGINT; |
11677 | /* bash behavior on ^C + ignored SIGINT: */ | 11697 | /* bash behavior on ^C + ignored SIGINT: */ |
11678 | write(STDOUT_FILENO, "\n", 1); | ||
11679 | goto again; | 11698 | goto again; |
11680 | } | 11699 | } |
11681 | if (nr < 0) { | 11700 | if (nr < 0) { |
11682 | if (errno == 0) { | 11701 | if (errno == 0) { |
11683 | /* Ctrl+D pressed */ | 11702 | /* ^D pressed */ |
11684 | nr = 0; | 11703 | nr = 0; |
11685 | } | 11704 | } |
11705 | else if (errno == EINTR) { /* got signal? */ | ||
11706 | if (bb_got_signal != SIGINT) | ||
11707 | write(STDOUT_FILENO, "\n", 1); | ||
11708 | goto empty_line_input; | ||
11709 | } | ||
11686 | # if ENABLE_ASH_IDLE_TIMEOUT | 11710 | # if ENABLE_ASH_IDLE_TIMEOUT |
11687 | else if (errno == EAGAIN && timeout > 0) { | 11711 | else if (errno == EAGAIN && timeout > 0) { |
11688 | puts("\007timed out waiting for input: auto-logout"); | 11712 | puts("\007timed out waiting for input: auto-logout"); |
diff --git a/shell/hush.c b/shell/hush.c index 982fc356a..ae81f0da5 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -564,7 +564,7 @@ enum { | |||
564 | #define NULL_O_STRING { NULL } | 564 | #define NULL_O_STRING { NULL } |
565 | 565 | ||
566 | #ifndef debug_printf_parse | 566 | #ifndef debug_printf_parse |
567 | static const char *const assignment_flag[] = { | 567 | static const char *const assignment_flag[] ALIGN_PTR = { |
568 | "MAYBE_ASSIGNMENT", | 568 | "MAYBE_ASSIGNMENT", |
569 | "DEFINITELY_ASSIGNMENT", | 569 | "DEFINITELY_ASSIGNMENT", |
570 | "NOT_ASSIGNMENT", | 570 | "NOT_ASSIGNMENT", |
@@ -918,6 +918,7 @@ struct globals { | |||
918 | #if ENABLE_HUSH_INTERACTIVE | 918 | #if ENABLE_HUSH_INTERACTIVE |
919 | smallint promptmode; /* 0: PS1, 1: PS2 */ | 919 | smallint promptmode; /* 0: PS1, 1: PS2 */ |
920 | #endif | 920 | #endif |
921 | /* set by signal handler if SIGINT is received _and_ its trap is not set */ | ||
921 | smallint flag_SIGINT; | 922 | smallint flag_SIGINT; |
922 | #if ENABLE_HUSH_LOOPS | 923 | #if ENABLE_HUSH_LOOPS |
923 | smallint flag_break_continue; | 924 | smallint flag_break_continue; |
@@ -1944,6 +1945,9 @@ enum { | |||
1944 | static void record_pending_signo(int sig) | 1945 | static void record_pending_signo(int sig) |
1945 | { | 1946 | { |
1946 | sigaddset(&G.pending_set, sig); | 1947 | sigaddset(&G.pending_set, sig); |
1948 | #if ENABLE_FEATURE_EDITING | ||
1949 | bb_got_signal = sig; /* for read_line_input: "we got a signal" */ | ||
1950 | #endif | ||
1947 | #if ENABLE_HUSH_FAST | 1951 | #if ENABLE_HUSH_FAST |
1948 | if (sig == SIGCHLD) { | 1952 | if (sig == SIGCHLD) { |
1949 | G.count_SIGCHLD++; | 1953 | G.count_SIGCHLD++; |
@@ -2652,30 +2656,53 @@ static int get_user_input(struct in_str *i) | |||
2652 | for (;;) { | 2656 | for (;;) { |
2653 | reinit_unicode_for_hush(); | 2657 | reinit_unicode_for_hush(); |
2654 | G.flag_SIGINT = 0; | 2658 | G.flag_SIGINT = 0; |
2655 | /* buglet: SIGINT will not make new prompt to appear _at once_, | 2659 | |
2656 | * only after <Enter>. (^C works immediately) */ | 2660 | bb_got_signal = 0; |
2657 | r = read_line_input(G.line_input_state, prompt_str, | 2661 | if (!sigisemptyset(&G.pending_set)) { |
2662 | /* Whoops, already got a signal, do not call read_line_input */ | ||
2663 | bb_got_signal = r = -1; | ||
2664 | } else { | ||
2665 | /* For shell, LI_INTERRUPTIBLE is set: | ||
2666 | * read_line_input will abort on either | ||
2667 | * getting EINTR in poll(), or if it sees bb_got_signal != 0 | ||
2668 | * (IOW: if signal arrives before poll() is reached). | ||
2669 | * Interactive testcases: | ||
2670 | * (while kill -INT $$; do sleep 1; done) & | ||
2671 | * #^^^ prints ^C, prints prompt, repeats | ||
2672 | * trap 'echo I' int; (while kill -INT $$; do sleep 1; done) & | ||
2673 | * #^^^ prints ^C, prints "I", prints prompt, repeats | ||
2674 | * trap 'echo T' term; (while kill $$; do sleep 1; done) & | ||
2675 | * #^^^ prints "T", prints prompt, repeats | ||
2676 | * #(bash 5.0.17 exits after first "T", looks like a bug) | ||
2677 | */ | ||
2678 | r = read_line_input(G.line_input_state, prompt_str, | ||
2658 | G.user_input_buf, CONFIG_FEATURE_EDITING_MAX_LEN-1 | 2679 | G.user_input_buf, CONFIG_FEATURE_EDITING_MAX_LEN-1 |
2659 | ); | 2680 | ); |
2660 | /* read_line_input intercepts ^C, "convert" it to SIGINT */ | 2681 | /* read_line_input intercepts ^C, "convert" it to SIGINT */ |
2661 | if (r == 0) { | 2682 | if (r == 0) |
2662 | raise(SIGINT); | 2683 | raise(SIGINT); |
2684 | } | ||
2685 | /* bash prints ^C (before running a trap, if any) | ||
2686 | * both on keyboard ^C and on real SIGINT (non-kbd generated). | ||
2687 | */ | ||
2688 | if (sigismember(&G.pending_set, SIGINT)) { | ||
2689 | write(STDOUT_FILENO, "^C\n", 3); | ||
2690 | G.last_exitcode = 128 | SIGINT; | ||
2663 | } | 2691 | } |
2664 | check_and_run_traps(); | 2692 | check_and_run_traps(); |
2665 | if (r != 0 && !G.flag_SIGINT) | 2693 | if (r == 0) /* keyboard ^C? */ |
2694 | continue; /* go back, read another input line */ | ||
2695 | if (r > 0) /* normal input? (no ^C, no ^D, no signals) */ | ||
2666 | break; | 2696 | break; |
2667 | /* ^C or SIGINT: repeat */ | 2697 | if (!bb_got_signal) { |
2668 | /* bash prints ^C even on real SIGINT (non-kbd generated) */ | 2698 | /* r < 0: ^D/EOF/error detected (but not signal) */ |
2669 | write(STDOUT_FILENO, "^C\n", 3); | 2699 | /* ^D on interactive input goes to next line before exiting: */ |
2670 | G.last_exitcode = 128 | SIGINT; | 2700 | write(STDOUT_FILENO, "\n", 1); |
2671 | } | 2701 | i->p = NULL; |
2672 | if (r < 0) { | 2702 | i->peek_buf[0] = r = EOF; |
2673 | /* EOF/error detected */ | 2703 | return r; |
2674 | /* ^D on interactive input goes to next line before exiting: */ | 2704 | } |
2675 | write(STDOUT_FILENO, "\n", 1); | 2705 | /* it was a signal: go back, read another input line */ |
2676 | i->p = NULL; | ||
2677 | i->peek_buf[0] = r = EOF; | ||
2678 | return r; | ||
2679 | } | 2706 | } |
2680 | i->p = G.user_input_buf; | 2707 | i->p = G.user_input_buf; |
2681 | return (unsigned char)*i->p++; | 2708 | return (unsigned char)*i->p++; |
@@ -3655,7 +3682,7 @@ static void free_pipe_list(struct pipe *pi) | |||
3655 | #ifndef debug_print_tree | 3682 | #ifndef debug_print_tree |
3656 | static void debug_print_tree(struct pipe *pi, int lvl) | 3683 | static void debug_print_tree(struct pipe *pi, int lvl) |
3657 | { | 3684 | { |
3658 | static const char *const PIPE[] = { | 3685 | static const char *const PIPE[] ALIGN_PTR = { |
3659 | [PIPE_SEQ] = "SEQ", | 3686 | [PIPE_SEQ] = "SEQ", |
3660 | [PIPE_AND] = "AND", | 3687 | [PIPE_AND] = "AND", |
3661 | [PIPE_OR ] = "OR" , | 3688 | [PIPE_OR ] = "OR" , |
@@ -3690,7 +3717,7 @@ static void debug_print_tree(struct pipe *pi, int lvl) | |||
3690 | [RES_XXXX ] = "XXXX" , | 3717 | [RES_XXXX ] = "XXXX" , |
3691 | [RES_SNTX ] = "SNTX" , | 3718 | [RES_SNTX ] = "SNTX" , |
3692 | }; | 3719 | }; |
3693 | static const char *const CMDTYPE[] = { | 3720 | static const char *const CMDTYPE[] ALIGN_PTR = { |
3694 | "{}", | 3721 | "{}", |
3695 | "()", | 3722 | "()", |
3696 | "[noglob]", | 3723 | "[noglob]", |
@@ -7632,7 +7659,7 @@ static int generate_stream_from_string(const char *s, pid_t *pid_p) | |||
7632 | if (is_prefixed_with(s, "trap") | 7659 | if (is_prefixed_with(s, "trap") |
7633 | && skip_whitespace(s + 4)[0] == '\0' | 7660 | && skip_whitespace(s + 4)[0] == '\0' |
7634 | ) { | 7661 | ) { |
7635 | static const char *const argv[] = { NULL, NULL }; | 7662 | static const char *const argv[] ALIGN_PTR = { NULL, NULL }; |
7636 | builtin_trap((char**)argv); | 7663 | builtin_trap((char**)argv); |
7637 | fflush_all(); /* important */ | 7664 | fflush_all(); /* important */ |
7638 | _exit(0); | 7665 | _exit(0); |
@@ -9799,7 +9826,7 @@ static int run_list(struct pipe *pi) | |||
9799 | static const char encoded_dollar_at[] ALIGN1 = { | 9826 | static const char encoded_dollar_at[] ALIGN1 = { |
9800 | SPECIAL_VAR_SYMBOL, '@' | 0x80, SPECIAL_VAR_SYMBOL, '\0' | 9827 | SPECIAL_VAR_SYMBOL, '@' | 0x80, SPECIAL_VAR_SYMBOL, '\0' |
9801 | }; /* encoded representation of "$@" */ | 9828 | }; /* encoded representation of "$@" */ |
9802 | static const char *const encoded_dollar_at_argv[] = { | 9829 | static const char *const encoded_dollar_at_argv[] ALIGN_PTR = { |
9803 | encoded_dollar_at, NULL | 9830 | encoded_dollar_at, NULL |
9804 | }; /* argv list with one element: "$@" */ | 9831 | }; /* argv list with one element: "$@" */ |
9805 | char **vals; | 9832 | char **vals; |
@@ -10361,7 +10388,7 @@ int hush_main(int argc, char **argv) | |||
10361 | //it ignores TERM: | 10388 | //it ignores TERM: |
10362 | // bash -i -c 'kill $$; echo ALIVE' | 10389 | // bash -i -c 'kill $$; echo ALIVE' |
10363 | // ALIVE | 10390 | // ALIVE |
10364 | //it resets SIG_INGed HUP to SIG_DFL: | 10391 | //it resets SIG_IGNed HUP to SIG_DFL: |
10365 | // trap '' hup; bash -i -c 'kill -hup $$; echo ALIVE' | 10392 | // trap '' hup; bash -i -c 'kill -hup $$; echo ALIVE' |
10366 | // Hangup [the message is not printed by bash, it's the shell which started it] | 10393 | // Hangup [the message is not printed by bash, it's the shell which started it] |
10367 | //is talkative about jobs and exiting: | 10394 | //is talkative about jobs and exiting: |
diff --git a/shell/shell_common.c b/shell/shell_common.c index fff356c04..399d5e684 100644 --- a/shell/shell_common.c +++ b/shell/shell_common.c | |||
@@ -218,6 +218,7 @@ shell_builtin_read(struct builtin_read_params *params) | |||
218 | */ | 218 | */ |
219 | errno = 0; | 219 | errno = 0; |
220 | pfd[0].events = POLLIN; | 220 | pfd[0].events = POLLIN; |
221 | //TODO race with a signal arriving just before the poll! | ||
221 | if (poll(pfd, 1, timeout) <= 0) { | 222 | if (poll(pfd, 1, timeout) <= 0) { |
222 | /* timed out, or EINTR */ | 223 | /* timed out, or EINTR */ |
223 | err = errno; | 224 | err = errno; |