isatty: Support for MSVC 9.
[gnulib.git] / lib / select.c
1 /* Emulation for select(2)
2    Contributed by Paolo Bonzini.
3
4    Copyright 2008-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 #include <config.h>
23 #include <alloca.h>
24 #include <assert.h>
25
26 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
27 /* Native Win32.  */
28
29 #include <sys/types.h>
30 #include <errno.h>
31 #include <limits.h>
32
33 #include <winsock2.h>
34 #include <windows.h>
35 #include <io.h>
36 #include <stdio.h>
37 #include <conio.h>
38 #include <time.h>
39
40 #include "msvc-nothrow.h"
41
42 struct bitset {
43   unsigned char in[FD_SETSIZE / CHAR_BIT];
44   unsigned char out[FD_SETSIZE / CHAR_BIT];
45 };
46
47 /* Declare data structures for ntdll functions.  */
48 typedef struct _FILE_PIPE_LOCAL_INFORMATION {
49   ULONG NamedPipeType;
50   ULONG NamedPipeConfiguration;
51   ULONG MaximumInstances;
52   ULONG CurrentInstances;
53   ULONG InboundQuota;
54   ULONG ReadDataAvailable;
55   ULONG OutboundQuota;
56   ULONG WriteQuotaAvailable;
57   ULONG NamedPipeState;
58   ULONG NamedPipeEnd;
59 } FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
60
61 typedef struct _IO_STATUS_BLOCK
62 {
63   union {
64     DWORD Status;
65     PVOID Pointer;
66   } u;
67   ULONG_PTR Information;
68 } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
69
70 typedef enum _FILE_INFORMATION_CLASS {
71   FilePipeLocalInformation = 24
72 } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
73
74 typedef DWORD (WINAPI *PNtQueryInformationFile)
75          (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
76
77 #ifndef PIPE_BUF
78 #define PIPE_BUF        512
79 #endif
80
81 /* Optimized test whether a HANDLE refers to a console.
82    See <http://lists.gnu.org/archive/html/bug-gnulib/2009-08/msg00065.html>.  */
83 #define IsConsoleHandle(h) (((long) (h) & 3) == 3)
84
85 static BOOL
86 IsSocketHandle (HANDLE h)
87 {
88   WSANETWORKEVENTS ev;
89
90   if (IsConsoleHandle (h))
91     return FALSE;
92
93   /* Under Wine, it seems that getsockopt returns 0 for pipes too.
94      WSAEnumNetworkEvents instead distinguishes the two correctly.  */
95   ev.lNetworkEvents = 0xDEADBEEF;
96   WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
97   return ev.lNetworkEvents != 0xDEADBEEF;
98 }
99
100 /* Compute output fd_sets for libc descriptor FD (whose Win32 handle is H).  */
101
102 static int
103 win32_poll_handle (HANDLE h, int fd, struct bitset *rbits, struct bitset *wbits,
104                    struct bitset *xbits)
105 {
106   BOOL read, write, except;
107   int i, ret;
108   INPUT_RECORD *irbuffer;
109   DWORD avail, nbuffer;
110   BOOL bRet;
111   IO_STATUS_BLOCK iosb;
112   FILE_PIPE_LOCAL_INFORMATION fpli;
113   static PNtQueryInformationFile NtQueryInformationFile;
114   static BOOL once_only;
115
116   read = write = except = FALSE;
117   switch (GetFileType (h))
118     {
119     case FILE_TYPE_DISK:
120       read = TRUE;
121       write = TRUE;
122       break;
123
124     case FILE_TYPE_PIPE:
125       if (!once_only)
126         {
127           NtQueryInformationFile = (PNtQueryInformationFile)
128             GetProcAddress (GetModuleHandle ("ntdll.dll"),
129                             "NtQueryInformationFile");
130           once_only = TRUE;
131         }
132
133       if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
134         {
135           if (avail)
136             read = TRUE;
137         }
138       else if (GetLastError () == ERROR_BROKEN_PIPE)
139         ;
140
141       else
142         {
143           /* It was the write-end of the pipe.  Check if it is writable.
144              If NtQueryInformationFile fails, optimistically assume the pipe is
145              writable.  This could happen on Win9x, where NtQueryInformationFile
146              is not available, or if we inherit a pipe that doesn't permit
147              FILE_READ_ATTRIBUTES access on the write end (I think this should
148              not happen since WinXP SP2; WINE seems fine too).  Otherwise,
149              ensure that enough space is available for atomic writes.  */
150           memset (&iosb, 0, sizeof (iosb));
151           memset (&fpli, 0, sizeof (fpli));
152
153           if (!NtQueryInformationFile
154               || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
155                                          FilePipeLocalInformation)
156               || fpli.WriteQuotaAvailable >= PIPE_BUF
157               || (fpli.OutboundQuota < PIPE_BUF &&
158                   fpli.WriteQuotaAvailable == fpli.OutboundQuota))
159             write = TRUE;
160         }
161       break;
162
163     case FILE_TYPE_CHAR:
164       write = TRUE;
165       if (!(rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
166         break;
167
168       ret = WaitForSingleObject (h, 0);
169       if (ret == WAIT_OBJECT_0)
170         {
171           if (!IsConsoleHandle (h))
172             {
173               read = TRUE;
174               break;
175             }
176
177           nbuffer = avail = 0;
178           bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
179
180           /* Screen buffers handles are filtered earlier.  */
181           assert (bRet);
182           if (nbuffer == 0)
183             {
184               except = TRUE;
185               break;
186             }
187
188           irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
189           bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
190           if (!bRet || avail == 0)
191             {
192               except = TRUE;
193               break;
194             }
195
196           for (i = 0; i < avail; i++)
197             if (irbuffer[i].EventType == KEY_EVENT)
198               read = TRUE;
199         }
200       break;
201
202     default:
203       ret = WaitForSingleObject (h, 0);
204       write = TRUE;
205       if (ret == WAIT_OBJECT_0)
206         read = TRUE;
207
208       break;
209     }
210
211   ret = 0;
212   if (read && (rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
213     {
214       rbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
215       ret++;
216     }
217
218   if (write && (wbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
219     {
220       wbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
221       ret++;
222     }
223
224   if (except && (xbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
225     {
226       xbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
227       ret++;
228     }
229
230   return ret;
231 }
232
233 int
234 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
235             struct timeval *timeout)
236 {
237   static struct timeval tv0;
238   static HANDLE hEvent;
239   HANDLE h, handle_array[FD_SETSIZE + 2];
240   fd_set handle_rfds, handle_wfds, handle_xfds;
241   struct bitset rbits, wbits, xbits;
242   unsigned char anyfds_in[FD_SETSIZE / CHAR_BIT];
243   DWORD ret, wait_timeout, nhandles, nsock, nbuffer;
244   MSG msg;
245   int i, fd, rc;
246
247   if (nfds > FD_SETSIZE)
248     nfds = FD_SETSIZE;
249
250   if (!timeout)
251     wait_timeout = INFINITE;
252   else
253     {
254       wait_timeout = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
255
256       /* select is also used as a portable usleep.  */
257       if (!rfds && !wfds && !xfds)
258         {
259           Sleep (wait_timeout);
260           return 0;
261         }
262     }
263
264   if (!hEvent)
265     hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
266
267   handle_array[0] = hEvent;
268   nhandles = 1;
269   nsock = 0;
270
271   /* Copy descriptors to bitsets.  At the same time, eliminate
272      bits in the "wrong" direction for console input buffers
273      and screen buffers, because screen buffers are waitable
274      and they will block until a character is available.  */
275   memset (&rbits, 0, sizeof (rbits));
276   memset (&wbits, 0, sizeof (wbits));
277   memset (&xbits, 0, sizeof (xbits));
278   memset (anyfds_in, 0, sizeof (anyfds_in));
279   if (rfds)
280     for (i = 0; i < rfds->fd_count; i++)
281       {
282         fd = rfds->fd_array[i];
283         h = (HANDLE) _get_osfhandle (fd);
284         if (IsConsoleHandle (h)
285             && !GetNumberOfConsoleInputEvents (h, &nbuffer))
286           continue;
287
288         rbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
289         anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
290       }
291   else
292     rfds = (fd_set *) alloca (sizeof (fd_set));
293
294   if (wfds)
295     for (i = 0; i < wfds->fd_count; i++)
296       {
297         fd = wfds->fd_array[i];
298         h = (HANDLE) _get_osfhandle (fd);
299         if (IsConsoleHandle (h)
300             && GetNumberOfConsoleInputEvents (h, &nbuffer))
301           continue;
302
303         wbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
304         anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
305       }
306   else
307     wfds = (fd_set *) alloca (sizeof (fd_set));
308
309   if (xfds)
310     for (i = 0; i < xfds->fd_count; i++)
311       {
312         fd = xfds->fd_array[i];
313         xbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
314         anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
315       }
316   else
317     xfds = (fd_set *) alloca (sizeof (fd_set));
318
319   /* Zero all the fd_sets, including the application's.  */
320   FD_ZERO (rfds);
321   FD_ZERO (wfds);
322   FD_ZERO (xfds);
323   FD_ZERO (&handle_rfds);
324   FD_ZERO (&handle_wfds);
325   FD_ZERO (&handle_xfds);
326
327   /* Classify handles.  Create fd sets for sockets, poll the others. */
328   for (i = 0; i < nfds; i++)
329     {
330       if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
331         continue;
332
333       h = (HANDLE) _get_osfhandle (i);
334       if (!h)
335         {
336           errno = EBADF;
337           return -1;
338         }
339
340       if (IsSocketHandle (h))
341         {
342           int requested = FD_CLOSE;
343
344           /* See above; socket handles are mapped onto select, but we
345              need to map descriptors to handles.  */
346           if (rbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
347             {
348               requested |= FD_READ | FD_ACCEPT;
349               FD_SET ((SOCKET) h, rfds);
350               FD_SET ((SOCKET) h, &handle_rfds);
351             }
352           if (wbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
353             {
354               requested |= FD_WRITE | FD_CONNECT;
355               FD_SET ((SOCKET) h, wfds);
356               FD_SET ((SOCKET) h, &handle_wfds);
357             }
358           if (xbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
359             {
360               requested |= FD_OOB;
361               FD_SET ((SOCKET) h, xfds);
362               FD_SET ((SOCKET) h, &handle_xfds);
363             }
364
365           WSAEventSelect ((SOCKET) h, hEvent, requested);
366           nsock++;
367         }
368       else
369         {
370           handle_array[nhandles++] = h;
371
372           /* Poll now.  If we get an event, do not wait below.  */
373           if (wait_timeout != 0
374               && win32_poll_handle (h, i, &rbits, &wbits, &xbits))
375             wait_timeout = 0;
376         }
377     }
378
379   if (wait_timeout == 0 || nsock == 0)
380     rc = 0;
381   else
382     {
383       /* See if we need to wait in the loop below.  If any select is ready,
384          do MsgWaitForMultipleObjects anyway to dispatch messages, but
385          no need to call select again.  */
386       rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
387       if (rc == 0)
388         {
389           /* Restore the fd_sets for the other select we do below.  */
390           memcpy (&handle_rfds, rfds, sizeof (fd_set));
391           memcpy (&handle_wfds, wfds, sizeof (fd_set));
392           memcpy (&handle_xfds, xfds, sizeof (fd_set));
393         }
394       else
395         wait_timeout = 0;
396     }
397
398   for (;;)
399     {
400       ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
401                                        wait_timeout, QS_ALLINPUT);
402
403       if (ret == WAIT_OBJECT_0 + nhandles)
404         {
405           /* new input of some other kind */
406           BOOL bRet;
407           while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
408             {
409               TranslateMessage (&msg);
410               DispatchMessage (&msg);
411             }
412         }
413       else
414         break;
415     }
416
417   /* If we haven't done it yet, check the status of the sockets.  */
418   if (rc == 0 && nsock > 0)
419     rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
420
421   /* Now fill in the results.  */
422   FD_ZERO (rfds);
423   FD_ZERO (wfds);
424   FD_ZERO (xfds);
425
426   /* Place a sentinel at the end of the array.  */
427   handle_array[nhandles] = NULL;
428   nhandles = 1;
429   for (i = 0; i < nfds; i++)
430     {
431       if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
432         continue;
433
434       h = (HANDLE) _get_osfhandle (i);
435       if (h != handle_array[nhandles])
436         {
437           /* Perform handle->descriptor mapping.  Don't update rc, as these
438              results are counted in the return value of Winsock's select.  */
439           WSAEventSelect ((SOCKET) h, NULL, 0);
440           if (FD_ISSET (h, &handle_rfds))
441             FD_SET (i, rfds);
442           if (FD_ISSET (h, &handle_wfds))
443             FD_SET (i, wfds);
444           if (FD_ISSET (h, &handle_xfds))
445             FD_SET (i, xfds);
446         }
447       else
448         {
449           /* Not a socket.  */
450           nhandles++;
451           win32_poll_handle (h, i, &rbits, &wbits, &xbits);
452           if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
453             {
454               rc++;
455               FD_SET (i, rfds);
456             }
457           if (wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
458             {
459               rc++;
460               FD_SET (i, wfds);
461             }
462           if (xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
463             {
464               rc++;
465               FD_SET (i, xfds);
466             }
467         }
468     }
469
470   return rc;
471 }
472
473 #else /* ! Native Win32.  */
474
475 #include <sys/select.h>
476
477 #undef select
478
479 int
480 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
481             struct timeval *timeout)
482 {
483   /* Interix 3.5 has a bug: it does not support nfds == 0.  */
484   if (nfds == 0)
485     {
486       nfds = 1;
487       rfds = NULL;
488       wfds = NULL;
489       xfds = NULL;
490     }
491   return select (nfds, rfds, wfds, xfds, timeout);
492 }
493
494 #endif