• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/libubox/lua/uloop.c

  1 /*
  2  * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
  3  *
  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.
  7  *
  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.
 15  */
 16 #include <stdio.h>
 17 #include <string.h>
 18 #include <stdlib.h>
 19 #include <unistd.h>
 20 
 21 #include <lua.h>
 22 #include <lualib.h>
 23 #include <lauxlib.h>
 24 
 25 #include "../uloop.h"
 26 #include "../list.h"
 27 
 28 struct lua_uloop_fd {
 29         struct uloop_fd fd;
 30         int r;
 31         int fd_r;
 32 };
 33 
 34 struct lua_uloop_timeout {
 35         struct uloop_timeout t;
 36         int r;
 37 };
 38 
 39 struct lua_uloop_process {
 40         struct uloop_process p;
 41         int r;
 42 };
 43 
 44 struct lua_uloop_interval {
 45         struct uloop_interval i;
 46         int r;
 47 };
 48 
 49 struct lua_uloop_signal {
 50         struct uloop_signal s;
 51         int r;
 52 };
 53 
 54 static lua_State *state;
 55 
 56 static void *
 57 ul_create_userdata(lua_State *L, size_t size, const luaL_Reg *reg, lua_CFunction gc)
 58 {
 59         void *ret = lua_newuserdata(L, size);
 60 
 61         memset(ret, 0, size);
 62         lua_createtable(L, 0, 2);
 63         lua_pushvalue(L, -1);
 64         lua_setfield(L, -2, "__index");
 65         lua_pushcfunction(L, gc);
 66         lua_setfield(L, -2, "__gc");
 67         lua_pushvalue(L, -1);
 68         lua_setmetatable(L, -3);
 69         lua_pushvalue(L, -2);
 70         luaI_openlib(L, NULL, reg, 1);
 71         lua_pushvalue(L, -2);
 72 
 73         return ret;
 74 }
 75 
 76 static void ul_timer_cb(struct uloop_timeout *t)
 77 {
 78         struct lua_uloop_timeout *tout = container_of(t, struct lua_uloop_timeout, t);
 79 
 80         lua_getglobal(state, "__uloop_cb");
 81         lua_rawgeti(state, -1, tout->r);
 82         lua_remove(state, -2);
 83 
 84         lua_call(state, 0, 0);
 85 
 86 }
 87 
 88 static int ul_timer_set(lua_State *L)
 89 {
 90         struct lua_uloop_timeout *tout;
 91         double set;
 92 
 93         if (!lua_isnumber(L, -1)) {
 94                 lua_pushstring(L, "invalid arg list");
 95                 lua_error(L);
 96 
 97                 return 0;
 98         }
 99 
100         set = lua_tointeger(L, -1);
101         tout = lua_touserdata(L, 1);
102         uloop_timeout_set(&tout->t, set);
103 
104         return 1;
105 }
106 
107 static int ul_timer_remaining(lua_State *L)
108 {
109         struct lua_uloop_timeout *tout;
110 
111         tout = lua_touserdata(L, 1);
112         lua_pushnumber(L, uloop_timeout_remaining64(&tout->t));
113         return 1;
114 }
115 
116 static int ul_timer_free(lua_State *L)
117 {
118         struct lua_uloop_timeout *tout = lua_touserdata(L, 1);
119 
120         uloop_timeout_cancel(&tout->t);
121 
122         /* obj.__index.__gc = nil , make sure executing only once*/
123         lua_getfield(L, -1, "__index");
124         lua_pushstring(L, "__gc");
125         lua_pushnil(L);
126         lua_settable(L, -3);
127 
128         lua_getglobal(state, "__uloop_cb");
129         luaL_unref(state, -1, tout->r);
130 
131         return 1;
132 }
133 
134 static const luaL_Reg timer_m[] = {
135         { "set", ul_timer_set },
136         { "remaining", ul_timer_remaining },
137         { "cancel", ul_timer_free },
138         { NULL, NULL }
139 };
140 
141 static int ul_timer(lua_State *L)
142 {
143         struct lua_uloop_timeout *tout;
144         int set = 0;
145         int ref;
146 
147         if (lua_isnumber(L, -1)) {
148                 set = lua_tointeger(L, -1);
149                 lua_pop(L, 1);
150         }
151 
152         if (!lua_isfunction(L, -1)) {
153                 lua_pushstring(L, "invalid arg list");
154                 lua_error(L);
155 
156                 return 0;
157         }
158 
159         lua_getglobal(L, "__uloop_cb");
160         lua_pushvalue(L, -2);
161         ref = luaL_ref(L, -2);
162 
163         tout = ul_create_userdata(L, sizeof(*tout), timer_m, ul_timer_free);
164         tout->r = ref;
165         tout->t.cb = ul_timer_cb;
166 
167         if (set)
168                 uloop_timeout_set(&tout->t, set);
169 
170         return 1;
171 }
172 
173 static void ul_ufd_cb(struct uloop_fd *fd, unsigned int events)
174 {
175         struct lua_uloop_fd *ufd = container_of(fd, struct lua_uloop_fd, fd);
176 
177         lua_getglobal(state, "__uloop_cb");
178         lua_rawgeti(state, -1, ufd->r);
179         lua_remove(state, -2);
180 
181         /* push fd object */
182         lua_getglobal(state, "__uloop_fds");
183         lua_rawgeti(state, -1, ufd->fd_r);
184         lua_remove(state, -2);
185 
186         /* push events */
187         lua_pushinteger(state, events);
188         lua_call(state, 2, 0);
189 }
190 
191 
192 static int get_sock_fd(lua_State* L, int idx) {
193         int fd;
194         if(lua_isnumber(L, idx)) {
195                 fd = lua_tonumber(L, idx);
196         } else {
197                 luaL_checktype(L, idx, LUA_TUSERDATA);
198                 lua_getfield(L, idx, "getfd");
199                 if(lua_isnil(L, -1))
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);
203                 lua_call(L, 1, 1);
204                 fd = lua_tointeger(L, -1);
205                 lua_pop(L, 1);
206         }
207         return fd;
208 }
209 
210 static int ul_ufd_delete(lua_State *L)
211 {
212         struct lua_uloop_fd *ufd = lua_touserdata(L, 1);
213 
214         uloop_fd_delete(&ufd->fd);
215 
216         /* obj.__index.__gc = nil , make sure executing only once*/
217         lua_getfield(L, -1, "__index");
218         lua_pushstring(L, "__gc");
219         lua_pushnil(L);
220         lua_settable(L, -3);
221 
222         lua_getglobal(state, "__uloop_cb");
223         luaL_unref(state, -1, ufd->r);
224         lua_remove(state, -1);
225 
226         lua_getglobal(state, "__uloop_fds");
227         luaL_unref(state, -1, ufd->fd_r);
228         lua_remove(state, -1);
229 
230         return 1;
231 }
232 
233 static const luaL_Reg ufd_m[] = {
234         { "delete", ul_ufd_delete },
235         { NULL, NULL }
236 };
237 
238 static int ul_ufd_add(lua_State *L)
239 {
240         struct lua_uloop_fd *ufd;
241         int fd = 0;
242         unsigned int flags = 0;
243         int ref;
244         int fd_ref;
245 
246         flags = luaL_checkinteger(L, 3);
247         if (!flags) {
248                 lua_pushstring(L, "flags cannot be zero");
249                 lua_error(L);
250         }
251 
252         luaL_checktype(L, 2, LUA_TFUNCTION);
253 
254         fd = get_sock_fd(L, 1);
255 
256         lua_getglobal(L, "__uloop_cb");
257         lua_pushvalue(L, 2);
258         ref = luaL_ref(L, -2);
259         lua_pop(L, 1);
260 
261         lua_getglobal(L, "__uloop_fds");
262         lua_pushvalue(L, 1);
263         fd_ref = luaL_ref(L, -2);
264         lua_pop(L, 1);
265 
266         ufd = ul_create_userdata(L, sizeof(*ufd), ufd_m, ul_ufd_delete);
267         ufd->r = ref;
268         ufd->fd.fd = fd;
269         ufd->fd_r = fd_ref;
270         ufd->fd.cb = ul_ufd_cb;
271         uloop_fd_add(&ufd->fd, flags);
272 
273         return 1;
274 }
275 
276 static int ul_process_free(lua_State *L)
277 {
278         struct lua_uloop_process *proc = lua_touserdata(L, 1);
279 
280         /* obj.__index.__gc = nil , make sure executing only once*/
281         lua_getfield(L, -1, "__index");
282         lua_pushstring(L, "__gc");
283         lua_pushnil(L);
284         lua_settable(L, -3);
285 
286         if (proc->r != LUA_NOREF) {
287                 uloop_process_delete(&proc->p);
288 
289                 lua_getglobal(state, "__uloop_cb");
290                 luaL_unref(state, -1, proc->r);
291                 lua_remove(state, -1);
292         }
293 
294         return 1;
295 }
296 
297 static int ul_process_pid(lua_State *L)
298 {
299         struct lua_uloop_process *proc = lua_touserdata(L, 1);
300 
301         if (proc->p.pid) {
302                 lua_pushnumber(L, proc->p.pid);
303                 return 1;
304         }
305 
306         return 0;
307 }
308 
309 static const luaL_Reg process_m[] = {
310         { "delete", ul_process_free },
311         { "pid", ul_process_pid },
312         { NULL, NULL }
313 };
314 
315 static void ul_process_cb(struct uloop_process *p, int ret)
316 {
317         struct lua_uloop_process *proc = container_of(p, struct lua_uloop_process, p);
318 
319         lua_getglobal(state, "__uloop_cb");
320         lua_rawgeti(state, -1, proc->r);
321 
322         luaL_unref(state, -2, proc->r);
323         proc->r = LUA_NOREF;
324         lua_remove(state, -2);
325         lua_pushinteger(state, ret >> 8);
326         lua_call(state, 1, 0);
327 }
328 
329 static int ul_process(lua_State *L)
330 {
331         struct lua_uloop_process *proc;
332         pid_t pid;
333         int ref;
334 
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");
338                 lua_error(L);
339 
340                 return 0;
341         }
342 
343         pid = fork();
344 
345         if (pid == -1) {
346                 lua_pushstring(L, "failed to fork");
347                 lua_error(L);
348 
349                 return 0;
350         }
351 
352         if (pid == 0) {
353                 /* child */
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));
358                 int i = 1;
359 
360                 if (!argp || !envp)
361                         _exit(-1);
362 
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);
367                         lua_pop(L, 1);
368                 }
369                 argp[i] = NULL;
370 
371                 for (i = 1; i <= envn; i++) {
372                         lua_rawgeti(L, -2, i);
373                         envp[i - 1] = (char*) lua_tostring(L, -1);
374                         lua_pop(L, 1);
375                 }
376                 envp[i - 1] = NULL;
377 
378                 execve(*argp, argp, envp);
379                 _exit(-1);
380         }
381 
382         lua_getglobal(L, "__uloop_cb");
383         lua_pushvalue(L, -2);
384         ref = luaL_ref(L, -2);
385 
386         proc = ul_create_userdata(L, sizeof(*proc), process_m, ul_process_free);
387         proc->r = ref;
388         proc->p.pid = pid;
389         proc->p.cb = ul_process_cb;
390         uloop_process_add(&proc->p);
391 
392         return 1;
393 }
394 
395 static void ul_interval_cb(struct uloop_interval *i)
396 {
397         struct lua_uloop_interval *intv = container_of(i, struct lua_uloop_interval, i);
398 
399         lua_getglobal(state, "__uloop_cb");
400         lua_rawgeti(state, -1, intv->r);
401         lua_remove(state, -2);
402 
403         lua_call(state, 0, 0);
404 }
405 
406 static int ul_interval_set(lua_State *L)
407 {
408         struct lua_uloop_interval *intv;
409         double set;
410 
411         if (!lua_isnumber(L, -1)) {
412                 lua_pushstring(L, "invalid arg list");
413                 lua_error(L);
414 
415                 return 0;
416         }
417 
418         set = lua_tointeger(L, -1);
419         intv = lua_touserdata(L, 1);
420         uloop_interval_set(&intv->i, set);
421 
422         return 1;
423 }
424 
425 static int ul_interval_expirations(lua_State *L)
426 {
427         struct lua_uloop_interval *intv;
428 
429         intv = lua_touserdata(L, 1);
430         lua_pushinteger(L, intv->i.expirations);
431         return 1;
432 }
433 
434 static int ul_interval_remaining(lua_State *L)
435 {
436         struct lua_uloop_interval *intv;
437 
438         intv = lua_touserdata(L, 1);
439         lua_pushnumber(L, uloop_interval_remaining(&intv->i));
440         return 1;
441 }
442 
443 static int ul_interval_free(lua_State *L)
444 {
445         struct lua_uloop_interval *intv = lua_touserdata(L, 1);
446 
447         uloop_interval_cancel(&intv->i);
448 
449         /* obj.__index.__gc = nil , make sure executing only once*/
450         lua_getfield(L, -1, "__index");
451         lua_pushstring(L, "__gc");
452         lua_pushnil(L);
453         lua_settable(L, -3);
454 
455         lua_getglobal(state, "__uloop_cb");
456         luaL_unref(state, -1, intv->r);
457 
458         return 1;
459 }
460 
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 },
466         { NULL, NULL }
467 };
468 
469 static int ul_interval(lua_State *L)
470 {
471         struct lua_uloop_interval *intv;
472         unsigned int set = 0;
473         int ref;
474 
475         if (lua_isnumber(L, -1)) {
476                 set = lua_tointeger(L, -1);
477                 lua_pop(L, 1);
478         }
479 
480         if (!lua_isfunction(L, -1)) {
481                 lua_pushstring(L, "invalid arg list");
482                 lua_error(L);
483 
484                 return 0;
485         }
486 
487         lua_getglobal(L, "__uloop_cb");
488         lua_pushvalue(L, -2);
489         ref = luaL_ref(L, -2);
490 
491         intv = ul_create_userdata(L, sizeof(*intv), interval_m, ul_interval_free);
492         intv->r = ref;
493         intv->i.cb = ul_interval_cb;
494 
495         if (set)
496                 uloop_interval_set(&intv->i, set);
497 
498         return 1;
499 }
500 
501 static void ul_signal_cb(struct uloop_signal *s)
502 {
503         struct lua_uloop_signal *sig = container_of(s, struct lua_uloop_signal, s);
504 
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);
509 
510         lua_call(state, 1, 0);
511 }
512 
513 static int ul_signal_signo(lua_State *L)
514 {
515         struct lua_uloop_signal *sig = lua_touserdata(L, 1);
516 
517         lua_pushinteger(L, sig->s.signo);
518 
519         return 1;
520 }
521 
522 static int ul_signal_free(lua_State *L)
523 {
524         struct lua_uloop_signal *sig = lua_touserdata(L, 1);
525 
526         uloop_signal_delete(&sig->s);
527 
528         /* obj.__index.__gc = nil , make sure executing only once*/
529         lua_getfield(L, -1, "__index");
530         lua_pushstring(L, "__gc");
531         lua_pushnil(L);
532         lua_settable(L, -3);
533 
534         lua_getglobal(state, "__uloop_cb");
535         luaL_unref(state, -1, sig->r);
536 
537         return 1;
538 }
539 
540 static const luaL_Reg signal_m[] = {
541         { "signo", ul_signal_signo },
542         { "delete", ul_signal_free },
543         { NULL, NULL }
544 };
545 
546 static int ul_signal(lua_State *L)
547 {
548         struct lua_uloop_signal *sig;
549         int signo = -1;
550         int ref;
551 
552         if (lua_isnumber(L, -1)) {
553                 signo = lua_tointeger(L, -1);
554                 lua_pop(L, 1);
555         }
556 
557         if (!lua_isfunction(L, -1) || signo <= 0 || signo > NSIG) {
558                 lua_pushstring(L, "invalid arg list");
559                 lua_error(L);
560 
561                 return 0;
562         }
563 
564         lua_getglobal(L, "__uloop_cb");
565         lua_pushvalue(L, -2);
566         ref = luaL_ref(L, -2);
567 
568         sig = ul_create_userdata(L, sizeof(*sig), signal_m, ul_signal_free);
569         sig->r = ref;
570         sig->s.cb = ul_signal_cb;
571         sig->s.signo = signo;
572 
573         uloop_signal_add(&sig->s);
574 
575         return 1;
576 }
577 
578 static int ul_init(lua_State *L)
579 {
580         uloop_init();
581         lua_pushboolean(L, 1);
582 
583         return 1;
584 }
585 
586 static int ul_run(lua_State *L)
587 {
588         uloop_run();
589         lua_pushboolean(L, 1);
590 
591         return 1;
592 }
593 
594 static int ul_end(lua_State *L)
595 {
596         uloop_end();
597         return 1;
598 }
599 
600 static luaL_reg uloop_func[] = {
601         {"init", ul_init},
602         {"run", ul_run},
603         {"timer", ul_timer},
604         {"process", ul_process},
605         {"fd_add", ul_ufd_add},
606         {"interval", ul_interval},
607         {"signal", ul_signal},
608         {"cancel", ul_end},
609         {NULL, NULL},
610 };
611 
612 /* avoid warnings about missing declarations */
613 int luaopen_uloop(lua_State *L);
614 int luaclose_uloop(lua_State *L);
615 
616 int luaopen_uloop(lua_State *L)
617 {
618         state = L;
619 
620         lua_createtable(L, 1, 0);
621         lua_setglobal(L, "__uloop_cb");
622 
623         lua_createtable(L, 1, 0);
624         lua_setglobal(L, "__uloop_fds");
625 
626         luaL_openlib(L, "uloop", uloop_func, 0);
627         lua_pushstring(L, "_VERSION");
628         lua_pushstring(L, "1.0");
629         lua_rawset(L, -3);
630 
631         lua_pushstring(L, "ULOOP_READ");
632         lua_pushinteger(L, ULOOP_READ);
633         lua_rawset(L, -3);
634 
635         lua_pushstring(L, "ULOOP_WRITE");
636         lua_pushinteger(L, ULOOP_WRITE);
637         lua_rawset(L, -3);
638 
639         lua_pushstring(L, "ULOOP_EDGE_TRIGGER");
640         lua_pushinteger(L, ULOOP_EDGE_TRIGGER);
641         lua_rawset(L, -3);
642 
643         lua_pushstring(L, "ULOOP_BLOCKING");
644         lua_pushinteger(L, ULOOP_BLOCKING);
645         lua_rawset(L, -3);
646 
647 #define SIGNAME_CONST(signame) do { \
648         lua_pushstring(L, #signame);    \
649         lua_pushinteger(L, signame);    \
650         lua_rawset(L, -3);                  \
651 } while(0)
652 
653 #if defined(SIGINT)
654         SIGNAME_CONST(SIGINT);
655 #endif
656 #if defined(SIGILL)
657         SIGNAME_CONST(SIGILL);
658 #endif
659 #if defined(SIGABRT)
660         SIGNAME_CONST(SIGABRT);
661 #endif
662 #if defined(SIGFPE)
663         SIGNAME_CONST(SIGFPE);
664 #endif
665 #if defined(SIGSEGV)
666         SIGNAME_CONST(SIGSEGV);
667 #endif
668 #if defined(SIGTERM)
669         SIGNAME_CONST(SIGTERM);
670 #endif
671 #if defined(SIGHUP)
672         SIGNAME_CONST(SIGHUP);
673 #endif
674 #if defined(SIGQUIT)
675         SIGNAME_CONST(SIGQUIT);
676 #endif
677 #if defined(SIGTRAP)
678         SIGNAME_CONST(SIGTRAP);
679 #endif
680 #if defined(SIGKILL)
681         SIGNAME_CONST(SIGKILL);
682 #endif
683 #if defined(SIGPIPE)
684         SIGNAME_CONST(SIGPIPE);
685 #endif
686 #if defined(SIGALRM)
687         SIGNAME_CONST(SIGALRM);
688 #endif
689 #if defined(SIGSTKFLT)
690         SIGNAME_CONST(SIGSTKFLT);
691 #endif
692 #if defined(SIGPWR)
693         SIGNAME_CONST(SIGPWR);
694 #endif
695 #if defined(SIGBUS)
696         SIGNAME_CONST(SIGBUS);
697 #endif
698 #if defined(SIGSYS)
699         SIGNAME_CONST(SIGSYS);
700 #endif
701 #if defined(SIGURG)
702         SIGNAME_CONST(SIGURG);
703 #endif
704 #if defined(SIGSTOP)
705         SIGNAME_CONST(SIGSTOP);
706 #endif
707 #if defined(SIGTSTP)
708         SIGNAME_CONST(SIGTSTP);
709 #endif
710 #if defined(SIGCONT)
711         SIGNAME_CONST(SIGCONT);
712 #endif
713 #if defined(SIGCHLD)
714         SIGNAME_CONST(SIGCHLD);
715 #endif
716 #if defined(SIGTTIN)
717         SIGNAME_CONST(SIGTTIN);
718 #endif
719 #if defined(SIGTTOU)
720         SIGNAME_CONST(SIGTTOU);
721 #endif
722 #if defined(SIGPOLL)
723         SIGNAME_CONST(SIGPOLL);
724 #endif
725 #if defined(SIGXFSZ)
726         SIGNAME_CONST(SIGXFSZ);
727 #endif
728 #if defined(SIGXCPU)
729         SIGNAME_CONST(SIGXCPU);
730 #endif
731 #if defined(SIGVTALRM)
732         SIGNAME_CONST(SIGVTALRM);
733 #endif
734 #if defined(SIGPROF)
735         SIGNAME_CONST(SIGPROF);
736 #endif
737 #if defined(SIGUSR1)
738         SIGNAME_CONST(SIGUSR1);
739 #endif
740 #if defined(SIGUSR2)
741         SIGNAME_CONST(SIGUSR2);
742 #endif
743 
744         return 1;
745 }
746 
747 int luaclose_uloop(lua_State *L)
748 {
749         lua_pushstring(L, "Called");
750 
751         return 1;
752 }
753 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt