aboutsummaryrefslogtreecommitdiff
path: root/libbb/lineedit.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-11-11 03:19:30 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2009-11-11 03:19:30 +0100
commit13ad90627c85c0d744dfa28637fb80e89677a37f (patch)
treede2415eeecb648ff57fcc5b6c022e4dc6ac0cce8 /libbb/lineedit.c
parentb6d221ac9ca16645b3fd24870496dd6cbb0fc1fa (diff)
downloadbusybox-w32-13ad90627c85c0d744dfa28637fb80e89677a37f.tar.gz
busybox-w32-13ad90627c85c0d744dfa28637fb80e89677a37f.tar.bz2
busybox-w32-13ad90627c85c0d744dfa28637fb80e89677a37f.zip
ash: fix bad interaction of "stty -echo" + ASK_TERMINAL
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@googlemail.com>
Diffstat (limited to 'libbb/lineedit.c')
-rw-r--r--libbb/lineedit.c99
1 files changed, 52 insertions, 47 deletions
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index a9972576e..7bb3f2e35 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -372,55 +372,14 @@ static void input_backward(unsigned num)
372 372
373static void put_prompt(void) 373static void put_prompt(void)
374{ 374{
375 unsigned w;
376
375 out1str(cmdedit_prompt); 377 out1str(cmdedit_prompt);
376 fflush_all(); 378 fflush_all();
377#if ENABLE_FEATURE_EDITING_ASK_TERMINAL
378 {
379 /* Ask terminal where is the cursor now.
380 * lineedit_read_key handles response and corrects
381 * our idea of current cursor position.
382 * Testcase: run "echo -n long_line_long_line_long_line",
383 * then type in a long, wrapping command and try to
384 * delete it using backspace key.
385 * Note: we print it _after_ prompt, because
386 * prompt may contain CR. Example: PS1='\[\r\n\]\w '
387 */
388 /* Problem: if there is buffered input on stdin,
389 * the response will be delivered later,
390 * possibly to an unsuspecting application.
391 * Testcase: "sleep 1; busybox ash" + press and hold [Enter].
392 * Result:
393 * ~/srcdevel/bbox/fix/busybox.t4 #
394 * ~/srcdevel/bbox/fix/busybox.t4 #
395 * ^[[59;34~/srcdevel/bbox/fix/busybox.t4 # <-- garbage
396 * ~/srcdevel/bbox/fix/busybox.t4 #
397 *
398 * Checking for input with poll only makes the race narrower,
399 * I still can trigger it. Strace:
400 *
401 * write(1, "~/srcdevel/bbox/fix/busybox.t4 # ", 33) = 33
402 * poll([{fd=0, events=POLLIN}], 1, 0) = 0 (Timeout) <-- no input exists
403 * write(1, "\33[6n", 4) = 4 <-- send the ESC sequence, quick!
404 * poll([{fd=0, events=POLLIN}], 1, 4294967295) = 1 ([{fd=0, revents=POLLIN}])
405 * read(0, "\n", 1) = 1 <-- oh crap, user's input got in first
406 */
407 struct pollfd pfd;
408
409 pfd.fd = STDIN_FILENO;
410 pfd.events = POLLIN;
411 if (safe_poll(&pfd, 1, 0) == 0) {
412 S.sent_ESC_br6n = 1;
413 out1str("\033" "[6n");
414 fflush_all(); /* make terminal see it ASAP! */
415 }
416 }
417#endif
418 cursor = 0; 379 cursor = 0;
419 { 380 w = cmdedit_termw; /* read volatile var once */
420 unsigned w = cmdedit_termw; /* volatile var */ 381 cmdedit_y = cmdedit_prmt_len / w; /* new quasireal y */
421 cmdedit_y = cmdedit_prmt_len / w; /* new quasireal y */ 382 cmdedit_x = cmdedit_prmt_len % w;
422 cmdedit_x = cmdedit_prmt_len % w;
423 }
424} 383}
425 384
426/* draw prompt, editor line, and clear tail */ 385/* draw prompt, editor line, and clear tail */
@@ -1503,6 +1462,51 @@ static void ctrl_right(void)
1503 * read_line_input and its helpers 1462 * read_line_input and its helpers
1504 */ 1463 */
1505 1464
1465#if ENABLE_FEATURE_EDITING_ASK_TERMINAL
1466static void ask_terminal(void)
1467{
1468 /* Ask terminal where is the cursor now.
1469 * lineedit_read_key handles response and corrects
1470 * our idea of current cursor position.
1471 * Testcase: run "echo -n long_line_long_line_long_line",
1472 * then type in a long, wrapping command and try to
1473 * delete it using backspace key.
1474 * Note: we print it _after_ prompt, because
1475 * prompt may contain CR. Example: PS1='\[\r\n\]\w '
1476 */
1477 /* Problem: if there is buffered input on stdin,
1478 * the response will be delivered later,
1479 * possibly to an unsuspecting application.
1480 * Testcase: "sleep 1; busybox ash" + press and hold [Enter].
1481 * Result:
1482 * ~/srcdevel/bbox/fix/busybox.t4 #
1483 * ~/srcdevel/bbox/fix/busybox.t4 #
1484 * ^[[59;34~/srcdevel/bbox/fix/busybox.t4 # <-- garbage
1485 * ~/srcdevel/bbox/fix/busybox.t4 #
1486 *
1487 * Checking for input with poll only makes the race narrower,
1488 * I still can trigger it. Strace:
1489 *
1490 * write(1, "~/srcdevel/bbox/fix/busybox.t4 # ", 33) = 33
1491 * poll([{fd=0, events=POLLIN}], 1, 0) = 0 (Timeout) <-- no input exists
1492 * write(1, "\33[6n", 4) = 4 <-- send the ESC sequence, quick!
1493 * poll([{fd=0, events=POLLIN}], 1, 4294967295) = 1 ([{fd=0, revents=POLLIN}])
1494 * read(0, "\n", 1) = 1 <-- oh crap, user's input got in first
1495 */
1496 struct pollfd pfd;
1497
1498 pfd.fd = STDIN_FILENO;
1499 pfd.events = POLLIN;
1500 if (safe_poll(&pfd, 1, 0) == 0) {
1501 S.sent_ESC_br6n = 1;
1502 out1str("\033" "[6n");
1503 fflush_all(); /* make terminal see it ASAP! */
1504 }
1505}
1506#else
1507#define ask_terminal() ((void)0)
1508#endif
1509
1506#if !ENABLE_FEATURE_EDITING_FANCY_PROMPT 1510#if !ENABLE_FEATURE_EDITING_FANCY_PROMPT
1507static void parse_and_put_prompt(const char *prmt_ptr) 1511static void parse_and_put_prompt(const char *prmt_ptr)
1508{ 1512{
@@ -1822,8 +1826,9 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
1822 bb_error_msg("cur_history:%d cnt_history:%d", state->cur_history, state->cnt_history); 1826 bb_error_msg("cur_history:%d cnt_history:%d", state->cur_history, state->cnt_history);
1823#endif 1827#endif
1824 1828
1825 /* Print out the command prompt */ 1829 /* Print out the command prompt, optionally ask where cursor is */
1826 parse_and_put_prompt(prompt); 1830 parse_and_put_prompt(prompt);
1831 ask_terminal();
1827 1832
1828 read_key_buffer[0] = 0; 1833 read_key_buffer[0] = 0;
1829 while (1) { 1834 while (1) {