123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- /*
- * uxsel.c
- *
- * This module is a sort of all-purpose interchange for file
- * descriptors. At one end it talks to network.c and pty.c and
- * anything else which might have one or more fds that need
- * select() or poll()-type things doing to them during an extended
- * program run; at the other end it talks to window.c or plink.c or
- * anything else which might have its own means of actually doing
- * those select()-type things.
- */
- #include <assert.h>
- #include "putty.h"
- #include "tree234.h"
- struct fd {
- int fd;
- int rwx; /* 4=except 2=write 1=read */
- uxsel_callback_fn callback;
- uxsel_id *id; /* for uxsel_input_remove */
- };
- 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;
- assert(fd >= 0);
- uxsel_del(fd);
- if (rwx) {
- newfd = snew(struct fd);
- newfd->fd = fd;
- newfd->rwx = rwx;
- newfd->callback = callback;
- newfd->id = uxsel_input_add(fd, rwx);
- add234(fds, newfd);
- }
- }
- void uxsel_del(int fd)
- {
- struct fd *oldfd = find234(fds, &fd, uxsel_fd_findcmp);
- if (oldfd) {
- if (oldfd->id)
- uxsel_input_remove(oldfd->id);
- 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);
- }
- void select_result(int fd, int event)
- {
- struct fd *fdstruct = find234(fds, &fd, uxsel_fd_findcmp);
- noise_ultralight(NOISE_SOURCE_IOID, fd);
- /*
- * Apparently this can sometimes be NULL. Can't see how, but I
- * assume it means I need to ignore the event since it's on an
- * fd I've stopped being interested in. Sigh.
- */
- if (fdstruct)
- fdstruct->callback(fd, event);
- }
|