2 * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
34 struct lua_uloop_timeout
{
35 struct uloop_timeout t
;
39 struct lua_uloop_process
{
40 struct uloop_process p
;
44 struct lua_uloop_interval
{
45 struct uloop_interval i
;
49 struct lua_uloop_signal
{
50 struct uloop_signal s
;
54 static lua_State
*state
;
57 ul_create_userdata(lua_State
*L
, size_t size
, const luaL_Reg
*reg
, lua_CFunction gc
)
59 void *ret
= lua_newuserdata(L
, size
);
62 lua_createtable(L
, 0, 2);
64 lua_setfield(L
, -2, "__index");
65 lua_pushcfunction(L
, gc
);
66 lua_setfield(L
, -2, "__gc");
68 lua_setmetatable(L
, -3);
70 luaI_openlib(L
, NULL
, reg
, 1);
76 static void ul_timer_cb(struct uloop_timeout
*t
)
78 struct lua_uloop_timeout
*tout
= container_of(t
, struct lua_uloop_timeout
, t
);
80 lua_getglobal(state
, "__uloop_cb");
81 lua_rawgeti(state
, -1, tout
->r
);
82 lua_remove(state
, -2);
84 lua_call(state
, 0, 0);
88 static int ul_timer_set(lua_State
*L
)
90 struct lua_uloop_timeout
*tout
;
93 if (!lua_isnumber(L
, -1)) {
94 lua_pushstring(L
, "invalid arg list");
100 set
= lua_tointeger(L
, -1);
101 tout
= lua_touserdata(L
, 1);
102 uloop_timeout_set(&tout
->t
, set
);
107 static int ul_timer_remaining(lua_State
*L
)
109 struct lua_uloop_timeout
*tout
;
111 tout
= lua_touserdata(L
, 1);
112 lua_pushnumber(L
, uloop_timeout_remaining64(&tout
->t
));
116 static int ul_timer_free(lua_State
*L
)
118 struct lua_uloop_timeout
*tout
= lua_touserdata(L
, 1);
120 uloop_timeout_cancel(&tout
->t
);
122 /* obj.__index.__gc = nil , make sure executing only once*/
123 lua_getfield(L
, -1, "__index");
124 lua_pushstring(L
, "__gc");
128 lua_getglobal(state
, "__uloop_cb");
129 luaL_unref(state
, -1, tout
->r
);
134 static const luaL_Reg timer_m
[] = {
135 { "set", ul_timer_set
},
136 { "remaining", ul_timer_remaining
},
137 { "cancel", ul_timer_free
},
141 static int ul_timer(lua_State
*L
)
143 struct lua_uloop_timeout
*tout
;
147 if (lua_isnumber(L
, -1)) {
148 set
= lua_tointeger(L
, -1);
152 if (!lua_isfunction(L
, -1)) {
153 lua_pushstring(L
, "invalid arg list");
159 lua_getglobal(L
, "__uloop_cb");
160 lua_pushvalue(L
, -2);
161 ref
= luaL_ref(L
, -2);
163 tout
= ul_create_userdata(L
, sizeof(*tout
), timer_m
, ul_timer_free
);
165 tout
->t
.cb
= ul_timer_cb
;
168 uloop_timeout_set(&tout
->t
, set
);
173 static void ul_ufd_cb(struct uloop_fd
*fd
, unsigned int events
)
175 struct lua_uloop_fd
*ufd
= container_of(fd
, struct lua_uloop_fd
, fd
);
177 lua_getglobal(state
, "__uloop_cb");
178 lua_rawgeti(state
, -1, ufd
->r
);
179 lua_remove(state
, -2);
182 lua_getglobal(state
, "__uloop_fds");
183 lua_rawgeti(state
, -1, ufd
->fd_r
);
184 lua_remove(state
, -2);
187 lua_pushinteger(state
, events
);
188 lua_call(state
, 2, 0);
192 static int get_sock_fd(lua_State
* L
, int idx
) {
194 if(lua_isnumber(L
, idx
)) {
195 fd
= lua_tonumber(L
, idx
);
197 luaL_checktype(L
, idx
, LUA_TUSERDATA
);
198 lua_getfield(L
, idx
, "getfd");
200 return luaL_error(L
, "socket type missing 'getfd' method");
201 /* if we have absolute, no need to adjust for getfield() call */
202 lua_pushvalue(L
, idx
> 0 ? idx
: idx
- 1);
204 fd
= lua_tointeger(L
, -1);
210 static int ul_ufd_delete(lua_State
*L
)
212 struct lua_uloop_fd
*ufd
= lua_touserdata(L
, 1);
214 uloop_fd_delete(&ufd
->fd
);
216 /* obj.__index.__gc = nil , make sure executing only once*/
217 lua_getfield(L
, -1, "__index");
218 lua_pushstring(L
, "__gc");
222 lua_getglobal(state
, "__uloop_cb");
223 luaL_unref(state
, -1, ufd
->r
);
224 lua_remove(state
, -1);
226 lua_getglobal(state
, "__uloop_fds");
227 luaL_unref(state
, -1, ufd
->fd_r
);
228 lua_remove(state
, -1);
233 static const luaL_Reg ufd_m
[] = {
234 { "delete", ul_ufd_delete
},
238 static int ul_ufd_add(lua_State
*L
)
240 struct lua_uloop_fd
*ufd
;
242 unsigned int flags
= 0;
246 flags
= luaL_checkinteger(L
, 3);
248 lua_pushstring(L
, "flags cannot be zero");
252 luaL_checktype(L
, 2, LUA_TFUNCTION
);
254 fd
= get_sock_fd(L
, 1);
256 lua_getglobal(L
, "__uloop_cb");
258 ref
= luaL_ref(L
, -2);
261 lua_getglobal(L
, "__uloop_fds");
263 fd_ref
= luaL_ref(L
, -2);
266 ufd
= ul_create_userdata(L
, sizeof(*ufd
), ufd_m
, ul_ufd_delete
);
270 ufd
->fd
.cb
= ul_ufd_cb
;
271 uloop_fd_add(&ufd
->fd
, flags
);
276 static int ul_process_free(lua_State
*L
)
278 struct lua_uloop_process
*proc
= lua_touserdata(L
, 1);
280 /* obj.__index.__gc = nil , make sure executing only once*/
281 lua_getfield(L
, -1, "__index");
282 lua_pushstring(L
, "__gc");
286 if (proc
->r
!= LUA_NOREF
) {
287 uloop_process_delete(&proc
->p
);
289 lua_getglobal(state
, "__uloop_cb");
290 luaL_unref(state
, -1, proc
->r
);
291 lua_remove(state
, -1);
297 static int ul_process_pid(lua_State
*L
)
299 struct lua_uloop_process
*proc
= lua_touserdata(L
, 1);
302 lua_pushnumber(L
, proc
->p
.pid
);
309 static const luaL_Reg process_m
[] = {
310 { "delete", ul_process_free
},
311 { "pid", ul_process_pid
},
315 static void ul_process_cb(struct uloop_process
*p
, int ret
)
317 struct lua_uloop_process
*proc
= container_of(p
, struct lua_uloop_process
, p
);
319 lua_getglobal(state
, "__uloop_cb");
320 lua_rawgeti(state
, -1, proc
->r
);
322 luaL_unref(state
, -2, proc
->r
);
324 lua_remove(state
, -2);
325 lua_pushinteger(state
, ret
>> 8);
326 lua_call(state
, 1, 0);
329 static int ul_process(lua_State
*L
)
331 struct lua_uloop_process
*proc
;
335 if (!lua_isfunction(L
, -1) || !lua_istable(L
, -2) ||
336 !lua_istable(L
, -3) || !lua_isstring(L
, -4)) {
337 lua_pushstring(L
, "invalid arg list");
346 lua_pushstring(L
, "failed to fork");
354 int argn
= lua_objlen(L
, -3);
355 int envn
= lua_objlen(L
, -2);
356 char** argp
= malloc(sizeof(char*) * (argn
+ 2));
357 char** envp
= malloc(sizeof(char*) * (envn
+ 1));
363 argp
[0] = (char*) lua_tostring(L
, -4);
364 for (i
= 1; i
<= argn
; i
++) {
365 lua_rawgeti(L
, -3, i
);
366 argp
[i
] = (char*) lua_tostring(L
, -1);
371 for (i
= 1; i
<= envn
; i
++) {
372 lua_rawgeti(L
, -2, i
);
373 envp
[i
- 1] = (char*) lua_tostring(L
, -1);
378 execve(*argp
, argp
, envp
);
382 lua_getglobal(L
, "__uloop_cb");
383 lua_pushvalue(L
, -2);
384 ref
= luaL_ref(L
, -2);
386 proc
= ul_create_userdata(L
, sizeof(*proc
), process_m
, ul_process_free
);
389 proc
->p
.cb
= ul_process_cb
;
390 uloop_process_add(&proc
->p
);
395 static void ul_interval_cb(struct uloop_interval
*i
)
397 struct lua_uloop_interval
*intv
= container_of(i
, struct lua_uloop_interval
, i
);
399 lua_getglobal(state
, "__uloop_cb");
400 lua_rawgeti(state
, -1, intv
->r
);
401 lua_remove(state
, -2);
403 lua_call(state
, 0, 0);
406 static int ul_interval_set(lua_State
*L
)
408 struct lua_uloop_interval
*intv
;
411 if (!lua_isnumber(L
, -1)) {
412 lua_pushstring(L
, "invalid arg list");
418 set
= lua_tointeger(L
, -1);
419 intv
= lua_touserdata(L
, 1);
420 uloop_interval_set(&intv
->i
, set
);
425 static int ul_interval_expirations(lua_State
*L
)
427 struct lua_uloop_interval
*intv
;
429 intv
= lua_touserdata(L
, 1);
430 lua_pushinteger(L
, intv
->i
.expirations
);
434 static int ul_interval_remaining(lua_State
*L
)
436 struct lua_uloop_interval
*intv
;
438 intv
= lua_touserdata(L
, 1);
439 lua_pushnumber(L
, uloop_interval_remaining(&intv
->i
));
443 static int ul_interval_free(lua_State
*L
)
445 struct lua_uloop_interval
*intv
= lua_touserdata(L
, 1);
447 uloop_interval_cancel(&intv
->i
);
449 /* obj.__index.__gc = nil , make sure executing only once*/
450 lua_getfield(L
, -1, "__index");
451 lua_pushstring(L
, "__gc");
455 lua_getglobal(state
, "__uloop_cb");
456 luaL_unref(state
, -1, intv
->r
);
461 static const luaL_Reg interval_m
[] = {
462 { "set", ul_interval_set
},
463 { "expirations", ul_interval_expirations
},
464 { "remaining", ul_interval_remaining
},
465 { "cancel", ul_interval_free
},
469 static int ul_interval(lua_State
*L
)
471 struct lua_uloop_interval
*intv
;
472 unsigned int set
= 0;
475 if (lua_isnumber(L
, -1)) {
476 set
= lua_tointeger(L
, -1);
480 if (!lua_isfunction(L
, -1)) {
481 lua_pushstring(L
, "invalid arg list");
487 lua_getglobal(L
, "__uloop_cb");
488 lua_pushvalue(L
, -2);
489 ref
= luaL_ref(L
, -2);
491 intv
= ul_create_userdata(L
, sizeof(*intv
), interval_m
, ul_interval_free
);
493 intv
->i
.cb
= ul_interval_cb
;
496 uloop_interval_set(&intv
->i
, set
);
501 static void ul_signal_cb(struct uloop_signal
*s
)
503 struct lua_uloop_signal
*sig
= container_of(s
, struct lua_uloop_signal
, s
);
505 lua_getglobal(state
, "__uloop_cb");
506 lua_rawgeti(state
, -1, sig
->r
);
507 lua_remove(state
, -2);
508 lua_pushinteger(state
, sig
->s
.signo
);
510 lua_call(state
, 1, 0);
513 static int ul_signal_signo(lua_State
*L
)
515 struct lua_uloop_signal
*sig
= lua_touserdata(L
, 1);
517 lua_pushinteger(L
, sig
->s
.signo
);
522 static int ul_signal_free(lua_State
*L
)
524 struct lua_uloop_signal
*sig
= lua_touserdata(L
, 1);
526 uloop_signal_delete(&sig
->s
);
528 /* obj.__index.__gc = nil , make sure executing only once*/
529 lua_getfield(L
, -1, "__index");
530 lua_pushstring(L
, "__gc");
534 lua_getglobal(state
, "__uloop_cb");
535 luaL_unref(state
, -1, sig
->r
);
540 static const luaL_Reg signal_m
[] = {
541 { "signo", ul_signal_signo
},
542 { "delete", ul_signal_free
},
546 static int ul_signal(lua_State
*L
)
548 struct lua_uloop_signal
*sig
;
552 if (lua_isnumber(L
, -1)) {
553 signo
= lua_tointeger(L
, -1);
557 if (!lua_isfunction(L
, -1) || signo
<= 0 || signo
> NSIG
) {
558 lua_pushstring(L
, "invalid arg list");
564 lua_getglobal(L
, "__uloop_cb");
565 lua_pushvalue(L
, -2);
566 ref
= luaL_ref(L
, -2);
568 sig
= ul_create_userdata(L
, sizeof(*sig
), signal_m
, ul_signal_free
);
570 sig
->s
.cb
= ul_signal_cb
;
571 sig
->s
.signo
= signo
;
573 uloop_signal_add(&sig
->s
);
578 static int ul_init(lua_State
*L
)
581 lua_pushboolean(L
, 1);
586 static int ul_run(lua_State
*L
)
589 lua_pushboolean(L
, 1);
594 static int ul_end(lua_State
*L
)
600 static luaL_reg uloop_func
[] = {
604 {"process", ul_process
},
605 {"fd_add", ul_ufd_add
},
606 {"interval", ul_interval
},
607 {"signal", ul_signal
},
612 /* avoid warnings about missing declarations */
613 int luaopen_uloop(lua_State
*L
);
614 int luaclose_uloop(lua_State
*L
);
616 int luaopen_uloop(lua_State
*L
)
620 lua_createtable(L
, 1, 0);
621 lua_setglobal(L
, "__uloop_cb");
623 lua_createtable(L
, 1, 0);
624 lua_setglobal(L
, "__uloop_fds");
626 luaL_openlib(L
, "uloop", uloop_func
, 0);
627 lua_pushstring(L
, "_VERSION");
628 lua_pushstring(L
, "1.0");
631 lua_pushstring(L
, "ULOOP_READ");
632 lua_pushinteger(L
, ULOOP_READ
);
635 lua_pushstring(L
, "ULOOP_WRITE");
636 lua_pushinteger(L
, ULOOP_WRITE
);
639 lua_pushstring(L
, "ULOOP_EDGE_TRIGGER");
640 lua_pushinteger(L
, ULOOP_EDGE_TRIGGER
);
643 lua_pushstring(L
, "ULOOP_BLOCKING");
644 lua_pushinteger(L
, ULOOP_BLOCKING
);
647 #define SIGNAME_CONST(signame) do { \
648 lua_pushstring(L, #signame); \
649 lua_pushinteger(L, signame); \
654 SIGNAME_CONST(SIGINT
);
657 SIGNAME_CONST(SIGILL
);
660 SIGNAME_CONST(SIGABRT
);
663 SIGNAME_CONST(SIGFPE
);
666 SIGNAME_CONST(SIGSEGV
);
669 SIGNAME_CONST(SIGTERM
);
672 SIGNAME_CONST(SIGHUP
);
675 SIGNAME_CONST(SIGQUIT
);
678 SIGNAME_CONST(SIGTRAP
);
681 SIGNAME_CONST(SIGKILL
);
684 SIGNAME_CONST(SIGPIPE
);
687 SIGNAME_CONST(SIGALRM
);
689 #if defined(SIGSTKFLT)
690 SIGNAME_CONST(SIGSTKFLT
);
693 SIGNAME_CONST(SIGPWR
);
696 SIGNAME_CONST(SIGBUS
);
699 SIGNAME_CONST(SIGSYS
);
702 SIGNAME_CONST(SIGURG
);
705 SIGNAME_CONST(SIGSTOP
);
708 SIGNAME_CONST(SIGTSTP
);
711 SIGNAME_CONST(SIGCONT
);
714 SIGNAME_CONST(SIGCHLD
);
717 SIGNAME_CONST(SIGTTIN
);
720 SIGNAME_CONST(SIGTTOU
);
723 SIGNAME_CONST(SIGPOLL
);
726 SIGNAME_CONST(SIGXFSZ
);
729 SIGNAME_CONST(SIGXCPU
);
731 #if defined(SIGVTALRM)
732 SIGNAME_CONST(SIGVTALRM
);
735 SIGNAME_CONST(SIGPROF
);
738 SIGNAME_CONST(SIGUSR1
);
741 SIGNAME_CONST(SIGUSR2
);
747 int luaclose_uloop(lua_State
*L
)
749 lua_pushstring(L
, "Called");