aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libbb.h3
-rw-r--r--libbb/lineedit.c4
-rw-r--r--shell/ash.c91
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};
2045line_input_t *new_line_input_t(int flags) FAST_FUNC; 2048line_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 */
872static void raise_interrupt(void) NORETURN; 870static void raise_interrupt(void) IF_NOT_PLATFORM_MINGW32(NORETURN);
873static void 871static void
874raise_interrupt(void) 872raise_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)
4820static BOOL WINAPI ctrl_handler(DWORD dwCtrlType) 4825static 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() 10195static void
10196dotrap(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 }