diff options
Diffstat (limited to 'contrib/sendmail/libsm/makebuf.c')
-rw-r--r-- | contrib/sendmail/libsm/makebuf.c | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/contrib/sendmail/libsm/makebuf.c b/contrib/sendmail/libsm/makebuf.c new file mode 100644 index 0000000..044de8c --- /dev/null +++ b/contrib/sendmail/libsm/makebuf.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + */ + +#include <sm/gen.h> +SM_RCSID("@(#)$Id: makebuf.c,v 1.26 2001/10/31 16:04:08 ca Exp $") +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sm/io.h> +#include <sm/heap.h> +#include <sm/conf.h> +#include "local.h" + +/* +** SM_MAKEBUF -- make a buffer for the file +** +** Parameters: +** fp -- the file to be buffered +** +** Returns: +** nothing +** +** Allocate a file buffer, or switch to unbuffered I/O. +** By default tty devices default to line buffered. +*/ + +void +sm_makebuf(fp) + register SM_FILE_T *fp; +{ + register void *p; + register int flags; + size_t size; + int couldbetty; + + if (fp->f_flags & SMNBF) + { + fp->f_bf.smb_base = fp->f_p = fp->f_nbuf; + fp->f_bf.smb_size = 1; + return; + } + flags = sm_whatbuf(fp, &size, &couldbetty); + if ((p = sm_malloc(size)) == NULL) + { + fp->f_flags |= SMNBF; + fp->f_bf.smb_base = fp->f_p = fp->f_nbuf; + fp->f_bf.smb_size = 1; + return; + } + if (!Sm_IO_DidInit) + sm_init(); + flags |= SMMBF; + fp->f_bf.smb_base = fp->f_p = p; + fp->f_bf.smb_size = size; + if (couldbetty && isatty(fp->f_file)) + flags |= SMLBF; + fp->f_flags |= flags; +} + +/* +** SM_WHATBUF -- determine proper buffer for a file (internal) +** +** Plus it fills in 'bufsize' for recommended buffer size and +** fills in flag to indicate if 'fp' could be a tty (nothing +** to do with "betty" :-) ). +** +** Parameters: +** fp -- file pointer to be buffered +** bufsize -- new buffer size (a return) +** couldbetty -- could be a tty (returns) +** +** Returns: +** Success: +** on error: +** SMNPT -- not seek opimized +** SMOPT -- seek opimized +*/ + +int +sm_whatbuf(fp, bufsize, couldbetty) + register SM_FILE_T *fp; + size_t *bufsize; + int *couldbetty; +{ + struct stat st; + + if (fp->f_file < 0 || fstat(fp->f_file, &st) < 0) + { + *couldbetty = 0; + *bufsize = SM_IO_BUFSIZ; + return SMNPT; + } + + /* could be a tty iff it is a character device */ + *couldbetty = S_ISCHR(st.st_mode); + if (st.st_blksize == 0) + { + *bufsize = SM_IO_BUFSIZ; + return SMNPT; + } + +#if SM_IO_MAX_BUF_FILE > 0 + if (S_ISREG(st.st_mode) && st.st_blksize > SM_IO_MAX_BUF_FILE) + st.st_blksize = SM_IO_MAX_BUF_FILE; +#endif /* SM_IO_MAX_BUF_FILE > 0 */ + +#if SM_IO_MAX_BUF > 0 || SM_IO_MIN_BUF > 0 + if (!S_ISREG(st.st_mode)) + { +# if SM_IO_MAX_BUF > 0 + if (st.st_blksize > SM_IO_MAX_BUF) + st.st_blksize = SM_IO_MAX_BUF; +# if SM_IO_MIN_BUF > 0 + else +# endif /* SM_IO_MIN_BUF > 0 */ +# endif /* SM_IO_MAX_BUF > 0 */ +# if SM_IO_MIN_BUF > 0 + if (st.st_blksize < SM_IO_MIN_BUF) + st.st_blksize = SM_IO_MIN_BUF; +# endif /* SM_IO_MIN_BUF > 0 */ + } +#endif /* SM_IO_MAX_BUF > 0 || SM_IO_MIN_BUF > 0 */ + + /* + ** Optimise fseek() only if it is a regular file. (The test for + ** sm_std_seek is mainly paranoia.) It is safe to set _blksize + ** unconditionally; it will only be used if SMOPT is also set. + */ + + if ((fp->f_flags & SMSTR) == 0) + { + *bufsize = st.st_blksize; + fp->f_blksize = st.st_blksize; + } + else + *bufsize = SM_IO_BUFSIZ; + if ((st.st_mode & S_IFMT) == S_IFREG && + fp->f_seek == sm_stdseek) + return SMOPT; + else + return SMNPT; +} |