From c62d4056e67a6a0faa17c6492ab1c7e368e5e766 Mon Sep 17 00:00:00 2001 From: Jeremy Baxter Date: Sun, 2 Jul 2023 08:15:17 +1200 Subject: [PATCH] Use the environ table over the environment library --- Makefile | 6 +- lcallisto.c | 2 +- lcallisto.h | 6 +- lenviron.c | 115 ++++++++++++++++++++++++++++++++++++++ lenvironment.c | 148 ------------------------------------------------- 5 files changed, 123 insertions(+), 154 deletions(-) create mode 100644 lenviron.c delete mode 100644 lenvironment.c diff --git a/Makefile b/Makefile index 88e1bc2..bfb557d 100644 --- a/Makefile +++ b/Makefile @@ -5,8 +5,8 @@ CFLAGS = -std=c99 -pedantic -fpic -O2 -Wall -Wextra -Wno-override-init -I. -Il CPPFLAGS = -D_DEFAULT_SOURCE -DLUA_USE_READLINE LDFLAGS = -lm -lreadline -OBJS = csto.o lcallisto.o lcl.o lenvironment.o lextra.o \ - lfile.o ljson.o lmath.o los.o lprocess.o lsocket.o util.o +OBJS = csto.o lcallisto.o lcl.o lenviron.o lextra.o lfile.o \ + ljson.o lmath.o los.o lprocess.o lsocket.o util.o LIBS = liblua.a cjson.a socket.a all: csto libcallisto.so @@ -25,7 +25,7 @@ csto.o: csto.c lcallisto.h lcallisto.o: lcallisto.c lcallisto.h lcl.o: lcl.c lcallisto.h lextra.o: lextra.c lcallisto.h -lenvironment.o: lenvironment.c lcallisto.h +lenviron.o: lenviron.c lcallisto.h lfile.o: lfile.c lcallisto.h ljson.o: ljson.c lcallisto.h lmath.o: lmath.c lcallisto.h diff --git a/lcallisto.c b/lcallisto.c index 6543d21..09dc949 100644 --- a/lcallisto.c +++ b/lcallisto.c @@ -11,7 +11,7 @@ static const luaL_Reg loadedlibs[] = { {CALLISTO_CLLIBNAME, callistoopen_cl}, - {CALLISTO_ENVLIBNAME, callistoopen_environment}, + {CALLISTO_ENVLIBNAME, callistoopen_environ}, {CALLISTO_EXTLIBNAME, callistoopen_extra}, {CALLISTO_FILELIBNAME, callistoopen_file}, {CALLISTO_JSONLIBNAME, callistoopen_json}, diff --git a/lcallisto.h b/lcallisto.h index 29c5180..f2aaa30 100644 --- a/lcallisto.h +++ b/lcallisto.h @@ -16,7 +16,7 @@ #define CALLISTO_COPYRIGHT CALLISTO_VERSION " (" LUA_RELEASE ") Copyright (C) 1994-2022 Lua.org, PUC-Rio" #define CALLISTO_CLLIBNAME "cl" -#define CALLISTO_ENVLIBNAME "environment" +#define CALLISTO_ENVLIBNAME "environ" #define CALLISTO_EXTLIBNAME "_G" /* global table */ #define CALLISTO_FILELIBNAME "file" #define CALLISTO_JSONLIBNAME "json" @@ -25,8 +25,10 @@ #define CALLISTO_PROCLIBNAME "process" #define CALLISTO_SOCKLIBNAME "socket" +#define CALLISTO_ENVIRON "environ" + int callistoopen_cl(lua_State *); -int callistoopen_environment(lua_State *); +int callistoopen_environ(lua_State *); int callistoopen_extra(lua_State *); int callistoopen_file(lua_State *); int callistoopen_json(lua_State *); diff --git a/lenviron.c b/lenviron.c new file mode 100644 index 0000000..f07996a --- /dev/null +++ b/lenviron.c @@ -0,0 +1,115 @@ +/*** + * Getting and setting environment variables. + * @module environ + */ + +#include +#include + +#include +#include + +#include "lcallisto.h" + + +extern char **environ; + +/*** + * Table enabling easy access to environment + * variables. + * + * Has metamethods *\_\_index* and *\_\_newindex*, + * which allow for the table to be indexed with a + * string to get values of environment variables, + * or for fields to be set to set an environment + * variable. + * + * @table environ + * @usage +-- Print the value of an environment variable: +print(environ["MYVAR"]) +-- Set an environment variable: +environ["MYVAR"] = 1 + */ + +/* + * Returns the value of the given environment variable. + */ +static int +environ_index(lua_State *L) +{ + const char *variable; /* parameter 2 (string) */ + char *ret; + + variable = luaL_checkstring(L, 2); + ret = getenv(variable); + + if (ret == NULL) /* no environment variable? */ + lua_pushnil(L); + else + lua_pushstring(L, ret); /* push variable value */ + + return 1; +} + +/* + * Sets the value of the given environment variable. + */ +static int +environ_newindex(lua_State *L) +{ + int ret; + const char *variable; /* parameter 2 (string) */ + const char *value; /* parameter 3 (string) */ + + variable = luaL_checkstring(L, 2); + + if (lua_isnil(L, 3)) { + ret = unsetenv(variable); /* remove variable from environ */ + if (ret == 0) /* did unsetenv succeed? */ + return 0; + + /* if unsetenv didn't succeed: + * (unsetenv only sets errno to EINVAL on error) */ + return luaL_error(L, "invalid input string"); + } + + value = luaL_checkstring(L, 3); + ret = setenv(variable, value, 1); + + if (ret == 0) /* did setenv succeed? */ + return 0; + + switch (errno) { + case EINVAL: + return luaL_error(L, "invalid input string"); + break; + case ENOMEM: + return luaL_error(L, "insufficient memory"); + break; + } + + return 0; +} + +static const luaL_Reg mt[] = { + {"__index", environ_index}, + {"__newindex", environ_newindex}, + {NULL, NULL} +}; + +int +callistoopen_environ(lua_State *L) +{ + const luaL_Reg *lib; + + lua_newtable(L); + luaL_newmetatable(L, CALLISTO_ENVIRON); /* metatable for environ */ + + for (lib = mt; lib->func; lib++) { + lua_pushcfunction(L, lib->func); + lua_setfield(L, -2, lib->name); + } + lua_setmetatable(L, -2); + return 1; +} diff --git a/lenvironment.c b/lenvironment.c deleted file mode 100644 index 838335f..0000000 --- a/lenvironment.c +++ /dev/null @@ -1,148 +0,0 @@ -/*** - * Getting and setting - * environment variables. - * @module environment - */ - -#include -#include -#ifdef BSD -# include -#endif - -#include -#include - -#include "lcallisto.h" -#include "util.h" - - -extern char **environ; - -/*** - * Returns the value of the given environment - * variable. - * - * If *var* does not exist in the environment - * and *defaultvalue* is not nil, - * *defaultvalue* will be returned. - * - * @function get - * @usage environment.get("HOME", "/root") - * @tparam string var The environment variable to get. - * @param[opt] defaultvalue The value to return in case the environment variable was not found. - */ -static int -environment_get(lua_State *L) -{ - const char *variable; - char *ret; - - variable = luaL_checkstring(L, 1); - ret = getenv(variable); - - if (ret == NULL) - if (!lua_isnoneornil(L, 2)) - lua_pushvalue(L, 2); - else - lua_pushnil(L); - else - lua_pushstring(L, ret); - return 1; -} - -/*** - * Sets the value of the given environment variable. - * - * This function will throw an error if the value of - * *var* is invalid for the name of an environment - * variable, or if there is insufficient memory - * available to perform the operation. - * - * @function set - * @usage environment.set("MYVAR", "1") - * @tparam string var The environment variable to set. - * @tparam string value The value to set for *var*. - */ -static int -environment_set(lua_State *L) -{ - int ret; - const char *variable; - const char *value; - - variable = luaL_checkstring(L, 1); - value = luaL_checkstring(L, 2); - - ret = setenv(variable, value, 1); - - if (ret == 0) - return 0; - - switch (errno) { - case EINVAL: - return luaL_error(L, "invalid input string"); - break; - case ENOMEM: - return luaL_error(L, "insufficient memory"); - break; - } - return 0; -} - -/*** - * Clears the environment. - * - * If *var* is not nil, only clears the value of that - * environment variable (not the whole environment). - * - * This function will throw an error if the value of - * *var* is invalid for the name of an environment - * variable, or if there is insufficient memory - * available to perform the operation. - * - * @function clear - * @usage environment.clear("MYVAR") - * @tparam[opt] string var The environment variable to clear. - */ -static int -environment_clear(lua_State *L) -{ - const char *variable; - int ret; - - if (lua_isnoneornil(L, 1)) { - environ = NULL; - return 0; - } - - variable = luaL_checkstring(L, 1); - ret = unsetenv(variable); - - if (ret == 0) - return 0; - - switch (errno) { - case EINVAL: - return luaL_error(L, "invalid input string"); - break; - case ENOMEM: - return luaL_error(L, "insufficient memory"); - break; - } - return 0; -} - -static const luaL_Reg envlib[] = { - {"get", environment_get}, - {"set", environment_set}, - {"clear", environment_clear}, - {NULL, NULL} -}; - -int -callistoopen_environment(lua_State *L) -{ - luaL_newlib(L, envlib); - return 1; -}