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