Skip to content
This repository was archived by the owner on Nov 20, 2020. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
LUA_PREFIX = /usr/local/
PREFIX = /usr/local/
LUA_PKGCONF ?= lua

MODULE = lpc
VERSION = 1.0.0

INSTALL_PREFIX = $(PREFIX)/lib/lua/5.1/
ifneq ($(shell pkg-config $(LUA_PKGCONF) || echo not-installed),)
$(error $(LUA_PKGCONF).pc not found)
endif

INSTALL_PREFIX = $(DESTDIR)$(shell pkg-config $(LUA_PKGCONF) --variable=INSTALL_CMOD)

CC = gcc
TARGET = lpc.so
OBJS = lpc.o
LIBS =
CFLAGS = -I $(LUA_PREFIX)/include -fPIC
LDFLAGS = -shared -fPIC
CFLAGS = $(shell pkg-config $(LUA_PKGCONF) --cflags) -fPIC
LDFLAGS = $(shell pkg-config $(LUA_PKGCONF) --libs) -shared -fPIC

default: $(TARGET)

Expand Down
178 changes: 112 additions & 66 deletions lpc.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
** LuaProcessCall
** Copyright DarkGod 2007
**
** lua 5.1/5.2 compat (c) 2014 Timo Teräs
*/

#include <errno.h>
Expand All @@ -15,47 +15,98 @@
#include "lauxlib.h"
#include "lualib.h"

#define topfile(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE))
#if LUA_VERSION_NUM < 502

static FILE *tofile (lua_State *L) {
FILE **f = topfile(L);
if (*f == NULL)
luaL_error(L, "attempt to use a closed file");
return *f;
static int lua_absindex(lua_State *L, int idx) {
return (idx > 0 || idx <= LUA_REGISTRYINDEX)? idx : lua_gettop(L) + idx + 1;
} /* lua_absindex() */

static void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup) {
int i, t = lua_absindex(L, -1 - nup);

for (; l->name; l++) {
for (i = 0; i < nup; i++)
lua_pushvalue(L, -nup);
lua_pushcclosure(L, l->func, nup);
lua_setfield(L, t, l->name);
}

lua_pop(L, nup);
} /* luaL_setfuncs() */

#define luaL_newlibtable(L, l) \
lua_createtable(L, 0, (sizeof (l) / sizeof *(l)) - 1)

#define luaL_newlib(L, l) \
(luaL_newlibtable((L), (l)), luaL_setfuncs((L), (l), 0))

#ifndef LUA_FILEHANDLE /* Not defined by earlier LuaJIT releases */
#define LUA_FILEHANDLE "FILE*"
#endif

/*
* Lua 5.1 userdata is a simple FILE *, while LuaJIT is a struct with the
* first member a FILE *, similar to Lua 5.2.
*/
typedef struct luaL_Stream {
FILE *f;
} luaL_Stream;

static int luaL_fileresult(lua_State *L, int stat, const char *filename) {
int en = errno; /* calls to Lua API may change this value */
if (stat) {
lua_pushboolean(L, 1);
return 1;
}
else {
lua_pushnil(L);
if (filename)
lua_pushfstring(L, "%s: %s", filename, strerror(en));
else
lua_pushfstring(L, "%s", strerror(en));
lua_pushinteger(L, en);
return 3;
}
}

static int pushresult (lua_State *L, int i, const char *filename) {
int en = errno; /* calls to Lua API may change this value */
if (i) {
lua_pushboolean(L, 1);
return 1;
}
else {
lua_pushnil(L);
if (filename)
lua_pushfstring(L, "%s: %s", filename, strerror(en));
else
lua_pushfstring(L, "%s", strerror(en));
lua_pushinteger(L, en);
return 3;
}
#define isclosed(p) ((p)->f == NULL)
#define markclosed(p) ((p)->f = NULL)

#else

#define isclosed(p) ((p)->closef == NULL)
#define markclosed(p) ((p)->closef = NULL)

#endif

#define tolstream(L) ((luaL_Stream *)luaL_checkudata(L, 1, LUA_FILEHANDLE))

static FILE *tofile (lua_State *L) {
luaL_Stream *p = tolstream(L);
if (isclosed(p))
luaL_error(L, "attempt to use a closed file");
return p->f;
}

static int io_fclose (lua_State *L) {
FILE **p = topfile(L);
int ok = (fclose(*p) == 0);
*p = NULL;
return pushresult(L, ok, NULL);
static int io_fclose (lua_State *L)
{
luaL_Stream *p = tolstream(L);
int res = fclose(p->f);
markclosed(p);
return luaL_fileresult(L, (res == 0), NULL);
}

static FILE **newfile_fd(lua_State *L, int fd, const char *mode)
static luaL_Stream *newfile_fd(lua_State *L, int fd, const char *mode)
{
FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *));
*pf = NULL; /* file handle is currently `closed' */
luaL_Stream *p = (luaL_Stream *) lua_newuserdata(L, sizeof(luaL_Stream));
markclosed(p);
luaL_getmetatable(L, LUA_FILEHANDLE);
lua_setmetatable(L, -2);
*pf = fdopen(fd, mode);
return pf;
p->f = fdopen(fd, mode);
#if LUA_VERSION_NUM >= 502
p->closef = &io_fclose;
#endif
return p;
}

