@matheusbsbs / matheus-bagliano / commits / 49521af8a8
Fork 0

mingw: import poll-emulation from gnulib

copy lib/poll.c and lib/poll.in.h verbatim from commit 0a05120 in git://git.savannah.gnu.org/gnulib.git to compat/win32/sys/poll.[ch] To upgrade this code in the future, branch out from this commit, copy new versions of the files above on top, and merge back the result. Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

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