146111Sbostic /*-
2*61180Sbostic * Copyright (c) 1990, 1993
3*61180Sbostic * The Regents of the University of California. 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*61180Sbostic static char sccsid[] = "@(#)makebuf.c 8.1 (Berkeley) 06/04/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
__smakebuf(fp)3046111Sbostic __smakebuf(fp)
3146111Sbostic register FILE *fp;
3246111Sbostic {
3346111Sbostic register void *p;
3459777Storek register int flags;
3559777Storek size_t size;
3659777Storek int couldbetty;
3746111Sbostic
3846111Sbostic if (fp->_flags & __SNBF) {
3946111Sbostic fp->_bf._base = fp->_p = fp->_nbuf;
4046111Sbostic fp->_bf._size = 1;
4146111Sbostic return;
4246111Sbostic }
4359777Storek 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;
4859777Storek return;
4946111Sbostic }
5059777Storek __cleanup = _cleanup;
5159777Storek flags |= __SMBF;
5259777Storek fp->_bf._base = fp->_p = p;
5359777Storek fp->_bf._size = size;
5459777Storek if (couldbetty && isatty(fp->_file))
5559777Storek flags |= __SLBF;
5659777Storek fp->_flags |= flags;
5746111Sbostic }
5859777Storek
5959777Storek /*
6059777Storek * Internal routine to determine `proper' buffering for a file.
6159777Storek */
6259777Storek int
__swhatbuf(fp,bufsize,couldbetty)6359777Storek __swhatbuf(fp, bufsize, couldbetty)
6459777Storek register FILE *fp;
6559777Storek size_t *bufsize;
6659777Storek int *couldbetty;
6759777Storek {
6859777Storek struct stat st;
6959777Storek
7059777Storek if (fp->_file < 0 || fstat(fp->_file, &st) < 0) {
7159777Storek *couldbetty = 0;
7259777Storek *bufsize = BUFSIZ;
7359777Storek return (__SNPT);
7459777Storek }
7559777Storek
7659777Storek /* could be a tty iff it is a character device */
7759777Storek *couldbetty = (st.st_mode & S_IFMT) == S_IFCHR;
7859777Storek if (st.st_blksize <= 0) {
7959777Storek *bufsize = BUFSIZ;
8059777Storek return (__SNPT);
8159777Storek }
8259777Storek
8359777Storek /*
8459777Storek * Optimise fseek() only if it is a regular file. (The test for
8559777Storek * __sseek is mainly paranoia.) It is safe to set _blksize
8659777Storek * unconditionally; it will only be used if __SOPT is also set.
8759777Storek */
8859777Storek *bufsize = st.st_blksize;
8959777Storek fp->_blksize = st.st_blksize;
9059777Storek return ((st.st_mode & S_IFMT) == S_IFREG && fp->_seek == __sseek ?
9159777Storek __SOPT : __SNPT);
9259777Storek }
93