Event Log for Unix PuTTY. Doesn't yet allow X selection of its
[u/mdw/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;
74aca06d 22 int id; /* for uxsel_input_remove */
0ff9ea38 23};
24
25static tree234 *fds;
26
27static int uxsel_fd_cmp(void *av, void *bv)
28{
29 struct fd *a = (struct fd *)av;
30 struct fd *b = (struct fd *)bv;
31 if (a->fd < b->fd)
32 return -1;
33 if (a->fd > b->fd)
34 return +1;
35 return 0;
36}
37static int uxsel_fd_findcmp(void *av, void *bv)
38{
39 int *a = (int *)av;
40 struct fd *b = (struct fd *)bv;
41 if (*a < b->fd)
42 return -1;
43 if (*a > b->fd)
44 return +1;
45 return 0;
46}
47
48void uxsel_init(void)
49{
50 fds = newtree234(uxsel_fd_cmp);
51}
52
53/*
54 * Here is the interface to fd-supplying modules. They supply an
55 * fd, a set of read/write/execute states, and a callback function
56 * for when the fd satisfies one of those states. Repeated calls to
57 * uxsel_set on the same fd are perfectly legal and serve to change
58 * the rwx state (typically you only want to select an fd for
59 * writing when you actually have pending data you want to write to
60 * it!).
61 */
62
63void uxsel_set(int fd, int rwx, uxsel_callback_fn callback)
64{
65 struct fd *newfd = snew(struct fd);
66 struct fd *oldfd;
67
68 newfd->fd = fd;
69 newfd->rwx = rwx;
70 newfd->callback = callback;
71
72 oldfd = find234(fds, newfd, NULL);
73 if (oldfd) {
74aca06d 74 uxsel_input_remove(oldfd->id);
0ff9ea38 75 del234(fds, oldfd);
76 sfree(oldfd);
77 }
78
79 add234(fds, newfd);
74aca06d 80 newfd->id = uxsel_input_add(fd, rwx);
0ff9ea38 81}
82
83void uxsel_del(int fd)
84{
85 struct fd *oldfd = find234(fds, &fd, uxsel_fd_findcmp);
86 if (oldfd) {
74aca06d 87 uxsel_input_remove(oldfd->id);
0ff9ea38 88 del234(fds, oldfd);
89 sfree(oldfd);
90 }
91}
92
93/*
94 * And here is the interface to select-functionality-supplying
95 * modules.
96 */
97
98int next_fd(int *state, int *rwx)
99{
100 struct fd *fd;
101 fd = index234(fds, (*state)++);
102 if (fd) {
103 *rwx = fd->rwx;
104 return fd->fd;
105 } else
106 return -1;
107}
108
109int first_fd(int *state, int *rwx)
110{
111 *state = 0;
112 return next_fd(state, rwx);
113}
114
115int select_result(int fd, int event)
116{
117 struct fd *fdstruct = find234(fds, &fd, uxsel_fd_findcmp);
118 assert(fdstruct != NULL);
119 return fdstruct->callback(fd, event);
120}