From ff7e489f7b664130b6591fe3ac2a0d762843d2da Mon Sep 17 00:00:00 2001 From: mark Date: Sat, 14 Apr 2007 23:02:56 +0000 Subject: [PATCH] reformatted -- use spaces instead of tabs. --- posix/Makefile | 2 +- posix/ex.c | 682 +++++++++++++++++++-------------------- posix/posix_spawn.c | 92 +++--- posix/posix_spawn.h | 94 ++++-- posix/spawn.c | 167 +++++----- posix/spawn.h | 1 + w32api/dirent.c | 86 +++-- w32api/ex.c | 759 ++++++++++++++++++++++---------------------- w32api/pusherror.c | 52 ++- w32api/spawn.c | 230 +++++++------- w32api/spawn.h | 5 +- 11 files changed, 1094 insertions(+), 1076 deletions(-) diff --git a/posix/Makefile b/posix/Makefile index b83c328..5bcaa76 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 +WARNINGS= -W -Wall -std=c89 LIBS= $(LUALIB) T= ex.so diff --git a/posix/ex.c b/posix/ex.c index e8692dc..d658c72 100755 --- a/posix/ex.c +++ b/posix/ex.c @@ -27,120 +27,109 @@ ENVIRON_DECL /* -- nil error */ extern int push_error(lua_State *L) { - lua_pushnil(L); - lua_pushstring(L, strerror(errno)); - return 2; + lua_pushnil(L); + lua_pushstring(L, strerror(errno)); + return 2; } /* name -- value/nil */ static int ex_getenv(lua_State *L) { - const char *nam = luaL_checkstring(L, 1); - char *val = getenv(nam); - if (!val) - return push_error(L); - lua_pushstring(L, val); - return 1; + const char *nam = luaL_checkstring(L, 1); + char *val = getenv(nam); + if (!val) + return push_error(L); + lua_pushstring(L, val); + return 1; } /* name value -- true/nil error * name nil -- true/nil error */ static int ex_setenv(lua_State *L) { - const char *nam = luaL_checkstring(L, 1); - const char *val = lua_tostring(L, 2); - int err = val ? setenv(nam, val, 1) : unsetenv(nam); - if (err == -1) return push_error(L); - lua_pushboolean(L, 1); - return 1; + const char *nam = luaL_checkstring(L, 1); + const char *val = lua_tostring(L, 2); + int err = val ? setenv(nam, val, 1) : unsetenv(nam); + if (err == -1) return push_error(L); + lua_pushboolean(L, 1); + return 1; } /* -- environment-table */ static int ex_environ(lua_State *L) { - const char *nam, *val, *end; - const char **env; - lua_newtable(L); - for (env = (const char **)environ; (nam = *env); env++) { - end = strchr(val = strchr(nam, '=') + 1, '\0'); - lua_pushlstring(L, nam, val - nam - 1); - lua_pushlstring(L, val, end - val); - lua_settable(L, -3); - } - return 1; + const char *nam, *val, *end; + const char **env; + lua_newtable(L); + for (env = (const char **)environ; (nam = *env); env++) { + end = strchr(val = strchr(nam, '=') + 1, '\0'); + lua_pushlstring(L, nam, val - nam - 1); + lua_pushlstring(L, val, end - val); + lua_settable(L, -3); + } + return 1; } /* -- pathname/nil error */ static int ex_currentdir(lua_State *L) { - char pathname[PATH_MAX + 1]; - if (!getcwd(pathname, sizeof pathname)) - return push_error(L); - lua_pushstring(L, pathname); - return 1; + char pathname[PATH_MAX + 1]; + if (!getcwd(pathname, sizeof pathname)) + return push_error(L); + lua_pushstring(L, pathname); + return 1; } /* pathname -- true/nil error */ static int ex_chdir(lua_State *L) { - const char *pathname = luaL_checkstring(L, 1); - if (-1 == chdir(pathname)) - return push_error(L); - lua_pushboolean(L, 1); - return 1; + const char *pathname = luaL_checkstring(L, 1); + if (-1 == chdir(pathname)) + return push_error(L); + lua_pushboolean(L, 1); + return 1; } /* pathname -- true/nil error */ static int ex_mkdir(lua_State *L) { - const char *pathname = luaL_checkstring(L, 1); - if (-1 == mkdir(pathname, 0777)) - return push_error(L); - lua_pushboolean(L, 1); - return 1; + const char *pathname = luaL_checkstring(L, 1); + if (-1 == mkdir(pathname, 0777)) + return push_error(L); + lua_pushboolean(L, 1); + return 1; } -/* os.remove provides the correct semantics on POSIX systems */ -#if 0 -/* pathname -- true/nil error */ -static int ex_remove(lua_State *L) -{ - const char *pathname = luaL_checkstring(L, 1); - if (-1 == remove(pathname)) - return push_error(L); - lua_pushboolean(L, 1); - return 1; -} -#endif +/* Lua os.remove provides the correct semantics on POSIX systems */ static FILE *check_file(lua_State *L, int idx, const char *argname) { - FILE **pf; - if (idx > 0) pf = luaL_checkudata(L, idx, LUA_FILEHANDLE); - else { - idx = absindex(L, idx); - pf = lua_touserdata(L, idx); - luaL_getmetatable(L, LUA_FILEHANDLE); - if (!pf || !lua_getmetatable(L, idx) || !lua_rawequal(L, -1, -2)) - luaL_error(L, "bad %s option (%s expected, got %s)", - argname, LUA_FILEHANDLE, luaL_typename(L, idx)); - lua_pop(L, 2); - } - if (!*pf) return luaL_error(L, "attempt to use a closed file"), NULL; - return *pf; + FILE **pf; + if (idx > 0) pf = luaL_checkudata(L, idx, LUA_FILEHANDLE); + else { + idx = absindex(L, idx); + pf = lua_touserdata(L, idx); + luaL_getmetatable(L, LUA_FILEHANDLE); + if (!pf || !lua_getmetatable(L, idx) || !lua_rawequal(L, -1, -2)) + luaL_error(L, "bad %s option (%s expected, got %s)", + argname, LUA_FILEHANDLE, luaL_typename(L, idx)); + lua_pop(L, 2); + } + if (!*pf) return luaL_error(L, "attempt to use a closed file"), NULL; + return *pf; } static FILE **new_file(lua_State *L, int fd, const char *mode) { - FILE **pf = lua_newuserdata(L, sizeof *pf); - *pf = 0; - luaL_getmetatable(L, LUA_FILEHANDLE); - lua_setmetatable(L, -2); - *pf = fdopen(fd, mode); - return pf; + FILE **pf = lua_newuserdata(L, sizeof *pf); + *pf = 0; + luaL_getmetatable(L, LUA_FILEHANDLE); + lua_setmetatable(L, -2); + *pf = fdopen(fd, mode); + return pf; } @@ -149,35 +138,35 @@ static FILE **new_file(lua_State *L, int fd, const char *mode) /* pathname/file [entry] -- entry */ static int ex_dirent(lua_State *L) { - struct stat st; - switch (lua_type(L, 1)) { - default: return luaL_typerror(L, 1, "file or pathname"); - case LUA_TSTRING: { - const char *name = lua_tostring(L, 1); - if (-1 == stat(name, &st)) - return push_error(L); - } break; - case LUA_TUSERDATA: { - FILE *f = check_file(L, 1, NULL); - if (-1 == fstat(fileno(f), &st)) - return push_error(L); - } break; - } - if (lua_type(L, 2) != LUA_TTABLE) { - lua_settop(L, 1); - new_dirent(L); - } - else { - lua_settop(L, 2); - } - if (S_ISDIR(st.st_mode)) - lua_pushliteral(L, "directory"); - else - lua_pushliteral(L, "file"); - lua_setfield(L, 2, "type"); - lua_pushnumber(L, st.st_size); - lua_setfield(L, 2, "size"); - return 1; + struct stat st; + switch (lua_type(L, 1)) { + default: return luaL_typerror(L, 1, "file or pathname"); + case LUA_TSTRING: { + const char *name = lua_tostring(L, 1); + if (-1 == stat(name, &st)) + return push_error(L); + } break; + case LUA_TUSERDATA: { + FILE *f = check_file(L, 1, NULL); + if (-1 == fstat(fileno(f), &st)) + return push_error(L); + } break; + } + if (lua_type(L, 2) != LUA_TTABLE) { + lua_settop(L, 1); + new_dirent(L); + } + else { + lua_settop(L, 2); + } + if (S_ISDIR(st.st_mode)) + lua_pushliteral(L, "directory"); + else + lua_pushliteral(L, "file"); + lua_setfield(L, 2, "type"); + lua_pushnumber(L, st.st_size); + lua_setfield(L, 2, "size"); + return 1; } #define DIR_HANDLE "DIR*" @@ -185,140 +174,141 @@ static int ex_dirent(lua_State *L) /* ...diriter... -- ...diriter... pathname */ static int diriter_getpathname(lua_State *L, int index) { - lua_pushvalue(L, index); - lua_gettable(L, LUA_REGISTRYINDEX); - return 1; + lua_pushvalue(L, index); + lua_gettable(L, LUA_REGISTRYINDEX); + return 1; } /* ...diriter... pathname -- ...diriter... */ static int diriter_setpathname(lua_State *L, int index) { - size_t len; - const char *path = lua_tolstring(L, -1, &len); - if (path && path[len - 1] != *LUA_DIRSEP) { - lua_pushliteral(L, LUA_DIRSEP); - lua_concat(L, 2); - } - lua_pushvalue(L, index); /* ... pathname diriter */ - lua_insert(L, -2); /* ... diriter pathname */ - lua_settable(L, LUA_REGISTRYINDEX); /* ... */ - return 0; + size_t len; + const char *path = lua_tolstring(L, -1, &len); + if (path && path[len - 1] != *LUA_DIRSEP) { + lua_pushliteral(L, LUA_DIRSEP); + lua_concat(L, 2); + } + lua_pushvalue(L, index); /* ... pathname diriter */ + lua_insert(L, -2); /* ... diriter pathname */ + lua_settable(L, LUA_REGISTRYINDEX); /* ... */ + return 0; } /* diriter -- diriter */ static int diriter_close(lua_State *L) { - DIR **pd = lua_touserdata(L, 1); - if (*pd) { - closedir(*pd); - *pd = 0; - } - lua_pushnil(L); - diriter_setpathname(L, 1); - return 0; + DIR **pd = lua_touserdata(L, 1); + if (*pd) { + closedir(*pd); + *pd = 0; + } + lua_pushnil(L); + diriter_setpathname(L, 1); + return 0; } static int isdotfile(const char *name) { - return name[0] == '.' && (name[1] == '\0' - || (name[1] == '.' && name[2] == '\0')); + return name[0] == '.' && (name[1] == '\0' + || (name[1] == '.' && name[2] == '\0')); } /* pathname -- iter state nil */ /* diriter ... -- entry */ static int ex_dir(lua_State *L) { - const char *pathname; - DIR **pd; - struct dirent *d; - switch (lua_type(L, 1)) { - default: return luaL_typerror(L, 1, "pathname"); - case LUA_TSTRING: - pathname = lua_tostring(L, 1); - lua_pushcfunction(L, ex_dir); /* pathname ... iter */ - pd = lua_newuserdata(L, sizeof *pd);/* pathname ... iter state */ - *pd = opendir(pathname); - if (!*pd) return push_error(L); - luaL_getmetatable(L, DIR_HANDLE); /* pathname ... iter state M */ - lua_setmetatable(L, -2); /* pathname ... iter state */ - lua_pushvalue(L, 1); /* pathname ... iter state pathname */ - diriter_setpathname(L, -2); /* pathname ... iter state */ - return 2; - case LUA_TUSERDATA: - pd = luaL_checkudata(L, 1, DIR_HANDLE); - do d = readdir(*pd); - while (d && isdotfile(d->d_name)); - if (!d) return push_error(L); - new_dirent(L); /* diriter ... entry */ - diriter_getpathname(L, 1); /* diriter ... entry dirpath */ - lua_pushstring(L, d->d_name); /* diriter ... entry dirpath name */ - lua_pushvalue(L, -1); /* diriter ... entry dirpath name name */ - lua_setfield(L, -4, "name"); /* diriter ... entry dirpath name */ - lua_concat(L, 2); /* diriter ... entry fullpath */ - lua_replace(L, 1); /* fullpath ... entry */ - lua_replace(L, 2); /* fullpath entry ... */ - return ex_dirent(L); - } - /*NOTREACHED*/ + const char *pathname; + DIR **pd; + struct dirent *d; + switch (lua_type(L, 1)) { + default: return luaL_typerror(L, 1, "pathname"); + case LUA_TSTRING: + pathname = lua_tostring(L, 1); + lua_pushcfunction(L, ex_dir); /* pathname ... iter */ + pd = lua_newuserdata(L, sizeof *pd);/* pathname ... iter state */ + *pd = opendir(pathname); + if (!*pd) return push_error(L); + luaL_getmetatable(L, DIR_HANDLE); /* pathname ... iter state M */ + lua_setmetatable(L, -2); /* pathname ... iter state */ + lua_pushvalue(L, 1); /* pathname ... iter state pathname */ + diriter_setpathname(L, -2); /* pathname ... iter state */ + return 2; + case LUA_TUSERDATA: + pd = luaL_checkudata(L, 1, DIR_HANDLE); + do d = readdir(*pd); + while (d && isdotfile(d->d_name)) continue; + if (!d) 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 */ + lua_pushvalue(L, -1); /* diriter ... entry dir name name */ + lua_setfield(L, -4, "name"); /* diriter ... entry dir name */ + lua_concat(L, 2); /* diriter ... entry fullpath */ + lua_replace(L, 1); /* fullpath ... entry */ + lua_replace(L, 2); /* fullpath entry ... */ + return ex_dirent(L); + } + /*NOTREACHED*/ } -static int file_lock(lua_State *L, FILE *f, const char *mode, long offset, long length) +static int file_lock(lua_State *L, + FILE *f, const char *mode, long offset, long length) { - struct flock k; - switch (*mode) { - case 'w': k.l_type = F_WRLCK; break; - case 'r': k.l_type = F_RDLCK; break; - case 'u': k.l_type = F_UNLCK; break; - default: return luaL_error(L, "invalid mode"); - } - k.l_whence = SEEK_SET; - k.l_start = offset; - k.l_len = length; - if (-1 == fcntl(fileno(f), F_SETLK, &k)) - return push_error(L); - lua_settop(L, 1); - return 1; + struct flock k; + switch (*mode) { + case 'w': k.l_type = F_WRLCK; break; + case 'r': k.l_type = F_RDLCK; break; + case 'u': k.l_type = F_UNLCK; break; + default: return luaL_error(L, "invalid mode"); + } + k.l_whence = SEEK_SET; + k.l_start = offset; + k.l_len = length; + if (-1 == fcntl(fileno(f), F_SETLK, &k)) + return push_error(L); + lua_settop(L, 1); + return 1; } /* file mode [offset [length]] -- file/nil error */ static int ex_lock(lua_State *L) { - FILE *f = check_file(L, 1, NULL); - const char *mode = luaL_checkstring(L, 2); - long offset = luaL_optnumber(L, 3, 0); - long length = luaL_optnumber(L, 4, 0); - return file_lock(L, f, mode, offset, length); + FILE *f = check_file(L, 1, NULL); + const char *mode = luaL_checkstring(L, 2); + long offset = luaL_optnumber(L, 3, 0); + long length = luaL_optnumber(L, 4, 0); + return file_lock(L, f, mode, offset, length); } /* file [offset [length]] -- file/nil error */ static int ex_unlock(lua_State *L) { - lua_pushliteral(L, "u"); - lua_insert(L, 2); - return ex_lock(L); + lua_pushliteral(L, "u"); + lua_insert(L, 2); + return ex_lock(L); } static int closeonexec(int d) { - int fl = fcntl(d, F_GETFD); - if (fl != -1) - fl = fcntl(d, F_SETFD, fl | FD_CLOEXEC); - return fl; + int fl = fcntl(d, F_GETFD); + if (fl != -1) + fl = fcntl(d, F_SETFD, fl | FD_CLOEXEC); + return fl; } /* -- in out/nil error */ static int ex_pipe(lua_State *L) { - int fd[2]; - if (-1 == pipe(fd)) - return push_error(L); - closeonexec(fd[0]); - closeonexec(fd[1]); - new_file(L, fd[0], "r"); - new_file(L, fd[1], "w"); - return 2; + int fd[2]; + if (-1 == pipe(fd)) + return push_error(L); + closeonexec(fd[0]); + closeonexec(fd[1]); + new_file(L, fd[0], "r"); + new_file(L, fd[1], "w"); + return 2; } @@ -326,98 +316,97 @@ static int ex_pipe(lua_State *L) * interval units -- */ static int ex_sleep(lua_State *L) { - lua_Number interval = luaL_checknumber(L, 1); - lua_Number units = luaL_optnumber(L, 2, 1); - usleep(1e6 * interval / units); - return 0; + lua_Number interval = luaL_checknumber(L, 1); + lua_Number units = luaL_optnumber(L, 2, 1); + usleep(1e6 * interval / units); + return 0; } -static void get_redirect(lua_State *L, int idx, const char *stdname, struct spawn_params *p) +static void get_redirect(lua_State *L, + int idx, const char *stdname, struct spawn_params *p) { - lua_getfield(L, idx, stdname); - if (!lua_isnil(L, -1)) - spawn_param_redirect(p, stdname, fileno(check_file(L, -1, stdname))); - lua_pop(L, 1); + lua_getfield(L, idx, stdname); + if (!lua_isnil(L, -1)) + spawn_param_redirect(p, stdname, fileno(check_file(L, -1, stdname))); + lua_pop(L, 1); } /* filename [args-opts] -- proc/nil error */ /* args-opts -- proc/nil error */ static int ex_spawn(lua_State *L) { - struct spawn_params *params; - int have_options; - - switch (lua_type(L, 1)) { - default: return luaL_typerror(L, 1, "string or table"); - case LUA_TSTRING: - switch (lua_type(L, 2)) { - default: return luaL_typerror(L, 2, "table"); - case LUA_TNONE: have_options = 0; break; - case LUA_TTABLE: have_options = 1; break; - } - break; - case LUA_TTABLE: - have_options = 1; - lua_getfield(L, 1, "command"); /* opts ... cmd */ - if (!lua_isnil(L, -1)) { - /* convert {command=command,arg1,...} to command {arg1,...} */ - lua_insert(L, 1); /* cmd opts ... */ - } - else { - /* convert {arg0,arg1,...} to arg0 {arg1,...} */ - size_t i, n = lua_objlen(L, 1); - lua_rawgeti(L, 1, 1); /* opts ... nil cmd */ - lua_insert(L, 1); /* cmd opts ... nil */ - for (i = 2; i <= n; i++) { - lua_rawgeti(L, 2, i); /* cmd opts ... nil argi */ - lua_rawseti(L, 2, i - 1); /* cmd opts ... nil */ - } - lua_rawseti(L, 2, n); /* cmd opts ... */ - } - if (lua_type(L, 1) != LUA_TSTRING) - return luaL_error(L, "bad command option (string expected, got %s)", - luaL_typename(L, 1)); - break; - } - - params = spawn_param_init(L); - - /* get filename to execute */ - spawn_param_filename(params, lua_tostring(L, 1)); - - /* get arguments, environment, and redirections */ - if (have_options) { - lua_getfield(L, 2, "args"); /* cmd opts ... argtab */ - switch (lua_type(L, -1)) { - default: return luaL_error(L, "bad args option (table expected, got %s)", - luaL_typename(L, -1)); - case LUA_TNIL: - lua_pop(L, 1); /* cmd opts ... */ - lua_pushvalue(L, 2); /* cmd opts ... opts */ - if (0) /*FALLTHRU*/ - case LUA_TTABLE: - if (lua_objlen(L, 2) > 0) - return luaL_error(L, "cannot specify both the args option and array values"); - spawn_param_args(params); /* cmd opts ... */ - break; - } - lua_getfield(L, 2, "env"); /* cmd opts ... envtab */ - switch (lua_type(L, -1)) { - default: return luaL_error(L, "bad env option (table expected, got %s)", - luaL_typename(L, -1)); - case LUA_TNIL: - break; - case LUA_TTABLE: - spawn_param_env(params); /* cmd opts ... */ - break; - } - get_redirect(L, 2, "stdin", params); /* cmd opts ... */ - get_redirect(L, 2, "stdout", params); /* cmd opts ... */ - get_redirect(L, 2, "stderr", params); /* cmd opts ... */ - } - - return spawn_param_execute(params); /* proc/nil error */ + struct spawn_params *params; + int have_options; + switch (lua_type(L, 1)) { + default: return luaL_typerror(L, 1, "string or table"); + case LUA_TSTRING: + switch (lua_type(L, 2)) { + default: return luaL_typerror(L, 2, "table"); + case LUA_TNONE: have_options = 0; break; + case LUA_TTABLE: have_options = 1; break; + } + break; + case LUA_TTABLE: + have_options = 1; + lua_getfield(L, 1, "command"); /* opts ... cmd */ + if (!lua_isnil(L, -1)) { + /* convert {command=command,arg1,...} to command {arg1,...} */ + lua_insert(L, 1); /* cmd opts ... */ + } + else { + /* convert {arg0,arg1,...} to arg0 {arg1,...} */ + size_t i, n = lua_objlen(L, 1); + lua_rawgeti(L, 1, 1); /* opts ... nil cmd */ + lua_insert(L, 1); /* cmd opts ... nil */ + for (i = 2; i <= n; i++) { + lua_rawgeti(L, 2, i); /* cmd opts ... nil argi */ + lua_rawseti(L, 2, i - 1); /* cmd opts ... nil */ + } + lua_rawseti(L, 2, n); /* cmd opts ... */ + } + if (lua_type(L, 1) != LUA_TSTRING) + return luaL_error(L, "bad command option (string expected, got %s)", + luaL_typename(L, 1)); + break; + } + params = spawn_param_init(L); + /* get filename to execute */ + spawn_param_filename(params, lua_tostring(L, 1)); + /* get arguments, environment, and redirections */ + if (have_options) { + lua_getfield(L, 2, "args"); /* cmd opts ... argtab */ + switch (lua_type(L, -1)) { + default: + return luaL_error(L, "bad args option (table expected, got %s)", + luaL_typename(L, -1)); + case LUA_TNIL: + lua_pop(L, 1); /* cmd opts ... */ + lua_pushvalue(L, 2); /* cmd opts ... opts */ + if (0) /*FALLTHRU*/ + case LUA_TTABLE: + if (lua_objlen(L, 2) > 0) + return + luaL_error(L, "cannot specify both the args option and array values"); + spawn_param_args(params); /* cmd opts ... */ + break; + } + lua_getfield(L, 2, "env"); /* cmd opts ... envtab */ + switch (lua_type(L, -1)) { + default: + return luaL_error(L, "bad env option (table expected, got %s)", + luaL_typename(L, -1)); + case LUA_TNIL: + break; + case LUA_TTABLE: + spawn_param_env(params); /* cmd opts ... */ + break; + } + get_redirect(L, 2, "stdin", params); /* cmd opts ... */ + get_redirect(L, 2, "stdout", params); /* cmd opts ... */ + get_redirect(L, 2, "stderr", params); /* cmd opts ... */ + } + return spawn_param_execute(params); /* proc/nil error */ } @@ -425,90 +414,79 @@ static int ex_spawn(lua_State *L) * closures from table 'from' or by creating new closures */ static void copyfields(lua_State *L, const luaL_reg *l, int from, int to) { - for (to = absindex(L, to); l->name; l++) { - lua_getfield(L, from, l->name); - if (lua_isnil(L, -1)) { - lua_pop(L, 1); - lua_pushcfunction(L, l->func); - } - lua_setfield(L, to, l->name); - } + for (to = absindex(L, to); l->name; l++) { + lua_getfield(L, from, l->name); + if (lua_isnil(L, -1)) { + lua_pop(L, 1); + lua_pushcfunction(L, l->func); + } + lua_setfield(L, to, l->name); + } } int luaopen_ex(lua_State *L) { - const luaL_reg ex_iolib[] = { - {"pipe", ex_pipe}, + const char *name = lua_tostring(L, 1); + int ex; + const luaL_reg ex_iolib[] = { + {"pipe", ex_pipe}, #define ex_iofile_methods (ex_iolib + 1) - {"lock", ex_lock}, - {"unlock", ex_unlock}, - {0,0} }; - const luaL_reg ex_oslib[] = { - {"getenv", ex_getenv}, - {"setenv", ex_setenv}, - {"environ", ex_environ}, - - {"currentdir", ex_currentdir}, - {"chdir", ex_chdir}, - {"mkdir", ex_mkdir}, -#if 0 - {"remove", ex_remove}, -#endif - - {"dir", ex_dir}, - {"dirent", ex_dirent}, - - {"sleep", ex_sleep}, - {"spawn", ex_spawn}, - {0,0} }; - const luaL_reg ex_diriter_methods[] = { - {"__gc", diriter_close}, - {0,0} }; - const luaL_reg ex_process_methods[] = { - {"__tostring", process_tostring}, + {"lock", ex_lock}, + {"unlock", ex_unlock}, + {0,0} }; + const luaL_reg ex_oslib[] = { + /* environment */ + {"getenv", ex_getenv}, + {"setenv", ex_setenv}, + {"environ", ex_environ}, + /* file system */ + {"currentdir", ex_currentdir}, + {"chdir", ex_chdir}, + {"mkdir", ex_mkdir}, + {"dir", ex_dir}, + {"dirent", ex_dirent}, + /* process control */ + {"sleep", ex_sleep}, + {"spawn", ex_spawn}, + {0,0} }; + const luaL_reg ex_diriter_methods[] = { + {"__gc", diriter_close}, + {0,0} }; + const luaL_reg ex_process_methods[] = { + {"__tostring", process_tostring}, #define ex_process_functions (ex_process_methods + 1) - {"wait", process_wait}, - {0,0} }; - - int ex; - const char *name = lua_tostring(L, 1); - - /* diriter metatable */ - luaL_newmetatable(L, DIR_HANDLE); /* . D */ - luaL_register(L, 0, ex_diriter_methods); /* . D */ - - /* proc metatable */ - luaL_newmetatable(L, PROCESS_HANDLE); /* . P */ - luaL_register(L, 0, ex_process_methods); /* . P */ - lua_pushvalue(L, -1); /* . P P */ - lua_setfield(L, -2, "__index"); /* . P */ - - /* make all functions available via ex. namespace */ - luaL_register(L, name, ex_oslib); /* . P ex */ - luaL_register(L, 0, ex_iolib); - copyfields(L, ex_process_functions, -2, -1); - ex = lua_gettop(L); - - /* extend the os table */ - lua_getglobal(L, "os"); /* . os */ - if (lua_isnil(L, -1)) return luaL_error(L, "os not loaded"); - copyfields(L, ex_oslib, ex, -1); - lua_getfield(L, -1, "remove"); - lua_setfield(L, ex, "remove"); - - /* extend the io table */ - lua_getglobal(L, "io"); /* . io */ - if (lua_isnil(L, -1)) return luaL_error(L, "io not loaded"); - copyfields(L, ex_iolib, ex, -1); - lua_getfield(L, ex, "pipe"); /* . io ex_pipe */ - lua_getfield(L, -2, "stderr"); /* . io ex_pipe io_stderr */ - lua_getfenv(L, -1); /* . io ex_pipe io_stderr E */ - lua_setfenv(L, -3); /* . io ex_pipe io_stderr */ - - /* extend the io.file metatable */ - luaL_getmetatable(L, LUA_FILEHANDLE); /* . F */ - if (lua_isnil(L, -1)) return luaL_error(L, "can't find FILE* metatable"); - copyfields(L, ex_iofile_methods, ex, -1); - - return 1; + {"wait", process_wait}, + {0,0} }; + /* diriter metatable */ + luaL_newmetatable(L, DIR_HANDLE); /* . D */ + luaL_register(L, 0, ex_diriter_methods); /* . D */ + /* proc metatable */ + luaL_newmetatable(L, PROCESS_HANDLE); /* . P */ + luaL_register(L, 0, ex_process_methods); /* . P */ + lua_pushvalue(L, -1); /* . P P */ + lua_setfield(L, -2, "__index"); /* . P */ + /* make all functions available via ex. namespace */ + luaL_register(L, name, ex_oslib); /* . P ex */ + luaL_register(L, 0, ex_iolib); + copyfields(L, ex_process_functions, -2, -1); + ex = lua_gettop(L); + /* extend the os table */ + lua_getglobal(L, "os"); /* . os */ + if (lua_isnil(L, -1)) return luaL_error(L, "os not loaded"); + copyfields(L, ex_oslib, ex, -1); + lua_getfield(L, -1, "remove"); + lua_setfield(L, ex, "remove"); + /* extend the io table */ + lua_getglobal(L, "io"); /* . io */ + if (lua_isnil(L, -1)) return luaL_error(L, "io not loaded"); + copyfields(L, ex_iolib, ex, -1); + lua_getfield(L, ex, "pipe"); /* . io ex_pipe */ + lua_getfield(L, -2, "stderr"); /* . io ex_pipe io_stderr */ + lua_getfenv(L, -1); /* . io ex_pipe io_stderr E */ + lua_setfenv(L, -3); /* . io ex_pipe io_stderr */ + /* extend the io.file metatable */ + luaL_getmetatable(L, LUA_FILEHANDLE); /* . F */ + if (lua_isnil(L, -1)) return luaL_error(L, "can't find FILE* metatable"); + copyfields(L, ex_iofile_methods, ex, -1); + return 1; } diff --git a/posix/posix_spawn.c b/posix/posix_spawn.c index 470a952..300e20c 100755 --- a/posix/posix_spawn.c +++ b/posix/posix_spawn.c @@ -19,57 +19,63 @@ ENVIRON_DECL #endif -int posix_spawn_file_actions_init(posix_spawn_file_actions_t *act) +int posix_spawn_file_actions_init( + posix_spawn_file_actions_t *act) { - act->dups[0] = act->dups[1] = act->dups[2] = -1; - return 0; + act->dups[0] = act->dups[1] = act->dups[2] = -1; + return 0; } -int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *act, int d, int n) +int posix_spawn_file_actions_adddup2( + posix_spawn_file_actions_t *act, + int d, + int n) { - /* good faith effort to determine validity of descriptors */ - if (d < 0 || OPEN_MAX < d || n < 0 || OPEN_MAX < n) { - errno = EBADF; - return -1; - } - /* we only support duplication to 0,1,2 */ - if (2 < n) { - errno = EINVAL; - return -1; - } - act->dups[n] = d; - return 0; + /* good faith effort to determine validity of descriptors */ + if (d < 0 || OPEN_MAX < d || n < 0 || OPEN_MAX < n) { + errno = EBADF; + return -1; + } + /* we only support duplication to 0,1,2 */ + if (2 < n) { + errno = EINVAL; + return -1; + } + act->dups[n] = d; + return 0; } -int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *act) +int posix_spawn_file_actions_destroy( + posix_spawn_file_actions_t *act) { - return 0; + return 0; } -int posix_spawnp(pid_t *restrict ppid, - const char *restrict path, - const posix_spawn_file_actions_t *act, - const posix_spawnattr_t *restrict attrp, - char *const argv[restrict], - char *const envp[restrict]) +int posix_spawnp( + pid_t *restrict ppid, + const char *restrict path, + const posix_spawn_file_actions_t *act, + const posix_spawnattr_t *restrict attrp, + char *const argv[restrict], + char *const envp[restrict]) { - if (!ppid || !path || !argv || !envp) - return EINVAL; - if (attrp) - return EINVAL; - switch (*ppid = fork()) { - case -1: return -1; - default: return 0; - case 0: - if (act) { - int i; - for (i = 0; i < 3; i++) - if (act->dups[i] != -1 && -1 == dup2(act->dups[i], i)) - _exit(111); - } - environ = (char **)envp; - execvp(path, argv); - _exit(111); - /*NOTREACHED*/ - } + if (!ppid || !path || !argv || !envp) + return EINVAL; + if (attrp) + return EINVAL; + switch (*ppid = fork()) { + case -1: return -1; + default: return 0; + case 0: + if (act) { + int i; + for (i = 0; i < 3; i++) + if (act->dups[i] != -1 && -1 == dup2(act->dups[i], i)) + _exit(111); + } + environ = (char **)envp; + execvp(path, argv); + _exit(111); + /*NOTREACHED*/ + } } diff --git a/posix/posix_spawn.h b/posix/posix_spawn.h index 3e0bbd7..f43f1e2 100755 --- a/posix/posix_spawn.h +++ b/posix/posix_spawn.h @@ -14,39 +14,85 @@ typedef void *posix_spawnattr_t; enum { - POSIX_SPAWN_RESETIDS, - POSIX_SPAWN_SETPGROUP, - POSIX_SPAWN_SETSCHEDPARAM, - POSIX_SPAWN_SETSCHEDULER, - POSIX_SPAWN_SETSIGDEF, - POSIX_SPAWN_SETSIGMASK, + POSIX_SPAWN_RESETIDS, + POSIX_SPAWN_SETPGROUP, + POSIX_SPAWN_SETSCHEDPARAM, + POSIX_SPAWN_SETSCHEDULER, + POSIX_SPAWN_SETSIGDEF, + POSIX_SPAWN_SETSIGMASK, }; int posix_spawnattr_init(posix_spawnattr_t *attrp); -int posix_spawnattr_getflags(const posix_spawnattr_t *restrict attrp, short *restrict flags); -int posix_spawnattr_setflags(posix_spawnattr_t *attrp, short flags); -int posix_spawnattr_getpgroup(const posix_spawnattr_t *restrict attrp, pid_t *restrict pgroup); -int posix_spawnattr_setpgroup(posix_spawnattr_t *attrp, pid_t pgroup); -int posix_spawnattr_getschedparam(const posix_spawnattr_t *restrict attrp, struct sched_param *restrict schedparam); -int posix_spawnattr_setschedparam(posix_spawnattr_t *restrict attrp, const struct sched_param *restrict schedparam); -int posix_spawnattr_getschedpolicy(const posix_spawnattr_t *restrict attrp, int *restrict schedpolicy); -int posix_spawnattr_setschedpolicy(posix_spawnattr_t *attrp, int schedpolicy); -int posix_spawnattr_getsigdefault(const posix_spawnattr_t *restrict attrp, sigset_t *restrict sigdefault); -int posix_spawnattr_setsigdefault(posix_spawnattr_t *restrict attrp, const sigset_t *restrict sigdefault); -int posix_spawnattr_getsigmask(const posix_spawnattr_t *restrict attrp, sigset_t *restrict sigmask); -int posix_spawnattr_setsigmask(posix_spawnattr_t *restrict attrp, const sigset_t *restrict sigmask); +int posix_spawnattr_getflags( + const posix_spawnattr_t *restrict attrp, + short *restrict flags); +int posix_spawnattr_setflags( + posix_spawnattr_t *attrp, + short flags); +int posix_spawnattr_getpgroup( + const posix_spawnattr_t *restrict attrp, + pid_t *restrict pgroup); +int posix_spawnattr_setpgroup( + posix_spawnattr_t *attrp, + pid_t pgroup); +int posix_spawnattr_getschedparam( + const posix_spawnattr_t *restrict attrp, + struct sched_param *restrict schedparam); +int posix_spawnattr_setschedparam( + posix_spawnattr_t *restrict attrp, + const struct sched_param *restrict schedparam); +int posix_spawnattr_getschedpolicy( + const posix_spawnattr_t *restrict attrp, + int *restrict schedpolicy); +int posix_spawnattr_setschedpolicy( + posix_spawnattr_t *attrp, + int schedpolicy); +int posix_spawnattr_getsigdefault( + const posix_spawnattr_t *restrict attrp, + sigset_t *restrict sigdefault); +int posix_spawnattr_setsigdefault( + posix_spawnattr_t *restrict attrp, + const sigset_t *restrict sigdefault); +int posix_spawnattr_getsigmask( + const posix_spawnattr_t *restrict attrp, + sigset_t *restrict sigmask); +int posix_spawnattr_setsigmask( + posix_spawnattr_t *restrict attrp, + const sigset_t *restrict sigmask); int posix_spawnattr_destroy(posix_spawnattr_t *attrp); typedef struct posix_spawn_file_actions posix_spawn_file_actions_t; struct posix_spawn_file_actions { - int dups[3]; + int dups[3]; }; int posix_spawn_file_actions_init(posix_spawn_file_actions_t *file_actions); -int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *file_actions, int filedes, int newfiledes); -int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *file_actions, int filedes); -int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t *restrict file_actions, int filedes, const char *restrict path, int oflag, mode_t mode); +int posix_spawn_file_actions_adddup2( + posix_spawn_file_actions_t *file_actions, + int filedes, + int newfiledes); +int posix_spawn_file_actions_addclose( + posix_spawn_file_actions_t *file_actions, + int filedes); +int posix_spawn_file_actions_addopen( + posix_spawn_file_actions_t *restrict file_actions, + int filedes, + const char *restrict path, + int oflag, + mode_t mode); int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *file_actions); -int posix_spawn(pid_t *restrict, const char *restrict, const posix_spawn_file_actions_t *, const posix_spawnattr_t *restrict, char *const argv[restrict], char *const envp[restrict]); -int posix_spawnp(pid_t *restrict, const char *restrict, const posix_spawn_file_actions_t *, const posix_spawnattr_t *restrict, char *const argv[restrict], char *const envp[restrict]); +int posix_spawn( + pid_t *restrict, + const char *restrict, + const posix_spawn_file_actions_t *, + const posix_spawnattr_t *restrict, + char *const argv[restrict], + char *const envp[restrict]); +int posix_spawnp( + pid_t *restrict, + const char *restrict, + const posix_spawn_file_actions_t *, + const posix_spawnattr_t *restrict, + char *const argv[restrict], + char *const envp[restrict]); diff --git a/posix/spawn.c b/posix/spawn.c index aaa5600..d6232e5 100755 --- a/posix/spawn.c +++ b/posix/spawn.c @@ -18,26 +18,26 @@ ENVIRON_DECL #include "spawn.h" struct spawn_params { - lua_State *L; - const char *command, **argv, **envp; - posix_spawn_file_actions_t redirect; + lua_State *L; + const char *command, **argv, **envp; + posix_spawn_file_actions_t redirect; }; extern int push_error(lua_State *L); struct spawn_params *spawn_param_init(lua_State *L) { - struct spawn_params *p = lua_newuserdata(L, sizeof *p); - p->L = L; - p->command = 0; - p->argv = p->envp = 0; - posix_spawn_file_actions_init(&p->redirect); - return p; + struct spawn_params *p = lua_newuserdata(L, sizeof *p); + p->L = L; + p->command = 0; + p->argv = p->envp = 0; + posix_spawn_file_actions_init(&p->redirect); + return p; } void spawn_param_filename(struct spawn_params *p, const char *filename) { - p->command = filename; + p->command = filename; } /* Converts a Lua array of strings to a null-terminated array of char pointers. @@ -51,108 +51,109 @@ void spawn_param_filename(struct spawn_params *p, const char *filename) /* ... 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; + 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; + const char **argv = make_vector(p->L); + if (!argv[0]) argv[0] = p->command; + p->argv = argv; } /* ... envtab */ void spawn_param_env(struct spawn_params *p) { - 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 */ + 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 */ } void spawn_param_redirect(struct spawn_params *p, const char *stdname, int fd) { - int d; - switch (stdname[3]) { - case 'i': d = STDIN_FILENO; break; - case 'o': d = STDOUT_FILENO; break; - case 'e': d = STDERR_FILENO; break; - } - posix_spawn_file_actions_adddup2(&p->redirect, fd, d); + int d; + switch (stdname[3]) { + case 'i': d = STDIN_FILENO; break; + case 'o': d = STDOUT_FILENO; break; + case 'e': d = STDERR_FILENO; break; + } + posix_spawn_file_actions_adddup2(&p->redirect, fd, d); } struct process { - int status; - pid_t pid; + int status; + pid_t pid; }; int spawn_param_execute(struct spawn_params *p) { - lua_State *L = p->L; - int ret; - struct process *proc; - if (!p->argv) { - p->argv = lua_newuserdata(L, 2 * sizeof *p->argv); - p->argv[0] = p->command; - p->argv[1] = 0; - } - if (!p->envp) - p->envp = (const char **)environ; - proc = lua_newuserdata(L, sizeof *proc); - luaL_getmetatable(L, PROCESS_HANDLE); - lua_setmetatable(L, -2); - proc->status = -1; - ret = posix_spawnp(&proc->pid, p->command, &p->redirect, 0, (char *const *)p->argv, (char *const *)p->envp); - posix_spawn_file_actions_destroy(&p->redirect); - return ret != 0 ? push_error(L) : 1; + lua_State *L = p->L; + int ret; + struct process *proc; + if (!p->argv) { + p->argv = lua_newuserdata(L, 2 * sizeof *p->argv); + p->argv[0] = p->command; + p->argv[1] = 0; + } + if (!p->envp) + p->envp = (const char **)environ; + proc = lua_newuserdata(L, sizeof *proc); + luaL_getmetatable(L, PROCESS_HANDLE); + lua_setmetatable(L, -2); + proc->status = -1; + ret = posix_spawnp(&proc->pid, p->command, &p->redirect, 0, + (char *const *)p->argv, (char *const *)p->envp); + posix_spawn_file_actions_destroy(&p->redirect); + return ret != 0 ? push_error(L) : 1; } /* proc -- exitcode/nil error */ int process_wait(lua_State *L) { - struct process *p = luaL_checkudata(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; + struct process *p = luaL_checkudata(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; } /* proc -- string */ int process_tostring(lua_State *L) { - struct process *p = luaL_checkudata(L, 1, PROCESS_HANDLE); - char buf[40]; - lua_pushlstring(L, buf, - sprintf(buf, "process (%lu, %s)", (unsigned long)p->pid, - p->status==-1 ? "running" : "terminated")); - return 1; + struct process *p = luaL_checkudata(L, 1, PROCESS_HANDLE); + char buf[40]; + lua_pushlstring(L, buf, + sprintf(buf, "process (%lu, %s)", (unsigned long)p->pid, + p->status==-1 ? "running" : "terminated")); + return 1; } diff --git a/posix/spawn.h b/posix/spawn.h index 3fddfb7..84fb3db 100755 --- a/posix/spawn.h +++ b/posix/spawn.h @@ -19,6 +19,7 @@ void spawn_param_args(struct spawn_params *p); void spawn_param_env(struct spawn_params *p); void spawn_param_redirect(struct spawn_params *p, const char *stdname, int fd); int spawn_param_execute(struct spawn_params *p); + int process_wait(lua_State *L); int process_tostring(lua_State *L); diff --git a/w32api/dirent.c b/w32api/dirent.c index 188590e..c9831df 100755 --- a/w32api/dirent.c +++ b/w32api/dirent.c @@ -8,66 +8,62 @@ #include "dirent.h" struct DIR_tag { - int first; - HANDLE hf; - WIN32_FIND_DATA fd; + int first; + HANDLE hf; + WIN32_FIND_DATA fd; }; static char *mkpattern(const char *name) { - static const char suffix[] = "\\*"; - size_t len = strlen(name); - char *pattern = malloc(len + sizeof suffix); - if (pattern) - strcpy(memcpy(pattern, name, len) + len, suffix); - return pattern; + static const char suffix[] = "\\*"; + size_t len = strlen(name); + char *pattern = malloc(len + sizeof suffix); + if (pattern) + strcpy(memcpy(pattern, name, len) + len, suffix); + return pattern; } -DIR * -opendir(const char *name) +DIR *opendir(const char *name) { - DIR *pi = malloc(sizeof *pi); - char *pattern = mkpattern(name); - if (!pi || !pattern - || INVALID_HANDLE_VALUE == (pi->hf = FindFirstFile(pattern, &pi->fd))) { - free(pi); - pi = 0; - } - else { - pi->first = 1; - } - free(pattern); - return pi; + DIR *pi = malloc(sizeof *pi); + char *pattern = mkpattern(name); + if (!pi || !pattern + || INVALID_HANDLE_VALUE == (pi->hf = FindFirstFile(pattern, &pi->fd))) { + free(pi); + pi = 0; + } + else { + pi->first = 1; + } + free(pattern); + return pi; } static int isdotfile(const char *name) { - return name[0] == '.' && (name[1] == 0 - || (name[1] == '.' && name[2] == 0)); + return name[0] == '.' && (name[1] == 0 + || (name[1] == '.' && name[2] == 0)); } -const WIN32_FIND_DATA * -readdir(DIR *pi) +const WIN32_FIND_DATA *readdir(DIR *pi) { - switch (pi->first) do { - default: - if (!FindNextFile(pi->hf, &pi->fd)) { - FindClose(pi->hf); - pi->hf = INVALID_HANDLE_VALUE; - return 0; - } - case 1: pi->first = 0; - } while (isdotfile(pi->fd.cFileName)); - return &pi->fd; + switch (pi->first) do { + default: + if (!FindNextFile(pi->hf, &pi->fd)) { + FindClose(pi->hf); + pi->hf = INVALID_HANDLE_VALUE; + return 0; + } + case 1: pi->first = 0; + } while (isdotfile(pi->fd.cFileName)); + return &pi->fd; } -void -closedir(DIR *pi) +void closedir(DIR *pi) { - if (pi->hf != INVALID_HANDLE_VALUE) - { - FindClose(pi->hf); - pi->hf = INVALID_HANDLE_VALUE; - } - free(pi); + if (pi->hf != INVALID_HANDLE_VALUE) { + FindClose(pi->hf); + pi->hf = INVALID_HANDLE_VALUE; + } + free(pi); } diff --git a/w32api/ex.c b/w32api/ex.c index b91e919..ec37f67 100755 --- a/w32api/ex.c +++ b/w32api/ex.c @@ -29,149 +29,150 @@ /* name -- value/nil */ static int ex_getenv(lua_State *L) { - const char *nam = luaL_checkstring(L, 1); - char sval[256], *val = sval; - size_t len = GetEnvironmentVariable(nam, val, sizeof sval); - if (sizeof sval < len) { - len = GetEnvironmentVariable(nam, val = lua_newuserdata(len), len); - } - if (len == 0) - return push_error(L); - lua_pushlstring(L, val, len); - return 1; + const char *nam = luaL_checkstring(L, 1); + char sval[256], *val = sval; + size_t len = GetEnvironmentVariable(nam, val, sizeof sval); + if (sizeof sval < len) { + len = GetEnvironmentVariable(nam, val = lua_newuserdata(len), len); + } + if (len == 0) + return push_error(L); + lua_pushlstring(L, val, len); + return 1; } /* name value -- true/nil error * name nil -- true/nil error */ static int ex_setenv(lua_State *L) { - const char *nam = luaL_checkstring(L, 1); - const char *val = lua_tostring(L, 2); - if (!SetEnvironmentVariable(nam, val)) - return push_error(L); - lua_pushboolean(L, 1); - return 1; + const char *nam = luaL_checkstring(L, 1); + const char *val = lua_tostring(L, 2); + if (!SetEnvironmentVariable(nam, val)) + return push_error(L); + lua_pushboolean(L, 1); + return 1; } /* -- environment-table */ static int ex_environ(lua_State *L) { - const char *nam, *val, *end; - const char *envs = GetEnvironmentStrings(); - if (!envs) return push_error(L); - lua_newtable(L); - for (nam = envs; *nam; nam = end + 1) { - end = strchr(val = strchr(nam, '=') + 1, '\0'); - lua_pushlstring(L, nam, val - nam - 1); - lua_pushlstring(L, val, end - val); - lua_settable(L, -3); - } - return 1; + const char *nam, *val, *end; + const char *envs = GetEnvironmentStrings(); + if (!envs) return push_error(L); + lua_newtable(L); + for (nam = envs; *nam; nam = end + 1) { + end = strchr(val = strchr(nam, '=') + 1, '\0'); + lua_pushlstring(L, nam, val - nam - 1); + lua_pushlstring(L, val, end - val); + lua_settable(L, -3); + } + return 1; } /* -- pathname/nil error */ static int ex_currentdir(lua_State *L) { - char pathname[MAX_PATH + 1]; - size_t len = GetCurrentDirectory(sizeof pathname, pathname); - if (len == 0) return push_error(L); - lua_pushlstring(L, pathname, len); - return 1; + char pathname[MAX_PATH + 1]; + size_t len = GetCurrentDirectory(sizeof pathname, pathname); + if (len == 0) return push_error(L); + lua_pushlstring(L, pathname, len); + return 1; } /* pathname -- true/nil error */ static int ex_chdir(lua_State *L) { - const char *pathname = luaL_checkstring(L, 1); - if (!SetCurrentDirectory(pathname)) - return push_error(L); - lua_pushboolean(L, 1); - return 1; + const char *pathname = luaL_checkstring(L, 1); + if (!SetCurrentDirectory(pathname)) + return push_error(L); + lua_pushboolean(L, 1); + return 1; } /* pathname -- true/nil error */ static int ex_mkdir(lua_State *L) { - const char *pathname = luaL_checkstring(L, 1); - if (!CreateDirectory(pathname, 0)) - return push_error(L); - lua_pushboolean(L, 1); - return 1; + const char *pathname = luaL_checkstring(L, 1); + if (!CreateDirectory(pathname, 0)) + return push_error(L); + lua_pushboolean(L, 1); + return 1; } /* pathname -- true/nil error */ static int ex_remove(lua_State *L) { - const char *pathname = luaL_checkstring(L, 1); - DWORD attr = GetFileAttributes(pathname); - if (attr == (DWORD)-1 - || (attr & FILE_ATTRIBUTE_DIRECTORY - ? !RemoveDirectory(pathname) - : !DeleteFile(pathname))) - return push_error(L); - lua_pushboolean(L, 1); - return 1; + const char *pathname = luaL_checkstring(L, 1); + DWORD attr = GetFileAttributes(pathname); + if (attr == (DWORD)-1 + || (attr & FILE_ATTRIBUTE_DIRECTORY + ? !RemoveDirectory(pathname) + : !DeleteFile(pathname))) + return push_error(L); + lua_pushboolean(L, 1); + return 1; } static FILE *check_file(lua_State *L, int idx, const char *argname) { - FILE **pf; - if (idx > 0) pf = luaL_checkudata(L, idx, LUA_FILEHANDLE); - else { - idx = absindex(L, idx); - pf = lua_touserdata(L, idx); - luaL_getmetatable(L, LUA_FILEHANDLE); - if (!pf || !lua_getmetatable(L, idx) || !lua_rawequal(L, -1, -2)) - luaL_error(L, "bad %s option (%s expected, got %s)", - argname, LUA_FILEHANDLE, luaL_typename(L, idx)); - lua_pop(L, 2); - } - if (!*pf) return luaL_error(L, "attempt to use a closed file"), NULL; - return *pf; + FILE **pf; + if (idx > 0) pf = luaL_checkudata(L, idx, LUA_FILEHANDLE); + else { + idx = absindex(L, idx); + pf = lua_touserdata(L, idx); + luaL_getmetatable(L, LUA_FILEHANDLE); + if (!pf || !lua_getmetatable(L, idx) || !lua_rawequal(L, -1, -2)) + luaL_error(L, "bad %s option (%s expected, got %s)", + argname, LUA_FILEHANDLE, luaL_typename(L, idx)); + lua_pop(L, 2); + } + if (!*pf) return luaL_error(L, "attempt to use a closed file"), NULL; + return *pf; } static FILE **new_file(lua_State *L, HANDLE h, int dmode, const char *mode) { - FILE **pf = lua_newuserdata(L, sizeof *pf); - *pf = 0; - luaL_getmetatable(L, LUA_FILEHANDLE); - lua_setmetatable(L, -2); - *pf = _fdopen(_open_osfhandle((long)h, dmode), mode); - return pf; + FILE **pf = lua_newuserdata(L, sizeof *pf); + *pf = 0; + luaL_getmetatable(L, LUA_FILEHANDLE); + lua_setmetatable(L, -2); + *pf = _fdopen(_open_osfhandle((long)h, dmode), mode); + return pf; } #define file_handle(fp) (HANDLE)_get_osfhandle(_fileno(fp)) 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_Number)0.5 > 0 - || sizeof(lua_Number) > 2 * sizeof(DWORD) - || !"lua_Number cannot adequately represent large file sizes" ); - return hi * (1.0 + (DWORD)-1) + 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_Number)0.5 > 0 + || sizeof(lua_Number) > 2 * sizeof(DWORD) + || !"lua_Number cannot adequately represent large file sizes" ); + return hi * (1.0 + (DWORD)-1) + lo; } static lua_Number get_file_size(const char *name) { - HANDLE h = CreateFile(name, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); - DWORD lo, hi; - lua_Number size; - if (h == INVALID_HANDLE_VALUE) - size = 0; - else { - lo = GetFileSize(h, &hi); - if (lo == INVALID_FILE_SIZE && GetLastError() != NO_ERROR) - size = 0; - else - size = qword_to_number(hi, lo); - CloseHandle(h); - } - return size; + HANDLE h = CreateFile(name, GENERIC_READ, FILE_SHARE_READ, 0, + OPEN_EXISTING, 0, 0); + DWORD lo, hi; + lua_Number size; + if (h == INVALID_HANDLE_VALUE) + size = 0; + else { + lo = GetFileSize(h, &hi); + if (lo == INVALID_FILE_SIZE && GetLastError() != NO_ERROR) + size = 0; + else + size = qword_to_number(hi, lo); + CloseHandle(h); + } + return size; } #define new_dirent(L) lua_newtable(L) @@ -179,47 +180,47 @@ static lua_Number get_file_size(const char *name) /* pathname/file [entry] -- entry */ static int ex_dirent(lua_State *L) { - int isdir; - lua_Number size; - DWORD attr; - switch (lua_type(L, 1)) { - default: return luaL_typerror(L, 1, "file or pathname"); - case LUA_TSTRING: { - const char *name = lua_tostring(L, 1); - attr = GetFileAttributes(name); - if (attr == (DWORD)-1) - return push_error(L); - isdir = attr & FILE_ATTRIBUTE_DIRECTORY; - if (isdir) - size = 0; - else - size = get_file_size(name); - } break; - case LUA_TUSERDATA: { - FILE *f = check_file(L, 1, NULL); - BY_HANDLE_FILE_INFORMATION info; - if (!GetFileInformationByHandle(file_handle(f), &info)) - return push_error(L); - attr = info.dwFileAttributes; - isdir = attr & FILE_ATTRIBUTE_DIRECTORY; - size = qword_to_number(info.nFileSizeHigh, info.nFileSizeLow); - } break; - } - if (lua_type(L, 2) != LUA_TTABLE) { - lua_settop(L, 1); - new_dirent(L); - } - else { - lua_settop(L, 2); - } - if (isdir) - lua_pushliteral(L, "directory"); - else - lua_pushliteral(L, "file"); - lua_setfield(L, 2, "type"); - lua_pushnumber(L, size); - lua_setfield(L, 2, "size"); - return 1; + int isdir; + lua_Number size; + DWORD attr; + switch (lua_type(L, 1)) { + default: return luaL_typerror(L, 1, "file or pathname"); + case LUA_TSTRING: { + const char *name = lua_tostring(L, 1); + attr = GetFileAttributes(name); + if (attr == (DWORD)-1) + return push_error(L); + isdir = attr & FILE_ATTRIBUTE_DIRECTORY; + if (isdir) + size = 0; + else + size = get_file_size(name); + } break; + case LUA_TUSERDATA: { + FILE *f = check_file(L, 1, NULL); + BY_HANDLE_FILE_INFORMATION info; + if (!GetFileInformationByHandle(file_handle(f), &info)) + return push_error(L); + attr = info.dwFileAttributes; + isdir = attr & FILE_ATTRIBUTE_DIRECTORY; + size = qword_to_number(info.nFileSizeHigh, info.nFileSizeLow); + } break; + } + if (lua_type(L, 2) != LUA_TTABLE) { + lua_settop(L, 1); + new_dirent(L); + } + else { + lua_settop(L, 2); + } + if (isdir) + lua_pushliteral(L, "directory"); + else + lua_pushliteral(L, "file"); + lua_setfield(L, 2, "type"); + lua_pushnumber(L, size); + lua_setfield(L, 2, "size"); + return 1; } #define DIR_HANDLE "DIR*" @@ -227,138 +228,139 @@ static int ex_dirent(lua_State *L) /* ...diriter... -- ...diriter... pathname */ static int diriter_getpathname(lua_State *L, int index) { - lua_pushvalue(L, index); - lua_gettable(L, LUA_REGISTRYINDEX); - return 1; + lua_pushvalue(L, index); + lua_gettable(L, LUA_REGISTRYINDEX); + return 1; } /* ...diriter... pathname -- ...diriter... */ static int diriter_setpathname(lua_State *L, int index) { - size_t len; - const char *path = lua_tolstring(L, -1, &len); - if (path && path[len - 1] != *LUA_DIRSEP) { - lua_pushliteral(L, LUA_DIRSEP); - lua_concat(L, 2); - } - lua_pushvalue(L, index); /* ... pathname diriter */ - lua_insert(L, -2); /* ... diriter pathname */ - lua_settable(L, LUA_REGISTRYINDEX); /* ... */ - return 0; + size_t len; + const char *path = lua_tolstring(L, -1, &len); + if (path && path[len - 1] != *LUA_DIRSEP) { + lua_pushliteral(L, LUA_DIRSEP); + lua_concat(L, 2); + } + lua_pushvalue(L, index); /* ... pathname diriter */ + lua_insert(L, -2); /* ... diriter pathname */ + lua_settable(L, LUA_REGISTRYINDEX); /* ... */ + return 0; } /* diriter -- diriter */ static int diriter_close(lua_State *L) { - DIR **pd = lua_touserdata(L, 1); - if (*pd) { - closedir(*pd); - *pd = 0; - } - lua_pushnil(L); - diriter_setpathname(L, 1); - return 0; + DIR **pd = lua_touserdata(L, 1); + if (*pd) { + closedir(*pd); + *pd = 0; + } + lua_pushnil(L); + diriter_setpathname(L, 1); + return 0; } static int isdotfile(const char *name) { - return name[0] == '.' && (name[1] == '\0' - || (name[1] == '.' && name[2] == '\0')); + return name[0] == '.' && (name[1] == '\0' + || (name[1] == '.' && name[2] == '\0')); } /* pathname -- iter state nil */ /* diriter ... -- entry */ static int ex_dir(lua_State *L) { - const char *pathname; - DIR **pd; - const WIN32_FIND_DATA *d; - switch (lua_type(L, 1)) { - default: return luaL_typerror(L, 1, "pathname"); - case LUA_TSTRING: - pathname = lua_tostring(L, 1); - lua_pushcfunction(L, ex_dir); /* pathname ... iter */ - pd = lua_newuserdata(L, sizeof *pd);/* pathname ... iter state */ - *pd = opendir(pathname); - if (!*pd) return push_error(L); - luaL_getmetatable(L, DIR_HANDLE); /* pathname ... iter state M */ - lua_setmetatable(L, -2); /* pathname ... iter state */ - lua_pushvalue(L, 1); /* pathname ... iter state pathname */ - diriter_setpathname(L, -2); /* pathname ... iter state */ - return 2; - case LUA_TUSERDATA: - pd = luaL_checkudata(L, 1, DIR_HANDLE); - do d = readdir(*pd); - while (d && isdotfile(d->cFileName)); - if (!d) return push_error(L); - new_dirent(L); /* diriter ... entry */ - diriter_getpathname(L, 1); /* diriter ... entry dirpath */ - lua_pushstring(L, d->cFileName); /* diriter ... entry dirpath name */ - lua_pushvalue(L, -1); /* diriter ... entry dirpath name name */ - lua_setfield(L, -4, "name"); /* diriter ... entry dirpath name */ - lua_concat(L, 2); /* diriter ... entry fullpath */ - lua_replace(L, 1); /* fullpath ... entry */ - lua_replace(L, 2); /* fullpath entry ... */ - return ex_dirent(L); - } - /*NOTREACHED*/ + const char *pathname; + DIR **pd; + const WIN32_FIND_DATA *d; + switch (lua_type(L, 1)) { + default: return luaL_typerror(L, 1, "pathname"); + case LUA_TSTRING: + pathname = lua_tostring(L, 1); + lua_pushcfunction(L, ex_dir); /* pathname ... iter */ + pd = lua_newuserdata(L, sizeof *pd);/* pathname ... iter state */ + *pd = opendir(pathname); + if (!*pd) return push_error(L); + luaL_getmetatable(L, DIR_HANDLE); /* pathname ... iter state M */ + lua_setmetatable(L, -2); /* pathname ... iter state */ + lua_pushvalue(L, 1); /* pathname ... iter state pathname */ + diriter_setpathname(L, -2); /* pathname ... iter state */ + return 2; + case LUA_TUSERDATA: + pd = luaL_checkudata(L, 1, DIR_HANDLE); + do d = readdir(*pd); + while (d && isdotfile(d->cFileName)) continue; + if (!d) return push_error(L); + new_dirent(L); /* diriter ... entry */ + diriter_getpathname(L, 1); /* diriter ... entry dir */ + lua_pushstring(L, d->cFileName); /* diriter ... entry dir name */ + lua_pushvalue(L, -1); /* diriter ... entry dir name name */ + lua_setfield(L, -4, "name"); /* diriter ... entry dir name */ + lua_concat(L, 2); /* diriter ... entry fullpath */ + lua_replace(L, 1); /* fullpath ... entry */ + lua_replace(L, 2); /* fullpath entry ... */ + return ex_dirent(L); + } + /*NOTREACHED*/ } -static int file_lock(lua_State *L, FILE *f, const char *mode, long offset, long length) +static int file_lock(lua_State *L, + FILE *f, const char *mode, long offset, long length) { - HANDLE h = file_handle(f); - DWORD flags; - ULARGE_INTEGER len = {0}; - OVERLAPPED ov = {0}; - BOOL ret; - if (length) len.LowPart = length; - else len.LowPart = GetFileSize(h, &len.HighPart); - ov.Offset = offset; - switch (*mode) { - case 'w': flags = LOCKFILE_EXCLUSIVE_LOCK; /*FALLTHRU*/ - case 'r': flags |= LOCKFILE_FAIL_IMMEDIATELY; break; - case 'u': flags = 0; break; - default: return luaL_error(L, "invalid mode"); - } - ret = flags ? LockFileEx(h, flags, 0, len.LowPart, len.HighPart, &ov) - : UnlockFileEx(h, 0, len.LowPart, len.HighPart, &ov); - if (!ret) - return push_error(L); - lua_settop(L, 1); - return 1; + HANDLE h = file_handle(f); + DWORD flags; + ULARGE_INTEGER len = {0}; + OVERLAPPED ov = {0}; + BOOL ret; + if (length) len.LowPart = length; + else len.LowPart = GetFileSize(h, &len.HighPart); + ov.Offset = offset; + switch (*mode) { + case 'w': flags = LOCKFILE_EXCLUSIVE_LOCK; /*FALLTHRU*/ + case 'r': flags |= LOCKFILE_FAIL_IMMEDIATELY; break; + case 'u': flags = 0; break; + default: return luaL_error(L, "invalid mode"); + } + ret = flags ? LockFileEx(h, flags, 0, len.LowPart, len.HighPart, &ov) + : UnlockFileEx(h, 0, len.LowPart, len.HighPart, &ov); + if (!ret) + return push_error(L); + lua_settop(L, 1); + return 1; } /* file mode [offset [length]] -- file/nil error */ static int ex_lock(lua_State *L) { - FILE *f = check_file(L, 1, NULL); - const char *mode = luaL_checkstring(L, 2); - long offset = luaL_optnumber(L, 3, 0); - long length = luaL_optnumber(L, 4, 0); - return file_lock(L, f, mode, offset, length); + FILE *f = check_file(L, 1, NULL); + const char *mode = luaL_checkstring(L, 2); + long offset = luaL_optnumber(L, 3, 0); + long length = luaL_optnumber(L, 4, 0); + return file_lock(L, f, mode, offset, length); } /* file [offset [length]] -- file/nil error */ static int ex_unlock(lua_State *L) { - lua_pushliteral(L, "u"); - lua_insert(L, 2); - return ex_lock(L); + lua_pushliteral(L, "u"); + lua_insert(L, 2); + return ex_lock(L); } /* -- in out/nil error */ static int ex_pipe(lua_State *L) { - HANDLE ph[2]; - if (!CreatePipe(ph + 0, ph + 1, 0, 0)) - return push_error(L); - SetHandleInformation(ph[0], HANDLE_FLAG_INHERIT, 0); - SetHandleInformation(ph[1], HANDLE_FLAG_INHERIT, 0); - new_file(L, ph[0], _O_RDONLY, "r"); - new_file(L, ph[1], _O_WRONLY, "w"); - return 2; + HANDLE ph[2]; + if (!CreatePipe(ph + 0, ph + 1, 0, 0)) + return push_error(L); + SetHandleInformation(ph[0], HANDLE_FLAG_INHERIT, 0); + SetHandleInformation(ph[1], HANDLE_FLAG_INHERIT, 0); + new_file(L, ph[0], _O_RDONLY, "r"); + new_file(L, ph[1], _O_WRONLY, "w"); + return 2; } @@ -366,98 +368,97 @@ static int ex_pipe(lua_State *L) * interval units -- */ static int ex_sleep(lua_State *L) { - lua_Number interval = luaL_checknumber(L, 1); - lua_Number units = luaL_optnumber(L, 2, 1); - Sleep(1e3 * interval / units); - return 0; + lua_Number interval = luaL_checknumber(L, 1); + lua_Number units = luaL_optnumber(L, 2, 1); + Sleep(1e3 * interval / units); + return 0; } -static void get_redirect(lua_State *L, int idx, const char *stdname, struct spawn_params *p) +static void get_redirect(lua_State *L, + int idx, const char *stdname, struct spawn_params *p) { - lua_getfield(L, idx, stdname); - if (!lua_isnil(L, -1)) - spawn_param_redirect(p, stdname, file_handle(check_file(L, -1, stdname))); - lua_pop(L, 1); + lua_getfield(L, idx, stdname); + if (!lua_isnil(L, -1)) + spawn_param_redirect(p, stdname, file_handle(check_file(L, -1, stdname))); + lua_pop(L, 1); } /* filename [args-opts] -- proc/nil error */ /* args-opts -- proc/nil error */ static int ex_spawn(lua_State *L) { - struct spawn_params *params; - int have_options; - - switch (lua_type(L, 1)) { - default: return luaL_typerror(L, 1, "string or table"); - case LUA_TSTRING: - switch (lua_type(L, 2)) { - default: return luaL_typerror(L, 2, "table"); - case LUA_TNONE: have_options = 0; break; - case LUA_TTABLE: have_options = 1; break; - } - break; - case LUA_TTABLE: - have_options = 1; - lua_getfield(L, 1, "command"); /* opts ... cmd */ - if (!lua_isnil(L, -1)) { - /* convert {command=command,arg1,...} to command {arg1,...} */ - lua_insert(L, 1); /* cmd opts ... */ - } - else { - /* convert {arg0,arg1,...} to arg0 {arg1,...} */ - size_t i, n = lua_objlen(L, 1); - lua_rawgeti(L, 1, 1); /* opts ... nil cmd */ - lua_insert(L, 1); /* cmd opts ... nil */ - for (i = 2; i <= n; i++) { - lua_rawgeti(L, 2, i); /* cmd opts ... nil argi */ - lua_rawseti(L, 2, i - 1); /* cmd opts ... nil */ - } - lua_rawseti(L, 2, n); /* cmd opts ... */ - } - if (lua_type(L, 1) != LUA_TSTRING) - return luaL_error(L, "bad command option (string expected, got %s)", - luaL_typename(L, 1)); - break; - } - - params = spawn_param_init(L); - - /* get filename to execute */ - spawn_param_filename(params, lua_tostring(L, 1)); - - /* get arguments, environment, and redirections */ - if (have_options) { - lua_getfield(L, 2, "args"); /* cmd opts ... argtab */ - switch (lua_type(L, -1)) { - default: return luaL_error(L, "bad args option (table expected, got %s)", - luaL_typename(L, -1)); - case LUA_TNIL: - lua_pop(L, 1); /* cmd opts ... */ - lua_pushvalue(L, 2); /* cmd opts ... opts */ - if (0) /*FALLTHRU*/ - case LUA_TTABLE: - if (lua_objlen(L, 2) > 0) - return luaL_error(L, "cannot specify both the args option and array values"); - spawn_param_args(params); /* cmd opts ... */ - break; - } - lua_getfield(L, 2, "env"); /* cmd opts ... envtab */ - switch (lua_type(L, -1)) { - default: return luaL_error(L, "bad env option (table expected, got %s)", - luaL_typename(L, -1)); - case LUA_TNIL: - break; - case LUA_TTABLE: - spawn_param_env(params); /* cmd opts ... */ - break; - } - get_redirect(L, 2, "stdin", params); /* cmd opts ... */ - get_redirect(L, 2, "stdout", params); /* cmd opts ... */ - get_redirect(L, 2, "stderr", params); /* cmd opts ... */ - } - - return spawn_param_execute(params); /* proc/nil error */ + struct spawn_params *params; + int have_options; + switch (lua_type(L, 1)) { + default: return luaL_typerror(L, 1, "string or table"); + case LUA_TSTRING: + switch (lua_type(L, 2)) { + default: return luaL_typerror(L, 2, "table"); + case LUA_TNONE: have_options = 0; break; + case LUA_TTABLE: have_options = 1; break; + } + break; + case LUA_TTABLE: + have_options = 1; + lua_getfield(L, 1, "command"); /* opts ... cmd */ + if (!lua_isnil(L, -1)) { + /* convert {command=command,arg1,...} to command {arg1,...} */ + lua_insert(L, 1); /* cmd opts ... */ + } + else { + /* convert {arg0,arg1,...} to arg0 {arg1,...} */ + size_t i, n = lua_objlen(L, 1); + lua_rawgeti(L, 1, 1); /* opts ... nil cmd */ + lua_insert(L, 1); /* cmd opts ... nil */ + for (i = 2; i <= n; i++) { + lua_rawgeti(L, 2, i); /* cmd opts ... nil argi */ + lua_rawseti(L, 2, i - 1); /* cmd opts ... nil */ + } + lua_rawseti(L, 2, n); /* cmd opts ... */ + } + if (lua_type(L, 1) != LUA_TSTRING) + return luaL_error(L, "bad command option (string expected, got %s)", + luaL_typename(L, 1)); + break; + } + params = spawn_param_init(L); + /* get filename to execute */ + spawn_param_filename(params, lua_tostring(L, 1)); + /* get arguments, environment, and redirections */ + if (have_options) { + lua_getfield(L, 2, "args"); /* cmd opts ... argtab */ + switch (lua_type(L, -1)) { + default: + return luaL_error(L, "bad args option (table expected, got %s)", + luaL_typename(L, -1)); + case LUA_TNIL: + lua_pop(L, 1); /* cmd opts ... */ + lua_pushvalue(L, 2); /* cmd opts ... opts */ + if (0) /*FALLTHRU*/ + case LUA_TTABLE: + if (lua_objlen(L, 2) > 0) + return + luaL_error(L, "cannot specify both the args option and array values"); + spawn_param_args(params); /* cmd opts ... */ + break; + } + lua_getfield(L, 2, "env"); /* cmd opts ... envtab */ + switch (lua_type(L, -1)) { + default: + return luaL_error(L, "bad env option (table expected, got %s)", + luaL_typename(L, -1)); + case LUA_TNIL: + break; + case LUA_TTABLE: + spawn_param_env(params); /* cmd opts ... */ + break; + } + get_redirect(L, 2, "stdin", params); /* cmd opts ... */ + get_redirect(L, 2, "stdout", params); /* cmd opts ... */ + get_redirect(L, 2, "stderr", params); /* cmd opts ... */ + } + return spawn_param_execute(params); /* proc/nil error */ } @@ -465,86 +466,78 @@ static int ex_spawn(lua_State *L) * closures from table 'from' or by creating new closures */ static void copyfields(lua_State *L, const luaL_reg *l, int from, int to) { - for (to = absindex(L, to); l->name; l++) { - lua_getfield(L, from, l->name); - if (lua_isnil(L, -1)) { - lua_pop(L, 1); - lua_pushcfunction(L, l->func); - } - lua_setfield(L, to, l->name); - } + for (to = absindex(L, to); l->name; l++) { + lua_getfield(L, from, l->name); + if (lua_isnil(L, -1)) { + lua_pop(L, 1); + lua_pushcfunction(L, l->func); + } + lua_setfield(L, to, l->name); + } } int luaopen_ex(lua_State *L) { - const luaL_reg ex_iolib[] = { - {"pipe", ex_pipe}, + const char *name = lua_tostring(L, 1); + int ex; + const luaL_reg ex_iolib[] = { + {"pipe", ex_pipe}, #define ex_iofile_methods (ex_iolib + 1) - {"lock", ex_lock}, - {"unlock", ex_unlock}, - {0,0} }; - const luaL_reg ex_oslib[] = { - {"getenv", ex_getenv}, - {"setenv", ex_setenv}, - {"environ", ex_environ}, - - {"currentdir", ex_currentdir}, - {"chdir", ex_chdir}, - {"mkdir", ex_mkdir}, - {"remove", ex_remove}, - - {"dir", ex_dir}, - {"dirent", ex_dirent}, - - {"sleep", ex_sleep}, - {"spawn", ex_spawn}, - {0,0} }; - const luaL_reg ex_diriter_methods[] = { - {"__gc", diriter_close}, - {0,0} }; - const luaL_reg ex_process_methods[] = { - {"__tostring", process_tostring}, + {"lock", ex_lock}, + {"unlock", ex_unlock}, + {0,0} }; + const luaL_reg ex_oslib[] = { + /* environment */ + {"getenv", ex_getenv}, + {"setenv", ex_setenv}, + {"environ", ex_environ}, + /* file system */ + {"currentdir", ex_currentdir}, + {"chdir", ex_chdir}, + {"mkdir", ex_mkdir}, + {"remove", ex_remove}, + {"dir", ex_dir}, + {"dirent", ex_dirent}, + /* process control */ + {"sleep", ex_sleep}, + {"spawn", ex_spawn}, + {0,0} }; + const luaL_reg ex_diriter_methods[] = { + {"__gc", diriter_close}, + {0,0} }; + const luaL_reg ex_process_methods[] = { + {"__tostring", process_tostring}, #define ex_process_functions (ex_process_methods + 1) - {"wait", process_wait}, - {0,0} }; - - int ex; - const char *name = lua_tostring(L, 1); - - /* diriter metatable */ - luaL_newmetatable(L, DIR_HANDLE); /* . D */ - luaL_register(L, 0, ex_diriter_methods); /* . D */ - - /* proc metatable */ - luaL_newmetatable(L, PROCESS_HANDLE); /* . P */ - luaL_register(L, 0, ex_process_methods); /* . P */ - lua_pushvalue(L, -1); /* . P P */ - lua_setfield(L, -2, "__index"); /* . P */ - - /* make all functions available via ex. namespace */ - luaL_register(L, name, ex_oslib); /* . P ex */ - luaL_register(L, 0, ex_iolib); - copyfields(L, ex_process_functions, -2, -1); - ex = lua_gettop(L); - - /* extend the os table */ - lua_getglobal(L, "os"); /* . os */ - if (lua_isnil(L, -1)) return luaL_error(L, "os not loaded"); - copyfields(L, ex_oslib, ex, -1); - - /* extend the io table */ - lua_getglobal(L, "io"); /* . io */ - if (lua_isnil(L, -1)) return luaL_error(L, "io not loaded"); - copyfields(L, ex_iolib, ex, -1); - lua_getfield(L, ex, "pipe"); /* . io ex_pipe */ - lua_getfield(L, -2, "stderr"); /* . io ex_pipe io_stderr */ - lua_getfenv(L, -1); /* . io ex_pipe io_stderr E */ - lua_setfenv(L, -3); /* . io ex_pipe io_stderr */ - - /* extend the io.file metatable */ - luaL_getmetatable(L, LUA_FILEHANDLE); /* . F */ - if (lua_isnil(L, -1)) return luaL_error(L, "can't find FILE* metatable"); - copyfields(L, ex_iofile_methods, ex, -1); - - return 1; + {"wait", process_wait}, + {0,0} }; + /* diriter metatable */ + luaL_newmetatable(L, DIR_HANDLE); /* . D */ + luaL_register(L, 0, ex_diriter_methods); /* . D */ + /* proc metatable */ + luaL_newmetatable(L, PROCESS_HANDLE); /* . P */ + luaL_register(L, 0, ex_process_methods); /* . P */ + lua_pushvalue(L, -1); /* . P P */ + lua_setfield(L, -2, "__index"); /* . P */ + /* make all functions available via ex. namespace */ + luaL_register(L, name, ex_oslib); /* . P ex */ + luaL_register(L, 0, ex_iolib); + copyfields(L, ex_process_functions, -2, -1); + ex = lua_gettop(L); + /* extend the os table */ + lua_getglobal(L, "os"); /* . os */ + if (lua_isnil(L, -1)) return luaL_error(L, "os not loaded"); + copyfields(L, ex_oslib, ex, -1); + /* extend the io table */ + lua_getglobal(L, "io"); /* . io */ + if (lua_isnil(L, -1)) return luaL_error(L, "io not loaded"); + copyfields(L, ex_iolib, ex, -1); + lua_getfield(L, ex, "pipe"); /* . io ex_pipe */ + lua_getfield(L, -2, "stderr"); /* . io ex_pipe io_stderr */ + lua_getfenv(L, -1); /* . io ex_pipe io_stderr E */ + lua_setfenv(L, -3); /* . io ex_pipe io_stderr */ + /* extend the io.file metatable */ + luaL_getmetatable(L, LUA_FILEHANDLE); /* . F */ + if (lua_isnil(L, -1)) return luaL_error(L, "can't find FILE* metatable"); + copyfields(L, ex_iofile_methods, ex, -1); + return 1; } diff --git a/w32api/pusherror.c b/w32api/pusherror.c index 7ae7f5c..d656c6a 100755 --- a/w32api/pusherror.c +++ b/w32api/pusherror.c @@ -18,33 +18,29 @@ * nresults is -1 and error is NO_ERROR, then push true and return 1. * Otherwise, if error is NO_ERROR, return nresults. */ -int -windows_pusherror(lua_State *L, DWORD error, int nresults) +int windows_pusherror(lua_State *L, DWORD error, int nresults) { - if (error != NO_ERROR || nresults == -2) { - char buffer[1024]; - size_t len, res; - - len = sprintf(buffer, "%lu (0x%lX): ", error, error); - - res = FormatMessage( - FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, - 0, error, 0, buffer + len, sizeof buffer - len, 0); - if (res) { - len += res; - while (len > 0 && isspace(buffer[len - 1])) - len--; - } - else - len += sprintf(buffer + len, ""); - - lua_pushnil(L); - lua_pushlstring(L, buffer, len); - nresults = 2; - } - else if (nresults < 0) { - lua_pushboolean(L, 1); - nresults = 1; - } - return nresults; + if (error != NO_ERROR || nresults == -2) { + char buffer[1024]; + size_t len = sprintf(buffer, "%lu (0x%lX): ", error, error); + size_t res = FormatMessage( + FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, + 0, error, 0, buffer + len, sizeof buffer - len, 0); + if (res) { + len += res; + while (len > 0 && isspace(buffer[len - 1])) + len--; + } + else { + len += sprintf(buffer + len, ""); + } + lua_pushnil(L); + lua_pushlstring(L, buffer, len); + nresults = 2; + } + else if (nresults < 0) { + lua_pushboolean(L, 1); + nresults = 1; + } + return nresults; } diff --git a/w32api/spawn.c b/w32api/spawn.c index f34b551..11fdc34 100755 --- a/w32api/spawn.c +++ b/w32api/spawn.c @@ -20,162 +20,160 @@ static int needs_quoting(const char *s) { - return s[0] != '"' && strchr(s, ' '); + return s[0] != '"' && strchr(s, ' '); } struct spawn_params { - lua_State *L; - const char *cmdline; - const char *environment; - STARTUPINFO si; + lua_State *L; + const char *cmdline; + const char *environment; + STARTUPINFO si; }; struct spawn_params *spawn_param_init(lua_State *L) { - static const STARTUPINFO si = {sizeof si}; - struct spawn_params *p = lua_newuserdata(L, sizeof *p); - p->L = L; - p->cmdline = p->environment = 0; - p->si = si; - return p; + static const STARTUPINFO si = {sizeof si}; + struct spawn_params *p = lua_newuserdata(L, sizeof *p); + p->L = L; + p->cmdline = p->environment = 0; + p->si = si; + return p; } void spawn_param_filename(struct spawn_params *p, const char *filename) { - 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); - } + 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); + } } /* cmd opts ... argtab -- cmd opts ... 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; - debug("spawn_param_args:"); debug_stack(L); - luaL_buffinit(L, &args); - /* 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_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); + lua_State *L = p->L; + size_t i, n = lua_objlen(L, -1); + luaL_Buffer args; + debug("spawn_param_args:"); debug_stack(L); + luaL_buffinit(L, &args); + /* 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_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); } /* ... envtab/nil */ 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); + 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); } void spawn_param_redirect(struct spawn_params *p, const char *stdname, HANDLE h) { - SetHandleInformation(h, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); - if (!(p->si.dwFlags & STARTF_USESTDHANDLES)) { - p->si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); - p->si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); - p->si.hStdError = GetStdHandle(STD_ERROR_HANDLE); - p->si.dwFlags |= STARTF_USESTDHANDLES; - } - switch (stdname[3]) { - case 'i': p->si.hStdInput = h; break; - case 'o': p->si.hStdOutput = h; break; - case 'e': p->si.hStdError = h; break; - } + SetHandleInformation(h, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); + if (!(p->si.dwFlags & STARTF_USESTDHANDLES)) { + p->si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + p->si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); + p->si.hStdError = GetStdHandle(STD_ERROR_HANDLE); + p->si.dwFlags |= STARTF_USESTDHANDLES; + } + switch (stdname[3]) { + case 'i': p->si.hStdInput = h; break; + case 'o': p->si.hStdOutput = h; break; + case 'e': p->si.hStdError = h; break; + } } struct process { - int status; - HANDLE hProcess; - DWORD dwProcessId; + int status; + HANDLE hProcess; + DWORD dwProcessId; }; int spawn_param_execute(struct spawn_params *p) { - lua_State *L = p->L; - struct process *proc; - char *c, *e; - PROCESS_INFORMATION pi; - BOOL ret; - - 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 */ - proc->status = -1; - c = strdup(p->cmdline); - e = (char *)p->environment; /* strdup(p->environment); */ - /* XXX does CreateProcess modify its environment argument? */ - ret = CreateProcess(0, c, 0, 0, TRUE, 0, e, 0, &p->si, &pi); - /* if (e) free(e); */ - free(c); - if (!ret) - return windows_pushlasterror(L); - proc->hProcess = pi.hProcess; - proc->dwProcessId = pi.dwProcessId; - return 1; + lua_State *L = p->L; + char *c, *e; + PROCESS_INFORMATION pi; + BOOL ret; + struct process *proc = lua_newuserdata(L, sizeof *proc); + luaL_getmetatable(L, PROCESS_HANDLE); + lua_setmetatable(L, -2); + proc->status = -1; + c = strdup(p->cmdline); + e = (char *)p->environment; /* strdup(p->environment); */ + /* XXX does CreateProcess modify its environment argument? */ + ret = CreateProcess(0, c, 0, 0, TRUE, 0, e, 0, &p->si, &pi); + /* if (e) free(e); */ + free(c); + if (!ret) + return windows_pushlasterror(L); + proc->hProcess = pi.hProcess; + proc->dwProcessId = pi.dwProcessId; + return 1; } /* proc -- exitcode/nil error */ int process_wait(lua_State *L) { - struct process *p = luaL_checkudata(L, 1, PROCESS_HANDLE); - if (p->status == -1) { - DWORD exitcode; - if (WAIT_FAILED == WaitForSingleObject(p->hProcess, INFINITE) - || !GetExitCodeProcess(p->hProcess, &exitcode)) - return windows_pushlasterror(L); - p->status = exitcode; - } - lua_pushnumber(L, p->status); - return 1; + struct process *p = luaL_checkudata(L, 1, PROCESS_HANDLE); + if (p->status == -1) { + DWORD exitcode; + if (WAIT_FAILED == WaitForSingleObject(p->hProcess, INFINITE) + || !GetExitCodeProcess(p->hProcess, &exitcode)) + return windows_pushlasterror(L); + p->status = exitcode; + } + lua_pushnumber(L, p->status); + return 1; } /* proc -- string */ int process_tostring(lua_State *L) { - struct process *p = luaL_checkudata(L, 1, PROCESS_HANDLE); - char buf[40]; - lua_pushlstring(L, buf, - sprintf(buf, "process (%lu, %s)", (unsigned long)p->dwProcessId, - p->status==-1 ? "running" : "terminated")); - return 1; + struct process *p = luaL_checkudata(L, 1, PROCESS_HANDLE); + char buf[40]; + lua_pushlstring(L, buf, + sprintf(buf, "process (%lu, %s)", (unsigned long)p->dwProcessId, + p->status==-1 ? "running" : "terminated")); + return 1; } diff --git a/w32api/spawn.h b/w32api/spawn.h index bff6feb..da51a4f 100755 --- a/w32api/spawn.h +++ b/w32api/spawn.h @@ -17,7 +17,10 @@ struct spawn_params *spawn_param_init(lua_State *L); void spawn_param_filename(struct spawn_params *p, const char *filename); void spawn_param_args(struct spawn_params *p); void spawn_param_env(struct spawn_params *p); -void spawn_param_redirect(struct spawn_params *p, const char *stdname, HANDLE h); +void spawn_param_redirect( + struct spawn_params *p, + const char *stdname, + HANDLE h); int spawn_param_execute(struct spawn_params *p); int process_wait(lua_State *L);