From e7e76fe13c1546e792d7b16cc4104228455991f3 Mon Sep 17 00:00:00 2001 From: mark Date: Wed, 18 Jan 2006 03:36:01 +0000 Subject: [PATCH] --- Makefile | 5 ++ posix/osex.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++ sleep.c | 2 + w32api/osex.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 306 insertions(+) create mode 100755 Makefile create mode 100755 posix/osex.c create mode 100755 sleep.c create mode 100755 w32api/osex.c diff --git a/Makefile b/Makefile new file mode 100755 index 0000000..5100fe4 --- /dev/null +++ b/Makefile @@ -0,0 +1,5 @@ +CFLAGS = $(WARNINGS) $(DEFINES) $(INCLUDES) +DEFINES = -D_XOPEN_SOURCE=600 +INCLUDES = -I${LUA}/src +WARNINGS = -W -Wall +LUA = /home/mark/src/lang/lua/lua-5.1 diff --git a/posix/osex.c b/posix/osex.c new file mode 100755 index 0000000..e785400 --- /dev/null +++ b/posix/osex.c @@ -0,0 +1,152 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +extern char **environ; + +/* helper functions */ +static void *safe_alloc(lua_State *L, size_t n) +{ + return lua_newuserdata(L, n); +} + +static int posix_error(lua_State *L) +{ + lua_pushnil(L); + lua_pushstring(L, strerror(errno)); + return 2; +} + + +/* seconds -- */ +static int osex_sleep(lua_State *L) +{ + lua_Number seconds = luaL_checknumber(L, 1); + usleep(1e6 * seconds); + return 0; +} + + +#define PROCESS_HANDLE "process" + +struct process { + pid_t pid; + int status; +}; + +static void get_redirect(lua_State *L, posix_spawn_file_actions_t *file_actions, + const char *stream, int descriptor) +{ + lua_getfield(L, 2, stream); + if (!lua_isnil(L, -1)) + posix_spawn_file_actions_adddup2(file_actions, + fileno(luaL_checkudata(L, -1, LUA_FILEHANDLE)), descriptor); + lua_pop(L, 1); +} + +/* filename [options] -- true/nil,error */ +static int osex_spawn(lua_State *L) +{ + const char *filename = luaL_checkstring(L, 1); + posix_spawn_file_actions_t file_actions; + char **argv; + char **envp; + struct process *p; + if (lua_type(L, 2) == LUA_TTABLE) { + lua_getfield(L, 2, "args"); + if (!lua_isnil(L, -1)) { + luaL_checktype(L, -1, LUA_TTABLE); + /* XXX */ + } + else { + argv = safe_alloc(L, 1 * sizeof *argv); + argv[0] = 0; + } + lua_pop(L, 1); + + lua_getfield(L, 2, "env"); + if (!lua_isnil(L, -1)) { + size_t i, n; + luaL_checktype(L, -1, LUA_TTABLE); + n = lua_objlen(L, -1); + envp = safe_alloc(L, (n + 1) * sizeof *envp); + for (i = 1; i <= n; i++) { + lua_rawgeti(L, -1, i); + luaL_checktype(L, -1, LUA_TSTRING); + /* XXX push onto zz */ + } + } + else { + envp = environ; + } + lua_pop(L, 1); + + get_redirect(L, &file_actions, "stdin", STDIN_FILENO); + get_redirect(L, &file_actions, "stdout", STDOUT_FILENO); + get_redirect(L, &file_actions, "stderr", STDERR_FILENO); + } + p = lua_newuserdata(L, sizeof *p); + luaL_getmetatable(L, PROCESS_HANDLE); + lua_setmetatable(L, -2); + p->status = -1; + if (0 != posix_spawnp(&p->pid, filename, &file_actions, 0, argv, envp)) + return posix_error(L); + return 1; +} + +static int process_wait(lua_State *L) +{ + struct process *p = luaL_checkudata(L, 1, PROCESS_HANDLE); + if (p->status != -1) { + int status; + waitpid(p->pid, &status, 0); + p->status = WEXITSTATUS(status); + } + lua_pushnumber(L, p->status); + return 1; +} + +static const luaL_reg process_lib[] = { + {"wait", process_wait}, + {0,0} +}; + + +static int osex_newpipe(lua_State *L) +{ + int fd[2]; + FILE **pf; + if (0 != pipe(fd)) + return posix_error(L); + luaL_getmetatable(L, LUA_FILEHANDLE); + pf = lua_newuserdata(L, sizeof *pf); + lua_pushvalue(L, -2); + lua_setmetatable(L, -2); + *pf = fdopen(fd[0], "r"); + pf = lua_newuserdata(L, sizeof *pf); + lua_pushvalue(L, -2); + lua_setmetatable(L, -2); + *pf = fdopen(fd[1], "w"); + return 2; +} + + +static const luaL_reg osex_lib[] = { + {"sleep", osex_sleep}, + {"spawn", osex_spawn}, + {"newpipe", osex_newpipe}, + {0,0} +}; + +int luaopen_osex(lua_State *L) +{ + luaL_newmetatable(L, PROCESS_HANDLE); + luaL_register(L, 0, process_lib); + luaL_register(L, "os", osex_lib); + return 1; +} diff --git a/sleep.c b/sleep.c new file mode 100755 index 0000000..10b222c --- /dev/null +++ b/sleep.c @@ -0,0 +1,2 @@ +#include + diff --git a/w32api/osex.c b/w32api/osex.c new file mode 100755 index 0000000..a62e40e --- /dev/null +++ b/w32api/osex.c @@ -0,0 +1,147 @@ +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include + +extern char **environ; + +/* helper functions */ +static void *safe_alloc(lua_State *L, size_t n) +{ + return lua_newuserdata(L, n); +} + +static int windows_error(lua_State *L) +{ + lua_pushnil(L); + lua_pushstring(L, strerror(errno)); + return 2; +} + + +/* seconds -- */ +static int osex_sleep(lua_State *L) +{ + lua_Number seconds = luaL_checknumber(L, 1); + Sleep(1e3 * seconds); + return 0; +} + + +#define PROCESS_HANDLE "process" + +struct process { + HANDLE pid; + int status; +}; + +static void get_redirect(lua_State *L, HANDLE *handle, const char *stream) +{ + lua_getfield(L, 2, stream); + if (!lua_isnil(L, -1)) { + FILE **pf = luaL_checkudata(L, LUA_FILEHANDLE); + *handle = _get_osfhandle(_filen(*pf)); + } + lua_pop(L, 1); +} + +/* filename [options] -- true/nil,error */ +static int osex_spawn(lua_State *L) +{ + size_t len; + const char *filename; + char *cmdline; + char *environment; + struct process *p; + STARTUPINFO si; + PROCESS_INFORMATION pi; + filename = luaL_checklstring(L, 1, &len); + cmdline = safe_alloc(len + 3); + sprintf(cmdline, "\"%s\"", filename); + environment = 0; + si.cb = sizeof si; + si.dwFlags = STARTF_USESTDHANDLES; + si.hStdInput = GetStandardHandle(STD_INPUT_HANDLE); + si.hStdOutput = GetStandardHandle(STD_OUTPUT_HANDLE); + si.hStdError = GetStandardHandle(STD_ERROR_HANDLE); + if (lua_type(L, 2) == LUA_TTABLE) { + lua_getfield(L, 2, "args"); + if (!lua_isnil(L, -1)) { + luaL_checktype(L, -1, LUA_TTABLE); + cmdline = insert_alli(L, -1); + } + lua_pop(L, 1); + + lua_getfield(L, 2, "env"); + if (!lua_isnil(L, -1)) { + luaL_checktype(L, -1, LUA_TTABLE); + environment = insert_all(L, -1); + } + lua_pop(L, 1); + + get_redirect(L, "stdin", &si.hStdInput ); + get_redirect(L, "stdout", &si.hStdOutput); + get_redirect(L, "stderr", &si.hStdError ); + } + p = lua_newuserdata(L, sizeof *p); + luaL_getmetatable(L, PROCESS_HANDLE); + lua_setmetatable(L, -2); + p->status = -1; + if (!CreateProcess(0, cmdline, 0, 0, 0, 0, environment, 0, &si, &pi)) + return windows_error(L); + p->pid = pi.hProcess; + return 1; +} + +static int process_wait(lua_State *L) +{ + struct process *p = luaL_checkudata(L, 1, PROCESS_HANDLE); + if (p->status != -1) { + int status; + waitpid(p->pid, &status, 0); + p->status = WEXITSTATUS(status); + } + lua_pushnumber(L, p->status); + return 1; +} + +static const luaL_reg process_lib[] = { + {"wait", process_wait}, + {0,0} +}; + + +static int osex_newpipe(lua_State *L) +{ + int fd[2]; + FILE **pf; + if (0 != pipe(fd)) + return posix_error(L); + luaL_getmetatable(L, LUA_FILEHANDLE); + pf = lua_newuserdata(L, sizeof *pf); + lua_pushvalue(L, -2); + lua_setmetatable(L, -2); + *pf = fdopen(fd[0], "r"); + pf = lua_newuserdata(L, sizeof *pf); + lua_pushvalue(L, -2); + lua_setmetatable(L, -2); + *pf = fdopen(fd[1], "w"); + return 2; +} + + +static const luaL_reg osex_lib[] = { + {"sleep", osex_sleep}, + {"spawn", osex_spawn}, + {"newpipe", osex_newpipe}, + {0,0} +}; + +int luaopen_osex(lua_State *L) +{ + luaL_newmetatable(L, PROCESS_HANDLE); + luaL_register(L, 0, process_lib); + luaL_register(L, "os", osex_lib); + return 1; +}