static int lpc_run(lua_State *L)
Expand All @@ -64,12 +115,12 @@ static int lpc_run(lua_State *L)
int p_in[2];
int pid;

if (pipe(p_out) == -1) { lua_pushnil(L); return 1; }
if (pipe(p_in) == -1) { lua_pushnil(L); return 1; }
if (pipe(p_out) == -1) goto err_noclose;
if (pipe(p_in) == -1) goto err_closeout;
if ((pid = fork()) == -1) goto err_closeinout;

if ((pid = fork()) == -1) { lua_pushnil(L); return 1; }
else if (pid == 0)
{
if (pid == 0) {
/* child */
char **args;
int n = lua_gettop(L); /* number of arguments */
int i;
Expand All @@ -93,20 +144,24 @@ static int lpc_run(lua_State *L)
_exit(1);
return 0;
}
else
{
FILE **in;
FILE **out;

/* Cleanup */
close(p_out[0]);
close(p_in[1]);

lua_pushnumber(L, pid);
out = newfile_fd(L, p_out[1], "w");
in = newfile_fd(L, p_in[0], "r");
return 3;
}
/* Cleanup */
close(p_out[0]);
close(p_in[1]);
lua_pushnumber(L, pid);
newfile_fd(L, p_out[1], "w");
newfile_fd(L, p_in[0], "r");
return 3;

err_closeinout:
close(p_in[0]);
close(p_in[1]);
err_closeout:
close(p_out[0]);
close(p_out[1]);
err_noclose:
lua_pushnil(L);
return 1;
}

static int lpc_wait(lua_State *L)
Expand All @@ -116,13 +171,9 @@ static int lpc_wait(lua_State *L)
int nonblock = luaL_optinteger(L, 2, 0);

if (waitpid(pid, &ret, (nonblock == 1) ? WNOHANG : 0) == pid)
{
lua_pushnumber(L, ret);
}
else
{
lua_pushnil(L);
}
return 1;
}

Expand All @@ -141,13 +192,9 @@ static int f_readable(lua_State *L)
FD_SET(fileno(f), &rfds);
retval = select(1 + fileno(f), &rfds, NULL, NULL, &tv);
if (retval == 1)
{
lua_pushboolean(L, 1);
}
else
{
lua_pushnil(L);
}
return 1;
}

Expand All @@ -166,13 +213,9 @@ static int f_writable(lua_State *L)
FD_SET(fileno(f), &wfds);
retval = select(1 + fileno(f), NULL, &wfds, NULL, &tv);
if (retval == 1)
{
lua_pushboolean(L, 1);
}
else
{
lua_pushboolean(L, 0);
}
return 1;
}

Expand All @@ -192,7 +235,7 @@ static void set_info (lua_State *L)
lua_settable (L, -3);
}

static const struct luaL_reg lpclib[] =
static const struct luaL_Reg lpclib[] =
{
{"run", lpc_run},
{"wait", lpc_wait},
Expand All @@ -207,15 +250,15 @@ static const luaL_Reg io_add_flib[] = {

static void createmeta(lua_State *L)
{
luaL_getmetatable(L, LUA_FILEHANDLE); /* get IO's metatable for file handles */
luaL_register(L, NULL, io_add_flib); /* file methods */
luaL_getmetatable(L, LUA_FILEHANDLE); /* get IO's metatable for file handles */
luaL_setfuncs(L, io_add_flib, 0); /* file methods */
}


int luaopen_lpc (lua_State *L)
{
createmeta(L);

#if LUA_VERSION_NUM < 502
luaL_openlib(L, "lpc", lpclib, 0);

/* create environment for 'run' */
Expand All @@ -225,6 +268,9 @@ int luaopen_lpc (lua_State *L)
lua_setfield(L, -2, "__close");
lua_setfenv(L, -2);
lua_pop(L, 1); /* pop 'run' */
#else
luaL_newlib(L, lpclib);
#endif

set_info(L);
return 1;
Expand Down