From dd49b986ed3612910ae75d10cf78411bef361b2d Mon Sep 17 00:00:00 2001 From: Quentin Smith Date: Fri, 20 Apr 2012 04:59:09 -0400 Subject: [PATCH] Pull in third-party poll emulator and automatically link it in if we detect the system's poll is broken --- configure.ac | 61 +++++++- third/Makefile.am | 3 + third/poll/LICENSE | 32 +++++ third/poll/Makefile.am | 10 ++ third/poll/poll.c | 306 +++++++++++++++++++++++++++++++++++++++++ third/poll/poll.h | 105 ++++++++++++++ third/poll/sys/poll.h | 1 + 7 files changed, 515 insertions(+), 3 deletions(-) create mode 100644 third/poll/LICENSE create mode 100644 third/poll/Makefile.am create mode 100644 third/poll/poll.c create mode 100644 third/poll/poll.h create mode 100644 third/poll/sys/poll.h diff --git a/configure.ac b/configure.ac index 0c07a7b..246eeaa 100644 --- a/configure.ac +++ b/configure.ac @@ -242,9 +242,63 @@ PKG_CHECK_MODULES([TINFO], [tinfo], , AC_ARG_VAR([poll_CFLAGS], [C compiler flags for poll]) AC_ARG_VAR([poll_LIBS], [linker flags for poll]) -if test -z "$poll_LIBS"; then - AC_CHECK_LIB([poll], [poll], [poll_LIBS="-lpoll"]) -fi +AS_IF([test -z "$poll_LIBS"], [ + AC_CHECK_LIB([poll], [poll], [poll_LIBS="-lpoll"]) +]) + +# Check to make sure poll() can handle stdin and ptys +AC_CACHE_CHECK([whether poll can handle ptys], + [ac_cv_poll_pty], +[ + save_CFLAGS="$CFLAGS" + save_LIBS="$LIBS" + + AS_IF([test "x$poll_CFLAGS" != "x"], + [CFLAGS="$CFLAGS $poll_CFLAGS"]) + + AS_IF([test "x$poll_LIBS" != "x"], + [LIBS="$LIBS $poll_LIBS"]) + + AC_RUN_IFELSE([AC_LANG_PROGRAM([[ +#include +#include +#include +#if HAVE_PTY_H +#include +#elif HAVE_UTIL_H +#include +#endif +#include + +int master, slave; +struct pollfd pollfds[ 1 ]; +]], [[ +if ( openpty( &master, &slave, NULL, NULL, NULL ) < 0 ) { + perror( "openpty" ); + exit( 1 ); +} +pollfds[ 0 ].fd = master; +pollfds[ 0 ].events = POLLIN; +int active_fds = poll( pollfds, 1, 100 ); +if ( active_fds < 0 ) { + perror( "poll" ); + exit( 1 ); +} +if ( pollfds[ 0 ].revents & (POLLERR | POLLHUP | POLLNVAL) ) { + exit( 2 ); +} +]])], + [ac_cv_poll_pty=yes], + [ac_cv_poll_pty=no]) + CFLAGS="$save_CFLAGS" + LIBS="$save_LIBS" +]) +AM_CONDITIONAL([COND_THIRD_POLL], [test "x$ac_cv_poll_pty" = "xno"]) +AM_COND_IF([COND_THIRD_POLL], + [ + poll_CFLAGS="-I\$(top_srcdir)/third/poll" + poll_LIBS="\$(top_builddir)/third/poll/libpoll.a" + ]) AC_MSG_CHECKING([whether pipe2(..., O_CLOEXEC) is supported]) AC_LINK_IFELSE([AC_LANG_PROGRAM([[#define _GNU_SOURCE @@ -306,6 +360,7 @@ AC_CONFIG_FILES([ Makefile third/Makefile third/libstddjb/Makefile + third/poll/Makefile src/Makefile src/crypto/Makefile src/frontend/Makefile diff --git a/third/Makefile.am b/third/Makefile.am index ba3cbf9..0291554 100644 --- a/third/Makefile.am +++ b/third/Makefile.am @@ -2,3 +2,6 @@ SUBDIRS = if COND_THIRD_LIBSTDDJB SUBDIRS += libstddjb endif +if COND_THIRD_POLL + SUBDIRS += poll +endif diff --git a/third/poll/LICENSE b/third/poll/LICENSE new file mode 100644 index 0000000..fc21ce6 --- /dev/null +++ b/third/poll/LICENSE @@ -0,0 +1,32 @@ +This software is released under the following BSD license, adapted from +http://opensource.org/licenses/bsd-license.php +--------------------------------------------------------------------------- + +Copyright (c) 1995-2011, Brian M. Clapper +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the clapper.org nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/third/poll/Makefile.am b/third/poll/Makefile.am new file mode 100644 index 0000000..1ac7df3 --- /dev/null +++ b/third/poll/Makefile.am @@ -0,0 +1,10 @@ +AM_CFLAGS = -pedantic -Wall -Wextra -pipe $(HARDEN_CFLAGS) + +noinst_LIBRARIES = libpoll.a + +libpoll_a_SOURCES = \ + sys/poll.h \ + poll.h \ + poll.c + +EXTRA_DIST = LICENSE diff --git a/third/poll/poll.c b/third/poll/poll.c new file mode 100644 index 0000000..6ec5446 --- /dev/null +++ b/third/poll/poll.c @@ -0,0 +1,306 @@ +/*---------------------------------------------------------------------------*\ + $Id$ + + NAME + + poll - select(2)-based poll() emulation function for BSD systems. + + SYNOPSIS + #include "poll.h" + + struct pollfd + { + int fd; + short events; + short revents; + } + + int poll (struct pollfd *pArray, unsigned long n_fds, int timeout) + + DESCRIPTION + + This file, and the accompanying "poll.h", implement the System V + poll(2) system call for BSD systems (which typically do not provide + poll()). Poll() provides a method for multiplexing input and output + on multiple open file descriptors; in traditional BSD systems, that + capability is provided by select(). While the semantics of select() + differ from those of poll(), poll() can be readily emulated in terms + of select() -- which is how this function is implemented. + + REFERENCES + Stevens, W. Richard. Unix Network Programming. Prentice-Hall, 1990. + + NOTES + 1. This software requires an ANSI C compiler. + + LICENSE + + This software is released under the following BSD license, adapted from + http://opensource.org/licenses/bsd-license.php + + Copyright (c) 1995-2011, Brian M. Clapper + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the clapper.org nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*\ + Includes +\*---------------------------------------------------------------------------*/ + +#include /* standard Unix definitions */ +#include /* system types */ +#include /* time definitions */ +#include /* assertion macros */ +#include /* string functions */ +#include "poll.h" /* this package */ + +/*---------------------------------------------------------------------------*\ + Macros +\*---------------------------------------------------------------------------*/ + +#ifndef MAX +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif + +/*---------------------------------------------------------------------------*\ + Private Functions +\*---------------------------------------------------------------------------*/ + +static int map_poll_spec +#if __STDC__ > 0 + (struct pollfd *pArray, + nfds_t n_fds, + fd_set *pReadSet, + fd_set *pWriteSet, + fd_set *pExceptSet) +#else + (pArray, n_fds, pReadSet, pWriteSet, pExceptSet) + struct pollfd *pArray; + nfds_t n_fds, + fd_set *pReadSet; + fd_set *pWriteSet; + fd_set *pExceptSet; +#endif +{ + register nfds_t i; /* loop control */ + register struct pollfd *pCur; /* current array element */ + register int max_fd = -1; /* return value */ + + /* + Map the poll() structures into the file descriptor sets required + by select(). + */ + for (i = 0, pCur = pArray; i < n_fds; i++, pCur++) + { + /* Skip any bad FDs in the array. */ + + if (pCur->fd < 0) + continue; + + if (pCur->events & POLLIN) + { + /* "Input Ready" notification desired. */ + FD_SET (pCur->fd, pReadSet); + } + + if (pCur->events & POLLOUT) + { + /* "Output Possible" notification desired. */ + FD_SET (pCur->fd, pWriteSet); + } + + if (pCur->events & POLLPRI) + { + /* + "Exception Occurred" notification desired. (Exceptions + include out of band data. + */ + FD_SET (pCur->fd, pExceptSet); + } + + max_fd = MAX (max_fd, pCur->fd); + } + + return max_fd; +} + +static struct timeval *map_timeout +#if __STDC__ > 0 + (int poll_timeout, struct timeval *pSelTimeout) +#else + (poll_timeout, pSelTimeout) + int poll_timeout; + struct timeval *pSelTimeout; +#endif +{ + struct timeval *pResult; + + /* + Map the poll() timeout value into a select() timeout. The possible + values of the poll() timeout value, and their meanings, are: + + VALUE MEANING + + -1 wait indefinitely (until signal occurs) + 0 return immediately, don't block + >0 wait specified number of milliseconds + + select() uses a "struct timeval", which specifies the timeout in + seconds and microseconds, so the milliseconds value has to be mapped + accordingly. + */ + + assert (pSelTimeout != (struct timeval *) NULL); + + switch (poll_timeout) + { + case -1: + /* + A NULL timeout structure tells select() to wait indefinitely. + */ + pResult = (struct timeval *) NULL; + break; + + case 0: + /* + "Return immediately" (test) is specified by all zeros in + a timeval structure. + */ + pSelTimeout->tv_sec = 0; + pSelTimeout->tv_usec = 0; + pResult = pSelTimeout; + break; + + default: + /* Wait the specified number of milliseconds. */ + pSelTimeout->tv_sec = poll_timeout / 1000; /* get seconds */ + poll_timeout %= 1000; /* remove seconds */ + pSelTimeout->tv_usec = poll_timeout * 1000; /* get microseconds */ + pResult = pSelTimeout; + break; + } + + + return pResult; +} + +static void map_select_results +#if __STDC__ > 0 + (struct pollfd *pArray, + unsigned long n_fds, + fd_set *pReadSet, + fd_set *pWriteSet, + fd_set *pExceptSet) +#else + (pArray, n_fds, pReadSet, pWriteSet, pExceptSet) + struct pollfd *pArray; + unsigned long n_fds; + fd_set *pReadSet; + fd_set *pWriteSet; + fd_set *pExceptSet; +#endif +{ + register unsigned long i; /* loop control */ + register struct pollfd *pCur; /* current array element */ + + for (i = 0, pCur = pArray; i < n_fds; i++, pCur++) + { + /* Skip any bad FDs in the array. */ + + if (pCur->fd < 0) + continue; + + /* Exception events take priority over input events. */ + + pCur->revents = 0; + if (FD_ISSET (pCur->fd, pExceptSet)) + pCur->revents |= POLLPRI; + + else if (FD_ISSET (pCur->fd, pReadSet)) + pCur->revents |= POLLIN; + + if (FD_ISSET (pCur->fd, pWriteSet)) + pCur->revents |= POLLOUT; + } + + return; +} + +/*---------------------------------------------------------------------------*\ + Public Functions +\*---------------------------------------------------------------------------*/ + +int poll + +#if __STDC__ > 0 + (struct pollfd *pArray, unsigned long n_fds, int timeout) +#else + (pArray, n_fds, timeout) + struct pollfd *pArray; + unsigned long n_fds; + int timeout; +#endif + +{ + fd_set read_descs; /* input file descs */ + fd_set write_descs; /* output file descs */ + fd_set except_descs; /* exception descs */ + struct timeval stime; /* select() timeout value */ + int ready_descriptors; /* function result */ + int max_fd; /* maximum fd value */ + struct timeval *pTimeout; /* actually passed */ + + FD_ZERO (&read_descs); + FD_ZERO (&write_descs); + FD_ZERO (&except_descs); + + assert (pArray != (struct pollfd *) NULL); + + /* Map the poll() file descriptor list in the select() data structures. */ + + max_fd = map_poll_spec (pArray, n_fds, + &read_descs, &write_descs, &except_descs); + + /* Map the poll() timeout value in the select() timeout structure. */ + + pTimeout = map_timeout (timeout, &stime); + + /* Make the select() call. */ + + ready_descriptors = select (max_fd + 1, &read_descs, &write_descs, + &except_descs, pTimeout); + + if (ready_descriptors >= 0) + { + map_select_results (pArray, n_fds, + &read_descs, &write_descs, &except_descs); + } + + return ready_descriptors; +} diff --git a/third/poll/poll.h b/third/poll/poll.h new file mode 100644 index 0000000..1d294e8 --- /dev/null +++ b/third/poll/poll.h @@ -0,0 +1,105 @@ +/*---------------------------------------------------------------------------*\ + $Id$ + + NAME + + poll - select(2)-based poll() emulation function for BSD systems. + + SYNOPSIS + #include "poll.h" + + struct pollfd + { + int fd; + short events; + short revents; + } + + int poll (struct pollfd *pArray, unsigned long n_fds, int timeout) + + DESCRIPTION + + This file, and the accompanying "poll.c", implement the System V + poll(2) system call for BSD systems (which typically do not provide + poll()). Poll() provides a method for multiplexing input and output + on multiple open file descriptors; in traditional BSD systems, that + capability is provided by select(). While the semantics of select() + differ from those of poll(), poll() can be readily emulated in terms + of select() -- which is how this function is implemented. + + REFERENCES + Stevens, W. Richard. Unix Network Programming. Prentice-Hall, 1990. + + NOTES + 1. This software requires an ANSI C compiler. + + LICENSE + + This software is released under the following BSD license, adapted from + http://opensource.org/licenses/bsd-license.php + + Copyright (c) 1995-2011, Brian M. Clapper + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the clapper.org nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\*---------------------------------------------------------------------------*/ + +#ifndef _POLL_EMUL_H_ +#define _POLL_EMUL_H_ + +#define POLLIN 0x01 +#define POLLPRI 0x02 +#define POLLOUT 0x04 +#define POLLERR 0x08 +#define POLLHUP 0x10 +#define POLLNVAL 0x20 + +struct pollfd +{ + int fd; + short events; + short revents; +}; + +typedef unsigned long nfds_t; + +#ifdef __cplusplus +extern "C" +{ +#endif + +#if (__STDC__ > 0) || defined(__cplusplus) +extern int poll (struct pollfd *pArray, nfds_t n_fds, int timeout); +#else +extern int poll(); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _POLL_EMUL_H_ */ diff --git a/third/poll/sys/poll.h b/third/poll/sys/poll.h new file mode 100644 index 0000000..779ec77 --- /dev/null +++ b/third/poll/sys/poll.h @@ -0,0 +1 @@ +#include