tech-userlevel archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
stdio buffering extension
Hi,
After discussing importing stdbuf(1) from FreeBSD with various
people, they objected about it using LD_PRELOAD and suggested to
use the environment directly to alter the default buffering policy.
Here's an implementation of that...
Suggestions/Comments?
christos
Index: fopen.3
===================================================================
RCS file: /cvsroot/src/lib/libc/stdio/fopen.3,v
retrieving revision 1.30
diff -u -u -r1.30 fopen.3
--- fopen.3 11 Feb 2015 15:19:05 -0000 1.30
+++ fopen.3 14 Jul 2015 20:16:45 -0000
@@ -196,6 +196,13 @@
.Em stdin ,
or
.Em stdout ) .
+.Pp
+Input and output against the opened stream will be fully buffered, unless
+it refers to an interactive terminal device, or a different kind of buffering
+is specified in the environment.
+See
+.Xr setvbuf 3
+for additional details.
.Sh RETURN VALUES
Upon successful completion
.Fn fopen ,
Index: makebuf.c
===================================================================
RCS file: /cvsroot/src/lib/libc/stdio/makebuf.c,v
retrieving revision 1.17
diff -u -u -r1.17 makebuf.c
--- makebuf.c 15 Mar 2012 18:22:30 -0000 1.17
+++ makebuf.c 14 Jul 2015 20:16:45 -0000
@@ -49,10 +49,64 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
+#include <inttypes.h>
+#include <ctype.h>
#include "reentrant.h"
#include "local.h"
/*
+ * Override the file buffering based on the environment setting STDBUF%d
+ * (for the specific file descriptor) and STDBUF (for all descriptors).
+ * the setting is ULB<num> standing for "Unbuffered", "Linebuffered",
+ * and Fullybuffered", and <num> is a value from 0 to 1M
+ */
+static int
+__senvbuf(FILE *fp, size_t *size, int *couldbetty)
+{
+ char evb[64], *evp;
+ int flags, e;
+ intmax_t s;
+
+ flags = 0;
+ if (snprintf(evb, sizeof(evb), "STDBUF%d", fp->_file) < 0)
+ return flags;
+
+ if ((evp = getenv(evb)) == NULL && (evp = getenv("STDBUF")) == NULL)
+ return flags;
+
+ switch (*evp) {
+ case 'u':
+ case 'U':
+ evp++;
+ flags |= __SNBF;
+ break;
+ case 'l':
+ case 'L':
+ evp++;
+ flags |= __SLBF;
+ break;
+ case 'f':
+ case 'F':
+ evp++;
+ *couldbetty = 0;
+ break;
+ }
+
+ if (!isdigit((unsigned char)*evp))
+ return flags;
+
+ s = strtoi(evp, NULL, 0, 0, 1024 * 1024, &e);
+ if (e != 0)
+ return flags;
+
+ *size = (size_t)s;
+ if (*size == 0)
+ return __SNBF;
+
+ return flags;
+}
+
+/*
* Allocate a file buffer, or switch to unbuffered I/O.
* Per the ANSI C standard, ALL tty devices default to line buffered.
*
@@ -69,18 +123,21 @@
_DIAGASSERT(fp != NULL);
- if (fp->_flags & __SNBF) {
- fp->_bf._base = fp->_p = fp->_nbuf;
- fp->_bf._size = 1;
- return;
- }
+ if (fp->_flags & __SNBF)
+ goto unbuf;
+
flags = __swhatbuf(fp, &size, &couldbetty);
- if ((p = malloc(size)) == NULL) {
- fp->_flags |= __SNBF;
- fp->_bf._base = fp->_p = fp->_nbuf;
- fp->_bf._size = 1;
- return;
+
+ if ((fp->_flags & (__SLBF|__SNBF|__SMBF)) == 0
+ && fp->_cookie == fp && fp->_file >= 0) {
+ flags |= __senvbuf(fp, &size, &couldbetty);
+ if (flags & __SNBF)
+ goto unbuf;
}
+
+ if ((p = malloc(size)) == NULL)
+ goto unbuf;
+
__cleanup = _cleanup;
flags |= __SMBF;
fp->_bf._base = fp->_p = p;
@@ -89,6 +146,11 @@
if (couldbetty && isatty(__sfileno(fp)))
flags |= __SLBF;
fp->_flags |= flags;
+ return;
+unbuf:
+ fp->_flags |= __SNBF;
+ fp->_bf._base = fp->_p = fp->_nbuf;
+ fp->_bf._size = 1;
}
/*
Index: setbuf.3
===================================================================
RCS file: /cvsroot/src/lib/libc/stdio/setbuf.3,v
retrieving revision 1.13
diff -u -u -r1.13 setbuf.3
--- setbuf.3 7 Aug 2003 16:43:31 -0000 1.13
+++ setbuf.3 14 Jul 2015 20:16:45 -0000
@@ -63,6 +63,27 @@
when it is line buffered characters are saved up until a newline is
output or input is read from any stream attached to a terminal device
(typically stdin).
+.Pp
+The default buffer settings can be overwritten per descriptor
+.Dv ( STDBUFn )
+where
+.Dv n
+is the numeric value of the file descriptor represented by the stream, or
+for all descriptors
+.Dv ( STDBUF ) .
+The environment variable value is a letter followed by an optional numeric
+value indicating the size of the buffer.
+Valid sizes range from 0B to 1MB.
+Valid letters are:
+.Bl -tag -width X -indent
+.It Dv Li U
+Unbuffered.
+.It Dv Li L
+Line-buffered.
+.It Dv Li F
+Fully-buffered.
+.El
+.Pp
The function
.Xr fflush 3
may be used to force the block out early.
Home |
Main Index |
Thread Index |
Old Index