diff options
| author | Ron Yorston <rmy@pobox.com> | 2026-05-22 08:41:25 +0100 |
|---|---|---|
| committer | Ron Yorston <rmy@pobox.com> | 2026-05-22 08:41:25 +0100 |
| commit | a560fdf23d0a8d9dec61cd72c9eb892787aa6901 (patch) | |
| tree | 3cfe9d3c7950e38f202a8af4f666fbde009915b5 | |
| parent | 6a7ccb6ca3bd9b661760879478ecf0d5f6112fc3 (diff) | |
| download | busybox-w32-a560fdf23d0a8d9dec61cd72c9eb892787aa6901.tar.gz busybox-w32-a560fdf23d0a8d9dec61cd72c9eb892787aa6901.tar.bz2 busybox-w32-a560fdf23d0a8d9dec61cd72c9eb892787aa6901.zip | |
win32: better handling of console state
When 'stty size' was run in a command substitution with stderr
redirected or 'stty -echo' with stdin redirected, it failed to
work properly. The redirections broke its connection to the
terminal.
To fix this, ioctl/tcsetattr/tcgetattr have been modified to use
CONIN$ or CONOUT$ to access the screen buffer. Using CON isn't
an adequate substitute in this case.
Also, if ioctl(fd, TIOCGWINSZ) fails, set errno.
Adds 112-116 bytes.
(GitHub issue #594)
Signed-off-by: Ron Yorston <rmy@pobox.com>
| -rw-r--r-- | win32/ioctl.c | 18 | ||||
| -rw-r--r-- | win32/termios.c | 42 |
2 files changed, 35 insertions, 25 deletions
diff --git a/win32/ioctl.c b/win32/ioctl.c index 12b7dd714..55b0c9e0d 100644 --- a/win32/ioctl.c +++ b/win32/ioctl.c | |||
| @@ -11,16 +11,18 @@ static int mingw_get_terminal_width_height(struct winsize *win) | |||
| 11 | win->ws_row = 0; | 11 | win->ws_row = 0; |
| 12 | win->ws_col = 0; | 12 | win->ws_col = 0; |
| 13 | 13 | ||
| 14 | for (fd=STDOUT_FILENO; fd<=STDERR_FILENO; ++fd) { | 14 | fd = open("CONOUT$", O_RDWR); |
| 15 | handle = (HANDLE)_get_osfhandle(fd); | 15 | handle = (HANDLE)_get_osfhandle(fd); |
| 16 | if (handle != INVALID_HANDLE_VALUE && | 16 | |
| 17 | GetConsoleScreenBufferInfo(handle, &sbi) != 0) { | 17 | if (fd != -1 && GetConsoleScreenBufferInfo(handle, &sbi) != 0) { |
| 18 | win->ws_row = sbi.srWindow.Bottom - sbi.srWindow.Top + 1; | 18 | win->ws_row = sbi.srWindow.Bottom - sbi.srWindow.Top + 1; |
| 19 | win->ws_col = sbi.srWindow.Right - sbi.srWindow.Left + 1; | 19 | win->ws_col = sbi.srWindow.Right - sbi.srWindow.Left + 1; |
| 20 | return 0; | 20 | |
| 21 | } | 21 | close(fd); |
| 22 | return 0; | ||
| 22 | } | 23 | } |
| 23 | 24 | ||
| 25 | errno = err_win_to_posix(); | ||
| 24 | return -1; | 26 | return -1; |
| 25 | } | 27 | } |
| 26 | #endif | 28 | #endif |
diff --git a/win32/termios.c b/win32/termios.c index c846dc165..dd64d95b6 100644 --- a/win32/termios.c +++ b/win32/termios.c | |||
| @@ -3,32 +3,40 @@ | |||
| 3 | int FAST_FUNC | 3 | int FAST_FUNC |
| 4 | tcsetattr(int fd, int mode UNUSED_PARAM, const struct termios *t) | 4 | tcsetattr(int fd, int mode UNUSED_PARAM, const struct termios *t) |
| 5 | { | 5 | { |
| 6 | HANDLE h = (HANDLE)_get_osfhandle(fd); | 6 | HANDLE h; |
| 7 | if (!SetConsoleMode(h, t->w_mode)) { | 7 | |
| 8 | errno = err_win_to_posix(); | 8 | fd = open("CONIN$", O_RDWR); |
| 9 | return -1; | 9 | h = (HANDLE)_get_osfhandle(fd); |
| 10 | if (fd != -1 && SetConsoleMode(h, t->w_mode) != 0) { | ||
| 11 | close(fd); | ||
| 12 | return 0; | ||
| 10 | } | 13 | } |
| 11 | 14 | ||
| 12 | return 0; | 15 | errno = err_win_to_posix(); |
| 16 | return -1; | ||
| 13 | } | 17 | } |
| 14 | 18 | ||
| 15 | int FAST_FUNC tcgetattr(int fd, struct termios *t) | 19 | int FAST_FUNC tcgetattr(int fd, struct termios *t) |
| 16 | { | 20 | { |
| 17 | HANDLE h = (HANDLE)_get_osfhandle(fd); | 21 | HANDLE h; |
| 18 | if (!GetConsoleMode(h, &t->w_mode)) { | 22 | |
| 19 | errno = err_win_to_posix(); | 23 | fd = open("CONOUT$", O_RDWR); |
| 20 | return -1; | 24 | h = (HANDLE)_get_osfhandle(fd); |
| 21 | } | 25 | if (fd != -1 && GetConsoleMode(h, &t->w_mode) != 0) { |
| 26 | t->c_cc[VINTR] = 3; // ctrl-c | ||
| 27 | t->c_cc[VEOF] = 4; // ctrl-d | ||
| 22 | 28 | ||
| 23 | t->c_cc[VINTR] = 3; // ctrl-c | 29 | if (t->w_mode & ENABLE_ECHO_INPUT) |
| 24 | t->c_cc[VEOF] = 4; // ctrl-d | 30 | t->c_lflag |= ECHO; |
| 31 | else | ||
| 32 | t->c_lflag &= ~ECHO; | ||
| 25 | 33 | ||
| 26 | if (t->w_mode & ENABLE_ECHO_INPUT) | 34 | close(fd); |
| 27 | t->c_lflag |= ECHO; | 35 | return 0; |
| 28 | else | 36 | } |
| 29 | t->c_lflag &= ~ECHO; | ||
| 30 | 37 | ||
| 31 | return 0; | 38 | errno = err_win_to_posix(); |
| 39 | return -1; | ||
| 32 | } | 40 | } |
| 33 | 41 | ||
| 34 | int64_t FAST_FUNC windows_read_key(int fd, char *buf UNUSED_PARAM, int timeout) | 42 | int64_t FAST_FUNC windows_read_key(int fd, char *buf UNUSED_PARAM, int timeout) |
