changeset 11397:bbd55a939862

Rename lib/winsock-select.c to lib/select.c.
author Bruno Haible <bruno@clisp.org>
date Thu, 12 Mar 2009 11:05:28 +0100
parents 5f341b3ec7e5
children 2de4c4d41f01
files ChangeLog lib/select.c lib/winsock-select.c modules/select
diffstat 4 files changed, 432 insertions(+), 425 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2009-03-12  Bruno Haible  <bruno@clisp.org>
+
+	* lib/select.c: Renamed from lib/winsock-select.c.
+	* modules/select (Files): Add lib/select.c, remove
+	lib/winsock-select.c.
+	(configure.ac): Update.
+
 2009-03-12  Jim Meyering  <meyering@redhat.com>
 
 	avoid gcc warnings about unused macro definitions
new file mode 100644
--- /dev/null
+++ b/lib/select.c
@@ -0,0 +1,423 @@
+/* Emulation for select(2)
+   Contributed by Paolo Bonzini.
+
+   Copyright 2008 Free Software Foundation, Inc.
+
+   This file is part of gnulib.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#include <config.h>
+#include <alloca.h>
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+#include <sys/types.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <limits.h>
+
+#include <winsock2.h>
+#include <windows.h>
+#include <io.h>
+#include <stdio.h>
+#include <conio.h>
+#include <time.h>
+
+struct bitset {
+  unsigned char in[FD_SETSIZE / CHAR_BIT];
+  unsigned char out[FD_SETSIZE / CHAR_BIT];
+};
+
+/* Declare data structures for ntdll functions.  */
+typedef struct _FILE_PIPE_LOCAL_INFORMATION {
+  ULONG NamedPipeType;
+  ULONG NamedPipeConfiguration;
+  ULONG MaximumInstances;
+  ULONG CurrentInstances;
+  ULONG InboundQuota;
+  ULONG ReadDataAvailable;
+  ULONG OutboundQuota;
+  ULONG WriteQuotaAvailable;
+  ULONG NamedPipeState;
+  ULONG NamedPipeEnd;
+} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
+
+typedef struct _IO_STATUS_BLOCK
+{
+  union {
+    DWORD Status;
+    PVOID Pointer;
+  } u;
+  ULONG_PTR Information;
+} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
+
+typedef enum _FILE_INFORMATION_CLASS {
+  FilePipeLocalInformation = 24
+} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
+
+typedef DWORD (WINAPI *PNtQueryInformationFile)
+	 (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
+
+#ifndef PIPE_BUF
+#define PIPE_BUF	512
+#endif
+
+/* Compute output fd_sets for libc descriptor FD (whose Win32 handle is H).  */
+
+static int
+win32_poll_handle (HANDLE h, int fd, struct bitset *rbits, struct bitset *wbits,
+		   struct bitset *xbits)
+{
+  BOOL read, write, except;
+  int i, ret;
+  INPUT_RECORD *irbuffer;
+  DWORD avail, nbuffer;
+  BOOL bRet;
+  IO_STATUS_BLOCK iosb;
+  FILE_PIPE_LOCAL_INFORMATION fpli;
+  static PNtQueryInformationFile NtQueryInformationFile;
+  static BOOL once_only;
+
+  read = write = except = FALSE;
+  switch (GetFileType (h))
+    {
+    case FILE_TYPE_DISK:
+      read = TRUE;
+      write = TRUE;
+      break;
+
+    case FILE_TYPE_PIPE:
+      if (!once_only)
+	{
+	  NtQueryInformationFile = (PNtQueryInformationFile)
+	    GetProcAddress (GetModuleHandle ("ntdll.dll"),
+			    "NtQueryInformationFile");
+	  once_only = TRUE;
+	}
+
+      if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
+	{
+	  if (avail)
+	    read = TRUE;
+	}
+
+      else
+	{
+	  /* It was the write-end of the pipe.  Check if it is writable.
+	     If NtQueryInformationFile fails, optimistically assume the pipe is
+	     writable.  This could happen on Win9x, where NtQueryInformationFile
+	     is not available, or if we inherit a pipe that doesn't permit
+	     FILE_READ_ATTRIBUTES access on the write end (I think this should
+	     not happen since WinXP SP2; WINE seems fine too).  Otherwise,
+	     ensure that enough space is available for atomic writes.  */
+          memset (&iosb, 0, sizeof (iosb));
+          memset (&fpli, 0, sizeof (fpli));
+
+          if (!NtQueryInformationFile
+              || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
+				         FilePipeLocalInformation)
+	      || fpli.WriteQuotaAvailable >= PIPE_BUF
+	      || (fpli.OutboundQuota < PIPE_BUF &&
+	          fpli.WriteQuotaAvailable == fpli.OutboundQuota))
+	    write = TRUE;
+	}
+      break;
+
+    case FILE_TYPE_CHAR:
+      ret = WaitForSingleObject (h, 0);
+      write = TRUE;
+      if (ret == WAIT_OBJECT_0)
+        {
+	  nbuffer = avail = 0;
+	  bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
+	  if (!bRet || nbuffer == 0)
+	    except = TRUE;
+
+	  irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
+	  bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
+	  if (!bRet || avail == 0)
+	    except = TRUE;
+
+	  for (i = 0; i < avail; i++)
+	    if (irbuffer[i].EventType == KEY_EVENT)
+	      read = TRUE;
+	}
+      break;
+
+    default:
+      ret = WaitForSingleObject (h, 0);
+      write = TRUE;
+      if (ret == WAIT_OBJECT_0)
+        read = TRUE;
+
+      break;
+    }
+
+  ret = 0;
+  if (read && (rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
+    {
+      rbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
+      ret++;
+    }
+
+  if (write && (wbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
+    {
+      wbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
+      ret++;
+    }
+
+  if (except && (xbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
+    {
+      xbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
+      ret++;
+    }
+
+  return ret;
+}
+
+int
+rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
+            struct timeval *timeout)
+{
+  static struct timeval tv0;
+  static HANDLE hEvent;
+  HANDLE h, handle_array[FD_SETSIZE + 2];
+  fd_set handle_rfds, handle_wfds, handle_xfds;
+  struct bitset rbits, wbits, xbits;
+  unsigned char anyfds_in[FD_SETSIZE / CHAR_BIT];
+  DWORD ret, wait_timeout, nhandles, nsock;
+  MSG msg;
+  int i, fd, rc;
+
+  if (nfds > FD_SETSIZE)
+    nfds = FD_SETSIZE;
+
+  if (!timeout)
+    wait_timeout = INFINITE;
+  else
+    {
+      wait_timeout = timeout->tv_sec + timeout->tv_usec / 1000;
+
+      /* select is also used as a portable usleep.  */
+      if (!rfds && !wfds && !xfds)
+        {
+          Sleep (wait_timeout);
+          return 0;
+        }
+    }
+
+  if (!hEvent)
+    hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
+
+  handle_array[0] = hEvent;
+  nhandles = 1;
+  nsock = 0;
+
+  /* Copy descriptors to bitsets.  */
+  memset (&rbits, 0, sizeof (rbits));
+  memset (&wbits, 0, sizeof (wbits));
+  memset (&xbits, 0, sizeof (xbits));
+  memset (anyfds_in, 0, sizeof (anyfds_in));
+  if (rfds)
+    for (i = 0; i < rfds->fd_count; i++)
+      {
+        fd = rfds->fd_array[i];
+        rbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
+        anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
+      }
+  else
+    rfds = (fd_set *) alloca (sizeof (fd_set));
+
+  if (wfds)
+    for (i = 0; i < wfds->fd_count; i++)
+      {
+        fd = wfds->fd_array[i];
+        wbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
+        anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
+      }
+  else
+    wfds = (fd_set *) alloca (sizeof (fd_set));
+
+  if (xfds)
+    for (i = 0; i < xfds->fd_count; i++)
+      {
+        fd = xfds->fd_array[i];
+        xbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
+        anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
+      }
+  else
+    xfds = (fd_set *) alloca (sizeof (fd_set));
+
+  /* Zero all the fd_sets, including the application's.  */
+  FD_ZERO (rfds);
+  FD_ZERO (wfds);
+  FD_ZERO (xfds);
+  FD_ZERO (&handle_rfds);
+  FD_ZERO (&handle_wfds);
+  FD_ZERO (&handle_xfds);
+
+  /* Classify handles.  Create fd sets for sockets, poll the others. */
+  for (i = 0; i < nfds; i++)
+    {
+      WSANETWORKEVENTS ev;
+
+      if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
+	continue;
+
+      h = (HANDLE) _get_osfhandle (i);
+      if (!h)
+        {
+	  errno = EBADF;
+	  return -1;
+        }
+
+      /* Under Wine, it seems that getsockopt returns 0 for pipes too.
+	 WSAEnumNetworkEvents instead distinguishes the two correctly.  */
+      ev.lNetworkEvents = 0xDEADBEEF;
+      WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
+      if (ev.lNetworkEvents != 0xDEADBEEF)
+        {
+          int requested = FD_CLOSE;
+
+          /* See above; socket handles are mapped onto select, but we
+	     need to map descriptors to handles.  */
+          if (rbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
+	    {
+              requested |= FD_READ | FD_ACCEPT;
+	      FD_SET ((SOCKET) h, rfds);
+	      FD_SET ((SOCKET) h, &handle_rfds);
+	    }
+          if (wbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
+	    {
+              requested |= FD_WRITE | FD_CONNECT;
+	      FD_SET ((SOCKET) h, wfds);
+	      FD_SET ((SOCKET) h, &handle_wfds);
+	    }
+          if (xbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
+	    {
+              requested |= FD_OOB;
+	      FD_SET ((SOCKET) h, xfds);
+	      FD_SET ((SOCKET) h, &handle_xfds);
+	    }
+
+          WSAEventSelect ((SOCKET) h, hEvent, requested);
+	  nsock++;
+        }
+      else
+        {
+          handle_array[nhandles++] = h;
+
+	  /* Poll now.  If we get an event, do not wait below.  */
+          if (wait_timeout != 0
+	      && win32_poll_handle (h, i, &rbits, &wbits, &xbits))
+	    wait_timeout = 0;
+        }
+    }
+
+  if (wait_timeout == 0 || nsock == 0)
+    rc = 0;
+  else
+    {
+      /* See if we need to wait in the loop below.  If any select is ready,
+         do MsgWaitForMultipleObjects anyway to dispatch messages, but
+         no need to call select again.  */
+      rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
+      if (rc == 0)
+	{
+	  /* Restore the fd_sets for the other select we do below.  */
+          memcpy (&handle_rfds, rfds, sizeof (fd_set));
+          memcpy (&handle_wfds, wfds, sizeof (fd_set));
+          memcpy (&handle_xfds, xfds, sizeof (fd_set));
+	}
+      else
+        wait_timeout = 0;
+    }
+
+  for (;;)
+    {
+      ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
+				       wait_timeout, QS_ALLINPUT);
+
+      if (ret == WAIT_OBJECT_0 + nhandles)
+	{
+          /* new input of some other kind */
+	  BOOL bRet;
+          while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
+            {
+              TranslateMessage (&msg);
+              DispatchMessage (&msg);
+            }
+	}
+      else
+	break;
+    }
+
+  /* If we haven't done it yet, check the status of the sockets.  */
+  if (rc == 0 && nsock > 0)
+    rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
+
+  /* Now fill in the results.  */
+  FD_ZERO (rfds);
+  FD_ZERO (wfds);
+  FD_ZERO (xfds);
+
+  /* Place a sentinel at the end of the array.  */
+  handle_array[nhandles] = NULL;
+  nhandles = 1;
+  for (i = 0; i < nfds; i++)
+    {
+      if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
+	continue;
+
+      h = (HANDLE) _get_osfhandle (i);
+      if (h != handle_array[nhandles])
+	{
+	  /* Perform handle->descriptor mapping.  Don't update rc, as these
+	     results are counted in the return value of Winsock's select.  */
+          WSAEventSelect ((SOCKET) h, NULL, 0);
+          if (FD_ISSET (h, &handle_rfds))
+            FD_SET (i, rfds);
+          if (FD_ISSET (h, &handle_wfds))
+            FD_SET (i, wfds);
+          if (FD_ISSET (h, &handle_xfds))
+            FD_SET (i, xfds);
+	}
+      else
+        {
+          /* Not a socket.  */
+          nhandles++;
+          win32_poll_handle (h, i, &rbits, &wbits, &xbits);
+          if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
+            {
+	      rc++;
+	      FD_SET (i, rfds);
+	    }
+          if (wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
+            {
+	      rc++;
+	      FD_SET (i, wfds);
+	    }
+          if (xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
+            {
+	      rc++;
+	      FD_SET (i, xfds);
+	    }
+        }
+    }
+
+  return rc;
+}
+
+#endif /* Native Win32.  */
deleted file mode 100644
--- a/lib/winsock-select.c
+++ /dev/null
@@ -1,423 +0,0 @@
-/* Emulation for select(2)
-   Contributed by Paolo Bonzini.
-
-   Copyright 2008 Free Software Foundation, Inc.
-
-   This file is part of gnulib.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License along
-   with this program; if not, write to the Free Software Foundation,
-   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
-
-#include <config.h>
-#include <alloca.h>
-
-#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
-#include <sys/types.h>
-#include <stdbool.h>
-#include <errno.h>
-#include <limits.h>
-
-#include <winsock2.h>
-#include <windows.h>
-#include <io.h>
-#include <stdio.h>
-#include <conio.h>
-#include <time.h>
-
-struct bitset {
-  unsigned char in[FD_SETSIZE / CHAR_BIT];
-  unsigned char out[FD_SETSIZE / CHAR_BIT];
-};
-
-/* Declare data structures for ntdll functions.  */
-typedef struct _FILE_PIPE_LOCAL_INFORMATION {
-  ULONG NamedPipeType;
-  ULONG NamedPipeConfiguration;
-  ULONG MaximumInstances;
-  ULONG CurrentInstances;
-  ULONG InboundQuota;
-  ULONG ReadDataAvailable;
-  ULONG OutboundQuota;
-  ULONG WriteQuotaAvailable;
-  ULONG NamedPipeState;
-  ULONG NamedPipeEnd;
-} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
-
-typedef struct _IO_STATUS_BLOCK
-{
-  union {
-    DWORD Status;
-    PVOID Pointer;
-  } u;
-  ULONG_PTR Information;
-} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
-
-typedef enum _FILE_INFORMATION_CLASS {
-  FilePipeLocalInformation = 24
-} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
-
-typedef DWORD (WINAPI *PNtQueryInformationFile)
-	 (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
-
-#ifndef PIPE_BUF
-#define PIPE_BUF	512
-#endif
-
-/* Compute output fd_sets for libc descriptor FD (whose Win32 handle is H).  */
-
-static int
-win32_poll_handle (HANDLE h, int fd, struct bitset *rbits, struct bitset *wbits,
-		   struct bitset *xbits)
-{
-  BOOL read, write, except;
-  int i, ret;
-  INPUT_RECORD *irbuffer;
-  DWORD avail, nbuffer;
-  BOOL bRet;
-  IO_STATUS_BLOCK iosb;
-  FILE_PIPE_LOCAL_INFORMATION fpli;
-  static PNtQueryInformationFile NtQueryInformationFile;
-  static BOOL once_only;
-
-  read = write = except = FALSE;
-  switch (GetFileType (h))
-    {
-    case FILE_TYPE_DISK:
-      read = TRUE;
-      write = TRUE;
-      break;
-
-    case FILE_TYPE_PIPE:
-      if (!once_only)
-	{
-	  NtQueryInformationFile = (PNtQueryInformationFile)
-	    GetProcAddress (GetModuleHandle ("ntdll.dll"),
-			    "NtQueryInformationFile");
-	  once_only = TRUE;
-	}
-
-      if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
-	{
-	  if (avail)
-	    read = TRUE;
-	}
-
-      else
-	{
-	  /* It was the write-end of the pipe.  Check if it is writable.
-	     If NtQueryInformationFile fails, optimistically assume the pipe is
-	     writable.  This could happen on Win9x, where NtQueryInformationFile
-	     is not available, or if we inherit a pipe that doesn't permit
-	     FILE_READ_ATTRIBUTES access on the write end (I think this should
-	     not happen since WinXP SP2; WINE seems fine too).  Otherwise,
-	     ensure that enough space is available for atomic writes.  */
-          memset (&iosb, 0, sizeof (iosb));
-          memset (&fpli, 0, sizeof (fpli));
-
-          if (!NtQueryInformationFile
-              || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
-				         FilePipeLocalInformation)
-	      || fpli.WriteQuotaAvailable >= PIPE_BUF
-	      || (fpli.OutboundQuota < PIPE_BUF &&
-	          fpli.WriteQuotaAvailable == fpli.OutboundQuota))
-	    write = TRUE;
-	}
-      break;
-
-    case FILE_TYPE_CHAR:
-      ret = WaitForSingleObject (h, 0);
-      write = TRUE;
-      if (ret == WAIT_OBJECT_0)
-        {
-	  nbuffer = avail = 0;
-	  bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
-	  if (!bRet || nbuffer == 0)
-	    except = TRUE;
-
-	  irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
-	  bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
-	  if (!bRet || avail == 0)
-	    except = TRUE;
-
-	  for (i = 0; i < avail; i++)
-	    if (irbuffer[i].EventType == KEY_EVENT)
-	      read = TRUE;
-	}
-      break;
-
-    default:
-      ret = WaitForSingleObject (h, 0);
-      write = TRUE;
-      if (ret == WAIT_OBJECT_0)
-        read = TRUE;
-
-      break;
-    }
-
-  ret = 0;
-  if (read && (rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
-    {
-      rbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
-      ret++;
-    }
-
-  if (write && (wbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
-    {
-      wbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
-      ret++;
-    }
-
-  if (except && (xbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
-    {
-      xbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
-      ret++;
-    }
-
-  return ret;
-}
-
-int
-rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
-            struct timeval *timeout)
-{
-  static struct timeval tv0;
-  static HANDLE hEvent;
-  HANDLE h, handle_array[FD_SETSIZE + 2];
-  fd_set handle_rfds, handle_wfds, handle_xfds;
-  struct bitset rbits, wbits, xbits;
-  unsigned char anyfds_in[FD_SETSIZE / CHAR_BIT];
-  DWORD ret, wait_timeout, nhandles, nsock;
-  MSG msg;
-  int i, fd, rc;
-
-  if (nfds > FD_SETSIZE)
-    nfds = FD_SETSIZE;
-
-  if (!timeout)
-    wait_timeout = INFINITE;
-  else
-    {
-      wait_timeout = timeout->tv_sec + timeout->tv_usec / 1000;
-
-      /* select is also used as a portable usleep.  */
-      if (!rfds && !wfds && !xfds)
-        {
-          Sleep (wait_timeout);
-          return 0;
-        }
-    }
-
-  if (!hEvent)
-    hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
-
-  handle_array[0] = hEvent;
-  nhandles = 1;
-  nsock = 0;
-
-  /* Copy descriptors to bitsets.  */
-  memset (&rbits, 0, sizeof (rbits));
-  memset (&wbits, 0, sizeof (wbits));
-  memset (&xbits, 0, sizeof (xbits));
-  memset (anyfds_in, 0, sizeof (anyfds_in));
-  if (rfds)
-    for (i = 0; i < rfds->fd_count; i++)
-      {
-        fd = rfds->fd_array[i];
-        rbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
-        anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
-      }
-  else
-    rfds = (fd_set *) alloca (sizeof (fd_set));
-
-  if (wfds)
-    for (i = 0; i < wfds->fd_count; i++)
-      {
-        fd = wfds->fd_array[i];
-        wbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
-        anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
-      }
-  else
-    wfds = (fd_set *) alloca (sizeof (fd_set));
-
-  if (xfds)
-    for (i = 0; i < xfds->fd_count; i++)
-      {
-        fd = xfds->fd_array[i];
-        xbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
-        anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
-      }
-  else
-    xfds = (fd_set *) alloca (sizeof (fd_set));
-
-  /* Zero all the fd_sets, including the application's.  */
-  FD_ZERO (rfds);
-  FD_ZERO (wfds);
-  FD_ZERO (xfds);
-  FD_ZERO (&handle_rfds);
-  FD_ZERO (&handle_wfds);
-  FD_ZERO (&handle_xfds);
-
-  /* Classify handles.  Create fd sets for sockets, poll the others. */
-  for (i = 0; i < nfds; i++)
-    {
-      WSANETWORKEVENTS ev;
-
-      if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
-	continue;
-
-      h = (HANDLE) _get_osfhandle (i);
-      if (!h)
-        {
-	  errno = EBADF;
-	  return -1;
-        }
-
-      /* Under Wine, it seems that getsockopt returns 0 for pipes too.
-	 WSAEnumNetworkEvents instead distinguishes the two correctly.  */
-      ev.lNetworkEvents = 0xDEADBEEF;
-      WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
-      if (ev.lNetworkEvents != 0xDEADBEEF)
-        {
-          int requested = FD_CLOSE;
-
-          /* See above; socket handles are mapped onto select, but we
-	     need to map descriptors to handles.  */
-          if (rbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
-	    {
-              requested |= FD_READ | FD_ACCEPT;
-	      FD_SET ((SOCKET) h, rfds);
-	      FD_SET ((SOCKET) h, &handle_rfds);
-	    }
-          if (wbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
-	    {
-              requested |= FD_WRITE | FD_CONNECT;
-	      FD_SET ((SOCKET) h, wfds);
-	      FD_SET ((SOCKET) h, &handle_wfds);
-	    }
-          if (xbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
-	    {
-              requested |= FD_OOB;
-	      FD_SET ((SOCKET) h, xfds);
-	      FD_SET ((SOCKET) h, &handle_xfds);
-	    }
-
-          WSAEventSelect ((SOCKET) h, hEvent, requested);
-	  nsock++;
-        }
-      else
-        {
-          handle_array[nhandles++] = h;
-
-	  /* Poll now.  If we get an event, do not wait below.  */
-          if (wait_timeout != 0
-	      && win32_poll_handle (h, i, &rbits, &wbits, &xbits))
-	    wait_timeout = 0;
-        }
-    }
-
-  if (wait_timeout == 0 || nsock == 0)
-    rc = 0;
-  else
-    {
-      /* See if we need to wait in the loop below.  If any select is ready,
-         do MsgWaitForMultipleObjects anyway to dispatch messages, but
-         no need to call select again.  */
-      rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
-      if (rc == 0)
-	{
-	  /* Restore the fd_sets for the other select we do below.  */
-          memcpy (&handle_rfds, rfds, sizeof (fd_set));
-          memcpy (&handle_wfds, wfds, sizeof (fd_set));
-          memcpy (&handle_xfds, xfds, sizeof (fd_set));
-	}
-      else
-        wait_timeout = 0;
-    }
-
-  for (;;)
-    {
-      ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
-				       wait_timeout, QS_ALLINPUT);
-
-      if (ret == WAIT_OBJECT_0 + nhandles)
-	{
-          /* new input of some other kind */
-	  BOOL bRet;
-          while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
-            {
-              TranslateMessage (&msg);
-              DispatchMessage (&msg);
-            }
-	}
-      else
-	break;
-    }
-
-  /* If we haven't done it yet, check the status of the sockets.  */
-  if (rc == 0 && nsock > 0)
-    rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
-
-  /* Now fill in the results.  */
-  FD_ZERO (rfds);
-  FD_ZERO (wfds);
-  FD_ZERO (xfds);
-
-  /* Place a sentinel at the end of the array.  */
-  handle_array[nhandles] = NULL;
-  nhandles = 1;
-  for (i = 0; i < nfds; i++)
-    {
-      if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
-	continue;
-
-      h = (HANDLE) _get_osfhandle (i);
-      if (h != handle_array[nhandles])
-	{
-	  /* Perform handle->descriptor mapping.  Don't update rc, as these
-	     results are counted in the return value of Winsock's select.  */
-          WSAEventSelect ((SOCKET) h, NULL, 0);
-          if (FD_ISSET (h, &handle_rfds))
-            FD_SET (i, rfds);
-          if (FD_ISSET (h, &handle_wfds))
-            FD_SET (i, wfds);
-          if (FD_ISSET (h, &handle_xfds))
-            FD_SET (i, xfds);
-	}
-      else
-        {
-          /* Not a socket.  */
-          nhandles++;
-          win32_poll_handle (h, i, &rbits, &wbits, &xbits);
-          if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
-            {
-	      rc++;
-	      FD_SET (i, rfds);
-	    }
-          if (wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
-            {
-	      rc++;
-	      FD_SET (i, wfds);
-	    }
-          if (xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
-            {
-	      rc++;
-	      FD_SET (i, xfds);
-	    }
-        }
-    }
-
-  return rc;
-}
-
-#endif /* Native Win32.  */
--- a/modules/select
+++ b/modules/select
@@ -2,7 +2,7 @@
 select() function: synchronous I/O multiplexing.
 
 Files:
-lib/winsock-select.c
+lib/select.c
 
 Depends-on:
 alloca
@@ -11,7 +11,7 @@
 configure.ac:
 AC_REQUIRE([gl_HEADER_SYS_SELECT])
 if test "$ac_cv_header_winsock2_h" = yes; then
-  AC_LIBOBJ([winsock-select])
+  AC_LIBOBJ([select])
 fi
 gl_SYS_SELECT_MODULE_INDICATOR([select])