2 * Copyright (c) 2000-2002, 2004-2006 Sendmail, Inc. and its suppliers.
4 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
10 * By using this file, you agree to the terms and conditions set
11 * forth in the LICENSE file which can be found at the top level of
12 * the sendmail distribution.
14 * $Id: local.h,v 1.58 2006/12/19 19:44:23 ca Exp $
17 #pragma ident "%Z%%M% %I% %E% SMI"
20 ** Information local to this implementation of stdio,
21 ** in particular, macros and private variables.
27 #endif /* !SM_CONF_MEMCHR */
30 int sm_flush
__P((SM_FILE_T
*, int *));
31 SM_FILE_T
*smfp
__P((void));
32 int sm_refill
__P((SM_FILE_T
*, int));
33 void sm_init
__P((void));
34 void sm_cleanup
__P((void));
35 void sm_makebuf
__P((SM_FILE_T
*));
36 int sm_whatbuf
__P((SM_FILE_T
*, size_t *, int *));
37 int sm_fwalk
__P((int (*)(SM_FILE_T
*, int *), int *));
38 int sm_wsetup
__P((SM_FILE_T
*));
39 int sm_flags
__P((int));
40 SM_FILE_T
*sm_fp
__P((const SM_FILE_T
*, const int, SM_FILE_T
*));
41 int sm_vprintf
__P((int, char const *, va_list));
43 /* std io functions */
44 ssize_t sm_stdread
__P((SM_FILE_T
*, char *, size_t));
45 ssize_t sm_stdwrite
__P((SM_FILE_T
*, char const *, size_t));
46 off_t sm_stdseek
__P((SM_FILE_T
*, off_t
, int));
47 int sm_stdclose
__P((SM_FILE_T
*));
48 int sm_stdopen
__P((SM_FILE_T
*, const void *, int, const void *));
49 int sm_stdfdopen
__P((SM_FILE_T
*, const void *, int, const void *));
50 int sm_stdsetinfo
__P((SM_FILE_T
*, int , void *));
51 int sm_stdgetinfo
__P((SM_FILE_T
*, int , void *));
53 /* stdio io functions */
54 ssize_t sm_stdioread
__P((SM_FILE_T
*, char *, size_t));
55 ssize_t sm_stdiowrite
__P((SM_FILE_T
*, char const *, size_t));
56 off_t sm_stdioseek
__P((SM_FILE_T
*, off_t
, int));
57 int sm_stdioclose
__P((SM_FILE_T
*));
58 int sm_stdioopen
__P((SM_FILE_T
*, const void *, int, const void *));
59 int sm_stdiosetinfo
__P((SM_FILE_T
*, int , void *));
60 int sm_stdiogetinfo
__P((SM_FILE_T
*, int , void *));
62 /* string io functions */
63 ssize_t sm_strread
__P((SM_FILE_T
*, char *, size_t));
64 ssize_t sm_strwrite
__P((SM_FILE_T
*, char const *, size_t));
65 off_t sm_strseek
__P((SM_FILE_T
*, off_t
, int));
66 int sm_strclose
__P((SM_FILE_T
*));
67 int sm_stropen
__P((SM_FILE_T
*, const void *, int, const void *));
68 int sm_strsetinfo
__P((SM_FILE_T
*, int , void *));
69 int sm_strgetinfo
__P((SM_FILE_T
*, int , void *));
71 /* syslog io functions */
72 ssize_t sm_syslogread
__P((SM_FILE_T
*, char *, size_t));
73 ssize_t sm_syslogwrite
__P((SM_FILE_T
*, char const *, size_t));
74 off_t sm_syslogseek
__P((SM_FILE_T
*, off_t
, int));
75 int sm_syslogclose
__P((SM_FILE_T
*));
76 int sm_syslogopen
__P((SM_FILE_T
*, const void *, int, const void *));
77 int sm_syslogsetinfo
__P((SM_FILE_T
*, int , void *));
78 int sm_sysloggetinfo
__P((SM_FILE_T
*, int , void *));
80 extern bool Sm_IO_DidInit
;
82 /* Return true iff the given SM_FILE_T cannot be written now. */
83 #define cantwrite(fp) \
84 ((((fp)->f_flags & SMWR) == 0 || (fp)->f_bf.smb_base == NULL) && \
88 ** Test whether the given stdio file has an active ungetc buffer;
89 ** release such a buffer, without restoring ordinary unread data.
92 #define HASUB(fp) ((fp)->f_ub.smb_base != NULL)
95 if ((fp)->f_ub.smb_base != (fp)->f_ubuf) \
96 sm_free((char *)(fp)->f_ub.smb_base); \
97 (fp)->f_ub.smb_base = NULL; \
100 extern const char SmFileMagic
[];
102 #define SM_ALIGN(p) (((unsigned long)(p) + SM_ALIGN_BITS) & ~SM_ALIGN_BITS)
104 #define sm_io_flockfile(fp) ((void) 0)
105 #define sm_io_funlockfile(fp) ((void) 0)
107 int sm_flags
__P((int));
110 # define FDSET_CAST /* empty cast for fd_set arg to select */
114 ** SM_CONVERT_TIME -- convert the API timeout flag for select() usage.
116 ** This takes a 'fp' (a file type pointer) and obtains the "raw"
117 ** file descriptor (fd) if possible. The 'fd' is needed to possibly
118 ** switch the mode of the file (blocking/non-blocking) to match
119 ** the type of timeout. If timeout is SM_TIME_FOREVER then the
120 ** timeout using select won't be needed and the file is best placed
121 ** in blocking mode. If there is to be a finite timeout then the file
122 ** is best placed in non-blocking mode. Then, if not enough can be
123 ** written, select() can be used to test when something can be written
124 ** yet still timeout if the wait is too long.
125 ** If the mode is already in the correct state we don't change it.
126 ** Iff (yes "iff") the 'fd' is "-1" in value then the mode change
127 ** will not happen. This situation arises when a late-binding-to-disk
128 ** file type is in use. An example of this is the sendmail buffered
129 ** file type (in sendmail/bf.c).
132 ** fp -- the file pointer the timeout is for
133 ** fd -- to become the file descriptor value from 'fp'
134 ** val -- the timeout value to be converted
135 ** time -- a struct timeval holding the converted value
138 ** nothing, this is flow-through code
141 ** May or may not change the mode of a currently open file.
142 ** The file mode may be changed to O_NONBLOCK or ~O_NONBLOCK
143 ** (meaning block). This is done to best match the type of
144 ** timeout and for (possible) use with select().
147 # define SM_CONVERT_TIME(fp, fd, val, time) { \
148 if (((fd) = sm_io_getinfo(fp, SM_IO_WHAT_FD, NULL)) == -1) \
150 /* can't get an fd, likely internal 'fake' fp */ \
153 if ((val) == SM_TIME_DEFAULT) \
154 (val) = (fp)->f_timeout; \
155 if ((val) == SM_TIME_IMMEDIATE || (val) == SM_TIME_FOREVER) \
157 (time)->tv_sec = 0; \
158 (time)->tv_usec = 0; \
162 (time)->tv_sec = (val) / 1000; \
163 (time)->tv_usec = ((val) - ((time)->tv_sec * 1000)) * 1000; \
165 if ((val) == SM_TIME_FOREVER) \
167 if ((fp)->f_timeoutstate == SM_TIME_NONBLOCK && (fd) != -1) \
170 ret = fcntl((fd), F_GETFL, 0); \
171 if (ret == -1 || fcntl((fd), F_SETFL, \
172 ret & ~O_NONBLOCK) == -1) \
174 /* errno should be set */ \
177 (fp)->f_timeoutstate = SM_TIME_BLOCK; \
178 if ((fp)->f_modefp != NULL) \
179 (fp)->f_modefp->f_timeoutstate = SM_TIME_BLOCK; \
183 if ((fp)->f_timeoutstate == SM_TIME_BLOCK && (fd) != -1) \
186 ret = fcntl((fd), F_GETFL, 0); \
187 if (ret == -1 || fcntl((fd), F_SETFL, \
188 ret | O_NONBLOCK) == -1) \
190 /* errno should be set */ \
193 (fp)->f_timeoutstate = SM_TIME_NONBLOCK; \
194 if ((fp)->f_modefp != NULL) \
195 (fp)->f_modefp->f_timeoutstate = SM_TIME_NONBLOCK; \
201 ** SM_IO_WR_TIMEOUT -- setup the timeout for the write
203 ** This #define uses a select() to wait for the 'fd' to become writable.
204 ** The select() can be active for up to 'to' time. The select may not
205 ** use all of the the 'to' time. Hence, the amount of "wall-clock" time is
206 ** measured to decide how much to subtract from 'to' to update it. On some
207 ** BSD-based/like systems the timeout for a select is updated for the
208 ** amount of time used. On many/most systems this does not happen. Therefore
209 ** the updating of 'to' must be done ourselves; a copy of 'to' is passed
210 ** since a BSD-like system will have updated it and we don't want to
211 ** double the time used!
212 ** Note: if a valid 'fd' doesn't exist yet, don't use this (e.g. the
213 ** sendmail buffered file type in sendmail/bf.c; see fvwrite.c).
216 ** fd -- a file descriptor for doing select() with
217 ** timeout -- the original user set value.
220 ** nothing, this is flow through code
223 ** adjusts 'timeout' for time used
226 #define SM_IO_WR_TIMEOUT(fp, fd, to) { \
227 struct timeval sm_io_to_before, sm_io_to_after, sm_io_to_diff; \
228 struct timeval sm_io_to; \
230 fd_set sm_io_to_mask, sm_io_x_mask; \
232 if ((to) == SM_TIME_DEFAULT) \
233 (to) = (fp)->f_timeout; \
234 if ((to) == SM_TIME_IMMEDIATE) \
239 else if ((to) == SM_TIME_FOREVER) \
246 sm_io_to.tv_sec = (to) / 1000; \
247 sm_io_to.tv_usec = ((to) - (sm_io_to.tv_sec * 1000)) * 1000; \
249 if (FD_SETSIZE > 0 && (fd) >= FD_SETSIZE) \
254 FD_ZERO(&sm_io_to_mask); \
255 FD_SET((fd), &sm_io_to_mask); \
256 FD_ZERO(&sm_io_x_mask); \
257 FD_SET((fd), &sm_io_x_mask); \
258 if (gettimeofday(&sm_io_to_before, NULL) < 0) \
262 sm_io_to_sel = select((fd) + 1, NULL, &sm_io_to_mask, \
263 &sm_io_x_mask, &sm_io_to); \
264 } while (sm_io_to_sel < 0 && errno == EINTR); \
265 if (sm_io_to_sel < 0) \
267 /* something went wrong, errno set */ \
270 else if (sm_io_to_sel == 0) \
276 /* else loop again */ \
277 if (gettimeofday(&sm_io_to_after, NULL) < 0) \
279 timersub(&sm_io_to_after, &sm_io_to_before, &sm_io_to_diff); \
280 (to) -= (sm_io_to_diff.tv_sec * 1000); \
281 (to) -= (sm_io_to_diff.tv_usec / 1000); \
287 ** If there is no 'fd' just error (we can't timeout). If the timeout
288 ** is SM_TIME_FOREVER then there is no need to do a timeout with
289 ** select since this will be a real error. If the error is not
290 ** EAGAIN/EWOULDBLOCK (from a nonblocking) then it's a real error.
291 ** Specify the condition here as macro so it can be used in several places.
294 #define IS_IO_ERROR(fd, ret, to) \
296 ((ret) < 0 && errno != EAGAIN && errno != EWOULDBLOCK) || \
297 (to) == SM_TIME_FOREVER)