| /* |
| * C wrapper for poll(). |
| */ |
| |
| #define _GNU_SOURCE |
| #include <errno.h> |
| #include <string.h> |
| #include <stdio.h> |
| #include <poll.h> |
| #include <time.h> |
| |
| #include "duktape.h" |
| |
| static int poll_poll(duk_context *ctx) { |
| int timeout = duk_to_int(ctx, 1); |
| int i, n, nchanged; |
| int fd, rc; |
| struct pollfd fds[20]; |
| struct timespec ts; |
| |
| memset(fds, 0, sizeof(fds)); |
| |
| n = 0; |
| duk_enum(ctx, 0, 0 /*enum_flags*/); |
| while (duk_next(ctx, -1, 0)) { |
| if ((size_t) n >= sizeof(fds) / sizeof(struct pollfd)) { |
| return -1; |
| } |
| |
| /* [... enum key] */ |
| duk_dup_top(ctx); /* -> [... enum key key] */ |
| duk_get_prop(ctx, 0); /* -> [... enum key val] */ |
| fd = duk_to_int(ctx, -2); |
| |
| duk_push_string(ctx, "events"); |
| duk_get_prop(ctx, -2); /* -> [... enum key val events] */ |
| |
| fds[n].fd = fd; |
| fds[n].events = duk_to_int(ctx, -1); |
| fds[n].revents = 0; |
| |
| duk_pop_n(ctx, 3); /* -> [... enum] */ |
| |
| n++; |
| } |
| /* leave enum on stack */ |
| |
| memset(&ts, 0, sizeof(ts)); |
| ts.tv_nsec = (timeout % 1000) * 1000000; |
| ts.tv_sec = timeout / 1000; |
| |
| /*rc = ppoll(fds, n, &ts, NULL);*/ |
| rc = poll(fds, n, timeout); |
| if (rc < 0) { |
| duk_error(ctx, DUK_ERR_ERROR, "%s (errno=%d)", strerror(errno), errno); |
| } |
| |
| duk_push_array(ctx); |
| nchanged = 0; |
| for (i = 0; i < n; i++) { |
| /* update revents */ |
| |
| if (fds[i].revents) { |
| duk_push_int(ctx, fds[i].fd); /* -> [... retarr fd] */ |
| duk_put_prop_index(ctx, -2, nchanged); |
| nchanged++; |
| } |
| |
| duk_push_int(ctx, fds[i].fd); /* -> [... retarr key] */ |
| duk_get_prop(ctx, 0); /* -> [... retarr val] */ |
| duk_push_string(ctx, "revents"); |
| duk_push_int(ctx, fds[i].revents); /* -> [... retarr val "revents" fds[i].revents] */ |
| duk_put_prop(ctx, -3); /* -> [... retarr val] */ |
| duk_pop(ctx); |
| } |
| |
| /* [retarr] */ |
| |
| return 1; |
| } |
| |
| static duk_function_list_entry poll_funcs[] = { |
| { "poll", poll_poll, 2 }, |
| { NULL, NULL, 0 } |
| }; |
| |
| static duk_number_list_entry poll_consts[] = { |
| { "POLLIN", (double) POLLIN }, |
| { "POLLPRI", (double) POLLPRI }, |
| { "POLLOUT", (double) POLLOUT }, |
| #if 0 |
| /* Linux 2.6.17 and upwards, requires _GNU_SOURCE etc, not added |
| * now because we don't use it. |
| */ |
| { "POLLRDHUP", (double) POLLRDHUP }, |
| #endif |
| { "POLLERR", (double) POLLERR }, |
| { "POLLHUP", (double) POLLHUP }, |
| { "POLLNVAL", (double) POLLNVAL }, |
| { NULL, 0.0 } |
| }; |
| |
| void poll_register(duk_context *ctx) { |
| /* Set global 'Poll' with functions and constants. */ |
| duk_push_global_object(ctx); |
| duk_push_object(ctx); |
| duk_put_function_list(ctx, -1, poll_funcs); |
| duk_put_number_list(ctx, -1, poll_consts); |
| duk_put_prop_string(ctx, -2, "Poll"); |
| duk_pop(ctx); |
| } |