1 /*- 2 * Copyright (c) 1990, 1993 3 * The Regents of the University of California. 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 8.1 (Berkeley) 06/04/93"; 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 size_t iosize; 31 int ttyflag; 32 33 /* 34 * Verify arguments. The `int' limit on `size' is due to this 35 * particular implementation. Note, buf and size are ignored 36 * when setting _IONBF. 37 */ 38 if (mode != _IONBF) 39 if ((mode != _IOFBF && mode != _IOLBF) || (int)size < 0) 40 return (EOF); 41 42 /* 43 * Write current buffer, if any. Discard unread input, cancel 44 * line buffering, and free old buffer if malloc()ed. 45 */ 46 ret = 0; 47 (void)__sflush(fp); 48 fp->_r = fp->_lbfsize = 0; 49 flags = fp->_flags; 50 if (flags & __SMBF) 51 free((void *)fp->_bf._base); 52 flags &= ~(__SLBF | __SNBF | __SMBF | __SOPT | __SNPT); 53 54 /* If setting unbuffered mode, skip all the hard work. */ 55 if (mode == _IONBF) 56 goto nbf; 57 58 /* 59 * Find optimal I/O size for seek optimization. This also returns 60 * a `tty flag' to suggest that we check isatty(fd), but we do not 61 * care since our caller told us how to buffer. 62 */ 63 flags |= __swhatbuf(fp, &iosize, &ttyflag); 64 if (size == 0) { 65 buf = NULL; /* force local allocation */ 66 size = iosize; 67 } 68 69 /* Allocate buffer if needed. */ 70 if (buf == NULL) { 71 if ((buf = malloc(size)) == NULL) { 72 /* 73 * Unable to honor user's request. We will return 74 * failure, but try again with file system size. 75 */ 76 ret = EOF; 77 if (size != iosize) { 78 size = iosize; 79 buf = malloc(size); 80 } 81 } 82 if (buf == NULL) { 83 /* No luck; switch to unbuffered I/O. */ 84 nbf: 85 fp->_flags = flags | __SNBF; 86 fp->_w = 0; 87 fp->_bf._base = fp->_p = fp->_nbuf; 88 fp->_bf._size = 1; 89 return (ret); 90 } 91 flags |= __SMBF; 92 } 93 94 /* 95 * Kill any seek optimization if the buffer is not the 96 * right size. 97 * 98 * SHOULD WE ALLOW MULTIPLES HERE (i.e., ok iff (size % iosize) == 0)? 99 */ 100 if (size != iosize) 101 flags |= __SNPT; 102 103 /* 104 * Fix up the FILE fields, and set __cleanup for output flush on 105 * exit (since we are buffered in some way). If in r/w mode, go 106 * to the intermediate state, so that everyone has to call 107 * __srefill or __swsetup on the first operation -- it is more 108 * trouble than it is worth to set things up correctly here. 109 */ 110 if (mode == _IOLBF) 111 flags |= __SLBF; 112 if (flags & __SRW) 113 flags &= ~(__SRD | __SWR); 114 fp->_w = 0; 115 fp->_flags = flags; 116 fp->_bf._base = fp->_p = (unsigned char *)buf; 117 fp->_bf._size = size; 118 fp->_lbfsize = 0; 119 __cleanup = _cleanup; 120 121 return (ret); 122 } 123