A few changes.

master
mark 20 years ago
parent 465e0c4d57
commit 785c362a9f

@ -1,8 +1,8 @@
CFLAGS = -std=c99 $(WARNINGS) $(DEFINES) $(INCLUDES)
DEFINES = -D_POSIX_SOURCE -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=200112L \
-U__STRICT_ANSI__ \
-D_GNU_SOURCE -DMISSING_POSIX_SPAWN \
-D'debug(...)=fprintf(stderr,__VA_ARGS__)'
CFLAGS = $(WARNINGS) $(DEFINES) $(INCLUDES)
DEFINES = $(DEBUG) -D_XOPEN_SOURCE=500 -DMISSING_POSIX_SPAWN
DEBUG= -D'debug(...)=fprintf(stderr,__VA_ARGS__)'
# -D_POSIX_SOURCE -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=200112L \
-U__STRICT_ANSI__ -D_GNU_SOURCE
INCLUDES = -I$(LUA)/include
WARNINGS = -W -Wall
#LUA = /home/mark/src/lang/lua/lua-5.1-rc2
@ -16,9 +16,11 @@ ex.so: $(ex-OBJS); $(CC) -shared -o $@ $(ex-OBJS)
#LIBS = -L$(LUA)/lib -llua51 spawn.a
EXTRA = posix_spawn.o
ex.dll: $(ex-OBJS) $(LIBS); $(CC) -shared -L$(LUA)/bin/Cygwin -o $@ $(ex-OBJS) $(EXTRA) -llua51
ex.dll: $(ex-OBJS) $(EXTRA) $(LIBS); $(CC) -shared -L$(LUA)/bin/Cygwin -o $@ $(ex-OBJS) $(EXTRA) -llua51
ex.o: ex.c spawn.h
spawn.o: spawn.c spawn.h
posix_spawn.o: posix_spawn.c posix_spawn.h
clean:; rm -f *.o ex.dll ex.so ex.a

