Moved spawn_* functions out of ex.c

master
mark 21 years ago
parent ecb5e17609
commit 36cb453953

@ -1,13 +1,19 @@
CFLAGS = -std=c99 $(WARNINGS) $(DEFINES) $(INCLUDES)
DEFINES = -D_POSIX_SOURCE -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=200112L -U__STRICT_ANSI__
INCLUDES = -I$(LUA)/include -I.
DEFINES = -D_POSIX_SOURCE -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=200112L -U__STRICT_ANSI__ -DMISSING_POSIX_SPAWN
INCLUDES = -I$(LUA)/include
WARNINGS = -W -Wall
#LUA = /home/mark/src/lang/lua/lua-5.1-rc2
LUA = /home/mark/src/lang/lua/lua51
ex.so: ex.o; $(CC) -shared -o $@ ex.o
ex-OBJS = ex.o spawn.o
ex.so: $(ex-OBJS); $(CC) -shared -o $@ $(ex-OBJS)
#LIBS = -L$(LUA)/lib -llua51 spawn.a
ex.dll: ex.o $(LIBS); $(CC) -shared -L$(LUA)/bin/Cygwin -o $@ ex.o spawn.o -llua51
EXTRA = posix_spawn.o
ex.dll: $(ex-OBJS) $(LIBS); $(CC) -shared -L$(LUA)/bin/Cygwin -o $@ $(ex-OBJS) $(EXTRA) -llua51
ex.o: ex.c spawn.h
spawn.o: spawn.c spawn.h
posix_spawn.o: posix_spawn.c posix_spawn.h

