]> git.saurik.com Git - apple/libc.git/blobdiff - stdio/FreeBSD/makebuf.c
Libc-1439.100.3.tar.gz
[apple/libc.git] / stdio / FreeBSD / makebuf.c
index 85bb73a7515b3faea2eaa96706039fa460b07275..a472776afcb0cdfb8d986a56284a3d2c4a3deefe 100644 (file)
@@ -1,4 +1,6 @@
 /*-
 /*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
  * Copyright (c) 1990, 1993
  *     The Regents of the University of California.  All rights reserved.
  *
  * 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.
  * 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.
  *
  *    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 <sys/cdefs.h>
 static char sccsid[] = "@(#)makebuf.c  8.1 (Berkeley) 6/4/93";
 #endif /* LIBC_SCCS and not lint */
 #include <sys/cdefs.h>
-__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 <sys/types.h>
 
 #include "namespace.h"
 #include <sys/types.h>
@@ -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 "libc_private.h"
 #include "local.h"
+#include <xlocale/_stdio.h>
+#include <xlocale/_stdlib.h>
+#include <os/once_private.h>
 
 #ifdef FEATURE_SMALL_STDIOBUF
 # define MAXBUFSIZE    (1 << 12)
 
 #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
 #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.
 
 /*
  * 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
  * optimisation) right after the _fstat() that finds the buffer size.
  */
 void
-__smakebuf(fp)
-       FILE *fp;
+__smakebuf(FILE *fp)
 {
        void *p;
        int flags;
 {
        void *p;
        int flags;
@@ -77,6 +179,17 @@ __smakebuf(fp)
                return;
        }
        flags = __swhatbuf(fp, &size, &couldbetty);
                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 */
        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
  * 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;
 
 {
        struct stat st;