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