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