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 gnulib is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published
10 by the Free Software Foundation; either version 2.1, or (at your option)
13 gnulib is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16 License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with gnulib; see the file COPYING.LIB. If not, write to the Free
20 Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
28 #include <sys/types.h>
32 #include <sys/socket.h>
33 #include <sys/select.h>
36 #if TIME_WITH_SYS_TIME
37 # include <sys/time.h>
41 # include <sys/time.h>
52 #define EOVERFLOW EINVAL
56 poll (pfd, nfd, timeout)
61 fd_set rfds, wfds, efds;
62 struct timeval tv, *ptv;
63 int maxfd, rc, happened;
68 if (nfd > sysconf (_SC_OPEN_MAX))
73 #else /* !_SC_OPEN_MAX */
80 #endif /* OPEN_MAX -- else, no check is needed */
81 #endif /* !_SC_OPEN_MAX */
83 /* EFAULT is not necessary to implement, but let's do it in the
91 /* convert timeout number into a timeval structure */
95 /* return immediately or after timeout */
96 ptv->tv_sec = timeout / 1000;
97 ptv->tv_usec = (timeout % 1000) * 1000;
99 else if (timeout == INFTIM)
108 /* create fd sets and determine max fd */
113 for (i = 0; i < nfd; i++)
118 if (pfd[i].events & (POLLIN | POLLRDNORM))
119 FD_SET (pfd[i].fd, &rfds);
121 /* see select(2): "the only exceptional condition detectable
122 is out-of-band data received on a socket", hence we push
123 POLLWRBAND events onto wfds instead of efds. */
124 if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND))
125 FD_SET (pfd[i].fd, &wfds);
126 if (pfd[i].events & (POLLPRI | POLLRDBAND))
127 FD_SET (pfd[i].fd, &efds);
128 if (pfd[i].fd >= maxfd
129 && (pfd[i].events & (POLLIN | POLLOUT | POLLPRI
130 | POLLRDNORM | POLLRDBAND
131 | POLLWRNORM | POLLWRBAND)))
134 if (maxfd > FD_SETSIZE)
142 /* examine fd sets */
143 rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv);
145 /* establish results */
149 for (i = 0; i < nfd; i++)
156 if (FD_ISSET (pfd[i].fd, &rfds))
158 /* support for POLLHUP. An hung up descriptor does not
159 increase the return value! */
160 if (recv (pfd[i].fd, data, 64, MSG_PEEK) == -1)
162 if (errno == ESHUTDOWN || errno == ECONNRESET
163 || errno == ECONNABORTED || errno == ENETRESET)
164 pfd[i].revents |= POLLHUP;
167 happened |= POLLIN | POLLRDNORM;
170 if (FD_ISSET (pfd[i].fd, &wfds))
171 happened |= POLLOUT | POLLWRNORM | POLLWRBAND;
173 if (FD_ISSET (pfd[i].fd, &efds))
174 happened |= POLLPRI | POLLRDBAND;
176 pfd[i].revents |= pfd[i].events & happened;
177 rc += (happened > 0);