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