1 /*- 2 * Copyright (c) 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Chris Torek. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #if defined(LIBC_SCCS) && !defined(lint) 12 static char sccsid[] = "@(#)setvbuf.c 5.4 (Berkeley) 12/04/92"; 13 #endif /* LIBC_SCCS and not lint */ 14 15 #include <stdio.h> 16 #include <stdlib.h> 17 #include "local.h" 18 19 /* 20 * Set one of the three kinds of buffering, optionally including 21 * a buffer. 22 */ 23 setvbuf(fp, buf, mode, size) 24 register FILE *fp; 25 char *buf; 26 register int mode; 27 register size_t size; 28 { 29 register int ret, flags; 30 31 /* 32 * Verify arguments. The `int' limit on `size' is due to this 33 * particular implementation. 34 */ 35 if ((mode != _IOFBF && mode != _IOLBF && mode != _IONBF) || 36 (int)size < 0) 37 return (EOF); 38 39 /* 40 * OK so far. Write current buffer, if any; drop read count, if 41 * any. Make sure putc() will not think fp is line buffered. Free 42 * old buffer if it was from malloc(). Clear line and non-buffer 43 * flags, and clear malloc flag. 44 */ 45 ret = 0; 46 (void) __sflush(fp); 47 fp->_r = 0; 48 fp->_lbfsize = 0; 49 flags = fp->_flags; 50 if (flags & __SMBF) 51 free((void *)fp->_bf._base); 52 flags &= ~(__SLBF | __SNBF | __SMBF); 53 54 if (size == 0) 55 buf = NULL; /* we will make a real one later */ 56 else if (buf == NULL) { 57 /* 58 * Caller wants specific buffering mode and size but did 59 * not provide a buffer. Produce one of the given size. 60 * If that fails, set the size to 0 and continue, so that 61 * we will try again later with a system-supplied size 62 * (failure here is probably from someone with the bogus 63 * idea that larger is always better, asking for many MB), 64 * but return EOF to indicate failure. 65 */ 66 if ((buf = malloc(size)) == NULL) { 67 ret = EOF; 68 size = 0; 69 } else 70 flags |= __SMBF; 71 } 72 73 /* 74 * Now put back whichever flag is needed, and fix _lbfsize if line 75 * buffered. Ensure output flush on exit if the stream will be 76 * buffered at all. 77 */ 78 switch (mode) { 79 80 case _IONBF: 81 flags |= __SNBF; 82 fp->_bf._base = fp->_p = fp->_nbuf; 83 fp->_bf._size = 1; 84 break; 85 86 case _IOLBF: 87 flags |= __SLBF; 88 fp->_lbfsize = -size; 89 /* FALLTHROUGH */ 90 91 case _IOFBF: 92 /* no flag */ 93 __cleanup = _cleanup; 94 fp->_bf._base = fp->_p = (unsigned char *)buf; 95 fp->_bf._size = size; 96 break; 97 } 98 99 /* 100 * Patch up write count if necessary. 101 */ 102 if (flags & __SWR) 103 fp->_w = flags & (__SLBF | __SNBF) ? 0 : size; 104 fp->_flags = flags; 105 106 return (ret); 107 } 108