X-Git-Url: https://git.saurik.com/apple/libc.git/blobdiff_plain/6465356a983ac139f81d3b7913cdb548477c346c..refs/heads/master:/stdio/FreeBSD/makebuf.c?ds=sidebyside diff --git a/stdio/FreeBSD/makebuf.c b/stdio/FreeBSD/makebuf.c index 85bb73a..a472776 100644 --- a/stdio/FreeBSD/makebuf.c +++ b/stdio/FreeBSD/makebuf.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * @@ -13,7 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -34,7 +36,7 @@ static char sccsid[] = "@(#)makebuf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD: src/lib/libc/stdio/makebuf.c,v 1.6 2007/01/09 00:28:07 imp Exp $"); +__FBSDID("$FreeBSD$"); #include "namespace.h" #include @@ -46,6 +48,9 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/makebuf.c,v 1.6 2007/01/09 00:28:07 imp E #include "libc_private.h" #include "local.h" +#include +#include +#include #ifdef FEATURE_SMALL_STDIOBUF # define MAXBUFSIZE (1 << 12) @@ -54,6 +59,104 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/makebuf.c,v 1.6 2007/01/09 00:28:07 imp E #endif #define TTYBUFSIZE 4096 +#define MAXEVPSIZE 16 + +static char __fallback_evp[MAXEVPSIZE]; +static char __stdout_evp[MAXEVPSIZE]; + +static void +__loadevp(const char* key, char destination[MAXEVPSIZE]) +{ + char* evp = getenv(key); + if (evp != NULL) { + strlcpy(destination, evp, MAXEVPSIZE); + } else { + destination[0] = '\0'; + } +} + +static void +__evpinit(void* __unused unused) +{ + __loadevp("STDBUF", __fallback_evp); + __loadevp("STDBUF1", __stdout_evp); +} + +static char* +__getevp(int fd) +{ + static os_once_t predicate; + os_once(&predicate, NULL, __evpinit); + + if (fd == STDOUT_FILENO && __stdout_evp[0] != '\0') { + return __stdout_evp; + } else if (__fallback_evp[0] != '\0') { + return __fallback_evp; + } else { + return NULL; + } + +} + +/* + * Internal routine to determine environment override buffering for a file. + * + * Sections of the below taken from NetBSD's version of this file under the same license. + */ +static int +__senvbuf(FILE *fp, size_t *bufsize, int *couldbetty) +{ + char* evp; + char* end; + int flags; + long size; + + flags = 0; // Default to fully buffered + + if ((evp = __getevp(fp->_file)) == NULL) { + return flags; + } + + // Look at the first character only to determine buffering mode + switch (*evp) { + case 'u': + case 'U': + flags |= __SNBF; + break; + case 'l': + case 'L': + flags |= __SLBF; + break; + case 'f': + case 'F': + // Default flags is fully buffered + break; + default: + // Unexpected buffering mode, use default fully buffered + return flags; + } + // User specified envrionment defaults have higher priority than tty defaults + *couldbetty = 0; + + // Advance the envrionment variable pointer, so we can attempt to parse the number + evp++; + if (!isdigit(*evp)) { + return flags; // No number found, this protects us from negative size values + } + + size = strtol_l(evp, &end, 10, LC_C_LOCALE); + if (*end != '\0') { + return flags; + } + + if (size <= 0) { + return __SNBF; // Override with unbuffered if the buffer size is 0 + } + + // We had a non zero buffer, cap it and return the flags; + *bufsize = size > MAXBUFSIZE ? MAXBUFSIZE : size; + return flags; +} /* * Allocate a file buffer, or switch to unbuffered I/O. @@ -63,8 +166,7 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/makebuf.c,v 1.6 2007/01/09 00:28:07 imp E * optimisation) right after the _fstat() that finds the buffer size. */ void -__smakebuf(fp) - FILE *fp; +__smakebuf(FILE *fp) { void *p; int flags; @@ -77,6 +179,17 @@ __smakebuf(fp) return; } flags = __swhatbuf(fp, &size, &couldbetty); + if (fp->_file >= 0) { + flags |= __senvbuf(fp, &size, &couldbetty); + + if (flags & __SNBF) { + fp->_flags |= __SNBF; + fp->_bf._base = fp->_p = fp->_nbuf; + fp->_bf._size = 1; + return; + } + } + if (couldbetty && isatty(fp->_file)) { flags |= __SLBF; /* st_blksize for ttys is 128K, so make it more reasonable */ @@ -100,10 +213,7 @@ __smakebuf(fp) * Internal routine to determine `proper' buffering for a file. */ int -__swhatbuf(fp, bufsize, couldbetty) - FILE *fp; - size_t *bufsize; - int *couldbetty; +__swhatbuf(FILE *fp, size_t *bufsize, int *couldbetty) { struct stat st;