X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/putty/blobdiff_plain/3d88e64dfcf5dc0fd361ce0c504c67a9196ce44c..0ff9ea389c749836c7c6f23f1e654bc9a5600ebf:/unix/uxsel.c diff --git a/unix/uxsel.c b/unix/uxsel.c new file mode 100644 index 00000000..aaedc022 --- /dev/null +++ b/unix/uxsel.c @@ -0,0 +1,116 @@ +/* + * uxsel.c + * + * This module is a sort of all-purpose interchange for file + * descriptors. At one end it talks to uxnet.c and pty.c and + * anything else which might have one or more fds that need + * select()-type things doing to them during an extended program + * run; at the other end it talks to pterm.c or uxplink.c or + * anything else which might have its own means of actually doing + * those select()-type things. + */ + +#include + +#include "putty.h" +#include "tree234.h" + +struct fd { + int fd; + int rwx; /* 4=except 2=write 1=read */ + uxsel_callback_fn callback; +}; + +static tree234 *fds; + +static int uxsel_fd_cmp(void *av, void *bv) +{ + struct fd *a = (struct fd *)av; + struct fd *b = (struct fd *)bv; + if (a->fd < b->fd) + return -1; + if (a->fd > b->fd) + return +1; + return 0; +} +static int uxsel_fd_findcmp(void *av, void *bv) +{ + int *a = (int *)av; + struct fd *b = (struct fd *)bv; + if (*a < b->fd) + return -1; + if (*a > b->fd) + return +1; + return 0; +} + +void uxsel_init(void) +{ + fds = newtree234(uxsel_fd_cmp); +} + +/* + * Here is the interface to fd-supplying modules. They supply an + * fd, a set of read/write/execute states, and a callback function + * for when the fd satisfies one of those states. Repeated calls to + * uxsel_set on the same fd are perfectly legal and serve to change + * the rwx state (typically you only want to select an fd for + * writing when you actually have pending data you want to write to + * it!). + */ + +void uxsel_set(int fd, int rwx, uxsel_callback_fn callback) +{ + struct fd *newfd = snew(struct fd); + struct fd *oldfd; + + newfd->fd = fd; + newfd->rwx = rwx; + newfd->callback = callback; + + oldfd = find234(fds, newfd, NULL); + if (oldfd) { + del234(fds, oldfd); + sfree(oldfd); + } + + add234(fds, newfd); +} + +void uxsel_del(int fd) +{ + struct fd *oldfd = find234(fds, &fd, uxsel_fd_findcmp); + if (oldfd) { + del234(fds, oldfd); + sfree(oldfd); + } +} + +/* + * And here is the interface to select-functionality-supplying + * modules. + */ + +int next_fd(int *state, int *rwx) +{ + struct fd *fd; + fd = index234(fds, (*state)++); + if (fd) { + *rwx = fd->rwx; + return fd->fd; + } else + return -1; +} + +int first_fd(int *state, int *rwx) +{ + *state = 0; + return next_fd(state, rwx); +} + +int select_result(int fd, int event) +{ + struct fd *fdstruct = find234(fds, &fd, uxsel_fd_findcmp); + assert(fdstruct != NULL); + return fdstruct->callback(fd, event); +}