@ -11,12 +11,11 @@
#include <unistd.h>
#include <fcntl.h>
#include <spawn.h>
#include <sys/wait.h>
#include "spawn.h"
/* Generally useful function -- what luaL_checkudata() should do */
static void *luaL_checkuserdata(lua_State *L, int idx, const char *tname)
void *checkuserdata(lua_State *L, int idx, const char *tname)
{
void *ud;
luaL_argcheck(L, ud = luaL_checkudata(L, idx, tname), idx, tname);
@ -25,7 +24,7 @@ static void *luaL_checkuserdata(lua_State *L, int idx, const char *tname)
/* -- nil error */
static int push_error(lua_State *L)
int push_error(lua_State *L)
{
lua_pushnil(L);
lua_pushstring(L, strerror(errno));
@ -148,7 +147,7 @@ static int file_lock(lua_State *L, FILE *f, const char *mode, long offset, long
/* file mode [offset [length]] -- true/nil error */
static int ex_lock(lua_State *L)
{
FILE **pf = luaL_checkuserdata(L, 1, LUA_FILEHANDLE);
FILE **pf = checkuserdata(L, 1, LUA_FILEHANDLE);
const char *mode = luaL_checkstring(L, 2);
long offset = luaL_optnumber(L, 3, 0);
long length = luaL_optnumber(L, 4, 0);
@ -188,128 +187,6 @@ static int ex_pipe(lua_State *L)
}
struct spawn_params {
lua_State *L;
const char *command, **argv, **envp;
posix_spawn_file_actions_t file_actions;
int has_actions;
};
/* filename ... */
static void spawn_param_filename(struct spawn_params *p)
{
/* XXX confusing */
p->command = luaL_checkstring(p->L, 1);
}
/* -- */
static void spawn_param_defaults(struct spawn_params *p)
{
p->argv = lua_newuserdata(p->L, 2 * sizeof *p->argv);
p->argv[0] = p->command;
p->argv[1] = 0;
p->envp = (const char **)environ;
p->has_actions = 0;
}
/* Converts a Lua array of strings to a null-terminated array of char pointers.
* Pops a (0-based) Lua array and replaces it with a userdatum which is the
* null-terminated C array of char pointers. The elements of this array point
* to the strings in the Lua array. These strings should be associated with
* this userdatum via a weak table for GC purposes, but they are not here.
* Therefore, any function which calls this must make sure that these strings
* remain available until the userdatum is thrown away.
*/
/* ... array -- ... vector */
static const char **make_vector(lua_State *L)
{
size_t i, n = lua_objlen(L, -1);
const char **vec = lua_newuserdata(L, (n + 2) * sizeof *vec);
/* ... arr vec */
for (i = 0; i <= n; i++) {
lua_rawgeti(L, -2, i); /* ... arr vec elem */
vec[i] = lua_tostring(L, -1);
lua_pop(L, 1); /* ... arr vec */
}
vec[n + 1] = 0;
lua_replace(L, -2); /* ... vector */
return vec;
}
/* ... argtab */
static void spawn_param_args(struct spawn_params *p)
{
const char **argv = make_vector(p->L);
if (!argv[0]) argv[0] = p->command;
p->argv = argv;
}
/* ... envtab/nil */
static void spawn_param_env(struct spawn_params *p)
{
size_t i = 0;
luaL_Buffer estr;
if (lua_isnil(p->L, -1)) {
p->envp = (const char **)environ;
return;
}
luaL_buffinit(p->L, &estr);
lua_newtable(p->L); /* ... envtab arr */
lua_pushnil(p->L); /* ... envtab arr nil */
for (i = 0; lua_next(p->L, -3); i++) { /* ... envtab arr k v */
luaL_prepbuffer(&estr);
lua_pushvalue(p->L, -2); /* ... envtab arr k v k */
luaL_addvalue(&estr);
luaL_putchar(&estr, '=');
lua_pop(p->L, 1); /* ... envtab arr k v */
luaL_addvalue(&estr);
lua_pop(p->L, 1); /* ... envtab arr k */
luaL_pushresult(&estr); /* ... envtab arr k estr */
lua_rawseti(p->L, -3, i); /* ... envtab arr[n]=estr k */
} /* ... envtab arr */
lua_replace(p->L, -2); /* ... arr */
make_vector(p->L); /* ... arr */
}
/* _ opts ... */
static int get_redirect(struct spawn_params *p, const char *stdname, int descriptor)
{
int ret;
lua_getfield(p->L, 2, stdname);
if ((ret = !lua_isnil(p->L, -1)))
/* XXX luaL_checkuserdata is confusing here */
posix_spawn_file_actions_adddup2(&p->file_actions,
fileno(luaL_checkuserdata(p->L, -1, LUA_FILEHANDLE)), descriptor);
lua_pop(p->L, 1);
return ret;
}
/* _ opts ... */
static void spawn_param_redirects(struct spawn_params *p)
{
posix_spawn_file_actions_init(&p->file_actions);
p->has_actions = 1;
get_redirect(p, "stdin", STDIN_FILENO);
get_redirect(p, "stdout", STDOUT_FILENO);
get_redirect(p, "stderr", STDERR_FILENO);
}
#define PROCESS_HANDLE "process"
struct process {
int status;
pid_t pid;
};
static int spawn_param_execute(struct spawn_params *p, struct process *proc)
{
int ret;
proc->status = -1;
ret = posix_spawnp(&proc->pid, p->command, &p->file_actions, 0, (char *const *)p->argv, (char *const *)p->envp);
if (p->has_actions)
posix_spawn_file_actions_destroy(&p->file_actions);
return ret == 0;
}
/* filename [args-opts] -- true/nil,error */
/* args-opts -- true/nil,error */
static int ex_spawn(lua_State *L)
@ -381,20 +258,6 @@ static int ex_spawn(lua_State *L)
return 1; /* ... proc */
}
/* proc -- exitcode/nil error */
static int process_wait(lua_State *L)
{
struct process *p = luaL_checkuserdata(L, 1, PROCESS_HANDLE);
if (p->status == -1) {
int status;
if (-1 == waitpid(p->pid, &status, 0))
return push_error(L);
p->status = WEXITSTATUS(status);
}
lua_pushnumber(L, p->status);
return 1;
}
static const luaL_reg ex_iolib[] = {
{"pipe", ex_pipe},

@ -0,0 +1,135 @@
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include "spawn.h"
extern int push_error(lua_State *L);
extern void *checkuserdata(lua_State *L, int index, const char *name);
/* filename ... */
void spawn_param_filename(struct spawn_params *p)
{
/* XXX confusing */
p->command = luaL_checkstring(p->L, 1);
}
/* -- */
void spawn_param_defaults(struct spawn_params *p)
{
p->argv = lua_newuserdata(p->L, 2 * sizeof *p->argv);
p->argv[0] = p->command;
p->argv[1] = 0;
p->envp = (const char **)environ;
p->has_actions = 0;
}
/* Converts a Lua array of strings to a null-terminated array of char pointers.
* Pops a (0-based) Lua array and replaces it with a userdatum which is the
* null-terminated C array of char pointers. The elements of this array point
* to the strings in the Lua array. These strings should be associated with
* this userdatum via a weak table for GC purposes, but they are not here.
* Therefore, any function which calls this must make sure that these strings
* remain available until the userdatum is thrown away.
*/
/* ... array -- ... vector */
static const char **make_vector(lua_State *L)
{
size_t i, n = lua_objlen(L, -1);
const char **vec = lua_newuserdata(L, (n + 2) * sizeof *vec);
/* ... arr vec */
for (i = 0; i <= n; i++) {
lua_rawgeti(L, -2, i); /* ... arr vec elem */
vec[i] = lua_tostring(L, -1);
lua_pop(L, 1); /* ... arr vec */
}
vec[n + 1] = 0;
lua_replace(L, -2); /* ... vector */
return vec;
}
/* ... argtab */
void spawn_param_args(struct spawn_params *p)
{
const char **argv = make_vector(p->L);
if (!argv[0]) argv[0] = p->command;
p->argv = argv;
}
/* ... envtab/nil */
void spawn_param_env(struct spawn_params *p)
{
size_t i = 0;
luaL_Buffer estr;
if (lua_isnil(p->L, -1)) {
p->envp = (const char **)environ;
return;
}
luaL_buffinit(p->L, &estr);
lua_newtable(p->L); /* ... envtab arr */
lua_pushnil(p->L); /* ... envtab arr nil */
for (i = 0; lua_next(p->L, -3); i++) { /* ... envtab arr k v */
luaL_prepbuffer(&estr);
lua_pushvalue(p->L, -2); /* ... envtab arr k v k */
luaL_addvalue(&estr);
luaL_putchar(&estr, '=');
lua_pop(p->L, 1); /* ... envtab arr k v */
luaL_addvalue(&estr);
lua_pop(p->L, 1); /* ... envtab arr k */
luaL_pushresult(&estr); /* ... envtab arr k estr */
lua_rawseti(p->L, -3, i); /* ... envtab arr[n]=estr k */
} /* ... envtab arr */
lua_replace(p->L, -2); /* ... arr */
make_vector(p->L); /* ... arr */
}
/* _ opts ... */
static int get_redirect(struct spawn_params *p, const char *stdname, int descriptor)
{
int ret;
lua_getfield(p->L, 2, stdname);
if ((ret = !lua_isnil(p->L, -1)))
/* XXX checkuserdata is confusing here */
posix_spawn_file_actions_adddup2(&p->file_actions,
fileno(checkuserdata(p->L, -1, LUA_FILEHANDLE)), descriptor);
lua_pop(p->L, 1);
return ret;
}
/* _ opts ... */
void spawn_param_redirects(struct spawn_params *p)
{
posix_spawn_file_actions_init(&p->file_actions);
p->has_actions = 1;
get_redirect(p, "stdin", STDIN_FILENO);
get_redirect(p, "stdout", STDOUT_FILENO);
get_redirect(p, "stderr", STDERR_FILENO);
}
int spawn_param_execute(struct spawn_params *p, struct process *proc)
{
int ret;
proc->status = -1;
ret = posix_spawnp(&proc->pid, p->command, &p->file_actions, 0, (char *const *)p->argv, (char *const *)p->envp);
if (p->has_actions)
posix_spawn_file_actions_destroy(&p->file_actions);
return ret == 0;
}
/* proc -- exitcode/nil error */
int process_wait(lua_State *L)
{
struct process *p = checkuserdata(L, 1, PROCESS_HANDLE);
if (p->status == -1) {
int status;
if (-1 == waitpid(p->pid, &status, 0))
return push_error(L);
p->status = WEXITSTATUS(status);
}
lua_pushnumber(L, p->status);
return 1;
}

@ -0,0 +1,32 @@
#ifndef SPAWN_H
#define SPAWN_H
#ifdef MISSING_POSIX_SPAWN
#include "posix_spawn.h"
#endif
#include <lua.h>
#include <sys/types.h>
#define PROCESS_HANDLE "process"
struct process {
int status;
pid_t pid;
};
struct spawn_params {
lua_State *L;
const char *command, **argv, **envp;
posix_spawn_file_actions_t file_actions;
int has_actions;
};
void spawn_param_filename(struct spawn_params *p);
void spawn_param_defaults(struct spawn_params *p);
void spawn_param_args(struct spawn_params *p);
void spawn_param_env(struct spawn_params *p);
void spawn_param_redirects(struct spawn_params *p);
int spawn_param_execute(struct spawn_params *p, struct process *proc);
int process_wait(lua_State *L);
#endif/*SPAWN_H*/

@ -7,5 +7,6 @@ WARNINGS = -W -Wall -Wno-missing-braces
LUA = /home/mark/src/lang/lua/lua51
LUALIBS = -L$(LUA)/bin/mingw -llua51
ex.dll: ex.o
$(CC) $(TARGET_ARCH) -shared -o $@ ex.o $(LUALIBS) /c/windows/system32/msvcrt.dll
ex.dll-OBJS = ex.o spawn.o
ex.dll: $(ex.dll-OBJS)
$(CC) $(TARGET_ARCH) -shared -o $@ $(ex.dll-OBJS) $(LUALIBS) /c/windows/system32/msvcrt.dll

@ -12,15 +12,23 @@
#include <fcntl.h>
#include <sys/locking.h>
#include "spawn.h"
/* Generally useful function -- what luaL_checkudata() should do */
static void *luaL_checkuserdata(lua_State *L, int idx, const char *tname)
extern void *checkuserdata(lua_State *L, int idx, const char *tname)
{
void *ud;
luaL_argcheck(L, ud = luaL_checkudata(L, idx, tname), idx, tname);
return ud;
}
/* return HANDLE from a FILE */
extern HANDLE get_handle(FILE *f)
{
return (HANDLE)_get_osfhandle(fileno(f));
}
/* -- nil error */
static int push_error(lua_State *L)
@ -135,11 +143,6 @@ static int ex_currentdir(lua_State *L)
return 1;
}
static HANDLE get_handle(FILE *f)
{
return (HANDLE)_get_osfhandle(fileno(f));
}
/* pathname -- iter state nil */
static int ex_dir(lua_State *L) { return luaL_error(L, "not yet implemented"); }
@ -174,7 +177,7 @@ static int file_lock(lua_State *L, FILE *f, const char *mode, long offset, long
/* file mode [offset [length]] -- true/nil error */
static int ex_lock(lua_State *L)
{
FILE **pf = luaL_checkuserdata(L, 1, LUA_FILEHANDLE);
FILE **pf = checkuserdata(L, 1, LUA_FILEHANDLE);
const char *mode = luaL_checkstring(L, 2);
long offset = luaL_optnumber(L, 3, 0);
long length = luaL_optnumber(L, 4, 0);
@ -216,146 +219,6 @@ static int ex_pipe(lua_State *L)
}
struct spawn_params {
lua_State *L;
const char *cmdline;
const char *environment;
STARTUPINFO si;
};
static int needs_quoting(const char *s)
{
return s[0] != '"' && strchr(s, ' ');
}
/* filename ... */
static void spawn_param_filename(struct spawn_params *p)
{
/* XXX luaL_checkstring is confusing here */
p->cmdline = luaL_checkstring(p->L, 1);
if (needs_quoting(p->cmdline)) {
lua_pushliteral(p->L, "\""); /* cmd ... q */
lua_pushvalue(p->L, 1); /* cmd ... q cmd */
lua_pushvalue(p->L, -2); /* cmd ... q cmd q */
lua_concat(p->L, 3); /* cmd ... "cmd" */
lua_replace(p->L, 1); /* "cmd" ... */
p->cmdline = lua_tostring(p->L, 1);
}
}
/* -- */
static void spawn_param_defaults(struct spawn_params *p)
{
p->environment = 0;
memset(&p->si, 0, sizeof p->si);
p->si.cb = sizeof p->si;
}
/* cmd opts ... argtab -- cmd opts ... cmdline */
static void spawn_param_args(struct spawn_params *p)
{
lua_State *L = p->L;
luaL_Buffer args;
luaL_buffinit(L, &args);
size_t i, n = lua_objlen(L, -1);
/* concatenate the arg array to a string */
for (i = 1; i <= n; i++) {
int quote;
lua_rawgeti(L, -1, i); /* ... argtab arg */
/* XXX checkstring is confusing here */
quote = needs_quoting(luaL_checkstring(L, -1));
luaL_putchar(&args, ' ');
if (quote) luaL_putchar(&args, '"');
luaL_addvalue(&args);
if (quote) luaL_putchar(&args, '"');
lua_pop(L, 1); /* ... argtab */
}
luaL_pushresult(&args); /* ... argtab argstr */
lua_pushvalue(L, 1); /* cmd opts ... argtab argstr cmd */
lua_replace(L, -2); /* cmd opts ... argtab cmd argstr */
lua_concat(L, 2); /* cmd opts ... argtab cmdline */
lua_replace(L, -2); /* cmd opts ... cmdline */
p->cmdline = lua_tostring(L, -1);
}
/* ... envtab */
static void spawn_param_env(struct spawn_params *p)
{
lua_State *L = p->L;
luaL_Buffer env;
if (lua_isnil(L, -1)) {
p->environment = 0;
lua_pop(L, 1);
return;
}
/* convert env table to zstring list */
/* {nam1=val1,nam2=val2} => "nam1=val1\0nam2=val2\0\0" */
luaL_buffinit(L, &env);
lua_pushnil(L); /* ... envtab nil */
while (lua_next(L, -2)) { /* ... envtab k v */
/* XXX luaL_checktype is confusing here */
luaL_checktype(L, -2, LUA_TSTRING);
luaL_checktype(L, -1, LUA_TSTRING);
lua_pushvalue(L, -2); /* ... envtab k v k */
luaL_addvalue(&env);
luaL_putchar(&env, '=');
lua_pop(L, 1); /* ... envtab k v */
luaL_addvalue(&env);
luaL_putchar(&env, '\0');
lua_pop(L, 1); /* ... envtab k */
}
luaL_putchar(&env, '\0');
luaL_pushresult(&env); /* ... envtab envstr */
lua_replace(L, -2); /* ... envtab envstr */
p->environment = lua_tostring(L, -1);
}
/* _ opts ... */
static int get_redirect(struct spawn_params *p, const char *stdname, HANDLE *ph)
{
int ret;
lua_getfield(p->L, 2, stdname);
if ((ret = !lua_isnil(p->L, -1))) {
/* XXX checkuserdata is confusing here */
FILE **pf = luaL_checkuserdata(p->L, -1, LUA_FILEHANDLE);
*ph = get_handle(*pf);
}
lua_pop(p->L, 1);
return ret;
}
/* _ opts ... */
static void spawn_param_redirects(struct spawn_params *p)
{
p->si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
p->si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
p->si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
if (get_redirect(p, "stdin", &p->si.hStdInput)
| get_redirect(p, "stdout", &p->si.hStdOutput)
| get_redirect(p, "stderr", &p->si.hStdError))
p->si.dwFlags = STARTF_USESTDHANDLES;
}
#define PROCESS_HANDLE "process"
struct process {
int status;
HANDLE hProcess;
};
static int spawn_param_execute(struct spawn_params *p, struct process *proc)
{
char *c = strdup(p->cmdline);
char *e = (char *)p->environment; // strdup(p->environment);
PROCESS_INFORMATION pi;
proc->status = -1;
/* XXX does CreateProcess modify its environment argument? */
int ret = CreateProcess(0, c, 0, 0, 0, 0, e, 0, &p->si, &pi);
if (e) free(e);
free(c);
if (ret) proc->hProcess = pi.hProcess;
return ret;
}
/* filename [args-opts] -- true/nil,error */
/* args-opts -- true/nil,error */
static int ex_spawn(lua_State *L)
@ -427,20 +290,6 @@ static int ex_spawn(lua_State *L)
return 1; /* ... proc */
}
/* proc -- exitcode/nil error */
static int process_wait(lua_State *L)
{
struct process *p = luaL_checkuserdata(L, 1, PROCESS_HANDLE);
if (p->status == -1) {
DWORD exitcode;
WaitForSingleObject(p->hProcess, INFINITE);
GetExitCodeProcess(p->hProcess, &exitcode);
p->status = exitcode;
}
lua_pushnumber(L, p->status);
return 1;
}
static const luaL_reg ex_iolib[] = {
{"pipe", ex_pipe},

@ -0,0 +1,153 @@
#include <stdlib.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include <windows.h>
#include "spawn.h"
extern void *checkuserdata(lua_State *L, int index, const char *name);
extern HANDLE get_handle(FILE *f);
static int needs_quoting(const char *s)
{
return s[0] != '"' && strchr(s, ' ');
}
/* filename ... */
void spawn_param_filename(struct spawn_params *p)
{
/* XXX luaL_checkstring is confusing here */
p->cmdline = luaL_checkstring(p->L, 1);
if (needs_quoting(p->cmdline)) {
lua_pushliteral(p->L, "\""); /* cmd ... q */
lua_pushvalue(p->L, 1); /* cmd ... q cmd */
lua_pushvalue(p->L, -2); /* cmd ... q cmd q */
lua_concat(p->L, 3); /* cmd ... "cmd" */
lua_replace(p->L, 1); /* "cmd" ... */
p->cmdline = lua_tostring(p->L, 1);
}
}
/* -- */
void spawn_param_defaults(struct spawn_params *p)
{
p->environment = 0;
memset(&p->si, 0, sizeof p->si);
p->si.cb = sizeof p->si;
}
/* cmd opts ... argtab -- cmd opts ... cmdline */
void spawn_param_args(struct spawn_params *p)
{
lua_State *L = p->L;
luaL_Buffer args;
luaL_buffinit(L, &args);
size_t i, n = lua_objlen(L, -1);
/* concatenate the arg array to a string */
for (i = 1; i <= n; i++) {
int quote;
lua_rawgeti(L, -1, i); /* ... argtab arg */
/* XXX checkstring is confusing here */
quote = needs_quoting(luaL_checkstring(L, -1));
luaL_putchar(&args, ' ');
if (quote) luaL_putchar(&args, '"');
luaL_addvalue(&args);
if (quote) luaL_putchar(&args, '"');
lua_pop(L, 1); /* ... argtab */
}
luaL_pushresult(&args); /* ... argtab argstr */
lua_pushvalue(L, 1); /* cmd opts ... argtab argstr cmd */
lua_replace(L, -2); /* cmd opts ... argtab cmd argstr */
lua_concat(L, 2); /* cmd opts ... argtab cmdline */
lua_replace(L, -2); /* cmd opts ... cmdline */
p->cmdline = lua_tostring(L, -1);
}
/* ... envtab */
void spawn_param_env(struct spawn_params *p)
{
lua_State *L = p->L;
luaL_Buffer env;
if (lua_isnil(L, -1)) {
p->environment = 0;
lua_pop(L, 1);
return;
}
/* convert env table to zstring list */
/* {nam1=val1,nam2=val2} => "nam1=val1\0nam2=val2\0\0" */
luaL_buffinit(L, &env);
lua_pushnil(L); /* ... envtab nil */
while (lua_next(L, -2)) { /* ... envtab k v */
/* XXX luaL_checktype is confusing here */
luaL_checktype(L, -2, LUA_TSTRING);
luaL_checktype(L, -1, LUA_TSTRING);
lua_pushvalue(L, -2); /* ... envtab k v k */
luaL_addvalue(&env);
luaL_putchar(&env, '=');
lua_pop(L, 1); /* ... envtab k v */
luaL_addvalue(&env);
luaL_putchar(&env, '\0');
lua_pop(L, 1); /* ... envtab k */
}
luaL_putchar(&env, '\0');
luaL_pushresult(&env); /* ... envtab envstr */
lua_replace(L, -2); /* ... envtab envstr */
p->environment = lua_tostring(L, -1);
}
/* _ opts ... */
static int get_redirect(struct spawn_params *p, const char *stdname, HANDLE *ph)
{
int ret;
lua_getfield(p->L, 2, stdname);
if ((ret = !lua_isnil(p->L, -1))) {
/* XXX checkuserdata is confusing here */
FILE **pf = checkuserdata(p->L, -1, LUA_FILEHANDLE);
*ph = get_handle(*pf);
}
lua_pop(p->L, 1);
return ret;
}
/* _ opts ... */
void spawn_param_redirects(struct spawn_params *p)
{
p->si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
p->si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
p->si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
if (get_redirect(p, "stdin", &p->si.hStdInput)
| get_redirect(p, "stdout", &p->si.hStdOutput)
| get_redirect(p, "stderr", &p->si.hStdError))
p->si.dwFlags = STARTF_USESTDHANDLES;
}
int spawn_param_execute(struct spawn_params *p, struct process *proc)
{
char *c = strdup(p->cmdline);
char *e = (char *)p->environment; // strdup(p->environment);
PROCESS_INFORMATION pi;
proc->status = -1;
/* XXX does CreateProcess modify its environment argument? */
int ret = CreateProcess(0, c, 0, 0, 0, 0, e, 0, &p->si, &pi);
if (e) free(e);
free(c);
if (ret) proc->hProcess = pi.hProcess;
return ret;
}
/* proc -- exitcode/nil error */
int process_wait(lua_State *L)
{
struct process *p = checkuserdata(L, 1, PROCESS_HANDLE);
if (p->status == -1) {
DWORD exitcode;
WaitForSingleObject(p->hProcess, INFINITE);
GetExitCodeProcess(p->hProcess, &exitcode);
p->status = exitcode;
}
lua_pushnumber(L, p->status);
return 1;
}

@ -0,0 +1,29 @@
#ifndef SPAWN_H
#define SPAWN_H
#include <lua.h>
#include <windows.h>
struct spawn_params {
lua_State *L;
const char *cmdline;
const char *environment;
STARTUPINFO si;
};
#define PROCESS_HANDLE "process"
struct process {
int status;
HANDLE hProcess;
};
void spawn_param_filename(struct spawn_params *p);
void spawn_param_defaults(struct spawn_params *p);
void spawn_param_args(struct spawn_params *p);
void spawn_param_env(struct spawn_params *p);
void spawn_param_redirects(struct spawn_params *p);
int spawn_param_execute(struct spawn_params *p, struct process *proc);
int process_wait(lua_State *L);
#endif/*SPAWN_H*/
Loading…
Cancel
Save