1 /* 2 * Copyright (c) 2000-2001 Sendmail, 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 #pragma ident "%Z%%M% %I% %E% SMI" 16 17 #include <sm/gen.h> 18 SM_RCSID("@(#)$Id: makebuf.c,v 1.26 2001/10/31 16:04:08 ca Exp $") 19 #include <stdlib.h> 20 #include <unistd.h> 21 #include <sys/types.h> 22 #include <sys/stat.h> 23 #include <sm/io.h> 24 #include <sm/heap.h> 25 #include <sm/conf.h> 26 #include "local.h" 27 28 /* 29 ** SM_MAKEBUF -- make a buffer for the file 30 ** 31 ** Parameters: 32 ** fp -- the file to be buffered 33 ** 34 ** Returns: 35 ** nothing 36 ** 37 ** Allocate a file buffer, or switch to unbuffered I/O. 38 ** By default tty devices default to line buffered. 39 */ 40 41 void 42 sm_makebuf(fp) 43 register SM_FILE_T *fp; 44 { 45 register void *p; 46 register int flags; 47 size_t size; 48 int couldbetty; 49 50 if (fp->f_flags & SMNBF) 51 { 52 fp->f_bf.smb_base = fp->f_p = fp->f_nbuf; 53 fp->f_bf.smb_size = 1; 54 return; 55 } 56 flags = sm_whatbuf(fp, &size, &couldbetty); 57 if ((p = sm_malloc(size)) == NULL) 58 { 59 fp->f_flags |= SMNBF; 60 fp->f_bf.smb_base = fp->f_p = fp->f_nbuf; 61 fp->f_bf.smb_size = 1; 62 return; 63 } 64 if (!Sm_IO_DidInit) 65 sm_init(); 66 flags |= SMMBF; 67 fp->f_bf.smb_base = fp->f_p = p; 68 fp->f_bf.smb_size = size; 69 if (couldbetty && isatty(fp->f_file)) 70 flags |= SMLBF; 71 fp->f_flags |= flags; 72 } 73 74 /* 75 ** SM_WHATBUF -- determine proper buffer for a file (internal) 76 ** 77 ** Plus it fills in 'bufsize' for recommended buffer size and 78 ** fills in flag to indicate if 'fp' could be a tty (nothing 79 ** to do with "betty" :-) ). 80 ** 81 ** Parameters: 82 ** fp -- file pointer to be buffered 83 ** bufsize -- new buffer size (a return) 84 ** couldbetty -- could be a tty (returns) 85 ** 86 ** Returns: 87 ** Success: 88 ** on error: 89 ** SMNPT -- not seek opimized 90 ** SMOPT -- seek opimized 91 */ 92 93 int 94 sm_whatbuf(fp, bufsize, couldbetty) 95 register SM_FILE_T *fp; 96 size_t *bufsize; 97 int *couldbetty; 98 { 99 struct stat st; 100 101 if (fp->f_file < 0 || fstat(fp->f_file, &st) < 0) 102 { 103 *couldbetty = 0; 104 *bufsize = SM_IO_BUFSIZ; 105 return SMNPT; 106 } 107 108 /* could be a tty iff it is a character device */ 109 *couldbetty = S_ISCHR(st.st_mode); 110 if (st.st_blksize == 0) 111 { 112 *bufsize = SM_IO_BUFSIZ; 113 return SMNPT; 114 } 115 116 #if SM_IO_MAX_BUF_FILE > 0 117 if (S_ISREG(st.st_mode) && st.st_blksize > SM_IO_MAX_BUF_FILE) 118 st.st_blksize = SM_IO_MAX_BUF_FILE; 119 #endif /* SM_IO_MAX_BUF_FILE > 0 */ 120 121 #if SM_IO_MAX_BUF > 0 || SM_IO_MIN_BUF > 0 122 if (!S_ISREG(st.st_mode)) 123 { 124 # if SM_IO_MAX_BUF > 0 125 if (st.st_blksize > SM_IO_MAX_BUF) 126 st.st_blksize = SM_IO_MAX_BUF; 127 # if SM_IO_MIN_BUF > 0 128 else 129 # endif /* SM_IO_MIN_BUF > 0 */ 130 # endif /* SM_IO_MAX_BUF > 0 */ 131 # if SM_IO_MIN_BUF > 0 132 if (st.st_blksize < SM_IO_MIN_BUF) 133 st.st_blksize = SM_IO_MIN_BUF; 134 # endif /* SM_IO_MIN_BUF > 0 */ 135 } 136 #endif /* SM_IO_MAX_BUF > 0 || SM_IO_MIN_BUF > 0 */ 137 138 /* 139 ** Optimise fseek() only if it is a regular file. (The test for 140 ** sm_std_seek is mainly paranoia.) It is safe to set _blksize 141 ** unconditionally; it will only be used if SMOPT is also set. 142 */ 143 144 if ((fp->f_flags & SMSTR) == 0) 145 { 146 *bufsize = st.st_blksize; 147 fp->f_blksize = st.st_blksize; 148 } 149 else 150 *bufsize = SM_IO_BUFSIZ; 151 if ((st.st_mode & S_IFMT) == S_IFREG && 152 fp->f_seek == sm_stdseek) 153 return SMOPT; 154 else 155 return SMNPT; 156 } 157