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 | |
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 | } |