summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko2011-05-08 21:20:01 +0200
committerDenys Vlasenko2011-05-08 21:20:01 +0200
commitb8709032a3fb57b3ec536bdf9b92b526ed63b995 (patch)
tree2dea5e1de762aa127a3bb5b031ff1f2704fbf4fb
parent29c54aa9f9e8eedf2d227550a790e76661ce63ad (diff)
downloadbusybox-b8709032a3fb57b3ec536bdf9b92b526ed63b995.zip
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.c27
1 files changed, 22 insertions, 5 deletions
diff --git a/shell/hush.c b/shell/hush.c
index d3e957c..bcd4584 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)