Allow changing the default buffering policy for a stdio stream during

construction by setting environment variables.
This commit is contained in:
christos 2015-07-15 19:08:43 +00:00
parent 2e2a488279
commit 90b9d61d73
3 changed files with 104 additions and 14 deletions

View File

@ -1,4 +1,4 @@
.\" $NetBSD: fopen.3,v 1.30 2015/02/11 15:19:05 riastradh Exp $
.\" $NetBSD: fopen.3,v 1.31 2015/07/15 19:08:43 christos Exp $
.\"
.\" Copyright (c) 1990, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
@ -196,6 +196,13 @@ standard text stream
.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 ,

View File

@ -1,4 +1,4 @@
/* $NetBSD: makebuf.c,v 1.17 2012/03/15 18:22:30 christos Exp $ */
/* $NetBSD: makebuf.c,v 1.18 2015/07/15 19:08:43 christos Exp $ */
/*-
* Copyright (c) 1990, 1993
@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)makebuf.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: makebuf.c,v 1.17 2012/03/15 18:22:30 christos Exp $");
__RCSID("$NetBSD: makebuf.c,v 1.18 2015/07/15 19:08:43 christos Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
@ -49,9 +49,63 @@ __RCSID("$NetBSD: makebuf.c,v 1.17 2012/03/15 18:22:30 christos Exp $");
#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 @@ __smakebuf(FILE *fp)
_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 @@ __smakebuf(FILE *fp)
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;
}
/*

View File

@ -1,4 +1,4 @@
.\" $NetBSD: setbuf.3,v 1.13 2003/08/07 16:43:31 agc Exp $
.\" $NetBSD: setbuf.3,v 1.14 2015/07/15 19:08:43 christos Exp $
.\"
.\" Copyright (c) 1980, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
@ -63,6 +63,27 @@ when it is block buffered many characters are saved up and written as a block;
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.