Added uxsel.c, into which I've moved those parts of the uxnet.c
[sgt/putty] / unix / uxsel.c
CommitLineData
0ff9ea38 1/*
2 * uxsel.c
3 *
4 * This module is a sort of all-purpose interchange for file
5 * descriptors. At one end it talks to uxnet.c and pty.c and
6 * anything else which might have one or more fds that need
7 * select()-type things doing to them during an extended program
8 * run; at the other end it talks to pterm.c or uxplink.c or
9 * anything else which might have its own means of actually doing
10 * those select()-type things.
11 */
12
13#include <assert.h>
14
15#include "putty.h"
16#include "tree234.h"
17
18struct fd {
19 int fd;
20 int rwx; /* 4=except 2=write 1=read */
21 uxsel_callback_fn callback;
22};
23
24static tree234 *fds;
25
26static int uxsel_fd_cmp(void *av, void *bv)
27{
28 struct fd *a = (struct fd *)av;
29 struct fd *b = (struct fd *)bv;
30 if (a->fd < b->fd)
31 return -1;
32 if (a->fd > b->fd)
33 return +1;
34 return 0;
35}
36static int uxsel_fd_findcmp(void *av, void *bv)
37{
38 int *a = (int *)av;
39 struct fd *b = (struct fd *)bv;
40 if (*a < b->fd)
41 return -1;
42 if (*a > b->fd)
43 return +1;
44 return 0;
45}
46
47void uxsel_init(void)
48{
49 fds = newtree234(uxsel_fd_cmp);
50}
51
52/*
53 * Here is the interface to fd-supplying modules. They supply an
54 * fd, a set of read/write/execute states, and a callback function
55 * for when the fd satisfies one of those states. Repeated calls to
56 * uxsel_set on the same fd are perfectly legal and serve to change
57 * the rwx state (typically you only want to select an fd for
58 * writing when you actually have pending data you want to write to
59 * it!).
60 */
61
62void uxsel_set(int fd, int rwx, uxsel_callback_fn callback)
63{
64 struct fd *newfd = snew(struct fd);
65 struct fd *oldfd;
66
67 newfd->fd = fd;
68 newfd->rwx = rwx;
69 newfd->callback = callback;
70
71 oldfd = find234(fds, newfd, NULL);
72 if (oldfd) {
73 del234(fds, oldfd);
74 sfree(oldfd);
75 }
76
77 add234(fds, newfd);
78}
79
80void uxsel_del(int fd)
81{
82 struct fd *oldfd = find234(fds, &fd, uxsel_fd_findcmp);
83 if (oldfd) {
84 del234(fds, oldfd);
85 sfree(oldfd);
86 }
87}
88
89/*
90 * And here is the interface to select-functionality-supplying
91 * modules.
92 */
93
94int next_fd(int *state, int *rwx)
95{
96 struct fd *fd;
97 fd = index234(fds, (*state)++);
98 if (fd) {
99 *rwx = fd->rwx;
100 return fd->fd;
101 } else
102 return -1;
103}
104
105int first_fd(int *state, int *rwx)
106{
107 *state = 0;
108 return next_fd(state, rwx);
109}
110
111int select_result(int fd, int event)
112{
113 struct fd *fdstruct = find234(fds, &fd, uxsel_fd_findcmp);
114 assert(fdstruct != NULL);
115 return fdstruct->callback(fd, event);
116}