aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2023-03-05 12:34:31 +0000
committerRon Yorston <rmy@pobox.com>2023-03-05 12:43:46 +0000
commit8ade494aebe60ea14026d48025a462e6d0b58a7f (patch)
tree55181219752cf8c2efac037d8f2bd26c71baaca4
parent9aef4d4d298987437e33bf25bcddd16175148d45 (diff)
downloadbusybox-w32-8ade494aebe60ea14026d48025a462e6d0b58a7f.tar.gz
busybox-w32-8ade494aebe60ea14026d48025a462e6d0b58a7f.tar.bz2
busybox-w32-8ade494aebe60ea14026d48025a462e6d0b58a7f.zip
win32: add support for virtual terminal input
Alter certain applets to support virtual terminal input, if enabled. In many places this is achieved by building previously excluded upstream terminal-handling code. The busybox-w32 implementation of termios(3) functions does nothing if virtual terminal input is disabled, so it can be invoked regardless. Some applet-specific terminal-handling code is also required. This affects less, more, vi and command line editing in the shell. (The `more` applet isn't enabled in the default configuration.) This series of patches adds about 1.7KB to the binaries.
-rw-r--r--editors/vi.c7
-rw-r--r--libbb/lineedit.c21
-rw-r--r--miscutils/less.c27
-rw-r--r--util-linux/more.c11
4 files changed, 34 insertions, 32 deletions
diff --git a/editors/vi.c b/editors/vi.c
index 13f0ae8ee..74028e2b4 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -456,9 +456,7 @@ struct globals {
456#if ENABLE_FEATURE_VI_USE_SIGNALS 456#if ENABLE_FEATURE_VI_USE_SIGNALS
457 sigjmp_buf restart; // int_handler() jumps to location remembered here 457 sigjmp_buf restart; // int_handler() jumps to location remembered here
458#endif 458#endif
459#if !ENABLE_PLATFORM_MINGW32
460 struct termios term_orig; // remember what the cooked mode was 459 struct termios term_orig; // remember what the cooked mode was
461#endif
462 int cindex; // saved character index for up/down motion 460 int cindex; // saved character index for up/down motion
463 smallint keep_index; // retain saved character index 461 smallint keep_index; // retain saved character index
464#if ENABLE_FEATURE_VI_COLON 462#if ENABLE_FEATURE_VI_COLON
@@ -700,7 +698,6 @@ static int mysleep(int hund)
700} 698}
701 699
702//----- Set terminal attributes -------------------------------- 700//----- Set terminal attributes --------------------------------
703#if !ENABLE_PLATFORM_MINGW32
704static void rawmode(void) 701static void rawmode(void)
705{ 702{
706 // no TERMIOS_CLEAR_ISIG: leave ISIG on - allow signals 703 // no TERMIOS_CLEAR_ISIG: leave ISIG on - allow signals
@@ -712,10 +709,6 @@ static void cookmode(void)
712 fflush_all(); 709 fflush_all();
713 tcsetattr_stdin_TCSANOW(&term_orig); 710 tcsetattr_stdin_TCSANOW(&term_orig);
714} 711}
715#else
716#define rawmode() ((void)0)
717#define cookmode fflush_all
718#endif
719 712
720//----- Terminal Drawing --------------------------------------- 713//----- Terminal Drawing ---------------------------------------
721// The terminal is made up of 'rows' line of 'columns' columns. 714// The terminal is made up of 'rows' line of 'columns' columns.
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index c4f0c65f1..9bf2f89a5 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -726,7 +726,12 @@ static void input_forward(void)
726#if !ENABLE_PLATFORM_MINGW32 726#if !ENABLE_PLATFORM_MINGW32
727 put_cur_glyph_and_inc_cursor(); 727 put_cur_glyph_and_inc_cursor();
728#else 728#else
729 inc_cursor(); 729 {
730 if (terminal_mode(FALSE) & VT_INPUT)
731 put_cur_glyph_and_inc_cursor();
732 else
733 inc_cursor();
734 }
730#endif 735#endif
731} 736}
732 737
@@ -2579,7 +2584,7 @@ static void sigaction2(int sig, struct sigaction *act)
2579 */ 2584 */
2580int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize) 2585int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize)
2581{ 2586{
2582 int len IF_NOT_PLATFORM_MINGW32(, n); 2587 int len, n;
2583 int timeout; 2588 int timeout;
2584#if ENABLE_FEATURE_TAB_COMPLETION 2589#if ENABLE_FEATURE_TAB_COMPLETION
2585 smallint lastWasTab = 0; 2590 smallint lastWasTab = 0;
@@ -2589,9 +2594,7 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
2589 smallint vi_cmdmode = 0; 2594 smallint vi_cmdmode = 0;
2590#endif 2595#endif
2591 struct termios initial_settings; 2596 struct termios initial_settings;
2592#if !ENABLE_PLATFORM_MINGW32
2593 struct termios new_settings; 2597 struct termios new_settings;
2594#endif
2595 char read_key_buffer[KEYCODE_BUFFER_SIZE]; 2598 char read_key_buffer[KEYCODE_BUFFER_SIZE];
2596 2599
2597 INIT_S(); 2600 INIT_S();
@@ -2600,15 +2603,13 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
2600 cmdedit_termw = 80; 2603 cmdedit_termw = 80;
2601 IF_FEATURE_EDITING_VI(delptr = delbuf;) 2604 IF_FEATURE_EDITING_VI(delptr = delbuf;)
2602 2605
2603#if !ENABLE_PLATFORM_MINGW32
2604 n = get_termios_and_make_raw(STDIN_FILENO, &new_settings, &initial_settings, 0 2606 n = get_termios_and_make_raw(STDIN_FILENO, &new_settings, &initial_settings, 0
2605 | TERMIOS_CLEAR_ISIG /* turn off INTR (ctrl-C), QUIT, SUSP */ 2607 | TERMIOS_CLEAR_ISIG /* turn off INTR (ctrl-C), QUIT, SUSP */
2606 ); 2608 );
2609#if !ENABLE_PLATFORM_MINGW32
2607 if (n != 0 || (initial_settings.c_lflag & (ECHO|ICANON)) == ICANON) { 2610 if (n != 0 || (initial_settings.c_lflag & (ECHO|ICANON)) == ICANON) {
2608#else 2611#else
2609 initial_settings.c_cc[VINTR] = CTRL('C'); 2612 if (n != 0 || !isatty(0) || !isatty(1)) {
2610 initial_settings.c_cc[VEOF] = CTRL('D');
2611 if (!isatty(0) || !isatty(1)) {
2612#endif 2613#endif
2613 /* Happens when e.g. stty -echo was run before. 2614 /* Happens when e.g. stty -echo was run before.
2614 * But if ICANON is not set, we don't come here. 2615 * But if ICANON is not set, we don't come here.
@@ -2661,9 +2662,7 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
2661#endif 2662#endif
2662#define command command_must_not_be_used 2663#define command command_must_not_be_used
2663 2664
2664#if !ENABLE_PLATFORM_MINGW32
2665 tcsetattr_stdin_TCSANOW(&new_settings); 2665 tcsetattr_stdin_TCSANOW(&new_settings);
2666#endif
2667 2666
2668#if 0 2667#if 0
2669 for (i = 0; i <= state->max_history; i++) 2668 for (i = 0; i <= state->max_history; i++)
@@ -3150,10 +3149,8 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
3150 free_tab_completion_data(); 3149 free_tab_completion_data();
3151#endif 3150#endif
3152 3151
3153#if !ENABLE_PLATFORM_MINGW32
3154 /* restore initial_settings */ 3152 /* restore initial_settings */
3155 tcsetattr_stdin_TCSANOW(&initial_settings); 3153 tcsetattr_stdin_TCSANOW(&initial_settings);
3156#endif
3157#if ENABLE_FEATURE_EDITING_WINCH 3154#if ENABLE_FEATURE_EDITING_WINCH
3158 /* restore SIGWINCH handler */ 3155 /* restore SIGWINCH handler */
3159 sigaction_set(SIGWINCH, &S.SIGWINCH_handler); 3156 sigaction_set(SIGWINCH, &S.SIGWINCH_handler);
diff --git a/miscutils/less.c b/miscutils/less.c
index 842031ca3..467c76e2a 100644
--- a/miscutils/less.c
+++ b/miscutils/less.c
@@ -240,9 +240,7 @@ struct globals {
240 smallint winsize_err; 240 smallint winsize_err;
241#endif 241#endif
242 smallint terminated; 242 smallint terminated;
243#if !ENABLE_PLATFORM_MINGW32
244 struct termios term_orig, term_less; 243 struct termios term_orig, term_less;
245#endif
246 char kbd_input[KEYCODE_BUFFER_SIZE]; 244 char kbd_input[KEYCODE_BUFFER_SIZE];
247}; 245};
248#define G (*ptr_to_globals) 246#define G (*ptr_to_globals)
@@ -304,9 +302,7 @@ struct globals {
304static void set_tty_cooked(void) 302static void set_tty_cooked(void)
305{ 303{
306 fflush_all(); 304 fflush_all();
307#if !ENABLE_PLATFORM_MINGW32
308 tcsetattr(kbd_fd, TCSANOW, &term_orig); 305 tcsetattr(kbd_fd, TCSANOW, &term_orig);
309#endif
310} 306}
311 307
312/* Move the cursor to a position (x,y), where (0,0) is the 308/* Move the cursor to a position (x,y), where (0,0) is the
@@ -1132,8 +1128,11 @@ static void reinitialize(void)
1132 buffer_fill_and_print(); 1128 buffer_fill_and_print();
1133} 1129}
1134 1130
1135#if !ENABLE_PLATFORM_MINGW32 1131#if ENABLE_PLATFORM_MINGW32
1132static int64_t unix_getch_nowait(void)
1133#else
1136static int64_t getch_nowait(void) 1134static int64_t getch_nowait(void)
1135#endif
1137{ 1136{
1138 int rd; 1137 int rd;
1139 int64_t key64; 1138 int64_t key64;
@@ -1194,11 +1193,15 @@ static int64_t getch_nowait(void)
1194 set_tty_cooked(); 1193 set_tty_cooked();
1195 return key64; 1194 return key64;
1196} 1195}
1197#else 1196
1197#if ENABLE_PLATFORM_MINGW32
1198static int64_t getch_nowait(void) 1198static int64_t getch_nowait(void)
1199{ 1199{
1200 int64_t c; 1200 int64_t c;
1201 1201
1202 if (terminal_mode(FALSE) & VT_INPUT)
1203 return unix_getch_nowait();
1204
1202retry: 1205retry:
1203 c = _getch(); 1206 c = _getch();
1204 if (c == 0 || c == 0xe0) { 1207 if (c == 0 || c == 0xe0) {
@@ -1894,6 +1897,8 @@ int less_main(int argc, char **argv)
1894{ 1897{
1895#if !ENABLE_PLATFORM_MINGW32 1898#if !ENABLE_PLATFORM_MINGW32
1896 char *tty_name; 1899 char *tty_name;
1900#else
1901 HANDLE h;
1897#endif 1902#endif
1898 int tty_fd; 1903 int tty_fd;
1899 1904
@@ -1980,12 +1985,16 @@ int less_main(int argc, char **argv)
1980 G.kbd_fd_orig_flags = ndelay_on(tty_fd); 1985 G.kbd_fd_orig_flags = ndelay_on(tty_fd);
1981 kbd_fd = tty_fd; /* save in a global */ 1986 kbd_fd = tty_fd; /* save in a global */
1982#else 1987#else
1983 kbd_fd = tty_fd = 0; 1988 h = CreateFileA("CONIN$", GENERIC_READ | GENERIC_WRITE,
1989 FILE_SHARE_READ, NULL, OPEN_EXISTING,
1990 FILE_ATTRIBUTE_NORMAL, NULL);
1991 if (h == INVALID_HANDLE_VALUE)
1992 bb_simple_error_msg_and_die("unable to open console");
1993
1994 kbd_fd = tty_fd = _open_osfhandle((intptr_t)h, O_BINARY);
1984#endif 1995#endif
1985 1996
1986#if !ENABLE_PLATFORM_MINGW32
1987 get_termios_and_make_raw(tty_fd, &term_less, &term_orig, TERMIOS_RAW_CRNL_INPUT); 1997 get_termios_and_make_raw(tty_fd, &term_less, &term_orig, TERMIOS_RAW_CRNL_INPUT);
1988#endif
1989 1998
1990 IF_FEATURE_LESS_ASK_TERMINAL(G.winsize_err =) get_terminal_width_height(tty_fd, &width, &max_displayed_line); 1999 IF_FEATURE_LESS_ASK_TERMINAL(G.winsize_err =) get_terminal_width_height(tty_fd, &width, &max_displayed_line);
1991 /* 20: two tabstops + 4 */ 2000 /* 20: two tabstops + 4 */
diff --git a/util-linux/more.c b/util-linux/more.c
index 07275131e..84ce37bc7 100644
--- a/util-linux/more.c
+++ b/util-linux/more.c
@@ -62,6 +62,7 @@ static void tcsetattr_tty_TCSANOW(struct termios *settings)
62 tcsetattr(G.tty_fileno, TCSANOW, settings); 62 tcsetattr(G.tty_fileno, TCSANOW, settings);
63} 63}
64 64
65#if !ENABLE_PLATFORM_MINGW32
65static void gotsig(int sig UNUSED_PARAM) 66static void gotsig(int sig UNUSED_PARAM)
66{ 67{
67 /* bb_putchar_stderr doesn't use stdio buffering, 68 /* bb_putchar_stderr doesn't use stdio buffering,
@@ -70,6 +71,7 @@ static void gotsig(int sig UNUSED_PARAM)
70 tcsetattr_tty_TCSANOW(&G.initial_settings); 71 tcsetattr_tty_TCSANOW(&G.initial_settings);
71 _exit(EXIT_FAILURE); 72 _exit(EXIT_FAILURE);
72} 73}
74#endif
73 75
74#define CONVERTED_TAB_SIZE 8 76#define CONVERTED_TAB_SIZE 8
75 77
@@ -159,12 +161,13 @@ int more_main(int argc UNUSED_PARAM, char **argv)
159 * to get input from the user. 161 * to get input from the user.
160 */ 162 */
161 for (;;) { 163 for (;;) {
162#if !ENABLE_PLATFORM_MINGW32
163 fflush_all(); 164 fflush_all();
164 input = getc(tty); 165#if ENABLE_PLATFORM_MINGW32
165#else 166 if (!(terminal_mode(FALSE) & VT_INPUT))
166 input = _getch(); 167 input = _getch();
168 else
167#endif 169#endif
170 input = getc(tty);
168 input = tolower(input); 171 input = tolower(input);
169 /* Erase the last message */ 172 /* Erase the last message */
170 printf("\r%*s\r", len, ""); 173 printf("\r%*s\r", len, "");