2019-03-26 18:37:26 +00:00
|
|
|
/* On some systems this is needed to get poll.h to define eg.. POLLRDNORM */
|
|
|
|
#define _XOPEN_SOURCE
|
|
|
|
|
2019-02-07 18:21:06 +00:00
|
|
|
#include <poll.h>
|
|
|
|
|
|
|
|
#include "putty.h"
|
|
|
|
#include "tree234.h"
|
|
|
|
|
|
|
|
struct pollwrapper {
|
|
|
|
struct pollfd *fds;
|
|
|
|
size_t nfd, fdsize;
|
|
|
|
tree234 *fdtopos;
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct pollwrap_fdtopos pollwrap_fdtopos;
|
|
|
|
struct pollwrap_fdtopos {
|
|
|
|
int fd;
|
|
|
|
size_t pos;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int pollwrap_fd_cmp(void *av, void *bv)
|
|
|
|
{
|
|
|
|
pollwrap_fdtopos *a = (pollwrap_fdtopos *)av;
|
|
|
|
pollwrap_fdtopos *b = (pollwrap_fdtopos *)bv;
|
|
|
|
return a->fd < b->fd ? -1 : a->fd > b->fd ? +1 : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
pollwrapper *pollwrap_new(void)
|
|
|
|
{
|
|
|
|
pollwrapper *pw = snew(pollwrapper);
|
|
|
|
pw->fdsize = 16;
|
|
|
|
pw->nfd = 0;
|
|
|
|
pw->fds = snewn(pw->fdsize, struct pollfd);
|
|
|
|
pw->fdtopos = newtree234(pollwrap_fd_cmp);
|
|
|
|
return pw;
|
|
|
|
}
|
|
|
|
|
|
|
|
void pollwrap_free(pollwrapper *pw)
|
|
|
|
{
|
|
|
|
pollwrap_clear(pw);
|
|
|
|
freetree234(pw->fdtopos);
|
|
|
|
sfree(pw->fds);
|
|
|
|
sfree(pw);
|
|
|
|
}
|
|
|
|
|
|
|
|
void pollwrap_clear(pollwrapper *pw)
|
|
|
|
{
|
|
|
|
pw->nfd = 0;
|
|
|
|
for (pollwrap_fdtopos *f2p;
|
|
|
|
(f2p = delpos234(pw->fdtopos, 0)) != NULL ;)
|
|
|
|
sfree(f2p);
|
|
|
|
}
|
|
|
|
|
|
|
|
void pollwrap_add_fd_events(pollwrapper *pw, int fd, int events)
|
|
|
|
{
|
|
|
|
pollwrap_fdtopos *f2p, f2p_find;
|
|
|
|
|
|
|
|
assert(fd >= 0);
|
|
|
|
|
|
|
|
f2p_find.fd = fd;
|
|
|
|
f2p = find234(pw->fdtopos, &f2p_find, NULL);
|
|
|
|
if (!f2p) {
|
|
|
|
sgrowarray(pw->fds, pw->fdsize, pw->nfd);
|
|
|
|
size_t index = pw->nfd++;
|
|
|
|
pw->fds[index].fd = fd;
|
|
|
|
pw->fds[index].events = pw->fds[index].revents = 0;
|
|
|
|
|
|
|
|
f2p = snew(pollwrap_fdtopos);
|
|
|
|
f2p->fd = fd;
|
|
|
|
f2p->pos = index;
|
|
|
|
pollwrap_fdtopos *added = add234(pw->fdtopos, f2p);
|
|
|
|
assert(added == f2p);
|
|
|
|
}
|
|
|
|
|
|
|
|
pw->fds[f2p->pos].events |= events;
|
|
|
|
}
|
|
|
|
|
2019-03-26 18:37:26 +00:00
|
|
|
/* Omit any of the POLL{RD,WR}{NORM,BAND} flag values that are still
|
|
|
|
* not defined by poll.h, just in case */
|
|
|
|
#ifndef POLLRDNORM
|
|
|
|
#define POLLRDNORM 0
|
|
|
|
#endif
|
|
|
|
#ifndef POLLRDBAND
|
|
|
|
#define POLLRDBAND 0
|
|
|
|
#endif
|
|
|
|
#ifndef POLLWRNORM
|
|
|
|
#define POLLWRNORM 0
|
|
|
|
#endif
|
|
|
|
#ifndef POLLWRBAND
|
|
|
|
#define POLLWRBAND 0
|
|
|
|
#endif
|
|
|
|
|
2019-02-07 18:21:06 +00:00
|
|
|
#define SELECT_R_IN (POLLIN | POLLRDNORM | POLLRDBAND)
|
|
|
|
#define SELECT_W_IN (POLLOUT | POLLWRNORM | POLLWRBAND)
|
|
|
|
#define SELECT_X_IN (POLLPRI)
|
|
|
|
|
|
|
|
#define SELECT_R_OUT (SELECT_R_IN | POLLERR | POLLHUP)
|
|
|
|
#define SELECT_W_OUT (SELECT_W_IN | POLLERR)
|
|
|
|
#define SELECT_X_OUT (SELECT_X_IN)
|
|
|
|
|
|
|
|
void pollwrap_add_fd_rwx(pollwrapper *pw, int fd, int rwx)
|
|
|
|
{
|
|
|
|
int events = 0;
|
|
|
|
if (rwx & SELECT_R)
|
|
|
|
events |= SELECT_R_IN;
|
|
|
|
if (rwx & SELECT_W)
|
|
|
|
events |= SELECT_W_IN;
|
|
|
|
if (rwx & SELECT_X)
|
|
|
|
events |= SELECT_X_IN;
|
|
|
|
pollwrap_add_fd_events(pw, fd, events);
|
|
|
|
}
|
|
|
|
|
|
|
|
int pollwrap_poll_instant(pollwrapper *pw)
|
|
|
|
{
|
|
|
|
return poll(pw->fds, pw->nfd, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int pollwrap_poll_endless(pollwrapper *pw)
|
|
|
|
{
|
|
|
|
return poll(pw->fds, pw->nfd, -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
int pollwrap_poll_timeout(pollwrapper *pw, int milliseconds)
|
|
|
|
{
|
|
|
|
assert(milliseconds >= 0);
|
|
|
|
return poll(pw->fds, pw->nfd, milliseconds);
|
|
|
|
}
|
|
|
|
|
2020-02-06 23:48:36 +00:00
|
|
|
static void pollwrap_get_fd_events_revents(pollwrapper *pw, int fd,
|
|
|
|
int *events_p, int *revents_p)
|
2019-02-07 18:21:06 +00:00
|
|
|
{
|
|
|
|
pollwrap_fdtopos *f2p, f2p_find;
|
2020-02-06 23:48:36 +00:00
|
|
|
int events = 0, revents = 0;
|
2019-02-07 18:21:06 +00:00
|
|
|
|
|
|
|
assert(fd >= 0);
|
|
|
|
|
|
|
|
f2p_find.fd = fd;
|
|
|
|
f2p = find234(pw->fdtopos, &f2p_find, NULL);
|
2020-02-06 23:48:36 +00:00
|
|
|
if (f2p) {
|
|
|
|
events = pw->fds[f2p->pos].events;
|
|
|
|
revents = pw->fds[f2p->pos].revents;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (events_p)
|
|
|
|
*events_p = events;
|
|
|
|
if (revents_p)
|
|
|
|
*revents_p = revents;
|
|
|
|
}
|
2019-02-07 18:21:06 +00:00
|
|
|
|
2020-02-06 23:48:36 +00:00
|
|
|
int pollwrap_get_fd_events(pollwrapper *pw, int fd)
|
|
|
|
{
|
|
|
|
int revents;
|
|
|
|
pollwrap_get_fd_events_revents(pw, fd, NULL, &revents);
|
|
|
|
return revents;
|
2019-02-07 18:21:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int pollwrap_get_fd_rwx(pollwrapper *pw, int fd)
|
|
|
|
{
|
2020-02-06 23:48:36 +00:00
|
|
|
int events, revents;
|
|
|
|
pollwrap_get_fd_events_revents(pw, fd, &events, &revents);
|
2019-02-07 18:21:06 +00:00
|
|
|
int rwx = 0;
|
2020-02-06 23:48:36 +00:00
|
|
|
if ((events & POLLIN) && (revents & SELECT_R_OUT))
|
2019-02-07 18:21:06 +00:00
|
|
|
rwx |= SELECT_R;
|
2020-02-06 23:48:36 +00:00
|
|
|
if ((events & POLLOUT) && (revents & SELECT_W_OUT))
|
2019-02-07 18:21:06 +00:00
|
|
|
rwx |= SELECT_W;
|
2020-02-06 23:48:36 +00:00
|
|
|
if ((events & POLLPRI) && (revents & SELECT_X_OUT))
|
2019-02-07 18:21:06 +00:00
|
|
|
rwx |= SELECT_X;
|
|
|
|
return rwx;
|
|
|
|
}
|