diff --git a/libio/filedoalloc.c b/libio/filedoalloc.c index 412b8d5937..35044e3512 100644 --- a/libio/filedoalloc.c +++ b/libio/filedoalloc.c @@ -58,6 +58,7 @@ #include "libioP.h" #include <device-nrs.h> #include <sys/stat.h> +#include <sys/types.h> #include <stdlib.h> #include <unistd.h> @@ -71,6 +72,17 @@ local_isatty (int fd) return res; } +struct _IO_stdout_unbuffered +{ + int initialized; + int present; + dev_t dev; + ino_t ino; +} _IO_stdout_unbuffered_values; + +static void +process_stdout_unbuffered (void); + /* Allocate a file buffer, or switch to unbuffered I/O. Streams for TTY devices default to line buffered. */ int @@ -80,9 +92,23 @@ _IO_file_doallocate (FILE *fp) char *p; struct stat64 st; + /* Check to see if buffering of stdout has been suppressed. */ + if (! _IO_stdout_unbuffered_values.initialized) + { + process_stdout_unbuffered(); + } + size = BUFSIZ; if (fp->_fileno >= 0 && __builtin_expect (_IO_SYSSTAT (fp, &st), 0) >= 0) { + // If this fd matched STDOUT_UNBUFFERED ... + if (_IO_stdout_unbuffered_values.present && + _IO_stdout_unbuffered_values.dev == st.st_dev && + _IO_stdout_unbuffered_values.ino == st.st_ino) + { + fp->_flags |= _IO_UNBUFFERED; + return 1; + } if (S_ISCHR (st.st_mode)) { /* Possibly a tty. */ @@ -105,3 +131,26 @@ _IO_file_doallocate (FILE *fp) return 1; } libc_hidden_def (_IO_file_doallocate) + +/* Examine the STDOUT_UNBUFFERED environment variable, if any. + If it has the format NNNN:NNNN, parse those numbers into + _IP_stdout_unbuffered_values. */ +static void +process_stdout_unbuffered (void) +{ + _IO_stdout_unbuffered_values.initialized = 1; + _IO_stdout_unbuffered_values.present = 0; + char *su_value = getenv("STDOUT_UNBUFFERED"); + if (!su_value) + return; + char *p1; + _IO_stdout_unbuffered_values.dev = strtoul(su_value, &p1, 10); + if (*p1 != ':') + return; + char *p2; + _IO_stdout_unbuffered_values.ino = strtoul(p1+1, &p2, 10); + if (*p2) + return; + // Enable the values that we have set. + _IO_stdout_unbuffered_values.present = 1; +}