New module poll, from Paolo Bonzini <bonzini@gnu.org>.
authorBruno Haible <bruno@clisp.org>
Thu, 20 Feb 2003 13:10:05 +0000 (13:10 +0000)
committerBruno Haible <bruno@clisp.org>
Thu, 20 Feb 2003 13:10:05 +0000 (13:10 +0000)
ChangeLog
MODULES.html.sh
lib/ChangeLog
lib/poll.c [new file with mode: 0644]
lib/poll_.h [new file with mode: 0644]
m4/ChangeLog
m4/poll.m4 [new file with mode: 0644]
modules/poll [new file with mode: 0644]

index ab546e7e3204fd15298bc2bfcfce30d641872597..45120a1573a8032819552f73acca732c2f905a76 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2003-02-20  Bruno Haible  <bruno@clisp.org>
+
+       * MODULES.html.sh (func_all_modules): Add poll.
+
+2003-02-19  Paolo Bonzino  <bonzini@gnu.org>
+
+       * modules/poll: New file.
+
 2003-02-18  Bruno Haible  <bruno@clisp.org>
 
        * MODULES.html.sh (func_all_modules): Add mathl.
index 97206be7936e63431333713e2c340966db07f641..384bbbea40cb518516ae8a1f9e0be06ef645acb5 100755 (executable)
@@ -1670,6 +1670,7 @@ func_all_modules ()
   func_module mkdir
   func_module mkstemp
   func_module mkdtemp
+  func_module poll
   func_module stat
   func_module lstat
   func_module timespec
index 553a8a17186489c5ec1b70dbecb1a057c89f38d3..f454c4a6a611dfc844d882e61a730f0cde5a2aee 100644 (file)
@@ -1,3 +1,8 @@
+2003-02-19  Paolo Bonzino  <bonzini@gnu.org>
+
+       * poll_.h: New file.
+       * poll.c: New file.
+
 2003-02-18  Paolo Bonzino  <bonzini@gnu.org>
 
        * mathl.h: New file.
