|
4 | 4 | * |
5 | 5 | * SPDX-License-Identifier: BSD-3-Clause |
6 | 6 | */ |
7 | | -#include <sys/time.h> |
8 | | -#include <alloca.h> |
9 | 7 | #include <err.h> |
10 | 8 | #include <errno.h> |
11 | 9 | #include <fcntl.h> |
|
22 | 20 | #include "device_parser.h" |
23 | 21 | #include "fastboot.h" |
24 | 22 | #include "list.h" |
| 23 | +#include "watch.h" |
25 | 24 |
|
26 | | -static bool quit_invoked; |
27 | 25 | static const char *username; |
28 | 26 |
|
29 | 27 | struct device *selected_device; |
@@ -88,7 +86,7 @@ static void msg_select_board(const void *param) |
88 | 86 | selected_device = device_open(param, username, &fastboot_ops); |
89 | 87 | if (!selected_device) { |
90 | 88 | fprintf(stderr, "failed to open %s\n", (const char *)param); |
91 | | - quit_invoked = true; |
| 89 | + watch_quit(); |
92 | 90 | } |
93 | 91 |
|
94 | 92 | cdba_send(MSG_SELECT_BOARD); |
@@ -224,119 +222,14 @@ static int handle_stdin(int fd, void *buf) |
224 | 222 | return 0; |
225 | 223 | } |
226 | 224 |
|
227 | | -struct watch { |
228 | | - struct list_head node; |
229 | | - |
230 | | - int fd; |
231 | | - int (*cb)(int, void*); |
232 | | - void *data; |
233 | | -}; |
234 | | - |
235 | | -struct timer { |
236 | | - struct list_head node; |
237 | | - struct timeval tv; |
238 | | - |
239 | | - void (*cb)(void *); |
240 | | - void *data; |
241 | | -}; |
242 | | - |
243 | | -static struct list_head read_watches = LIST_INIT(read_watches); |
244 | | -static struct list_head timer_watches = LIST_INIT(timer_watches); |
245 | | - |
246 | | -void watch_add_readfd(int fd, int (*cb)(int, void*), void *data) |
247 | | -{ |
248 | | - struct watch *w; |
249 | | - |
250 | | - w = calloc(1, sizeof(*w)); |
251 | | - w->fd = fd; |
252 | | - w->cb = cb; |
253 | | - w->data = data; |
254 | | - |
255 | | - list_add(&read_watches, &w->node); |
256 | | -} |
257 | | - |
258 | | -void watch_timer_add(int timeout_ms, void (*cb)(void *), void *data) |
259 | | -{ |
260 | | - struct timeval tv_timeout; |
261 | | - struct timeval now; |
262 | | - struct timer *t; |
263 | | - |
264 | | - t = calloc(1, sizeof(*t)); |
265 | | - |
266 | | - gettimeofday(&now, NULL); |
267 | | - |
268 | | - tv_timeout.tv_sec = timeout_ms / 1000; |
269 | | - tv_timeout.tv_usec = (timeout_ms % 1000) * 1000; |
270 | | - |
271 | | - t->cb = cb; |
272 | | - t->data = data; |
273 | | - timeradd(&now, &tv_timeout, &t->tv); |
274 | | - |
275 | | - list_add(&timer_watches, &t->node); |
276 | | -} |
277 | | - |
278 | | -static struct timeval *watch_timer_next(void) |
279 | | -{ |
280 | | - static struct timeval timeout; |
281 | | - struct timeval now; |
282 | | - struct timer *next; |
283 | | - struct timer *t; |
284 | | - |
285 | | - if (list_empty(&timer_watches)) |
286 | | - return NULL; |
287 | | - |
288 | | - next = list_entry_first(&timer_watches, struct timer, node); |
289 | | - |
290 | | - list_for_each_entry(t, &timer_watches, node) { |
291 | | - if (timercmp(&t->tv, &next->tv, <)) |
292 | | - next = t; |
293 | | - } |
294 | | - |
295 | | - gettimeofday(&now, NULL); |
296 | | - timersub(&next->tv, &now, &timeout); |
297 | | - if (timeout.tv_sec < 0) { |
298 | | - timeout.tv_sec = 0; |
299 | | - timeout.tv_usec = 0; |
300 | | - } |
301 | | - |
302 | | - return &timeout; |
303 | | -} |
304 | | - |
305 | | -static void watch_timer_invoke(void) |
306 | | -{ |
307 | | - struct timeval now; |
308 | | - struct timer *tmp; |
309 | | - struct timer *t; |
310 | | - |
311 | | - gettimeofday(&now, NULL); |
312 | | - |
313 | | - list_for_each_entry_safe(t, tmp, &timer_watches, node) { |
314 | | - if (timercmp(&t->tv, &now, <)) { |
315 | | - t->cb(t->data); |
316 | | - |
317 | | - list_del(&t->node); |
318 | | - free(t); |
319 | | - } |
320 | | - } |
321 | | -} |
322 | | - |
323 | 225 | static void sigpipe_handler(int signo) |
324 | 226 | { |
325 | | - quit_invoked = true; |
326 | | -} |
327 | | - |
328 | | -void watch_quit(void) |
329 | | -{ |
330 | | - quit_invoked = true; |
| 227 | + watch_quit(); |
331 | 228 | } |
332 | 229 |
|
333 | 230 | int main(int argc, char **argv) |
334 | 231 | { |
335 | | - struct timeval *timeoutp; |
336 | | - struct watch *w; |
337 | | - fd_set rfds; |
338 | 232 | int flags; |
339 | | - int nfds; |
340 | 233 | int ret; |
341 | 234 |
|
342 | 235 | signal(SIGPIPE, sigpipe_handler); |
@@ -365,40 +258,7 @@ int main(int argc, char **argv) |
365 | 258 | flags = fcntl(STDIN_FILENO, F_GETFL, 0); |
366 | 259 | fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK); |
367 | 260 |
|
368 | | - while (!quit_invoked) { |
369 | | - nfds = 0; |
370 | | - |
371 | | - list_for_each_entry(w, &read_watches, node) { |
372 | | - nfds = MAX(nfds, w->fd); |
373 | | - FD_SET(w->fd, &rfds); |
374 | | - } |
375 | | - |
376 | | - if (!FD_ISSET(STDIN_FILENO, &rfds)) { |
377 | | - fprintf(stderr, "rfds is trash!\n"); |
378 | | - goto done; |
379 | | - } |
380 | | - |
381 | | - timeoutp = watch_timer_next(); |
382 | | - ret = select(nfds + 1, &rfds, NULL, NULL, timeoutp); |
383 | | - if (ret < 0 && errno == EINTR) |
384 | | - continue; |
385 | | - else if (ret < 0) |
386 | | - break; |
387 | | - |
388 | | - watch_timer_invoke(); |
389 | | - |
390 | | - list_for_each_entry(w, &read_watches, node) { |
391 | | - if (FD_ISSET(w->fd, &rfds)) { |
392 | | - ret = w->cb(w->fd, w->data); |
393 | | - if (ret < 0) { |
394 | | - fprintf(stderr, "cb returned %d\n", ret); |
395 | | - goto done; |
396 | | - } |
397 | | - } |
398 | | - } |
399 | | - } |
400 | | - |
401 | | -done: |
| 261 | + watch_run(); |
402 | 262 |
|
403 | 263 | /* if we got here, stdin/out/err might be not accessible anymore */ |
404 | 264 | ret = open("/dev/null", O_RDWR); |
|
0 commit comments