*** empty log message ***

master
mark 20 years ago
parent d0e584b79f
commit 76a98495ba

@ -0,0 +1,31 @@
ex-20070109
API changes
* os.unsetenv is now folded into os.setenv
* os.rmdir is now folded into os.remove
* os.dir now elides . and .. entries from the listing
* lock and unlock now appear in the io table
* io.lock and io.unlock return the file object in case of success
POSIX implementation changes
* ENVIRON_DECL should be defined to expand to extern char **environ; on systems which neglect to declare environ when including <unistd.h>
* prepare for dirent metatable
* ex_pipe() refactored
Windows implementation changes
* os.remove must be overridden
* prepare for dirent metatable
* simplify directory iteration by adding POSIX-like abstraction
* ex_pipe() refactored

@ -1,10 +1,10 @@
-- Environment -- Environment
os.setenv(name, value) os.getenv(name) -- get environment variable
os.unsetenv(name) os.setenv(name, value) -- set/unset environment variable
os.environ() -- returns a copy of the environment os.environ() -- returns a copy of the environment
-- Miscellaneous -- Miscellaneous
os.sleep(seconds) os.sleep(seconds) -- sleep for (floating) seconds
-- File system -- File system
os.chdir(pathname) os.chdir(pathname)

@ -1,13 +1,13 @@
CFLAGS = $(WARNINGS) $(DEFINES) $(INCLUDES) CFLAGS = $(WARNINGS) $(DEFINES) $(INCLUDES)
DEFINES = $(DEBUG) -D_XOPEN_SOURCE=600 -DMISSING_POSIX_SPAWN -DMISSING_ENVIRON_DECL="extern char **environ" DEFINES = $(DEBUG) -D_XOPEN_SOURCE=600 -DMISSING_POSIX_SPAWN -DENVIRON_DECL="extern char **environ;"
DEBUG= -D'debug(...)=fprintf(stderr,__VA_ARGS__)' DEBUG= -D'debug(...)=fprintf(stderr,__VA_ARGS__)'
# -D_POSIX_SOURCE -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=200112L \ # -D_POSIX_SOURCE -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=200112L \
-U__STRICT_ANSI__ -D_GNU_SOURCE -U__STRICT_ANSI__ -D_GNU_SOURCE
INCLUDES = -I$(LUA)/include -I$(LUA)/src INCLUDES = -I$(LUA)/include -I$(LUA)/src
WARNINGS = -W -Wall WARNINGS = -W -Wall
#LUA = /home/mark/src/lang/lua/lua-5.1-rc2 #LUA = /home/mark/src/lang/lua/lua-5.1-rc2
#LUA = /home/mark/src/lang/lua/lua51
LUA = /home/medgar/src/lang/lua/lua-5.1.1 LUA = /home/medgar/src/lang/lua/lua-5.1.1
#LUA = /home/medgar/src/lang/lua/lua5_1_1/cygw15
LIBS = -L$(LUA)/src -llua5.1 LIBS = -L$(LUA)/src -llua5.1
ex-OBJS = ex.o spawn.o ex-OBJS = ex.o spawn.o

