Import sendmail 8.13.4 into a new contrib directory as the first step
[dragonfly.git] / contrib / sendmail-8.13.4 / libsm / refill.c
blobc3db172229572744e4c5a216b32d6f4694496bf1
1 /*
2 * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers.
3 * All rights reserved.
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
8 * Chris Torek.
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.
15 #include <sm/gen.h>
16 SM_RCSID("@(#)$Id: refill.c,v 1.50 2002/09/09 21:50:10 gshapiro Exp $")
17 #include <stdlib.h>
18 #include <unistd.h>
19 #include <errno.h>
20 #include <setjmp.h>
21 #include <signal.h>
22 #include <sys/time.h>
23 #include <fcntl.h>
24 #include <string.h>
25 #include <sm/io.h>
26 #include <sm/conf.h>
27 #include <sm/assert.h>
28 #include "local.h"
30 static int sm_lflush __P((SM_FILE_T *, int *));
33 ** SM_IO_RD_TIMEOUT -- measured timeout for reads
35 ** This #define uses a select() to wait for the 'fd' to become readable.
36 ** The select() can be active for up to 'To' time. The select() may not
37 ** use all of the the 'To' time. Hence, the amount of "wall-clock" time is
38 ** measured to decide how much to subtract from 'To' to update it. On some
39 ** BSD-based/like systems the timeout for a select() is updated for the
40 ** amount of time used. On many/most systems this does not happen. Therefore
41 ** the updating of 'To' must be done ourselves; a copy of 'To' is passed
42 ** since a BSD-like system will have updated it and we don't want to
43 ** double the time used!
44 ** Note: if a valid 'fd' doesn't exist yet, don't use this (e.g. the
45 ** sendmail buffered file type in sendmail/bf.c; see use below).
47 ** Parameters
48 ** fp -- the file pointer for the active file
49 ** fd -- raw file descriptor (from 'fp') to use for select()
50 ** to -- struct timeval of the timeout
51 ** timeout -- the original timeout value
52 ** sel_ret -- the return value from the select()
54 ** Returns:
55 ** nothing, flow through code
58 #define SM_IO_RD_TIMEOUT(fp, fd, to, timeout, sel_ret) \
59 { \
60 struct timeval sm_io_to_before, sm_io_to_after, sm_io_to_diff; \
61 fd_set sm_io_to_mask, sm_io_x_mask; \
62 errno = 0; \
63 if (timeout == SM_TIME_IMMEDIATE) \
64 { \
65 errno = EAGAIN; \
66 return SM_IO_EOF; \
67 } \
68 if (FD_SETSIZE > 0 && (fd) >= FD_SETSIZE) \
69 { \
70 errno = EINVAL; \
71 return SM_IO_EOF; \
72 } \
73 FD_ZERO(&sm_io_to_mask); \
74 FD_SET((fd), &sm_io_to_mask); \
75 FD_ZERO(&sm_io_x_mask); \
76 FD_SET((fd), &sm_io_x_mask); \
77 if (gettimeofday(&sm_io_to_before, NULL) < 0) \
78 return SM_IO_EOF; \
79 (sel_ret) = select((fd) + 1, &sm_io_to_mask, NULL, \
80 &sm_io_x_mask, (to)); \
81 if ((sel_ret) < 0) \
82 { \
83 /* something went wrong, errno set */ \
84 fp->f_r = 0; \
85 fp->f_flags |= SMERR; \
86 return SM_IO_EOF; \
87 } \
88 else if ((sel_ret) == 0) \
89 { \
90 /* timeout */ \
91 errno = EAGAIN; \
92 return SM_IO_EOF; \
93 } \
94 /* calulate wall-clock time used */ \
95 if (gettimeofday(&sm_io_to_after, NULL) < 0) \
96 return SM_IO_EOF; \
97 timersub(&sm_io_to_before, &sm_io_to_after, &sm_io_to_diff); \
98 timersub((to), &sm_io_to_diff, (to)); \
102 ** SM_LFLUSH -- flush a file if it is line buffered and writable
104 ** Parameters:
105 ** fp -- file pointer to flush
106 ** timeout -- original timeout value (in milliseconds)
108 ** Returns:
109 ** Failure: returns SM_IO_EOF and sets errno
110 ** Success: returns 0
113 static int
114 sm_lflush(fp, timeout)
115 SM_FILE_T *fp;
116 int *timeout;
119 if ((fp->f_flags & (SMLBF|SMWR)) == (SMLBF|SMWR))
120 return sm_flush(fp, timeout);
121 return 0;
125 ** SM_REFILL -- refill a buffer
127 ** Parameters:
128 ** fp -- file pointer for buffer refill
129 ** timeout -- time to complete filling the buffer in milliseconds
131 ** Returns:
132 ** Success: returns 0
133 ** Failure: returns SM_IO_EOF
137 sm_refill(fp, timeout)
138 register SM_FILE_T *fp;
139 int timeout;
141 int ret, r;
142 struct timeval to;
143 int fd;
145 if (timeout == SM_TIME_DEFAULT)
146 timeout = fp->f_timeout;
147 if (timeout == SM_TIME_IMMEDIATE)
150 ** Filling the buffer will take time and we are wanted to
151 ** return immediately. And we're not EOF or ERR really.
152 ** So... the failure is we couldn't do it in time.
155 errno = EAGAIN;
156 fp->f_r = 0; /* just to be sure */
157 return 0;
160 /* make sure stdio is set up */
161 if (!Sm_IO_DidInit)
162 sm_init();
164 fp->f_r = 0; /* largely a convenience for callers */
166 if (fp->f_flags & SMFEOF)
167 return SM_IO_EOF;
169 SM_CONVERT_TIME(fp, fd, timeout, &to);
171 /* if not already reading, have to be reading and writing */
172 if ((fp->f_flags & SMRD) == 0)
174 if ((fp->f_flags & SMRW) == 0)
176 errno = EBADF;
177 fp->f_flags |= SMERR;
178 return SM_IO_EOF;
181 /* switch to reading */
182 if (fp->f_flags & SMWR)
184 if (sm_flush(fp, &timeout))
185 return SM_IO_EOF;
186 fp->f_flags &= ~SMWR;
187 fp->f_w = 0;
188 fp->f_lbfsize = 0;
190 fp->f_flags |= SMRD;
192 else
195 ** We were reading. If there is an ungetc buffer,
196 ** we must have been reading from that. Drop it,
197 ** restoring the previous buffer (if any). If there
198 ** is anything in that buffer, return.
201 if (HASUB(fp))
203 FREEUB(fp);
204 if ((fp->f_r = fp->f_ur) != 0)
206 fp->f_p = fp->f_up;
208 /* revert blocking state */
209 return 0;
214 if (fp->f_bf.smb_base == NULL)
215 sm_makebuf(fp);
218 ** Before reading from a line buffered or unbuffered file,
219 ** flush all line buffered output files, per the ANSI C standard.
222 if (fp->f_flags & (SMLBF|SMNBF))
223 (void) sm_fwalk(sm_lflush, &timeout);
226 ** If this file is linked to another, and we are going to hang
227 ** on the read, flush the linked file before continuing.
230 if (fp->f_flushfp != NULL &&
231 (*fp->f_getinfo)(fp, SM_IO_IS_READABLE, NULL) <= 0)
232 sm_flush(fp->f_flushfp, &timeout);
234 fp->f_p = fp->f_bf.smb_base;
237 ** The do-while loop stops trying to read when something is read
238 ** or it appears that the timeout has expired before finding
239 ** something available to be read (via select()).
242 ret = 0;
245 errno = 0; /* needed to ensure EOF correctly found */
246 r = (*fp->f_read)(fp, (char *)fp->f_p, fp->f_bf.smb_size);
247 if (r <= 0)
249 if (r == 0 && errno == 0)
250 break; /* EOF found */
251 if (IS_IO_ERROR(fd, r, timeout))
252 goto err; /* errno set */
254 /* read would block */
255 SM_IO_RD_TIMEOUT(fp, fd, &to, timeout, ret);
257 } while (r <= 0 && ret > 0);
259 err:
260 if (r <= 0)
262 if (r == 0)
263 fp->f_flags |= SMFEOF;
264 else
265 fp->f_flags |= SMERR;
266 fp->f_r = 0;
267 return SM_IO_EOF;
269 fp->f_r = r;
270 return 0;
274 ** SM_RGET -- refills buffer and returns first character
276 ** Handle sm_getc() when the buffer ran out:
277 ** Refill, then return the first character in the newly-filled buffer.
279 ** Parameters:
280 ** fp -- file pointer to work on
281 ** timeout -- time to complete refill
283 ** Returns:
284 ** Success: first character in refilled buffer as an int
285 ** Failure: SM_IO_EOF
289 sm_rget(fp, timeout)
290 register SM_FILE_T *fp;
291 int timeout;
293 if (sm_refill(fp, timeout) == 0)
295 fp->f_r--;
296 return *fp->f_p++;
298 return SM_IO_EOF;