1/* 2 * Copyright (c) 2000-2001 Proofpoint, Inc. and its suppliers. 3 * All rights reserved. 4 * Copyright (c) 1990, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Chris Torek. 9 * 10 * By using this file, you agree to the terms and conditions set 11 * forth in the LICENSE file which can be found at the top level of 12 * the sendmail distribution. 13 */ 14 15#include <sm/gen.h> 16SM_RCSID("@(#)$Id: makebuf.c,v 1.27 2013-11-22 20:51:43 ca Exp $") 17#include <stdlib.h> 18#include <unistd.h> 19#include <sys/types.h> 20#include <sys/stat.h> 21#include <sm/io.h> 22#include <sm/heap.h> 23#include <sm/conf.h> 24#include "local.h" 25 26/* 27** SM_MAKEBUF -- make a buffer for the file 28** 29** Parameters: 30** fp -- the file to be buffered 31** 32** Returns: 33** nothing 34** 35** Allocate a file buffer, or switch to unbuffered I/O. 36** By default tty devices default to line buffered. 37*/ 38 39void 40sm_makebuf(fp) 41 register SM_FILE_T *fp; 42{ 43 register void *p; 44 register int flags; 45 size_t size; 46 int couldbetty; 47 48 if (fp->f_flags & SMNBF) 49 { 50 fp->f_bf.smb_base = fp->f_p = fp->f_nbuf; 51 fp->f_bf.smb_size = 1; 52 return; 53 } 54 flags = sm_whatbuf(fp, &size, &couldbetty); 55 if ((p = sm_malloc(size)) == NULL) 56 { 57 fp->f_flags |= SMNBF; 58 fp->f_bf.smb_base = fp->f_p = fp->f_nbuf; 59 fp->f_bf.smb_size = 1; 60 return; 61 } 62 if (!Sm_IO_DidInit) 63 sm_init(); 64 flags |= SMMBF; 65 fp->f_bf.smb_base = fp->f_p = p; 66 fp->f_bf.smb_size = size; 67 if (couldbetty && isatty(fp->f_file)) 68 flags |= SMLBF; 69 fp->f_flags |= flags; 70} 71 72/* 73** SM_WHATBUF -- determine proper buffer for a file (internal) 74** 75** Plus it fills in 'bufsize' for recommended buffer size and 76** fills in flag to indicate if 'fp' could be a tty (nothing 77** to do with "betty" :-) ). 78** 79** Parameters: 80** fp -- file pointer to be buffered 81** bufsize -- new buffer size (a return) 82** couldbetty -- could be a tty (returns) 83** 84** Returns: 85** Success: 86** on error: 87** SMNPT -- not seek opimized 88** SMOPT -- seek opimized 89*/ 90 91int 92sm_whatbuf(fp, bufsize, couldbetty) 93 register SM_FILE_T *fp; 94 size_t *bufsize; 95 int *couldbetty; 96{ 97 struct stat st; 98 99 if (fp->f_file < 0 || fstat(fp->f_file, &st) < 0) 100 { 101 *couldbetty = 0; 102 *bufsize = SM_IO_BUFSIZ; 103 return SMNPT; 104 } 105 106 /* could be a tty iff it is a character device */ 107 *couldbetty = S_ISCHR(st.st_mode); 108 if (st.st_blksize == 0) 109 { 110 *bufsize = SM_IO_BUFSIZ; 111 return SMNPT; 112 } 113 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