From 0925ba938ea6e4002e3fb2756b3106746d6dc52c Mon Sep 17 00:00:00 2001 From: mark Date: Sat, 26 May 2007 05:36:04 +0000 Subject: [PATCH] *** empty log message *** --- Makefile | 1 + posix/Makefile | 2 +- posix/ex.c | 2 +- posix/spawn.c | 50 ++++++++++------- w32api/Makefile | 2 +- w32api/ex.c | 10 ++-- w32api/spawn.c | 139 ++++++++++++++++++++++++++++++------------------ w32api/spawn.h | 2 +- 8 files changed, 128 insertions(+), 80 deletions(-) diff --git a/Makefile b/Makefile index f31bd36..7043716 100755 --- a/Makefile +++ b/Makefile @@ -8,3 +8,4 @@ linux:; $(MAKE) -C posix ex.so clean: $(MAKE) -C posix clean $(MAKE) -C w32api clean + diff --git a/posix/Makefile b/posix/Makefile index 5bcaa76..b83c328 100755 --- a/posix/Makefile +++ b/posix/Makefile @@ -3,7 +3,7 @@ include ../conf CFLAGS= $(WARNINGS) $(DEFINES) $(INCLUDES) DEFINES= -D_XOPEN_SOURCE=600 $(POSIX_SPAWN) $(ENVIRON) INCLUDES= $(LUAINC) -WARNINGS= -W -Wall -std=c89 +WARNINGS= -W -Wall LIBS= $(LUALIB) T= ex.so diff --git a/posix/ex.c b/posix/ex.c index 4f337cc..61deaa2 100755 --- a/posix/ex.c +++ b/posix/ex.c @@ -237,7 +237,7 @@ static int ex_dir(lua_State *L) pd = luaL_checkudata(L, 1, DIR_HANDLE); do d = readdir(*pd); while (d && isdotfile(d->d_name)); - if (!d) return push_error(L); + if (!d) { diriter_close(L); return push_error(L); } new_dirent(L); /* diriter ... entry */ diriter_getpathname(L, 1); /* diriter ... entry dir */ lua_pushstring(L, d->d_name); /* diriter ... entry dir name */ diff --git a/posix/spawn.c b/posix/spawn.c index d6232e5..7fa27bd 100755 --- a/posix/spawn.c +++ b/posix/spawn.c @@ -57,6 +57,11 @@ static const char **make_vector(lua_State *L) for (i = 0; i <= n; i++) { lua_rawgeti(L, -2, i); /* ... arr vec elem */ vec[i] = lua_tostring(L, -1); + if (!vec[i]) { + luaL_error(L, "expected string for argument %d, got %s", + i, lua_typename(L, lua_type(L, -1))); + return 0; + } lua_pop(L, 1); /* ... arr vec */ } vec[n + 1] = 0; @@ -64,7 +69,7 @@ static const char **make_vector(lua_State *L) return vec; } -/* ... argtab */ +/* ... argtab -- ... argtab vector */ void spawn_param_args(struct spawn_params *p) { const char **argv = make_vector(p->L); @@ -72,27 +77,34 @@ void spawn_param_args(struct spawn_params *p) p->argv = argv; } -/* ... envtab */ +/* ... envtab -- ... envtab vector */ void spawn_param_env(struct spawn_params *p) { + lua_State *L = p->L; size_t i = 0; - luaL_Buffer estr; - 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 */ + lua_newtable(L); /* ... envtab arr */ + lua_pushliteral(L, "="); /* ... envtab arr "=" */ + lua_pushnil(L); /* ... envtab arr "=" nil */ + for (i = 0; lua_next(L, -3); i++) { /* ... envtab arr "=" k v */ + if (!lua_tostring(L, -2)) { + luaL_error(L, "expected string for environment variable name, got %s", + lua_typename(L, lua_type(L, -2))); + return; + } + if (!lua_tostring(L, -1)) { + luaL_error(L, "expected string for environment variable value, got %s", + lua_typename(L, lua_type(L, -1))); + return; + } + lua_pushvalue(L, -2); /* ... envtab arr "=" k v k */ + lua_pushvalue(L, -5); /* ... envtab arr "=" k v k "=" */ + lua_pushvalue(L, -3); /* ... envtab arr "=" k v k "=" v */ + lua_concat(L, 3); /* ... envtab arr "=" k v "k=v" */ + lua_rawseti(L, -4, i); /* ... envtab arr "=" k v */ + lua_pop(L, 1); /* ... envtab arr "=" k */ + } /* ... envtab arr "=" */ + lua_pop(L, 1); /* ... envtab arr */ + make_vector(L); /* ... envtab arr vector */ } void spawn_param_redirect(struct spawn_params *p, const char *stdname, int fd) diff --git a/w32api/Makefile b/w32api/Makefile index 0f32736..5109357 100755 --- a/w32api/Makefile +++ b/w32api/Makefile @@ -4,7 +4,7 @@ TARGET_ARCH= -mno-cygwin CFLAGS= $(WARNINGS) $(DEFINES) $(INCLUDES) DEFINES= -DWIN32_LEAN_AND_MEAN -DNOGDI INCLUDES= $(LUAINC) -WARNINGS= -W -Wall -Wno-missing-braces +WARNINGS= -W -Wall OBJS= ex.o spawn.o pusherror.o dirent.o LIBS= $(LUALIB) diff --git a/w32api/ex.c b/w32api/ex.c index 066b867..56e98e8 100755 --- a/w32api/ex.c +++ b/w32api/ex.c @@ -148,7 +148,7 @@ static lua_Number qword_to_number(DWORD hi, DWORD lo) /* lua_Number must be floating-point or as large or larger than * two DWORDs in order to be considered adequate for representing * large file sizes */ - assert(hi == 0 + lua_assert(hi == 0 || (lua_Number)0.5 > 0 || sizeof(lua_Number) > 2 * sizeof(DWORD) || !"lua_Number cannot adequately represent large file sizes" ); @@ -275,6 +275,8 @@ static int ex_dir(lua_State *L) const WIN32_FIND_DATA *d; switch (lua_type(L, 1)) { default: return luaL_typerror(L, 1, "pathname"); + case LUA_TNONE: + lua_pushliteral(L, "."); case LUA_TSTRING: pathname = lua_tostring(L, 1); lua_pushcfunction(L, ex_dir); /* pathname ... iter */ @@ -304,12 +306,12 @@ static int ex_dir(lua_State *L) /*NOTREACHED*/ } -static const ULARGE_INTEGER zero_len; -static const OVERLAPPED zero_ov; static int file_lock(lua_State *L, FILE *f, const char *mode, long offset, long length) { + static const ULARGE_INTEGER zero_len; + static const OVERLAPPED zero_ov; HANDLE h = file_handle(f); ULARGE_INTEGER len = zero_len; OVERLAPPED ov = zero_ov; @@ -431,7 +433,7 @@ static int ex_spawn(lua_State *L) } params = spawn_param_init(L); /* get filename to execute */ - spawn_param_filename(params, lua_tostring(L, 1)); + spawn_param_filename(params); /* get arguments, environment, and redirections */ if (have_options) { lua_getfield(L, 2, "args"); /* cmd opts ... argtab */ diff --git a/w32api/spawn.c b/w32api/spawn.c index 11fdc34..6ac70b2 100755 --- a/w32api/spawn.c +++ b/w32api/spawn.c @@ -18,11 +18,6 @@ #define file_handle(fp) (HANDLE)_get_osfhandle(fileno(fp)) -static int needs_quoting(const char *s) -{ - return s[0] != '"' && strchr(s, ' '); -} - struct spawn_params { lua_State *L; const char *cmdline; @@ -30,6 +25,30 @@ struct spawn_params { STARTUPINFO si; }; +/* quotes and adds argument string to b */ +static int add_argument(luaL_Buffer *b, const char *s) { + int oddbs = 0; + luaL_addchar(b, '"'); + for (; *s; s++) { + switch (*s) { + case '\\': + luaL_addchar(b, '\\'); + oddbs = !oddbs; + break; + case '"': + luaL_addchar(b, '\\'); + oddbs = 0; + break; + default: + oddbs = 0; + break; + } + luaL_addchar(b, *s); + } + luaL_addchar(b, '"'); + return oddbs; +} + struct spawn_params *spawn_param_init(lua_State *L) { static const STARTUPINFO si = {sizeof si}; @@ -40,71 +59,85 @@ struct spawn_params *spawn_param_init(lua_State *L) return p; } -void spawn_param_filename(struct spawn_params *p, const char *filename) +/* cmd ... -- cmd ... */ +void spawn_param_filename(struct spawn_params *p) { - p->cmdline = filename; - if (needs_quoting(p->cmdline)) { - lua_pushliteral(p->L, "\""); /* cmd ... q */ - lua_pushstring(p->L, p->cmdline); /* cmd ... q cmd */ - lua_pushvalue(p->L, -2); /* cmd ... q cmd q */ - lua_concat(p->L, 3); /* cmd ... "cmd" */ - p->cmdline = lua_tostring(p->L, -1); + lua_State *L = p->L; + luaL_Buffer b; + luaL_buffinit(L, &b); + if (add_argument(&b, lua_tostring(L, 1))) { + luaL_error(L, "argument ends in odd number of backslashes"); + return; } + luaL_pushresult(&b); + lua_replace(L, 1); + p->cmdline = lua_tostring(L, 1); } -/* cmd opts ... argtab -- cmd opts ... cmdline */ +/* cmd ... argtab -- cmdline ... */ void spawn_param_args(struct spawn_params *p) { lua_State *L = p->L; - size_t i, n = lua_objlen(L, -1); - luaL_Buffer args; + int argtab = lua_gettop(L); + size_t i, n = lua_objlen(L, argtab); + luaL_Buffer b; debug("spawn_param_args:"); debug_stack(L); - luaL_buffinit(L, &args); + lua_pushnil(L); /* cmd opts ... argtab nil */ + luaL_buffinit(L, &b); /* cmd opts ... argtab nil b... */ + lua_pushvalue(L, 1); /* cmd opts ... argtab nil b... cmd */ + luaL_addvalue(&b); /* cmd opts ... argtab nil b... */ /* concatenate the arg array to a string */ for (i = 1; i <= n; i++) { - int quote; - lua_rawgeti(L, -1, i); /* ... argtab arg */ + const char *s; + lua_rawgeti(L, argtab, i); /* cmd opts ... argtab nil b... arg */ + lua_replace(L, argtab + 1); /* cmd opts ... argtab arg b... */ + luaL_addchar(&b, ' '); /* 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 */ + s = lua_tostring(L, argtab + 1); + if (!s) { + luaL_error(L, "expected string for argument %d, got %s", + i, lua_typename(L, lua_type(L, argtab + 1))); + return; + } + add_argument(&b, luaL_checkstring(L, argtab + 1)); + } + luaL_pushresult(&b); /* cmd opts ... argtab arg cmdline */ + lua_replace(L, 1); /* cmdline opts ... argtab arg */ + lua_pop(L, 2); /* cmdline opts ... */ + p->cmdline = lua_tostring(L, 1); +} + +/* ... tab nil nil [...] -- ... tab envstr */ +static char *add_env(lua_State *L, int tab, size_t where) { + char *t; + lua_checkstack(L, 2); + lua_pushvalue(L, -2); + if (lua_next(L, tab)) { + size_t klen, vlen; + const char *key = lua_tolstring(L, -2, &klen); + const char *val = lua_tolstring(L, -1, &vlen); + t = add_env(L, tab, where + klen + vlen + 2); + memcpy(&t[where], key, klen); + t[where += klen] = '='; + memcpy(&t[where + 1], val, vlen + 1); + } + else { + t = lua_newuserdata(L, where + 1); + t[where] = '\0'; + lua_replace(L, tab + 1); } - luaL_pushresult(&args); /* ... argtab argstr */ - lua_pushvalue(L, 1); /* cmd opts ... argtab argstr cmd */ - lua_insert(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); + return t; } -/* ... envtab/nil */ +/* ... envtab -- ... envtab envstr */ void spawn_param_env(struct spawn_params *p) { lua_State *L = p->L; - luaL_Buffer env; - /* 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); + int envtab = lua_gettop(L); + lua_pushnil(L); + lua_pushnil(L); + p->environment = add_env(L, envtab, 0); + lua_settop(L, envtab + 1); } void spawn_param_redirect(struct spawn_params *p, const char *stdname, HANDLE h) diff --git a/w32api/spawn.h b/w32api/spawn.h index da51a4f..085474d 100755 --- a/w32api/spawn.h +++ b/w32api/spawn.h @@ -14,7 +14,7 @@ struct process; struct spawn_params; struct spawn_params *spawn_param_init(lua_State *L); -void spawn_param_filename(struct spawn_params *p, const char *filename); +void spawn_param_filename(struct spawn_params *p); void spawn_param_args(struct spawn_params *p); void spawn_param_env(struct spawn_params *p); void spawn_param_redirect(