1/*++ 2/* NAME 3/* timed_read 3 4/* SUMMARY 5/* read operation with pre-read timeout 6/* SYNOPSIS 7/* #include <iostuff.h> 8/* 9/* ssize_t timed_read(fd, buf, len, timeout, context) 10/* int fd; 11/* void *buf; 12/* size_t len; 13/* int timeout; 14/* void *context; 15/* DESCRIPTION 16/* timed_read() performs a read() operation when the specified 17/* descriptor becomes readable within a user-specified deadline. 18/* 19/* Arguments: 20/* .IP fd 21/* File descriptor in the range 0..FD_SETSIZE. 22/* .IP buf 23/* Read buffer pointer. 24/* .IP len 25/* Read buffer size. 26/* .IP timeout 27/* The deadline in seconds. If this is <= 0, the deadline feature 28/* is disabled. 29/* .IP context 30/* Application context. This parameter is unused. It exists only 31/* for the sake of VSTREAM compatibility. 32/* DIAGNOSTICS 33/* When the operation does not complete within the deadline, the 34/* result value is -1, and errno is set to ETIMEDOUT. 35/* All other returns are identical to those of a read(2) operation. 36/* LICENSE 37/* .ad 38/* .fi 39/* The Secure Mailer license must be distributed with this software. 40/* AUTHOR(S) 41/* Wietse Venema 42/* IBM T.J. Watson Research 43/* P.O. Box 704 44/* Yorktown Heights, NY 10598, USA 45/*--*/ 46 47/* System library. */ 48 49#include <sys_defs.h> 50#include <unistd.h> 51#include <errno.h> 52 53/* Utility library. */ 54 55#include <msg.h> 56#include <iostuff.h> 57 58/* timed_read - read with deadline */ 59 60ssize_t timed_read(int fd, void *buf, size_t len, 61 int timeout, void *unused_context) 62{ 63 ssize_t ret; 64 65 /* 66 * Wait for a limited amount of time for something to happen. If nothing 67 * happens, report an ETIMEDOUT error. 68 * 69 * XXX Solaris 8 read() fails with EAGAIN after read-select() returns 70 * success. 71 */ 72 for (;;) { 73 if (timeout > 0 && read_wait(fd, timeout) < 0) 74 return (-1); 75 if ((ret = read(fd, buf, len)) < 0 && timeout > 0 && errno == EAGAIN) { 76 msg_warn("read() returns EAGAIN on a readable file descriptor!"); 77 msg_warn("pausing to avoid going into a tight select/read loop!"); 78 sleep(1); 79 continue; 80 } else if (ret < 0 && errno == EINTR) { 81 continue; 82 } else { 83 return (ret); 84 } 85 } 86} 87