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.3 (Berkeley) 08/13/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 if (buf == NULL) 30 size = 0; 31 32 /* 33 * Verify arguments. The `int' limit on `size' is due to this 34 * particular implementation. 35 */ 36 if ((mode != _IOFBF && mode != _IOLBF && mode != _IONBF) || 37 (int)size < 0) 38 return (EOF); 39 40 /* 41 * Write current buffer, if any; drop read count, if any. 42 * Make sure putc() will not think fp is line buffered. 43 * Free old buffer if it was from malloc(). Clear line and 44 * non buffer flags, and clear malloc flag. 45 */ 46 (void) __sflush(fp); 47 fp->_r = 0; 48 fp->_lbfsize = 0; 49 if (fp->_flags & __SMBF) 50 free((void *)fp->_bf._base); 51 fp->_flags &= ~(__SLBF|__SNBF|__SMBF); 52 53 /* 54 * Now put back whichever flag is needed, and fix _lbfsize 55 * if line buffered. Ensure output flush on exit if the 56 * stream will be buffered at all. 57 */ 58 switch (mode) { 59 60 case _IONBF: 61 fp->_flags |= __SNBF; 62 fp->_bf._base = fp->_p = fp->_nbuf; 63 fp->_bf._size = 1; 64 break; 65 66 case _IOLBF: 67 fp->_flags |= __SLBF; 68 fp->_lbfsize = -size; 69 /* FALLTHROUGH */ 70 71 case _IOFBF: 72 /* no flag */ 73 __cleanup = _cleanup; 74 fp->_bf._base = fp->_p = (unsigned char *)buf; 75 fp->_bf._size = size; 76 break; 77 } 78 79 /* 80 * Patch up write count if necessary. 81 */ 82 if (fp->_flags & __SWR) 83 fp->_w = fp->_flags & (__SLBF|__SNBF) ? 0 : size; 84 85 return (0); 86 } 87