summaryrefslogtreecommitdiffstats
path: root/contrib/sendmail/libsm/setvbuf.c
diff options
context:
space:
mode:
authorgshapiro <gshapiro@FreeBSD.org>2002-02-17 21:56:45 +0000
committergshapiro <gshapiro@FreeBSD.org>2002-02-17 21:56:45 +0000
commit8449595fe97f4474b9b9a7e4edee1ef35dcff393 (patch)
treee7a33b132264d449a512ddf4a8685df097669c1d /contrib/sendmail/libsm/setvbuf.c
parent289b381b31415647269c7520d881017e2dcb27f1 (diff)
downloadFreeBSD-src-8449595fe97f4474b9b9a7e4edee1ef35dcff393.zip
FreeBSD-src-8449595fe97f4474b9b9a7e4edee1ef35dcff393.tar.gz
Import sendmail 8.12.2
Diffstat (limited to 'contrib/sendmail/libsm/setvbuf.c')
-rw-r--r--contrib/sendmail/libsm/setvbuf.c190
1 files changed, 190 insertions, 0 deletions
diff --git a/contrib/sendmail/libsm/setvbuf.c b/contrib/sendmail/libsm/setvbuf.c
new file mode 100644
index 0000000..172a767
--- /dev/null
+++ b/contrib/sendmail/libsm/setvbuf.c
@@ -0,0 +1,190 @@
+/*
+ * 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: setvbuf.c,v 1.32 2001/09/11 04:04:49 gshapiro Exp $")
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sm/io.h>
+#include <sm/heap.h>
+#include <sm/assert.h>
+#include <sm/conf.h>
+#include "local.h"
+
+/*
+** SM_IO_SETVBUF -- set the buffering type for a file
+**
+** Set one of the different kinds of buffering, optionally including
+** a buffer.
+** If 'size' is == 0 then an "optimal" size will be selected.
+** If 'buf' is == NULL then space will be allocated at 'size'.
+**
+** Parameters:
+** fp -- the file that buffering is to be changed for
+** timeout -- time allowed for completing the function
+** buf -- buffer to use
+** mode -- buffering method to use
+** size -- size of 'buf'
+**
+** Returns:
+** Failure: SM_IO_EOF
+** Success: 0 (zero)
+*/
+
+int
+sm_io_setvbuf(fp, timeout, buf, mode, size)
+ SM_FILE_T *fp;
+ int timeout;
+ char *buf;
+ int mode;
+ size_t size;
+{
+ int ret, flags;
+ size_t iosize;
+ int ttyflag;
+ int fd;
+ struct timeval to;
+
+ SM_REQUIRE_ISA(fp, SmFileMagic);
+
+ /*
+ ** Verify arguments. The `int' limit on `size' is due to this
+ ** particular implementation. Note, buf and size are ignored
+ ** when setting SM_IO_NBF.
+ */
+
+ if (mode != SM_IO_NBF)
+ if ((mode != SM_IO_FBF && mode != SM_IO_LBF &&
+ mode != SM_IO_NOW) || (int) size < 0)
+ return SM_IO_EOF;
+
+ /*
+ ** Write current buffer, if any. Discard unread input (including
+ ** ungetc data), cancel line buffering, and free old buffer if
+ ** malloc()ed. We also clear any eof condition, as if this were
+ ** a seek.
+ */
+
+ ret = 0;
+ SM_CONVERT_TIME(fp, fd, timeout, &to);
+ (void) sm_flush(fp, &timeout);
+ if (HASUB(fp))
+ FREEUB(fp);
+ fp->f_r = fp->f_lbfsize = 0;
+ flags = fp->f_flags;
+ if (flags & SMMBF)
+ {
+ sm_free((void *) fp->f_bf.smb_base);
+ fp->f_bf.smb_base = NULL;
+ }
+ flags &= ~(SMLBF | SMNBF | SMMBF | SMOPT | SMNPT | SMFEOF | SMNOW |
+ SMFBF);
+
+ /* If setting unbuffered mode, skip all the hard work. */
+ if (mode == SM_IO_NBF)
+ goto nbf;
+
+ /*
+ ** Find optimal I/O size for seek optimization. This also returns
+ ** a `tty flag' to suggest that we check isatty(fd), but we do not
+ ** care since our caller told us how to buffer.
+ */
+
+ flags |= sm_whatbuf(fp, &iosize, &ttyflag);
+ if (size == 0)
+ {
+ buf = NULL; /* force local allocation */
+ size = iosize;
+ }
+
+ /* Allocate buffer if needed. */
+ if (buf == NULL)
+ {
+ if ((buf = sm_malloc(size)) == NULL)
+ {
+ /*
+ ** Unable to honor user's request. We will return
+ ** failure, but try again with file system size.
+ */
+
+ ret = SM_IO_EOF;
+ if (size != iosize)
+ {
+ size = iosize;
+ buf = sm_malloc(size);
+ }
+ }
+ if (buf == NULL)
+ {
+ /* No luck; switch to unbuffered I/O. */
+nbf:
+ fp->f_flags = flags | SMNBF;
+ fp->f_w = 0;
+ fp->f_bf.smb_base = fp->f_p = fp->f_nbuf;
+ fp->f_bf.smb_size = 1;
+ return ret;
+ }
+ flags |= SMMBF;
+ }
+
+ /*
+ ** Kill any seek optimization if the buffer is not the
+ ** right size.
+ **
+ ** SHOULD WE ALLOW MULTIPLES HERE (i.e., ok iff (size % iosize) == 0)?
+ */
+
+ if (size != iosize)
+ flags |= SMNPT;
+
+ /*
+ ** Fix up the SM_FILE_T fields, and set sm_cleanup for output flush on
+ ** exit (since we are buffered in some way).
+ */
+
+ if (mode == SM_IO_LBF)
+ flags |= SMLBF;
+ else if (mode == SM_IO_NOW)
+ flags |= SMNOW;
+ else if (mode == SM_IO_FBF)
+ flags |= SMFBF;
+ fp->f_flags = flags;
+ fp->f_bf.smb_base = fp->f_p = (unsigned char *)buf;
+ fp->f_bf.smb_size = size;
+ /* fp->f_lbfsize is still 0 */
+ if (flags & SMWR)
+ {
+ /*
+ ** Begin or continue writing: see sm_wsetup(). Note
+ ** that SMNBF is impossible (it was handled earlier).
+ */
+
+ if (flags & SMLBF)
+ {
+ fp->f_w = 0;
+ fp->f_lbfsize = -fp->f_bf.smb_size;
+ }
+ else
+ fp->f_w = size;
+ }
+ else
+ {
+ /* begin/continue reading, or stay in intermediate state */
+ fp->f_w = 0;
+ }
+
+ atexit(sm_cleanup);
+ return ret;
+}
OpenPOWER on IntegriCloud