26 |
#include <list.h> |
#include <list.h> |
27 |
|
|
28 |
struct input_system { |
struct input_system { |
29 |
|
fd_set fdset; |
30 |
|
int fd_max; |
31 |
LIST *methods; /* List of METHOD structures */ |
LIST *methods; /* List of METHOD structures */ |
|
ITERATOR *mitr; |
|
32 |
LIST *channels; /* List of CHANNEL structures */ |
LIST *channels; /* List of CHANNEL structures */ |
33 |
ITERATOR *citr; |
ITERATOR *citr; |
34 |
}; |
}; |
36 |
typedef struct input_method METHOD; |
typedef struct input_method METHOD; |
37 |
struct input_method { |
struct input_method { |
38 |
const char *name; |
const char *name; |
39 |
fd_set fdset; |
int prio; |
|
int fd_max; |
|
40 |
int (*handler)(int, void *); |
int (*handler)(int, void *); |
41 |
int (*close)(int, void *); |
int (*close)(int, void *); |
42 |
int (*cmp)(const void *, const void *); |
int (*cmp)(const void *, const void *); |
55 |
INPUT *p = emalloc(sizeof(*p)); |
INPUT *p = emalloc(sizeof(*p)); |
56 |
p->methods = list_create(); |
p->methods = list_create(); |
57 |
p->channels = list_create(); |
p->channels = list_create(); |
58 |
|
FD_ZERO(&p->fdset); |
59 |
|
p->fd_max = -2; |
60 |
return p; |
return p; |
61 |
} |
} |
62 |
|
|
69 |
void |
void |
70 |
input_register_method(INPUT *input, |
input_register_method(INPUT *input, |
71 |
const char *name, |
const char *name, |
72 |
|
int prio, |
73 |
int (*handler)(int, void *), |
int (*handler)(int, void *), |
74 |
int (*close)(int, void *), |
int (*close)(int, void *), |
75 |
int (*cmp)(const void *, const void *)) |
int (*cmp)(const void *, const void *)) |
76 |
{ |
{ |
77 |
METHOD *m = emalloc(sizeof(*m)); |
METHOD *m = emalloc(sizeof(*m)); |
78 |
m->name = name; |
m->name = name; |
79 |
|
m->prio = prio; |
80 |
m->handler = handler; |
m->handler = handler; |
81 |
m->close = close; |
m->close = close; |
82 |
m->cmp = cmp ? cmp : def_cmp; |
m->cmp = cmp ? cmp : def_cmp; |
|
FD_ZERO(&m->fdset); |
|
|
m->fd_max = -2; |
|
83 |
list_append(input->methods, m); |
list_append(input->methods, m); |
84 |
} |
} |
85 |
|
|
92 |
} |
} |
93 |
|
|
94 |
int |
int |
95 |
|
_channel_prio_comp(const void *a, const void *b) |
96 |
|
{ |
97 |
|
const CHANNEL *ca = a; |
98 |
|
const CHANNEL *cb = b; |
99 |
|
|
100 |
|
return ca->method->prio - cb->method->prio; |
101 |
|
} |
102 |
|
|
103 |
|
int |
104 |
input_register_channel(INPUT *input, char *name, int fd, void *data) |
input_register_channel(INPUT *input, char *name, int fd, void *data) |
105 |
{ |
{ |
106 |
CHANNEL *c; |
CHANNEL *c; |
113 |
c->fd = fd; |
c->fd = fd; |
114 |
c->data = data; |
c->data = data; |
115 |
c->method = m; |
c->method = m; |
116 |
FD_SET(fd, &m->fdset); |
FD_SET(fd, &input->fdset); |
117 |
if (fd > m->fd_max) |
if (fd > input->fd_max) |
118 |
m->fd_max = fd; |
input->fd_max = fd; |
119 |
list_append(input->channels, c); |
list_insert_sorted(input->channels, c, _channel_prio_comp); |
120 |
return 0; |
return 0; |
121 |
} |
} |
122 |
|
|
123 |
static void |
static void |
124 |
channel_close(CHANNEL *chan) |
channel_close(INPUT *input, CHANNEL *chan) |
125 |
{ |
{ |
126 |
if (chan->method->close) |
if (chan->method->close) |
127 |
chan->method->close(chan->fd, chan->data); |
chan->method->close(chan->fd, chan->data); |
128 |
FD_CLR(chan->fd, &chan->method->fdset); |
FD_CLR(chan->fd, &input->fdset); |
129 |
chan->method->fd_max = -2; |
input->fd_max = -2; |
130 |
efree(chan); |
efree(chan); |
131 |
} |
} |
132 |
|
|
171 |
for (p = iterator_first(input->citr); p; |
for (p = iterator_first(input->citr); p; |
172 |
p = iterator_next(input->citr)) { |
p = iterator_next(input->citr)) { |
173 |
list_remove(input->channels, p, NULL); |
list_remove(input->channels, p, NULL); |
174 |
channel_close(p); |
channel_close(input, p); |
175 |
} |
} |
176 |
iterator_destroy(&input->citr); |
iterator_destroy(&input->citr); |
177 |
} |
} |
183 |
|
|
184 |
if (p) { |
if (p) { |
185 |
list_remove(input->channels, p, NULL); |
list_remove(input->channels, p, NULL); |
186 |
channel_close(p); |
channel_close(input, p); |
187 |
} |
} |
188 |
} |
} |
189 |
|
|
210 |
p = list_locate(input->channels, &clos, _channel_cmp); |
p = list_locate(input->channels, &clos, _channel_cmp); |
211 |
if (p) { |
if (p) { |
212 |
list_remove(input->channels, p, NULL); |
list_remove(input->channels, p, NULL); |
213 |
channel_close(p); |
channel_close(input, p); |
214 |
} |
} |
215 |
} |
} |
216 |
|
|
217 |
int |
int |
218 |
input_select(INPUT *input, struct timeval *tv) |
input_select(INPUT *input, struct timeval *tv) |
219 |
{ |
{ |
220 |
METHOD *m; |
CHANNEL *p; |
221 |
int status; |
int status; |
222 |
int count = 0; |
fd_set readfds; |
223 |
|
|
224 |
debug(100,("enter")); |
debug(100,("enter")); |
225 |
if (!input->citr) |
if (!input->citr) |
226 |
input->citr = iterator_create(input->channels); |
input->citr = iterator_create(input->channels); |
227 |
if (!input->mitr) |
|
228 |
input->mitr = iterator_create(input->methods); |
if (input->fd_max == -2) { |
229 |
|
for (p = iterator_first(input->citr); p; |
230 |
for (m = iterator_first(input->mitr); m; |
p = iterator_next(input->citr)) { |
231 |
m = iterator_next(input->mitr)) { |
if (p->fd > input->fd_max) |
232 |
CHANNEL *p; |
input->fd_max = p->fd; |
|
fd_set readfds; |
|
|
|
|
|
if (m->fd_max == -2) { |
|
|
for (p = iterator_first(input->citr); p; |
|
|
p = iterator_next(input->citr)) { |
|
|
if (p->method == m && p->fd > m->fd_max) |
|
|
m->fd_max = p->fd; |
|
|
} |
|
|
if (m->fd_max == -2) |
|
|
m->fd_max = -1; |
|
233 |
} |
} |
234 |
|
if (input->fd_max == -2) |
235 |
|
input->fd_max = -1; |
236 |
|
} |
237 |
|
|
238 |
if (m->fd_max < 0) |
insist(input->fd_max >= 0); |
239 |
continue; |
|
240 |
|
readfds = input->fdset; |
|
count++; |
|
|
|
|
|
readfds = m->fdset; |
|
241 |
|
|
242 |
status = select(m->fd_max + 1, &readfds, NULL, NULL, tv); |
status = select(input->fd_max + 1, &readfds, NULL, NULL, tv); |
243 |
|
|
244 |
if (status == -1) { |
if (status == -1) { |
245 |
if (errno == EINTR) |
if (errno == EINTR) |
246 |
return 0; |
return 0; |
247 |
} else if (status > 0) { |
} else if (status > 0) { |
248 |
debug(1, ("select returned %d", status)); |
debug(1, ("select returned %d", status)); |
249 |
for (p = iterator_first(input->citr); p; |
|
250 |
p = iterator_next(input->citr)) { |
for (p = iterator_first(input->citr); p; |
251 |
if (FD_ISSET(p->fd, &readfds)) |
p = iterator_next(input->citr)) |
252 |
channel_handle(p); |
if (FD_ISSET(p->fd, &readfds)) |
253 |
} |
channel_handle(p); |
254 |
} |
} |
|
} |
|
|
insist(count > 0); |
|
|
|
|
255 |
debug(100,("exit")); |
debug(100,("exit")); |
256 |
return status; |
return status; |
257 |
} |
} |