31 |
typedef struct input_method METHOD; |
typedef struct input_method METHOD; |
32 |
struct input_method { |
struct input_method { |
33 |
const char *name; |
const char *name; |
34 |
|
fd_set fdset; |
35 |
|
int fd_max; |
36 |
int (*handler)(int, void *); |
int (*handler)(int, void *); |
37 |
int (*close)(int, void *); |
int (*close)(int, void *); |
38 |
int (*cmp)(const void *, const void *); |
int (*cmp)(const void *, const void *); |
72 |
m->handler = handler; |
m->handler = handler; |
73 |
m->close = close; |
m->close = close; |
74 |
m->cmp = cmp ? cmp : def_cmp; |
m->cmp = cmp ? cmp : def_cmp; |
75 |
|
FD_ZERO(&m->fdset); |
76 |
|
m->fd_max = -2; |
77 |
list_append(input->methods, m); |
list_append(input->methods, m); |
78 |
} |
} |
79 |
|
|
98 |
c->fd = fd; |
c->fd = fd; |
99 |
c->data = data; |
c->data = data; |
100 |
c->method = m; |
c->method = m; |
101 |
|
FD_SET(fd, &m->fdset); |
102 |
|
if (fd > m->fd_max) |
103 |
|
m->fd_max = fd; |
104 |
list_append(input->channels, c); |
list_append(input->channels, c); |
105 |
return 0; |
return 0; |
106 |
} |
} |
108 |
static void |
static void |
109 |
channel_close(CHANNEL *chan) |
channel_close(CHANNEL *chan) |
110 |
{ |
{ |
111 |
if (chan->method->close) |
if (chan->method->close) |
112 |
chan->method->close(chan->fd, chan->data); |
chan->method->close(chan->fd, chan->data); |
113 |
|
FD_CLR(chan->fd, &chan->method->fdset); |
114 |
|
chan->method->fd_max = -2; |
115 |
} |
} |
116 |
|
|
117 |
static int |
static int |
162 |
CHANNEL *p = list_locate(input->channels, &fd, _channel_cmp_fd); |
CHANNEL *p = list_locate(input->channels, &fd, _channel_cmp_fd); |
163 |
|
|
164 |
if (p) { |
if (p) { |
165 |
efree(p); |
channel_close(p); |
166 |
list_remove_current(input->channels); |
list_remove_current(input->channels); |
167 |
} |
} |
168 |
} |
} |
189 |
clos.data = data; |
clos.data = data; |
190 |
p = list_locate(input->channels, &clos, _channel_cmp); |
p = list_locate(input->channels, &clos, _channel_cmp); |
191 |
if (p) { |
if (p) { |
192 |
|
channel_close(p); |
193 |
efree(p); |
efree(p); |
194 |
list_remove_current(input->channels); |
list_remove_current(input->channels); |
195 |
} |
} |
198 |
int |
int |
199 |
input_select(INPUT *input, struct timeval *tv) |
input_select(INPUT *input, struct timeval *tv) |
200 |
{ |
{ |
201 |
CHANNEL *p; |
METHOD *m; |
|
fd_set readfds; |
|
|
int max_fd = 0; |
|
202 |
int status; |
int status; |
|
|
|
|
FD_ZERO(&readfds); |
|
203 |
|
|
204 |
for (p = list_first(input->channels); p; |
for (m = list_first(input->methods); m; |
205 |
p = list_next(input->channels)) { |
m = list_next(input->methods)) { |
206 |
FD_SET(p->fd, &readfds); |
CHANNEL *p; |
207 |
if (p->fd > max_fd) |
fd_set readfds; |
208 |
max_fd = p->fd; |
|
209 |
} |
if (m->fd_max == -2) { |
210 |
|
for (p = list_first(input->channels); p; |
211 |
|
p = list_next(input->channels)) { |
212 |
|
if (p->method == m && p->fd > m->fd_max) |
213 |
|
m->fd_max = p->fd; |
214 |
|
} |
215 |
|
if (m->fd_max == -2) |
216 |
|
m->fd_max = -1; |
217 |
|
} |
218 |
|
|
219 |
status = select(max_fd + 1, &readfds, NULL, NULL, tv); |
if (m->fd_max < 0) |
220 |
|
continue; |
221 |
|
|
222 |
|
readfds = m->fdset; |
223 |
|
|
224 |
|
status = select(m->fd_max + 1, &readfds, NULL, NULL, tv); |
225 |
|
|
226 |
if (status == -1) { |
if (status == -1) { |
227 |
if (errno == EINTR) |
if (errno == EINTR) |
228 |
return 0; |
return 0; |
229 |
} else if (status > 0) { |
} else if (status > 0) { |
230 |
for (p = list_first(input->channels); p; |
for (p = list_first(input->channels); p; |
231 |
p = list_next(input->channels)) { |
p = list_next(input->channels)) { |
232 |
if (FD_ISSET(p->fd, &readfds)) |
if (FD_ISSET(p->fd, &readfds)) |
233 |
channel_handle(p); |
channel_handle(p); |
234 |
} |
} |
235 |
|
} |
236 |
} |
} |
237 |
return status; |
return status; |
238 |
} |
} |