diff options
| author | dacctal <donotcontactmevia@email.invalid> | 2026-07-21 21:32:27 +0000 |
|---|---|---|
| committer | dacctal <donotcontactmevia@email.invalid> | 2026-07-21 21:32:27 +0000 |
| commit | 184bd50e2ea12b4bf40f4ae1b0d685f0bfa1c995 (patch) | |
| tree | bfe4f0a8fb39def302bdc807308c30b60dd18a92 /src/lua_state.c | |
| parent | c251d37c98efba534766e914f7392cc7a0470351 (diff) | |
started 2.0 refactor. Co-authored-by: ezntek <eason@ezntek.com>
Diffstat (limited to 'src/lua_state.c')
| -rw-r--r-- | src/lua_state.c | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/src/lua_state.c b/src/lua_state.c new file mode 100644 index 0000000..7e9dd18 --- /dev/null +++ b/src/lua_state.c @@ -0,0 +1,146 @@ +#include <lua.h> +#include <stdlib.h> +#include <unistd.h> + +#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); +} + +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_concat_cstr(&config.dir, "/init.lua"); + config.autogenerated_path = + str_concat_cstr(&config.dir, "/autogenerated.lua"); +} + +#define HANDLE_LUA_ERROR \ + do { \ + log_error("lua: %s", lua_tostring(L, -1)); \ + lua_pop(L, 1); \ + return false; \ + } while (0) + +#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) { + if (luaL_loadfile(L, config.init_path.data)) + HANDLE_LUA_ERROR; + + 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 + + lua_getfield(L, -1, "prefix"); + + return true; +} + +bool init_lua_config(void) { + if (!init_lua_state()) + return false; + + setup_base_dirs(); + + 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; +} |
