| /* Emulation for poll(2) | 
 |    Contributed by Paolo Bonzini. | 
 |  | 
 |    Copyright 2001-2003, 2006-2011 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, see <http://www.gnu.org/licenses/>.  */ | 
 |  | 
 | /* Tell gcc not to warn about the (nfd < 0) tests, below.  */ | 
 | #if (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) || 4 < __GNUC__ | 
 | # pragma GCC diagnostic ignored "-Wtype-limits" | 
 | #endif | 
 |  | 
 | #if defined(WIN32) | 
 | # include <malloc.h> | 
 | #endif | 
 |  | 
 | #include <sys/types.h> | 
 |  | 
 | /* Specification.  */ | 
 | #include <poll.h> | 
 |  | 
 | #include <errno.h> | 
 | #include <limits.h> | 
 | #include <assert.h> | 
 |  | 
 | #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ | 
 | # define WIN32_NATIVE | 
 | # if defined (_MSC_VER) && !defined(_WIN32_WINNT) | 
 | #  define _WIN32_WINNT 0x0502 | 
 | # endif | 
 | # include <winsock2.h> | 
 | # include <windows.h> | 
 | # include <io.h> | 
 | # include <stdio.h> | 
 | # include <conio.h> | 
 | #else | 
 | # include <sys/time.h> | 
 | # include <sys/socket.h> | 
 | # ifndef NO_SYS_SELECT_H | 
 | #  include <sys/select.h> | 
 | # endif | 
 | # include <unistd.h> | 
 | #endif | 
 |  | 
 | #ifdef HAVE_SYS_IOCTL_H | 
 | # include <sys/ioctl.h> | 
 | #endif | 
 | #ifdef HAVE_SYS_FILIO_H | 
 | # include <sys/filio.h> | 
 | #endif | 
 |  | 
 | #include <time.h> | 
 |  | 
 | #ifndef INFTIM | 
 | # define INFTIM (-1) | 
 | #endif | 
 |  | 
 | /* BeOS does not have MSG_PEEK.  */ | 
 | #ifndef MSG_PEEK | 
 | # define MSG_PEEK 0 | 
 | #endif | 
 |  | 
 | #ifdef WIN32_NATIVE | 
 |  | 
 | #define IsConsoleHandle(h) (((long) (intptr_t) (h) & 3) == 3) | 
 |  | 
 | static BOOL | 
 | IsSocketHandle (HANDLE h) | 
 | { | 
 |   WSANETWORKEVENTS ev; | 
 |  | 
 |   if (IsConsoleHandle (h)) | 
 |     return FALSE; | 
 |  | 
 |   /* 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); | 
 |   return ev.lNetworkEvents != 0xDEADBEEF; | 
 | } | 
 |  | 
 | /* 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 revents values for file handle H.  If some events cannot happen | 
 |    for the handle, eliminate them from *P_SOUGHT.  */ | 
 |  | 
 | static int | 
 | win32_compute_revents (HANDLE h, int *p_sought) | 
 | { | 
 |   int i, ret, happened; | 
 |   INPUT_RECORD *irbuffer; | 
 |   DWORD avail, nbuffer; | 
 |   BOOL bRet; | 
 |   IO_STATUS_BLOCK iosb; | 
 |   FILE_PIPE_LOCAL_INFORMATION fpli; | 
 |   static PNtQueryInformationFile NtQueryInformationFile; | 
 |   static BOOL once_only; | 
 |  | 
 |   switch (GetFileType (h)) | 
 |     { | 
 |     case FILE_TYPE_PIPE: | 
 |       if (!once_only) | 
 | 	{ | 
 | 	  NtQueryInformationFile = (PNtQueryInformationFile) | 
 | 	    GetProcAddress (GetModuleHandle ("ntdll.dll"), | 
 | 			    "NtQueryInformationFile"); | 
 | 	  once_only = TRUE; | 
 | 	} | 
 |  | 
 |       happened = 0; | 
 |       if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0) | 
 | 	{ | 
 | 	  if (avail) | 
 | 	    happened |= *p_sought & (POLLIN | POLLRDNORM); | 
 | 	} | 
 |       else if (GetLastError () == ERROR_BROKEN_PIPE) | 
 | 	happened |= POLLHUP; | 
 |  | 
 |       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)) | 
 | 	    happened |= *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND); | 
 | 	} | 
 |       return happened; | 
 |  | 
 |     case FILE_TYPE_CHAR: | 
 |       ret = WaitForSingleObject (h, 0); | 
 |       if (!IsConsoleHandle (h)) | 
 | 	return ret == WAIT_OBJECT_0 ? *p_sought & ~(POLLPRI | POLLRDBAND) : 0; | 
 |  | 
 |       nbuffer = avail = 0; | 
 |       bRet = GetNumberOfConsoleInputEvents (h, &nbuffer); | 
 |       if (bRet) | 
 | 	{ | 
 | 	  /* Input buffer.  */ | 
 | 	  *p_sought &= POLLIN | POLLRDNORM; | 
 | 	  if (nbuffer == 0) | 
 | 	    return POLLHUP; | 
 | 	  if (!*p_sought) | 
 | 	    return 0; | 
 |  | 
 | 	  irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD)); | 
 | 	  bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail); | 
 | 	  if (!bRet || avail == 0) | 
 | 	    return POLLHUP; | 
 |  | 
 | 	  for (i = 0; i < avail; i++) | 
 | 	    if (irbuffer[i].EventType == KEY_EVENT) | 
 | 	      return *p_sought; | 
 | 	  return 0; | 
 | 	} | 
 |       else | 
 | 	{ | 
 | 	  /* Screen buffer.  */ | 
 | 	  *p_sought &= POLLOUT | POLLWRNORM | POLLWRBAND; | 
 | 	  return *p_sought; | 
 | 	} | 
 |  | 
 |     default: | 
 |       ret = WaitForSingleObject (h, 0); | 
 |       if (ret == WAIT_OBJECT_0) | 
 | 	return *p_sought & ~(POLLPRI | POLLRDBAND); | 
 |  | 
 |       return *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND); | 
 |     } | 
 | } | 
 |  | 
 | /* Convert fd_sets returned by select into revents values.  */ | 
 |  | 
 | static int | 
 | win32_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents) | 
 | { | 
 |   int happened = 0; | 
 |  | 
 |   if ((lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) == FD_ACCEPT) | 
 |     happened |= (POLLIN | POLLRDNORM) & sought; | 
 |  | 
 |   else if (lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) | 
 |     { | 
 |       int r, error; | 
 |  | 
 |       char data[64]; | 
 |       WSASetLastError (0); | 
 |       r = recv (h, data, sizeof (data), MSG_PEEK); | 
 |       error = WSAGetLastError (); | 
 |       WSASetLastError (0); | 
 |  | 
 |       if (r > 0 || error == WSAENOTCONN) | 
 | 	happened |= (POLLIN | POLLRDNORM) & sought; | 
 |  | 
 |       /* Distinguish hung-up sockets from other errors.  */ | 
 |       else if (r == 0 || error == WSAESHUTDOWN || error == WSAECONNRESET | 
 | 	       || error == WSAECONNABORTED || error == WSAENETRESET) | 
 | 	happened |= POLLHUP; | 
 |  | 
 |       else | 
 | 	happened |= POLLERR; | 
 |     } | 
 |  | 
 |   if (lNetworkEvents & (FD_WRITE | FD_CONNECT)) | 
 |     happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought; | 
 |  | 
 |   if (lNetworkEvents & FD_OOB) | 
 |     happened |= (POLLPRI | POLLRDBAND) & sought; | 
 |  | 
 |   return happened; | 
 | } | 
 |  | 
 | #else /* !MinGW */ | 
 |  | 
 | /* Convert select(2) returned fd_sets into poll(2) revents values.  */ | 
 | static int | 
 | compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds) | 
 | { | 
 |   int happened = 0; | 
 |   if (FD_ISSET (fd, rfds)) | 
 |     { | 
 |       int r; | 
 |       int socket_errno; | 
 |  | 
 | # if defined __MACH__ && defined __APPLE__ | 
 |       /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK | 
 | 	 for some kinds of descriptors.  Detect if this descriptor is a | 
 | 	 connected socket, a server socket, or something else using a | 
 | 	 0-byte recv, and use ioctl(2) to detect POLLHUP.  */ | 
 |       r = recv (fd, NULL, 0, MSG_PEEK); | 
 |       socket_errno = (r < 0) ? errno : 0; | 
 |       if (r == 0 || socket_errno == ENOTSOCK) | 
 | 	ioctl (fd, FIONREAD, &r); | 
 | # else | 
 |       char data[64]; | 
 |       r = recv (fd, data, sizeof (data), MSG_PEEK); | 
 |       socket_errno = (r < 0) ? errno : 0; | 
 | # endif | 
 |       if (r == 0) | 
 | 	happened |= POLLHUP; | 
 |  | 
 |       /* If the event happened on an unconnected server socket, | 
 | 	 that's fine. */ | 
 |       else if (r > 0 || ( /* (r == -1) && */ socket_errno == ENOTCONN)) | 
 | 	happened |= (POLLIN | POLLRDNORM) & sought; | 
 |  | 
 |       /* Distinguish hung-up sockets from other errors.  */ | 
 |       else if (socket_errno == ESHUTDOWN || socket_errno == ECONNRESET | 
 | 	       || socket_errno == ECONNABORTED || socket_errno == ENETRESET) | 
 | 	happened |= POLLHUP; | 
 |  | 
 |       /* some systems can't use recv() on non-socket, including HP NonStop */ | 
 |       else if (/* (r == -1) && */ socket_errno == ENOTSOCK) | 
 | 	happened |= (POLLIN | POLLRDNORM) & sought; | 
 |  | 
 |       else | 
 | 	happened |= POLLERR; | 
 |     } | 
 |  | 
 |   if (FD_ISSET (fd, wfds)) | 
 |     happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought; | 
 |  | 
 |   if (FD_ISSET (fd, efds)) | 
 |     happened |= (POLLPRI | POLLRDBAND) & sought; | 
 |  | 
 |   return happened; | 
 | } | 
 | #endif /* !MinGW */ | 
 |  | 
 | int | 
 | poll (struct pollfd *pfd, nfds_t nfd, int timeout) | 
 | { | 
 | #ifndef WIN32_NATIVE | 
 |   fd_set rfds, wfds, efds; | 
 |   struct timeval tv; | 
 |   struct timeval *ptv; | 
 |   int maxfd, rc; | 
 |   nfds_t i; | 
 |  | 
 | # ifdef _SC_OPEN_MAX | 
 |   static int sc_open_max = -1; | 
 |  | 
 |   if (nfd < 0 | 
 |       || (nfd > sc_open_max | 
 | 	  && (sc_open_max != -1 | 
 | 	      || nfd > (sc_open_max = sysconf (_SC_OPEN_MAX))))) | 
 |     { | 
 |       errno = EINVAL; | 
 |       return -1; | 
 |     } | 
 | # else /* !_SC_OPEN_MAX */ | 
 | #  ifdef OPEN_MAX | 
 |   if (nfd < 0 || nfd > OPEN_MAX) | 
 |     { | 
 |       errno = EINVAL; | 
 |       return -1; | 
 |     } | 
 | #  endif /* OPEN_MAX -- else, no check is needed */ | 
 | # endif /* !_SC_OPEN_MAX */ | 
 |  | 
 |   /* EFAULT is not necessary to implement, but let's do it in the | 
 |      simplest case. */ | 
 |   if (!pfd && nfd) | 
 |     { | 
 |       errno = EFAULT; | 
 |       return -1; | 
 |     } | 
 |  | 
 |   /* convert timeout number into a timeval structure */ | 
 |   if (timeout == 0) | 
 |     { | 
 |       ptv = &tv; | 
 |       ptv->tv_sec = 0; | 
 |       ptv->tv_usec = 0; | 
 |     } | 
 |   else if (timeout > 0) | 
 |     { | 
 |       ptv = &tv; | 
 |       ptv->tv_sec = timeout / 1000; | 
 |       ptv->tv_usec = (timeout % 1000) * 1000; | 
 |     } | 
 |   else if (timeout == INFTIM) | 
 |     /* wait forever */ | 
 |     ptv = NULL; | 
 |   else | 
 |     { | 
 |       errno = EINVAL; | 
 |       return -1; | 
 |     } | 
 |  | 
 |   /* create fd sets and determine max fd */ | 
 |   maxfd = -1; | 
 |   FD_ZERO (&rfds); | 
 |   FD_ZERO (&wfds); | 
 |   FD_ZERO (&efds); | 
 |   for (i = 0; i < nfd; i++) | 
 |     { | 
 |       if (pfd[i].fd < 0) | 
 | 	continue; | 
 |  | 
 |       if (pfd[i].events & (POLLIN | POLLRDNORM)) | 
 | 	FD_SET (pfd[i].fd, &rfds); | 
 |  | 
 |       /* see select(2): "the only exceptional condition detectable | 
 | 	 is out-of-band data received on a socket", hence we push | 
 | 	 POLLWRBAND events onto wfds instead of efds. */ | 
 |       if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND)) | 
 | 	FD_SET (pfd[i].fd, &wfds); | 
 |       if (pfd[i].events & (POLLPRI | POLLRDBAND)) | 
 | 	FD_SET (pfd[i].fd, &efds); | 
 |       if (pfd[i].fd >= maxfd | 
 | 	  && (pfd[i].events & (POLLIN | POLLOUT | POLLPRI | 
 | 			       | POLLRDNORM | POLLRDBAND | 
 | 			       | POLLWRNORM | POLLWRBAND))) | 
 | 	{ | 
 | 	  maxfd = pfd[i].fd; | 
 | 	  if (maxfd > FD_SETSIZE) | 
 | 	    { | 
 | 	      errno = EOVERFLOW; | 
 | 	      return -1; | 
 | 	    } | 
 | 	} | 
 |     } | 
 |  | 
 |   /* examine fd sets */ | 
 |   rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv); | 
 |   if (rc < 0) | 
 |     return rc; | 
 |  | 
 |   /* establish results */ | 
 |   rc = 0; | 
 |   for (i = 0; i < nfd; i++) | 
 |     if (pfd[i].fd < 0) | 
 |       pfd[i].revents = 0; | 
 |     else | 
 |       { | 
 | 	int happened = compute_revents (pfd[i].fd, pfd[i].events, | 
 | 					&rfds, &wfds, &efds); | 
 | 	if (happened) | 
 | 	  { | 
 | 	    pfd[i].revents = happened; | 
 | 	    rc++; | 
 | 	  } | 
 | 	else | 
 | 	  { | 
 | 	    pfd[i].revents = 0; | 
 | 	  } | 
 |       } | 
 |  | 
 |   return rc; | 
 | #else | 
 |   static struct timeval tv0; | 
 |   static HANDLE hEvent; | 
 |   WSANETWORKEVENTS ev; | 
 |   HANDLE h, handle_array[FD_SETSIZE + 2]; | 
 |   DWORD ret, wait_timeout, nhandles, start = 0, elapsed, orig_timeout = 0; | 
 |   fd_set rfds, wfds, xfds; | 
 |   BOOL poll_again; | 
 |   MSG msg; | 
 |   int rc = 0; | 
 |   nfds_t i; | 
 |  | 
 |   if (nfd < 0 || timeout < -1) | 
 |     { | 
 |       errno = EINVAL; | 
 |       return -1; | 
 |     } | 
 |  | 
 |   if (timeout != INFTIM) | 
 |     { | 
 |       orig_timeout = timeout; | 
 |       start = GetTickCount(); | 
 |     } | 
 |  | 
 |   if (!hEvent) | 
 |     hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); | 
 |  | 
 | restart: | 
 |   handle_array[0] = hEvent; | 
 |   nhandles = 1; | 
 |   FD_ZERO (&rfds); | 
 |   FD_ZERO (&wfds); | 
 |   FD_ZERO (&xfds); | 
 |  | 
 |   /* Classify socket handles and create fd sets. */ | 
 |   for (i = 0; i < nfd; i++) | 
 |     { | 
 |       int sought = pfd[i].events; | 
 |       pfd[i].revents = 0; | 
 |       if (pfd[i].fd < 0) | 
 | 	continue; | 
 |       if (!(sought & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLWRBAND | 
 | 		      | POLLPRI | POLLRDBAND))) | 
 | 	continue; | 
 |  | 
 |       h = (HANDLE) _get_osfhandle (pfd[i].fd); | 
 |       assert (h != NULL); | 
 |       if (IsSocketHandle (h)) | 
 | 	{ | 
 | 	  int requested = FD_CLOSE; | 
 |  | 
 | 	  /* see above; socket handles are mapped onto select.  */ | 
 | 	  if (sought & (POLLIN | POLLRDNORM)) | 
 | 	    { | 
 | 	      requested |= FD_READ | FD_ACCEPT; | 
 | 	      FD_SET ((SOCKET) h, &rfds); | 
 | 	    } | 
 | 	  if (sought & (POLLOUT | POLLWRNORM | POLLWRBAND)) | 
 | 	    { | 
 | 	      requested |= FD_WRITE | FD_CONNECT; | 
 | 	      FD_SET ((SOCKET) h, &wfds); | 
 | 	    } | 
 | 	  if (sought & (POLLPRI | POLLRDBAND)) | 
 | 	    { | 
 | 	      requested |= FD_OOB; | 
 | 	      FD_SET ((SOCKET) h, &xfds); | 
 | 	    } | 
 |  | 
 | 	  if (requested) | 
 | 	    WSAEventSelect ((SOCKET) h, hEvent, requested); | 
 | 	} | 
 |       else | 
 | 	{ | 
 | 	  /* Poll now.  If we get an event, do not poll again.  Also, | 
 | 	     screen buffer handles are waitable, and they'll block until | 
 | 	     a character is available.  win32_compute_revents eliminates | 
 | 	     bits for the "wrong" direction. */ | 
 | 	  pfd[i].revents = win32_compute_revents (h, &sought); | 
 | 	  if (sought) | 
 | 	    handle_array[nhandles++] = h; | 
 | 	  if (pfd[i].revents) | 
 | 	    timeout = 0; | 
 | 	} | 
 |     } | 
 |  | 
 |   if (select (0, &rfds, &wfds, &xfds, &tv0) > 0) | 
 |     { | 
 |       /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but | 
 | 	 no need to call select again.  */ | 
 |       poll_again = FALSE; | 
 |       wait_timeout = 0; | 
 |     } | 
 |   else | 
 |     { | 
 |       poll_again = TRUE; | 
 |       if (timeout == INFTIM) | 
 | 	wait_timeout = INFINITE; | 
 |       else | 
 | 	wait_timeout = timeout; | 
 |     } | 
 |  | 
 |   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 (poll_again) | 
 |     select (0, &rfds, &wfds, &xfds, &tv0); | 
 |  | 
 |   /* Place a sentinel at the end of the array.  */ | 
 |   handle_array[nhandles] = NULL; | 
 |   nhandles = 1; | 
 |   for (i = 0; i < nfd; i++) | 
 |     { | 
 |       int happened; | 
 |  | 
 |       if (pfd[i].fd < 0) | 
 | 	continue; | 
 |       if (!(pfd[i].events & (POLLIN | POLLRDNORM | | 
 | 			     POLLOUT | POLLWRNORM | POLLWRBAND))) | 
 | 	continue; | 
 |  | 
 |       h = (HANDLE) _get_osfhandle (pfd[i].fd); | 
 |       if (h != handle_array[nhandles]) | 
 | 	{ | 
 | 	  /* It's a socket.  */ | 
 | 	  WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev); | 
 | 	  WSAEventSelect ((SOCKET) h, NULL, 0); | 
 |  | 
 | 	  /* If we're lucky, WSAEnumNetworkEvents already provided a way | 
 | 	     to distinguish FD_READ and FD_ACCEPT; this saves a recv later.  */ | 
 | 	  if (FD_ISSET ((SOCKET) h, &rfds) | 
 | 	      && !(ev.lNetworkEvents & (FD_READ | FD_ACCEPT))) | 
 | 	    ev.lNetworkEvents |= FD_READ | FD_ACCEPT; | 
 | 	  if (FD_ISSET ((SOCKET) h, &wfds)) | 
 | 	    ev.lNetworkEvents |= FD_WRITE | FD_CONNECT; | 
 | 	  if (FD_ISSET ((SOCKET) h, &xfds)) | 
 | 	    ev.lNetworkEvents |= FD_OOB; | 
 |  | 
 | 	  happened = win32_compute_revents_socket ((SOCKET) h, pfd[i].events, | 
 | 						   ev.lNetworkEvents); | 
 | 	} | 
 |       else | 
 | 	{ | 
 | 	  /* Not a socket.  */ | 
 | 	  int sought = pfd[i].events; | 
 | 	  happened = win32_compute_revents (h, &sought); | 
 | 	  nhandles++; | 
 | 	} | 
 |  | 
 |        if ((pfd[i].revents |= happened) != 0) | 
 | 	rc++; | 
 |     } | 
 |  | 
 |   if (!rc && orig_timeout && timeout != INFTIM) | 
 |     { | 
 |       elapsed = GetTickCount() - start; | 
 |       timeout = elapsed >= orig_timeout ? 0 : orig_timeout - elapsed; | 
 |     } | 
 |  | 
 |   if (!rc && timeout) | 
 |     { | 
 |       SleepEx (1, TRUE); | 
 |       goto restart; | 
 |     } | 
 |  | 
 |   return rc; | 
 | #endif | 
 | } |