diff options
| author | Ron Yorston <rmy@pobox.com> | 2023-03-05 12:34:31 +0000 |
|---|---|---|
| committer | Ron Yorston <rmy@pobox.com> | 2023-03-05 12:43:46 +0000 |
| commit | 8ade494aebe60ea14026d48025a462e6d0b58a7f (patch) | |
| tree | 55181219752cf8c2efac037d8f2bd26c71baaca4 | |
| parent | 9aef4d4d298987437e33bf25bcddd16175148d45 (diff) | |
| download | busybox-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.c | 7 | ||||
| -rw-r--r-- | libbb/lineedit.c | 21 | ||||
| -rw-r--r-- | miscutils/less.c | 27 | ||||
| -rw-r--r-- | util-linux/more.c | 11 |
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 | ||
| 704 | static void rawmode(void) | 701 | static 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 | */ |
| 2580 | int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize) | 2585 | int 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 { | |||
| 304 | static void set_tty_cooked(void) | 302 | static 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 |
| 1132 | static int64_t unix_getch_nowait(void) | ||
| 1133 | #else | ||
| 1136 | static int64_t getch_nowait(void) | 1134 | static 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 | ||
| 1198 | static int64_t getch_nowait(void) | 1198 | static 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 | |||
| 1202 | retry: | 1205 | retry: |
| 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 | ||
| 65 | static void gotsig(int sig UNUSED_PARAM) | 66 | static 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, ""); |