@ -1,17 +1,16 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <string.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <fcntl.h>
#include <sys/stat.h>
#include "spawn.h"
@ -121,11 +120,11 @@ 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(idx);
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, "%s option: expected %s, got %s",
luaL_error(L, "bad %s option (%s expected, got %s)",
argname, LUA_FILEHANDLE, luaL_typename(L, idx));
lua_pop(L, 2);
}
@ -137,8 +136,10 @@ FILE *check_file(lua_State *L, int idx, const char *argname)
static int ex_dirent(lua_State *L)
{
struct stat st;
int isdir;
lua_Number size;
switch (lua_type(L, 1)) {
default: return luaL_argerror(L, 1, "expected file or pathname");
default: return luaL_typerror(L, 1, "file or pathname");
case LUA_TSTRING: {
const char *name = lua_tostring(L, 1);
if (-1 == stat(name, &st))
@ -150,18 +151,19 @@ static int ex_dirent(lua_State *L)
return push_error(L);
} break;
}
isdir = S_ISDIR(st.st_mode);
if (lua_type(L, 2) != LUA_TTABLE) {
lua_newtable(L);
lua_replace(L, 2);
}
lua_pushliteral(L, "type");
if (S_ISDIR(st.st_mode))
if (isdir)
lua_pushliteral(L, "directory");
else
lua_pushliteral(L, "file");
lua_settable(L, 2);
lua_pushliteral(L, "size");
lua_pushnumber(L, st.st_size);
lua_pushnumber(L, size);
lua_settable(L, 2);
lua_settop(L, 2);
return 1;
@ -216,7 +218,7 @@ static int ex_dir(lua_State *L)
struct diriter *pi;
struct dirent *d;
switch (lua_type(L, 1)) {
default: return luaL_argerror(L, 1, "expected pathname");
default: return luaL_typerror(L, 1, "pathname");
case LUA_TSTRING:
pathname = lua_tostring(L, 1);
lua_pushcfunction(L, ex_dir); /* pathname ... iter */
@ -313,7 +315,6 @@ static int ex_pipe(lua_State *L)
FILE *i, *o, **pf;
if (!make_pipe(&i, &o))
return push_error(L);
debug("make_pipe returns %p<-%p\n", i, o);
luaL_getmetatable(L, LUA_FILEHANDLE); /* M */
*(pf = lua_newuserdata(L, sizeof *pf)) = i; /* M i */
lua_pushvalue(L, -2); /* M i M */
@ -337,9 +338,20 @@ static void get_redirect(lua_State *L, int idx, const char *stdname, struct spaw
/* args-opts -- true/nil error */
static int ex_spawn(lua_State *L)
{
struct spawn_params *params = spawn_param_init(L);
struct spawn_params *params;
int have_options;
if (lua_type(L, 1) == LUA_TTABLE) {
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,...} */
@ -356,21 +368,23 @@ static int ex_spawn(lua_State *L)
}
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 */
if (lua_type(L, 1) != LUA_TSTRING)
return luaL_error(L, "command option: expected string, got %s", luaL_typename(L, 1));
spawn_param_filename(params, lua_tostring(L, 1));
/* get arguments, environment, and redirections */
switch (lua_type(L, 2)) {
default: return luaL_argerror(L, 2, "expected options table");
case LUA_TNONE: break;
case LUA_TTABLE:
if (have_options) {
lua_getfield(L, 2, "args"); /* cmd opts ... argtab */
switch (lua_type(L, -1)) {
default: return luaL_error(L, "args option must be an array");
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 */
@ -383,7 +397,8 @@ static int ex_spawn(lua_State *L)
}
lua_getfield(L, 2, "env"); /* cmd opts ... envtab */
switch (lua_type(L, -1)) {
default: return luaL_error(L, "env option must be a table");
default: return luaL_error(L, "bad env option (table expected, got %s)",
luaL_typename(L, -1));
case LUA_TNIL:
case LUA_TTABLE:
spawn_param_env(params); /* cmd opts ... */
@ -392,8 +407,8 @@ static int ex_spawn(lua_State *L)
get_redirect(L, 2, "stdin", params); /* cmd opts ... */
get_redirect(L, 2, "stdout", params); /* cmd opts ... */
get_redirect(L, 2, "stderr", params); /* cmd opts ... */
break;
}
return spawn_param_execute(params); /* proc/nil error */
}
@ -486,9 +501,7 @@ int luaopen_ex(lua_State *L)
/* proc metatable */
luaL_newmetatable(L, PROCESS_HANDLE); /* ex . P */
copy_fields(L, ex_process_methods, 1, -1); /* ex . P */
lua_pushliteral(L, "__index"); /* ex . P __index */
lua_pushvalue(L, -2); /* ex . P __index P */
lua_settable(L, -3); /* ex . P */
lua_setfield(L, -1, "__index"); /* ex . P */
lua_settop(L, 1); /* ex */
return 1;

@ -5,7 +5,8 @@
#include <unistd.h>
#include <limits.h>
#include <sys/types.h>
#include "spawn.h"
#include "posix_spawn.h"
#define nelemof(A) (sizeof A / sizeof *A)
@ -50,10 +51,12 @@ int posix_spawnp(pid_t *restrict ppid,
case -1: return -1;
default: return 0;
case 0:
if (act)
for (size_t i = 0; i < nelemof(act->dups); i++)
if (act) {
size_t i;
for (i = 0; i < nelemof(act->dups); i++)
if (act->dups[i] > -1)
dup2(i, act->dups[i]);
}
environ = (char **)envp;
execvp(path, argv);
_exit(EXIT_FAILURE);

@ -2,6 +2,10 @@
#include <signal.h>
#include <sys/types.h>
#if __STDC_VERSION__ < 199901L
#define restrict
#endif
typedef void *posix_spawnattr_t;
enum {

@ -1,3 +1,5 @@
#include <assert.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
@ -115,11 +117,8 @@ struct process {
int spawn_param_execute(struct spawn_params *p)
{
lua_State *L = p->L;
struct process *proc = lua_newuserdata(L, sizeof *proc);
int ret;
luaL_getmetatable(L, PROCESS_HANDLE);
lua_setmetatable(L, -2);
proc->status = -1;
struct process *proc;
if (!p->argv) {
p->argv = lua_newuserdata(L, 2 * sizeof *p->argv);
p->argv[0] = p->command;
@ -127,6 +126,10 @@ int spawn_param_execute(struct spawn_params *p)
}
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;

@ -1,6 +1,7 @@
#ifndef SPAWN_H
#define SPAWN_H
#include <stdio.h>
#include <lua.h>
#define PROCESS_HANDLE "process"

@ -2,7 +2,7 @@
require "ex"
print"os.chdir"
assert(os.chdir(".."))
assert(os.chdir("tests"))
print(os.currentdir())
print"os.mkdir"

@ -1,6 +1,5 @@
#!/usr/bin/env lua
require "ex"
local f = assert(io.open("hullo.test", "w+"))
f:lock("w")
f:write("Hello\n")

@ -1,6 +1,5 @@
#!/usr/bin/env lua
require "ex"
assert(arg[1], "argument required")
local proc = assert(os.spawn(arg[1]))
print(proc)

@ -143,12 +143,12 @@ 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(idx);
idx = absindex(L, idx);
pf = lua_touserdata(L, idx);
luaL_getmetatable(L, LUA_FILEHANDLE);
if (!pf || !lua_getmetatable(L, idx - 1) || !lua_rawequal(L, -1, -2))
luaL_error(L, "%s option: expected %s, got %s",
argname, LUA_FILEHANDLE, luaL_typename(L, idx - 2));
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;
@ -176,27 +176,30 @@ static uint64_t get_size(const char *name)
/* pathname/file -- entry */
static int ex_dirent(lua_State *L)
{
DWORD attr;
uint64_t size;
int isdir;
lua_Number size;
switch (lua_type(L, 1)) {
default: return luaL_argerror(L, 1, "expected file or pathname");
default: return luaL_typerror(L, 1, "file or pathname");
case LUA_TSTRING: {
const char *name = lua_tostring(L, 1);
attr = GetFileAttributes(name);
DWORD attr = GetFileAttributes(name);
if (attr == (DWORD)-1)
return push_error(L);
if (attr & FILE_ATTRIBUTE_DIRECTORY)
isdir = attr & FILE_ATTRIBUTE_DIRECTORY;
if (isdir)
size = 0;
else
size = get_size(name);
} break;
case LUA_TUSERDATA: {
FILE *f = check_file(L, 1, NULL);
uint64_t lsize;
BY_HANDLE_FILE_INFORMATION info;
if (!GetFileInformationByHandle(get_handle(f), &info))
return push_error(L);
attr = info.dwFileAttributes;
size = info.nFileSizeHigh; size <<= 32; size += info.nFileSizeLow;
isdir = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
lsize = info.nFileSizeHigh; lsize <<= 32; lsize += info.nFileSizeLow;
size = lsize;
} break;
}
if (lua_type(L, 2) != LUA_TTABLE) {
@ -204,7 +207,7 @@ static int ex_dirent(lua_State *L)
lua_replace(L, 2);
}
lua_pushliteral(L, "type");
if (attr & FILE_ATTRIBUTE_DIRECTORY)
if (isdir)
lua_pushliteral(L, "directory");
else
lua_pushliteral(L, "file");
@ -235,7 +238,7 @@ static int diriter_setpathname(lua_State *L, int index)
{
size_t len;
const char *path = lua_tolstring(L, -1, &len);
if (path[len - 1] != *LUA_DIRSEP) {
if (path && path[len - 1] != *LUA_DIRSEP) {
lua_pushliteral(L, LUA_DIRSEP);
lua_concat(L, 2);
}
@ -265,7 +268,7 @@ static int ex_dir(lua_State *L)
const char *pathname;
struct diriter *pi;
switch (lua_type(L, 1)) {
default: return luaL_argerror(L, 1, "expected pathname");
default: return luaL_typerror(L, 1, "pathname");
case LUA_TSTRING:
lua_pushvalue(L, 1); /* pathname ... pathname */
lua_pushliteral(L, "\\*"); /* pathname ... pathname "\\*" */
@ -389,9 +392,20 @@ static void get_redirect(lua_State *L, int idx, const char *stdname, struct spaw
/* args-opts -- true/nil error */
static int ex_spawn(lua_State *L)
{
struct spawn_params *params = spawn_param_init(L);
struct spawn_params *params;
int have_options;
if (lua_type(L, 1) == LUA_TTABLE) {
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,...} */
@ -408,21 +422,23 @@ static int ex_spawn(lua_State *L)
}
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 */
if (lua_type(L, 1) != LUA_TSTRING)
return luaL_error(L, "command option: expected string, got %s", luaL_typename(L, 1));
spawn_param_filename(params, lua_tostring(L, 1));
/* get arguments, environment, and redirections */
switch (lua_type(L, 2)) {
default: return luaL_argerror(L, 2, "expected options table");
case LUA_TNONE: break;
case LUA_TTABLE:
if (have_options) {
lua_getfield(L, 2, "args"); /* cmd opts ... argtab */
switch (lua_type(L, -1)) {
default: return luaL_error(L, "args option must be an array");
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 */
@ -435,7 +451,8 @@ static int ex_spawn(lua_State *L)
}
lua_getfield(L, 2, "env"); /* cmd opts ... envtab */
switch (lua_type(L, -1)) {
default: return luaL_error(L, "env option must be a table");
default: return luaL_error(L, "bad env option (table expected, got %s)",
luaL_typename(L, -1));
case LUA_TNIL:
case LUA_TTABLE:
spawn_param_env(params); /* cmd opts ... */
@ -444,8 +461,8 @@ static int ex_spawn(lua_State *L)
get_redirect(L, 2, "stdin", params); /* cmd opts ... */
get_redirect(L, 2, "stdout", params); /* cmd opts ... */
get_redirect(L, 2, "stderr", params); /* cmd opts ... */
break;
}
return spawn_param_execute(params); /* proc/nil error */
}
@ -538,9 +555,7 @@ int luaopen_ex(lua_State *L)
/* proc metatable */
luaL_newmetatable(L, PROCESS_HANDLE); /* ex . P */
copy_fields(L, ex_process_methods, 1, -1); /* ex . P */
lua_pushliteral(L, "__index"); /* ex . P __index */
lua_pushvalue(L, -2); /* ex . P __index P */
lua_settable(L, -3); /* ex . P */
lua_setfield(L, -1, "__index"); /* ex . P */
lua_settop(L, 1); /* ex */
return 1;

Loading…
Cancel
Save