From a1771488db7a7e3b587e93ca661b7128fbfaa07e Mon Sep 17 00:00:00 2001 From: Tulio A M Mendes Date: Sun, 19 Apr 2026 18:05:46 -0300 Subject: [PATCH] =?utf8?q?libgloss:=20fix=20isatty()=20and=20ttyname()=20?= =?utf8?q?=E2=80=94=20use=20TCGETS=20instead=20of=20TIOCGPGRP=20with=20NUL?= =?utf8?q?L?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit isatty() in syscalls.c used ioctl(TIOCGPGRP, 0) which always failed because the kernel rejects NULL user_arg with -EFAULT. This caused bash to think stdin was not a terminal, running in non-interactive mode (no prompt, no line editing). Fix: use TCGETS (0x5401) with a stack-allocated termios struct instead. TCGETS succeeds on any tty regardless of process group state — this is the standard POSIX way to test for a terminal. Also fix ttyname() in posix_stubs.c which had the same bug. --- newlib/libgloss/adros/posix_stubs.c | 3 ++- newlib/libgloss/adros/syscalls.c | 8 ++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/newlib/libgloss/adros/posix_stubs.c b/newlib/libgloss/adros/posix_stubs.c index ea391696..db32cadd 100644 --- a/newlib/libgloss/adros/posix_stubs.c +++ b/newlib/libgloss/adros/posix_stubs.c @@ -431,7 +431,8 @@ int cfsetospeed(struct termios *t, speed_t speed) { (void)t; (void)speed; return char *ttyname(int fd) { /* Minimal: check if fd is a tty, return generic name */ - int r = _sc3(SYS_IOCTL, fd, TTY_TIOCGPGRP, 0); + struct { uint32_t a, b, c, d; uint8_t e[8]; } t; + int r = _sc3(SYS_IOCTL, fd, TTY_TCGETS, (int)&t); if (r < 0) { errno = ENOTTY; return 0; } return "/dev/tty"; } diff --git a/newlib/libgloss/adros/syscalls.c b/newlib/libgloss/adros/syscalls.c index 949592b9..a68a9e65 100644 --- a/newlib/libgloss/adros/syscalls.c +++ b/newlib/libgloss/adros/syscalls.c @@ -162,8 +162,12 @@ int mkdir(const char *path, mode_t mode) { } int isatty(int fd) { - /* Use ioctl TIOCGPGRP (0x540F) — if it succeeds, fd is a tty */ - int r = _sc3(SYS_IOCTL, fd, 0x540F, 0); + /* Use ioctl TCGETS (0x5401) — if it succeeds, fd is a tty. + * TCGETS is the standard test: it succeeds on any terminal device + * regardless of process group state. TIOCGPGRP was unreliable because + * it requires a valid output pointer and a foreground pgrp to be set. */ + struct { uint32_t a, b, c, d; uint8_t e[8]; } t; + int r = _sc3(SYS_IOCTL, fd, 0x5401, (int)&t); if (r < 0) { errno = ENOTTY; return 0; -- 2.43.0