#include #include #include #include "log.h" #include "lua_state.h" #include "state.h" #include "str.h" lua_State *L = NULL; bool L_is_loaded = false; static void lua_path_push(const char *new_path) { lua_getglobal(L, "package"); lua_getfield(L, -1, "path"); const char *current_path = lua_tostring(L, -1); if (!current_path) current_path = ""; lua_pop(L, 1); lua_pushfstring(L, "%s;%s", current_path, new_path); lua_setfield(L, -2, "path"); lua_pop(L, 1); } #define HANDLE_LUA_ERROR \ do { \ log_error("lua: %s", lua_tostring(L, -1)); \ lua_pop(L, 1); \ return false; \ } while (0) bool init_lua_state(void) { if (L_is_loaded) return true; L = luaL_newstate(); luaL_openlibs(L); str lua_path = str_format("%.*s/?.lua", str_fmt(&config.dir)); lua_path_push(lua_path.data); if (luaL_loadfile(L, config.init_path.data) || lua_pcall(L, 0, 1, 0)) { log_error("cannot run configuration script: %s", lua_tostring(L, -1)); log_pkgit("to generate a configuration file, head into the"); log_pkgit( "root directory of the pkgit source and run `make defconfig`"); lua_close(L); return false; } if (!lua_istable(L, -1)) { log_error("top-level configuration is not a table"); lua_pop(L, 1); lua_close(L); return false; } str_free(&lua_path); L_is_loaded = true; return true; } static void setup_base_dirs(void) { int uid = getuid(), euid = geteuid(); config.is_root = false; if (uid < 0 || uid != euid) { config.is_root = true; config.dir = mstr("/etc/pkgit"); } else { char *tmp = getenv("XDG_CONFIG_HOME"); if (tmp) { config.dir = str_format("%s/pkgit", tmp); } else { config.dir = str_format("%s/.config/pkgit", getenv("HOME")); } } config.init_path = str_format( "%.*s/init.lua", str_fmt(&config.dir) ); config.autogenerated_path = str_format( "%.*s/autogenerated.lua", str_fmt(&config.dir) ); } #define lua_get_field_type(name, type, file) \ do { \ lua_getfield(L, -1, name); \ if (!lua_is##type(L, -1)) { \ log_error("lua: expected type " #type " for " name " in %.*s", \ str_fmt(file)); \ lua_pop(L, 1); \ return false; \ } \ } while (0) static bool load_init_lua(void) { lua_setglobal(L, "__PkgitUserConfig"); lua_getglobal(L, "__PkgitUserConfig"); lua_get_field_type("dirs", table, &config.init_path); #define X(field) \ do { \ lua_get_field_type(#field, string, &config.init_path); \ config.inst_dirs.field = str_adopt((char *)lua_tostring(L, -1)); \ lua_pop(L, 1); \ } while (0) X(prefix); X(bin); X(include); X(lib); X(src); #undef X return true; } bool init_lua_config(void) { setup_base_dirs(); if (!init_lua_state()) return false; if (!load_init_lua()) return false; return true; } void free_lua_state(void) { if (L != NULL) { lua_close(L); L = NULL; } L_is_loaded = false; } void free_lua_config(void) { free_lua_state(); }