From d16e151b56840f7e4646dd09b667866b30645b5d Mon Sep 17 00:00:00 2001 From: mark Date: Sun, 29 Jan 2006 06:51:00 +0000 Subject: [PATCH] *** empty log message *** --- posix/Makefile | 5 ++-- posix/ex.c | 71 ++++++++++++++++++++++++++++++++++---------------- 2 files changed, 52 insertions(+), 24 deletions(-) diff --git a/posix/Makefile b/posix/Makefile index 353a26b..0184cd9 100755 --- a/posix/Makefile +++ b/posix/Makefile @@ -3,9 +3,10 @@ DEFINES = -D_POSIX_SOURCE -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=200112L -U__STRI INCLUDES = -I${LUA}/src WARNINGS = -W -Wall LUA = /home/mark/src/lang/lua/lua-5.1-rc2 -LUALIBS = -L$(LUA)/lib -llua51 -LIBS = spawn.a +ex.so: ex.o; $(CC) -shared -o $@ ex.o + +#LIBS = -L$(LUA)/lib -llua51 spawn.a ex.dll: ex.o $(LIBS); $(CC) -shared -o $@ ex.o $(LUALIBS) $(LIBS) spawn.a: spawn.o; $(AR) r $@ $< diff --git a/posix/ex.c b/posix/ex.c index 4a06bbb..932bfb4 100755 --- a/posix/ex.c +++ b/posix/ex.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -10,9 +11,16 @@ #include #include -#include "spawn.h" +#include #include +extern char **environ; + +#define debug(...) fprintf(stderr,__VA_ARGS__) +#define Dposix_spawnp(ppid,cmd,act,attrp,argv,envp) \ + (debug("posix_spawnp(%p,\"%s\",%p,%p,%p,%p)\n",(void*)ppid,cmd,(void*)act,(void*)attrp,(void*)argv,(void*)envp),\ + posix_spawnp(ppid,cmd,act,attrp,argv,envp)) + /* Generally useful function -- what luaL_checkudata() should do */ static void *luaL_checkuserdata(lua_State *L, int idx, const char *tname) @@ -227,14 +235,16 @@ static const char **build_env(lua_State *L) return build_args(L); /* ... */ } -static void get_redirect(lua_State *L, posix_spawn_file_actions_t *file_actions, +static int get_redirect(lua_State *L, posix_spawn_file_actions_t *file_actions, const char *stream, int descriptor) { + int ret; lua_getfield(L, 2, stream); - if (!lua_isnil(L, -1)) + if ((ret = !lua_isnil(L, -1))) posix_spawn_file_actions_adddup2(file_actions, fileno(luaL_checkudata(L, -1, LUA_FILEHANDLE)), descriptor); lua_pop(L, 1); + return ret; } #define PROCESS_HANDLE "process" @@ -248,10 +258,10 @@ struct process { static int ex_spawn(lua_State *L) { const char *command; - posix_spawn_file_actions_t file_actions; const char **argv; const char **envp; - struct process *p; + posix_spawn_file_actions_t file_actions, *pactions = 0; + struct process *proc; int ret; if (lua_type(L, 1) == LUA_TTABLE) { @@ -279,15 +289,16 @@ static int ex_spawn(lua_State *L) /* XXX confusing */ command = luaL_checkstring(L, 1); - /* set defaults */ - argv = 0; - envp = (const char **)environ; - posix_spawn_file_actions_init(&file_actions); - /* get arguments, environment, and redirections */ switch (lua_type(L, 2)) { default: luaL_argerror(L, 2, "expected options table"); break; - case LUA_TNONE: break; + case LUA_TNONE: + argv = lua_newuserdata(L, 2 * sizeof *argv); + argv[0] = command; + argv[1] = 0; + envp = (const char **)environ; + pactions = 0; + break; case LUA_TTABLE: lua_getfield(L, 2, "args"); /* cmd opts ... argtab */ switch (lua_type(L, -1)) { @@ -301,25 +312,40 @@ static int ex_spawn(lua_State *L) luaL_error(L, "cannot specify both the args option and array values"); argv = build_args(L); /* cmd opts ... */ if (!argv[0]) argv[0] = command; + break; } lua_getfield(L, 2, "env"); switch (lua_type(L, -1)) { default: luaL_error(L, "env option must be a table"); break; - case LUA_TNIL: break; + case LUA_TNIL: + envp = (const char **)environ; + break; case LUA_TTABLE: envp = build_env(L); /* cmd opts ... */ + break; + } + posix_spawn_file_actions_init(&file_actions); + if (get_redirect(L, &file_actions, "stdin", STDIN_FILENO) + | get_redirect(L, &file_actions, "stdout", STDOUT_FILENO) + | get_redirect(L, &file_actions, "stderr", STDERR_FILENO)) { + pactions = &file_actions; + } + else { + posix_spawn_file_actions_destroy(&file_actions); + pactions = 0; } - 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); /* cmd opts ... proc */ + proc = lua_newuserdata(L, sizeof *proc); /* cmd opts ... proc */ luaL_getmetatable(L, PROCESS_HANDLE); /* cmd opts ... proc M */ lua_setmetatable(L, -2); /* cmd opts ... proc */ - p->status = -1; - ret = posix_spawnp(&p->pid, command, &file_actions, 0, (char *const *)argv, (char *const *)envp); - posix_spawn_file_actions_destroy(&file_actions); - if (-1 == ret) + proc->status = -1; + assert(argv && argv[0]); + assert(envp && envp[0]); + ret = Dposix_spawnp(&proc->pid, command, pactions, 0, (char *const *)argv, (char *const *)envp); + debug("returns %d:%ld\n", ret, (long)proc->pid); + if (pactions) + posix_spawn_file_actions_destroy(pactions); + if (0 != ret) return posix_error(L); return 1; /* ... proc */ } @@ -328,9 +354,10 @@ static int ex_spawn(lua_State *L) static int process_wait(lua_State *L) { struct process *p = luaL_checkudata(L, 1, PROCESS_HANDLE); - if (p->status != -1) { + if (p->status == -1) { int status; - waitpid(p->pid, &status, 0); + if (-1 == waitpid(p->pid, &status, 0)) + return posix_error(L); p->status = WEXITSTATUS(status); } lua_pushnumber(L, p->status);