]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/sendmail/libsm/local.h
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / sendmail / libsm / local.h
1 /*
2  * Copyright (c) 2000-2002, 2004-2006 Proofpoint, Inc. and its suppliers.
3  *      All rights reserved.
4  * Copyright (c) 1990, 1993
5  *      The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Chris Torek.
9  *
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.
13  *
14  *      $Id: local.h,v 1.59 2013-11-22 20:51:43 ca Exp $
15  */
16
17 /*
18 **  Information local to this implementation of stdio,
19 **  in particular, macros and private variables.
20 */
21
22 #include <sm/time.h>
23 #include <sm/fdset.h>
24 #if !SM_CONF_MEMCHR
25 # include <memory.h>
26 #endif /* !SM_CONF_MEMCHR */
27 #include <sm/heap.h>
28
29 int     sm_flush __P((SM_FILE_T *, int *));
30 SM_FILE_T       *smfp __P((void));
31 int     sm_refill __P((SM_FILE_T *, int));
32 void    sm_init __P((void));
33 void    sm_cleanup __P((void));
34 void    sm_makebuf __P((SM_FILE_T *));
35 int     sm_whatbuf __P((SM_FILE_T *, size_t *, int *));
36 int     sm_fwalk __P((int (*)(SM_FILE_T *, int *), int *));
37 int     sm_wsetup __P((SM_FILE_T *));
38 int     sm_flags __P((int));
39 SM_FILE_T       *sm_fp __P((const SM_FILE_T *, const int, SM_FILE_T *));
40 int     sm_vprintf __P((int, char const *, va_list));
41
42 /* std io functions */
43 ssize_t sm_stdread __P((SM_FILE_T *, char *, size_t));
44 ssize_t sm_stdwrite __P((SM_FILE_T *, char const *, size_t));
45 off_t   sm_stdseek __P((SM_FILE_T *, off_t, int));
46 int     sm_stdclose __P((SM_FILE_T *));
47 int     sm_stdopen __P((SM_FILE_T *, const void *, int, const void *));
48 int     sm_stdfdopen __P((SM_FILE_T *, const void *, int, const void *));
49 int     sm_stdsetinfo __P((SM_FILE_T *, int , void *));
50 int     sm_stdgetinfo __P((SM_FILE_T *, int , void *));
51
52 /* stdio io functions */
53 ssize_t sm_stdioread __P((SM_FILE_T *, char *, size_t));
54 ssize_t sm_stdiowrite __P((SM_FILE_T *, char const *, size_t));
55 off_t   sm_stdioseek __P((SM_FILE_T *, off_t, int));
56 int     sm_stdioclose __P((SM_FILE_T *));
57 int     sm_stdioopen __P((SM_FILE_T *, const void *, int, const void *));
58 int     sm_stdiosetinfo __P((SM_FILE_T *, int , void *));
59 int     sm_stdiogetinfo __P((SM_FILE_T *, int , void *));
60
61 /* string io functions */
62 ssize_t sm_strread __P((SM_FILE_T *, char *, size_t));
63 ssize_t sm_strwrite __P((SM_FILE_T *, char const *, size_t));
64 off_t   sm_strseek __P((SM_FILE_T *, off_t, int));
65 int     sm_strclose __P((SM_FILE_T *));
66 int     sm_stropen __P((SM_FILE_T *, const void *, int, const void *));
67 int     sm_strsetinfo __P((SM_FILE_T *, int , void *));
68 int     sm_strgetinfo __P((SM_FILE_T *, int , void *));
69
70 /* syslog io functions */
71 ssize_t sm_syslogread __P((SM_FILE_T *, char *, size_t));
72 ssize_t sm_syslogwrite __P((SM_FILE_T *, char const *, size_t));
73 off_t   sm_syslogseek __P((SM_FILE_T *, off_t, int));
74 int     sm_syslogclose __P((SM_FILE_T *));
75 int     sm_syslogopen __P((SM_FILE_T *, const void *, int, const void *));
76 int     sm_syslogsetinfo __P((SM_FILE_T *, int , void *));
77 int     sm_sysloggetinfo __P((SM_FILE_T *, int , void *));
78
79 extern bool Sm_IO_DidInit;
80
81 /* Return true iff the given SM_FILE_T cannot be written now. */
82 #define cantwrite(fp) \
83         ((((fp)->f_flags & SMWR) == 0 || (fp)->f_bf.smb_base == NULL) && \
84          sm_wsetup(fp))
85
86 /*
87 **  Test whether the given stdio file has an active ungetc buffer;
88 **   release such a buffer, without restoring ordinary unread data.
89 */
90
91 #define HASUB(fp) ((fp)->f_ub.smb_base != NULL)
92 #define FREEUB(fp)                                      \
93 {                                                       \
94         if ((fp)->f_ub.smb_base != (fp)->f_ubuf)        \
95                 sm_free((char *)(fp)->f_ub.smb_base);   \
96         (fp)->f_ub.smb_base = NULL;                     \
97 }
98
99 extern const char SmFileMagic[];
100
101 #define SM_ALIGN(p)     (((unsigned long)(p) + SM_ALIGN_BITS) & ~SM_ALIGN_BITS)
102
103 #define sm_io_flockfile(fp)     ((void) 0)
104 #define sm_io_funlockfile(fp)   ((void) 0)
105
106 int sm_flags __P((int));
107
108 #ifndef FDSET_CAST
109 # define FDSET_CAST             /* empty cast for fd_set arg to select */
110 #endif
111
112 /*
113 **  SM_CONVERT_TIME -- convert the API timeout flag for select() usage.
114 **
115 **      This takes a 'fp' (a file type pointer) and obtains the "raw"
116 **      file descriptor (fd) if possible. The 'fd' is needed to possibly
117 **      switch the mode of the file (blocking/non-blocking) to match
118 **      the type of timeout. If timeout is SM_TIME_FOREVER then the
119 **      timeout using select won't be needed and the file is best placed
120 **      in blocking mode. If there is to be a finite timeout then the file
121 **      is best placed in non-blocking mode. Then, if not enough can be
122 **      written, select() can be used to test when something can be written
123 **      yet still timeout if the wait is too long.
124 **      If the mode is already in the correct state we don't change it.
125 **      Iff (yes "iff") the 'fd' is "-1" in value then the mode change
126 **      will not happen. This situation arises when a late-binding-to-disk
127 **      file type is in use. An example of this is the sendmail buffered
128 **      file type (in sendmail/bf.c).
129 **
130 **      Parameters
131 **              fp -- the file pointer the timeout is for
132 **              fd -- to become the file descriptor value from 'fp'
133 **              val -- the timeout value to be converted
134 **              time -- a struct timeval holding the converted value
135 **
136 **      Returns
137 **              nothing, this is flow-through code
138 **
139 **      Side Effects:
140 **              May or may not change the mode of a currently open file.
141 **              The file mode may be changed to O_NONBLOCK or ~O_NONBLOCK
142 **              (meaning block). This is done to best match the type of
143 **              timeout and for (possible) use with select().
144 */
145
146 # define SM_CONVERT_TIME(fp, fd, val, time) { \
147         if (((fd) = sm_io_getinfo(fp, SM_IO_WHAT_FD, NULL)) == -1) \
148         { \
149                 /* can't get an fd, likely internal 'fake' fp */ \
150                 errno = 0; \
151         } \
152         if ((val) == SM_TIME_DEFAULT) \
153                 (val) = (fp)->f_timeout; \
154         if ((val) == SM_TIME_IMMEDIATE || (val) == SM_TIME_FOREVER) \
155         { \
156                 (time)->tv_sec = 0; \
157                 (time)->tv_usec = 0; \
158         } \
159         else \
160         { \
161                 (time)->tv_sec = (val) / 1000; \
162                 (time)->tv_usec = ((val) - ((time)->tv_sec * 1000)) * 1000; \
163         } \
164         if ((val) == SM_TIME_FOREVER) \
165         { \
166                 if ((fp)->f_timeoutstate == SM_TIME_NONBLOCK && (fd) != -1) \
167                 { \
168                         int ret; \
169                         ret = fcntl((fd), F_GETFL, 0); \
170                         if (ret == -1 || fcntl((fd), F_SETFL, \
171                                                ret & ~O_NONBLOCK) == -1) \
172                         { \
173                                 /* errno should be set */ \
174                                 return SM_IO_EOF; \
175                         } \
176                         (fp)->f_timeoutstate = SM_TIME_BLOCK; \
177                         if ((fp)->f_modefp != NULL) \
178                                 (fp)->f_modefp->f_timeoutstate = SM_TIME_BLOCK; \
179                 } \
180         } \
181         else { \
182                 if ((fp)->f_timeoutstate == SM_TIME_BLOCK && (fd) != -1) \
183                 { \
184                         int ret; \
185                         ret = fcntl((fd), F_GETFL, 0); \
186                         if (ret == -1 || fcntl((fd), F_SETFL, \
187                                                ret | O_NONBLOCK) == -1) \
188                         { \
189                                 /* errno should be set */ \
190                                 return SM_IO_EOF; \
191                         } \
192                         (fp)->f_timeoutstate = SM_TIME_NONBLOCK; \
193                         if ((fp)->f_modefp != NULL) \
194                                 (fp)->f_modefp->f_timeoutstate = SM_TIME_NONBLOCK; \
195                 } \
196         } \
197 }
198
199 /*
200 **  SM_IO_WR_TIMEOUT -- setup the timeout for the write
201 **
202 **  This #define uses a select() to wait for the 'fd' to become writable.
203 **  The select() can be active for up to 'to' time. The select may not
204 **  use all of the the 'to' time. Hence, the amount of "wall-clock" time is
205 **  measured to decide how much to subtract from 'to' to update it. On some
206 **  BSD-based/like systems the timeout for a select is updated for the
207 **  amount of time used. On many/most systems this does not happen. Therefore
208 **  the updating of 'to' must be done ourselves; a copy of 'to' is passed
209 **  since a BSD-like system will have updated it and we don't want to
210 **  double the time used!
211 **  Note: if a valid 'fd' doesn't exist yet, don't use this (e.g. the
212 **  sendmail buffered file type in sendmail/bf.c; see fvwrite.c).
213 **
214 **      Parameters
215 **              fd -- a file descriptor for doing select() with
216 **              timeout -- the original user set value.
217 **
218 **      Returns
219 **              nothing, this is flow through code
220 **
221 **      Side Effects:
222 **              adjusts 'timeout' for time used
223 */
224
225 #define SM_IO_WR_TIMEOUT(fp, fd, to) { \
226         struct timeval sm_io_to_before, sm_io_to_after, sm_io_to_diff; \
227         struct timeval sm_io_to; \
228         int sm_io_to_sel; \
229         fd_set sm_io_to_mask, sm_io_x_mask; \
230         errno = 0; \
231         if ((to) == SM_TIME_DEFAULT) \
232                 (to) = (fp)->f_timeout; \
233         if ((to) == SM_TIME_IMMEDIATE) \
234         { \
235                 errno = EAGAIN; \
236                 return SM_IO_EOF; \
237         } \
238         else if ((to) == SM_TIME_FOREVER) \
239         { \
240                 errno = EINVAL; \
241                 return SM_IO_EOF; \
242         } \
243         else \
244         { \
245                 sm_io_to.tv_sec = (to) / 1000; \
246                 sm_io_to.tv_usec = ((to) - (sm_io_to.tv_sec * 1000)) * 1000; \
247         } \
248         if (!SM_FD_OK_SELECT(fd)) \
249         { \
250                 errno = EINVAL; \
251                 return SM_IO_EOF; \
252         } \
253         FD_ZERO(&sm_io_to_mask); \
254         FD_SET((fd), &sm_io_to_mask); \
255         FD_ZERO(&sm_io_x_mask); \
256         FD_SET((fd), &sm_io_x_mask); \
257         if (gettimeofday(&sm_io_to_before, NULL) < 0) \
258                 return SM_IO_EOF; \
259         do \
260         {       \
261                 sm_io_to_sel = select((fd) + 1, NULL, &sm_io_to_mask, \
262                                         &sm_io_x_mask, &sm_io_to); \
263         } while (sm_io_to_sel < 0 && errno == EINTR); \
264         if (sm_io_to_sel < 0) \
265         { \
266                 /* something went wrong, errno set */ \
267                 return SM_IO_EOF; \
268         } \
269         else if (sm_io_to_sel == 0) \
270         { \
271                 /* timeout */ \
272                 errno = EAGAIN; \
273                 return SM_IO_EOF; \
274         } \
275         /* else loop again */ \
276         if (gettimeofday(&sm_io_to_after, NULL) < 0) \
277                 return SM_IO_EOF; \
278         timersub(&sm_io_to_after, &sm_io_to_before, &sm_io_to_diff); \
279         (to) -= (sm_io_to_diff.tv_sec * 1000); \
280         (to) -= (sm_io_to_diff.tv_usec / 1000); \
281         if ((to) < 0) \
282                 (to) = 0; \
283 }
284
285 /*
286 **  If there is no 'fd' just error (we can't timeout). If the timeout
287 **  is SM_TIME_FOREVER then there is no need to do a timeout with
288 **  select since this will be a real error.  If the error is not
289 **  EAGAIN/EWOULDBLOCK (from a nonblocking) then it's a real error.
290 **  Specify the condition here as macro so it can be used in several places.
291 */
292
293 #define IS_IO_ERROR(fd, ret, to) \
294         ((fd) < 0 ||    \
295          ((ret) < 0 && errno != EAGAIN && errno != EWOULDBLOCK) ||      \
296          (to) == SM_TIME_FOREVER)
297