diff --git a/lib/poll.c b/lib/poll.c
new file mode 100644 (file)
index 0000000..3be55dd
--- /dev/null
@@ -0,0 +1,182 @@
+/* Emulation for poll(2)
+   Contributed by Paolo Bonzini.
+
+   Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
+
+   This file is part of gnulib.
+
+   gnulib is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Lesser General Public License as published
+   by the Free Software Foundation; either version 2.1, or (at your option)
+   any later version.
+
+   gnulib 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 Lesser General Public
+   License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with gnulib; see the file COPYING.LIB.  If not, write to the Free
+   Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include "poll.h"
+#include <errno.h>
+#include <limits.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <unistd.h>
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+
+#ifndef INFTIM
+#define INFTIM (-1)
+#endif
+
+#ifndef EOVERFLOW
+#define EOVERFLOW EINVAL
+#endif
+
+int
+poll (pfd, nfd, timeout)
+     struct pollfd *pfd;
+     nfds_t nfd;
+     int timeout;
+{
+  fd_set rfds, wfds, efds;
+  struct timeval tv, *ptv;
+  int maxfd, rc, happened;
+  nfds_t i;
+  char data[64];
+
+#ifdef _SC_OPEN_MAX
+  if (nfd > sysconf (_SC_OPEN_MAX))
+    {
+      errno = EINVAL;
+      return -1;
+    }
+#else /* !_SC_OPEN_MAX */
+#ifdef OPEN_MAX
+  if (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)
+    {
+      errno = EFAULT;
+      return -1;
+    }
+
+  /* convert timeout number into a timeval structure */
+  ptv = &tv;
+  if (timeout >= 0)
+    {
+      /* return immediately or after timeout */
+      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);
+
+  /* establish results */
+  if (rc > 0)
+    {
+      rc = 0;
+      for (i = 0; i < nfd; i++)
+       {
+         pfd[i].revents = 0;
+         if (pfd[i].fd < 0)
+           continue;
+
+         happened = 0;
+         if (FD_ISSET (pfd[i].fd, &rfds))
+           {
+             /* support for POLLHUP.  An hung up descriptor does not
+                increase the return value! */
+             if (recv (pfd[i].fd, data, 64, MSG_PEEK) == -1)
+               {
+                 if (errno == ESHUTDOWN || errno == ECONNRESET
+                     || errno == ECONNABORTED || errno == ENETRESET)
+                   pfd[i].revents |= POLLHUP;
+               }
+             else
+               happened |= POLLIN | POLLRDNORM;
+           }
+
+         if (FD_ISSET (pfd[i].fd, &wfds))
+           happened |= POLLOUT | POLLWRNORM | POLLWRBAND;
+
+         if (FD_ISSET (pfd[i].fd, &efds))
+           happened |= POLLPRI | POLLRDBAND;
+
+         pfd[i].revents |= pfd[i].events & happened;
+         rc += (happened > 0);
+       }
+    }
+
+  return rc;
+}
diff --git a/lib/poll_.h b/lib/poll_.h
new file mode 100644 (file)
index 0000000..9c68e41
--- /dev/null
@@ -0,0 +1,55 @@
+/* Header for poll(2) emulation
+   Contributed by Paolo Bonzini.
+
+   Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
+
+   This file is part of gnulib.
+
+   gnulib is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Lesser General Public License as published
+   by the Free Software Foundation; either version 2.1, or (at your option)
+   any later version.
+
+   gnulib 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 Lesser General Public
+   License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with gnulib; see the file COPYING.LIB.  If not, write to the Free
+   Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  
+ */
+
+#ifndef GNULIB_POLL_H
+#define GNULIB_POLL_H
+
+/* fake a poll(2) environment */
+#define POLLIN      0x0001     /* any readable data available   */
+#define POLLPRI     0x0002     /* OOB/Urgent readable data      */
+#define POLLOUT     0x0004     /* file descriptor is writeable  */
+#define POLLERR     0x0008     /* some poll error occurred      */
+#define POLLHUP     0x0010     /* file descriptor was "hung up" */
+#define POLLNVAL    0x0020     /* requested events "invalid"    */
+#define POLLRDNORM  0x0040
+#define POLLRDBAND  0x0080
+#define POLLWRNORM  0x0100
+#define POLLWRBAND  0x0200
+
+struct pollfd
+{
+  int fd;                      /* which file descriptor to poll */
+  short events;                        /* events we are interested in   */
+  short revents;               /* events found on return        */
+};
+
+typedef unsigned long nfds_t;
+
+extern int poll (struct pollfd *pfd, nfds_t nfd, int timeout);
+
+/* Define INFTIM only if doing so conforms to POSIX.  */
+#if !defined (_POSIX_C_SOURCE) && !defined (_XOPEN_SOURCE)
+#define INFTIM (-1)
+#endif
+
+#endif
index 3c9361706908187f6edc3582435d4cc7f119e8f8..de1b0266d2491c50822398684d5f835f749f4e60 100644 (file)
@@ -1,3 +1,7 @@
+2003-02-19  Paolo Bonzino  <bonzini@gnu.org>
+
+       * poll.m4: New file.
+
 2003-02-18  Paolo Bonzino  <bonzini@gnu.org>
 
        * mathl.m4: New file.
diff --git a/m4/poll.m4 b/m4/poll.m4
new file mode 100644 (file)
index 0000000..a23f504
--- /dev/null
@@ -0,0 +1,27 @@
+# poll.m4 serial 1
+dnl Copyright (c) 2003 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License.  As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of the program.
+
+AC_DEFUN([gl_FUNC_POLL],
+[
+  AC_CHECK_HEADERS(poll.h)
+  if test x$ac_cv_header_poll_h = xno; then
+    AC_CONFIG_LINKS([lib/poll.h:lib/poll_.h])
+  fi
+
+  AC_REPLACE_FUNCS(poll)
+  if test $ac_cv_func_poll = no; then
+    gl_PREREQ_POLL
+  fi
+])
+
+# Prerequisites of lib/poll.c.
+AC_DEFUN([gl_PREREQ_POLL],
+[
+  AC_REQUIRE([AC_HEADER_TIME])
+  AC_CHECK_HEADERS_ONCE(sys/time.h)
+])
diff --git a/modules/poll b/modules/poll
new file mode 100644 (file)
index 0000000..1d796ad
--- /dev/null
@@ -0,0 +1,23 @@
+Description:
+poll() function: wait for some event on a set of file descriptors.
+
+Files:
+lib/poll.c
+lib/poll_.h
+m4/poll.m4
+
+Depends-on:
+
+configure.ac:
+gl_FUNC_POLL
+
+Makefile.am:
+noinst_HEADERS += poll_.h
+DISTCLEANFILES += poll.h
+
+Include:
+#include <poll.h>
+
+Maintainer:
+Paolo Bonzini  <bonzini@gnu.org>
+