1234772Sjlh/*- 2234772Sjlh * Copyright (c) 2012 Jeremie Le Hen <jlh@FreeBSD.org> 3234772Sjlh * All rights reserved. 4234772Sjlh * 5234772Sjlh * Redistribution and use in source and binary forms, with or without 6234772Sjlh * modification, are permitted provided that the following conditions 7234772Sjlh * are met: 8234772Sjlh * 1. Redistributions of source code must retain the above copyright 9234772Sjlh * notice, this list of conditions and the following disclaimer. 10234772Sjlh * 2. Redistributions in binary form must reproduce the above copyright 11234772Sjlh * notice, this list of conditions and the following disclaimer in the 12234772Sjlh * documentation and/or other materials provided with the distribution. 13234772Sjlh * 14234772Sjlh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15234772Sjlh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16234772Sjlh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17234772Sjlh * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18234772Sjlh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19234772Sjlh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20234772Sjlh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21234772Sjlh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22234772Sjlh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23234772Sjlh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24234772Sjlh * SUCH DAMAGE. 25234772Sjlh * 26234772Sjlh * $FreeBSD$ 27234772Sjlh */ 28234772Sjlh 29234772Sjlh#include <err.h> 30234772Sjlh#include <errno.h> 31234772Sjlh#include <limits.h> 32234772Sjlh#include <stdio.h> 33234772Sjlh#include <stdlib.h> 34234772Sjlh#include <string.h> 35234772Sjlh 36234772Sjlhstatic const char * 37234772Sjlhstream_name(FILE *s) 38234772Sjlh{ 39234772Sjlh 40234772Sjlh if (s == stdin) 41234772Sjlh return "stdin"; 42234772Sjlh if (s == stdout) 43234772Sjlh return "stdout"; 44234772Sjlh if (s == stderr) 45234772Sjlh return "stderr"; 46234772Sjlh /* This should not happen. */ 47234772Sjlh abort(); 48234772Sjlh} 49234772Sjlh 50234772Sjlhstatic void 51234772Sjlhchange_buf(FILE *s, const char *bufmode) 52234772Sjlh{ 53234772Sjlh char *unit; 54234772Sjlh size_t bufsize; 55234772Sjlh int mode; 56234772Sjlh 57234772Sjlh bufsize = 0; 58234772Sjlh if (bufmode[0] == '0' && bufmode[1] == '\0') 59234772Sjlh mode = _IONBF; 60234772Sjlh else if (bufmode[0] == 'L' && bufmode[1] == '\0') 61234772Sjlh mode = _IOLBF; 62234772Sjlh else if (bufmode[0] == 'B' && bufmode[1] == '\0') { 63234772Sjlh mode = _IOFBF; 64234772Sjlh bufsize = 0; 65234772Sjlh } else { 66234772Sjlh /* 67234772Sjlh * This library being preloaded, depending on libutil 68234772Sjlh * would lead to excessive namespace pollution. 69234772Sjlh * Thus we do not use expand_number(). 70234772Sjlh */ 71234772Sjlh errno = 0; 72234772Sjlh bufsize = strtol(bufmode, &unit, 0); 73234772Sjlh if (errno == EINVAL || errno == ERANGE || unit == bufmode) 74234772Sjlh warn("Wrong buffer mode '%s' for %s", bufmode, 75234772Sjlh stream_name(s)); 76234772Sjlh switch (*unit) { 77234772Sjlh case 'G': 78234772Sjlh bufsize *= 1024 * 1024 * 1024; 79234772Sjlh break; 80234772Sjlh case 'M': 81234772Sjlh bufsize *= 1024 * 1024; 82234772Sjlh break; 83234772Sjlh case 'k': 84234772Sjlh bufsize *= 1024; 85234772Sjlh break; 86234772Sjlh case '\0': 87234772Sjlh break; 88234772Sjlh default: 89234772Sjlh warnx("Unknown suffix '%c' for %s", *unit, 90234772Sjlh stream_name(s)); 91234772Sjlh return; 92234772Sjlh } 93234772Sjlh mode = _IOFBF; 94234772Sjlh } 95234772Sjlh if (setvbuf(s, NULL, mode, bufsize) != 0) 96234772Sjlh warn("Cannot set buffer mode '%s' for %s", bufmode, 97234772Sjlh stream_name(s)); 98234772Sjlh} 99234772Sjlh 100234772Sjlh__attribute__ ((constructor)) static void 101234772Sjlhstdbuf(void) 102234772Sjlh{ 103234772Sjlh char *i_mode, *o_mode, *e_mode; 104234772Sjlh 105234772Sjlh i_mode = getenv("_STDBUF_I"); 106234772Sjlh o_mode = getenv("_STDBUF_O"); 107234772Sjlh e_mode = getenv("_STDBUF_E"); 108234772Sjlh 109234772Sjlh if (e_mode != NULL) 110234772Sjlh change_buf(stderr, e_mode); 111234772Sjlh if (i_mode != NULL) 112234772Sjlh change_buf(stdin, i_mode); 113234772Sjlh if (o_mode != NULL) 114234772Sjlh change_buf(stdout, o_mode); 115234772Sjlh} 116