Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F109841407
D39083.id119481.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D39083.id119481.diff
View Options
diff --git a/libexec/flua/linit_flua.c b/libexec/flua/linit_flua.c
--- a/libexec/flua/linit_flua.c
+++ b/libexec/flua/linit_flua.c
@@ -58,7 +58,10 @@
#endif
/* FreeBSD Extensions */
{"lfs", luaopen_lfs},
+ {"posix.libgen", luaopen_posix_libgen},
+ {"posix.stdlib", luaopen_posix_stdlib},
{"posix.sys.stat", luaopen_posix_sys_stat},
+ {"posix.sys.wait", luaopen_posix_sys_wait},
{"posix.unistd", luaopen_posix_unistd},
{"ucl", luaopen_ucl},
{NULL, NULL}
diff --git a/libexec/flua/modules/lposix.h b/libexec/flua/modules/lposix.h
--- a/libexec/flua/modules/lposix.h
+++ b/libexec/flua/modules/lposix.h
@@ -8,5 +8,8 @@
#include <lua.h>
+int luaopen_posix_libgen(lua_State *L);
+int luaopen_posix_stdlib(lua_State *L);
int luaopen_posix_sys_stat(lua_State *L);
+int luaopen_posix_sys_wait(lua_State *L);
int luaopen_posix_unistd(lua_State *L);
diff --git a/libexec/flua/modules/lposix.c b/libexec/flua/modules/lposix.c
--- a/libexec/flua/modules/lposix.c
+++ b/libexec/flua/modules/lposix.c
@@ -1,5 +1,6 @@
/*-
- * Copyright (c) 2019 Kyle Evans <kevans@FreeBSD.org>
+ *
+ * Copyright (c) 2019, 2023 Kyle Evans <kevans@FreeBSD.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -28,10 +29,13 @@
__FBSDID("$FreeBSD$");
#include <sys/stat.h>
+#include <sys/wait.h>
#include <errno.h>
#include <grp.h>
+#include <libgen.h>
#include <pwd.h>
+#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -42,6 +46,68 @@
/*
* Minimal implementation of luaposix needed for internal FreeBSD bits.
*/
+static int
+lposix_alloc(lua_State *L, size_t sz, char **buf)
+{
+ char *nbuf;
+ void *ud;
+ lua_Alloc allocf;
+
+ if (sz == 0)
+ return EINVAL;
+
+ allocf = lua_getallocf(L, &ud);
+
+ nbuf = allocf(ud, NULL, 0, sz);
+ if (nbuf == NULL)
+ return ENOMEM;
+
+ *buf = nbuf;
+ return 0;
+}
+
+static void
+lposix_free(lua_State *L, size_t sz, char *buf)
+{
+ void *ud;
+ lua_Alloc allocf;
+
+ allocf = lua_getallocf(L, &ud);
+ (void)allocf(ud, buf, sz, 0);
+}
+
+static int
+lua__exit(lua_State *L)
+{
+ int code, n;
+
+ n = lua_gettop(L);
+ luaL_argcheck(L, n == 1, 1, "_exit takes exactly one argument");
+
+ code = luaL_checkinteger(L, 1);
+ _exit(code);
+}
+
+static int
+lua_basename(lua_State *L)
+{
+ char *inpath, *outpath;
+ int n;
+
+ n = lua_gettop(L);
+ luaL_argcheck(L, n > 0, 1, "at least one argument required");
+ inpath = strdup(luaL_checkstring(L, 1));
+ if (inpath == NULL) {
+ lua_pushnil(L);
+ lua_pushstring(L, strerror(ENOMEM));
+ lua_pushinteger(L, ENOMEM);
+ }
+
+ outpath = basename(inpath);
+ lua_pushstring(L, outpath);
+ free(inpath);
+ return 1;
+}
static int
lua_chmod(lua_State *L)
@@ -115,10 +181,81 @@
lua_pushnil(L);
lua_pushstring(L, strerror(errno));
lua_pushinteger(L, errno);
- return (3);
+ return 3;
}
lua_pushinteger(L, 0);
- return (1);
+ return 1;
+}
+
+static int
+lua_pclose(lua_State *L)
+{
+ int error, fd, n;
+
+ n = lua_gettop(L);
+ luaL_argcheck(L, n == 1, 1,
+ "close takes exactly one arguments (fd)");
+
+ fd = luaL_checkinteger(L, 1);
+ if (fd < 0) {
+ error = EBADF;
+ goto err;
+ }
+
+ if (close(fd) == 0) {
+ lua_pushinteger(L, 0);
+ return 1;
+ }
+
+ error = errno;
+err:
+ lua_pushnil(L);
+ lua_pushstring(L, strerror(error));
+ lua_pushinteger(L, error);
+ return 3;
+
+}
+
+static int
+lua_dirname(lua_State *L)
+{
+ char *inpath, *outpath;
+ int n;
+
+ n = lua_gettop(L);
+ luaL_argcheck(L, n > 0, 1, "at least one argument required");
+ inpath = strdup(luaL_checkstring(L, 1));
+ if (inpath == NULL) {
+ lua_pushnil(L);
+ lua_pushstring(L, strerror(ENOMEM));
+ lua_pushinteger(L, ENOMEM);
+ }
+
+ outpath = dirname(inpath);
+ lua_pushstring(L, outpath);
+ free(inpath);
+ return 1;
+}
+
+static int
+lua_fork(lua_State *L)
+{
+ pid_t pid;
+ int n;
+
+ n = lua_gettop(L);
+ luaL_argcheck(L, n == 0, 1, "too many arguments");
+
+ pid = fork();
+ if (pid < 0) {
+ lua_pushnil(L);
+ lua_pushstring(L, strerror(errno));
+ lua_pushinteger(L, errno);
+ return 1;
+ }
+
+ lua_pushinteger(L, pid);
+ return 1;
}
static int
@@ -132,18 +269,253 @@
return 1;
}
-#define REG_SIMPLE(n) { #n, lua_ ## n }
+static int
+lua_pipe(lua_State *L)
+{
+ int error, fd[2], n;
+
+ n = lua_gettop(L);
+ luaL_argcheck(L, n == 0, 1, "too many arguments");
+
+ error = pipe(fd);
+ if (error != 0) {
+ lua_pushnil(L);
+ lua_pushstring(L, strerror(errno));
+ lua_pushinteger(L, errno);
+ return 1;
+ }
+
+ lua_pushinteger(L, fd[0]);
+ lua_pushinteger(L, fd[1]);
+ return 2;
+}
+
+static int
+lua_read(lua_State *L)
+{
+ char *buf;
+ ssize_t ret;
+ size_t sz;
+ int error, fd, n;
+
+ n = lua_gettop(L);
+ luaL_argcheck(L, n == 2, 1,
+ "read takes exactly two arguments (fd, size)");
+
+ fd = luaL_checkinteger(L, 1);
+ sz = luaL_checkinteger(L, 2);
+
+ if (fd < 0) {
+ error = EBADF;
+ goto err;
+ }
+
+ error = lposix_alloc(L, sz, &buf);
+ if (error != 0)
+ goto err;
+
+ /*
+ * For 0-byte reads, we'll still push the empty string and let the
+ * caller deal with EOF to match lposix semantics.
+ */
+ ret = read(fd, buf, sz);
+ if (ret >= 0)
+ lua_pushlstring(L, buf, ret);
+ else if (ret < 0)
+ error = errno; /* Save to avoid clobber by free() */
+
+ lposix_free(L, sz, buf);
+ if (error != 0)
+ goto err;
+
+ /* Just the string pushed. */
+ return 1;
+err:
+ lua_pushnil(L);
+ lua_pushstring(L, strerror(error));
+ lua_pushinteger(L, error);
+ return 3;
+}
+
+static int
+lua_realpath(lua_State *L)
+{
+ const char *inpath;
+ char *outpath;
+ int n;
+
+ n = lua_gettop(L);
+ luaL_argcheck(L, n > 0, 1, "at least one argument required");
+ inpath = luaL_checkstring(L, 1);
+
+ outpath = realpath(inpath, NULL);
+ if (outpath == NULL) {
+ lua_pushnil(L);
+ lua_pushstring(L, strerror(errno));
+ lua_pushinteger(L, errno);
+ }
+
+ lua_pushstring(L, outpath);
+ free(outpath);
+ return 1;
+}
+
+static int
+lua_wait(lua_State *L)
+{
+ pid_t pid;
+ int options, status;
+ int n;
+
+ n = lua_gettop(L);
+
+ pid = -1;
+ status = options = 0;
+ if (n >= 1 && !lua_isnil(L, 1))
+ pid = luaL_checkinteger(L, 1);
+ if (n >= 2 && !lua_isnil(L, 2))
+ options = luaL_checkinteger(L, 2);
+
+ pid = waitpid(pid, &status, options);
+ if (pid < 0) {
+ lua_pushnil(L);
+ lua_pushstring(L, strerror(errno));
+ lua_pushinteger(L, errno);
+ return 3;
+ }
+
+ lua_pushinteger(L, pid);
+ if (pid == 0) {
+ lua_pushliteral(L, "running");
+ return 2;
+ }
+
+ if (WIFCONTINUED(status)) {
+ lua_pushliteral(L, "continued");
+ return 2;
+ } else if(WIFSTOPPED(status)) {
+ lua_pushliteral(L, "stopped");
+ lua_pushinteger(L, WSTOPSIG(status));
+ return 3;
+ } else if (WIFEXITED(status)) {
+ lua_pushliteral(L, "exited");
+ lua_pushinteger(L, WEXITSTATUS(status));
+ return 3;
+ } else if (WIFSIGNALED(status)) {
+ lua_pushliteral(L, "killed");
+ lua_pushinteger(L, WTERMSIG(status));
+ return 3;
+ }
+
+ return 1;
+}
+
+static int
+lua_write(lua_State *L)
+{
+ const char *buf;
+ size_t bufsz, sz;
+ ssize_t ret;
+ off_t offset;
+ int error, fd, n;
+
+ n = lua_gettop(L);
+ luaL_argcheck(L, n >= 2, 1,
+ "write takes at least two arguments (fd, buf, sz, off)");
+ luaL_argcheck(L, n <= 4, 5,
+ "write takes no more than four arguments (fd, buf, sz, off)");
+
+ fd = luaL_checkinteger(L, 1);
+ if (fd < 0) {
+ error = EBADF;
+ goto err;
+ }
+
+ buf = luaL_checkstring(L, 2);
+
+ bufsz = sz = lua_rawlen(L, 2);
+ if (n >= 3 && !lua_isnil(L, 3))
+ sz = luaL_checkinteger(L, 3);
+
+ offset = 0;
+ if (n >= 4 && !lua_isnil(L, 4))
+ offset = luaL_checkinteger(L, 4);
+
+ if (offset > bufsz || offset + sz > bufsz) {
+ lua_pushnil(L);
+ lua_pushfstring(L,
+ "write: invalid access offset %zu, size %zu in a buffer size %zu",
+ offset, sz, bufsz);
+ lua_pushinteger(L, EINVAL);
+ return 3;
+ }
+
+ ret = write(fd, buf + offset, sz);
+ if (ret < 0) {
+ error = errno;
+ goto err;
+ }
+
+ lua_pushinteger(L, ret);
+ return 1;
+err:
+ lua_pushnil(L);
+ lua_pushstring(L, strerror(error));
+ lua_pushinteger(L, error);
+ return 3;
+}
+
+#define REG_DEF(n, func) { #n, func }
+#define REG_SIMPLE(n) REG_DEF(n, lua_ ## n)
+static const struct luaL_Reg libgenlib[] = {
+ REG_SIMPLE(basename),
+ REG_SIMPLE(dirname),
+ { NULL, NULL },
+};
+
+static const struct luaL_Reg stdliblib[] = {
+ REG_SIMPLE(realpath),
+ { NULL, NULL },
+};
+
static const struct luaL_Reg sys_statlib[] = {
REG_SIMPLE(chmod),
{ NULL, NULL },
};
+static const struct luaL_Reg sys_waitlib[] = {
+ REG_SIMPLE(wait),
+ {NULL, NULL},
+};
+
static const struct luaL_Reg unistdlib[] = {
- REG_SIMPLE(getpid),
+ REG_SIMPLE(_exit),
REG_SIMPLE(chown),
+ REG_DEF(close, lua_pclose),
+ REG_SIMPLE(fork),
+ REG_SIMPLE(getpid),
+ REG_SIMPLE(pipe),
+ REG_SIMPLE(read),
+ REG_SIMPLE(write),
{ NULL, NULL },
};
+
#undef REG_SIMPLE
+#undef REG_DEF
+
+int
+luaopen_posix_libgen(lua_State *L)
+{
+ luaL_newlib(L, libgenlib);
+ return 1;
+}
+
+int
+luaopen_posix_stdlib(lua_State *L)
+{
+ luaL_newlib(L, stdliblib);
+ return 1;
+}
int
luaopen_posix_sys_stat(lua_State *L)
@@ -152,6 +524,30 @@
return 1;
}
+int
+luaopen_posix_sys_wait(lua_State *L)
+{
+ luaL_newlib(L, sys_waitlib);
+
+#define lua_pushflag(L, flag) do { \
+ lua_pushinteger(L, flag); \
+ lua_setfield(L, -2, #flag); \
+} while(0)
+
+ /* Only these two exported by lposix */
+ lua_pushflag(L, WNOHANG);
+ lua_pushflag(L, WUNTRACED);
+
+ lua_pushflag(L, WCONTINUED);
+ lua_pushflag(L, WSTOPPED);
+ lua_pushflag(L, WTRAPPED);
+ lua_pushflag(L, WEXITED);
+ lua_pushflag(L, WNOWAIT);
+#undef lua_pushflag
+
+ return 1;
+}
+
int
luaopen_posix_unistd(lua_State *L)
{
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Feb 11, 5:43 AM (10 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16589479
Default Alt Text
D39083.id119481.diff (9 KB)
Attached To
Mode
D39083: flua: lposix: add more useful functions for general purpose scripts
Attached
Detach File
Event Timeline
Log In to Comment