]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - unix/uxsel.c
Added uxsel.c, into which I've moved those parts of the uxnet.c
[PuTTY.git] / unix / uxsel.c
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
18 struct fd {
19     int fd;
20     int rwx;                           /* 4=except 2=write 1=read */
21     uxsel_callback_fn callback;
22 };
23
24 static tree234 *fds;
25
26 static 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 }
36 static 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
47 void 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
62 void 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
80 void 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
94 int 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
105 int first_fd(int *state, int *rwx)
106 {
107     *state = 0;
108     return next_fd(state, rwx);
109 }
110
111 int 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 }