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