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