aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2012-03-30 12:42:24 +0100
committerRon Yorston <rmy@pobox.com>2012-03-30 12:42:24 +0100
commit4319368c60244268a19f58fd6f1a0b31d3cd4853 (patch)
treea511501ed8bcc73ab24e0c5e5f9280ba713e7495
parent506360df73c9c9f95f4caf70373673cf55046c9d (diff)
downloadbusybox-w32-4319368c60244268a19f58fd6f1a0b31d3cd4853.tar.gz
busybox-w32-4319368c60244268a19f58fd6f1a0b31d3cd4853.tar.bz2
busybox-w32-4319368c60244268a19f58fd6f1a0b31d3cd4853.zip
Use gnulib poll, importing the version from git
-rw-r--r--include/mingw.h14
-rw-r--r--win32/Kbuild1
-rw-r--r--win32/mingw.c69
-rw-r--r--win32/poll.c606
-rw-r--r--win32/sys/poll.h53
5 files changed, 660 insertions, 83 deletions
diff --git a/include/mingw.h b/include/mingw.h
index b281a4b49..138275588 100644
--- a/include/mingw.h
+++ b/include/mingw.h
@@ -76,20 +76,6 @@ struct sockaddr_un {
76}; 76};
77 77
78/* 78/*
79 * poll.h
80 */
81struct pollfd {
82 int fd; /* file descriptor */
83 short events; /* requested events */
84 short revents; /* returned events */
85};
86typedef unsigned long nfds_t;
87#define POLLIN 1
88#define POLLHUP 2
89
90int poll(struct pollfd *ufds, unsigned int nfds, int timeout);
91
92/*
93 * pwd.h 79 * pwd.h
94 */ 80 */
95struct passwd { 81struct passwd {
diff --git a/win32/Kbuild b/win32/Kbuild
index ef3af7458..3b06e83a7 100644
--- a/win32/Kbuild
+++ b/win32/Kbuild
@@ -10,6 +10,7 @@ lib-$(CONFIG_PLATFORM_MINGW32) += mingw.o
10lib-$(CONFIG_PLATFORM_MINGW32) += process.o 10lib-$(CONFIG_PLATFORM_MINGW32) += process.o
11lib-$(CONFIG_PLATFORM_MINGW32) += regex.o 11lib-$(CONFIG_PLATFORM_MINGW32) += regex.o
12lib-$(CONFIG_WIN32_NET) += net.o 12lib-$(CONFIG_WIN32_NET) += net.o
13lib-$(CONFIG_PLATFORM_MINGW32) += poll.o
13lib-$(CONFIG_PLATFORM_MINGW32) += termios.o 14lib-$(CONFIG_PLATFORM_MINGW32) += termios.o
14lib-$(CONFIG_PLATFORM_MINGW32) += uname.o 15lib-$(CONFIG_PLATFORM_MINGW32) += uname.o
15lib-$(CONFIG_PLATFORM_MINGW32) += winansi.o 16lib-$(CONFIG_PLATFORM_MINGW32) += winansi.o
diff --git a/win32/mingw.c b/win32/mingw.c
index 0a7345374..df413d18e 100644
--- a/win32/mingw.c
+++ b/win32/mingw.c
@@ -421,75 +421,6 @@ int pipe(int filedes[2])
421 return 0; 421 return 0;
422} 422}
423 423
424int poll(struct pollfd *ufds, unsigned int nfds, int timeout)
425{
426 int i, pending;
427
428 if (timeout >= 0) {
429 if (nfds == 0) {
430 Sleep(timeout);
431 return 0;
432 }
433 errno = EINVAL;
434 return -1;
435 }
436
437 /* When there is only one fd to wait for, then we pretend that
438 * input is available and let the actual wait happen when the
439 * caller invokes read().
440 */
441 if (nfds == 1) {
442 if (!(ufds[0].events & POLLIN)) {
443 errno = EINVAL;
444 return -1;
445 }
446 ufds[0].revents = POLLIN;
447 return 0;
448 }
449
450repeat:
451 pending = 0;
452 for (i = 0; i < nfds; i++) {
453 DWORD avail = 0;
454 HANDLE h = (HANDLE) _get_osfhandle(ufds[i].fd);
455 if (h == INVALID_HANDLE_VALUE)
456 return -1; /* errno was set */
457
458 if (!(ufds[i].events & POLLIN)) {
459 errno = EINVAL;
460 return -1;
461 }
462
463 /* this emulation works only for pipes */
464 if (!PeekNamedPipe(h, NULL, 0, NULL, &avail, NULL)) {
465 int err = GetLastError();
466 if (err == ERROR_BROKEN_PIPE) {
467 ufds[i].revents = POLLHUP;
468 pending++;
469 } else {
470 errno = EINVAL;
471 return -1;
472 }
473 } else if (avail) {
474 ufds[i].revents = POLLIN;
475 pending++;
476 } else
477 ufds[i].revents = 0;
478 }
479 if (!pending) {
480 /* The only times that we spin here is when the process
481 * that is connected through the pipes is waiting for
482 * its own input data to become available. But since
483 * the process (pack-objects) is itself CPU intensive,
484 * it will happily pick up the time slice that we are
485 * relinguishing here.
486 */
487 Sleep(0);
488 goto repeat;
489 }
490 return 0;
491}
492
493struct tm *gmtime_r(const time_t *timep, struct tm *result) 424struct tm *gmtime_r(const time_t *timep, struct tm *result)
494{ 425{
495 /* gmtime() in MSVCRT.DLL is thread-safe, but not reentrant */ 426 /* gmtime() in MSVCRT.DLL is thread-safe, but not reentrant */
diff --git a/win32/poll.c b/win32/poll.c
new file mode 100644
index 000000000..4438305ce
--- /dev/null
+++ b/win32/poll.c
@@ -0,0 +1,606 @@
1/* Emulation for poll(2)
2 Contributed by Paolo Bonzini.
3
4 Copyright 2001-2003, 2006-2011 Free Software Foundation, Inc.
5
6 This file is part of gnulib.
7
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)
11 any later version.
12
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.
17
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. */
21
22/* Tell gcc not to warn about the (nfd < 0) tests, below. */
23#if (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) || 4 < __GNUC__
24# pragma GCC diagnostic ignored "-Wtype-limits"
25#endif
26
27#include <malloc.h>
28
29#include <sys/types.h>
30
31/* Specification. */
32#include <sys/poll.h>
33
34#include <errno.h>
35#include <limits.h>
36#include <assert.h>
37
38#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
39# define WIN32_NATIVE
40# if defined (_MSC_VER)
41# define _WIN32_WINNT 0x0502
42# endif
43# include <winsock2.h>
44# include <windows.h>
45# include <io.h>
46# include <stdio.h>
47# include <conio.h>
48#else
49# include <sys/time.h>
50# include <sys/socket.h>
51# include <sys/select.h>
52# include <unistd.h>
53#endif
54
55#ifdef HAVE_SYS_IOCTL_H
56# include <sys/ioctl.h>
57#endif
58#ifdef HAVE_SYS_FILIO_H
59# include <sys/filio.h>
60#endif
61
62#include <time.h>
63
64#ifndef INFTIM
65# define INFTIM (-1)
66#endif
67
68/* BeOS does not have MSG_PEEK. */
69#ifndef MSG_PEEK
70# define MSG_PEEK 0
71#endif
72
73#ifdef WIN32_NATIVE
74
75#define IsConsoleHandle(h) (((long) (h) & 3) == 3)
76
77static BOOL
78IsSocketHandle (HANDLE h)
79{
80 WSANETWORKEVENTS ev;
81
82 if (IsConsoleHandle (h))
83 return FALSE;
84
85 /* Under Wine, it seems that getsockopt returns 0 for pipes too.
86 WSAEnumNetworkEvents instead distinguishes the two correctly. */
87 ev.lNetworkEvents = 0xDEADBEEF;
88 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
89 return ev.lNetworkEvents != 0xDEADBEEF;
90}
91
92/* Declare data structures for ntdll functions. */
93typedef struct _FILE_PIPE_LOCAL_INFORMATION {
94 ULONG NamedPipeType;
95 ULONG NamedPipeConfiguration;
96 ULONG MaximumInstances;
97 ULONG CurrentInstances;
98 ULONG InboundQuota;
99 ULONG ReadDataAvailable;
100 ULONG OutboundQuota;
101 ULONG WriteQuotaAvailable;
102 ULONG NamedPipeState;
103 ULONG NamedPipeEnd;
104} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
105
106typedef struct _IO_STATUS_BLOCK
107{
108 union {
109 DWORD Status;
110 PVOID Pointer;
111 } u;
112 ULONG_PTR Information;
113} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
114
115typedef enum _FILE_INFORMATION_CLASS {
116 FilePipeLocalInformation = 24
117} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
118
119typedef DWORD (WINAPI *PNtQueryInformationFile)
120 (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
121
122# ifndef PIPE_BUF
123# define PIPE_BUF 512
124# endif
125
126/* Compute revents values for file handle H. If some events cannot happen
127 for the handle, eliminate them from *P_SOUGHT. */
128
129static int
130win32_compute_revents (HANDLE h, int *p_sought)
131{
132 int i, ret, happened;
133 INPUT_RECORD *irbuffer;
134 DWORD avail, nbuffer;
135 BOOL bRet;
136 IO_STATUS_BLOCK iosb;
137 FILE_PIPE_LOCAL_INFORMATION fpli;
138 static PNtQueryInformationFile NtQueryInformationFile;
139 static BOOL once_only;
140
141 switch (GetFileType (h))
142 {
143 case FILE_TYPE_PIPE:
144 if (!once_only)
145 {
146 NtQueryInformationFile = (PNtQueryInformationFile)
147 GetProcAddress (GetModuleHandle ("ntdll.dll"),
148 "NtQueryInformationFile");
149 once_only = TRUE;
150 }
151
152 happened = 0;
153 if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
154 {
155 if (avail)
156 happened |= *p_sought & (POLLIN | POLLRDNORM);
157 }
158 else if (GetLastError () == ERROR_BROKEN_PIPE)
159 happened |= POLLHUP;
160
161 else
162 {
163 /* It was the write-end of the pipe. Check if it is writable.
164 If NtQueryInformationFile fails, optimistically assume the pipe is
165 writable. This could happen on Win9x, where NtQueryInformationFile
166 is not available, or if we inherit a pipe that doesn't permit
167 FILE_READ_ATTRIBUTES access on the write end (I think this should
168 not happen since WinXP SP2; WINE seems fine too). Otherwise,
169 ensure that enough space is available for atomic writes. */
170 memset (&iosb, 0, sizeof (iosb));
171 memset (&fpli, 0, sizeof (fpli));
172
173 if (!NtQueryInformationFile
174 || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
175 FilePipeLocalInformation)
176 || fpli.WriteQuotaAvailable >= PIPE_BUF
177 || (fpli.OutboundQuota < PIPE_BUF &&
178 fpli.WriteQuotaAvailable == fpli.OutboundQuota))
179 happened |= *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
180 }
181 return happened;
182
183 case FILE_TYPE_CHAR:
184 ret = WaitForSingleObject (h, 0);
185 if (!IsConsoleHandle (h))
186 return ret == WAIT_OBJECT_0 ? *p_sought & ~(POLLPRI | POLLRDBAND) : 0;
187
188 nbuffer = avail = 0;
189 bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
190 if (bRet)
191 {
192 /* Input buffer. */
193 *p_sought &= POLLIN | POLLRDNORM;
194 if (nbuffer == 0)
195 return POLLHUP;
196 if (!*p_sought)
197 return 0;
198
199 irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
200 bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
201 if (!bRet || avail == 0)
202 return POLLHUP;
203
204 for (i = 0; i < avail; i++)
205 if (irbuffer[i].EventType == KEY_EVENT)
206 return *p_sought;
207 return 0;
208 }
209 else
210 {
211 /* Screen buffer. */
212 *p_sought &= POLLOUT | POLLWRNORM | POLLWRBAND;
213 return *p_sought;
214 }
215
216 default:
217 ret = WaitForSingleObject (h, 0);
218 if (ret == WAIT_OBJECT_0)
219 return *p_sought & ~(POLLPRI | POLLRDBAND);
220
221 return *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
222 }
223}
224
225/* Convert fd_sets returned by select into revents values. */
226
227static int
228win32_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents)
229{
230 int happened = 0;
231
232 if ((lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) == FD_ACCEPT)
233 happened |= (POLLIN | POLLRDNORM) & sought;
234
235 else if (lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
236 {
237 int r, error;
238
239 char data[64];
240 WSASetLastError (0);
241 r = recv (h, data, sizeof (data), MSG_PEEK);
242 error = WSAGetLastError ();
243 WSASetLastError (0);
244
245 if (r > 0 || error == WSAENOTCONN)
246 happened |= (POLLIN | POLLRDNORM) & sought;
247
248 /* Distinguish hung-up sockets from other errors. */
249 else if (r == 0 || error == WSAESHUTDOWN || error == WSAECONNRESET
250 || error == WSAECONNABORTED || error == WSAENETRESET)
251 happened |= POLLHUP;
252
253 else
254 happened |= POLLERR;
255 }
256
257 if (lNetworkEvents & (FD_WRITE | FD_CONNECT))
258 happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
259
260 if (lNetworkEvents & FD_OOB)
261 happened |= (POLLPRI | POLLRDBAND) & sought;
262
263 return happened;
264}
265
266#else /* !MinGW */
267
268/* Convert select(2) returned fd_sets into poll(2) revents values. */
269static int
270compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds)
271{
272 int happened = 0;
273 if (FD_ISSET (fd, rfds))
274 {
275 int r;
276 int socket_errno;
277
278# if defined __MACH__ && defined __APPLE__
279 /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
280 for some kinds of descriptors. Detect if this descriptor is a
281 connected socket, a server socket, or something else using a
282 0-byte recv, and use ioctl(2) to detect POLLHUP. */
283 r = recv (fd, NULL, 0, MSG_PEEK);
284 socket_errno = (r < 0) ? errno : 0;
285 if (r == 0 || socket_errno == ENOTSOCK)
286 ioctl (fd, FIONREAD, &r);
287# else
288 char data[64];
289 r = recv (fd, data, sizeof (data), MSG_PEEK);
290 socket_errno = (r < 0) ? errno : 0;
291# endif
292 if (r == 0)
293 happened |= POLLHUP;
294
295 /* If the event happened on an unconnected server socket,
296 that's fine. */
297 else if (r > 0 || ( /* (r == -1) && */ socket_errno == ENOTCONN))
298 happened |= (POLLIN | POLLRDNORM) & sought;
299
300 /* Distinguish hung-up sockets from other errors. */
301 else if (socket_errno == ESHUTDOWN || socket_errno == ECONNRESET
302 || socket_errno == ECONNABORTED || socket_errno == ENETRESET)
303 happened |= POLLHUP;
304
305 else
306 happened |= POLLERR;
307 }
308
309 if (FD_ISSET (fd, wfds))
310 happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
311
312 if (FD_ISSET (fd, efds))
313 happened |= (POLLPRI | POLLRDBAND) & sought;
314
315 return happened;
316}
317#endif /* !MinGW */
318
319int
320poll (struct pollfd *pfd, nfds_t nfd, int timeout)
321{
322#ifndef WIN32_NATIVE
323 fd_set rfds, wfds, efds;
324 struct timeval tv;
325 struct timeval *ptv;
326 int maxfd, rc;
327 nfds_t i;
328
329# ifdef _SC_OPEN_MAX
330 static int sc_open_max = -1;
331
332 if (nfd < 0
333 || (nfd > sc_open_max
334 && (sc_open_max != -1
335 || nfd > (sc_open_max = sysconf (_SC_OPEN_MAX)))))
336 {
337 errno = EINVAL;
338 return -1;
339 }
340# else /* !_SC_OPEN_MAX */
341# ifdef OPEN_MAX
342 if (nfd < 0 || nfd > OPEN_MAX)
343 {
344 errno = EINVAL;
345 return -1;
346 }
347# endif /* OPEN_MAX -- else, no check is needed */
348# endif /* !_SC_OPEN_MAX */
349
350 /* EFAULT is not necessary to implement, but let's do it in the
351 simplest case. */
352 if (!pfd)
353 {
354 errno = EFAULT;
355 return -1;
356 }
357
358 /* convert timeout number into a timeval structure */
359 if (timeout == 0)
360 {
361 ptv = &tv;
362 ptv->tv_sec = 0;
363 ptv->tv_usec = 0;
364 }
365 else if (timeout > 0)
366 {
367 ptv = &tv;
368 ptv->tv_sec = timeout / 1000;
369 ptv->tv_usec = (timeout % 1000) * 1000;
370 }
371 else if (timeout == INFTIM)
372 /* wait forever */
373 ptv = NULL;
374 else
375 {
376 errno = EINVAL;
377 return -1;
378 }
379
380 /* create fd sets and determine max fd */
381 maxfd = -1;
382 FD_ZERO (&rfds);
383 FD_ZERO (&wfds);
384 FD_ZERO (&efds);
385 for (i = 0; i < nfd; i++)
386 {
387 if (pfd[i].fd < 0)
388 continue;
389
390 if (pfd[i].events & (POLLIN | POLLRDNORM))
391 FD_SET (pfd[i].fd, &rfds);
392
393 /* see select(2): "the only exceptional condition detectable
394 is out-of-band data received on a socket", hence we push
395 POLLWRBAND events onto wfds instead of efds. */
396 if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND))
397 FD_SET (pfd[i].fd, &wfds);
398 if (pfd[i].events & (POLLPRI | POLLRDBAND))
399 FD_SET (pfd[i].fd, &efds);
400 if (pfd[i].fd >= maxfd
401 && (pfd[i].events & (POLLIN | POLLOUT | POLLPRI
402 | POLLRDNORM | POLLRDBAND
403 | POLLWRNORM | POLLWRBAND)))
404 {
405 maxfd = pfd[i].fd;
406 if (maxfd > FD_SETSIZE)
407 {
408 errno = EOVERFLOW;
409 return -1;
410 }
411 }
412 }
413
414 /* examine fd sets */
415 rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv);
416 if (rc < 0)
417 return rc;
418
419 /* establish results */
420 rc = 0;
421 for (i = 0; i < nfd; i++)
422 if (pfd[i].fd < 0)
423 pfd[i].revents = 0;
424 else
425 {
426 int happened = compute_revents (pfd[i].fd, pfd[i].events,
427 &rfds, &wfds, &efds);
428 if (happened)
429 {
430 pfd[i].revents = happened;
431 rc++;
432 }
433 }
434
435 return rc;
436#else
437 static struct timeval tv0;
438 static HANDLE hEvent;
439 WSANETWORKEVENTS ev;
440 HANDLE h, handle_array[FD_SETSIZE + 2];
441 DWORD ret, wait_timeout, nhandles;
442 fd_set rfds, wfds, xfds;
443 BOOL poll_again;
444 MSG msg;
445 int rc = 0;
446 nfds_t i;
447
448 if (nfd < 0 || timeout < -1)
449 {
450 errno = EINVAL;
451 return -1;
452 }
453
454 if (!hEvent)
455 hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
456
457restart:
458 handle_array[0] = hEvent;
459 nhandles = 1;
460 FD_ZERO (&rfds);
461 FD_ZERO (&wfds);
462 FD_ZERO (&xfds);
463
464 /* Classify socket handles and create fd sets. */
465 for (i = 0; i < nfd; i++)
466 {
467 int sought = pfd[i].events;
468 pfd[i].revents = 0;
469 if (pfd[i].fd < 0)
470 continue;
471 if (!(sought & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLWRBAND
472 | POLLPRI | POLLRDBAND)))
473 continue;
474
475 h = (HANDLE) _get_osfhandle (pfd[i].fd);
476 assert (h != NULL);
477 if (IsSocketHandle (h))
478 {
479 int requested = FD_CLOSE;
480
481 /* see above; socket handles are mapped onto select. */
482 if (sought & (POLLIN | POLLRDNORM))
483 {
484 requested |= FD_READ | FD_ACCEPT;
485 FD_SET ((SOCKET) h, &rfds);
486 }
487 if (sought & (POLLOUT | POLLWRNORM | POLLWRBAND))
488 {
489 requested |= FD_WRITE | FD_CONNECT;
490 FD_SET ((SOCKET) h, &wfds);
491 }
492 if (sought & (POLLPRI | POLLRDBAND))
493 {
494 requested |= FD_OOB;
495 FD_SET ((SOCKET) h, &xfds);
496 }
497
498 if (requested)
499 WSAEventSelect ((SOCKET) h, hEvent, requested);
500 }
501 else
502 {
503 /* Poll now. If we get an event, do not poll again. Also,
504 screen buffer handles are waitable, and they'll block until
505 a character is available. win32_compute_revents eliminates
506 bits for the "wrong" direction. */
507 pfd[i].revents = win32_compute_revents (h, &sought);
508 if (sought)
509 handle_array[nhandles++] = h;
510 if (pfd[i].revents)
511 timeout = 0;
512 }
513 }
514
515 if (select (0, &rfds, &wfds, &xfds, &tv0) > 0)
516 {
517 /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
518 no need to call select again. */
519 poll_again = FALSE;
520 wait_timeout = 0;
521 }
522 else
523 {
524 poll_again = TRUE;
525 if (timeout == INFTIM)
526 wait_timeout = INFINITE;
527 else
528 wait_timeout = timeout;
529 }
530
531 for (;;)
532 {
533 ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
534 wait_timeout, QS_ALLINPUT);
535
536 if (ret == WAIT_OBJECT_0 + nhandles)
537 {
538 /* new input of some other kind */
539 BOOL bRet;
540 while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
541 {
542 TranslateMessage (&msg);
543 DispatchMessage (&msg);
544 }
545 }
546 else
547 break;
548 }
549
550 if (poll_again)
551 select (0, &rfds, &wfds, &xfds, &tv0);
552
553 /* Place a sentinel at the end of the array. */
554 handle_array[nhandles] = NULL;
555 nhandles = 1;
556 for (i = 0; i < nfd; i++)
557 {
558 int happened;
559
560 if (pfd[i].fd < 0)
561 continue;
562 if (!(pfd[i].events & (POLLIN | POLLRDNORM |
563 POLLOUT | POLLWRNORM | POLLWRBAND)))
564 continue;
565
566 h = (HANDLE) _get_osfhandle (pfd[i].fd);
567 if (h != handle_array[nhandles])
568 {
569 /* It's a socket. */
570 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
571 WSAEventSelect ((SOCKET) h, 0, 0);
572
573 /* If we're lucky, WSAEnumNetworkEvents already provided a way
574 to distinguish FD_READ and FD_ACCEPT; this saves a recv later. */
575 if (FD_ISSET ((SOCKET) h, &rfds)
576 && !(ev.lNetworkEvents & (FD_READ | FD_ACCEPT)))
577 ev.lNetworkEvents |= FD_READ | FD_ACCEPT;
578 if (FD_ISSET ((SOCKET) h, &wfds))
579 ev.lNetworkEvents |= FD_WRITE | FD_CONNECT;
580 if (FD_ISSET ((SOCKET) h, &xfds))
581 ev.lNetworkEvents |= FD_OOB;
582
583 happened = win32_compute_revents_socket ((SOCKET) h, pfd[i].events,
584 ev.lNetworkEvents);
585 }
586 else
587 {
588 /* Not a socket. */
589 int sought = pfd[i].events;
590 happened = win32_compute_revents (h, &sought);
591 nhandles++;
592 }
593
594 if ((pfd[i].revents |= happened) != 0)
595 rc++;
596 }
597
598 if (!rc && timeout == INFTIM)
599 {
600 SwitchToThread();
601 goto restart;
602 }
603
604 return rc;
605#endif
606}
diff --git a/win32/sys/poll.h b/win32/sys/poll.h
index e69de29bb..b7aa59d97 100644
--- a/win32/sys/poll.h
+++ b/win32/sys/poll.h
@@ -0,0 +1,53 @@
1/* Header for poll(2) emulation
2 Contributed by Paolo Bonzini.
3
4 Copyright 2001, 2002, 2003, 2007, 2009, 2010 Free Software Foundation, Inc.
5
6 This file is part of gnulib.
7
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)
11 any later version.
12
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.
17
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. */
21
22#ifndef _GL_POLL_H
23#define _GL_POLL_H
24
25/* fake a poll(2) environment */
26#define POLLIN 0x0001 /* any readable data available */
27#define POLLPRI 0x0002 /* OOB/Urgent readable data */
28#define POLLOUT 0x0004 /* file descriptor is writeable */
29#define POLLERR 0x0008 /* some poll error occurred */
30#define POLLHUP 0x0010 /* file descriptor was "hung up" */
31#define POLLNVAL 0x0020 /* requested events "invalid" */
32#define POLLRDNORM 0x0040
33#define POLLRDBAND 0x0080
34#define POLLWRNORM 0x0100
35#define POLLWRBAND 0x0200
36
37struct pollfd
38{
39 int fd; /* which file descriptor to poll */
40 short events; /* events we are interested in */
41 short revents; /* events found on return */
42};
43
44typedef unsigned long nfds_t;
45
46extern int poll (struct pollfd *pfd, nfds_t nfd, int timeout);
47
48/* Define INFTIM only if doing so conforms to POSIX. */
49#if !defined (_POSIX_C_SOURCE) && !defined (_XOPEN_SOURCE)
50#define INFTIM (-1)
51#endif
52
53#endif /* _GL_POLL_H */