makebuf.c revision 98121
1176669Spiso/* 2176669Spiso * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. 3176669Spiso * All rights reserved. 4176669Spiso * Copyright (c) 1990, 1993 5176669Spiso * The Regents of the University of California. All rights reserved. 6176669Spiso * 7176669Spiso * This code is derived from software contributed to Berkeley by 8176669Spiso * Chris Torek. 9176669Spiso * 10176669Spiso * By using this file, you agree to the terms and conditions set 11176669Spiso * forth in the LICENSE file which can be found at the top level of 12176669Spiso * the sendmail distribution. 13176669Spiso */ 14176669Spiso 15176669Spiso#include <sm/gen.h> 16176669SpisoSM_RCSID("@(#)$Id: makebuf.c,v 1.26 2001/10/31 16:04:08 ca Exp $") 17176669Spiso#include <stdlib.h> 18176669Spiso#include <unistd.h> 19176669Spiso#include <sys/types.h> 20176669Spiso#include <sys/stat.h> 21176669Spiso#include <sm/io.h> 22176669Spiso#include <sm/heap.h> 23176669Spiso#include <sm/conf.h> 24176669Spiso#include "local.h" 25176669Spiso 26176669Spiso/* 27176669Spiso** SM_MAKEBUF -- make a buffer for the file 28176669Spiso** 29176669Spiso** Parameters: 30176669Spiso** fp -- the file to be buffered 31176669Spiso** 32176669Spiso** Returns: 33176669Spiso** nothing 34176669Spiso** 35176669Spiso** Allocate a file buffer, or switch to unbuffered I/O. 36176669Spiso** By default tty devices default to line buffered. 37176669Spiso*/ 38176669Spiso 39200580Sluigivoid 40200580Sluigism_makebuf(fp) 41176669Spiso register SM_FILE_T *fp; 42176669Spiso{ 43176669Spiso register void *p; 44176669Spiso register int flags; 45176669Spiso size_t size; 46176669Spiso int couldbetty; 47176669Spiso 48176669Spiso if (fp->f_flags & SMNBF) 49176669Spiso { 50176669Spiso fp->f_bf.smb_base = fp->f_p = fp->f_nbuf; 51176669Spiso fp->f_bf.smb_size = 1; 52243401Sglebius return; 53243401Sglebius } 54176669Spiso flags = sm_whatbuf(fp, &size, &couldbetty); 55176669Spiso if ((p = sm_malloc(size)) == NULL) 56215701Sdim { 57195727Srwatson fp->f_flags |= SMNBF; 58176669Spiso fp->f_bf.smb_base = fp->f_p = fp->f_nbuf; 59200909Sluigi fp->f_bf.smb_size = 1; 60176669Spiso return; 61176669Spiso } 62176669Spiso if (!Sm_IO_DidInit) 63176669Spiso sm_init(); 64200897Sluigi flags |= SMMBF; 65176669Spiso fp->f_bf.smb_base = fp->f_p = p; 66200897Sluigi fp->f_bf.smb_size = size; 67200909Sluigi if (couldbetty && isatty(fp->f_file)) 68176669Spiso flags |= SMLBF; 69200897Sluigi fp->f_flags |= flags; 70176669Spiso} 71200909Sluigi 72200909Sluigi/* 73200909Sluigi** SM_WHATBUF -- determine proper buffer for a file (internal) 74200909Sluigi** 75200909Sluigi** Plus it fills in 'bufsize' for recommended buffer size and 76200909Sluigi** fills in flag to indicate if 'fp' could be a tty (nothing 77200909Sluigi** to do with "betty" :-) ). 78200909Sluigi** 79200909Sluigi** Parameters: 80200909Sluigi** fp -- file pointer to be buffered 81200909Sluigi** bufsize -- new buffer size (a return) 82176669Spiso** couldbetty -- could be a tty (returns) 83200909Sluigi** 84176669Spiso** Returns: 85200909Sluigi** Success: 86176669Spiso** on error: 87176669Spiso** SMNPT -- not seek opimized 88200897Sluigi** SMOPT -- seek opimized 89200897Sluigi*/ 90200897Sluigi 91176669Spisoint 92200897Sluigism_whatbuf(fp, bufsize, couldbetty) 93176669Spiso register SM_FILE_T *fp; 94200897Sluigi size_t *bufsize; 95200909Sluigi int *couldbetty; 96176669Spiso{ 97200897Sluigi struct stat st; 98200897Sluigi 99200909Sluigi if (fp->f_file < 0 || fstat(fp->f_file, &st) < 0) 100200909Sluigi { 101200897Sluigi *couldbetty = 0; 102200897Sluigi *bufsize = SM_IO_BUFSIZ; 103176669Spiso return SMNPT; 104176669Spiso } 105176669Spiso 106176669Spiso /* could be a tty iff it is a character device */ 107176669Spiso *couldbetty = S_ISCHR(st.st_mode); 108176669Spiso if (st.st_blksize == 0) 109176669Spiso { 110176669Spiso *bufsize = SM_IO_BUFSIZ; 111176669Spiso return SMNPT; 112176669Spiso } 113176669Spiso 114176669Spiso#if SM_IO_MAX_BUF_FILE > 0 115176669Spiso if (S_ISREG(st.st_mode) && st.st_blksize > SM_IO_MAX_BUF_FILE) 116176669Spiso st.st_blksize = SM_IO_MAX_BUF_FILE; 117176669Spiso#endif /* SM_IO_MAX_BUF_FILE > 0 */ 118176669Spiso 119176669Spiso#if SM_IO_MAX_BUF > 0 || SM_IO_MIN_BUF > 0 120176669Spiso if (!S_ISREG(st.st_mode)) 121176669Spiso { 122176669Spiso# if SM_IO_MAX_BUF > 0 123176669Spiso if (st.st_blksize > SM_IO_MAX_BUF) 124176669Spiso st.st_blksize = SM_IO_MAX_BUF; 125176669Spiso# if SM_IO_MIN_BUF > 0 126176669Spiso else 127176669Spiso# endif /* SM_IO_MIN_BUF > 0 */ 128176669Spiso# endif /* SM_IO_MAX_BUF > 0 */ 129176669Spiso# if SM_IO_MIN_BUF > 0 130176669Spiso if (st.st_blksize < SM_IO_MIN_BUF) 131176669Spiso st.st_blksize = SM_IO_MIN_BUF; 132176669Spiso# endif /* SM_IO_MIN_BUF > 0 */ 133176669Spiso } 134176669Spiso#endif /* SM_IO_MAX_BUF > 0 || SM_IO_MIN_BUF > 0 */ 135200909Sluigi 136176669Spiso /* 137200909Sluigi ** Optimise fseek() only if it is a regular file. (The test for 138176669Spiso ** sm_std_seek is mainly paranoia.) It is safe to set _blksize 139176669Spiso ** unconditionally; it will only be used if SMOPT is also set. 140176669Spiso */ 141176669Spiso 142220837Sglebius if ((fp->f_flags & SMSTR) == 0) 143176669Spiso { 144176669Spiso *bufsize = st.st_blksize; 145176669Spiso fp->f_blksize = st.st_blksize; 146176669Spiso } 147176669Spiso else 148176669Spiso *bufsize = SM_IO_BUFSIZ; 149176669Spiso if ((st.st_mode & S_IFMT) == S_IFREG && 150176669Spiso fp->f_seek == sm_stdseek) 151176669Spiso return SMOPT; 152176669Spiso else 153176669Spiso return SMNPT; 154176669Spiso} 155176669Spiso