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*59777Storek static char sccsid[] = "@(#)makebuf.c 5.3 (Berkeley) 05/06/93"; 1346111Sbostic #endif /* LIBC_SCCS and not lint */ 1446111Sbostic 1546111Sbostic #include <sys/types.h> 1646111Sbostic #include <sys/stat.h> 1746611Sbostic #include <unistd.h> 1846111Sbostic #include <stdio.h> 1946111Sbostic #include <stdlib.h> 2046111Sbostic #include "local.h" 2146111Sbostic 2246111Sbostic /* 2346111Sbostic * Allocate a file buffer, or switch to unbuffered I/O. 2446111Sbostic * Per the ANSI C standard, ALL tty devices default to line buffered. 2546111Sbostic * 2646111Sbostic * As a side effect, we set __SOPT or __SNPT (en/dis-able fseek 2746111Sbostic * optimisation) right after the fstat() that finds the buffer size. 2846111Sbostic */ 2946111Sbostic void 3046111Sbostic __smakebuf(fp) 3146111Sbostic register FILE *fp; 3246111Sbostic { 3346111Sbostic register void *p; 34*59777Storek register int flags; 35*59777Storek size_t size; 36*59777Storek int couldbetty; 3746111Sbostic 3846111Sbostic if (fp->_flags & __SNBF) { 3946111Sbostic fp->_bf._base = fp->_p = fp->_nbuf; 4046111Sbostic fp->_bf._size = 1; 4146111Sbostic return; 4246111Sbostic } 43*59777Storek flags = __swhatbuf(fp, &size, &couldbetty); 4446111Sbostic if ((p = malloc(size)) == NULL) { 4546111Sbostic fp->_flags |= __SNBF; 4646111Sbostic fp->_bf._base = fp->_p = fp->_nbuf; 4746111Sbostic fp->_bf._size = 1; 48*59777Storek return; 4946111Sbostic } 50*59777Storek __cleanup = _cleanup; 51*59777Storek flags |= __SMBF; 52*59777Storek fp->_bf._base = fp->_p = p; 53*59777Storek fp->_bf._size = size; 54*59777Storek if (couldbetty && isatty(fp->_file)) 55*59777Storek flags |= __SLBF; 56*59777Storek fp->_flags |= flags; 5746111Sbostic } 58*59777Storek 59*59777Storek /* 60*59777Storek * Internal routine to determine `proper' buffering for a file. 61*59777Storek */ 62*59777Storek int 63*59777Storek __swhatbuf(fp, bufsize, couldbetty) 64*59777Storek register FILE *fp; 65*59777Storek size_t *bufsize; 66*59777Storek int *couldbetty; 67*59777Storek { 68*59777Storek struct stat st; 69*59777Storek 70*59777Storek if (fp->_file < 0 || fstat(fp->_file, &st) < 0) { 71*59777Storek *couldbetty = 0; 72*59777Storek *bufsize = BUFSIZ; 73*59777Storek return (__SNPT); 74*59777Storek } 75*59777Storek 76*59777Storek /* could be a tty iff it is a character device */ 77*59777Storek *couldbetty = (st.st_mode & S_IFMT) == S_IFCHR; 78*59777Storek if (st.st_blksize <= 0) { 79*59777Storek *bufsize = BUFSIZ; 80*59777Storek return (__SNPT); 81*59777Storek } 82*59777Storek 83*59777Storek /* 84*59777Storek * Optimise fseek() only if it is a regular file. (The test for 85*59777Storek * __sseek is mainly paranoia.) It is safe to set _blksize 86*59777Storek * unconditionally; it will only be used if __SOPT is also set. 87*59777Storek */ 88*59777Storek *bufsize = st.st_blksize; 89*59777Storek fp->_blksize = st.st_blksize; 90*59777Storek return ((st.st_mode & S_IFMT) == S_IFREG && fp->_seek == __sseek ? 91*59777Storek __SOPT : __SNPT); 92*59777Storek } 93