aboutsummaryrefslogtreecommitdiff
path: root/libbb/lineedit.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-10-26 15:23:32 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2009-10-26 15:23:32 +0100
commit727e1b536e5478b8f28c93990a5bf34091144608 (patch)
treec8993291a1a03a06fcb7a2382e6cc211e6d7861e /libbb/lineedit.c
parentd31a8793ebedb53b686c9ea01be33d3d564760b9 (diff)
downloadbusybox-w32-727e1b536e5478b8f28c93990a5bf34091144608.tar.gz
busybox-w32-727e1b536e5478b8f28c93990a5bf34091144608.tar.bz2
busybox-w32-727e1b536e5478b8f28c93990a5bf34091144608.zip
read_key,lineeedit: parse position answerback faster; sanitize its use
it's still not reliable, and probably cannot be made so... added comment with explanation. function old new delta put_prompt 52 110 +58 read_key 601 607 +6 lineedit_read_key 201 207 +6 win_changed 108 104 -4 read_line_input 4824 4809 -15 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/2 up/down: 70/-19) Total: 51 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'libbb/lineedit.c')
-rw-r--r--libbb/lineedit.c38
1 files changed, 33 insertions, 5 deletions
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index bfd0e3346..2e1bc5d2e 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -370,6 +370,7 @@ static void input_backward(unsigned num)
370static void put_prompt(void) 370static void put_prompt(void)
371{ 371{
372 out1str(cmdedit_prompt); 372 out1str(cmdedit_prompt);
373 fflush(NULL);
373 if (ENABLE_FEATURE_EDITING_ASK_TERMINAL) { 374 if (ENABLE_FEATURE_EDITING_ASK_TERMINAL) {
374 /* Ask terminal where is the cursor now. 375 /* Ask terminal where is the cursor now.
375 * lineedit_read_key handles response and corrects 376 * lineedit_read_key handles response and corrects
@@ -380,7 +381,33 @@ static void put_prompt(void)
380 * Note: we print it _after_ prompt, because 381 * Note: we print it _after_ prompt, because
381 * prompt may contain CR. Example: PS1='\[\r\n\]\w ' 382 * prompt may contain CR. Example: PS1='\[\r\n\]\w '
382 */ 383 */
383 out1str("\033" "[6n"); 384 /* Problem: if there is buffered input on stdin,
385 * the response will be delivered later,
386 * possibly to an unsuspecting application.
387 * Testcase: "sleep 1; busybox ash" + press and hold [Enter].
388 * Result:
389 * ~/srcdevel/bbox/fix/busybox.t4 #
390 * ~/srcdevel/bbox/fix/busybox.t4 #
391 * ^[[59;34~/srcdevel/bbox/fix/busybox.t4 # <-- garbage
392 * ~/srcdevel/bbox/fix/busybox.t4 #
393 *
394 * Checking for input with poll only makes the race narrower,
395 * I still can trigger it. Strace:
396 *
397 * write(1, "~/srcdevel/bbox/fix/busybox.t4 # ", 33) = 33
398 * poll([{fd=0, events=POLLIN}], 1, 0) = 0 (Timeout) <-- no input exists
399 * write(1, "\33[6n", 4) = 4 <-- send the ESC sequence, quick!
400 * poll([{fd=0, events=POLLIN}], 1, 4294967295) = 1 ([{fd=0, revents=POLLIN}])
401 * read(0, "\n", 1) = 1 <-- oh crap, user's input got in first
402 */
403 struct pollfd pfd;
404
405 pfd.fd = STDIN_FILENO;
406 pfd.events = POLLIN;
407 if (safe_poll(&pfd, 1, 0) == 0) {
408 out1str("\033" "[6n");
409 fflush(NULL); /* make terminal see it ASAP! */
410 }
384 } 411 }
385 cursor = 0; 412 cursor = 0;
386 { 413 {
@@ -1603,7 +1630,7 @@ static void cmdedit_setwidth(unsigned w, int redraw_flg)
1603 int new_y = (cursor + cmdedit_prmt_len) / w; 1630 int new_y = (cursor + cmdedit_prmt_len) / w;
1604 /* redraw */ 1631 /* redraw */
1605 redraw((new_y >= cmdedit_y ? new_y : cmdedit_y), command_len - cursor); 1632 redraw((new_y >= cmdedit_y ? new_y : cmdedit_y), command_len - cursor);
1606 fflush(stdout); 1633 fflush(NULL);
1607 } 1634 }
1608} 1635}
1609 1636
@@ -1640,6 +1667,7 @@ static int lineedit_read_key(char *read_key_buffer)
1640 ic = read_key(STDIN_FILENO, read_key_buffer); 1667 ic = read_key(STDIN_FILENO, read_key_buffer);
1641 1668
1642 if (ENABLE_FEATURE_EDITING_ASK_TERMINAL 1669 if (ENABLE_FEATURE_EDITING_ASK_TERMINAL
1670 && cursor == 0 /* otherwise it may be bogus */
1643 && (int32_t)ic == KEYCODE_CURSOR_POS 1671 && (int32_t)ic == KEYCODE_CURSOR_POS
1644 ) { 1672 ) {
1645 int col = ((ic >> 32) & 0x7fff) - 1; 1673 int col = ((ic >> 32) & 0x7fff) - 1;
@@ -1708,7 +1736,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
1708 ) { 1736 ) {
1709 /* Happens when e.g. stty -echo was run before */ 1737 /* Happens when e.g. stty -echo was run before */
1710 parse_and_put_prompt(prompt); 1738 parse_and_put_prompt(prompt);
1711 fflush(stdout); 1739 /* fflush(stdout); - done by parse_and_put_prompt */
1712 if (fgets(command, maxsize, stdin) == NULL) 1740 if (fgets(command, maxsize, stdin) == NULL)
1713 len = -1; /* EOF or error */ 1741 len = -1; /* EOF or error */
1714 else 1742 else
@@ -2190,7 +2218,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
2190 tcsetattr_stdin_TCSANOW(&initial_settings); 2218 tcsetattr_stdin_TCSANOW(&initial_settings);
2191 /* restore SIGWINCH handler */ 2219 /* restore SIGWINCH handler */
2192 signal(SIGWINCH, previous_SIGWINCH_handler); 2220 signal(SIGWINCH, previous_SIGWINCH_handler);
2193 fflush(stdout); 2221 fflush(NULL);
2194 2222
2195 len = command_len; 2223 len = command_len;
2196 DEINIT_S(); 2224 DEINIT_S();
@@ -2204,7 +2232,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
2204int FAST_FUNC read_line_input(const char* prompt, char* command, int maxsize) 2232int FAST_FUNC read_line_input(const char* prompt, char* command, int maxsize)
2205{ 2233{
2206 fputs(prompt, stdout); 2234 fputs(prompt, stdout);
2207 fflush(stdout); 2235 fflush(NULL);
2208 fgets(command, maxsize, stdin); 2236 fgets(command, maxsize, stdin);
2209 return strlen(command); 2237 return strlen(command);
2210} 2238}