diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2011-05-08 21:20:01 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2011-05-08 21:20:01 +0200 |
commit | b8709032a3fb57b3ec536bdf9b92b526ed63b995 (patch) | |
tree | 2dea5e1de762aa127a3bb5b031ff1f2704fbf4fb | |
parent | 29c54aa9f9e8eedf2d227550a790e76661ce63ad (diff) | |
download | busybox-b8709032a3fb57b3ec536bdf9b92b526ed63b995.tar.gz |
hush: fix incorrect PS2 dispaly and trap handling while reading command
The fix affects only !ENABLE_FEATURE_EDITING configuration
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | shell/hush.c | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/shell/hush.c b/shell/hush.c index d3e957c2f..bcd458427 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -1319,6 +1319,8 @@ static void restore_G_args(save_arg_t *sv, char **argv) * "echo $$; sleep 5 & wait; ls -l" + "kill -INT <pid>" * Example 3: this does not wait 5 sec, but executes ls: * "sleep 5; ls -l" + press ^C + * Example 4: this does not wait and does not execute ls: + * "sleep 5 & wait; ls -l" + press ^C * * (What happens to signals which are IGN on shell start?) * (What happens with signal mask on shell start?) @@ -1471,13 +1473,13 @@ static int check_and_run_traps(int sig) int last_sig = 0; if (sig) - goto jump_in; + goto got_sig; + while (1) { sig = sigtimedwait(&G.blocked_set, NULL, &zero_timespec); if (sig <= 0) break; - jump_in: - last_sig = sig; + got_sig: if (G.traps && G.traps[sig]) { if (G.traps[sig][0]) { /* We have user-defined handler */ @@ -1488,6 +1490,7 @@ static int check_and_run_traps(int sig) save_rcode = G.last_exitcode; builtin_eval(argv); G.last_exitcode = save_rcode; + last_sig = sig; } /* else: "" trap, ignoring signal */ continue; } @@ -1503,6 +1506,7 @@ static int check_and_run_traps(int sig) /* Builtin was ^C'ed, make it look prettier: */ bb_putchar('\n'); G.flag_SIGINT = 1; + last_sig = sig; break; #if ENABLE_HUSH_JOB case SIGHUP: { @@ -1521,6 +1525,11 @@ static int check_and_run_traps(int sig) #endif default: /* ignored: */ /* SIGTERM, SIGQUIT, SIGTTIN, SIGTTOU, SIGTSTP */ + /* note: + * we dont do 'last_sig = sig' here -> NOT returning this sig. + * example: wait is not interrupted by TERM + * in interactive shell, because TERM is ignored. + */ break; } } @@ -1921,11 +1930,18 @@ static void get_user_input(struct in_str *i) # else do { G.flag_SIGINT = 0; - fputs(prompt_str, stdout); + if (i->last_char == '\0' || i->last_char == '\n') { + /* Why check_and_run_traps here? Try this interactively: + * $ trap 'echo INT' INT; (sleep 2; kill -INT $$) & + * $ <[enter], repeatedly...> + * Without check_and_run_traps, handler never runs. + */ + check_and_run_traps(0); + fputs(prompt_str, stdout); + } fflush_all(); G.user_input_buf[0] = r = fgetc(i->file); /*G.user_input_buf[1] = '\0'; - already is and never changed */ -//do we need check_and_run_traps(0)? (maybe only if stdin) } while (G.flag_SIGINT); i->eof_flag = (r == EOF); # endif @@ -3322,6 +3338,7 @@ static char *fetch_till_str(o_string *as_string, int ch; goto jump_in; + while (1) { ch = i_getch(input); if (ch != EOF) |