diff options
author | Isaac Freund <ifreund@freebsdfoundation.org> | 2025-05-05 09:57:13 +0000 |
---|---|---|
committer | Ed Maste <emaste@FreeBSD.org> | 2025-05-12 18:27:57 +0000 |
commit | 7080a0c170daf8e4b3f331ec33003b2f8893dc23 (patch) | |
tree | cb51e93327c86b007dbd27a1de3678ae16753d3c | |
parent | e3b16f53a6455903a7e814045584fe203d4fff64 (diff) |
flua: add posix.unistd.execp
This matches the interface of lposix, although I do wonder why they went
with execp rather than execvp for the function name here.
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D50177
-rw-r--r-- | libexec/flua/modules/lposix.c | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/libexec/flua/modules/lposix.c b/libexec/flua/modules/lposix.c index a706adf2c353..816d4bc688d2 100644 --- a/libexec/flua/modules/lposix.c +++ b/libexec/flua/modules/lposix.c @@ -199,6 +199,62 @@ err: } static int +lua_execp(lua_State *L) +{ + int argc, error; + const char *file; + const char **argv; + + enforce_max_args(L, 2); + + file = luaL_checkstring(L, 1); + luaL_checktype(L, 2, LUA_TTABLE); + + lua_len(L, 2); + argc = lua_tointeger(L, -1); + + /* + * Use lua_newuserdatauv() to allocate a scratch buffer that is tracked + * and freed by lua's GC. This avoid any chance of a leak if a lua error + * is raised later in this function (e.g. by luaL_argerror()). + * The (argc + 2) size gives enough space in the buffer for argv[0] and + * the terminating NULL. + */ + argv = lua_newuserdatauv(L, (argc + 2) * sizeof(char *), 0); + + /* + * Sequential tables in lua start at index 1 by convention. + * If there happens to be a string at index 0, use that to + * override the default argv[0]. This matches the lposix API. + */ + lua_pushinteger(L, 0); + lua_gettable(L, 2); + argv[0] = lua_tostring(L, -1); + if (argv[0] == NULL) { + argv[0] = file; + } + + for (int i = 1; i <= argc; i++) { + lua_pushinteger(L, i); + lua_gettable(L, 2); + argv[i] = lua_tostring(L, -1); + if (argv[i] == NULL) { + luaL_argerror(L, 2, + "argv table must contain only strings"); + } + } + argv[argc + 1] = NULL; + + execvp(file, (char **)argv); + error = errno; + + lua_pushnil(L); + lua_pushstring(L, strerror(error)); + lua_pushinteger(L, error); + return (3); +} + +static int lua_fnmatch(lua_State *L) { const char *pattern, *string; @@ -513,6 +569,7 @@ static const struct luaL_Reg unistdlib[] = { REG_SIMPLE(chown), REG_DEF(close, lua_pclose), REG_SIMPLE(dup2), + REG_SIMPLE(execp), REG_SIMPLE(fork), REG_SIMPLE(getpid), REG_SIMPLE(pipe), |