mirror of https://github.com/sheumann/hush.git
Add an implementation of poll() written in terms of select(), to work around the lack of poll() on GNO.
This is a BSD-licensed poll() implementation by Brian M. Clapper. Its performance characteristics aren't as good as a "native" poll() would be, but this shouldn't be a problem in practice.
This commit is contained in:
parent
4e47bee9d2
commit
488a238ad7
3
Makefile
3
Makefile
|
@ -51,7 +51,8 @@ SRCS = \
|
||||||
libbb/appletlib.c \
|
libbb/appletlib.c \
|
||||||
libbb/bb.basename.c \
|
libbb/bb.basename.c \
|
||||||
libbb/mempcpy.c \
|
libbb/mempcpy.c \
|
||||||
libbb/vfork.and.run.c
|
libbb/vfork.and.run.c \
|
||||||
|
libbb/poll.c
|
||||||
OBJS = $(SRCS:.c=.o)
|
OBJS = $(SRCS:.c=.o)
|
||||||
ROOTS = $(SRCS:.c=.root)
|
ROOTS = $(SRCS:.c=.root)
|
||||||
|
|
||||||
|
|
|
@ -34,11 +34,7 @@
|
||||||
/* See the dirname/basename man page for details */
|
/* See the dirname/basename man page for details */
|
||||||
#undef basename
|
#undef basename
|
||||||
#define basename dont_use_basename
|
#define basename dont_use_basename
|
||||||
#ifndef __GNO__
|
#include "poll.h"
|
||||||
# include <poll.h>
|
|
||||||
#else
|
|
||||||
//TODO Deal with lack of poll in GNO
|
|
||||||
#endif
|
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
@ -755,11 +751,7 @@ void qsort_string_vector(char **sv, unsigned count) FAST_FUNC;
|
||||||
* On other errors complains [perror("poll")] and returns.
|
* On other errors complains [perror("poll")] and returns.
|
||||||
* Warning! May take (much) longer than timeout_ms to return!
|
* Warning! May take (much) longer than timeout_ms to return!
|
||||||
* If this is a problem, use bare poll and open-code EINTR/ENOMEM handling */
|
* If this is a problem, use bare poll and open-code EINTR/ENOMEM handling */
|
||||||
#ifndef __GNO__
|
|
||||||
int safe_poll(struct pollfd *ufds, nfds_t nfds, int timeout_ms) FAST_FUNC;
|
int safe_poll(struct pollfd *ufds, nfds_t nfds, int timeout_ms) FAST_FUNC;
|
||||||
#else
|
|
||||||
//TODO Deal with lack of poll in GNO
|
|
||||||
#endif
|
|
||||||
|
|
||||||
char *safe_gethostname(void) FAST_FUNC;
|
char *safe_gethostname(void) FAST_FUNC;
|
||||||
|
|
||||||
|
|
|
@ -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_ */
|
|
@ -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 <unistd.h> /* standard Unix definitions */
|
||||||
|
#include <sys/types.h> /* system types */
|
||||||
|
#include <sys/time.h> /* time definitions */
|
||||||
|
#include <assert.h> /* assertion macros */
|
||||||
|
#include <string.h> /* 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;
|
||||||
|
}
|
|
@ -188,19 +188,14 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val),
|
||||||
* regardless of SA_RESTART-ness of that signal!
|
* regardless of SA_RESTART-ness of that signal!
|
||||||
*/
|
*/
|
||||||
errno = 0;
|
errno = 0;
|
||||||
#ifndef __GNO__
|
|
||||||
// GNO doesn't have poll, so disable this for now. This disables the -t
|
|
||||||
// (timeout) flag and may interfere with signal handling, as mentioned above.
|
|
||||||
// TODO Do something more intelligent here.
|
|
||||||
pfd[0].fd = fd;
|
pfd[0].fd = fd;
|
||||||
pfd[0].events = POLLIN;
|
pfd[0].events = POLLIN;
|
||||||
if (poll(pfd, 1, timeout * 1000) != 1) {
|
if (poll(pfd, 1, timeout == -1 ? -1 : timeout * 1000) != 1) {
|
||||||
/* timed out, or EINTR */
|
/* timed out, or EINTR */
|
||||||
err = errno;
|
err = errno;
|
||||||
retval = (const char *)(uintptr_t)1;
|
retval = (const char *)(uintptr_t)1;
|
||||||
goto ret;
|
goto ret;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
if (read(fd, &buffer[bufpos], 1) != 1) {
|
if (read(fd, &buffer[bufpos], 1) != 1) {
|
||||||
err = errno;
|
err = errno;
|
||||||
retval = (const char *)(uintptr_t)1;
|
retval = (const char *)(uintptr_t)1;
|
||||||
|
|
Loading…
Reference in New Issue