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