1 /* Emulation for poll(2)
2 Contributed by Paolo Bonzini.
4 Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
6 This file is part of gnulib.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License along
19 with this program; if not, write to the Free Software Foundation,
20 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
26 #include <sys/types.h>
30 #include <sys/socket.h>
31 #include <sys/select.h>
34 #if TIME_WITH_SYS_TIME
35 # include <sys/time.h>
39 # include <sys/time.h>
50 #define EOVERFLOW EINVAL
54 poll (pfd, nfd, timeout)
59 fd_set rfds, wfds, efds;
60 struct timeval tv, *ptv;
61 int maxfd, rc, happened;
66 if (nfd > sysconf (_SC_OPEN_MAX))
71 #else /* !_SC_OPEN_MAX */
78 #endif /* OPEN_MAX -- else, no check is needed */
79 #endif /* !_SC_OPEN_MAX */
81 /* EFAULT is not necessary to implement, but let's do it in the
89 /* convert timeout number into a timeval structure */
93 /* return immediately or after timeout */
94 ptv->tv_sec = timeout / 1000;
95 ptv->tv_usec = (timeout % 1000) * 1000;
97 else if (timeout == INFTIM)
106 /* create fd sets and determine max fd */
111 for (i = 0; i < nfd; i++)
116 if (pfd[i].events & (POLLIN | POLLRDNORM))
117 FD_SET (pfd[i].fd, &rfds);
119 /* see select(2): "the only exceptional condition detectable
120 is out-of-band data received on a socket", hence we push
121 POLLWRBAND events onto wfds instead of efds. */
122 if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND))
123 FD_SET (pfd[i].fd, &wfds);
124 if (pfd[i].events & (POLLPRI | POLLRDBAND))
125 FD_SET (pfd[i].fd, &efds);
126 if (pfd[i].fd >= maxfd
127 && (pfd[i].events & (POLLIN | POLLOUT | POLLPRI
128 | POLLRDNORM | POLLRDBAND
129 | POLLWRNORM | POLLWRBAND)))
132 if (maxfd > FD_SETSIZE)
140 /* examine fd sets */
141 rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv);
143 /* establish results */
147 for (i = 0; i < nfd; i++)
154 if (FD_ISSET (pfd[i].fd, &rfds))
156 /* support for POLLHUP. An hung up descriptor does not
157 increase the return value! */
158 if (recv (pfd[i].fd, data, 64, MSG_PEEK) == -1)
160 if (errno == ESHUTDOWN || errno == ECONNRESET
161 || errno == ECONNABORTED || errno == ENETRESET)
162 pfd[i].revents |= POLLHUP;
165 happened |= POLLIN | POLLRDNORM;
168 if (FD_ISSET (pfd[i].fd, &wfds))
169 happened |= POLLOUT | POLLWRNORM | POLLWRBAND;
171 if (FD_ISSET (pfd[i].fd, &efds))
172 happened |= POLLPRI | POLLRDBAND;
174 pfd[i].revents |= pfd[i].events & happened;
175 rc += (happened > 0);