summaryrefslogtreecommitdiffstats
path: root/contrib/sendmail/libsm/makebuf.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/sendmail/libsm/makebuf.c')
-rw-r--r--contrib/sendmail/libsm/makebuf.c154
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;
+}
OpenPOWER on IntegriCloud