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