1 /* 2 * Copyright (c) 2000-2001, 2005-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 15 #include <sm/gen.h> 16 SM_RCSID("@(#)$Id: refill.c,v 1.54 2013-11-22 20:51:43 ca Exp $") 17 #include <stdlib.h> 18 #include <unistd.h> 19 #include <errno.h> 20 #include <setjmp.h> 21 #include <signal.h> 22 #include <sm/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 <sm/fdset.h> 29 #include "local.h" 30 31 static int sm_lflush __P((SM_FILE_T *, int *)); 32 33 /* 34 ** SM_IO_RD_TIMEOUT -- measured timeout for reads 35 ** 36 ** This #define uses a select() to wait for the 'fd' to become readable. 37 ** The select() can be active for up to 'To' time. The select() may not 38 ** use all of the the 'To' time. Hence, the amount of "wall-clock" time is 39 ** measured to decide how much to subtract from 'To' to update it. On some 40 ** BSD-based/like systems the timeout for a select() is updated for the 41 ** amount of time used. On many/most systems this does not happen. Therefore 42 ** the updating of 'To' must be done ourselves; a copy of 'To' is passed 43 ** since a BSD-like system will have updated it and we don't want to 44 ** double the time used! 45 ** Note: if a valid 'fd' doesn't exist yet, don't use this (e.g. the 46 ** sendmail buffered file type in sendmail/bf.c; see use below). 47 ** 48 ** Parameters 49 ** fp -- the file pointer for the active file 50 ** fd -- raw file descriptor (from 'fp') to use for select() 51 ** to -- struct timeval of the timeout 52 ** timeout -- the original timeout value 53 ** sel_ret -- the return value from the select() 54 ** 55 ** Returns: 56 ** nothing, flow through code 57 */ 58 59 #define SM_IO_RD_TIMEOUT(fp, fd, to, timeout, sel_ret) \ 60 { \ 61 struct timeval sm_io_to_before, sm_io_to_after, sm_io_to_diff; \ 62 fd_set sm_io_to_mask, sm_io_x_mask; \ 63 errno = 0; \ 64 if (timeout == SM_TIME_IMMEDIATE) \ 65 { \ 66 errno = EAGAIN; \ 67 return SM_IO_EOF; \ 68 } \ 69 if (!SM_FD_OK_SELECT(fd)) \ 70 { \ 71 errno = EINVAL; \ 72 return SM_IO_EOF; \ 73 } \ 74 FD_ZERO(&sm_io_to_mask); \ 75 FD_SET((fd), &sm_io_to_mask); \ 76 FD_ZERO(&sm_io_x_mask); \ 77 FD_SET((fd), &sm_io_x_mask); \ 78 if (gettimeofday(&sm_io_to_before, NULL) < 0) \ 79 return SM_IO_EOF; \ 80 do \ 81 { \ 82 (sel_ret) = select((fd) + 1, &sm_io_to_mask, NULL, \ 83 &sm_io_x_mask, (to)); \ 84 } while ((sel_ret) < 0 && errno == EINTR); \ 85 if ((sel_ret) < 0) \ 86 { \ 87 /* something went wrong, errno set */ \ 88 fp->f_r = 0; \ 89 fp->f_flags |= SMERR; \ 90 return SM_IO_EOF; \ 91 } \ 92 else if ((sel_ret) == 0) \ 93 { \ 94 /* timeout */ \ 95 errno = EAGAIN; \ 96 return SM_IO_EOF; \ 97 } \ 98 /* calculate wall-clock time used */ \ 99 if (gettimeofday(&sm_io_to_after, NULL) < 0) \ 100 return SM_IO_EOF; \ 101 timersub(&sm_io_to_after, &sm_io_to_before, &sm_io_to_diff); \ 102 timersub((to), &sm_io_to_diff, (to)); \ 103 } 104 105 /* 106 ** SM_LFLUSH -- flush a file if it is line buffered and writable 107 ** 108 ** Parameters: 109 ** fp -- file pointer to flush 110 ** timeout -- original timeout value (in milliseconds) 111 ** 112 ** Returns: 113 ** Failure: returns SM_IO_EOF and sets errno 114 ** Success: returns 0 115 */ 116 117 static int 118 sm_lflush(fp, timeout) 119 SM_FILE_T *fp; 120 int *timeout; 121 { 122 123 if ((fp->f_flags & (SMLBF|SMWR)) == (SMLBF|SMWR)) 124 return sm_flush(fp, timeout); 125 return 0; 126 } 127 128 /* 129 ** SM_REFILL -- refill a buffer 130 ** 131 ** Parameters: 132 ** fp -- file pointer for buffer refill 133 ** timeout -- time to complete filling the buffer in milliseconds 134 ** 135 ** Returns: 136 ** Success: returns 0 137 ** Failure: returns SM_IO_EOF 138 */ 139 140 int 141 sm_refill(fp, timeout) 142 register SM_FILE_T *fp; 143 int timeout; 144 { 145 int ret, r; 146 struct timeval to; 147 int fd; 148 149 if (timeout == SM_TIME_DEFAULT) 150 timeout = fp->f_timeout; 151 if (timeout == SM_TIME_IMMEDIATE) 152 { 153 /* 154 ** Filling the buffer will take time and we are wanted to 155 ** return immediately. And we're not EOF or ERR really. 156 ** So... the failure is we couldn't do it in time. 157 */ 158 159 errno = EAGAIN; 160 fp->f_r = 0; /* just to be sure */ 161 return 0; 162 } 163 164 /* make sure stdio is set up */ 165 if (!Sm_IO_DidInit) 166 sm_init(); 167 168 fp->f_r = 0; /* largely a convenience for callers */ 169 170 if (fp->f_flags & SMFEOF) 171 return SM_IO_EOF; 172 173 SM_CONVERT_TIME(fp, fd, timeout, &to); 174 175 /* if not already reading, have to be reading and writing */ 176 if ((fp->f_flags & SMRD) == 0) 177 { 178 if ((fp->f_flags & SMRW) == 0) 179 { 180 errno = EBADF; 181 fp->f_flags |= SMERR; 182 return SM_IO_EOF; 183 } 184 185 /* switch to reading */ 186 if (fp->f_flags & SMWR) 187 { 188 if (sm_flush(fp, &timeout)) 189 return SM_IO_EOF; 190 fp->f_flags &= ~SMWR; 191 fp->f_w = 0; 192 fp->f_lbfsize = 0; 193 } 194 fp->f_flags |= SMRD; 195 } 196 else 197 { 198 /* 199 ** We were reading. If there is an ungetc buffer, 200 ** we must have been reading from that. Drop it, 201 ** restoring the previous buffer (if any). If there 202 ** is anything in that buffer, return. 203 */ 204 205 if (HASUB(fp)) 206 { 207 FREEUB(fp); 208 if ((fp->f_r = fp->f_ur) != 0) 209 { 210 fp->f_p = fp->f_up; 211 212 /* revert blocking state */ 213 return 0; 214 } 215 } 216 } 217 218 if (fp->f_bf.smb_base == NULL) 219 sm_makebuf(fp); 220 221 /* 222 ** Before reading from a line buffered or unbuffered file, 223 ** flush all line buffered output files, per the ANSI C standard. 224 */ 225 226 if (fp->f_flags & (SMLBF|SMNBF)) 227 (void) sm_fwalk(sm_lflush, &timeout); 228 229 /* 230 ** If this file is linked to another, and we are going to hang 231 ** on the read, flush the linked file before continuing. 232 */ 233 234 if (fp->f_flushfp != NULL && 235 (*fp->f_getinfo)(fp, SM_IO_IS_READABLE, NULL) <= 0) 236 sm_flush(fp->f_flushfp, &timeout); 237 238 fp->f_p = fp->f_bf.smb_base; 239 240 /* 241 ** The do-while loop stops trying to read when something is read 242 ** or it appears that the timeout has expired before finding 243 ** something available to be read (via select()). 244 */ 245 246 ret = 0; 247 do 248 { 249 errno = 0; /* needed to ensure EOF correctly found */ 250 r = (*fp->f_read)(fp, (char *)fp->f_p, fp->f_bf.smb_size); 251 if (r <= 0) 252 { 253 if (r == 0 && errno == 0) 254 break; /* EOF found */ 255 if (IS_IO_ERROR(fd, r, timeout)) 256 goto err; /* errno set */ 257 258 /* read would block */ 259 SM_IO_RD_TIMEOUT(fp, fd, &to, timeout, ret); 260 } 261 } while (r <= 0 && ret > 0); 262 263 err: 264 if (r <= 0) 265 { 266 if (r == 0) 267 fp->f_flags |= SMFEOF; 268 else 269 fp->f_flags |= SMERR; 270 fp->f_r = 0; 271 return SM_IO_EOF; 272 } 273 fp->f_r = r; 274 return 0; 275 } 276 277 /* 278 ** SM_RGET -- refills buffer and returns first character 279 ** 280 ** Handle sm_getc() when the buffer ran out: 281 ** Refill, then return the first character in the newly-filled buffer. 282 ** 283 ** Parameters: 284 ** fp -- file pointer to work on 285 ** timeout -- time to complete refill 286 ** 287 ** Returns: 288 ** Success: first character in refilled buffer as an int 289 ** Failure: SM_IO_EOF 290 */ 291 292 int 293 sm_rget(fp, timeout) 294 register SM_FILE_T *fp; 295 int timeout; 296 { 297 if (sm_refill(fp, timeout) == 0) 298 { 299 fp->f_r--; 300 return *fp->f_p++; 301 } 302 return SM_IO_EOF; 303 } 304