1122207Sharti/* 2122207Sharti * Copyright (c) 2000-2001 Proofpoint, Inc. and its suppliers. 3122207Sharti * All rights reserved. 4122207Sharti * Copyright (c) 1990, 1993 5122207Sharti * The Regents of the University of California. All rights reserved. 6122207Sharti * 7122207Sharti * This code is derived from software contributed to Berkeley by 8122207Sharti * Chris Torek. 9122207Sharti * 10122207Sharti * By using this file, you agree to the terms and conditions set 11122207Sharti * forth in the LICENSE file which can be found at the top level of 12122207Sharti * the sendmail distribution. 13122207Sharti */ 14122207Sharti 15122207Sharti#include <sm/gen.h> 16122207ShartiSM_RCSID("@(#)$Id: makebuf.c,v 1.27 2013-11-22 20:51:43 ca Exp $") 17122207Sharti#include <stdlib.h> 18122207Sharti#include <unistd.h> 19122207Sharti#include <sys/types.h> 20122207Sharti#include <sys/stat.h> 21122207Sharti#include <sm/io.h> 22122207Sharti#include <sm/heap.h> 23122207Sharti#include <sm/conf.h> 24122207Sharti#include "local.h" 25122207Sharti 26122207Sharti/* 27122207Sharti** SM_MAKEBUF -- make a buffer for the file 28122207Sharti** 29122207Sharti** Parameters: 30122207Sharti** fp -- the file to be buffered 31122207Sharti** 32122207Sharti** Returns: 33122207Sharti** nothing 34122207Sharti** 35122207Sharti** Allocate a file buffer, or switch to unbuffered I/O. 36122207Sharti** By default tty devices default to line buffered. 37122207Sharti*/ 38122207Sharti 39122207Shartivoid 40122207Shartism_makebuf(fp) 41122207Sharti register SM_FILE_T *fp; 42122207Sharti{ 43122207Sharti register void *p; 44122207Sharti register int flags; 45122207Sharti size_t size; 46122207Sharti int couldbetty; 47122207Sharti 48122207Sharti if (fp->f_flags & SMNBF) 49122207Sharti { 50122207Sharti fp->f_bf.smb_base = fp->f_p = fp->f_nbuf; 51122207Sharti fp->f_bf.smb_size = 1; 52122207Sharti return; 53122207Sharti } 54122207Sharti flags = sm_whatbuf(fp, &size, &couldbetty); 55122207Sharti if ((p = sm_malloc(size)) == NULL) 56122207Sharti { 57122207Sharti fp->f_flags |= SMNBF; 58122207Sharti fp->f_bf.smb_base = fp->f_p = fp->f_nbuf; 59122207Sharti fp->f_bf.smb_size = 1; 60122207Sharti return; 61122207Sharti } 62122207Sharti if (!Sm_IO_DidInit) 63122207Sharti sm_init(); 64122207Sharti flags |= SMMBF; 65122207Sharti fp->f_bf.smb_base = fp->f_p = p; 66122207Sharti fp->f_bf.smb_size = size; 67122207Sharti if (couldbetty && isatty(fp->f_file)) 68122207Sharti flags |= SMLBF; 69122207Sharti fp->f_flags |= flags; 70122207Sharti} 71122207Sharti 72122207Sharti/* 73122207Sharti** SM_WHATBUF -- determine proper buffer for a file (internal) 74122207Sharti** 75122207Sharti** Plus it fills in 'bufsize' for recommended buffer size and 76122207Sharti** fills in flag to indicate if 'fp' could be a tty (nothing 77122207Sharti** to do with "betty" :-) ). 78122207Sharti** 79122207Sharti** Parameters: 80122207Sharti** fp -- file pointer to be buffered 81122207Sharti** bufsize -- new buffer size (a return) 82122207Sharti** couldbetty -- could be a tty (returns) 83122207Sharti** 84122207Sharti** Returns: 85122207Sharti** Success: 86122207Sharti** on error: 87122207Sharti** SMNPT -- not seek opimized 88122207Sharti** SMOPT -- seek opimized 89122207Sharti*/ 90122207Sharti 91122207Shartiint 92122207Shartism_whatbuf(fp, bufsize, couldbetty) 93122207Sharti register SM_FILE_T *fp; 94122207Sharti size_t *bufsize; 95122207Sharti int *couldbetty; 96122207Sharti{ 97122207Sharti struct stat st; 98122207Sharti 99122207Sharti if (fp->f_file < 0 || fstat(fp->f_file, &st) < 0) 100122207Sharti { 101122207Sharti *couldbetty = 0; 102122207Sharti *bufsize = SM_IO_BUFSIZ; 103122207Sharti return SMNPT; 104122207Sharti } 105122207Sharti 106122207Sharti /* could be a tty iff it is a character device */ 107122207Sharti *couldbetty = S_ISCHR(st.st_mode); 108122207Sharti if (st.st_blksize == 0) 109122207Sharti { 110122207Sharti *bufsize = SM_IO_BUFSIZ; 111122207Sharti return SMNPT; 112122207Sharti } 113122207Sharti 114#if SM_IO_MAX_BUF_FILE > 0 115 if (S_ISREG(st.st_mode) && st.st_blksize > SM_IO_MAX_BUF_FILE) 116 st.st_blksize = SM_IO_MAX_BUF_FILE; 117#endif /* SM_IO_MAX_BUF_FILE > 0 */ 118 119#if SM_IO_MAX_BUF > 0 || SM_IO_MIN_BUF > 0 120 if (!S_ISREG(st.st_mode)) 121 { 122# if SM_IO_MAX_BUF > 0 123 if (st.st_blksize > SM_IO_MAX_BUF) 124 st.st_blksize = SM_IO_MAX_BUF; 125# if SM_IO_MIN_BUF > 0 126 else 127# endif /* SM_IO_MIN_BUF > 0 */ 128# endif /* SM_IO_MAX_BUF > 0 */ 129# if SM_IO_MIN_BUF > 0 130 if (st.st_blksize < SM_IO_MIN_BUF) 131 st.st_blksize = SM_IO_MIN_BUF; 132# endif /* SM_IO_MIN_BUF > 0 */ 133 } 134#endif /* SM_IO_MAX_BUF > 0 || SM_IO_MIN_BUF > 0 */ 135 136 /* 137 ** Optimise fseek() only if it is a regular file. (The test for 138 ** sm_std_seek is mainly paranoia.) It is safe to set _blksize 139 ** unconditionally; it will only be used if SMOPT is also set. 140 */ 141 142 if ((fp->f_flags & SMSTR) == 0) 143 { 144 *bufsize = st.st_blksize; 145 fp->f_blksize = st.st_blksize; 146 } 147 else 148 *bufsize = SM_IO_BUFSIZ; 149 if ((st.st_mode & S_IFMT) == S_IFREG && 150 fp->f_seek == sm_stdseek) 151 return SMOPT; 152 else 153 return SMNPT; 154} 155