aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2026-05-22 08:41:25 +0100
committerRon Yorston <rmy@pobox.com>2026-05-22 08:41:25 +0100
commita560fdf23d0a8d9dec61cd72c9eb892787aa6901 (patch)
tree3cfe9d3c7950e38f202a8af4f666fbde009915b5
parent6a7ccb6ca3bd9b661760879478ecf0d5f6112fc3 (diff)
downloadbusybox-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.c18
-rw-r--r--win32/termios.c42
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 @@
3int FAST_FUNC 3int FAST_FUNC
4tcsetattr(int fd, int mode UNUSED_PARAM, const struct termios *t) 4tcsetattr(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
15int FAST_FUNC tcgetattr(int fd, struct termios *t) 19int 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
34int64_t FAST_FUNC windows_read_key(int fd, char *buf UNUSED_PARAM, int timeout) 42int64_t FAST_FUNC windows_read_key(int fd, char *buf UNUSED_PARAM, int timeout)