1 /* Emulation for poll(2)
2 Contributed by Paolo Bonzini.
4 Copyright 2001, 2002, 2003, 2006, 2007, 2008 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. */
24 #include <sys/types.h>
28 #include <sys/socket.h>
29 #include <sys/select.h>
32 #ifdef HAVE_SYS_IOCTL_H
33 #include <sys/ioctl.h>
35 #ifdef HAVE_SYS_FILIO_H
36 #include <sys/filio.h>
46 /* BeOS does not have MSG_PEEK. */
52 poll (pfd, nfd, timeout)
57 fd_set rfds, wfds, efds;
58 struct timeval tv = { 0, 0 };
64 static int sc_open_max = -1;
69 || nfd > (sc_open_max = sysconf (_SC_OPEN_MAX)))))
74 #else /* !_SC_OPEN_MAX */
76 if (nfd < 0 || nfd > OPEN_MAX)
81 #endif /* OPEN_MAX -- else, no check is needed */
82 #endif /* !_SC_OPEN_MAX */
84 /* EFAULT is not necessary to implement, but let's do it in the
92 /* convert timeout number into a timeval structure */
98 ptv->tv_sec = timeout / 1000;
99 ptv->tv_usec = (timeout % 1000) * 1000;
101 else if (timeout == INFTIM)
110 /* create fd sets and determine max fd */
115 for (i = 0; i < nfd; i++)
120 if (pfd[i].events & (POLLIN | POLLRDNORM))
121 FD_SET (pfd[i].fd, &rfds);
123 /* see select(2): "the only exceptional condition detectable
124 is out-of-band data received on a socket", hence we push
125 POLLWRBAND events onto wfds instead of efds. */
126 if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND))
127 FD_SET (pfd[i].fd, &wfds);
128 if (pfd[i].events & (POLLPRI | POLLRDBAND))
129 FD_SET (pfd[i].fd, &efds);
130 if (pfd[i].fd >= maxfd
131 && (pfd[i].events & (POLLIN | POLLOUT | POLLPRI
132 | POLLRDNORM | POLLRDBAND
133 | POLLWRNORM | POLLWRBAND)))
137 /* Windows use a linear array of sockets (of size FD_SETSIZE). The
138 descriptor value is not used to address the array. */
139 #if defined __CYGWIN__ || (!defined _WIN32 && !defined __WIN32__)
140 if (maxfd > FD_SETSIZE)
149 /* examine fd sets */
150 rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv);
154 /* establish results */
156 for (i = 0; i < nfd; i++)
161 int happened = 0, sought = pfd[i].events;
162 if (FD_ISSET (pfd[i].fd, &rfds))
167 #if defined __MACH__ && defined __APPLE__
168 /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
169 for some kinds of descriptors. Detect if this descriptor is a
170 connected socket, a server socket, or something else using a
171 0-byte recv, and use ioctl(2) to detect POLLHUP. */
172 r = recv (pfd[i].fd, NULL, 0, MSG_PEEK);
173 socket_errno = (r < 0) ? errno : 0;
174 if (r == 0 || socket_errno == ENOTSOCK)
175 ioctl(pfd[i].fd, FIONREAD, &r);
178 r = recv (pfd[i].fd, data, sizeof (data), MSG_PEEK);
179 socket_errno = (r < 0) ? errno : 0;
184 /* If the event happened on an unconnected server socket,
186 else if (r > 0 || ( /* (r == -1) && */ socket_errno == ENOTCONN))
187 happened |= (POLLIN | POLLRDNORM) & sought;
189 /* Distinguish hung-up sockets from other errors. */
190 else if (socket_errno == ESHUTDOWN || socket_errno == ECONNRESET
191 || socket_errno == ECONNABORTED || socket_errno == ENETRESET)
198 if (FD_ISSET (pfd[i].fd, &wfds))
199 happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
201 if (FD_ISSET (pfd[i].fd, &efds))
202 happened |= (POLLPRI | POLLRDBAND) & sought;
206 pfd[i].revents = happened;