changeset 4242:eec6ba9ed532

New module poll, from Paolo Bonzini <bonzini@gnu.org>.
author Bruno Haible <bruno@clisp.org>
date Thu, 20 Feb 2003 13:10:05 +0000
parents 65538d0c9302
children 8e98e4f8e06d
files ChangeLog MODULES.html.sh lib/ChangeLog lib/poll.c lib/poll_.h m4/ChangeLog m4/poll.m4 modules/poll
diffstat 8 files changed, 305 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- 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.
--- a/MODULES.html.sh
+++ b/MODULES.html.sh
@@ -1670,6 +1670,7 @@
   func_module mkdir
   func_module mkstemp
   func_module mkdtemp
+  func_module poll
   func_module stat
   func_module lstat
   func_module timespec
--- a/lib/ChangeLog
+++ b/lib/ChangeLog
@@ -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.
new file mode 100644
--- /dev/null
+++ b/lib/poll.c
@@ -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;
+}
new file mode 100644
--- /dev/null
+++ b/lib/poll_.h
@@ -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
--- a/m4/ChangeLog
+++ b/m4/ChangeLog
@@ -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.
new file mode 100644
--- /dev/null
+++ b/m4/poll.m4
@@ -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)
+])
new file mode 100644
--- /dev/null
+++ b/modules/poll
@@ -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>
+