aboutsummaryrefslogtreecommitdiff
path: root/libbb/lineedit.c
diff options
context:
space:
mode:
Diffstat (limited to 'libbb/lineedit.c')
-rw-r--r--libbb/lineedit.c62
1 files changed, 34 insertions, 28 deletions
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 811e3e475..bd4a17348 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -351,7 +351,7 @@ static unsigned save_string(char *dst, unsigned maxsize)
351 return i; 351 return i;
352 } 352 }
353} 353}
354/* I thought just fputwc(c, stdout) would work. But no... */ 354/* I thought just fputwc(c, stderr) would work. But no... */
355static void BB_PUTCHAR(wchar_t c) 355static void BB_PUTCHAR(wchar_t c)
356{ 356{
357 if (unicode_status == UNICODE_ON) { 357 if (unicode_status == UNICODE_ON) {
@@ -360,11 +360,11 @@ static void BB_PUTCHAR(wchar_t c)
360 ssize_t len = wcrtomb(buf, c, &mbst); 360 ssize_t len = wcrtomb(buf, c, &mbst);
361 if (len > 0) { 361 if (len > 0) {
362 buf[len] = '\0'; 362 buf[len] = '\0';
363 fputs_stdout(buf); 363 fputs(buf, stderr);
364 } 364 }
365 } else { 365 } else {
366 /* In this case, c is always one byte */ 366 /* In this case, c is always one byte */
367 putchar(c); 367 bb_putchar_stderr(c);
368 } 368 }
369} 369}
370# if ENABLE_UNICODE_COMBINING_WCHARS || ENABLE_UNICODE_WIDE_WCHARS 370# if ENABLE_UNICODE_COMBINING_WCHARS || ENABLE_UNICODE_WIDE_WCHARS
@@ -410,7 +410,7 @@ static void save_string(char *dst, unsigned maxsize)
410 safe_strncpy(dst, command_ps, maxsize); 410 safe_strncpy(dst, command_ps, maxsize);
411} 411}
412# endif 412# endif
413# define BB_PUTCHAR(c) bb_putchar(c) 413# define BB_PUTCHAR(c) bb_putchar_stderr(c)
414/* Should never be called: */ 414/* Should never be called: */
415int adjust_width_and_validate_wc(unsigned *width_adj, int wc); 415int adjust_width_and_validate_wc(unsigned *width_adj, int wc);
416#endif 416#endif
@@ -469,7 +469,7 @@ static void put_cur_glyph_and_inc_cursor(void)
469 if (c == BB_NUL) 469 if (c == BB_NUL)
470 c = ' '; 470 c = ' ';
471 BB_PUTCHAR(c); 471 BB_PUTCHAR(c);
472 bb_putchar('\b'); 472 bb_putchar_stderr('\b');
473#endif 473#endif
474 cmdedit_y++; 474 cmdedit_y++;
475 if (!ENABLE_UNICODE_WIDE_WCHARS || ofs_to_right == 0) { 475 if (!ENABLE_UNICODE_WIDE_WCHARS || ofs_to_right == 0) {
@@ -531,12 +531,12 @@ static void goto_new_line(void)
531 put_till_end_and_adv_cursor(); 531 put_till_end_and_adv_cursor();
532 /* "cursor == 0" is only if prompt is "" and user input is empty */ 532 /* "cursor == 0" is only if prompt is "" and user input is empty */
533 if (cursor == 0 || cmdedit_x != 0) 533 if (cursor == 0 || cmdedit_x != 0)
534 bb_putchar('\n'); 534 bb_putchar_stderr('\n');
535} 535}
536 536
537static void beep(void) 537static void beep(void)
538{ 538{
539 bb_putchar('\007'); 539 bb_putchar_stderr('\007');
540} 540}
541 541
542/* Full or last/sole prompt line, reset edit cursor, calculate terminal cursor. 542/* Full or last/sole prompt line, reset edit cursor, calculate terminal cursor.
@@ -544,7 +544,10 @@ static void beep(void)
544 */ 544 */
545static void put_prompt_custom(bool is_full) 545static void put_prompt_custom(bool is_full)
546{ 546{
547 fputs_stdout((is_full ? cmdedit_prompt : prompt_last_line)); 547 /* https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
548 * says that shells must write $PSn to stderr, not stdout.
549 */
550 fputs((is_full ? cmdedit_prompt : prompt_last_line), stderr);
548 cursor = 0; 551 cursor = 0;
549 cmdedit_y = cmdedit_prmt_len / cmdedit_termw; /* new quasireal y */ 552 cmdedit_y = cmdedit_prmt_len / cmdedit_termw; /* new quasireal y */
550 cmdedit_x = cmdedit_prmt_len % cmdedit_termw; 553 cmdedit_x = cmdedit_prmt_len % cmdedit_termw;
@@ -582,16 +585,16 @@ static void input_backward(unsigned num)
582 /* This is longer by 5 bytes on x86. 585 /* This is longer by 5 bytes on x86.
583 * Also gets miscompiled for ARM users 586 * Also gets miscompiled for ARM users
584 * (busybox.net/bugs/view.php?id=2274). 587 * (busybox.net/bugs/view.php?id=2274).
585 * printf(("\b\b\b\b" + 4) - num); 588 * fprintf(("\b\b\b\b" + 4) - num, stderr);
586 * return; 589 * return;
587 */ 590 */
588 do { 591 do {
589 bb_putchar('\b'); 592 bb_putchar_stderr('\b');
590 } while (--num); 593 } while (--num);
591 return; 594 return;
592 } 595 }
593#endif 596#endif
594 printf(ESC"[%uD", num); 597 fprintf(stderr, ESC"[%uD", num);
595 return; 598 return;
596 } 599 }
597 600
@@ -616,7 +619,7 @@ static void input_backward(unsigned num)
616 */ 619 */
617 unsigned sv_cursor; 620 unsigned sv_cursor;
618 /* go to 1st column; go up to first line */ 621 /* go to 1st column; go up to first line */
619 printf("\r" ESC"[%uA", cmdedit_y); 622 fprintf(stderr, "\r" ESC"[%uA", cmdedit_y);
620 cmdedit_y = 0; 623 cmdedit_y = 0;
621 sv_cursor = cursor; 624 sv_cursor = cursor;
622 put_prompt_last_line(); /* sets cursor to 0 */ 625 put_prompt_last_line(); /* sets cursor to 0 */
@@ -631,12 +634,12 @@ static void input_backward(unsigned num)
631 cmdedit_x = (cmdedit_termw * cmdedit_y - num) % cmdedit_termw; 634 cmdedit_x = (cmdedit_termw * cmdedit_y - num) % cmdedit_termw;
632 cmdedit_y -= lines_up; 635 cmdedit_y -= lines_up;
633 /* go to 1st column; go up */ 636 /* go to 1st column; go up */
634 printf("\r" ESC"[%uA", lines_up); 637 fprintf(stderr, "\r" ESC"[%uA", lines_up);
635 /* go to correct column. 638 /* go to correct column.
636 * xterm, konsole, Linux VT interpret 0 as 1 below! wow. 639 * xterm, konsole, Linux VT interpret 0 as 1 below! wow.
637 * need to *make sure* we skip it if cmdedit_x == 0 */ 640 * need to *make sure* we skip it if cmdedit_x == 0 */
638 if (cmdedit_x) 641 if (cmdedit_x)
639 printf(ESC"[%uC", cmdedit_x); 642 fprintf(stderr, ESC"[%uC", cmdedit_x);
640 } 643 }
641} 644}
642 645
@@ -644,11 +647,11 @@ static void input_backward(unsigned num)
644static void draw_custom(int y, int back_cursor, bool is_full) 647static void draw_custom(int y, int back_cursor, bool is_full)
645{ 648{
646 if (y > 0) /* up y lines */ 649 if (y > 0) /* up y lines */
647 printf(ESC"[%uA", y); 650 fprintf(stderr, ESC"[%uA", y);
648 bb_putchar('\r'); 651 bb_putchar_stderr('\r');
649 put_prompt_custom(is_full); 652 put_prompt_custom(is_full);
650 put_till_end_and_adv_cursor(); 653 put_till_end_and_adv_cursor();
651 printf(SEQ_CLEAR_TILL_END_OF_SCREEN); 654 fputs(SEQ_CLEAR_TILL_END_OF_SCREEN, stderr);
652 input_backward(back_cursor); 655 input_backward(back_cursor);
653} 656}
654 657
@@ -693,7 +696,7 @@ static void input_delete(int save)
693 command_len--; 696 command_len--;
694 put_till_end_and_adv_cursor(); 697 put_till_end_and_adv_cursor();
695 /* Last char is still visible, erase it (and more) */ 698 /* Last char is still visible, erase it (and more) */
696 printf(SEQ_CLEAR_TILL_END_OF_SCREEN); 699 fputs(SEQ_CLEAR_TILL_END_OF_SCREEN, stderr);
697 input_backward(cursor - j); /* back to old pos cursor */ 700 input_backward(cursor - j); /* back to old pos cursor */
698} 701}
699 702
@@ -1110,8 +1113,8 @@ static void remove_chunk(int16_t *int_buf, int beg, int end)
1110 if (dbg_bmp) { 1113 if (dbg_bmp) {
1111 int i; 1114 int i;
1112 for (i = 0; int_buf[i]; i++) 1115 for (i = 0; int_buf[i]; i++)
1113 bb_putchar((unsigned char)int_buf[i]); 1116 bb_putchar_stderr((unsigned char)int_buf[i]);
1114 bb_putchar('\n'); 1117 bb_putchar_stderr('\n');
1115 } 1118 }
1116} 1119}
1117/* Caller ensures that match_buf points to a malloced buffer 1120/* Caller ensures that match_buf points to a malloced buffer
@@ -1294,7 +1297,7 @@ static void showfiles(void)
1294 int nc; 1297 int nc;
1295 1298
1296 for (nc = 1; nc < ncols && n+nrows < nfiles; n += nrows, nc++) { 1299 for (nc = 1; nc < ncols && n+nrows < nfiles; n += nrows, nc++) {
1297 printf("%s%-*s", matches[n], 1300 fprintf(stderr, "%s%-*s", matches[n],
1298 (int)(column_width - unicode_strwidth(matches[n])), "" 1301 (int)(column_width - unicode_strwidth(matches[n])), ""
1299 ); 1302 );
1300 } 1303 }
@@ -1650,7 +1653,7 @@ void FAST_FUNC show_history(const line_input_t *st)
1650 if (!st) 1653 if (!st)
1651 return; 1654 return;
1652 for (i = 0; i < st->cnt_history; i++) 1655 for (i = 0; i < st->cnt_history; i++)
1653 printf("%4d %s\n", i, st->history[i]); 1656 fprintf(stderr, "%4d %s\n", i, st->history[i]);
1654} 1657}
1655 1658
1656# if ENABLE_FEATURE_EDITING_SAVEHISTORY 1659# if ENABLE_FEATURE_EDITING_SAVEHISTORY
@@ -2090,7 +2093,7 @@ static void ask_terminal(void)
2090 pfd.events = POLLIN; 2093 pfd.events = POLLIN;
2091 if (safe_poll(&pfd, 1, 0) == 0) { 2094 if (safe_poll(&pfd, 1, 0) == 0) {
2092 S.sent_ESC_br6n = 1; 2095 S.sent_ESC_br6n = 1;
2093 fputs_stdout(ESC"[6n"); 2096 fputs(ESC"[6n", stderr);
2094 fflush_all(); /* make terminal see it ASAP! */ 2097 fflush_all(); /* make terminal see it ASAP! */
2095 } 2098 }
2096} 2099}
@@ -2857,13 +2860,13 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
2857 /* Control-k -- clear to end of line */ 2860 /* Control-k -- clear to end of line */
2858 command_ps[cursor] = BB_NUL; 2861 command_ps[cursor] = BB_NUL;
2859 command_len = cursor; 2862 command_len = cursor;
2860 printf(SEQ_CLEAR_TILL_END_OF_SCREEN); 2863 fputs(SEQ_CLEAR_TILL_END_OF_SCREEN, stderr);
2861 break; 2864 break;
2862 case CTRL('L'): 2865 case CTRL('L'):
2863 vi_case(CTRL('L')|VI_CMDMODE_BIT:) 2866 vi_case(CTRL('L')|VI_CMDMODE_BIT:)
2864 /* Control-l -- clear screen */ 2867 /* Control-l -- clear screen */
2865 /* cursor to top,left; clear to the end of screen */ 2868 /* cursor to top,left; clear to the end of screen */
2866 printf(ESC"[H" ESC"[J"); 2869 fputs(ESC"[H" ESC"[J", stderr);
2867 draw_full(command_len - cursor); 2870 draw_full(command_len - cursor);
2868 break; 2871 break;
2869#if MAX_HISTORY > 0 2872#if MAX_HISTORY > 0
@@ -3050,8 +3053,8 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
3050 beep(); 3053 beep();
3051 } else { 3054 } else {
3052 command_ps[cursor] = ic; 3055 command_ps[cursor] = ic;
3053 bb_putchar(ic); 3056 bb_putchar_stderr(ic);
3054 bb_putchar('\b'); 3057 bb_putchar_stderr('\b');
3055 } 3058 }
3056 break; 3059 break;
3057 case '\x1b': /* ESC */ 3060 case '\x1b': /* ESC */
@@ -3249,7 +3252,10 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
3249#undef read_line_input 3252#undef read_line_input
3250int FAST_FUNC read_line_input(const char* prompt, char* command, int maxsize) 3253int FAST_FUNC read_line_input(const char* prompt, char* command, int maxsize)
3251{ 3254{
3252 fputs_stdout(prompt); 3255 /* https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
3256 * says that shells must write $PSn to stderr, not stdout.
3257 */
3258 fputs(prompt, stderr);
3253 fflush_all(); 3259 fflush_all();
3254 if (!fgets(command, maxsize, stdin)) 3260 if (!fgets(command, maxsize, stdin))
3255 return -1; 3261 return -1;