fix possible isatty false positives and unwanted device state changes
authorRich Felker <dalias@aerifal.cx>
Mon, 23 Feb 2015 23:53:01 +0000 (18:53 -0500)
committerRich Felker <dalias@aerifal.cx>
Mon, 23 Feb 2015 23:53:01 +0000 (18:53 -0500)
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.

src/stdio/__fdopen.c
src/stdio/__stdout_write.c
src/unistd/isatty.c

index a6ae73a2021306dfd461ef86592977c90f14cada..ef8f47dcdaf46f5265655f23d7a59fe35684255a 100644 (file)
@@ -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. */
index 200fe2c96f5296446b464b3a91385ad497aa4a82..dd1ec60ff703475120251bf9a005874aafa9ae74 100644 (file)
@@ -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);
 }
index cff6e9fe4334fc801d921951c0ff82618cdcf44e..c8badaf55edd7d6c4e692e5d238e093848cc7290 100644 (file)
@@ -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);
 }