1/* Emulation for poll(2)
   2   Contributed by Paolo Bonzini.
   3   Copyright 2001-2003, 2006-2011 Free Software Foundation, Inc.
   5   This file is part of gnulib.
   7   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   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   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/* Tell gcc not to warn about the (nfd < 0) tests, below.  */
  23#if (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) || 4 < __GNUC__
  24# pragma GCC diagnostic ignored "-Wtype-limits"
  25#endif
  26#include <malloc.h>
  28#include <sys/types.h>
  30/* Specification.  */
  32#include <poll.h>
  33#include <errno.h>
  35#include <limits.h>
  36#include <assert.h>
  37#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
  39# define WIN32_NATIVE
  40# if defined (_MSC_VER)
  41#  define _WIN32_WINNT 0x0502
  42# endif
  43# include <winsock2.h>
  44# include <windows.h>
  45# include <io.h>
  46# include <stdio.h>
  47# include <conio.h>
  48#else
  49# include <sys/time.h>
  50# include <sys/socket.h>
  51# include <sys/select.h>
  52# include <unistd.h>
  53#endif
  54#ifdef HAVE_SYS_IOCTL_H
  56# include <sys/ioctl.h>
  57#endif
  58#ifdef HAVE_SYS_FILIO_H
  59# include <sys/filio.h>
  60#endif
  61#include <time.h>
  63#ifndef INFTIM
  65# define INFTIM (-1)
  66#endif
  67/* BeOS does not have MSG_PEEK.  */
  69#ifndef MSG_PEEK
  70# define MSG_PEEK 0
  71#endif
  72#ifdef WIN32_NATIVE
  74#define IsConsoleHandle(h) (((long) (h) & 3) == 3)
  76static BOOL
  78IsSocketHandle (HANDLE h)
  79{
  80  WSANETWORKEVENTS ev;
  81  if (IsConsoleHandle (h))
  83    return FALSE;
  84  /* Under Wine, it seems that getsockopt returns 0 for pipes too.
  86     WSAEnumNetworkEvents instead distinguishes the two correctly.  */
  87  ev.lNetworkEvents = 0xDEADBEEF;
  88  WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
  89  return ev.lNetworkEvents != 0xDEADBEEF;
  90}
  91/* Declare data structures for ntdll functions.  */
  93typedef struct _FILE_PIPE_LOCAL_INFORMATION {
  94  ULONG NamedPipeType;
  95  ULONG NamedPipeConfiguration;
  96  ULONG MaximumInstances;
  97  ULONG CurrentInstances;
  98  ULONG InboundQuota;
  99  ULONG ReadDataAvailable;
 100  ULONG OutboundQuota;
 101  ULONG WriteQuotaAvailable;
 102  ULONG NamedPipeState;
 103  ULONG NamedPipeEnd;
 104} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
 105typedef struct _IO_STATUS_BLOCK
 107{
 108  union {
 109    DWORD Status;
 110    PVOID Pointer;
 111  } u;
 112  ULONG_PTR Information;
 113} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
 114typedef enum _FILE_INFORMATION_CLASS {
 116  FilePipeLocalInformation = 24
 117} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
 118typedef DWORD (WINAPI *PNtQueryInformationFile)
 120         (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
 121# ifndef PIPE_BUF
 123#  define PIPE_BUF      512
 124# endif
 125/* Compute revents values for file handle H.  If some events cannot happen
 127   for the handle, eliminate them from *P_SOUGHT.  */
 128static int
 130win32_compute_revents (HANDLE h, int *p_sought)
 131{
 132  int i, ret, happened;
 133  INPUT_RECORD *irbuffer;
 134  DWORD avail, nbuffer;
 135  BOOL bRet;
 136  IO_STATUS_BLOCK iosb;
 137  FILE_PIPE_LOCAL_INFORMATION fpli;
 138  static PNtQueryInformationFile NtQueryInformationFile;
 139  static BOOL once_only;
 140  switch (GetFileType (h))
 142    {
 143    case FILE_TYPE_PIPE:
 144      if (!once_only)
 145        {
 146          NtQueryInformationFile = (PNtQueryInformationFile)
 147            GetProcAddress (GetModuleHandle ("ntdll.dll"),
 148                            "NtQueryInformationFile");
 149          once_only = TRUE;
 150        }
 151      happened = 0;
 153      if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
 154        {
 155          if (avail)
 156            happened |= *p_sought & (POLLIN | POLLRDNORM);
 157        }
 158      else if (GetLastError () == ERROR_BROKEN_PIPE)
 159        happened |= POLLHUP;
 160      else
 162        {
 163          /* It was the write-end of the pipe.  Check if it is writable.
 164             If NtQueryInformationFile fails, optimistically assume the pipe is
 165             writable.  This could happen on Win9x, where NtQueryInformationFile
 166             is not available, or if we inherit a pipe that doesn't permit
 167             FILE_READ_ATTRIBUTES access on the write end (I think this should
 168             not happen since WinXP SP2; WINE seems fine too).  Otherwise,
 169             ensure that enough space is available for atomic writes.  */
 170          memset (&iosb, 0, sizeof (iosb));
 171          memset (&fpli, 0, sizeof (fpli));
 172          if (!NtQueryInformationFile
 174              || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
 175                                         FilePipeLocalInformation)
 176              || fpli.WriteQuotaAvailable >= PIPE_BUF
 177              || (fpli.OutboundQuota < PIPE_BUF &&
 178                  fpli.WriteQuotaAvailable == fpli.OutboundQuota))
 179            happened |= *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
 180        }
 181      return happened;
 182    case FILE_TYPE_CHAR:
 184      ret = WaitForSingleObject (h, 0);
 185      if (!IsConsoleHandle (h))
 186        return ret == WAIT_OBJECT_0 ? *p_sought & ~(POLLPRI | POLLRDBAND) : 0;
 187      nbuffer = avail = 0;
 189      bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
 190      if (bRet)
 191        {
 192          /* Input buffer.  */
 193          *p_sought &= POLLIN | POLLRDNORM;
 194          if (nbuffer == 0)
 195            return POLLHUP;
 196          if (!*p_sought)
 197            return 0;
 198          irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
 200          bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
 201          if (!bRet || avail == 0)
 202            return POLLHUP;
 203          for (i = 0; i < avail; i++)
 205            if (irbuffer[i].EventType == KEY_EVENT)
 206              return *p_sought;
 207          return 0;
 208        }
 209      else
 210        {
 211          /* Screen buffer.  */
 212          *p_sought &= POLLOUT | POLLWRNORM | POLLWRBAND;
 213          return *p_sought;
 214        }
 215    default:
 217      ret = WaitForSingleObject (h, 0);
 218      if (ret == WAIT_OBJECT_0)
 219        return *p_sought & ~(POLLPRI | POLLRDBAND);
 220      return *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
 222    }
 223}
 224/* Convert fd_sets returned by select into revents values.  */
 226static int
 228win32_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents)
 229{
 230  int happened = 0;
 231  if ((lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) == FD_ACCEPT)
 233    happened |= (POLLIN | POLLRDNORM) & sought;
 234  else if (lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
 236    {
 237      int r, error;
 238      char data[64];
 240      WSASetLastError (0);
 241      r = recv (h, data, sizeof (data), MSG_PEEK);
 242      error = WSAGetLastError ();
 243      WSASetLastError (0);
 244      if (r > 0 || error == WSAENOTCONN)
 246        happened |= (POLLIN | POLLRDNORM) & sought;
 247      /* Distinguish hung-up sockets from other errors.  */
 249      else if (r == 0 || error == WSAESHUTDOWN || error == WSAECONNRESET
 250               || error == WSAECONNABORTED || error == WSAENETRESET)
 251        happened |= POLLHUP;
 252      else
 254        happened |= POLLERR;
 255    }
 256  if (lNetworkEvents & (FD_WRITE | FD_CONNECT))
 258    happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
 259  if (lNetworkEvents & FD_OOB)
 261    happened |= (POLLPRI | POLLRDBAND) & sought;
 262  return happened;
 264}
 265#else /* !MinGW */
 267/* Convert select(2) returned fd_sets into poll(2) revents values.  */
 269static int
 270compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds)
 271{
 272  int happened = 0;
 273  if (FD_ISSET (fd, rfds))
 274    {
 275      int r;
 276      int socket_errno;
 277# if defined __MACH__ && defined __APPLE__
 279      /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
 280         for some kinds of descriptors.  Detect if this descriptor is a
 281         connected socket, a server socket, or something else using a
 282         0-byte recv, and use ioctl(2) to detect POLLHUP.  */
 283      r = recv (fd, NULL, 0, MSG_PEEK);
 284      socket_errno = (r < 0) ? errno : 0;
 285      if (r == 0 || socket_errno == ENOTSOCK)
 286        ioctl (fd, FIONREAD, &r);
 287# else
 288      char data[64];
 289      r = recv (fd, data, sizeof (data), MSG_PEEK);
 290      socket_errno = (r < 0) ? errno : 0;
 291# endif
 292      if (r == 0)
 293        happened |= POLLHUP;
 294      /* If the event happened on an unconnected server socket,
 296         that's fine. */
 297      else if (r > 0 || ( /* (r == -1) && */ socket_errno == ENOTCONN))
 298        happened |= (POLLIN | POLLRDNORM) & sought;
 299      /* Distinguish hung-up sockets from other errors.  */
 301      else if (socket_errno == ESHUTDOWN || socket_errno == ECONNRESET
 302               || socket_errno == ECONNABORTED || socket_errno == ENETRESET)
 303        happened |= POLLHUP;
 304      else
 306        happened |= POLLERR;
 307    }
 308  if (FD_ISSET (fd, wfds))
 310    happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
 311  if (FD_ISSET (fd, efds))
 313    happened |= (POLLPRI | POLLRDBAND) & sought;
 314  return happened;
 316}
 317#endif /* !MinGW */
 318int
 320poll (struct pollfd *pfd, nfds_t nfd, int timeout)
 321{
 322#ifndef WIN32_NATIVE
 323  fd_set rfds, wfds, efds;
 324  struct timeval tv;
 325  struct timeval *ptv;
 326  int maxfd, rc;
 327  nfds_t i;
 328# ifdef _SC_OPEN_MAX
 330  static int sc_open_max = -1;
 331  if (nfd < 0
 333      || (nfd > sc_open_max
 334          && (sc_open_max != -1
 335              || nfd > (sc_open_max = sysconf (_SC_OPEN_MAX)))))
 336    {
 337      errno = EINVAL;
 338      return -1;
 339    }
 340# else /* !_SC_OPEN_MAX */
 341#  ifdef OPEN_MAX
 342  if (nfd < 0 || nfd > OPEN_MAX)
 343    {
 344      errno = EINVAL;
 345      return -1;
 346    }
 347#  endif /* OPEN_MAX -- else, no check is needed */
 348# endif /* !_SC_OPEN_MAX */
 349  /* EFAULT is not necessary to implement, but let's do it in the
 351     simplest case. */
 352  if (!pfd)
 353    {
 354      errno = EFAULT;
 355      return -1;
 356    }
 357  /* convert timeout number into a timeval structure */
 359  if (timeout == 0)
 360    {
 361      ptv = &tv;
 362      ptv->tv_sec = 0;
 363      ptv->tv_usec = 0;
 364    }
 365  else if (timeout > 0)
 366    {
 367      ptv = &tv;
 368      ptv->tv_sec = timeout / 1000;
 369      ptv->tv_usec = (timeout % 1000) * 1000;
 370    }
 371  else if (timeout == INFTIM)
 372    /* wait forever */
 373    ptv = NULL;
 374  else
 375    {
 376      errno = EINVAL;
 377      return -1;
 378    }
 379  /* create fd sets and determine max fd */
 381  maxfd = -1;
 382  FD_ZERO (&rfds);
 383  FD_ZERO (&wfds);
 384  FD_ZERO (&efds);
 385  for (i = 0; i < nfd; i++)
 386    {
 387      if (pfd[i].fd < 0)
 388        continue;
 389      if (pfd[i].events & (POLLIN | POLLRDNORM))
 391        FD_SET (pfd[i].fd, &rfds);
 392      /* see select(2): "the only exceptional condition detectable
 394         is out-of-band data received on a socket", hence we push
 395         POLLWRBAND events onto wfds instead of efds. */
 396      if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND))
 397        FD_SET (pfd[i].fd, &wfds);
 398      if (pfd[i].events & (POLLPRI | POLLRDBAND))
 399        FD_SET (pfd[i].fd, &efds);
 400      if (pfd[i].fd >= maxfd
 401          && (pfd[i].events & (POLLIN | POLLOUT | POLLPRI
 402                               | POLLRDNORM | POLLRDBAND
 403                               | POLLWRNORM | POLLWRBAND)))
 404        {
 405          maxfd = pfd[i].fd;
 406          if (maxfd > FD_SETSIZE)
 407            {
 408              errno = EOVERFLOW;
 409              return -1;
 410            }
 411        }
 412    }
 413  /* examine fd sets */
 415  rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv);
 416  if (rc < 0)
 417    return rc;
 418  /* establish results */
 420  rc = 0;
 421  for (i = 0; i < nfd; i++)
 422    if (pfd[i].fd < 0)
 423      pfd[i].revents = 0;
 424    else
 425      {
 426        int happened = compute_revents (pfd[i].fd, pfd[i].events,
 427                                        &rfds, &wfds, &efds);
 428        if (happened)
 429          {
 430            pfd[i].revents = happened;
 431            rc++;
 432          }
 433      }
 434  return rc;
 436#else
 437  static struct timeval tv0;
 438  static HANDLE hEvent;
 439  WSANETWORKEVENTS ev;
 440  HANDLE h, handle_array[FD_SETSIZE + 2];
 441  DWORD ret, wait_timeout, nhandles;
 442  fd_set rfds, wfds, xfds;
 443  BOOL poll_again;
 444  MSG msg;
 445  int rc = 0;
 446  nfds_t i;
 447  if (nfd < 0 || timeout < -1)
 449    {
 450      errno = EINVAL;
 451      return -1;
 452    }
 453  if (!hEvent)
 455    hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
 456restart:
 458  handle_array[0] = hEvent;
 459  nhandles = 1;
 460  FD_ZERO (&rfds);
 461  FD_ZERO (&wfds);
 462  FD_ZERO (&xfds);
 463  /* Classify socket handles and create fd sets. */
 465  for (i = 0; i < nfd; i++)
 466    {
 467      int sought = pfd[i].events;
 468      pfd[i].revents = 0;
 469      if (pfd[i].fd < 0)
 470        continue;
 471      if (!(sought & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLWRBAND
 472                      | POLLPRI | POLLRDBAND)))
 473        continue;
 474      h = (HANDLE) _get_osfhandle (pfd[i].fd);
 476      assert (h != NULL);
 477      if (IsSocketHandle (h))
 478        {
 479          int requested = FD_CLOSE;
 480          /* see above; socket handles are mapped onto select.  */
 482          if (sought & (POLLIN | POLLRDNORM))
 483            {
 484              requested |= FD_READ | FD_ACCEPT;
 485              FD_SET ((SOCKET) h, &rfds);
 486            }
 487          if (sought & (POLLOUT | POLLWRNORM | POLLWRBAND))
 488            {
 489              requested |= FD_WRITE | FD_CONNECT;
 490              FD_SET ((SOCKET) h, &wfds);
 491            }
 492          if (sought & (POLLPRI | POLLRDBAND))
 493            {
 494              requested |= FD_OOB;
 495              FD_SET ((SOCKET) h, &xfds);
 496            }
 497          if (requested)
 499            WSAEventSelect ((SOCKET) h, hEvent, requested);
 500        }
 501      else
 502        {
 503          /* Poll now.  If we get an event, do not poll again.  Also,
 504             screen buffer handles are waitable, and they'll block until
 505             a character is available.  win32_compute_revents eliminates
 506             bits for the "wrong" direction. */
 507          pfd[i].revents = win32_compute_revents (h, &sought);
 508          if (sought)
 509            handle_array[nhandles++] = h;
 510          if (pfd[i].revents)
 511            timeout = 0;
 512        }
 513    }
 514  if (select (0, &rfds, &wfds, &xfds, &tv0) > 0)
 516    {
 517      /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
 518         no need to call select again.  */
 519      poll_again = FALSE;
 520      wait_timeout = 0;
 521    }
 522  else
 523    {
 524      poll_again = TRUE;
 525      if (timeout == INFTIM)
 526        wait_timeout = INFINITE;
 527      else
 528        wait_timeout = timeout;
 529    }
 530  for (;;)
 532    {
 533      ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
 534                                       wait_timeout, QS_ALLINPUT);
 535      if (ret == WAIT_OBJECT_0 + nhandles)
 537        {
 538          /* new input of some other kind */
 539          BOOL bRet;
 540          while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
 541            {
 542              TranslateMessage (&msg);
 543              DispatchMessage (&msg);
 544            }
 545        }
 546      else
 547        break;
 548    }
 549  if (poll_again)
 551    select (0, &rfds, &wfds, &xfds, &tv0);
 552  /* Place a sentinel at the end of the array.  */
 554  handle_array[nhandles] = NULL;
 555  nhandles = 1;
 556  for (i = 0; i < nfd; i++)
 557    {
 558      int happened;
 559      if (pfd[i].fd < 0)
 561        continue;
 562      if (!(pfd[i].events & (POLLIN | POLLRDNORM |
 563                             POLLOUT | POLLWRNORM | POLLWRBAND)))
 564        continue;
 565      h = (HANDLE) _get_osfhandle (pfd[i].fd);
 567      if (h != handle_array[nhandles])
 568        {
 569          /* It's a socket.  */
 570          WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
 571          WSAEventSelect ((SOCKET) h, 0, 0);
 572          /* If we're lucky, WSAEnumNetworkEvents already provided a way
 574             to distinguish FD_READ and FD_ACCEPT; this saves a recv later.  */
 575          if (FD_ISSET ((SOCKET) h, &rfds)
 576              && !(ev.lNetworkEvents & (FD_READ | FD_ACCEPT)))
 577            ev.lNetworkEvents |= FD_READ | FD_ACCEPT;
 578          if (FD_ISSET ((SOCKET) h, &wfds))
 579            ev.lNetworkEvents |= FD_WRITE | FD_CONNECT;
 580          if (FD_ISSET ((SOCKET) h, &xfds))
 581            ev.lNetworkEvents |= FD_OOB;
 582          happened = win32_compute_revents_socket ((SOCKET) h, pfd[i].events,
 584                                                   ev.lNetworkEvents);
 585        }
 586      else
 587        {
 588          /* Not a socket.  */
 589          int sought = pfd[i].events;
 590          happened = win32_compute_revents (h, &sought);
 591          nhandles++;
 592        }
 593       if ((pfd[i].revents |= happened) != 0)
 595        rc++;
 596    }
 597  if (!rc && timeout == INFTIM)
 599    {
 600      SwitchToThread();
 601      goto restart;
 602    }
 603  return rc;
 605#endif
 606}