From 99b32cb1b49f01732ff45d92d95155043980149d Mon Sep 17 00:00:00 2001 From: mark Date: Fri, 27 Jan 2006 08:55:26 +0000 Subject: [PATCH] renamed w32api/osex.c to ex.c --- Makefile | 2 +- README | 9 +- rt1.lua | 13 ++ rt2.lua | 6 + w32api/Makefile | 10 +- w32api/ex.c | 410 ++++++++++++++++++++++++++++++++++++++++++++++++ w32api/leak1.c | 29 ++++ w32api/osex.c | 229 --------------------------- 8 files changed, 469 insertions(+), 239 deletions(-) create mode 100755 rt1.lua create mode 100755 rt2.lua create mode 100755 w32api/ex.c create mode 100755 w32api/leak1.c delete mode 100755 w32api/osex.c diff --git a/Makefile b/Makefile index 5100fe4..4f3d57e 100755 --- a/Makefile +++ b/Makefile @@ -2,4 +2,4 @@ CFLAGS = $(WARNINGS) $(DEFINES) $(INCLUDES) DEFINES = -D_XOPEN_SOURCE=600 INCLUDES = -I${LUA}/src WARNINGS = -W -Wall -LUA = /home/mark/src/lang/lua/lua-5.1 +LUA = /home/mark/src/lang/lua/lua-5.0.2 diff --git a/README b/README index d680c6a..a60a4da 100755 --- a/README +++ b/README @@ -1,7 +1,7 @@ -- Environment -os.environ() -- returns a copy of the environment os.setenv(name, value) os.unsetenv(name) +os.environ() -- returns a copy of the environment -- Miscellaneous os.sleep(seconds) @@ -14,17 +14,18 @@ os.mkdir(pathname) for stat in os.dir(pathname) do ; end stat = os.stat(pathname) --[[ - stat is a table, contain at least the following keys: + stat is a table, containing at least the following keys: name: the filename type: "file" or "directory" or another implementation-defined string size: the file size in bytes --]] +-- Locking and pipes file = io.open("filename", "w") file:lock(mode, start, length) -- mode is "r" or "w", start and length are optional file:unlock(start, length) -- start and length are optional +in, out = io.pipe() -- Process control pid = os.spawn(filename, {args={}, env={}, stdin=file, stdout=file, stderr=file}) -in, out = os.pipe() -- in and out are io.file objects -exitcode = os.wait(pid) +exitcode = pid:wait(pid) diff --git a/rt1.lua b/rt1.lua new file mode 100755 index 0000000..955cbbc --- /dev/null +++ b/rt1.lua @@ -0,0 +1,13 @@ +#!/usr/bin/env lua +require "ex" + +--print"os.sleep" +--os.sleep(2); + +print"os.setenv" +assert(os.setenv("foo", "42")) +print("foo=", os.getenv("foo")) +assert(os.unsetenv("foo")) +print("foo=", os.getenv("foo")) + + diff --git a/rt2.lua b/rt2.lua new file mode 100755 index 0000000..11bdd59 --- /dev/null +++ b/rt2.lua @@ -0,0 +1,6 @@ +#!/usr/bin/env lua +require "ex" + +print"os.environ" +local e = assert(os.environ()) +table.foreach(e, function(nam,val) print(string.format("%s=%s", nam, val)) end) diff --git a/w32api/Makefile b/w32api/Makefile index 1fd1841..51221b3 100755 --- a/w32api/Makefile +++ b/w32api/Makefile @@ -1,10 +1,10 @@ TARGET_ARCH = -mno-cygwin CFLAGS = $(WARNINGS) $(DEFINES) $(INCLUDES) DEFINES = -DWIN32_LEAN_AND_MEAN -INCLUDES = -I${LUA}/src +INCLUDES = -I${LUA}/include WARNINGS = -W -Wall -LUA = /home/mark/src/lang/lua/lua-5.1 -LUALIBS = -L$(LUA)/src -llua51 +LUA = /home/mark/src/lang/lua/lua-5.1-rc2 +LUALIBS = -L$(LUA)/lib -llua51 -osex.dll: osex.o - $(CC) -shared -o $@ osex.o $(LUALIBS) /c/windows/system32/msvcrt.dll +ex.dll: ex.o + $(CC) $(TARGET_ARCH) -shared -o $@ ex.o $(LUALIBS) /c/windows/system32/msvcrt.dll diff --git a/w32api/ex.c b/w32api/ex.c new file mode 100755 index 0000000..1a6a814 --- /dev/null +++ b/w32api/ex.c @@ -0,0 +1,410 @@ +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + + +/* Generally useful function -- what luaL_checkudata() should do */ +static void * +luaL_checkuserdata(lua_State *L, int idx, const char *tname) +{ + void *ud; + luaL_argcheck(L, ud = luaL_checkudata(L, idx, tname), idx, tname); + return ud; +} + + +/* -- nil error */ +static int windows_error(lua_State *L) +{ + DWORD error = GetLastError(); + 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); + return 2; +} + + +/* -- environment-table */ +static int ex_environ(lua_State *L) +{ + const char *envs, *nam, *val, *end; + if (!(envs = GetEnvironmentStrings())) + return windows_error(L); + lua_newtable(L); + for (nam = envs; *nam; nam = end + 1) { + val = strchr(nam, '='); + end = strchr(val, '\0'); + lua_pushlstring(L, nam, val - nam); + val++; + lua_pushlstring(L, val, end - val); + lua_settable(L, -3); + } + return 1; +} + +/* name -- value/nil */ +static int ex_getenv(lua_State *L) +{ + const char *nam = luaL_checkstring(L, 1); + char val[1024]; + size_t len; + len = GetEnvironmentVariable(nam, val, sizeof val); + if (sizeof val < len) + return windows_error(L); + else if (len == 0) + lua_pushnil(L); + else + lua_pushlstring(L, val, len); + return 1; +} + +/* name value -- true/nil error */ +static int ex_setenv(lua_State *L) +{ + const char *nam = luaL_checkstring(L, 1); + const char *val = luaL_checkstring(L, 2); + if (!SetEnvironmentVariable(nam, val)) + return windows_error(L); + lua_pushboolean(L, 1); + return 1; +} + +/* name -- true/nil error */ +static int ex_unsetenv(lua_State *L) +{ + const char *nam = luaL_checkstring(L, 1); + if (!SetEnvironmentVariable(nam, 0)) + return windows_error(L); + lua_pushboolean(L, 1); + return 1; +} + + +/* seconds -- */ +static int ex_sleep(lua_State *L) +{ + lua_Number seconds = luaL_checknumber(L, 1); + Sleep(1e3 * seconds); + return 0; +} + + +/* pathname -- true/nil error */ +static int ex_chdir(lua_State *L) +{ + const char *pathname = luaL_checkstring(L, 1); + if (!SetCurrentDirectory(pathname)) + return windows_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 windows_error(L); + lua_pushboolean(L, 1); + return 1; +} + +/* -- pathname/nil error */ +static int ex_currentdir(lua_State *L) +{ + char pathname[PATH_MAX + 1]; + size_t len; + if (!(len = GetCurrentDirectory(sizeof pathname, pathname))) + return windows_error(L); + lua_pushlstring(L, pathname, len); + return 1; +} + + +/* pathname -- iter state nil */ +static int ex_dir(lua_State *L) { return luaL_error(L, "not yet implemented"); } + +/* pathname -- entry */ +static int ex_dirent(lua_State *L) { return luaL_error(L, "not yet implemented"); } + + +static int file_lock(lua_State *L, FILE *fh, const char *mode, long start, long len) +{ + int code; + int lkmode; + switch (*mode) { + case 'r': lkmode = LK_NBLCK; break; + case 'w': lkmode = LK_NBLCK; break; + case 'u': lkmode = LK_UNLCK; break; + default : return luaL_error (L, "invalid mode"); + } + if (!len) { + fseek (fh, 0L, SEEK_END); + len = ftell (fh); + } + fseek (fh, start, SEEK_SET); + code = _locking (fileno(fh), lkmode, len); + if (code == -1) { + lua_pushboolean(L, 0); + lua_pushstring(L, strerror(errno)); + return 2; + } + else { + lua_pushboolean(L, 1); + return 1; + } +} + +/* file mode [start [length]] -- true/nil error */ +static int ex_lock(lua_State *L) +{ + FILE *f = luaL_checkuserdata(L, 1, LUA_FILEHANDLE); + const char *mode = luaL_checkstring(L, 2); + long start = luaL_optnumber(L, 3, 0); + long length = luaL_optnumber(L, 4, 0); + return file_lock(L, f, mode, start, length); +} + +/* file [start [length]] -- true/nil error */ +static int ex_unlock(lua_State *L) +{ + FILE *f = luaL_checkuserdata(L, 1, LUA_FILEHANDLE); + long start = luaL_optnumber(L, 2, 0); + long length = luaL_optnumber(L, 3, 0); + return file_lock(L, f, "u", start, length); +} + + +/* -- in out/nil error */ +static int ex_pipe(lua_State *L) +{ + HANDLE ph[2]; + FILE **pf; + if (0 == CreatePipe(ph+0, ph+1, 0, 0)) + return windows_error(L); + luaL_getmetatable(L, LUA_FILEHANDLE); /* M */ + pf = lua_newuserdata(L, sizeof *pf); /* M in */ + lua_pushvalue(L, -2); /* M in M */ + lua_setmetatable(L, -2); /* M in */ + *pf = _fdopen(_open_osfhandle((long)ph[0], _O_RDONLY), "r"); + pf = lua_newuserdata(L, sizeof *pf); /* M in out */ + lua_pushvalue(L, -3); /* M in out M */ + lua_setmetatable(L, -2); /* M in out */ + *pf = _fdopen(_open_osfhandle((long)ph[1], _O_WRONLY), "w"); + return 2; +} + + +int abs_index(lua_State *L, int idx) +{ + return idx >= 0 ? idx : lua_gettop(L) + idx + 1; +} + +static const char *concat_args(lua_State *L, int index) +{ + luaL_Buffer args; + luaL_buffinit(L, &args); + size_t i, n = lua_objlen(L, index); + index = abs_index(L, index); + for (i = 1; i <= n; i++) { + int space; + lua_rawgeti(L, index, i); + space = 0 == strchr(luaL_checkstring(L, -1), ' '); + luaL_putchar(&args, ' '); + if (space) luaL_putchar(&args, '"'); + luaL_addvalue(&args); + if (space) luaL_putchar(&args, '"'); + } + lua_pop(L, n); + luaL_pushresult(&args); + return lua_tostring(L, -1); +} + +static const char *concat_env(lua_State *L, int index) +{ + luaL_Buffer env; + index = abs_index(L, index); + luaL_buffinit(L, &env); + lua_pushnil(L); /* nil */ + while (lua_next(L, -2)) { /* k v */ + /* Is the luaL_checktype() warning message useful here? */ + luaL_checktype(L, -2, LUA_TSTRING); + luaL_checktype(L, -1, LUA_TSTRING); + lua_pushvalue(L, -2); /* k v k */ + luaL_addvalue(&env); + luaL_putchar(&env, '='); + lua_pop(L, 1); /* k v */ + luaL_addvalue(&env); + luaL_putchar(&env, '\0'); + lua_pop(L, 1); /* k */ + } + luaL_putchar(&env, '\0'); + luaL_pushresult(&env); /* env */ + return lua_tostring(L, -1); +} + +static void get_redirect(lua_State *L, const char *stream, HANDLE *handle) +{ + lua_getfield(L, 2, stream); + if (!lua_isnil(L, -1)) { + FILE **pf = luaL_checkuserdata(L, -1, LUA_FILEHANDLE); + *handle = (HANDLE)_get_osfhandle(_fileno(*pf)); + } + lua_pop(L, 1); +} + +#define PROCESS_HANDLE "process" +struct process { + HANDLE hProcess; + int status; +}; + +/* filename [options] -- true/nil,error */ +/* args-options -- true/nil,error */ +static int ex_spawn(lua_State *L) +{ + const char *cmdline; + const char *environment; + struct process *p; + STARTUPINFO si; + PROCESS_INFORMATION pi; + BOOL ret; + /* XXX check for filename,options or just options */ + luaL_checktype(L, 1, LUA_TSTRING); + cmdline = lua_tostring(L, 1); + environment = 0; + si.cb = sizeof si; + si.dwFlags = STARTF_USESTDHANDLES; + si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); + si.hStdError = GetStdHandle(STD_ERROR_HANDLE); + if (lua_type(L, 2) == LUA_TTABLE) { + lua_getfield(L, 2, "args"); + if (!lua_isnil(L, -1)) { + luaL_checktype(L, -1, LUA_TTABLE); + lua_pushvalue(L, 1); /* push filename */ + concat_args(L, -2); + lua_concat(L, 2); /* filename .. (" args")* */ + cmdline = lua_tostring(L, -1); + } + lua_getfield(L, 2, "env"); + if (!lua_isnil(L, -1)) { + luaL_checktype(L, -1, LUA_TTABLE); + environment = concat_env(L, -1); + } + get_redirect(L, "stdin", &si.hStdInput); + get_redirect(L, "stdout", &si.hStdOutput); + get_redirect(L, "stderr", &si.hStdError); + } + p = lua_newuserdata(L, sizeof *p); + luaL_getmetatable(L, PROCESS_HANDLE); + lua_setmetatable(L, -2); + p->status = -1; + cmdline = strdup(cmdline); + environment = strdup(environment); + ret = CreateProcess(0, (char *)cmdline, 0, 0, 0, 0, (char *)environment, 0, &si, &pi); + free((char *)cmdline); + free((char *)environment); + if (!ret) + return windows_error(L); + p->hProcess = pi.hProcess; + return 1; +} + +/* proc -- exitcode/nil error */ +static int process_wait(lua_State *L) +{ + struct process *p = luaL_checkuserdata(L, 1, PROCESS_HANDLE); + if (p->status != -1) { + DWORD exitcode; + WaitForSingleObject(p->hProcess, INFINITE); + GetExitCodeProcess(p->hProcess, &exitcode); + p->status = exitcode; + } + lua_pushnumber(L, p->status); + return 1; +} + + +static const luaL_reg ex_iolib[] = { + {"pipe", ex_pipe}, + {0,0} +}; +static const luaL_reg ex_iofile_methods[] = { + {"lock", ex_lock}, + {"unlock", ex_unlock}, + {0,0} +}; +static const luaL_reg ex_oslib[] = { + {"getenv", ex_getenv}, + {"setenv", ex_setenv}, + {"unsetenv", ex_unsetenv}, + {"environ", ex_environ}, + + {"sleep", ex_sleep}, + + {"chdir", ex_chdir}, + {"mkdir", ex_mkdir}, + {"currentdir", ex_currentdir}, + + {"dir", ex_dir}, + {"dirent", ex_dirent}, + + {"spawn", ex_spawn}, + {0,0} +}; +static const luaL_reg ex_process_methods[] = { + {"wait", process_wait}, + {0,0} +}; + +int luaopen_ex(lua_State *L) +{ + + /* extend the io table */ + lua_getglobal(L, "io"); + if (lua_isnil(L, -1)) luaL_error(L, "io not loaded"); + luaL_openlib(L, 0, ex_iolib, 0); + + /* extend the os table */ + lua_getglobal(L, "os"); + if (lua_isnil(L, -1)) luaL_error(L, "os not loaded"); + luaL_openlib(L, "os", ex_oslib, 0); + + /* extend the io.file metatable */ + luaL_getmetatable(L, LUA_FILEHANDLE); + if (lua_isnil(L, -1)) luaL_error(L, "can't find FILE* metatable"); + luaL_openlib(L, 0, ex_iofile_methods, 0); + + /* proc metatable */ + luaL_newmetatable(L, PROCESS_HANDLE); /* proc */ + luaL_openlib(L, 0, ex_process_methods, 0); /* proc */ + lua_pushliteral(L, "__index"); /* proc __index */ + lua_pushvalue(L, -2); /* proc __index proc */ + lua_settable(L, -3); /* proc */ + + /* for lack of a better thing to return */ + lua_pushboolean(L, 1); + return 1; +} diff --git a/w32api/leak1.c b/w32api/leak1.c new file mode 100755 index 0000000..4160104 --- /dev/null +++ b/w32api/leak1.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include +#include + +int main(void) +{ + HANDLE h; + FILE *f; + h = CreateFile("NUL", GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); + assert(h != INVALID_HANDLE_VALUE); + f = _fdopen(_open_osfhandle(h, _O_RDONLY), "r"); + assert(f != 0); + assert(fgetc(f) == EOF); + fclose(f); +#if 0 + { + char buf[20]; + DWORD len; + fprintf(stderr, "read: %d\n", ReadFile(h, buf, sizeof buf, &len, 0)); + fprintf(stderr, "error: %lu\n", GetLastError()); + fprintf(stderr, "len: %lu\n", len); + } +#endif + fprintf(stderr, "%d\n", CloseHandle(h)); + fprintf(stderr, "error: %lu\n", GetLastError()); + return 0; +} diff --git a/w32api/osex.c b/w32api/osex.c deleted file mode 100755 index 662be3f..0000000 --- a/w32api/osex.c +++ /dev/null @@ -1,229 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -extern char **environ; - -/* helper functions */ -static void *safe_alloc(lua_State *L, void *p, size_t n) -#if 0 -{ - void *q = realloc(p, n); - if (!q) { - realloc(p, 0); - lua_error(L, "memory allocation error"); - } - return q; -} -#else -{ - p = lua_newuserdata(L, n); - lua_pop(L, 1); - return p; -} -#endif - - -static int windows_error(lua_State *L) -{ - DWORD error = GetLastError(); - 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); - return 2; -} - - -/* seconds -- */ -static int osex_sleep(lua_State *L) -{ - lua_Number seconds = luaL_checknumber(L, 1); - Sleep(1e3 * seconds); - return 0; -} - - -#define PROCESS_HANDLE "process" - -struct process { - HANDLE hProcess; - int status; -}; - -/* -extern long _get_osfhandle(int); -extern int _fileno(FILE *); -*/ - -static void get_redirect(lua_State *L, const char *stream, HANDLE *handle) -{ - lua_getfield(L, 2, stream); - if (!lua_isnil(L, -1)) { - FILE **pf = luaL_checkudata(L, -1, LUA_FILEHANDLE); - *handle = (HANDLE)_get_osfhandle(_fileno(*pf)); - } - lua_pop(L, 1); -} - -int abs_index(lua_State *L, int idx) -{ - if (idx < 0) - return lua_gettop(L) + idx + 1; - return idx; -} - -static char *insert_args(lua_State *L, int index, char *cmd, size_t cmdlen) -{ - size_t alloc = cmdlen + 1; - size_t i, n = lua_objlen(L, index); - index = abs_index(L, index); - for (i = 1; i <= n; i++) { - size_t arglen; - const char *arg; - lua_rawgeti(L, -1, i); - arg = luaL_checklstring(L, -1, &arglen); - if (cmdlen + arglen + 1 >= alloc) - cmd = safe_alloc(L, cmd, alloc *= 2); - cmdlen += sprintf(cmd + cmdlen, " \"%s\"", arg); - lua_pop(L, 1); - } - return cmd; -} - -static char *insert_env(lua_State *L, int index) -{ - char *env; - size_t envlen, alloc; - index = abs_index(L, index); - envlen = 0; - env = safe_alloc(L, env, alloc = 256); - lua_pushnil(L); - while (lua_next(L, -2)) { - size_t namlen, vallen; - const char *nam = luaL_checklstring(L, -2, &namlen); - const char *val = luaL_checklstring(L, -2, &vallen); - if (namlen + 1 + vallen + 2 >= alloc) - env = safe_alloc(L, env, alloc *= 2); - envlen += sprintf(env + envlen, "%s=%s", nam, val); - env[envlen++] = '\0'; - } - env[envlen] = '\0'; - return env; -} - -/* filename [options] -- true/nil,error */ -static int osex_spawn(lua_State *L) -{ - size_t len; - const char *filename; - char *cmdline; - char *environment; - struct process *p; - STARTUPINFO si; - PROCESS_INFORMATION pi; - filename = luaL_checklstring(L, 1, &len); - cmdline = safe_alloc(L, 0, len += 3); - sprintf(cmdline, "\"%s\"", filename); - environment = 0; - si.cb = sizeof si; - si.dwFlags = STARTF_USESTDHANDLES; - si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); - si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); - si.hStdError = GetStdHandle(STD_ERROR_HANDLE); - if (lua_type(L, 2) == LUA_TTABLE) { - lua_getfield(L, 2, "args"); - if (!lua_isnil(L, -1)) { - luaL_checktype(L, -1, LUA_TTABLE); - cmdline = insert_args(L, -1, cmdline, len); - } - lua_pop(L, 1); - - lua_getfield(L, 2, "env"); - if (!lua_isnil(L, -1)) { - luaL_checktype(L, -1, LUA_TTABLE); - environment = insert_env(L, -1); - } - lua_pop(L, 1); - - get_redirect(L, "stdin", &si.hStdInput); - get_redirect(L, "stdout", &si.hStdOutput); - get_redirect(L, "stderr", &si.hStdError); - } - p = lua_newuserdata(L, sizeof *p); - luaL_getmetatable(L, PROCESS_HANDLE); - lua_setmetatable(L, -2); - p->status = -1; - if (!CreateProcess(0, cmdline, 0, 0, 0, 0, environment, 0, &si, &pi)) - return windows_error(L); - p->hProcess = pi.hProcess; - return 1; -} - -static int process_wait(lua_State *L) -{ - struct process *p = luaL_checkudata(L, 1, PROCESS_HANDLE); - if (p->status != -1) { - DWORD exitcode; - WaitForSingleObject(p->hProcess, INFINITE); - GetExitCodeProcess(p->hProcess, &exitcode); - p->status = exitcode; - } - lua_pushnumber(L, p->status); - return 1; -} - -static const luaL_reg process_lib[] = { - {"wait", process_wait}, - {0,0} -}; - - -static int osex_newpipe(lua_State *L) -{ - HANDLE ph[2]; - FILE **pf; - if (0 == CreatePipe(ph+0, ph+1, 0, 0)) - return windows_error(L); - luaL_getmetatable(L, LUA_FILEHANDLE); /* M */ - pf = lua_newuserdata(L, sizeof *pf); /* M in */ - lua_pushvalue(L, -2); /* M in M */ - lua_setmetatable(L, -2); /* M in */ - *pf = _fdopen(_open_osfhandle((long)ph[0], _O_RDONLY), "r"); - pf = lua_newuserdata(L, sizeof *pf); /* M in out */ - lua_pushvalue(L, -3); /* M in out M */ - lua_setmetatable(L, -2); /* M in out */ - *pf = _fdopen(_open_osfhandle((long)ph[1], _O_WRONLY), "w"); - return 2; -} - - -static const luaL_reg osex_lib[] = { - {"sleep", osex_sleep}, - {"spawn", osex_spawn}, - {"newpipe", osex_newpipe}, - {0,0} -}; - -int luaopen_osex(lua_State *L) -{ - luaL_newmetatable(L, PROCESS_HANDLE); - luaL_register(L, 0, process_lib); - luaL_register(L, "os", osex_lib); - return 1; -}