146111Sbostic /*- 246111Sbostic * Copyright (c) 1990 The Regents of the University of California. 346111Sbostic * All rights reserved. 446111Sbostic * 546111Sbostic * This code is derived from software contributed to Berkeley by 646111Sbostic * Chris Torek. 746111Sbostic * 846111Sbostic * %sccs.include.redist.c% 946111Sbostic */ 1046111Sbostic 1146111Sbostic #if defined(LIBC_SCCS) && !defined(lint) 12*56990Storek static char sccsid[] = "@(#)setvbuf.c 5.4 (Berkeley) 12/04/92"; 1346111Sbostic #endif /* LIBC_SCCS and not lint */ 1446111Sbostic 1546111Sbostic #include <stdio.h> 1646111Sbostic #include <stdlib.h> 1746111Sbostic #include "local.h" 1846111Sbostic 1946111Sbostic /* 2046111Sbostic * Set one of the three kinds of buffering, optionally including 2146111Sbostic * a buffer. 2246111Sbostic */ 2346111Sbostic setvbuf(fp, buf, mode, size) 2446111Sbostic register FILE *fp; 2546111Sbostic char *buf; 2646111Sbostic register int mode; 2746111Sbostic register size_t size; 2846111Sbostic { 29*56990Storek register int ret, flags; 3046111Sbostic 3146111Sbostic /* 3246111Sbostic * Verify arguments. The `int' limit on `size' is due to this 3346111Sbostic * particular implementation. 3446111Sbostic */ 3546111Sbostic if ((mode != _IOFBF && mode != _IOLBF && mode != _IONBF) || 3646111Sbostic (int)size < 0) 3746111Sbostic return (EOF); 3846111Sbostic 3946111Sbostic /* 40*56990Storek * OK so far. Write current buffer, if any; drop read count, if 41*56990Storek * any. Make sure putc() will not think fp is line buffered. Free 42*56990Storek * old buffer if it was from malloc(). Clear line and non-buffer 43*56990Storek * flags, and clear malloc flag. 4446111Sbostic */ 45*56990Storek ret = 0; 4646217Sbostic (void) __sflush(fp); 4746111Sbostic fp->_r = 0; 4846111Sbostic fp->_lbfsize = 0; 49*56990Storek flags = fp->_flags; 50*56990Storek if (flags & __SMBF) 5146111Sbostic free((void *)fp->_bf._base); 52*56990Storek flags &= ~(__SLBF | __SNBF | __SMBF); 5346111Sbostic 54*56990Storek if (size == 0) 55*56990Storek buf = NULL; /* we will make a real one later */ 56*56990Storek else if (buf == NULL) { 57*56990Storek /* 58*56990Storek * Caller wants specific buffering mode and size but did 59*56990Storek * not provide a buffer. Produce one of the given size. 60*56990Storek * If that fails, set the size to 0 and continue, so that 61*56990Storek * we will try again later with a system-supplied size 62*56990Storek * (failure here is probably from someone with the bogus 63*56990Storek * idea that larger is always better, asking for many MB), 64*56990Storek * but return EOF to indicate failure. 65*56990Storek */ 66*56990Storek if ((buf = malloc(size)) == NULL) { 67*56990Storek ret = EOF; 68*56990Storek size = 0; 69*56990Storek } else 70*56990Storek flags |= __SMBF; 71*56990Storek } 72*56990Storek 7346111Sbostic /* 74*56990Storek * Now put back whichever flag is needed, and fix _lbfsize if line 75*56990Storek * buffered. Ensure output flush on exit if the stream will be 76*56990Storek * buffered at all. 7746111Sbostic */ 7846111Sbostic switch (mode) { 7946111Sbostic 8046111Sbostic case _IONBF: 81*56990Storek flags |= __SNBF; 8246111Sbostic fp->_bf._base = fp->_p = fp->_nbuf; 8346111Sbostic fp->_bf._size = 1; 8446111Sbostic break; 8546111Sbostic 8646111Sbostic case _IOLBF: 87*56990Storek flags |= __SLBF; 8846111Sbostic fp->_lbfsize = -size; 8946111Sbostic /* FALLTHROUGH */ 9046111Sbostic 9146111Sbostic case _IOFBF: 9246111Sbostic /* no flag */ 9346111Sbostic __cleanup = _cleanup; 9446111Sbostic fp->_bf._base = fp->_p = (unsigned char *)buf; 9546111Sbostic fp->_bf._size = size; 9646111Sbostic break; 9746111Sbostic } 9846111Sbostic 9946111Sbostic /* 10046111Sbostic * Patch up write count if necessary. 10146111Sbostic */ 102*56990Storek if (flags & __SWR) 103*56990Storek fp->_w = flags & (__SLBF | __SNBF) ? 0 : size; 104*56990Storek fp->_flags = flags; 10546111Sbostic 106*56990Storek return (ret); 10746111Sbostic } 108