xref: /freebsd/contrib/sendmail/libsm/makebuf.c (revision 2fb4f839f3fc72ce2bab12f9ba4760f97f73e97f)
140266059SGregory Neil Shapiro /*
25dd76dd0SGregory Neil Shapiro  * Copyright (c) 2000-2001 Proofpoint, Inc. and its suppliers.
340266059SGregory Neil Shapiro  *      All rights reserved.
440266059SGregory Neil Shapiro  * Copyright (c) 1990, 1993
540266059SGregory Neil Shapiro  *	The Regents of the University of California.  All rights reserved.
640266059SGregory Neil Shapiro  *
740266059SGregory Neil Shapiro  * This code is derived from software contributed to Berkeley by
840266059SGregory Neil Shapiro  * Chris Torek.
940266059SGregory Neil Shapiro  *
1040266059SGregory Neil Shapiro  * By using this file, you agree to the terms and conditions set
1140266059SGregory Neil Shapiro  * forth in the LICENSE file which can be found at the top level of
1240266059SGregory Neil Shapiro  * the sendmail distribution.
1340266059SGregory Neil Shapiro  */
1440266059SGregory Neil Shapiro 
1540266059SGregory Neil Shapiro #include <sm/gen.h>
164313cc83SGregory Neil Shapiro SM_RCSID("@(#)$Id: makebuf.c,v 1.27 2013-11-22 20:51:43 ca Exp $")
1740266059SGregory Neil Shapiro #include <stdlib.h>
1840266059SGregory Neil Shapiro #include <unistd.h>
1940266059SGregory Neil Shapiro #include <sys/types.h>
2040266059SGregory Neil Shapiro #include <sys/stat.h>
2140266059SGregory Neil Shapiro #include <sm/io.h>
2240266059SGregory Neil Shapiro #include <sm/heap.h>
2340266059SGregory Neil Shapiro #include <sm/conf.h>
2440266059SGregory Neil Shapiro #include "local.h"
2540266059SGregory Neil Shapiro 
2640266059SGregory Neil Shapiro /*
2740266059SGregory Neil Shapiro **  SM_MAKEBUF -- make a buffer for the file
2840266059SGregory Neil Shapiro **
2940266059SGregory Neil Shapiro **	Parameters:
3040266059SGregory Neil Shapiro **		fp -- the file to be buffered
3140266059SGregory Neil Shapiro **
3240266059SGregory Neil Shapiro **	Returns:
3340266059SGregory Neil Shapiro **		nothing
3440266059SGregory Neil Shapiro **
3540266059SGregory Neil Shapiro **	Allocate a file buffer, or switch to unbuffered I/O.
3640266059SGregory Neil Shapiro **	By default tty devices default to line buffered.
3740266059SGregory Neil Shapiro */
3840266059SGregory Neil Shapiro 
3940266059SGregory Neil Shapiro void
4040266059SGregory Neil Shapiro sm_makebuf(fp)
4140266059SGregory Neil Shapiro 	register SM_FILE_T *fp;
4240266059SGregory Neil Shapiro {
4340266059SGregory Neil Shapiro 	register void *p;
4440266059SGregory Neil Shapiro 	register int flags;
4540266059SGregory Neil Shapiro 	size_t size;
4640266059SGregory Neil Shapiro 	int couldbetty;
4740266059SGregory Neil Shapiro 
4840266059SGregory Neil Shapiro 	if (fp->f_flags & SMNBF)
4940266059SGregory Neil Shapiro 	{
5040266059SGregory Neil Shapiro 		fp->f_bf.smb_base = fp->f_p = fp->f_nbuf;
5140266059SGregory Neil Shapiro 		fp->f_bf.smb_size = 1;
5240266059SGregory Neil Shapiro 		return;
5340266059SGregory Neil Shapiro 	}
5440266059SGregory Neil Shapiro 	flags = sm_whatbuf(fp, &size, &couldbetty);
5540266059SGregory Neil Shapiro 	if ((p = sm_malloc(size)) == NULL)
5640266059SGregory Neil Shapiro 	{
5740266059SGregory Neil Shapiro 		fp->f_flags |= SMNBF;
5840266059SGregory Neil Shapiro 		fp->f_bf.smb_base = fp->f_p = fp->f_nbuf;
5940266059SGregory Neil Shapiro 		fp->f_bf.smb_size = 1;
6040266059SGregory Neil Shapiro 		return;
6140266059SGregory Neil Shapiro 	}
6240266059SGregory Neil Shapiro 	if (!Sm_IO_DidInit)
6340266059SGregory Neil Shapiro 		sm_init();
6440266059SGregory Neil Shapiro 	flags |= SMMBF;
6540266059SGregory Neil Shapiro 	fp->f_bf.smb_base = fp->f_p = p;
6640266059SGregory Neil Shapiro 	fp->f_bf.smb_size = size;
6740266059SGregory Neil Shapiro 	if (couldbetty && isatty(fp->f_file))
6840266059SGregory Neil Shapiro 		flags |= SMLBF;
6940266059SGregory Neil Shapiro 	fp->f_flags |= flags;
7040266059SGregory Neil Shapiro }
7140266059SGregory Neil Shapiro 
7240266059SGregory Neil Shapiro /*
7340266059SGregory Neil Shapiro **  SM_WHATBUF -- determine proper buffer for a file (internal)
7440266059SGregory Neil Shapiro **
7540266059SGregory Neil Shapiro **  Plus it fills in 'bufsize' for recommended buffer size and
7640266059SGregory Neil Shapiro **  fills in flag to indicate if 'fp' could be a tty (nothing
7740266059SGregory Neil Shapiro **  to do with "betty" :-) ).
7840266059SGregory Neil Shapiro **
7940266059SGregory Neil Shapiro **	Parameters:
8040266059SGregory Neil Shapiro **		fp -- file pointer to be buffered
8140266059SGregory Neil Shapiro **		bufsize -- new buffer size (a return)
8240266059SGregory Neil Shapiro **		couldbetty -- could be a tty (returns)
8340266059SGregory Neil Shapiro **
8440266059SGregory Neil Shapiro **	Returns:
8540266059SGregory Neil Shapiro **		Success:
8640266059SGregory Neil Shapiro **		on error:
8740266059SGregory Neil Shapiro **			SMNPT -- not seek opimized
8840266059SGregory Neil Shapiro **			SMOPT -- seek opimized
8940266059SGregory Neil Shapiro */
9040266059SGregory Neil Shapiro 
9140266059SGregory Neil Shapiro int
sm_whatbuf(fp,bufsize,couldbetty)9240266059SGregory Neil Shapiro sm_whatbuf(fp, bufsize, couldbetty)
9340266059SGregory Neil Shapiro 	register SM_FILE_T *fp;
9440266059SGregory Neil Shapiro 	size_t *bufsize;
9540266059SGregory Neil Shapiro 	int *couldbetty;
9640266059SGregory Neil Shapiro {
9740266059SGregory Neil Shapiro 	struct stat st;
9840266059SGregory Neil Shapiro 
9940266059SGregory Neil Shapiro 	if (fp->f_file < 0 || fstat(fp->f_file, &st) < 0)
10040266059SGregory Neil Shapiro 	{
10140266059SGregory Neil Shapiro 		*couldbetty = 0;
10240266059SGregory Neil Shapiro 		*bufsize = SM_IO_BUFSIZ;
10340266059SGregory Neil Shapiro 		return SMNPT;
10440266059SGregory Neil Shapiro 	}
10540266059SGregory Neil Shapiro 
10640266059SGregory Neil Shapiro 	/* could be a tty iff it is a character device */
10740266059SGregory Neil Shapiro 	*couldbetty = S_ISCHR(st.st_mode);
10840266059SGregory Neil Shapiro 	if (st.st_blksize == 0)
10940266059SGregory Neil Shapiro 	{
11040266059SGregory Neil Shapiro 		*bufsize = SM_IO_BUFSIZ;
11140266059SGregory Neil Shapiro 		return SMNPT;
11240266059SGregory Neil Shapiro 	}
11340266059SGregory Neil Shapiro 
11440266059SGregory Neil Shapiro #if SM_IO_MAX_BUF_FILE > 0
11540266059SGregory Neil Shapiro 	if (S_ISREG(st.st_mode) && st.st_blksize > SM_IO_MAX_BUF_FILE)
11640266059SGregory Neil Shapiro 		st.st_blksize = SM_IO_MAX_BUF_FILE;
1175b0945b5SGregory Neil Shapiro #endif
11840266059SGregory Neil Shapiro 
11940266059SGregory Neil Shapiro #if SM_IO_MAX_BUF > 0 || SM_IO_MIN_BUF > 0
12040266059SGregory Neil Shapiro 	if (!S_ISREG(st.st_mode))
12140266059SGregory Neil Shapiro 	{
12240266059SGregory Neil Shapiro # if SM_IO_MAX_BUF > 0
12340266059SGregory Neil Shapiro 		if (st.st_blksize > SM_IO_MAX_BUF)
12440266059SGregory Neil Shapiro 			st.st_blksize = SM_IO_MAX_BUF;
12540266059SGregory Neil Shapiro #  if SM_IO_MIN_BUF > 0
12640266059SGregory Neil Shapiro 		else
127*2fb4f839SGregory Neil Shapiro #  endif
12840266059SGregory Neil Shapiro # endif /* SM_IO_MAX_BUF > 0 */
12940266059SGregory Neil Shapiro # if SM_IO_MIN_BUF > 0
13040266059SGregory Neil Shapiro 		if (st.st_blksize < SM_IO_MIN_BUF)
13140266059SGregory Neil Shapiro 			st.st_blksize = SM_IO_MIN_BUF;
1325b0945b5SGregory Neil Shapiro # endif
13340266059SGregory Neil Shapiro 	}
13440266059SGregory Neil Shapiro #endif /* SM_IO_MAX_BUF > 0 || SM_IO_MIN_BUF > 0 */
13540266059SGregory Neil Shapiro 
13640266059SGregory Neil Shapiro 	/*
13740266059SGregory Neil Shapiro 	**  Optimise fseek() only if it is a regular file.  (The test for
13840266059SGregory Neil Shapiro 	**  sm_std_seek is mainly paranoia.)  It is safe to set _blksize
13940266059SGregory Neil Shapiro 	**  unconditionally; it will only be used if SMOPT is also set.
14040266059SGregory Neil Shapiro 	*/
14140266059SGregory Neil Shapiro 
14240266059SGregory Neil Shapiro 	if ((fp->f_flags & SMSTR) == 0)
14340266059SGregory Neil Shapiro 	{
14440266059SGregory Neil Shapiro 		*bufsize = st.st_blksize;
14540266059SGregory Neil Shapiro 		fp->f_blksize = st.st_blksize;
14640266059SGregory Neil Shapiro 	}
14740266059SGregory Neil Shapiro 	else
14840266059SGregory Neil Shapiro 		*bufsize = SM_IO_BUFSIZ;
14940266059SGregory Neil Shapiro 	if ((st.st_mode & S_IFMT) == S_IFREG &&
15040266059SGregory Neil Shapiro 	    fp->f_seek == sm_stdseek)
15140266059SGregory Neil Shapiro 		return SMOPT;
15240266059SGregory Neil Shapiro 	else
15340266059SGregory Neil Shapiro 		return SMNPT;
15440266059SGregory Neil Shapiro }
155