static int lenv_keys(lua_State* L) { int size = 0, i; char **env = luv_os_environ(); while (env[size]) size++; lua_createtable(L, size, 0); for (i = 0; i < size; ++i) { size_t length; const char* var = env[i]; const char* s = strchr(var, '='); if (s != NULL) { length = s - var; } else { length = strlen(var); } lua_pushlstring(L, var, length); lua_rawseti(L, -2, i + 1); } return 1; }
// Initializes uv_process_t and starts the process. int luv_spawn(lua_State* L) { int before = lua_gettop(L); uv_pipe_t* stdin_stream = (uv_pipe_t*)luv_checkudata(L, 1, "pipe"); uv_pipe_t* stdout_stream = (uv_pipe_t*)luv_checkudata(L, 2, "pipe"); uv_pipe_t* stderr_stream = (uv_pipe_t*)luv_checkudata(L, 3, "pipe"); const char* command = luaL_checkstring(L, 4); size_t argc; char** args; int i; char* cwd; char** env; uv_process_options_t options; uv_process_t* handle; int r; luv_ref_t* ref; luaL_checktype(L, 5, LUA_TTABLE); // args luaL_checktype(L, 6, LUA_TTABLE); // options // Parse the args array argc = lua_objlen(L, 5) + 1; args = malloc((argc + 1) * sizeof(char*)); args[0] = (char*)command; for (i = 1; i < argc; i++) { lua_rawgeti(L, 5, i); args[i] = (char*)lua_tostring(L, -1); lua_pop(L, 1); } args[argc] = NULL; // Get the cwd lua_getfield(L, 6, "cwd"); cwd = (char*)lua_tostring(L, -1); lua_pop(L, 1); // Get the env lua_getfield(L, 6, "env"); env = NULL; if (lua_type(L, -1) == LUA_TTABLE) { argc = lua_objlen(L, -1); env = malloc((argc + 1) * sizeof(char*)); for (i = 0; i < argc; i++) { lua_rawgeti(L, -1, i + 1); env[i] = (char*)lua_tostring(L, -1); lua_pop(L, 1); } env[argc] = NULL; } lua_pop(L, 1); options.exit_cb = luv_process_on_exit; options.file = command; options.args = args; options.env = env ? env : luv_os_environ(); options.cwd = cwd; options.stdin_stream = stdin_stream; options.stdout_stream = stdout_stream; options.stderr_stream = stderr_stream; // Create the userdata handle = (uv_process_t*)lua_newuserdata(L, sizeof(uv_process_t)); r = uv_spawn(luv_get_loop(L), handle, options); free(args); if (env) free(env); if (r) { uv_err_t err = uv_last_error(luv_get_loop(L)); return luaL_error(L, "spawn: %s", uv_strerror(err)); } // Set metatable for type luaL_getmetatable(L, "luv_process"); lua_setmetatable(L, -2); // Create a local environment for storing stuff lua_newtable(L); lua_setfenv (L, -2); // Store a reference to the userdata in the handle ref = (luv_ref_t*)malloc(sizeof(luv_ref_t)); ref->L = L; lua_pushvalue(L, -1); // duplicate so we can _ref it ref->r = luaL_ref(L, LUA_REGISTRYINDEX); handle->data = ref; assert(lua_gettop(L) == before + 1); // return the userdata return 1; }