hush: fix incorrect PS2 dispaly and trap handling while reading command
authorDenys Vlasenko <vda.linux@googlemail.com>
Sun, 8 May 2011 19:20:01 +0000 (21:20 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Sun, 8 May 2011 19:20:01 +0000 (21:20 +0200)
The fix affects only !ENABLE_FEATURE_EDITING configuration

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
shell/hush.c

index d3e957c2f2c8ea0490796c19da391ba4534acc01..bcd4584270218fadcaee15dc10da9ca71a12f595 100644 (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>"
  *    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)