diff options
authorRich Felker <>2015-02-23 18:53:01 -0500
committerRich Felker <>2015-02-23 18:53:01 -0500
commit2de85a985654d2c944931267645d9a0686242dfe (patch)
parente487c203db36750388228a2db75f96040cbfae58 (diff)
fix possible isatty false positives and unwanted device state changes
the equivalent checks for newly opened stdio output streams, used to determine buffering mode, are also fixed. on most archs, the TCGETS ioctl command shares a value with SNDCTL_TMR_TIMEBASE, part of the OSS sound API which was apparently used with certain MIDI and timer devices. for file descriptors referring to such a device, TCGETS will not fail with ENOTTY as expected; it may produce a different error, or may succeed, and if it succeeds it changes the mode of the device. while it's unlikely that such devices are in use, this is in principle very harmful behavior for an operation which is supposed to do nothing but query whether the fd refers to a tty. TIOCGWINSZ, used to query logical window size for a terminal, was chosen as an alternate ioctl to perform the isatty check. it does not share a value with any other ioctl commands, and it succeeds on any tty device. this change also cleans up strace output to be less ugly and misleading.
3 files changed, 8 insertions, 9 deletions
diff --git a/src/stdio/__fdopen.c b/src/stdio/__fdopen.c
index a6ae73a2..ef8f47dc 100644
--- a/src/stdio/__fdopen.c
+++ b/src/stdio/__fdopen.c
@@ -1,6 +1,5 @@
#include "stdio_impl.h"
#include <stdlib.h>
-#include <termios.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <errno.h>
@@ -9,7 +8,7 @@
FILE *__fdopen(int fd, const char *mode)
FILE *f;
- struct termios tio;
+ struct winsize wsz;
/* Check for valid initial mode character */
if (!strchr("rwa", *mode)) {
@@ -43,7 +42,7 @@ FILE *__fdopen(int fd, const char *mode)
/* Activate line buffered mode for terminals */
f->lbf = EOF;
- if (!(f->flags & F_NOWR) && !__syscall(SYS_ioctl, fd, TCGETS, &tio))
+ if (!(f->flags & F_NOWR) && !__syscall(SYS_ioctl, fd, TIOCGWINSZ, &wsz))
f->lbf = '\n';
/* Initialize op ptrs. No problem if some are unneeded. */
diff --git a/src/stdio/__stdout_write.c b/src/stdio/__stdout_write.c
index 200fe2c9..dd1ec60f 100644
--- a/src/stdio/__stdout_write.c
+++ b/src/stdio/__stdout_write.c
@@ -1,12 +1,11 @@
#include "stdio_impl.h"
-#include <termios.h>
#include <sys/ioctl.h>
size_t __stdout_write(FILE *f, const unsigned char *buf, size_t len)
- struct termios tio;
+ struct winsize wsz;
f->write = __stdio_write;
- if (!(f->flags & F_SVB) && __syscall(SYS_ioctl, f->fd, TCGETS, &tio))
+ if (!(f->flags & F_SVB) && __syscall(SYS_ioctl, f->fd, TIOCGWINSZ, &wsz))
f->lbf = -1;
return __stdio_write(f, buf, len);
diff --git a/src/unistd/isatty.c b/src/unistd/isatty.c
index cff6e9fe..c8badaf5 100644
--- a/src/unistd/isatty.c
+++ b/src/unistd/isatty.c
@@ -1,8 +1,9 @@
#include <unistd.h>
-#include <termios.h>
+#include <sys/ioctl.h>
+#include "syscall.h"
int isatty(int fd)
- struct termios t;
- return tcgetattr(fd, &t) == 0;
+ struct winsize wsz;
+ return !__syscall(SYS_ioctl, fd, TIOCGWINSZ, &wsz);