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> 16 SM_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 39 void 40 sm_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 91 int 92 sm_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 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 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 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