buildpack/vendor/autossh/fakepoll.h
2020-02-14 19:40:36 +02:00

172 lines
4.6 KiB
C

/* fakepoll.h
* poll using select
*
* Warning: a call to this poll() takes about 4K of stack space.
* Greg Parker gparker-web@sealiesoftware.com December 2000
* This code is in the public domain and may be copied or modified without
* permission.
*
* Updated May 2002:
* * fix crash when an fd is less than 0
* * set errno=EINVAL if an fd is greater or equal to FD_SETSIZE
* * don't set POLLIN or POLLOUT in revents if it wasn't requested
* in events (only happens when an fd is in the poll set twice)
*
* Updated Dec 2002:
* * change comment style (for autossh, Carson Harding)
* * undef FD_SETSIZE first
*/
#ifndef _FAKE_POLL_H
#define _FAKE_POLL_H
#include <limits.h>
#undef FD_SETSIZE
#define FD_SETSIZE OPEN_MAX
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <stdlib.h>
typedef struct pollfd {
int fd; /* file desc to poll */
short events; /* events of interest on fd */
short revents; /* events that occurred on fd */
} pollfd_t;
/* poll flags */
#define POLLIN 0x0001
#define POLLOUT 0x0004
#define POLLERR 0x0008
/* synonyms */
#define POLLNORM POLLIN
#define POLLPRI POLLIN
#define POLLRDNORM POLLIN
#define POLLRDBAND POLLIN
#define POLLWRNORM POLLOUT
#define POLLWRBAND POLLOUT
/* ignored */
#define POLLHUP 0x0010
#define POLLNVAL 0x0020
inline int poll(struct pollfd *pollSet, int pollCount, int pollTimeout)
{
struct timeval tv;
struct timeval *tvp;
fd_set readFDs, writeFDs, exceptFDs;
fd_set *readp, *writep, *exceptp;
struct pollfd *pollEnd, *p;
int selected;
int result;
int maxFD;
if (!pollSet) {
pollEnd = NULL;
readp = NULL;
writep = NULL;
exceptp = NULL;
maxFD = 0;
}
else {
pollEnd = pollSet + pollCount;
readp = &readFDs;
writep = &writeFDs;
exceptp = &exceptFDs;
FD_ZERO(readp);
FD_ZERO(writep);
FD_ZERO(exceptp);
/* Find the biggest fd in the poll set */
maxFD = 0;
for (p = pollSet; p < pollEnd; p++) {
if (p->fd > maxFD) maxFD = p->fd;
}
if (maxFD >= FD_SETSIZE) {
/* At least one fd is too big */
errno = EINVAL;
return -1;
}
/* Transcribe flags from the poll set to the fd sets */
for (p = pollSet; p < pollEnd; p++) {
if (p->fd < 0) {
/* Negative fd checks nothing and always reports zero */
} else {
if (p->events & POLLIN) FD_SET(p->fd, readp);
if (p->events & POLLOUT) FD_SET(p->fd, writep);
if (p->events != 0) FD_SET(p->fd, exceptp);
/* POLLERR is never set coming in; poll() always reports errors
* But don't report if we're not listening to anything at all.
*/
}
}
}
/* poll timeout is in milliseconds. Convert to struct timeval.
* poll timeout == -1 : wait forever : select timeout of NULL
* poll timeout == 0 : return immediately : select timeout of zero
*/
if (pollTimeout >= 0) {
tv.tv_sec = pollTimeout / 1000;
tv.tv_usec = (pollTimeout % 1000) * 1000;
tvp = &tv;
} else {
tvp = NULL;
}
selected = select(maxFD+1, readp, writep, exceptp, tvp);
if (selected < 0) {
/* Error during select */
result = -1;
}
else if (selected > 0) {
/* Select found something
* Transcribe result from fd sets to poll set.
* Also count the number of selected fds. poll returns the
* number of ready fds; select returns the number of bits set.
*/
int polled = 0;
for (p = pollSet; p < pollEnd; p++) {
p->revents = 0;
if (p->fd < 0) {
/* Negative fd always reports zero */
} else {
if ((p->events & POLLIN) && FD_ISSET(p->fd, readp)) {
p->revents |= POLLIN;
}
if ((p->events & POLLOUT) && FD_ISSET(p->fd, writep)) {
p->revents |= POLLOUT;
}
if ((p->events != 0) && FD_ISSET(p->fd, exceptp)) {
p->revents |= POLLERR;
}
if (p->revents) polled++;
}
}
result = polled;
}
else {
/* selected == 0, select timed out before anything happened
* Clear all result bits and return zero.
*/
for (p = pollSet; p < pollEnd; p++) {
p->revents = 0;
}
result = 0;
}
return result;
}
#endif