From 15fb91cefb22d64952f34fe246fc8f257172af63 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Wed, 23 Nov 2016 18:31:48 +0100
Subject: test: make [ and [[ forms individually selectable

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 shell/ash.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'shell')

diff --git a/shell/ash.c b/shell/ash.c
index 87f2127a1..15246f55f 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -9282,9 +9282,9 @@ static const struct builtincmd builtintab[] = {
 	{ BUILTIN_SPEC_REG      ":"       , truecmd    },
 #if ENABLE_ASH_BUILTIN_TEST
 	{ BUILTIN_REGULAR       "["       , testcmd    },
-#if ENABLE_ASH_BASH_COMPAT
+# if ENABLE_ASH_BASH_COMPAT
 	{ BUILTIN_REGULAR       "[["      , testcmd    },
-#endif
+# endif
 #endif
 #if ENABLE_ASH_ALIAS
 	{ BUILTIN_REG_ASSG      "alias"   , aliascmd   },
-- 
cgit v1.2.3-55-g6feb


From 8660aeb3127416a53e0b2e43bb1a82907f468692 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Thu, 24 Nov 2016 17:44:02 +0100
Subject: ash,hush: ^C from command line should set $? to 128+SIGINT

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 shell/ash.c  |  1 +
 shell/hush.c | 26 +++++++++++++++++++++-----
 2 files changed, 22 insertions(+), 5 deletions(-)

(limited to 'shell')

diff --git a/shell/ash.c b/shell/ash.c
index 15246f55f..3e5a3b3e9 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -9876,6 +9876,7 @@ preadfd(void)
 				raise(SIGINT);
 				return 1;
 			}
+			exitstatus = 128 + SIGINT;
 			goto retry;
 		}
 		if (nr < 0) {
diff --git a/shell/hush.c b/shell/hush.c
index 2f07f4ac1..5b720ce98 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -1746,6 +1746,7 @@ static int check_and_run_traps(void)
 				argv[2] = NULL;
 				save_rcode = G.last_exitcode;
 				builtin_eval(argv);
+//FIXME: shouldn't it be set to 128 + sig instead?
 				G.last_exitcode = save_rcode;
 				last_sig = sig;
 			} /* else: "" trap, ignoring signal */
@@ -2192,7 +2193,7 @@ static int get_user_input(struct in_str *i)
 
 	prompt_str = setup_prompt_string(i->promptmode);
 # if ENABLE_FEATURE_EDITING
-	do {
+	for (;;) {
 		reinit_unicode_for_hush();
 		G.flag_SIGINT = 0;
 		/* buglet: SIGINT will not make new prompt to appear _at once_,
@@ -2201,9 +2202,15 @@ static int get_user_input(struct in_str *i)
 				G.user_input_buf, CONFIG_FEATURE_EDITING_MAX_LEN-1,
 				/*timeout*/ -1
 		);
-		/* catch *SIGINT* etc (^C is handled by read_line_input) */
+		/* read_line_input intercepts ^C, "convert" it into SIGINT */
+		if (r == 0)
+			raise(SIGINT);
 		check_and_run_traps();
-	} while (r == 0 || G.flag_SIGINT); /* repeat if ^C or SIGINT */
+		if (r != 0 && !G.flag_SIGINT)
+			break;
+		/* ^C or SIGINT: repeat */
+		G.last_exitcode = 128 + SIGINT;
+	}
 	if (r < 0) {
 		/* EOF/error detected */
 		i->p = NULL;
@@ -2213,7 +2220,7 @@ static int get_user_input(struct in_str *i)
 	i->p = G.user_input_buf;
 	return (unsigned char)*i->p++;
 # else
-	do {
+	for (;;) {
 		G.flag_SIGINT = 0;
 		if (i->last_char == '\0' || i->last_char == '\n') {
 			/* Why check_and_run_traps here? Try this interactively:
@@ -2226,7 +2233,16 @@ static int get_user_input(struct in_str *i)
 		}
 		fflush_all();
 		r = fgetc(i->file);
-	} while (G.flag_SIGINT || r == '\0');
+		/* In !ENABLE_FEATURE_EDITING we don't use read_line_input,
+		 * no ^C masking happens during fgetc, no special code for ^C:
+		 * it generates SIGINT as usual.
+		 */
+		check_and_run_traps();
+		if (G.flag_SIGINT)
+			G.last_exitcode = 128 + SIGINT;
+		if (r != '\0')
+			break;
+	}
 	return r;
 # endif
 }
-- 
cgit v1.2.3-55-g6feb


From 4b89d512b1215e7b9d619af03496540d30cbbd1a Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Fri, 25 Nov 2016 03:41:03 +0100
Subject: ash,hush: make ^C in interactive mode visually much closer to bash
 behavior

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 libbb/lineedit.c |  2 +-
 shell/ash.c      |  4 +++-
 shell/hush.c     | 17 +++++++++++------
 3 files changed, 15 insertions(+), 8 deletions(-)

(limited to 'shell')

diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index ac049f57d..4d7828cfa 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -2251,6 +2251,7 @@ static int32_t reverse_i_search(void)
  * Returns:
  * -1 on read errors or EOF, or on bare Ctrl-D,
  * 0  on ctrl-C (the line entered is still returned in 'command'),
+ * (in both cases the cursor remains on the input line, '\n' is not printed)
  * >0 length of input string, including terminating '\n'
  */
 int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize, int timeout)
@@ -2686,7 +2687,6 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
 			 && ic_raw == initial_settings.c_cc[VINTR]
 			) {
 				/* Ctrl-C (usually) - stop gathering input */
-				goto_new_line();
 				command_len = 0;
 				break_out = -1; /* "do not append '\n'" */
 				break;
diff --git a/shell/ash.c b/shell/ash.c
index 3e5a3b3e9..2bdb4aad7 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -9869,7 +9869,8 @@ preadfd(void)
 		reinit_unicode_for_ash();
 		nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout);
 		if (nr == 0) {
-			/* Ctrl+C pressed */
+			/* ^C pressed, "convert" to SIGINT */
+			write(STDOUT_FILENO, "^C", 2);
 			if (trap[SIGINT]) {
 				buf[0] = '\n';
 				buf[1] = '\0';
@@ -9877,6 +9878,7 @@ preadfd(void)
 				return 1;
 			}
 			exitstatus = 128 + SIGINT;
+			bb_putchar('\n');
 			goto retry;
 		}
 		if (nr < 0) {
diff --git a/shell/hush.c b/shell/hush.c
index 5b720ce98..bcd4dffee 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -1756,8 +1756,6 @@ static int check_and_run_traps(void)
 		switch (sig) {
 		case SIGINT:
 			debug_printf_exec("%s: sig:%d default SIGINT handler\n", __func__, sig);
-			/* Builtin was ^C'ed, make it look prettier: */
-			bb_putchar('\n');
 			G.flag_SIGINT = 1;
 			last_sig = sig;
 			break;
@@ -2195,16 +2193,22 @@ static int get_user_input(struct in_str *i)
 # if ENABLE_FEATURE_EDITING
 	for (;;) {
 		reinit_unicode_for_hush();
-		G.flag_SIGINT = 0;
+		if (G.flag_SIGINT) {
+			/* There was ^C'ed, make it look prettier: */
+			bb_putchar('\n');
+			G.flag_SIGINT = 0;
+		}
 		/* buglet: SIGINT will not make new prompt to appear _at once_,
-		 * only after <Enter>. (^C will work) */
+		 * only after <Enter>. (^C works immediately) */
 		r = read_line_input(G.line_input_state, prompt_str,
 				G.user_input_buf, CONFIG_FEATURE_EDITING_MAX_LEN-1,
 				/*timeout*/ -1
 		);
-		/* read_line_input intercepts ^C, "convert" it into SIGINT */
-		if (r == 0)
+		/* read_line_input intercepts ^C, "convert" it to SIGINT */
+		if (r == 0) {
+			write(STDOUT_FILENO, "^C", 2);
 			raise(SIGINT);
+		}
 		check_and_run_traps();
 		if (r != 0 && !G.flag_SIGINT)
 			break;
@@ -2232,6 +2236,7 @@ static int get_user_input(struct in_str *i)
 			fputs(prompt_str, stdout);
 		}
 		fflush_all();
+//FIXME: here ^C or SIGINT will have effect only after <Enter>
 		r = fgetc(i->file);
 		/* In !ENABLE_FEATURE_EDITING we don't use read_line_input,
 		 * no ^C masking happens during fgetc, no special code for ^C:
-- 
cgit v1.2.3-55-g6feb