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-w32-b8709032a3fb57b3ec536bdf9b92b526ed63b995.tar.gz busybox-w32-b8709032a3fb57b3ec536bdf9b92b526ed63b995.tar.bz2 busybox-w32-b8709032a3fb57b3ec536bdf9b92b526ed63b995.zip |
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) | |||
1319 | * "echo $$; sleep 5 & wait; ls -l" + "kill -INT <pid>" | 1319 | * "echo $$; sleep 5 & wait; ls -l" + "kill -INT <pid>" |
1320 | * Example 3: this does not wait 5 sec, but executes ls: | 1320 | * Example 3: this does not wait 5 sec, but executes ls: |
1321 | * "sleep 5; ls -l" + press ^C | 1321 | * "sleep 5; ls -l" + press ^C |
1322 | * Example 4: this does not wait and does not execute ls: | ||
1323 | * "sleep 5 & wait; ls -l" + press ^C | ||
1322 | * | 1324 | * |
1323 | * (What happens to signals which are IGN on shell start?) | 1325 | * (What happens to signals which are IGN on shell start?) |
1324 | * (What happens with signal mask on shell start?) | 1326 | * (What happens with signal mask on shell start?) |
@@ -1471,13 +1473,13 @@ static int check_and_run_traps(int sig) | |||
1471 | int last_sig = 0; | 1473 | int last_sig = 0; |
1472 | 1474 | ||
1473 | if (sig) | 1475 | if (sig) |
1474 | goto jump_in; | 1476 | goto got_sig; |
1477 | |||
1475 | while (1) { | 1478 | while (1) { |
1476 | sig = sigtimedwait(&G.blocked_set, NULL, &zero_timespec); | 1479 | sig = sigtimedwait(&G.blocked_set, NULL, &zero_timespec); |
1477 | if (sig <= 0) | 1480 | if (sig <= 0) |
1478 | break; | 1481 | break; |
1479 | jump_in: | 1482 | got_sig: |
1480 | last_sig = sig; | ||
1481 | if (G.traps && G.traps[sig]) { | 1483 | if (G.traps && G.traps[sig]) { |
1482 | if (G.traps[sig][0]) { | 1484 | if (G.traps[sig][0]) { |
1483 | /* We have user-defined handler */ | 1485 | /* We have user-defined handler */ |
@@ -1488,6 +1490,7 @@ static int check_and_run_traps(int sig) | |||
1488 | save_rcode = G.last_exitcode; | 1490 | save_rcode = G.last_exitcode; |
1489 | builtin_eval(argv); | 1491 | builtin_eval(argv); |
1490 | G.last_exitcode = save_rcode; | 1492 | G.last_exitcode = save_rcode; |
1493 | last_sig = sig; | ||
1491 | } /* else: "" trap, ignoring signal */ | 1494 | } /* else: "" trap, ignoring signal */ |
1492 | continue; | 1495 | continue; |
1493 | } | 1496 | } |
@@ -1503,6 +1506,7 @@ static int check_and_run_traps(int sig) | |||
1503 | /* Builtin was ^C'ed, make it look prettier: */ | 1506 | /* Builtin was ^C'ed, make it look prettier: */ |
1504 | bb_putchar('\n'); | 1507 | bb_putchar('\n'); |
1505 | G.flag_SIGINT = 1; | 1508 | G.flag_SIGINT = 1; |
1509 | last_sig = sig; | ||
1506 | break; | 1510 | break; |
1507 | #if ENABLE_HUSH_JOB | 1511 | #if ENABLE_HUSH_JOB |
1508 | case SIGHUP: { | 1512 | case SIGHUP: { |
@@ -1521,6 +1525,11 @@ static int check_and_run_traps(int sig) | |||
1521 | #endif | 1525 | #endif |
1522 | default: /* ignored: */ | 1526 | default: /* ignored: */ |
1523 | /* SIGTERM, SIGQUIT, SIGTTIN, SIGTTOU, SIGTSTP */ | 1527 | /* SIGTERM, SIGQUIT, SIGTTIN, SIGTTOU, SIGTSTP */ |
1528 | /* note: | ||
1529 | * we dont do 'last_sig = sig' here -> NOT returning this sig. | ||
1530 | * example: wait is not interrupted by TERM | ||
1531 | * in interactive shell, because TERM is ignored. | ||
1532 | */ | ||
1524 | break; | 1533 | break; |
1525 | } | 1534 | } |
1526 | } | 1535 | } |
@@ -1921,11 +1930,18 @@ static void get_user_input(struct in_str *i) | |||
1921 | # else | 1930 | # else |
1922 | do { | 1931 | do { |
1923 | G.flag_SIGINT = 0; | 1932 | G.flag_SIGINT = 0; |
1924 | fputs(prompt_str, stdout); | 1933 | if (i->last_char == '\0' || i->last_char == '\n') { |
1934 | /* Why check_and_run_traps here? Try this interactively: | ||
1935 | * $ trap 'echo INT' INT; (sleep 2; kill -INT $$) & | ||
1936 | * $ <[enter], repeatedly...> | ||
1937 | * Without check_and_run_traps, handler never runs. | ||
1938 | */ | ||
1939 | check_and_run_traps(0); | ||
1940 | fputs(prompt_str, stdout); | ||
1941 | } | ||
1925 | fflush_all(); | 1942 | fflush_all(); |
1926 | G.user_input_buf[0] = r = fgetc(i->file); | 1943 | G.user_input_buf[0] = r = fgetc(i->file); |
1927 | /*G.user_input_buf[1] = '\0'; - already is and never changed */ | 1944 | /*G.user_input_buf[1] = '\0'; - already is and never changed */ |
1928 | //do we need check_and_run_traps(0)? (maybe only if stdin) | ||
1929 | } while (G.flag_SIGINT); | 1945 | } while (G.flag_SIGINT); |
1930 | i->eof_flag = (r == EOF); | 1946 | i->eof_flag = (r == EOF); |
1931 | # endif | 1947 | # endif |
@@ -3322,6 +3338,7 @@ static char *fetch_till_str(o_string *as_string, | |||
3322 | int ch; | 3338 | int ch; |
3323 | 3339 | ||
3324 | goto jump_in; | 3340 | goto jump_in; |
3341 | |||
3325 | while (1) { | 3342 | while (1) { |
3326 | ch = i_getch(input); | 3343 | ch = i_getch(input); |
3327 | if (ch != EOF) | 3344 | if (ch != EOF) |