@ -3,23 +3,21 @@
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#include <unistd.h> /* environ */
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#include <unistd.h> #include <unistd.h>
ENVIRON_DECL
#include <dirent.h> #include <dirent.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/stat.h> #include <sys/stat.h>
#include "spawn.h" #include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
MISSING_ENVIRON_DECL; #define absindex(L,i) ((i)>0?(i):lua_gettop(L)+(i)+1)
#include "spawn.h"
#define absindex(L,i) ((i)>0?(i):lua_gettop(L)+(i)+1)
/* -- nil error */ /* -- nil error */
extern int push_error(lua_State *L) extern int push_error(lua_State *L)
@ -41,8 +39,8 @@ static int ex_getenv(lua_State *L)
return 1; return 1;
} }
/* name value -- true/nil error * /* name value -- true/nil error
* name -- true/nil error */ * name nil -- true/nil error */
static int ex_setenv(lua_State *L) static int ex_setenv(lua_State *L)
{ {
const char *nam = luaL_checkstring(L, 1); const char *nam = luaL_checkstring(L, 1);
@ -126,13 +124,23 @@ static FILE *check_file(lua_State *L, int idx, const char *argname)
return *pf; 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;
}
#define new_dirent(L) lua_newtable(L) #define new_dirent(L) lua_newtable(L)
/* pathname/file -- entry */ /* pathname/file [entry] -- entry */
static int ex_dirent(lua_State *L) static int ex_dirent(lua_State *L)
{ {
struct stat st; struct stat st;
int isdir;
switch (lua_type(L, 1)) { switch (lua_type(L, 1)) {
default: return luaL_typerror(L, 1, "file or pathname"); default: return luaL_typerror(L, 1, "file or pathname");
case LUA_TSTRING: { case LUA_TSTRING: {
@ -146,19 +154,20 @@ static int ex_dirent(lua_State *L)
return push_error(L); return push_error(L);
} break; } break;
} }
isdir = S_ISDIR(st.st_mode);
if (lua_type(L, 2) != LUA_TTABLE) { if (lua_type(L, 2) != LUA_TTABLE) {
lua_settop(L, 1);
new_dirent(L); new_dirent(L);
lua_replace(L, 2);
} }
if (isdir) else {
lua_settop(L, 2);
}
if (S_ISDIR(st.st_mode))
lua_pushliteral(L, "directory"); lua_pushliteral(L, "directory");
else else
lua_pushliteral(L, "file"); lua_pushliteral(L, "file");
lua_setfield(L, 2, "type"); lua_setfield(L, 2, "type");
lua_pushnumber(L, st.st_size); lua_pushnumber(L, st.st_size);
lua_setfield(L, 2, "size"); lua_setfield(L, 2, "size");
lua_settop(L, 2);
return 1; return 1;
} }
@ -202,8 +211,8 @@ static int diriter_close(lua_State *L)
static int isdotfile(const char *name) static int isdotfile(const char *name)
{ {
return name[0] && (name[1] == 0 return name[0] == '.' && (name[1] == '\0'
|| (name[1] == '.' && name[2] == 0)); || (name[1] == '.' && name[2] == '\0'));
} }
/* pathname -- iter state nil */ /* pathname -- iter state nil */
@ -259,11 +268,11 @@ static int file_lock(lua_State *L, FILE *f, const char *mode, long offset, long
k.l_len = length; k.l_len = length;
if (-1 == fcntl(fileno(f), F_SETLK, &k)) if (-1 == fcntl(fileno(f), F_SETLK, &k))
return push_error(L); return push_error(L);
lua_pushboolean(L, 1); lua_settop(L, 1);
return 1; return 1;
} }
/* file mode [offset [length]] -- true/nil error */ /* file mode [offset [length]] -- file/nil error */
static int ex_lock(lua_State *L) static int ex_lock(lua_State *L)
{ {
FILE *f = check_file(L, 1, NULL); FILE *f = check_file(L, 1, NULL);
@ -273,7 +282,7 @@ static int ex_lock(lua_State *L)
return file_lock(L, f, mode, offset, length); return file_lock(L, f, mode, offset, length);
} }
/* file [offset [length]] -- true/nil error */ /* file [offset [length]] -- file/nil error */
static int ex_unlock(lua_State *L) static int ex_unlock(lua_State *L)
{ {
lua_pushliteral(L, "u"); lua_pushliteral(L, "u");
@ -290,22 +299,12 @@ static int closeonexec(int d)
return fl; return fl;
} }
static int 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 1;
}
/* -- in out/nil error */ /* -- in out/nil error */
static int ex_pipe(lua_State *L) static int ex_pipe(lua_State *L)
{ {
int fd[2]; int fd[2];
if (-1 == pipe(fd)) if (-1 == pipe(fd))
return 0; return push_error(L);
closeonexec(fd[0]); closeonexec(fd[0]);
closeonexec(fd[1]); closeonexec(fd[1]);
new_file(L, fd[0], "r"); new_file(L, fd[0], "r");
@ -322,8 +321,8 @@ static void get_redirect(lua_State *L, int idx, const char *stdname, struct spaw
lua_pop(L, 1); lua_pop(L, 1);
} }
/* filename [args-opts] -- true/nil error */ /* filename [args-opts] -- proc/nil error */
/* args-opts -- true/nil error */ /* args-opts -- proc/nil error */
static int ex_spawn(lua_State *L) static int ex_spawn(lua_State *L)
{ {
struct spawn_params *params; struct spawn_params *params;
@ -385,13 +384,13 @@ static int ex_spawn(lua_State *L)
} }
lua_getfield(L, 2, "env"); /* cmd opts ... envtab */ lua_getfield(L, 2, "env"); /* cmd opts ... envtab */
switch (lua_type(L, -1)) { switch (lua_type(L, -1)) {
default: return luaL_error(L, "bad env option (table expected, got %s)",
luaL_typename(L, -1));
case LUA_TNIL: case LUA_TNIL:
break; break;
case LUA_TTABLE: case LUA_TTABLE:
spawn_param_env(params); /* cmd opts ... */ spawn_param_env(params); /* cmd opts ... */
break; break;
default:
return luaL_error(L, "bad env option (table expected, got %s)", luaL_typename(L, -1));
} }
get_redirect(L, 2, "stdin", params); /* cmd opts ... */ get_redirect(L, 2, "stdin", params); /* cmd opts ... */
get_redirect(L, 2, "stdout", params); /* cmd opts ... */ get_redirect(L, 2, "stdout", params); /* cmd opts ... */
@ -405,9 +404,7 @@ static int ex_spawn(lua_State *L)
/* copy the fields given in 'l' from one table to another; insert missing fields */ /* copy the fields given in 'l' from one table to another; insert missing fields */
static void copy_fields(lua_State *L, const luaL_reg *l, int from, int to) static void copy_fields(lua_State *L, const luaL_reg *l, int from, int to)
{ {
from = absindex(L, from); for (to = absindex(L, to); l->name; l++) {
to = absindex(L, to);
for (; l->name; l++) {
lua_getfield(L, from, l->name); lua_getfield(L, from, l->name);
if (lua_isnil(L, -1)) { if (lua_isnil(L, -1)) {
lua_pop(L, 1); lua_pop(L, 1);
@ -467,6 +464,7 @@ int luaopen_ex(lua_State *L)
lua_getglobal(L, "io"); /* ex . io */ lua_getglobal(L, "io"); /* ex . io */
if (lua_isnil(L, -1)) return luaL_error(L, "io not loaded"); if (lua_isnil(L, -1)) return luaL_error(L, "io not loaded");
copy_fields(L, ex_iolib, 1, -1); /* ex . io */ copy_fields(L, ex_iolib, 1, -1); /* ex . io */
copy_fields(L, ex_iofile_methods, 1, -1); /* ex . io */
lua_getfield(L, 1, "pipe"); /* ex . io ex_pipe */ lua_getfield(L, 1, "pipe"); /* ex . io ex_pipe */
lua_getfield(L, -2, "stderr"); /* ex . io ex_pipe io_stderr */ lua_getfield(L, -2, "stderr"); /* ex . io ex_pipe io_stderr */
lua_getfenv(L, -1); /* ex . io ex_pipe io_stderr E */ lua_getfenv(L, -1); /* ex . io ex_pipe io_stderr E */

@ -3,6 +3,7 @@
#include <errno.h> #include <errno.h>
#include <unistd.h> #include <unistd.h>
ENVIRON_DECL
#include <limits.h> #include <limits.h>
#include <sys/types.h> #include <sys/types.h>
@ -12,7 +13,6 @@
#define OPEN_MAX sysconf(_SC_OPEN_MAX) #define OPEN_MAX sysconf(_SC_OPEN_MAX)
#endif #endif
MISSING_ENVIRON_DECL;
int posix_spawn_file_actions_init(posix_spawn_file_actions_t *act) int posix_spawn_file_actions_init(posix_spawn_file_actions_t *act)
{ {

@ -1,7 +1,5 @@
#include "lua.h"
#include "lauxlib.h"
#include <unistd.h> #include <unistd.h>
ENVIRON_DECL
#include <sys/wait.h> #include <sys/wait.h>
#if MISSING_POSIX_SPAWN #if MISSING_POSIX_SPAWN
#include "posix_spawn.h" #include "posix_spawn.h"
@ -9,8 +7,10 @@
#include <spawn.h> #include <spawn.h>
#endif #endif
#include "lua.h"
#include "lauxlib.h"
#include "spawn.h" #include "spawn.h"
MISSING_ENVIRON_DECL;
struct spawn_params { struct spawn_params {
lua_State *L; lua_State *L;

@ -2,7 +2,7 @@
#define SPAWN_H #define SPAWN_H
#include <stdio.h> #include <stdio.h>
#include <lua.h> #include "lua.h"
#define PROCESS_HANDLE "process" #define PROCESS_HANDLE "process"
struct process; struct process;

@ -8,8 +8,10 @@ WARNINGS = -W -Wall -Wno-missing-braces
LUA = /home/medgar/work/noom/lua/lua51 LUA = /home/medgar/work/noom/lua/lua51
LUALIBS = -L$(LUA) -llua5.1 LUALIBS = -L$(LUA) -llua5.1
ex.dll-OBJS = ex.o spawn.o pusherror.o ex.dll-OBJS = ex.o spawn.o pusherror.o dirent.o
ex.dll-LIBS = $(LUALIBS) $(EXTRALIBS) ex.dll-LIBS = $(LUALIBS) $(EXTRALIBS)
ex.dll: $(ex.dll-OBJS) ex.dll: $(ex.dll-OBJS)
$(CC) $(TARGET_ARCH) -shared -o $@ $(ex.dll-OBJS) $(ex.dll-LIBS) $(CC) $(TARGET_ARCH) -shared -o $@ $(ex.dll-OBJS) $(ex.dll-LIBS)
clean:; rm ex.dll *.o clean:; rm ex.dll *.o
wdir.o: wdir.c wdir.h

@ -0,0 +1,68 @@
#include <windows.h>
#include <stdlib.h>
#include "dirent.h"
struct DIR_tag {
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;
}
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;
}
static int isdotfile(const char *name)
{
return name[0] == '.' && (name[1] == 0
|| (name[1] == '.' && name[2] == 0));
}
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;
}
void
closedir(DIR *pi)
{
if (pi->hf != INVALID_HANDLE_VALUE)
{
FindClose(pi->hf);
pi->hf = INVALID_HANDLE_VALUE;
}
free(pi);
}

@ -0,0 +1,6 @@
#include <windows.h>
typedef struct DIR_tag DIR;
DIR *opendir(const char *name);
const WIN32_FIND_DATA *readdir(DIR *pi);
void closedir(DIR *pi);

@ -7,18 +7,19 @@
#include <io.h> #include <io.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/locking.h> #include <sys/locking.h>
#include "dirent.h"
#include "lua.h" #include "lua.h"
#include "lualib.h" #include "lualib.h"
#include "lauxlib.h" #include "lauxlib.h"
#include "spawn.h" #define absindex(L,i) ((i)>0?(i):lua_gettop(L)+(i)+1)
#include "pusherror.h"
#include "spawn.h"
#define absindex(L,i) ((i)>0?(i):lua_gettop(L)+(i)+1) #include "pusherror.h"
#define push_error(L) windows_pushlasterror(L)
#define file_handle(fp) (HANDLE)_get_osfhandle(fileno(fp))
/* name -- value/nil */ /* name -- value/nil */
@ -32,7 +33,7 @@ static int ex_getenv(lua_State *L)
len = GetEnvironmentVariable(nam, val, sizeof val); len = GetEnvironmentVariable(nam, val, sizeof val);
} }
if (len == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND) if (len == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND)
return windows_pushlasterror(L); return push_error(L);
lua_pushlstring(L, val, len); lua_pushlstring(L, val, len);
if (val != sval) free(val); if (val != sval) free(val);
return 1; return 1;
@ -45,7 +46,7 @@ static int ex_setenv(lua_State *L)
const char *nam = luaL_checkstring(L, 1); const char *nam = luaL_checkstring(L, 1);
const char *val = lua_tostring(L, 2); const char *val = lua_tostring(L, 2);
if (!SetEnvironmentVariable(nam, val)) if (!SetEnvironmentVariable(nam, val))
return windows_pushlasterror(L); return push_error(L);
lua_pushboolean(L, 1); lua_pushboolean(L, 1);
return 1; return 1;
} }
@ -55,7 +56,7 @@ static int ex_environ(lua_State *L)
{ {
const char *nam, *val, *end; const char *nam, *val, *end;
const char *envs = GetEnvironmentStrings(); const char *envs = GetEnvironmentStrings();
if (!envs) return windows_pushlasterror(L); if (!envs) return push_error(L);
lua_newtable(L); lua_newtable(L);
for (nam = envs; *nam; nam = end + 1) { for (nam = envs; *nam; nam = end + 1) {
end = strchr(val = strchr(nam, '=') + 1, '\0'); end = strchr(val = strchr(nam, '=') + 1, '\0');
@ -81,7 +82,7 @@ static int ex_chdir(lua_State *L)
{ {
const char *pathname = luaL_checkstring(L, 1); const char *pathname = luaL_checkstring(L, 1);
if (!SetCurrentDirectory(pathname)) if (!SetCurrentDirectory(pathname))
return windows_pushlasterror(L); return push_error(L);
lua_pushboolean(L, 1); lua_pushboolean(L, 1);
return 1; return 1;
} }
@ -91,7 +92,7 @@ static int ex_mkdir(lua_State *L)
{ {
const char *pathname = luaL_checkstring(L, 1); const char *pathname = luaL_checkstring(L, 1);
if (!CreateDirectory(pathname, 0)) if (!CreateDirectory(pathname, 0))
return windows_pushlasterror(L); return push_error(L);
lua_pushboolean(L, 1); lua_pushboolean(L, 1);
return 1; return 1;
} }
@ -101,7 +102,7 @@ static int ex_currentdir(lua_State *L)
{ {
char pathname[MAX_PATH + 1]; char pathname[MAX_PATH + 1];
size_t len = GetCurrentDirectory(sizeof pathname, pathname); size_t len = GetCurrentDirectory(sizeof pathname, pathname);
if (len == 0) return windows_pushlasterror(L); if (len == 0) return push_error(L);
lua_pushlstring(L, pathname, len); lua_pushlstring(L, pathname, len);
return 1; return 1;
} }
@ -115,12 +116,13 @@ static int ex_remove(lua_State *L)
|| (attr & FILE_ATTRIBUTE_DIRECTORY || (attr & FILE_ATTRIBUTE_DIRECTORY
? !RemoveDirectory(pathname) ? !RemoveDirectory(pathname)
: !DeleteFile(pathname))) : !DeleteFile(pathname)))
return windows_pushlasterror(L); return push_error(L);
lua_pushboolean(L, 1); lua_pushboolean(L, 1);
return 1; return 1;
} }
FILE *check_file(lua_State *L, int idx, const char *argname)
static FILE *check_file(lua_State *L, int idx, const char *argname)
{ {
FILE **pf; FILE **pf;
if (idx > 0) pf = luaL_checkudata(L, idx, LUA_FILEHANDLE); if (idx > 0) pf = luaL_checkudata(L, idx, LUA_FILEHANDLE);
@ -137,6 +139,19 @@ FILE *check_file(lua_State *L, int idx, const char *argname)
return *pf; 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;
}
#define file_handle(fp) (HANDLE)_get_osfhandle(fileno(fp))
static uint64_t get_file_size(const char *name) static uint64_t get_file_size(const char *name)
{ {
HANDLE h = CreateFile(name, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); HANDLE h = CreateFile(name, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
@ -169,7 +184,7 @@ static int ex_dirent(lua_State *L)
const char *name = lua_tostring(L, 1); const char *name = lua_tostring(L, 1);
attr = GetFileAttributes(name); attr = GetFileAttributes(name);
if (attr == (DWORD)-1) if (attr == (DWORD)-1)
return windows_pushlasterror(L); return push_error(L);
isdir = attr & FILE_ATTRIBUTE_DIRECTORY; isdir = attr & FILE_ATTRIBUTE_DIRECTORY;
if (isdir) if (isdir)
size = 0; size = 0;
@ -181,7 +196,7 @@ static int ex_dirent(lua_State *L)
uint64_t lsize; uint64_t lsize;
BY_HANDLE_FILE_INFORMATION info; BY_HANDLE_FILE_INFORMATION info;
if (!GetFileInformationByHandle(file_handle(f), &info)) if (!GetFileInformationByHandle(file_handle(f), &info))
return windows_pushlasterror(L); return push_error(L);
attr = info.dwFileAttributes; attr = info.dwFileAttributes;
isdir = attr & FILE_ATTRIBUTE_DIRECTORY; isdir = attr & FILE_ATTRIBUTE_DIRECTORY;
lsize = info.nFileSizeHigh; lsize <<= 32; lsize += info.nFileSizeLow; lsize = info.nFileSizeHigh; lsize <<= 32; lsize += info.nFileSizeLow;
@ -205,12 +220,7 @@ static int ex_dirent(lua_State *L)
return 1; return 1;
} }
#define DIR_HANDLE "WIN32_FIND_DATA" #define DIR_HANDLE "DIR*"
struct diriter {
HANDLE hf;
int first;
WIN32_FIND_DATA fd;
};
/* ...diriter... -- ...diriter... pathname */ /* ...diriter... -- ...diriter... pathname */
static int diriter_getpathname(lua_State *L, int index) static int diriter_getpathname(lua_State *L, int index)
@ -238,32 +248,18 @@ static int diriter_setpathname(lua_State *L, int index)
/* diriter -- diriter */ /* diriter -- diriter */
static int diriter_close(lua_State *L) static int diriter_close(lua_State *L)
{ {
struct diriter *pi = lua_touserdata(L, 1); DIR **pd = lua_touserdata(L, 1);
if (pi->hf != INVALID_HANDLE_VALUE) { closedir(*pd);
FindClose(pi->hf); *pd = 0;
pi->hf = INVALID_HANDLE_VALUE;
}
lua_pushnil(L); lua_pushnil(L);
diriter_setpathname(L, 1); diriter_setpathname(L, 1);
return 0; return 0;
} }
static int isdotfile(const char *filename) static int isdotfile(const char *name)
{ {
return filename[0] == '.' && return name[0] == '.' && (name[1] == '\0'
(filename[1] == '\0' || (filename[1] == '.' && filename[2] == '\0')); || (name[1] == '.' && name[2] == '\0'));
}
static int nextfile(struct diriter *pi)
{
if (!pi->first || isdotfile(pi->fd.cFileName))
do if (!FindNextFile(pi->hf, &pi->fd)) {
FindClose(pi->hf);
pi->hf = INVALID_HANDLE_VALUE;
return 0;
} while (isdotfile(pi->fd.cFileName));
pi->first = 0;
return 1;
} }
/* pathname -- iter state nil */ /* pathname -- iter state nil */
@ -271,31 +267,29 @@ static int nextfile(struct diriter *pi)
static int ex_dir(lua_State *L) static int ex_dir(lua_State *L)
{ {
const char *pathname; const char *pathname;
struct diriter *pi; DIR **pd;
const WIN32_FIND_DATA *d;
switch (lua_type(L, 1)) { switch (lua_type(L, 1)) {
default: return luaL_typerror(L, 1, "pathname"); default: return luaL_typerror(L, 1, "pathname");
case LUA_TSTRING: case LUA_TSTRING:
lua_pushvalue(L, 1); /* pathname ... pathname */ pathname = lua_tostring(L, 1);
lua_pushliteral(L, "\\*"); /* pathname ... pathname "\\*" */ lua_pushcfunction(L, ex_dir); /* pathname ... iter */
lua_concat(L, 2); /* pathname ... pattern */ pd = lua_newuserdata(L, sizeof *pd);/* pathname ... iter state */
pathname = lua_tostring(L, -1); *pd = opendir(pathname);
lua_pushcfunction(L, ex_dir); /* pathname ... pat iter */ if (!*pd) return push_error(L);
pi = lua_newuserdata(L, sizeof *pi);/* pathname ... pat iter state */ luaL_getmetatable(L, DIR_HANDLE); /* pathname ... iter state M */
pi->hf = FindFirstFile(pathname, &pi->fd); lua_setmetatable(L, -2); /* pathname ... iter state */
if (pi->hf == INVALID_HANDLE_VALUE) lua_pushvalue(L, 1); /* pathname ... iter state pathname */
return windows_pushlasterror(L); diriter_setpathname(L, -2); /* pathname ... iter state */
pi->first = 1;
luaL_getmetatable(L, DIR_HANDLE); /* pathname ... pat iter state M */
lua_setmetatable(L, -2); /* pathname ... pat iter state */
lua_pushvalue(L, 1); /* pathname ... pat iter state pathname */
diriter_setpathname(L, -2); /* pathname ... pat iter state */
return 2; return 2;
case LUA_TUSERDATA: case LUA_TUSERDATA:
pi = luaL_checkudata(L, 1, DIR_HANDLE); pd = luaL_checkudata(L, 1, DIR_HANDLE);
if (!nextfile(pi)) return 0; do d = readdir(*pd);
while (d && isdotfile(d->cFileName));
if (!d) return push_error(L);
new_dirent(L); /* diriter ... entry */ new_dirent(L); /* diriter ... entry */
diriter_getpathname(L, 1); /* diriter ... entry dirpath */ diriter_getpathname(L, 1); /* diriter ... entry dirpath */
lua_pushstring(L, pi->fd.cFileName);/* diriter ... entry dirpath name */ lua_pushstring(L, d->cFileName); /* diriter ... entry dirpath name */
lua_pushvalue(L, -1); /* diriter ... entry dirpath name name */ lua_pushvalue(L, -1); /* diriter ... entry dirpath name name */
lua_setfield(L, -4, "name"); /* diriter ... entry dirpath name */ lua_setfield(L, -4, "name"); /* diriter ... entry dirpath name */
lua_concat(L, 2); /* diriter ... entry fullpath */ lua_concat(L, 2); /* diriter ... entry fullpath */
@ -326,8 +320,7 @@ static int file_lock(lua_State *L, FILE *f, const char *mode, long offset, long
ret = flags ? LockFileEx(h, flags, 0, len.LowPart, len.HighPart, &ov) ret = flags ? LockFileEx(h, flags, 0, len.LowPart, len.HighPart, &ov)
: UnlockFileEx(h, 0, len.LowPart, len.HighPart, &ov); : UnlockFileEx(h, 0, len.LowPart, len.HighPart, &ov);
if (!ret) if (!ret)
return windows_pushlasterror(L); return push_error(L);
/* return the file */
lua_settop(L, 1); lua_settop(L, 1);
return 1; return 1;
} }
@ -351,33 +344,16 @@ static int ex_unlock(lua_State *L)
} }
static int make_pipe(FILE **i, FILE **o) /* -- in out/nil error */
static int ex_pipe(lua_State *L)
{ {
HANDLE ph[2]; HANDLE ph[2];
if (0 == CreatePipe(ph+0, ph+1, 0, 0)) if (!CreatePipe(ph + 0, ph + 1, 0, 0))
return 0; return push_error(L);
SetHandleInformation(ph[0], HANDLE_FLAG_INHERIT, 0); SetHandleInformation(ph[0], HANDLE_FLAG_INHERIT, 0);
SetHandleInformation(ph[1], HANDLE_FLAG_INHERIT, 0); SetHandleInformation(ph[1], HANDLE_FLAG_INHERIT, 0);
*i = _fdopen(_open_osfhandle((long)ph[0], _O_RDONLY), "r"); new_file(L, ph[0], _O_RDONLY, "r");
*o = _fdopen(_open_osfhandle((long)ph[1], _O_WRONLY), "w"); new_file(L, ph[1], _O_WRONLY, "w");
return 1;
}
#define new_file(L) lua_newuserdata(L, sizeof(FILE *))
/* -- in out/nil error */
static int ex_pipe(lua_State *L)
{
FILE *i, *o, **pf;
if (!make_pipe(&i, &o))
return windows_pushlasterror(L);
luaL_getmetatable(L, LUA_FILEHANDLE); /* M */
*(pf = new_file(L)) = i; /* M i */
lua_pushvalue(L, -2); /* M i M */
lua_setmetatable(L, -2); /* M i */
*(pf = new_file(L)) = o; /* M i o */
lua_pushvalue(L, -3); /* M i o M */
lua_setmetatable(L, -2); /* M i o */
return 2; return 2;
} }
@ -386,7 +362,7 @@ static void get_redirect(lua_State *L, int idx, const char *stdname, struct spaw
{ {
lua_getfield(L, idx, stdname); lua_getfield(L, idx, stdname);
if (!lua_isnil(L, -1)) if (!lua_isnil(L, -1))
spawn_param_redirect(p, stdname, check_file(L, -1, stdname)); spawn_param_redirect(p, stdname, file_handle(check_file(L, -1, stdname)));
lua_pop(L, 1); lua_pop(L, 1);
} }
@ -456,6 +432,7 @@ static int ex_spawn(lua_State *L)
default: return luaL_error(L, "bad env option (table expected, got %s)", default: return luaL_error(L, "bad env option (table expected, got %s)",
luaL_typename(L, -1)); luaL_typename(L, -1));
case LUA_TNIL: case LUA_TNIL:
break;
case LUA_TTABLE: case LUA_TTABLE:
spawn_param_env(params); /* cmd opts ... */ spawn_param_env(params); /* cmd opts ... */
break; break;
@ -468,11 +445,11 @@ static int ex_spawn(lua_State *L)
return spawn_param_execute(params); /* proc/nil error */ return spawn_param_execute(params); /* proc/nil error */
} }
/* copy the fields given in 'l' from one table to another; insert missing fields */ /* copy the fields given in 'l' from one table to another; insert missing fields */
static void copy_fields(lua_State *L, const luaL_reg *l, int from, int to) static void copy_fields(lua_State *L, const luaL_reg *l, int from, int to)
{ {
to = absindex(L, to); for (to = absindex(L, to); l->name; l++) {
for (; l->name; l++) {
lua_getfield(L, from, l->name); lua_getfield(L, from, l->name);
if (lua_isnil(L, -1)) { if (lua_isnil(L, -1)) {
lua_pop(L, 1); lua_pop(L, 1);
@ -533,6 +510,7 @@ int luaopen_ex(lua_State *L)
lua_getglobal(L, "io"); /* ex . io */ lua_getglobal(L, "io"); /* ex . io */
if (lua_isnil(L, -1)) return luaL_error(L, "io not loaded"); if (lua_isnil(L, -1)) return luaL_error(L, "io not loaded");
copy_fields(L, ex_iolib, 1, -1); /* ex . io */ copy_fields(L, ex_iolib, 1, -1); /* ex . io */
copy_fields(L, ex_iofile_methods, 1, -1); /* ex . io */
lua_getfield(L, 1, "pipe"); /* ex . io ex_pipe */ lua_getfield(L, 1, "pipe"); /* ex . io ex_pipe */
lua_getfield(L, -2, "stderr"); /* ex . io ex_pipe io_stderr */ lua_getfield(L, -2, "stderr"); /* ex . io ex_pipe io_stderr */
lua_getfenv(L, -1); /* ex . io ex_pipe io_stderr E */ lua_getfenv(L, -1); /* ex . io ex_pipe io_stderr E */

@ -1,8 +1,8 @@
#ifndef pusherror_h #ifndef pusherror_h
#define pusherror_h #define pusherror_h
#include <lua.h>
#include <windows.h> #include <windows.h>
#include "lua.h"
int windows_pusherror(lua_State *L, DWORD error, int nresults); int windows_pusherror(lua_State *L, DWORD error, int nresults);
#define windows_pushlasterror(L) windows_pusherror(L, GetLastError(), -2) #define windows_pushlasterror(L) windows_pusherror(L, GetLastError(), -2)

@ -1,11 +1,10 @@
#include <stdlib.h> #include <stdlib.h>
#include <lua.h>
#include <lauxlib.h>
#include <windows.h> #include <windows.h>
#include <io.h> #include <io.h>
#include "lua.h"
#include "lauxlib.h"
#include "spawn.h" #include "spawn.h"
#include "pusherror.h" #include "pusherror.h"
@ -81,11 +80,6 @@ void spawn_param_env(struct spawn_params *p)
{ {
lua_State *L = p->L; lua_State *L = p->L;
luaL_Buffer env; luaL_Buffer env;
if (lua_isnil(L, -1)) {
p->environment = 0;
lua_pop(L, 1);
return;
}
/* convert env table to zstring list */ /* convert env table to zstring list */
/* {nam1=val1,nam2=val2} => "nam1=val1\0nam2=val2\0\0" */ /* {nam1=val1,nam2=val2} => "nam1=val1\0nam2=val2\0\0" */
luaL_buffinit(L, &env); luaL_buffinit(L, &env);
@ -108,9 +102,8 @@ void spawn_param_env(struct spawn_params *p)
p->environment = lua_tostring(L, -1); p->environment = lua_tostring(L, -1);
} }
void spawn_param_redirect(struct spawn_params *p, const char *stdname, FILE *f) void spawn_param_redirect(struct spawn_params *p, const char *stdname, HANDLE h)
{ {
HANDLE h = file_handle(f);
SetHandleInformation(h, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); SetHandleInformation(h, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
if (!(p->si.dwFlags & STARTF_USESTDHANDLES)) { if (!(p->si.dwFlags & STARTF_USESTDHANDLES)) {
p->si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); p->si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);

@ -1,8 +1,8 @@
#ifndef SPAWN_H #ifndef SPAWN_H
#define SPAWN_H #define SPAWN_H
#include <lua.h>
#include <windows.h> #include <windows.h>
#include "lua.h"
#define PROCESS_HANDLE "process" #define PROCESS_HANDLE "process"
struct process; struct process;
@ -12,7 +12,7 @@ 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, const char *filename);
void spawn_param_args(struct spawn_params *p); void spawn_param_args(struct spawn_params *p);
void spawn_param_env(struct spawn_params *p); void spawn_param_env(struct spawn_params *p);
void spawn_param_redirect(struct spawn_params *p, const char *stdname, FILE *f); void spawn_param_redirect(struct spawn_params *p, const char *stdname, HANDLE h);
int spawn_param_execute(struct spawn_params *p); int spawn_param_execute(struct spawn_params *p);
int process_wait(lua_State *L); int process_wait(lua_State *L);

Loading…
Cancel
Save