makebuf.c revision 98121
1176669Spiso/*
2176669Spiso * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers.
3176669Spiso *      All rights reserved.
4176669Spiso * Copyright (c) 1990, 1993
5176669Spiso *	The Regents of the University of California.  All rights reserved.
6176669Spiso *
7176669Spiso * This code is derived from software contributed to Berkeley by
8176669Spiso * Chris Torek.
9176669Spiso *
10176669Spiso * By using this file, you agree to the terms and conditions set
11176669Spiso * forth in the LICENSE file which can be found at the top level of
12176669Spiso * the sendmail distribution.
13176669Spiso */
14176669Spiso
15176669Spiso#include <sm/gen.h>
16176669SpisoSM_RCSID("@(#)$Id: makebuf.c,v 1.26 2001/10/31 16:04:08 ca Exp $")
17176669Spiso#include <stdlib.h>
18176669Spiso#include <unistd.h>
19176669Spiso#include <sys/types.h>
20176669Spiso#include <sys/stat.h>
21176669Spiso#include <sm/io.h>
22176669Spiso#include <sm/heap.h>
23176669Spiso#include <sm/conf.h>
24176669Spiso#include "local.h"
25176669Spiso
26176669Spiso/*
27176669Spiso**  SM_MAKEBUF -- make a buffer for the file
28176669Spiso**
29176669Spiso**	Parameters:
30176669Spiso**		fp -- the file to be buffered
31176669Spiso**
32176669Spiso**	Returns:
33176669Spiso**		nothing
34176669Spiso**
35176669Spiso**	Allocate a file buffer, or switch to unbuffered I/O.
36176669Spiso**	By default tty devices default to line buffered.
37176669Spiso*/
38176669Spiso
39200580Sluigivoid
40200580Sluigism_makebuf(fp)
41176669Spiso	register SM_FILE_T *fp;
42176669Spiso{
43176669Spiso	register void *p;
44176669Spiso	register int flags;
45176669Spiso	size_t size;
46176669Spiso	int couldbetty;
47176669Spiso
48176669Spiso	if (fp->f_flags & SMNBF)
49176669Spiso	{
50176669Spiso		fp->f_bf.smb_base = fp->f_p = fp->f_nbuf;
51176669Spiso		fp->f_bf.smb_size = 1;
52243401Sglebius		return;
53243401Sglebius	}
54176669Spiso	flags = sm_whatbuf(fp, &size, &couldbetty);
55176669Spiso	if ((p = sm_malloc(size)) == NULL)
56215701Sdim	{
57195727Srwatson		fp->f_flags |= SMNBF;
58176669Spiso		fp->f_bf.smb_base = fp->f_p = fp->f_nbuf;
59200909Sluigi		fp->f_bf.smb_size = 1;
60176669Spiso		return;
61176669Spiso	}
62176669Spiso	if (!Sm_IO_DidInit)
63176669Spiso		sm_init();
64200897Sluigi	flags |= SMMBF;
65176669Spiso	fp->f_bf.smb_base = fp->f_p = p;
66200897Sluigi	fp->f_bf.smb_size = size;
67200909Sluigi	if (couldbetty && isatty(fp->f_file))
68176669Spiso		flags |= SMLBF;
69200897Sluigi	fp->f_flags |= flags;
70176669Spiso}
71200909Sluigi
72200909Sluigi/*
73200909Sluigi**  SM_WHATBUF -- determine proper buffer for a file (internal)
74200909Sluigi**
75200909Sluigi**  Plus it fills in 'bufsize' for recommended buffer size and
76200909Sluigi**  fills in flag to indicate if 'fp' could be a tty (nothing
77200909Sluigi**  to do with "betty" :-) ).
78200909Sluigi**
79200909Sluigi**	Parameters:
80200909Sluigi**		fp -- file pointer to be buffered
81200909Sluigi**		bufsize -- new buffer size (a return)
82176669Spiso**		couldbetty -- could be a tty (returns)
83200909Sluigi**
84176669Spiso**	Returns:
85200909Sluigi**		Success:
86176669Spiso**		on error:
87176669Spiso**			SMNPT -- not seek opimized
88200897Sluigi**			SMOPT -- seek opimized
89200897Sluigi*/
90200897Sluigi
91176669Spisoint
92200897Sluigism_whatbuf(fp, bufsize, couldbetty)
93176669Spiso	register SM_FILE_T *fp;
94200897Sluigi	size_t *bufsize;
95200909Sluigi	int *couldbetty;
96176669Spiso{
97200897Sluigi	struct stat st;
98200897Sluigi
99200909Sluigi	if (fp->f_file < 0 || fstat(fp->f_file, &st) < 0)
100200909Sluigi	{
101200897Sluigi		*couldbetty = 0;
102200897Sluigi		*bufsize = SM_IO_BUFSIZ;
103176669Spiso		return SMNPT;
104176669Spiso	}
105176669Spiso
106176669Spiso	/* could be a tty iff it is a character device */
107176669Spiso	*couldbetty = S_ISCHR(st.st_mode);
108176669Spiso	if (st.st_blksize == 0)
109176669Spiso	{
110176669Spiso		*bufsize = SM_IO_BUFSIZ;
111176669Spiso		return SMNPT;
112176669Spiso	}
113176669Spiso
114176669Spiso#if SM_IO_MAX_BUF_FILE > 0
115176669Spiso	if (S_ISREG(st.st_mode) && st.st_blksize > SM_IO_MAX_BUF_FILE)
116176669Spiso		st.st_blksize = SM_IO_MAX_BUF_FILE;
117176669Spiso#endif /* SM_IO_MAX_BUF_FILE > 0 */
118176669Spiso
119176669Spiso#if SM_IO_MAX_BUF > 0 || SM_IO_MIN_BUF > 0
120176669Spiso	if (!S_ISREG(st.st_mode))
121176669Spiso	{
122176669Spiso# if SM_IO_MAX_BUF > 0
123176669Spiso		if (st.st_blksize > SM_IO_MAX_BUF)
124176669Spiso			st.st_blksize = SM_IO_MAX_BUF;
125176669Spiso#  if SM_IO_MIN_BUF > 0
126176669Spiso		else
127176669Spiso#  endif /* SM_IO_MIN_BUF > 0 */
128176669Spiso# endif /* SM_IO_MAX_BUF > 0 */
129176669Spiso# if SM_IO_MIN_BUF > 0
130176669Spiso		if (st.st_blksize < SM_IO_MIN_BUF)
131176669Spiso			st.st_blksize = SM_IO_MIN_BUF;
132176669Spiso# endif /* SM_IO_MIN_BUF > 0 */
133176669Spiso	}
134176669Spiso#endif /* SM_IO_MAX_BUF > 0 || SM_IO_MIN_BUF > 0 */
135200909Sluigi
136176669Spiso	/*
137200909Sluigi	**  Optimise fseek() only if it is a regular file.  (The test for
138176669Spiso	**  sm_std_seek is mainly paranoia.)  It is safe to set _blksize
139176669Spiso	**  unconditionally; it will only be used if SMOPT is also set.
140176669Spiso	*/
141176669Spiso
142220837Sglebius	if ((fp->f_flags & SMSTR) == 0)
143176669Spiso	{
144176669Spiso		*bufsize = st.st_blksize;
145176669Spiso		fp->f_blksize = st.st_blksize;
146176669Spiso	}
147176669Spiso	else
148176669Spiso		*bufsize = SM_IO_BUFSIZ;
149176669Spiso	if ((st.st_mode & S_IFMT) == S_IFREG &&
150176669Spiso	    fp->f_seek == sm_stdseek)
151176669Spiso		return SMOPT;
152176669Spiso	else
153176669Spiso		return SMNPT;
154176669Spiso}
155176669Spiso