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 static lua_State *state; 45 46 static void * 47 ul_create_userdata(lua_State *L, size_t size, const luaL_Reg *reg, lua_CFunction gc) 48 { 49 void *ret = lua_newuserdata(L, size); 50 51 memset(ret, 0, size); 52 lua_createtable(L, 0, 2); 53 lua_pushvalue(L, -1); 54 lua_setfield(L, -2, "__index"); 55 lua_pushcfunction(L, gc); 56 lua_setfield(L, -2, "__gc"); 57 lua_pushvalue(L, -1); 58 lua_setmetatable(L, -3); 59 lua_pushvalue(L, -2); 60 luaI_openlib(L, NULL, reg, 1); 61 lua_pushvalue(L, -2); 62 63 return ret; 64 } 65 66 static void ul_timer_cb(struct uloop_timeout *t) 67 { 68 struct lua_uloop_timeout *tout = container_of(t, struct lua_uloop_timeout, t); 69 70 lua_getglobal(state, "__uloop_cb"); 71 lua_rawgeti(state, -1, tout->r); 72 lua_remove(state, -2); 73 74 lua_call(state, 0, 0); 75 76 } 77 78 static int ul_timer_set(lua_State *L) 79 { 80 struct lua_uloop_timeout *tout; 81 double set; 82 83 if (!lua_isnumber(L, -1)) { 84 lua_pushstring(L, "invalid arg list"); 85 lua_error(L); 86 87 return 0; 88 } 89 90 set = lua_tointeger(L, -1); 91 tout = lua_touserdata(L, 1); 92 uloop_timeout_set(&tout->t, set); 93 94 return 1; 95 } 96 97 static int ul_timer_remaining(lua_State *L) 98 { 99 struct lua_uloop_timeout *tout; 100 101 tout = lua_touserdata(L, 1); 102 lua_pushnumber(L, uloop_timeout_remaining64(&tout->t)); 103 return 1; 104 } 105 106 static int ul_timer_free(lua_State *L) 107 { 108 struct lua_uloop_timeout *tout = lua_touserdata(L, 1); 109 110 uloop_timeout_cancel(&tout->t); 111 112 /* obj.__index.__gc = nil , make sure executing only once*/ 113 lua_getfield(L, -1, "__index"); 114 lua_pushstring(L, "__gc"); 115 lua_pushnil(L); 116 lua_settable(L, -3); 117 118 lua_getglobal(state, "__uloop_cb"); 119 luaL_unref(state, -1, tout->r); 120 121 return 1; 122 } 123 124 static const luaL_Reg timer_m[] = { 125 { "set", ul_timer_set }, 126 { "remaining", ul_timer_remaining }, 127 { "cancel", ul_timer_free }, 128 { NULL, NULL } 129 }; 130 131 static int ul_timer(lua_State *L) 132 { 133 struct lua_uloop_timeout *tout; 134 int set = 0; 135 int ref; 136 137 if (lua_isnumber(L, -1)) { 138 set = lua_tointeger(L, -1); 139 lua_pop(L, 1); 140 } 141 142 if (!lua_isfunction(L, -1)) { 143 lua_pushstring(L, "invalid arg list"); 144 lua_error(L); 145 146 return 0; 147 } 148 149 lua_getglobal(L, "__uloop_cb"); 150 lua_pushvalue(L, -2); 151 ref = luaL_ref(L, -2); 152 153 tout = ul_create_userdata(L, sizeof(*tout), timer_m, ul_timer_free); 154 tout->r = ref; 155 tout->t.cb = ul_timer_cb; 156 157 if (set) 158 uloop_timeout_set(&tout->t, set); 159 160 return 1; 161 } 162 163 static void ul_ufd_cb(struct uloop_fd *fd, unsigned int events) 164 { 165 struct lua_uloop_fd *ufd = container_of(fd, struct lua_uloop_fd, fd); 166 167 lua_getglobal(state, "__uloop_cb"); 168 lua_rawgeti(state, -1, ufd->r); 169 lua_remove(state, -2); 170 171 /* push fd object */ 172 lua_getglobal(state, "__uloop_fds"); 173 lua_rawgeti(state, -1, ufd->fd_r); 174 lua_remove(state, -2); 175 176 /* push events */ 177 lua_pushinteger(state, events); 178 lua_call(state, 2, 0); 179 } 180 181 182 static int get_sock_fd(lua_State* L, int idx) { 183 int fd; 184 if(lua_isnumber(L, idx)) { 185 fd = lua_tonumber(L, idx); 186 } else { 187 luaL_checktype(L, idx, LUA_TUSERDATA); 188 lua_getfield(L, idx, "getfd"); 189 if(lua_isnil(L, -1)) 190 return luaL_error(L, "socket type missing 'getfd' method"); 191 /* if we have absolute, no need to adjust for getfield() call */ 192 lua_pushvalue(L, idx > 0 ? idx: idx - 1); 193 lua_call(L, 1, 1); 194 fd = lua_tointeger(L, -1); 195 lua_pop(L, 1); 196 } 197 return fd; 198 } 199 200 static int ul_ufd_delete(lua_State *L) 201 { 202 struct lua_uloop_fd *ufd = lua_touserdata(L, 1); 203 204 uloop_fd_delete(&ufd->fd); 205 206 /* obj.__index.__gc = nil , make sure executing only once*/ 207 lua_getfield(L, -1, "__index"); 208 lua_pushstring(L, "__gc"); 209 lua_pushnil(L); 210 lua_settable(L, -3); 211 212 lua_getglobal(state, "__uloop_cb"); 213 luaL_unref(state, -1, ufd->r); 214 lua_remove(state, -1); 215 216 lua_getglobal(state, "__uloop_fds"); 217 luaL_unref(state, -1, ufd->fd_r); 218 lua_remove(state, -1); 219 220 return 1; 221 } 222 223 static const luaL_Reg ufd_m[] = { 224 { "delete", ul_ufd_delete }, 225 { NULL, NULL } 226 }; 227 228 static int ul_ufd_add(lua_State *L) 229 { 230 struct lua_uloop_fd *ufd; 231 int fd = 0; 232 unsigned int flags = 0; 233 int ref; 234 int fd_ref; 235 236 flags = luaL_checkinteger(L, 3); 237 if (!flags) { 238 lua_pushstring(L, "flags cannot be zero"); 239 lua_error(L); 240 } 241 242 luaL_checktype(L, 2, LUA_TFUNCTION); 243 244 fd = get_sock_fd(L, 1); 245 246 lua_getglobal(L, "__uloop_cb"); 247 lua_pushvalue(L, 2); 248 ref = luaL_ref(L, -2); 249 lua_pop(L, 1); 250 251 lua_getglobal(L, "__uloop_fds"); 252 lua_pushvalue(L, 1); 253 fd_ref = luaL_ref(L, -2); 254 lua_pop(L, 1); 255 256 ufd = ul_create_userdata(L, sizeof(*ufd), ufd_m, ul_ufd_delete); 257 ufd->r = ref; 258 ufd->fd.fd = fd; 259 ufd->fd_r = fd_ref; 260 ufd->fd.cb = ul_ufd_cb; 261 uloop_fd_add(&ufd->fd, flags); 262 263 return 1; 264 } 265 266 static int ul_process_free(lua_State *L) 267 { 268 struct lua_uloop_process *proc = lua_touserdata(L, 1); 269 270 /* obj.__index.__gc = nil , make sure executing only once*/ 271 lua_getfield(L, -1, "__index"); 272 lua_pushstring(L, "__gc"); 273 lua_pushnil(L); 274 lua_settable(L, -3); 275 276 if (proc->r != LUA_NOREF) { 277 uloop_process_delete(&proc->p); 278 279 lua_getglobal(state, "__uloop_cb"); 280 luaL_unref(state, -1, proc->r); 281 lua_remove(state, -1); 282 } 283 284 return 1; 285 } 286 287 static int ul_process_pid(lua_State *L) 288 { 289 struct lua_uloop_process *proc = lua_touserdata(L, 1); 290 291 if (proc->p.pid) { 292 lua_pushnumber(L, proc->p.pid); 293 return 1; 294 } 295 296 return 0; 297 } 298 299 static const luaL_Reg process_m[] = { 300 { "delete", ul_process_free }, 301 { "pid", ul_process_pid }, 302 { NULL, NULL } 303 }; 304 305 static void ul_process_cb(struct uloop_process *p, int ret) 306 { 307 struct lua_uloop_process *proc = container_of(p, struct lua_uloop_process, p); 308 309 lua_getglobal(state, "__uloop_cb"); 310 lua_rawgeti(state, -1, proc->r); 311 312 luaL_unref(state, -2, proc->r); 313 proc->r = LUA_NOREF; 314 lua_remove(state, -2); 315 lua_pushinteger(state, ret >> 8); 316 lua_call(state, 1, 0); 317 } 318 319 static int ul_process(lua_State *L) 320 { 321 struct lua_uloop_process *proc; 322 pid_t pid; 323 int ref; 324 325 if (!lua_isfunction(L, -1) || !lua_istable(L, -2) || 326 !lua_istable(L, -3) || !lua_isstring(L, -4)) { 327 lua_pushstring(L, "invalid arg list"); 328 lua_error(L); 329 330 return 0; 331 } 332 333 pid = fork(); 334 335 if (pid == -1) { 336 lua_pushstring(L, "failed to fork"); 337 lua_error(L); 338 339 return 0; 340 } 341 342 if (pid == 0) { 343 /* child */ 344 int argn = lua_objlen(L, -3); 345 int envn = lua_objlen(L, -2); 346 char** argp = malloc(sizeof(char*) * (argn + 2)); 347 char** envp = malloc(sizeof(char*) * (envn + 1)); 348 int i = 1; 349 350 if (!argp || !envp) 351 _exit(-1); 352 353 argp[0] = (char*) lua_tostring(L, -4); 354 for (i = 1; i <= argn; i++) { 355 lua_rawgeti(L, -3, i); 356 argp[i] = (char*) lua_tostring(L, -1); 357 lua_pop(L, 1); 358 } 359 argp[i] = NULL; 360 361 for (i = 1; i <= envn; i++) { 362 lua_rawgeti(L, -2, i); 363 envp[i - 1] = (char*) lua_tostring(L, -1); 364 lua_pop(L, 1); 365 } 366 envp[i - 1] = NULL; 367 368 execve(*argp, argp, envp); 369 _exit(-1); 370 } 371 372 lua_getglobal(L, "__uloop_cb"); 373 lua_pushvalue(L, -2); 374 ref = luaL_ref(L, -2); 375 376 proc = ul_create_userdata(L, sizeof(*proc), process_m, ul_process_free); 377 proc->r = ref; 378 proc->p.pid = pid; 379 proc->p.cb = ul_process_cb; 380 uloop_process_add(&proc->p); 381 382 return 1; 383 } 384 385 static int ul_init(lua_State *L) 386 { 387 uloop_init(); 388 lua_pushboolean(L, 1); 389 390 return 1; 391 } 392 393 static int ul_run(lua_State *L) 394 { 395 uloop_run(); 396 lua_pushboolean(L, 1); 397 398 return 1; 399 } 400 401 static int ul_end(lua_State *L) 402 { 403 uloop_end(); 404 return 1; 405 } 406 407 static luaL_reg uloop_func[] = { 408 {"init", ul_init}, 409 {"run", ul_run}, 410 {"timer", ul_timer}, 411 {"process", ul_process}, 412 {"fd_add", ul_ufd_add}, 413 {"cancel", ul_end}, 414 {NULL, NULL}, 415 }; 416 417 /* avoid warnings about missing declarations */ 418 int luaopen_uloop(lua_State *L); 419 int luaclose_uloop(lua_State *L); 420 421 int luaopen_uloop(lua_State *L) 422 { 423 state = L; 424 425 lua_createtable(L, 1, 0); 426 lua_setglobal(L, "__uloop_cb"); 427 428 lua_createtable(L, 1, 0); 429 lua_setglobal(L, "__uloop_fds"); 430 431 luaL_openlib(L, "uloop", uloop_func, 0); 432 lua_pushstring(L, "_VERSION"); 433 lua_pushstring(L, "1.0"); 434 lua_rawset(L, -3); 435 436 lua_pushstring(L, "ULOOP_READ"); 437 lua_pushinteger(L, ULOOP_READ); 438 lua_rawset(L, -3); 439 440 lua_pushstring(L, "ULOOP_WRITE"); 441 lua_pushinteger(L, ULOOP_WRITE); 442 lua_rawset(L, -3); 443 444 lua_pushstring(L, "ULOOP_EDGE_TRIGGER"); 445 lua_pushinteger(L, ULOOP_EDGE_TRIGGER); 446 lua_rawset(L, -3); 447 448 lua_pushstring(L, "ULOOP_BLOCKING"); 449 lua_pushinteger(L, ULOOP_BLOCKING); 450 lua_rawset(L, -3); 451 452 return 1; 453 } 454 455 int luaclose_uloop(lua_State *L) 456 { 457 lua_pushstring(L, "Called"); 458 459 return 1; 460 } 461
This page was automatically generated by LXR 0.3.1. • OpenWrt