mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-10 01:48:00 +00:00
b109918032
functionality that deal with selectable fds in general. The idea is that pty.c will stop passing its fd straight to pterm.c and hand it to this module instead, and pterm.c will start requesting a general list of fds from this module rather than expecting a single one from pty.c, with the ultimate aim of pterm.c being able to form the basis of a Unix PuTTY as well as pterm proper. [originally from svn r3015]
117 lines
2.4 KiB
C
117 lines
2.4 KiB
C
/*
|
|
* 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 <assert.h>
|
|
|
|
#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);
|
|
}
|