select.c: indent with spaces, not TABs
[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 Windows.  */
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 Windows handle is
101    H).  */
102
103 static int
104 windows_poll_handle (HANDLE h, int fd,
105                      struct bitset *rbits,
106                      struct bitset *wbits,
107                      struct bitset *xbits)
108 {
109   BOOL read, write, except;
110   int i, ret;
111   INPUT_RECORD *irbuffer;
112   DWORD avail, nbuffer;
113   BOOL bRet;
114   IO_STATUS_BLOCK iosb;
115   FILE_PIPE_LOCAL_INFORMATION fpli;
116   static PNtQueryInformationFile NtQueryInformationFile;
117   static BOOL once_only;
118
119   read = write = except = FALSE;
120   switch (GetFileType (h))
121     {
122     case FILE_TYPE_DISK:
123       read = TRUE;
124       write = TRUE;
125       break;
126
127     case FILE_TYPE_PIPE:
128       if (!once_only)
129         {
130           NtQueryInformationFile = (PNtQueryInformationFile)
131             GetProcAddress (GetModuleHandle ("ntdll.dll"),
132                             "NtQueryInformationFile");
133           once_only = TRUE;
134         }
135
136       if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
137         {
138           if (avail)
139             read = TRUE;
140         }
141       else if (GetLastError () == ERROR_BROKEN_PIPE)
142         ;
143
144       else
145         {
146           /* It was the write-end of the pipe.  Check if it is writable.
147              If NtQueryInformationFile fails, optimistically assume the pipe is
148              writable.  This could happen on Windows 9x, where
149              NtQueryInformationFile is not available, or if we inherit a pipe
150              that doesn't permit FILE_READ_ATTRIBUTES access on the write end
151              (I think this should not happen since Windows XP SP2; WINE seems
152              fine too).  Otherwise, ensure that enough space is available for
153              atomic writes.  */
154           memset (&iosb, 0, sizeof (iosb));
155           memset (&fpli, 0, sizeof (fpli));
156
157           if (!NtQueryInformationFile
158               || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
159                                          FilePipeLocalInformation)
160               || fpli.WriteQuotaAvailable >= PIPE_BUF
161               || (fpli.OutboundQuota < PIPE_BUF &&
162                   fpli.WriteQuotaAvailable == fpli.OutboundQuota))
163             write = TRUE;
164         }
165       break;
166
167     case FILE_TYPE_CHAR:
168       write = TRUE;
169       if (!(rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
170         break;
171
172       ret = WaitForSingleObject (h, 0);
173       if (ret == WAIT_OBJECT_0)
174         {
175           if (!IsConsoleHandle (h))
176             {
177               read = TRUE;
178               break;
179             }
180
181           nbuffer = avail = 0;
182           bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
183
184           /* Screen buffers handles are filtered earlier.  */
185           assert (bRet);
186           if (nbuffer == 0)
187             {
188               except = TRUE;
189               break;
190             }
191
192           irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
193           bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
194           if (!bRet || avail == 0)
195             {
196               except = TRUE;
197               break;
198             }
199
200           for (i = 0; i < avail; i++)
201             if (irbuffer[i].EventType == KEY_EVENT)
202               read = TRUE;
203         }
204       break;
205
206     default:
207       ret = WaitForSingleObject (h, 0);
208       write = TRUE;
209       if (ret == WAIT_OBJECT_0)
210         read = TRUE;
211
212       break;
213     }
214
215   ret = 0;
216   if (read && (rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
217     {
218       rbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
219       ret++;
220     }
221
222   if (write && (wbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
223     {
224       wbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
225       ret++;
226     }
227
228   if (except && (xbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
229     {
230       xbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
231       ret++;
232     }
233
234   return ret;
235 }
236
237 int
238 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
239             struct timeval *timeout)
240 {
241   static struct timeval tv0;
242   static HANDLE hEvent;
243   HANDLE h, handle_array[FD_SETSIZE + 2];
244   fd_set handle_rfds, handle_wfds, handle_xfds;
245   struct bitset rbits, wbits, xbits;
246   unsigned char anyfds_in[FD_SETSIZE / CHAR_BIT];
247   DWORD ret, wait_timeout, nhandles, nsock, nbuffer;
248   MSG msg;
249   int i, fd, rc;
250
251   if (nfds > FD_SETSIZE)
252     nfds = FD_SETSIZE;
253
254   if (!timeout)
255     wait_timeout = INFINITE;
256   else
257     {
258       wait_timeout = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
259
260       /* select is also used as a portable usleep.  */
261       if (!rfds && !wfds && !xfds)
262         {
263           Sleep (wait_timeout);
264           return 0;
265         }
266     }
267
268   if (!hEvent)
269     hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
270
271   handle_array[0] = hEvent;
272   nhandles = 1;
273   nsock = 0;
274
275   /* Copy descriptors to bitsets.  At the same time, eliminate
276      bits in the "wrong" direction for console input buffers
277      and screen buffers, because screen buffers are waitable
278      and they will block until a character is available.  */
279   memset (&rbits, 0, sizeof (rbits));
280   memset (&wbits, 0, sizeof (wbits));
281   memset (&xbits, 0, sizeof (xbits));
282   memset (anyfds_in, 0, sizeof (anyfds_in));
283   if (rfds)
284     for (i = 0; i < rfds->fd_count; i++)
285       {
286         fd = rfds->fd_array[i];
287         h = (HANDLE) _get_osfhandle (fd);
288         if (IsConsoleHandle (h)
289             && !GetNumberOfConsoleInputEvents (h, &nbuffer))
290           continue;
291
292         rbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
293         anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
294       }
295   else
296     rfds = (fd_set *) alloca (sizeof (fd_set));
297
298   if (wfds)
299     for (i = 0; i < wfds->fd_count; i++)
300       {
301         fd = wfds->fd_array[i];
302         h = (HANDLE) _get_osfhandle (fd);
303         if (IsConsoleHandle (h)
304             && GetNumberOfConsoleInputEvents (h, &nbuffer))
305           continue;
306
307         wbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
308         anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
309       }
310   else
311     wfds = (fd_set *) alloca (sizeof (fd_set));
312
313   if (xfds)
314     for (i = 0; i < xfds->fd_count; i++)
315       {
316         fd = xfds->fd_array[i];
317         xbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
318         anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
319       }
320   else
321     xfds = (fd_set *) alloca (sizeof (fd_set));
322
323   /* Zero all the fd_sets, including the application's.  */
324   FD_ZERO (rfds);
325   FD_ZERO (wfds);
326   FD_ZERO (xfds);
327   FD_ZERO (&handle_rfds);
328   FD_ZERO (&handle_wfds);
329   FD_ZERO (&handle_xfds);
330
331   /* Classify handles.  Create fd sets for sockets, poll the others. */
332   for (i = 0; i < nfds; i++)
333     {
334       if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
335         continue;
336
337       h = (HANDLE) _get_osfhandle (i);
338       if (!h)
339         {
340           errno = EBADF;
341           return -1;
342         }
343
344       if (IsSocketHandle (h))
345         {
346           int requested = FD_CLOSE;
347
348           /* See above; socket handles are mapped onto select, but we
349              need to map descriptors to handles.  */
350           if (rbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
351             {
352               requested |= FD_READ | FD_ACCEPT;
353               FD_SET ((SOCKET) h, rfds);
354               FD_SET ((SOCKET) h, &handle_rfds);
355             }
356           if (wbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
357             {
358               requested |= FD_WRITE | FD_CONNECT;
359               FD_SET ((SOCKET) h, wfds);
360               FD_SET ((SOCKET) h, &handle_wfds);
361             }
362           if (xbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
363             {
364               requested |= FD_OOB;
365               FD_SET ((SOCKET) h, xfds);
366               FD_SET ((SOCKET) h, &handle_xfds);
367             }
368
369           WSAEventSelect ((SOCKET) h, hEvent, requested);
370           nsock++;
371         }
372       else
373         {
374           handle_array[nhandles++] = h;
375
376           /* Poll now.  If we get an event, do not wait below.  */
377           if (wait_timeout != 0
378               && windows_poll_handle (h, i, &rbits, &wbits, &xbits))
379             wait_timeout = 0;
380         }
381     }
382
383   if (wait_timeout == 0 || nsock == 0)
384     rc = 0;
385   else
386     {
387       /* See if we need to wait in the loop below.  If any select is ready,
388          do MsgWaitForMultipleObjects anyway to dispatch messages, but
389          no need to call select again.  */
390       rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
391       if (rc == 0)
392         {
393           /* Restore the fd_sets for the other select we do below.  */
394           memcpy (&handle_rfds, rfds, sizeof (fd_set));
395           memcpy (&handle_wfds, wfds, sizeof (fd_set));
396           memcpy (&handle_xfds, xfds, sizeof (fd_set));
397         }
398       else
399         wait_timeout = 0;
400     }
401
402   for (;;)
403     {
404       ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
405                                        wait_timeout, QS_ALLINPUT);
406
407       if (ret == WAIT_OBJECT_0 + nhandles)
408         {
409           /* new input of some other kind */
410           BOOL bRet;
411           while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
412             {
413               TranslateMessage (&msg);
414               DispatchMessage (&msg);
415             }
416         }
417       else
418         break;
419     }
420
421   /* If we haven't done it yet, check the status of the sockets.  */
422   if (rc == 0 && nsock > 0)
423     rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
424
425   /* Now fill in the results.  */
426   FD_ZERO (rfds);
427   FD_ZERO (wfds);
428   FD_ZERO (xfds);
429
430   /* Place a sentinel at the end of the array.  */
431   handle_array[nhandles] = NULL;
432   nhandles = 1;
433   for (i = 0; i < nfds; i++)
434     {
435       if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
436         continue;
437
438       h = (HANDLE) _get_osfhandle (i);
439       if (h != handle_array[nhandles])
440         {
441           /* Perform handle->descriptor mapping.  Don't update rc, as these
442              results are counted in the return value of Winsock's select.  */
443           WSAEventSelect ((SOCKET) h, NULL, 0);
444           if (FD_ISSET (h, &handle_rfds))
445             FD_SET (i, rfds);
446           if (FD_ISSET (h, &handle_wfds))
447             FD_SET (i, wfds);
448           if (FD_ISSET (h, &handle_xfds))
449             FD_SET (i, xfds);
450         }
451       else
452         {
453           /* Not a socket.  */
454           nhandles++;
455           windows_poll_handle (h, i, &rbits, &wbits, &xbits);
456           if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
457             {
458               rc++;
459               FD_SET (i, rfds);
460             }
461           if (wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
462             {
463               rc++;
464               FD_SET (i, wfds);
465             }
466           if (xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
467             {
468               rc++;
469               FD_SET (i, xfds);
470             }
471         }
472     }
473
474   return rc;
475 }
476
477 #else /* ! Native Windows.  */
478
479 #include <sys/select.h>
480
481 #undef select
482
483 int
484 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
485             struct timeval *timeout)
486 {
487   /* Interix 3.5 has a bug: it does not support nfds == 0.  */
488   if (nfds == 0)
489     {
490       nfds = 1;
491       rfds = NULL;
492       wfds = NULL;
493       xfds = NULL;
494     }
495   return select (nfds, rfds, wfds, xfds, timeout);
496 }
497
498 #endif