[git commit master] ash: fix bad interaction of "stty -echo" + ASK_TERMINAL

Denys Vlasenko vda.linux at googlemail.com
Wed Nov 11 02:19:30 UTC 2009


commit: http://git.busybox.net/busybox/commit/?id=13ad90627c85c0d744dfa28637fb80e89677a37f
branch: http://git.busybox.net/busybox/commit/?id=refs/heads/master

function                                             old     new   delta
read_line_input                                     4820    4886     +66
put_prompt                                           108      47     -61
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/1 up/down: 66/-61)              Total: 5 bytes

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 libbb/lineedit.c |   99 ++++++++++++++++++++++++++++-------------------------
 1 files changed, 52 insertions(+), 47 deletions(-)

diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index a997257..7bb3f2e 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -372,55 +372,14 @@ static void input_backward(unsigned num)
 
 static void put_prompt(void)
 {
+	unsigned w;
+
 	out1str(cmdedit_prompt);
 	fflush_all();
-#if ENABLE_FEATURE_EDITING_ASK_TERMINAL
-	{
-		/* Ask terminal where is the cursor now.
-		 * lineedit_read_key handles response and corrects
-		 * our idea of current cursor position.
-		 * Testcase: run "echo -n long_line_long_line_long_line",
-		 * then type in a long, wrapping command and try to
-		 * delete it using backspace key.
-		 * Note: we print it _after_ prompt, because
-		 * prompt may contain CR. Example: PS1='\[\r\n\]\w '
-		 */
-		/* Problem: if there is buffered input on stdin,
-		 * the response will be delivered later,
-		 * possibly to an unsuspecting application.
-		 * Testcase: "sleep 1; busybox ash" + press and hold [Enter].
-		 * Result:
-		 * ~/srcdevel/bbox/fix/busybox.t4 #
-		 * ~/srcdevel/bbox/fix/busybox.t4 #
-		 * ^[[59;34~/srcdevel/bbox/fix/busybox.t4 #  <-- garbage
-		 * ~/srcdevel/bbox/fix/busybox.t4 #
-		 *
-		 * Checking for input with poll only makes the race narrower,
-		 * I still can trigger it. Strace:
-		 *
-		 * write(1, "~/srcdevel/bbox/fix/busybox.t4 # ", 33) = 33
-		 * poll([{fd=0, events=POLLIN}], 1, 0) = 0 (Timeout)  <-- no input exists
-		 * write(1, "\33[6n", 4) = 4  <-- send the ESC sequence, quick!
-		 * poll([{fd=0, events=POLLIN}], 1, 4294967295) = 1 ([{fd=0, revents=POLLIN}])
-		 * read(0, "\n", 1)      = 1  <-- oh crap, user's input got in first
-		 */
-		struct pollfd pfd;
-
-		pfd.fd = STDIN_FILENO;
-		pfd.events = POLLIN;
-		if (safe_poll(&pfd, 1, 0) == 0) {
-			S.sent_ESC_br6n = 1;
-			out1str("\033" "[6n");
-			fflush_all(); /* make terminal see it ASAP! */
-		}
-	}
-#endif
 	cursor = 0;
-	{
-		unsigned w = cmdedit_termw; /* volatile var */
-		cmdedit_y = cmdedit_prmt_len / w; /* new quasireal y */
-		cmdedit_x = cmdedit_prmt_len % w;
-	}
+	w = cmdedit_termw; /* read volatile var once */
+	cmdedit_y = cmdedit_prmt_len / w; /* new quasireal y */
+	cmdedit_x = cmdedit_prmt_len % w;
 }
 
 /* draw prompt, editor line, and clear tail */
@@ -1503,6 +1462,51 @@ static void ctrl_right(void)
  * read_line_input and its helpers
  */
 
+#if ENABLE_FEATURE_EDITING_ASK_TERMINAL
+static void ask_terminal(void)
+{
+	/* Ask terminal where is the cursor now.
+	 * lineedit_read_key handles response and corrects
+	 * our idea of current cursor position.
+	 * Testcase: run "echo -n long_line_long_line_long_line",
+	 * then type in a long, wrapping command and try to
+	 * delete it using backspace key.
+	 * Note: we print it _after_ prompt, because
+	 * prompt may contain CR. Example: PS1='\[\r\n\]\w '
+	 */
+	/* Problem: if there is buffered input on stdin,
+	 * the response will be delivered later,
+	 * possibly to an unsuspecting application.
+	 * Testcase: "sleep 1; busybox ash" + press and hold [Enter].
+	 * Result:
+	 * ~/srcdevel/bbox/fix/busybox.t4 #
+	 * ~/srcdevel/bbox/fix/busybox.t4 #
+	 * ^[[59;34~/srcdevel/bbox/fix/busybox.t4 #  <-- garbage
+	 * ~/srcdevel/bbox/fix/busybox.t4 #
+	 *
+	 * Checking for input with poll only makes the race narrower,
+	 * I still can trigger it. Strace:
+	 *
+	 * write(1, "~/srcdevel/bbox/fix/busybox.t4 # ", 33) = 33
+	 * poll([{fd=0, events=POLLIN}], 1, 0) = 0 (Timeout)  <-- no input exists
+	 * write(1, "\33[6n", 4) = 4  <-- send the ESC sequence, quick!
+	 * poll([{fd=0, events=POLLIN}], 1, 4294967295) = 1 ([{fd=0, revents=POLLIN}])
+	 * read(0, "\n", 1)      = 1  <-- oh crap, user's input got in first
+	 */
+	struct pollfd pfd;
+
+	pfd.fd = STDIN_FILENO;
+	pfd.events = POLLIN;
+	if (safe_poll(&pfd, 1, 0) == 0) {
+		S.sent_ESC_br6n = 1;
+		out1str("\033" "[6n");
+		fflush_all(); /* make terminal see it ASAP! */
+	}
+}
+#else
+#define ask_terminal() ((void)0)
+#endif
+
 #if !ENABLE_FEATURE_EDITING_FANCY_PROMPT
 static void parse_and_put_prompt(const char *prmt_ptr)
 {
@@ -1822,8 +1826,9 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
 	bb_error_msg("cur_history:%d cnt_history:%d", state->cur_history, state->cnt_history);
 #endif
 
-	/* Print out the command prompt */
+	/* Print out the command prompt, optionally ask where cursor is */
 	parse_and_put_prompt(prompt);
+	ask_terminal();
 
 	read_key_buffer[0] = 0;
 	while (1) {
-- 
1.6.3.3



More information about the busybox-cvs mailing list