summaryrefslogtreecommitdiffstats
path: root/contrib/sendmail/libsm/local.h
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/sendmail/libsm/local.h')
-rw-r--r--contrib/sendmail/libsm/local.h340
1 files changed, 340 insertions, 0 deletions
diff --git a/contrib/sendmail/libsm/local.h b/contrib/sendmail/libsm/local.h
new file mode 100644
index 0000000..f97859e
--- /dev/null
+++ b/contrib/sendmail/libsm/local.h
@@ -0,0 +1,340 @@
+/*
+ * 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.
+ *
+ * $Id: local.h,v 1.48 2001/05/14 20:42:29 gshapiro Exp $
+ */
+
+/*
+** Information local to this implementation of stdio,
+** in particular, macros and private variables.
+*/
+
+#include <sys/time.h>
+#if !SM_CONF_MEMCHR
+# include <memory.h>
+#endif /* !SM_CONF_MEMCHR */
+#include <sm/heap.h>
+
+int sm_flush __P((SM_FILE_T *, int *));
+SM_FILE_T *smfp __P((void));
+int sm_refill __P((SM_FILE_T *, int));
+void sm_init __P((void));
+void sm_cleanup __P((void));
+void sm_makebuf __P((SM_FILE_T *));
+int sm_whatbuf __P((SM_FILE_T *, size_t *, int *));
+int sm_fwalk __P((int (*)(SM_FILE_T *, int *), int *));
+int sm_wsetup __P((SM_FILE_T *));
+int sm_flags __P((int));
+SM_FILE_T *sm_fp __P((const SM_FILE_T *, const int, SM_FILE_T *));
+int sm_vprintf __P((int, char const *, va_list));
+int sm_vfscanf __P((SM_FILE_T *, int, char const *, va_list));
+
+/* std io functions */
+ssize_t sm_stdread __P((SM_FILE_T *, char *, size_t));
+ssize_t sm_stdwrite __P((SM_FILE_T *, char const *, size_t));
+off_t sm_stdseek __P((SM_FILE_T *, off_t, int));
+int sm_stdclose __P((SM_FILE_T *));
+int sm_stdopen __P((SM_FILE_T *, const void *, int, const void *));
+int sm_stdfdopen __P((SM_FILE_T *, const void *, int, const void *));
+int sm_stdsetinfo __P((SM_FILE_T *, int , void *));
+int sm_stdgetinfo __P((SM_FILE_T *, int , void *));
+
+/* stdio io functions */
+ssize_t sm_stdioread __P((SM_FILE_T *, char *, size_t));
+ssize_t sm_stdiowrite __P((SM_FILE_T *, char const *, size_t));
+off_t sm_stdioseek __P((SM_FILE_T *, off_t, int));
+int sm_stdioclose __P((SM_FILE_T *));
+int sm_stdioopen __P((SM_FILE_T *, const void *, int, const void *));
+int sm_stdiosetinfo __P((SM_FILE_T *, int , void *));
+int sm_stdiogetinfo __P((SM_FILE_T *, int , void *));
+
+/* string io functions */
+ssize_t sm_strread __P((SM_FILE_T *, char *, size_t));
+ssize_t sm_strwrite __P((SM_FILE_T *, char const *, size_t));
+off_t sm_strseek __P((SM_FILE_T *, off_t, int));
+int sm_strclose __P((SM_FILE_T *));
+int sm_stropen __P((SM_FILE_T *, const void *, int, const void *));
+int sm_strsetinfo __P((SM_FILE_T *, int , void *));
+int sm_strgetinfo __P((SM_FILE_T *, int , void *));
+
+/* syslog io functions */
+ssize_t sm_syslogread __P((SM_FILE_T *, char *, size_t));
+ssize_t sm_syslogwrite __P((SM_FILE_T *, char const *, size_t));
+off_t sm_syslogseek __P((SM_FILE_T *, off_t, int));
+int sm_syslogclose __P((SM_FILE_T *));
+int sm_syslogopen __P((SM_FILE_T *, const void *, int, const void *));
+int sm_syslogsetinfo __P((SM_FILE_T *, int , void *));
+int sm_sysloggetinfo __P((SM_FILE_T *, int , void *));
+
+/* should be defined in sys/time.h */
+#ifndef timersub
+# define timersub(tvp, uvp, vvp) \
+ do \
+ { \
+ (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \
+ (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \
+ if ((vvp)->tv_usec < 0) \
+ { \
+ (vvp)->tv_sec--; \
+ (vvp)->tv_usec += 1000000; \
+ } \
+ } while (0)
+#endif /* !timersub */
+
+#ifndef timeradd
+# define timeradd(tvp, uvp, vvp) \
+ do \
+ { \
+ (vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \
+ (vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \
+ if ((vvp)->tv_usec >= 1000000) \
+ { \
+ (vvp)->tv_sec++; \
+ (vvp)->tv_usec -= 1000000; \
+ } \
+ } while (0)
+#endif /* !timeradd */
+
+#ifndef timercmp
+# define timercmp(tvp, uvp, cmp) \
+ (((tvp)->tv_sec == (uvp)->tv_sec) ? \
+ ((tvp)->tv_usec cmp (uvp)->tv_usec) : \
+ ((tvp)->tv_sec cmp (uvp)->tv_sec))
+#endif /* !timercmp */
+
+extern bool Sm_IO_DidInit;
+
+/* Return true iff the given SM_FILE_T cannot be written now. */
+#define cantwrite(fp) \
+ ((((fp)->f_flags & SMWR) == 0 || (fp)->f_bf.smb_base == NULL) && \
+ sm_wsetup(fp))
+
+/*
+** Test whether the given stdio file has an active ungetc buffer;
+** release such a buffer, without restoring ordinary unread data.
+*/
+
+#define HASUB(fp) ((fp)->f_ub.smb_base != NULL)
+#define FREEUB(fp) \
+{ \
+ if ((fp)->f_ub.smb_base != (fp)->f_ubuf) \
+ sm_free((char *)(fp)->f_ub.smb_base); \
+ (fp)->f_ub.smb_base = NULL; \
+}
+
+/* Test for an fgetln() buffer. */
+#define HASLB(fp) ((fp)->f_lb.smb_base != NULL)
+#define FREELB(fp) \
+{ \
+ sm_free((char *)(fp)->f_lb.smb_base); \
+ (fp)->f_lb.smb_base = NULL; \
+}
+
+struct sm_io_obj
+{
+ int file;
+};
+
+extern const char SmFileMagic[];
+
+#ifndef ALIGNBYTES
+# define ALIGNBYTES (sizeof(long) - 1)
+# define ALIGN(p) (((unsigned long)(p) + ALIGNBYTES) & ~ALIGNBYTES)
+#endif /* ALIGNBYTES */
+
+#define sm_io_flockfile(fp) ((void) 0)
+#define sm_io_funlockfile(fp) ((void) 0)
+
+#ifndef FDSET_CAST
+# define FDSET_CAST /* empty cast for fd_set arg to select */
+#endif
+
+/*
+** SM_CONVERT_TIME -- convert the API timeout flag for select() usage.
+**
+** This takes a 'fp' (a file type pointer) and obtains the "raw"
+** file descriptor (fd) if possible. The 'fd' is needed to possibly
+** switch the mode of the file (blocking/non-blocking) to match
+** the type of timeout. If timeout is SM_TIME_FOREVER then the
+** timeout using select won't be needed and the file is best placed
+** in blocking mode. If there is to be a finite timeout then the file
+** is best placed in non-blocking mode. Then, if not enough can be
+** written, select() can be used to test when something can be written
+** yet still timeout if the wait is too long.
+** If the mode is already in the correct state we don't change it.
+** Iff (yes "iff") the 'fd' is "-1" in value then the mode change
+** will not happen. This situation arises when a late-binding-to-disk
+** file type is in use. An example of this is the sendmail buffered
+** file type (in sendmail/bf.c).
+**
+** Parameters
+** fp -- the file pointer the timeout is for
+** fd -- to become the file descriptor value from 'fp'
+** val -- the timeout value to be converted
+** time -- a struct timeval holding the converted value
+**
+** Returns
+** nothing, this is flow-through code
+**
+** Side Effects:
+** May or may not change the mode of a currently open file.
+** The file mode may be changed to O_NONBLOCK or ~O_NONBLOCK
+** (meaning block). This is done to best match the type of
+** timeout and for (possible) use with select().
+*/
+
+# define SM_CONVERT_TIME(fp, fd, val, time) { \
+ if (((fd) = sm_io_getinfo(fp, SM_IO_WHAT_FD, NULL)) == -1) \
+ { \
+ /* can't get an fd, likely internal 'fake' fp */ \
+ errno = 0; \
+ } \
+ if ((val) == SM_TIME_DEFAULT) \
+ (val) = (fp)->f_timeout; \
+ if ((val) == SM_TIME_IMMEDIATE || (val) == SM_TIME_FOREVER) \
+ { \
+ (time)->tv_sec = 0; \
+ (time)->tv_usec = 0; \
+ } \
+ else \
+ { \
+ (time)->tv_sec = (val) / 1000; \
+ (time)->tv_usec = ((val) - ((time)->tv_sec * 1000)) * 10; \
+ } \
+ if ((val) == SM_TIME_FOREVER) \
+ { \
+ if ((fp)->f_timeoutstate == SM_TIME_NONBLOCK && (fd) != -1) \
+ { \
+ int ret; \
+ ret = fcntl((fd), F_GETFL, 0); \
+ if (ret == -1 || fcntl((fd), F_SETFL, \
+ ret & ~O_NONBLOCK) == -1) \
+ { \
+ /* errno should be set */ \
+ return SM_IO_EOF; \
+ } \
+ (fp)->f_timeoutstate = SM_TIME_BLOCK; \
+ if ((fp)->f_modefp != NULL) \
+ (fp)->f_modefp->f_timeoutstate = SM_TIME_BLOCK; \
+ } \
+ } \
+ else { \
+ if ((fp)->f_timeoutstate == SM_TIME_BLOCK && (fd) != -1) \
+ { \
+ int ret; \
+ ret = fcntl((fd), F_GETFL, 0); \
+ if (ret == -1 || fcntl((fd), F_SETFL, \
+ ret | O_NONBLOCK) == -1) \
+ { \
+ /* errno should be set */ \
+ return SM_IO_EOF; \
+ } \
+ (fp)->f_timeoutstate = SM_TIME_NONBLOCK; \
+ if ((fp)->f_modefp != NULL) \
+ (fp)->f_modefp->f_timeoutstate = SM_TIME_NONBLOCK; \
+ } \
+ } \
+}
+
+/*
+** SM_IO_WR_TIMEOUT -- setup the timeout for the write
+**
+** This #define uses a select() to wait for the 'fd' to become writable.
+** The select() can be active for up to 'to' time. The select may not
+** use all of the the 'to' time. Hence, the amount of "wall-clock" time is
+** measured to decide how much to subtract from 'to' to update it. On some
+** BSD-based/like systems the timeout for a select is updated for the
+** amount of time used. On many/most systems this does not happen. Therefore
+** the updating of 'to' must be done ourselves; a copy of 'to' is passed
+** since a BSD-like system will have updated it and we don't want to
+** double the time used!
+** Note: if a valid 'fd' doesn't exist yet, don't use this (e.g. the
+** sendmail buffered file type in sendmail/bf.c; see fvwrite.c).
+**
+** Parameters
+** fd -- a file descriptor for doing select() with
+** timeout -- the original user set value.
+**
+** Returns
+** nothing, this is flow through code
+**
+** Side Effects:
+** adjusts 'timeout' for time used
+*/
+
+#define SM_IO_WR_TIMEOUT(fp, fd, to) { \
+ struct timeval sm_io_to_before, sm_io_to_after, sm_io_to_diff; \
+ struct timeval sm_io_to; \
+ int sm_io_to_sel; \
+ fd_set sm_io_to_mask, sm_io_x_mask; \
+ errno = 0; \
+ if ((to) == SM_TIME_DEFAULT) \
+ (to) = (fp)->f_timeout; \
+ if ((to) == SM_TIME_IMMEDIATE) \
+ { \
+ errno = EAGAIN; \
+ return SM_IO_EOF; \
+ } \
+ else if ((to) == SM_TIME_FOREVER) \
+ { \
+ errno = EINVAL; \
+ return SM_IO_EOF; \
+ } \
+ else \
+ { \
+ sm_io_to.tv_sec = (to) / 1000; \
+ sm_io_to.tv_usec = ((to) - (sm_io_to.tv_sec * 1000)) * 10; \
+ } \
+ FD_ZERO(&sm_io_to_mask); \
+ FD_SET((fd), &sm_io_to_mask); \
+ FD_ZERO(&sm_io_x_mask); \
+ FD_SET((fd), &sm_io_x_mask); \
+ if (gettimeofday(&sm_io_to_before, NULL) < 0) \
+ return SM_IO_EOF; \
+ sm_io_to_sel = select((fd) + 1, NULL, &sm_io_to_mask, &sm_io_x_mask, \
+ &sm_io_to); \
+ if (sm_io_to_sel < 0) \
+ { \
+ /* something went wrong, errno set */ \
+ return SM_IO_EOF; \
+ } \
+ else if (sm_io_to_sel == 0) \
+ { \
+ /* timeout */ \
+ errno = EAGAIN; \
+ return SM_IO_EOF; \
+ } \
+ /* else loop again */ \
+ if (gettimeofday(&sm_io_to_after, NULL) < 0) \
+ return SM_IO_EOF; \
+ timersub(&sm_io_to_before, &sm_io_to_after, &sm_io_to_diff); \
+ timersub(&sm_io_to, &sm_io_to_diff, &sm_io_to); \
+ (to) -= (sm_io_to.tv_sec * 1000); \
+ (to) -= (sm_io_to.tv_usec / 10); \
+ if ((to) < 0) \
+ (to) = 0; \
+}
+
+/*
+** If there is no 'fd' just error (we can't timeout). If the timeout
+** is SM_TIME_FOREVER then there is no need to do a timeout with
+** select since this will be a real error. If the error is not
+** EAGAIN/EWOULDBLOCK (from a nonblocking) then it's a real error.
+** Specify the condition here as macro so it can be used in several places.
+*/
+
+#define IS_IO_ERROR(fd, ret, to) \
+ ((fd) < 0 || \
+ ((ret) < 0 && errno != EAGAIN && errno != EWOULDBLOCK) || \
+ (to) == SM_TIME_FOREVER)
+
OpenPOWER on IntegriCloud