diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2009-11-11 03:19:30 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2009-11-11 03:19:30 +0100 |
commit | 13ad90627c85c0d744dfa28637fb80e89677a37f (patch) | |
tree | de2415eeecb648ff57fcc5b6c022e4dc6ac0cce8 /libbb/lineedit.c | |
parent | b6d221ac9ca16645b3fd24870496dd6cbb0fc1fa (diff) | |
download | busybox-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.c | 99 |
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 | ||
373 | static void put_prompt(void) | 373 | static 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 | ||
1466 | static 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 |
1507 | static void parse_and_put_prompt(const char *prmt_ptr) | 1511 | static 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) { |