static int luv_idle_start(lua_State* L) { uv_idle_t* handle = luv_check_idle(L, 1); int ret; luv_check_callback(L, (luv_handle_t *)handle->data, LUV_IDLE, 2); ret = uv_idle_start(handle, luv_idle_cb); if (ret < 0) return luv_error(L, ret); lua_pushinteger(L, ret); return 1; }
static int luv_udp_recv_start(lua_State* L) { uv_udp_t* handle = luv_check_udp(L, 1); int ret; luv_check_callback(L, (luv_handle_t*)handle->data, LUV_RECV, 2); ret = uv_udp_recv_start(handle, luv_alloc_cb, luv_udp_recv_cb); if (ret < 0) return luv_error(L, ret); lua_pushinteger(L, ret); return 1; }
static int luv_read_start(lua_State* L) { uv_stream_t* handle = luv_check_stream(L, 1); int ret; luv_check_callback(L, handle->data, LUV_READ, 2); ret = uv_read_start(handle, luv_alloc_cb, luv_read_cb); if (ret < 0) return luv_error(L, ret); lua_pushinteger(L, ret); return 1; }
static int luv_prepare_start(lua_State* L) { uv_prepare_t* handle = luv_check_prepare(L, 1); int ret; luv_check_callback(L, handle->data, LUV_PREPARE, 2); ret = uv_prepare_start(handle, luv_prepare_cb); if (ret < 0) return luv_error(L, ret); lua_pushinteger(L, ret); return 1; }
static int luv_listen(lua_State* L) { uv_stream_t* handle = luv_check_stream(L, 1); int backlog = luaL_checkinteger(L, 2); int ret; luv_check_callback(L, handle->data, LUV_CONNECTION, 3); ret = uv_listen(handle, backlog, luv_connection_cb); if (ret < 0) return luv_error(L, ret); lua_pushinteger(L, ret); return 1; }
static int luv_close(lua_State* L) { uv_handle_t* handle = luv_check_handle(L, 1); if (uv_is_closing(handle)) { luaL_error(L, "handle %p is already closing", handle); } if (!lua_isnoneornil(L, 2)) { luv_check_callback(L, handle->data, LUV_CLOSED, 2); } uv_close(handle, luv_close_cb); return 0; }
static int luv_fs_poll_start(lua_State* L) { uv_fs_poll_t* handle = luv_check_fs_poll(L, 1); const char* path = luaL_checkstring(L, 2); unsigned int interval = luaL_checkinteger(L, 3); int ret; luv_check_callback(L, handle->data, LUV_FS_POLL, 4); ret = uv_fs_poll_start(handle, luv_fs_poll_cb, path, interval); if (ret < 0) return luv_error(L, ret); lua_pushinteger(L, ret); return 1; }
static int luv_poll_start(lua_State* L) { uv_poll_t* handle = luv_check_poll(L, 1); int events, ret; switch (luaL_checkoption(L, 2, "rw", luv_pollevents)) { case 0: events = UV_READABLE; break; case 1: events = UV_WRITABLE; break; case 2: events = UV_READABLE | UV_WRITABLE; break; case 3: events = UV_DISCONNECT; break; case 4: events = UV_READABLE|UV_DISCONNECT; break; case 5: events = UV_WRITABLE|UV_DISCONNECT; break; case 6: events = UV_READABLE|UV_WRITABLE|UV_DISCONNECT; break; default: events = 0; /* unreachable */ } luv_check_callback(L, (luv_handle_t*)handle->data, LUV_POLL, 3); ret = uv_poll_start(handle, events, luv_poll_cb); if (ret < 0) return luv_error(L, ret); lua_pushinteger(L, ret); return 1; }
static int luv_fs_event_start(lua_State* L) { uv_fs_event_t* handle = luv_check_fs_event(L, 1); const char* path = luaL_checkstring(L, 2); int flags = 0, ret; luaL_checktype(L, 3, LUA_TTABLE); lua_getfield(L, 3, "watch_entry"); if (lua_toboolean(L, -1)) flags |= UV_FS_EVENT_WATCH_ENTRY; lua_pop(L, 1); lua_getfield(L, 3, "stat"); if (lua_toboolean(L, -1)) flags |= UV_FS_EVENT_STAT; lua_pop(L, 1); lua_getfield(L, 3, "recursive"); if (lua_toboolean(L, -1)) flags |= UV_FS_EVENT_RECURSIVE; lua_pop(L, 1); luv_check_callback(L, handle->data, LUV_FS_EVENT, 4); ret = uv_fs_event_start(handle, luv_fs_event_cb, path, flags); if (ret < 0) return luv_error(L, ret); lua_pushinteger(L, ret); return 1; }
static int luv_signal_start(lua_State* L) { uv_signal_t* handle = luv_check_signal(L, 1); int signum, ret; if (lua_isnumber(L, 2)) { signum = lua_tointeger(L, 2); } else if (lua_isstring(L, 2)) { signum = luv_sig_string_to_num(luaL_checkstring(L, 2)); luaL_argcheck(L, signum, 2, "Invalid Signal name"); } else { return luaL_argerror(L, 2, "Missing Signal name"); } if (!lua_isnoneornil(L, 3)) { luv_check_callback(L, handle->data, LUV_SIGNAL, 3); } ret = uv_signal_start(handle, luv_signal_cb, signum); if (ret < 0) return luv_error(L, ret); lua_pushinteger(L, ret); return 1; }
static int luv_spawn(lua_State* L) { uv_process_t* handle; uv_process_options_t options; size_t i, len = 0; int ret; memset(&options, 0, sizeof(options)); options.exit_cb = exit_cb; options.file = luaL_checkstring(L, 1); options.flags = 0; // Make sure the 2nd argument is a table luaL_checktype(L, 2, LUA_TTABLE); // get the args list lua_getfield(L, 2, "args"); // +1 for inserted command at front if (lua_type(L, -1) == LUA_TTABLE) { len = 1 + lua_rawlen(L, -1); } else if (lua_type(L, -1) != LUA_TNIL) { luv_clean_options(&options); return luaL_argerror(L, 3, "args option must be table"); } else { len = 1; } // +1 for null terminator at end options.args = malloc((len + 1) * sizeof(*options.args)); if (!options.args) { luv_clean_options(&options); return luaL_error(L, "Problem allocating args"); } options.args[0] = (char*)options.file; for (i = 1; i < len; ++i) { lua_rawgeti(L, -1, i); options.args[i] = (char*)lua_tostring(L, -1); lua_pop(L, 1); } options.args[len] = NULL; lua_pop(L, 1); // get the stdio list lua_getfield(L, 2, "stdio"); if (lua_type(L, -1) == LUA_TTABLE) { options.stdio_count = len = lua_rawlen(L, -1); options.stdio = malloc(len * sizeof(*options.stdio)); if (!options.stdio) { luv_clean_options(&options); return luaL_error(L, "Problem allocating stdio"); } for (i = 0; i < len; ++i) { lua_rawgeti(L, -1, i + 1); // integers are assumed to be file descripters if (lua_type(L, -1) == LUA_TNUMBER) { options.stdio[i].flags = UV_INHERIT_FD; options.stdio[i].data.fd = lua_tointeger(L, -1); } // userdata is assumed to be a uv_stream_t instance else if (lua_type(L, -1) == LUA_TUSERDATA) { uv_os_fd_t fd; uv_stream_t* stream = luv_check_stream(L, -1); int err = uv_fileno((uv_handle_t*)stream, &fd); if (err == UV_EINVAL || err == UV_EBADF) { options.stdio[i].flags = UV_CREATE_PIPE | UV_READABLE_PIPE | UV_WRITABLE_PIPE; } else { options.stdio[i].flags = UV_INHERIT_STREAM; } options.stdio[i].data.stream = stream; } else if (lua_type(L, -1) == LUA_TNIL) { options.stdio[i].flags = UV_IGNORE; } else { luv_clean_options(&options); return luaL_argerror(L, 2, "stdio table entries must be nil, uv_stream_t, or integer"); } lua_pop(L, 1); } } else if (lua_type(L, -1) != LUA_TNIL) { luv_clean_options(&options); return luaL_argerror(L, 2, "stdio option must be table"); } lua_pop(L, 1); // Get the env lua_getfield(L, 2, "env"); if (lua_type(L, -1) == LUA_TTABLE) { len = lua_rawlen(L, -1); options.env = malloc((len + 1) * sizeof(*options.env)); if (!options.env) { luv_clean_options(&options); return luaL_error(L, "Problem allocating env"); } for (i = 0; i < len; ++i) { lua_rawgeti(L, -1, i + 1); options.env[i] = (char*)lua_tostring(L, -1); lua_pop(L, 1); } options.env[len] = NULL; } else if (lua_type(L, -1) != LUA_TNIL) { luv_clean_options(&options); return luaL_argerror(L, 2, "env option must be table"); } lua_pop(L, 1); // Get the cwd lua_getfield(L, 2, "cwd"); if (lua_type(L, -1) == LUA_TSTRING) { options.cwd = (char*)lua_tostring(L, -1); } else if (lua_type(L, -1) != LUA_TNIL) { luv_clean_options(&options); return luaL_argerror(L, 2, "cwd option must be string"); } lua_pop(L, 1); // Check for uid lua_getfield(L, 2, "uid"); if (lua_type(L, -1) == LUA_TNUMBER) { options.uid = lua_tointeger(L, -1); options.flags |= UV_PROCESS_SETUID; } else if (lua_type(L, -1) != LUA_TNIL) { luv_clean_options(&options); return luaL_argerror(L, 2, "uid option must be number"); } lua_pop(L, 1); // Check for gid lua_getfield(L, 2, "gid"); if (lua_type(L, -1) == LUA_TNUMBER) { options.gid = lua_tointeger(L, -1); options.flags |= UV_PROCESS_SETGID; } else if (lua_type(L, -1) != LUA_TNIL) { luv_clean_options(&options); return luaL_argerror(L, 2, "gid option must be number"); } lua_pop(L, 1); // Check for the boolean flags lua_getfield(L, 2, "verbatim"); if (lua_toboolean(L, -1)) { options.flags |= UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS; } lua_pop(L, 1); lua_getfield(L, 2, "detached"); if (lua_toboolean(L, -1)) { options.flags |= UV_PROCESS_DETACHED; } lua_pop(L, 1); lua_getfield(L, 2, "hide"); if (lua_toboolean(L, -1)) { options.flags |= UV_PROCESS_WINDOWS_HIDE; } lua_pop(L, 1); handle = lua_newuserdata(L, sizeof(*handle)); handle->type = UV_PROCESS; handle->data = luv_setup_handle(L); if (!lua_isnoneornil(L, 3)) { luv_check_callback(L, handle->data, LUV_EXIT, 3); } ret = uv_spawn(luv_loop(L), handle, &options); luv_clean_options(&options); if (ret < 0) { /* The async callback is required here because luajit GC may reclaim the * luv handle before libuv is done closing it down. */ uv_close((uv_handle_t*)handle, luv_spawn_close_cb); return luv_error(L, ret); } lua_pushinteger(L, handle->pid); return 2; }