Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / util / read_wait.c
blob14be076327e08480692967d8d4325830de140c41
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* read_wait 3
6 /* SUMMARY
7 /* wait until descriptor becomes readable
8 /* SYNOPSIS
9 /* #include <iostuff.h>
11 /* int read_wait(fd, timeout)
12 /* int fd;
13 /* int timeout;
14 /* DESCRIPTION
15 /* read_wait() blocks the current process until the specified file
16 /* descriptor becomes readable, or until the deadline is exceeded.
18 /* Arguments:
19 /* .IP fd
20 /* File descriptor in the range 0..FD_SETSIZE.
21 /* .IP timeout
22 /* If positive, deadline in seconds. A zero value effects a poll.
23 /* A negative value means wait until something happens.
24 /* DIAGNOSTICS
25 /* Panic: interface violation. All system call errors are fatal.
27 /* A zero result means success. When the specified deadline is
28 /* exceeded, read_wait() returns -1 and sets errno to ETIMEDOUT.
29 /* LICENSE
30 /* .ad
31 /* .fi
32 /* The Secure Mailer license must be distributed with this software.
33 /* AUTHOR(S)
34 /* Wietse Venema
35 /* IBM T.J. Watson Research
36 /* P.O. Box 704
37 /* Yorktown Heights, NY 10598, USA
38 /*--*/
40 /* System library. */
42 #include <sys_defs.h>
43 #include <sys/time.h>
44 #include <signal.h>
45 #include <errno.h>
46 #include <unistd.h>
47 #include <string.h>
49 #ifdef USE_SYSV_POLL
50 #include <poll.h>
51 #endif
53 #ifdef USE_SYS_SELECT_H
54 #include <sys/select.h>
55 #endif
57 /* Utility library. */
59 #include <msg.h>
60 #include <iostuff.h>
62 /* read_wait - block with timeout until file descriptor is readable */
64 int read_wait(int fd, int timeout)
66 #ifndef USE_SYSV_POLL
67 fd_set read_fds;
68 fd_set except_fds;
69 struct timeval tv;
70 struct timeval *tp;
73 * Sanity checks.
75 if (FD_SETSIZE <= fd)
76 msg_panic("descriptor %d does not fit FD_SETSIZE %d", fd, FD_SETSIZE);
79 * Use select() so we do not depend on alarm() and on signal() handlers.
80 * Restart the select when interrupted by some signal. Some select()
81 * implementations reduce the time to wait when interrupted, which is
82 * exactly what we want.
84 FD_ZERO(&read_fds);
85 FD_SET(fd, &read_fds);
86 FD_ZERO(&except_fds);
87 FD_SET(fd, &except_fds);
88 if (timeout >= 0) {
89 tv.tv_usec = 0;
90 tv.tv_sec = timeout;
91 tp = &tv;
92 } else {
93 tp = 0;
96 for (;;) {
97 switch (select(fd + 1, &read_fds, (fd_set *) 0, &except_fds, tp)) {
98 case -1:
99 if (errno != EINTR)
100 msg_fatal("select: %m");
101 continue;
102 case 0:
103 errno = ETIMEDOUT;
104 return (-1);
105 default:
106 return (0);
109 #else
112 * System-V poll() is optimal for polling a few descriptors.
114 struct pollfd pollfd;
116 #define WAIT_FOR_EVENT (-1)
118 pollfd.fd = fd;
119 pollfd.events = POLLIN;
120 for (;;) {
121 switch (poll(&pollfd, 1, timeout < 0 ?
122 WAIT_FOR_EVENT : timeout * 1000)) {
123 case -1:
124 if (errno != EINTR)
125 msg_fatal("poll: %m");
126 continue;
127 case 0:
128 errno = ETIMEDOUT;
129 return (-1);
130 default:
131 if (pollfd.revents & POLLNVAL)
132 msg_fatal("poll: %m");
133 return (0);
136 #endif