]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /* |
2 | * C wrapper for poll(). | |
3 | */ | |
4 | ||
5 | #define _GNU_SOURCE | |
6 | #include <errno.h> | |
7 | #include <string.h> | |
8 | #include <stdio.h> | |
9 | #include <poll.h> | |
10 | #include <time.h> | |
11 | ||
12 | #include "duktape.h" | |
13 | ||
14 | static int poll_poll(duk_context *ctx) { | |
15 | int timeout = duk_to_int(ctx, 1); | |
16 | int i, n, nchanged; | |
17 | int fd, rc; | |
18 | struct pollfd fds[20]; | |
19 | struct timespec ts; | |
20 | ||
21 | memset(fds, 0, sizeof(fds)); | |
22 | ||
23 | n = 0; | |
24 | duk_enum(ctx, 0, 0 /*enum_flags*/); | |
25 | while (duk_next(ctx, -1, 0)) { | |
26 | if ((size_t) n >= sizeof(fds) / sizeof(struct pollfd)) { | |
27 | return -1; | |
28 | } | |
29 | ||
30 | /* [... enum key] */ | |
31 | duk_dup_top(ctx); /* -> [... enum key key] */ | |
32 | duk_get_prop(ctx, 0); /* -> [... enum key val] */ | |
33 | fd = duk_to_int(ctx, -2); | |
34 | ||
35 | duk_push_string(ctx, "events"); | |
36 | duk_get_prop(ctx, -2); /* -> [... enum key val events] */ | |
37 | ||
38 | fds[n].fd = fd; | |
39 | fds[n].events = duk_to_int(ctx, -1); | |
40 | fds[n].revents = 0; | |
41 | ||
42 | duk_pop_n(ctx, 3); /* -> [... enum] */ | |
43 | ||
44 | n++; | |
45 | } | |
46 | /* leave enum on stack */ | |
47 | ||
48 | memset(&ts, 0, sizeof(ts)); | |
49 | ts.tv_nsec = (timeout % 1000) * 1000000; | |
50 | ts.tv_sec = timeout / 1000; | |
51 | ||
52 | /*rc = ppoll(fds, n, &ts, NULL);*/ | |
53 | rc = poll(fds, n, timeout); | |
54 | if (rc < 0) { | |
55 | duk_error(ctx, DUK_ERR_ERROR, "%s (errno=%d)", strerror(errno), errno); | |
56 | } | |
57 | ||
58 | duk_push_array(ctx); | |
59 | nchanged = 0; | |
60 | for (i = 0; i < n; i++) { | |
61 | /* update revents */ | |
62 | ||
63 | if (fds[i].revents) { | |
64 | duk_push_int(ctx, fds[i].fd); /* -> [... retarr fd] */ | |
65 | duk_put_prop_index(ctx, -2, nchanged); | |
66 | nchanged++; | |
67 | } | |
68 | ||
69 | duk_push_int(ctx, fds[i].fd); /* -> [... retarr key] */ | |
70 | duk_get_prop(ctx, 0); /* -> [... retarr val] */ | |
71 | duk_push_string(ctx, "revents"); | |
72 | duk_push_int(ctx, fds[i].revents); /* -> [... retarr val "revents" fds[i].revents] */ | |
73 | duk_put_prop(ctx, -3); /* -> [... retarr val] */ | |
74 | duk_pop(ctx); | |
75 | } | |
76 | ||
77 | /* [retarr] */ | |
78 | ||
79 | return 1; | |
80 | } | |
81 | ||
82 | static duk_function_list_entry poll_funcs[] = { | |
83 | { "poll", poll_poll, 2 }, | |
84 | { NULL, NULL, 0 } | |
85 | }; | |
86 | ||
87 | static duk_number_list_entry poll_consts[] = { | |
88 | { "POLLIN", (double) POLLIN }, | |
89 | { "POLLPRI", (double) POLLPRI }, | |
90 | { "POLLOUT", (double) POLLOUT }, | |
91 | #if 0 | |
92 | /* Linux 2.6.17 and upwards, requires _GNU_SOURCE etc, not added | |
93 | * now because we don't use it. | |
94 | */ | |
95 | { "POLLRDHUP", (double) POLLRDHUP }, | |
96 | #endif | |
97 | { "POLLERR", (double) POLLERR }, | |
98 | { "POLLHUP", (double) POLLHUP }, | |
99 | { "POLLNVAL", (double) POLLNVAL }, | |
100 | { NULL, 0.0 } | |
101 | }; | |
102 | ||
103 | void poll_register(duk_context *ctx) { | |
104 | /* Set global 'Poll' with functions and constants. */ | |
105 | duk_push_global_object(ctx); | |
106 | duk_push_object(ctx); | |
107 | duk_put_function_list(ctx, -1, poll_funcs); | |
108 | duk_put_number_list(ctx, -1, poll_consts); | |
109 | duk_put_prop_string(ctx, -2, "Poll"); | |
110 | duk_pop(ctx); | |
111 | } |