Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F109841333
D39083.id120527.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.id120527.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,7 @@
/*-
- * Copyright (c) 2019 Kyle Evans <kevans@FreeBSD.org>
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * 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 +30,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 +47,39 @@
/*
* Minimal implementation of luaposix needed for internal FreeBSD bits.
*/
+static int
+lua__exit(lua_State *L)
+{
+ int code, narg;
+
+ narg = lua_gettop(L);
+ luaL_argcheck(L, narg == 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 narg;
+
+ narg = lua_gettop(L);
+ luaL_argcheck(L, narg > 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);
+ return (3);
+ }
+
+ outpath = basename(inpath);
+ lua_pushstring(L, outpath);
+ free(inpath);
+ return (1);
+}
static int
lua_chmod(lua_State *L)
@@ -59,10 +97,10 @@
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
@@ -122,39 +160,371 @@
}
static int
-lua_getpid(lua_State *L)
+lua_pclose(lua_State *L)
{
- int n;
+ int error, fd, n;
n = lua_gettop(L);
- luaL_argcheck(L, n == 0, 1, "too many arguments");
+ 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 narg;
+
+ narg = lua_gettop(L);
+ luaL_argcheck(L, narg > 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);
+ return (3);
+ }
+
+ outpath = dirname(inpath);
+ lua_pushstring(L, outpath);
+ free(inpath);
+ return (1);
+}
+
+static int
+lua_fork(lua_State *L)
+{
+ pid_t pid;
+ int narg;
+
+ narg = lua_gettop(L);
+ luaL_argcheck(L, narg == 0, 1, "too many arguments");
+
+ pid = fork();
+ if (pid < 0) {
+ lua_pushnil(L);
+ lua_pushstring(L, strerror(errno));
+ lua_pushinteger(L, errno);
+ return (3);
+ }
+
+ lua_pushinteger(L, pid);
+ return (1);
+}
+
+static int
+lua_getpid(lua_State *L)
+{
+ int narg;
+
+ narg = lua_gettop(L);
+ luaL_argcheck(L, narg == 0, 1, "too many arguments");
lua_pushinteger(L, getpid());
- return 1;
+ return (1);
+}
+
+static int
+lua_pipe(lua_State *L)
+{
+ int error, fd[2], narg;
+
+ narg = lua_gettop(L);
+ luaL_argcheck(L, narg == 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, narg;
+
+ narg = lua_gettop(L);
+ luaL_argcheck(L, narg == 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;
+ }
+
+ buf = malloc(sz);
+ if (buf == NULL)
+ 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() */
+
+ free(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 narg;
+
+ narg = lua_gettop(L);
+ luaL_argcheck(L, narg > 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);
+ return (3);
+ }
+
+ lua_pushstring(L, outpath);
+ free(outpath);
+ return (1);
+}
+
+static int
+lua_wait(lua_State *L)
+{
+ pid_t pid;
+ int options, status;
+ int narg;
+
+ narg = lua_gettop(L);
+
+ pid = -1;
+ status = options = 0;
+ if (narg >= 1 && !lua_isnil(L, 1))
+ pid = luaL_checkinteger(L, 1);
+ if (narg >= 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, narg;
+
+ narg = lua_gettop(L);
+ luaL_argcheck(L, narg >= 2, 1,
+ "write takes at least two arguments (fd, buf, sz, off)");
+ luaL_argcheck(L, narg <= 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 (narg >= 3 && !lua_isnil(L, 3))
+ sz = luaL_checkinteger(L, 3);
+
+ offset = 0;
+ if (narg >= 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_SIMPLE(n) { #n, lua_ ## n }
+#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)
{
luaL_newlib(L, sys_statlib);
- return 1;
+ 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)
{
luaL_newlib(L, unistdlib);
- return 1;
+ return (1);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Feb 11, 5:42 AM (10 h, 17 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16589466
Default Alt Text
D39083.id120527.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