xref: /netbsd-src/external/ibm-public/postfix/dist/src/util/timed_read.c (revision 41fbaed053f8fbfdf9d2a4ee0a7386a3c83f8505)
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 
timed_read(int fd,void * buf,size_t len,int timeout,void * unused_context)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