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>
This commit is contained in:
Denys Vlasenko 2011-05-08 21:20:01 +02:00
parent 29c54aa9f9
commit b8709032a3

View File

@ -1319,6 +1319,8 @@ static void restore_G_args(save_arg_t *sv, char **argv)
* "echo $$; sleep 5 & wait; ls -l" + "kill -INT <pid>" * "echo $$; sleep 5 & wait; ls -l" + "kill -INT <pid>"
* Example 3: this does not wait 5 sec, but executes ls: * Example 3: this does not wait 5 sec, but executes ls:
* "sleep 5; ls -l" + press ^C * "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 to signals which are IGN on shell start?)
* (What happens with signal mask 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; int last_sig = 0;
if (sig) if (sig)
goto jump_in; goto got_sig;
while (1) { while (1) {
sig = sigtimedwait(&G.blocked_set, NULL, &zero_timespec); sig = sigtimedwait(&G.blocked_set, NULL, &zero_timespec);
if (sig <= 0) if (sig <= 0)
break; break;
jump_in: got_sig:
last_sig = sig;
if (G.traps && G.traps[sig]) { if (G.traps && G.traps[sig]) {
if (G.traps[sig][0]) { if (G.traps[sig][0]) {
/* We have user-defined handler */ /* We have user-defined handler */
@ -1488,6 +1490,7 @@ static int check_and_run_traps(int sig)
save_rcode = G.last_exitcode; save_rcode = G.last_exitcode;
builtin_eval(argv); builtin_eval(argv);
G.last_exitcode = save_rcode; G.last_exitcode = save_rcode;
last_sig = sig;
} /* else: "" trap, ignoring signal */ } /* else: "" trap, ignoring signal */
continue; continue;
} }
@ -1503,6 +1506,7 @@ static int check_and_run_traps(int sig)
/* Builtin was ^C'ed, make it look prettier: */ /* Builtin was ^C'ed, make it look prettier: */
bb_putchar('\n'); bb_putchar('\n');
G.flag_SIGINT = 1; G.flag_SIGINT = 1;
last_sig = sig;
break; break;
#if ENABLE_HUSH_JOB #if ENABLE_HUSH_JOB
case SIGHUP: { case SIGHUP: {
@ -1521,6 +1525,11 @@ static int check_and_run_traps(int sig)
#endif #endif
default: /* ignored: */ default: /* ignored: */
/* SIGTERM, SIGQUIT, SIGTTIN, SIGTTOU, SIGTSTP */ /* 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; break;
} }
} }
@ -1921,11 +1930,18 @@ static void get_user_input(struct in_str *i)
# else # else
do { do {
G.flag_SIGINT = 0; G.flag_SIGINT = 0;
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); fputs(prompt_str, stdout);
}
fflush_all(); fflush_all();
G.user_input_buf[0] = r = fgetc(i->file); G.user_input_buf[0] = r = fgetc(i->file);
/*G.user_input_buf[1] = '\0'; - already is and never changed */ /*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); } while (G.flag_SIGINT);
i->eof_flag = (r == EOF); i->eof_flag = (r == EOF);
# endif # endif
@ -3322,6 +3338,7 @@ static char *fetch_till_str(o_string *as_string,
int ch; int ch;
goto jump_in; goto jump_in;
while (1) { while (1) {
ch = i_getch(input); ch = i_getch(input);
if (ch != EOF) if (ch != EOF)