diff options
-rw-r--r-- | include/libbb.h | 3 | ||||
-rw-r--r-- | libbb/lineedit.c | 4 | ||||
-rw-r--r-- | shell/ash.c | 91 |
3 files changed, 88 insertions, 10 deletions
diff --git a/include/libbb.h b/include/libbb.h index 4276bae61..2841d7fbf 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -2040,6 +2040,9 @@ enum { | |||
2040 | VI_MODE = 8 * ENABLE_FEATURE_EDITING_VI, | 2040 | VI_MODE = 8 * ENABLE_FEATURE_EDITING_VI, |
2041 | WITH_PATH_LOOKUP = 0x10, | 2041 | WITH_PATH_LOOKUP = 0x10, |
2042 | LI_INTERRUPTIBLE = 0x20, | 2042 | LI_INTERRUPTIBLE = 0x20, |
2043 | #if ENABLE_PLATFORM_MINGW32 | ||
2044 | IGNORE_CTRL_C = 0x40, | ||
2045 | #endif | ||
2043 | FOR_SHELL = DO_HISTORY | TAB_COMPLETION | USERNAME_COMPLETION | LI_INTERRUPTIBLE, | 2046 | FOR_SHELL = DO_HISTORY | TAB_COMPLETION | USERNAME_COMPLETION | LI_INTERRUPTIBLE, |
2044 | }; | 2047 | }; |
2045 | line_input_t *new_line_input_t(int flags) FAST_FUNC; | 2048 | line_input_t *new_line_input_t(int flags) FAST_FUNC; |
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 9220ddeb3..45d4c33f5 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c | |||
@@ -3030,6 +3030,10 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman | |||
3030 | && ic_raw == initial_settings.c_cc[VINTR] | 3030 | && ic_raw == initial_settings.c_cc[VINTR] |
3031 | ) { | 3031 | ) { |
3032 | /* Ctrl-C (usually) - stop gathering input */ | 3032 | /* Ctrl-C (usually) - stop gathering input */ |
3033 | #if ENABLE_PLATFORM_MINGW32 | ||
3034 | if (state->flags & IGNORE_CTRL_C) | ||
3035 | break; | ||
3036 | #endif | ||
3033 | command_len = 0; | 3037 | command_len = 0; |
3034 | break_out = -1; /* "do not append '\n'" */ | 3038 | break_out = -1; /* "do not append '\n'" */ |
3035 | break; | 3039 | break; |
diff --git a/shell/ash.c b/shell/ash.c index d15a6f685..a748b003f 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -627,8 +627,8 @@ struct globals_misc { | |||
627 | 627 | ||
628 | /* indicates specified signal received */ | 628 | /* indicates specified signal received */ |
629 | uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */ | 629 | uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */ |
630 | uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */ | ||
631 | #endif | 630 | #endif |
631 | uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */ | ||
632 | char *trap[NSIG + 1]; | 632 | char *trap[NSIG + 1]; |
633 | /* trap[0] is EXIT trap, trap[NTRAP_ERR] is ERR trap, other trap[i] are signal traps */ | 633 | /* trap[0] is EXIT trap, trap[NTRAP_ERR] is ERR trap, other trap[i] are signal traps */ |
634 | #define NTRAP_ERR NSIG | 634 | #define NTRAP_ERR NSIG |
@@ -687,10 +687,8 @@ extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc; | |||
687 | #if ENABLE_PLATFORM_MINGW32 | 687 | #if ENABLE_PLATFORM_MINGW32 |
688 | #undef got_sigchld | 688 | #undef got_sigchld |
689 | #undef pending_sig | 689 | #undef pending_sig |
690 | #undef may_have_traps | ||
691 | #undef trap_ptr | 690 | #undef trap_ptr |
692 | #define pending_sig (0) | 691 | #define pending_sig (0) |
693 | #define may_have_traps (0) | ||
694 | #define trap_ptr trap | 692 | #define trap_ptr trap |
695 | #endif | 693 | #endif |
696 | 694 | ||
@@ -869,10 +867,17 @@ raise_exception(int e) | |||
869 | * are held using the INT_OFF macro. (The test for iflag is just | 867 | * are held using the INT_OFF macro. (The test for iflag is just |
870 | * defensive programming.) | 868 | * defensive programming.) |
871 | */ | 869 | */ |
872 | static void raise_interrupt(void) NORETURN; | 870 | static void raise_interrupt(void) IF_NOT_PLATFORM_MINGW32(NORETURN); |
873 | static void | 871 | static void |
874 | raise_interrupt(void) | 872 | raise_interrupt(void) |
875 | { | 873 | { |
874 | #if ENABLE_PLATFORM_MINGW32 | ||
875 | /* Contrary to the comment above on Windows raise_interrupt() is | ||
876 | * called when SIGINT is trapped or ignored. We detect this here | ||
877 | * and return without doing anything. */ | ||
878 | if (trap[SIGINT]) | ||
879 | return; | ||
880 | #endif | ||
876 | pending_int = 0; | 881 | pending_int = 0; |
877 | #if !ENABLE_PLATFORM_MINGW32 | 882 | #if !ENABLE_PLATFORM_MINGW32 |
878 | /* Signal is not automatically unmasked after it is raised, | 883 | /* Signal is not automatically unmasked after it is raised, |
@@ -4820,8 +4825,11 @@ sprint_status48(char *os, int status, int sigonly) | |||
4820 | static BOOL WINAPI ctrl_handler(DWORD dwCtrlType) | 4825 | static BOOL WINAPI ctrl_handler(DWORD dwCtrlType) |
4821 | { | 4826 | { |
4822 | if (dwCtrlType == CTRL_C_EVENT || dwCtrlType == CTRL_BREAK_EVENT) { | 4827 | if (dwCtrlType == CTRL_C_EVENT || dwCtrlType == CTRL_BREAK_EVENT) { |
4823 | if (!suppress_int && !(rootshell && iflag)) | 4828 | # if ENABLE_FEATURE_EDITING |
4824 | raise_interrupt(); /* does not return */ | 4829 | bb_got_signal = SIGINT; /* for read_line_input: "we got a signal" */ |
4830 | # endif | ||
4831 | if (!suppress_int) | ||
4832 | raise_interrupt(); | ||
4825 | pending_int = 1; | 4833 | pending_int = 1; |
4826 | return TRUE; | 4834 | return TRUE; |
4827 | } | 4835 | } |
@@ -10184,7 +10192,43 @@ dotrap(void) | |||
10184 | TRACE(("dotrap returns\n")); | 10192 | TRACE(("dotrap returns\n")); |
10185 | } | 10193 | } |
10186 | #else | 10194 | #else |
10187 | # define dotrap() | 10195 | static void |
10196 | dotrap(void) | ||
10197 | { | ||
10198 | int status, last_status; | ||
10199 | char *p; | ||
10200 | |||
10201 | if (!pending_int) | ||
10202 | return; | ||
10203 | |||
10204 | status = savestatus; | ||
10205 | last_status = status; | ||
10206 | if (status < 0) { | ||
10207 | status = exitstatus; | ||
10208 | savestatus = status; | ||
10209 | } | ||
10210 | pending_int = 0; | ||
10211 | barrier(); | ||
10212 | |||
10213 | TRACE(("dotrap entered\n")); | ||
10214 | if (evalskip) { | ||
10215 | pending_int = 1; | ||
10216 | return; | ||
10217 | } | ||
10218 | |||
10219 | p = trap[SIGINT]; | ||
10220 | if (p) { | ||
10221 | TRACE(("sig %d is active, will run handler '%s'\n", SIGINT, p)); | ||
10222 | trap_depth++; | ||
10223 | evalstring(p, 0); | ||
10224 | trap_depth--; | ||
10225 | if (evalskip != SKIPFUNC) | ||
10226 | exitstatus = status; | ||
10227 | } | ||
10228 | |||
10229 | savestatus = last_status; | ||
10230 | TRACE(("dotrap returns\n")); | ||
10231 | } | ||
10188 | #endif | 10232 | #endif |
10189 | 10233 | ||
10190 | /* forward declarations - evaluation is fairly recursive business... */ | 10234 | /* forward declarations - evaluation is fairly recursive business... */ |
@@ -11853,8 +11897,13 @@ preadfd(void) | |||
11853 | */ | 11897 | */ |
11854 | # else | 11898 | # else |
11855 | raise_interrupt(); | 11899 | raise_interrupt(); |
11900 | write(STDOUT_FILENO, "^C\n", 3); | ||
11856 | # endif | 11901 | # endif |
11857 | if (trap[SIGINT]) { | 11902 | if (trap[SIGINT]) { |
11903 | # if ENABLE_PLATFORM_MINGW32 | ||
11904 | pending_int = 1; | ||
11905 | dotrap(); | ||
11906 | # endif | ||
11858 | empty_line_input: | 11907 | empty_line_input: |
11859 | buf[0] = '\n'; | 11908 | buf[0] = '\n'; |
11860 | buf[1] = '\0'; | 11909 | buf[1] = '\0'; |
@@ -15088,12 +15137,30 @@ trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
15088 | } | 15137 | } |
15089 | free(trap[signo]); | 15138 | free(trap[signo]); |
15090 | trap[signo] = action; | 15139 | trap[signo] = action; |
15140 | #if ENABLE_PLATFORM_MINGW32 | ||
15141 | if (signo == SIGINT) { | ||
15142 | // trap '' INT disables Ctrl-C, anything else enables it | ||
15143 | if (action && action[0] == '\0') { | ||
15144 | SetConsoleCtrlHandler(NULL, TRUE); | ||
15145 | if (line_input_state) { | ||
15146 | line_input_state->flags |= IGNORE_CTRL_C; | ||
15147 | } | ||
15148 | } else { | ||
15149 | SetConsoleCtrlHandler(NULL, FALSE); | ||
15150 | if (line_input_state) { | ||
15151 | line_input_state->flags &= ~IGNORE_CTRL_C; | ||
15152 | } | ||
15153 | } | ||
15154 | } | ||
15155 | #else | ||
15091 | if (signo != 0 && signo < NSIG) | 15156 | if (signo != 0 && signo < NSIG) |
15092 | setsignal(signo); | 15157 | setsignal(signo); |
15158 | #endif | ||
15093 | INT_ON; | 15159 | INT_ON; |
15094 | next: | 15160 | next: |
15095 | ap++; | 15161 | ap++; |
15096 | } | 15162 | } |
15163 | may_have_traps = trap[SIGINT] && trap[SIGINT][0] != '\0'; | ||
15097 | return exitcode; | 15164 | return exitcode; |
15098 | } | 15165 | } |
15099 | 15166 | ||
@@ -15391,10 +15458,14 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
15391 | #if ENABLE_PLATFORM_MINGW32 | 15458 | #if ENABLE_PLATFORM_MINGW32 |
15392 | if ((uintptr_t)r == 2) { | 15459 | if ((uintptr_t)r == 2) { |
15393 | /* ^C pressed, propagate event */ | 15460 | /* ^C pressed, propagate event */ |
15394 | if (iflag) { | 15461 | if (trap[SIGINT]) { |
15462 | write(STDOUT_FILENO, "^C", 2); | ||
15463 | pending_int = 1; | ||
15464 | dotrap(); | ||
15465 | goto again; | ||
15466 | } else if (iflag) { | ||
15395 | raise_interrupt(); | 15467 | raise_interrupt(); |
15396 | } | 15468 | } else { |
15397 | else { | ||
15398 | GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); | 15469 | GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); |
15399 | exitshell(); | 15470 | exitshell(); |
15400 | } | 15471 | } |