| 1 | |
| 2 | |
| 3 | @@ -1,17 +1,24 @@
|
| 4 | -LUA_PREFIX = /usr/local/
|
| 5 | -PREFIX = /usr/local/
|
| 6 | +LUA_PKGCONF ?= lua
|
| 7 | +
|
| 8 | MODULE = lpc
|
| 9 | VERSION = 1.0.0
|
| 10 |
|
| 11 | -INSTALL_PREFIX = $(PREFIX)/lib/lua/5.1/
|
| 12 | +ifneq ($(shell pkg-config $(LUA_PKGCONF) || echo not-installed),)
|
| 13 | +$(error $(LUA_PKGCONF).pc not found)
|
| 14 | +endif
|
| 15 |
|
| 16 | +INSTALL_PREFIX = $(DESTDIR)$(shell pkg-config $(LUA_PKGCONF) --variable=INSTALL_CMOD)
|
| 17 | +
|
| 18 | CC = gcc
|
| 19 | TARGET = lpc.so
|
| 20 | OBJS = lpc.o
|
| 21 | LIBS =
|
| 22 | -CFLAGS = -I $(LUA_PREFIX)/include -fPIC
|
| 23 | +CFLAGS = -fPIC
|
| 24 | LDFLAGS = -shared -fPIC
|
| 25 |
|
| 26 | +LUA_CFLAGS = $(shell pkg-config $(LUA_PKGCONF) --cflags)
|
| 27 | +LUA_LDFLAGS = $(shell pkg-config $(LUA_PKGCONF) --libs)
|
| 28 | +
|
| 29 | default: $(TARGET)
|
| 30 |
|
| 31 |
|
| 32 | @@ -29,7 +36,7 @@
|
| 33 | rm -rf $(MODULE)-$(VERSION)
|
| 34 |
|
| 35 | $(TARGET): $(OBJS)
|
| 36 | - $(CC) $(LDFLAGS) -o $(TARGET) $(OBJS)
|
| 37 | + $(CC) $(LUA_LDFLAGS) $(LDFLAGS) -o $(TARGET) $(OBJS)
|
| 38 |
|
| 39 | .c.o:
|
| 40 | - $(CC) $(CFLAGS) -c $< -o $@
|
| 41 | + $(CC) $(LUA_CFLAGS) $(CFLAGS) -c $< -o $@
|
| 42 | |
| 43 | |
| 44 | @@ -1,7 +1,7 @@
|
| 45 | /*
|
| 46 | ** LuaProcessCall
|
| 47 | ** Copyright DarkGod 2007
|
| 48 | -**
|
| 49 | +** lua 5.1/5.2 compat (c) 2014 Timo Teräs
|
| 50 | */
|
| 51 |
|
| 52 | #include <errno.h>
|
| 53 | @@ -15,47 +15,98 @@
|
| 54 | #include "lauxlib.h"
|
| 55 | #include "lualib.h"
|
| 56 |
|
| 57 | -#define topfile(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE))
|
| 58 | +#if LUA_VERSION_NUM < 502
|
| 59 |
|
| 60 | -static FILE *tofile (lua_State *L) {
|
| 61 | - FILE **f = topfile(L);
|
| 62 | - if (*f == NULL)
|
| 63 | - luaL_error(L, "attempt to use a closed file");
|
| 64 | - return *f;
|
| 65 | +static int lua_absindex(lua_State *L, int idx) {
|
| 66 | + return (idx > 0 || idx <= LUA_REGISTRYINDEX)? idx : lua_gettop(L) + idx + 1;
|
| 67 | +} /* lua_absindex() */
|
| 68 | +
|
| 69 | +static void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup) {
|
| 70 | + int i, t = lua_absindex(L, -1 - nup);
|
| 71 | +
|
| 72 | + for (; l->name; l++) {
|
| 73 | + for (i = 0; i < nup; i++)
|
| 74 | + lua_pushvalue(L, -nup);
|
| 75 | + lua_pushcclosure(L, l->func, nup);
|
| 76 | + lua_setfield(L, t, l->name);
|
| 77 | + }
|
| 78 | +
|
| 79 | + lua_pop(L, nup);
|
| 80 | +} /* luaL_setfuncs() */
|
| 81 | +
|
| 82 | +#define luaL_newlibtable(L, l) \
|
| 83 | + lua_createtable(L, 0, (sizeof (l) / sizeof *(l)) - 1)
|
| 84 | +
|
| 85 | +#define luaL_newlib(L, l) \
|
| 86 | + (luaL_newlibtable((L), (l)), luaL_setfuncs((L), (l), 0))
|
| 87 | +
|
| 88 | +#ifndef LUA_FILEHANDLE /* Not defined by earlier LuaJIT releases */
|
| 89 | +#define LUA_FILEHANDLE "FILE*"
|
| 90 | +#endif
|
| 91 | +
|
| 92 | +/*
|
| 93 | + * Lua 5.1 userdata is a simple FILE *, while LuaJIT is a struct with the
|
| 94 | + * first member a FILE *, similar to Lua 5.2.
|
| 95 | + */
|
| 96 | +typedef struct luaL_Stream {
|
| 97 | + FILE *f;
|
| 98 | +} luaL_Stream;
|
| 99 | +
|
| 100 | +static int luaL_fileresult(lua_State *L, int stat, const char *filename) {
|
| 101 | + int en = errno; /* calls to Lua API may change this value */
|
| 102 | + if (stat) {
|
| 103 | + lua_pushboolean(L, 1);
|
| 104 | + return 1;
|
| 105 | + }
|
| 106 | + else {
|
| 107 | + lua_pushnil(L);
|
| 108 | + if (filename)
|
| 109 | + lua_pushfstring(L, "%s: %s", filename, strerror(en));
|
| 110 | + else
|
| 111 | + lua_pushfstring(L, "%s", strerror(en));
|
| 112 | + lua_pushinteger(L, en);
|
| 113 | + return 3;
|
| 114 | + }
|
| 115 | }
|
| 116 |
|
| 117 | -static int pushresult (lua_State *L, int i, const char *filename) {
|
| 118 | - int en = errno; /* calls to Lua API may change this value */
|
| 119 | - if (i) {
|
| 120 | - lua_pushboolean(L, 1);
|
| 121 | - return 1;
|
| 122 | - }
|
| 123 | - else {
|
| 124 | - lua_pushnil(L);
|
| 125 | - if (filename)
|
| 126 | - lua_pushfstring(L, "%s: %s", filename, strerror(en));
|
| 127 | - else
|
| 128 | - lua_pushfstring(L, "%s", strerror(en));
|
| 129 | - lua_pushinteger(L, en);
|
| 130 | - return 3;
|
| 131 | - }
|
| 132 | +#define isclosed(p) ((p)->f == NULL)
|
| 133 | +#define markclosed(p) ((p)->f = NULL)
|
| 134 | +
|
| 135 | +#else
|
| 136 | +
|
| 137 | +#define isclosed(p) ((p)->closef == NULL)
|
| 138 | +#define markclosed(p) ((p)->closef = NULL)
|
| 139 | +
|
| 140 | +#endif
|
| 141 | +
|
| 142 | +#define tolstream(L) ((luaL_Stream *)luaL_checkudata(L, 1, LUA_FILEHANDLE))
|
| 143 | +
|
| 144 | +static FILE *tofile (lua_State *L) {
|
| 145 | + luaL_Stream *p = tolstream(L);
|
| 146 | + if (isclosed(p))
|
| 147 | + luaL_error(L, "attempt to use a closed file");
|
| 148 | + return p->f;
|
| 149 | }
|
| 150 |
|
| 151 | -static int io_fclose (lua_State *L) {
|
| 152 | - FILE **p = topfile(L);
|
| 153 | - int ok = (fclose(*p) == 0);
|
| 154 | - *p = NULL;
|
| 155 | - return pushresult(L, ok, NULL);
|
| 156 | +static int io_fclose (lua_State *L)
|
| 157 | +{
|
| 158 | + luaL_Stream *p = tolstream(L);
|
| 159 | + int res = fclose(p->f);
|
| 160 | + markclosed(p);
|
| 161 | + return luaL_fileresult(L, (res == 0), NULL);
|
| 162 | }
|
| 163 |
|
| 164 | -static FILE **newfile_fd(lua_State *L, int fd, const char *mode)
|
| 165 | +static luaL_Stream *newfile_fd(lua_State *L, int fd, const char *mode)
|
| 166 | {
|
| 167 | - FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *));
|
| 168 | - *pf = NULL; /* file handle is currently `closed' */
|
| 169 | + luaL_Stream *p = (luaL_Stream *) lua_newuserdata(L, sizeof(luaL_Stream));
|
| 170 | + markclosed(p);
|
| 171 | luaL_getmetatable(L, LUA_FILEHANDLE);
|
| 172 | lua_setmetatable(L, -2);
|
| 173 | - *pf = fdopen(fd, mode);
|
| 174 | - return pf;
|
| 175 | + p->f = fdopen(fd, mode);
|
| 176 | +#if LUA_VERSION_NUM >= 502
|
| 177 | + p->closef = &io_fclose;
|
| 178 | +#endif
|
| 179 | + return p;
|
| 180 | }
|
| 181 |
|
| 182 | static int lpc_run(lua_State *L)
|
| 183 | @@ -64,12 +115,12 @@
|
| 184 | int p_in[2];
|
| 185 | int pid;
|
| 186 |
|
| 187 | - if (pipe(p_out) == -1) { lua_pushnil(L); return 1; }
|
| 188 | - if (pipe(p_in) == -1) { lua_pushnil(L); return 1; }
|
| 189 | + if (pipe(p_out) == -1) goto err_noclose;
|
| 190 | + if (pipe(p_in) == -1) goto err_closeout;
|
| 191 | + if ((pid = fork()) == -1) goto err_closeinout;
|
| 192 |
|
| 193 | - if ((pid = fork()) == -1) { lua_pushnil(L); return 1; }
|
| 194 | - else if (pid == 0)
|
| 195 | - {
|
| 196 | + if (pid == 0) {
|
| 197 | + /* child */
|
| 198 | char **args;
|
| 199 | int n = lua_gettop(L); /* number of arguments */
|
| 200 | int i;
|
| 201 | @@ -93,20 +144,24 @@
|
| 202 | _exit(1);
|
| 203 | return 0;
|
| 204 | }
|
| 205 | - else
|
| 206 | - {
|
| 207 | - FILE **in;
|
| 208 | - FILE **out;
|
| 209 |
|
| 210 | - /* Cleanup */
|
| 211 | - close(p_out[0]);
|
| 212 | - close(p_in[1]);
|
| 213 | + /* Cleanup */
|
| 214 | + close(p_out[0]);
|
| 215 | + close(p_in[1]);
|
| 216 | + lua_pushnumber(L, pid);
|
| 217 | + newfile_fd(L, p_out[1], "w");
|
| 218 | + newfile_fd(L, p_in[0], "r");
|
| 219 | + return 3;
|
| 220 |
|
| 221 | - lua_pushnumber(L, pid);
|
| 222 | - out = newfile_fd(L, p_out[1], "w");
|
| 223 | - in = newfile_fd(L, p_in[0], "r");
|
| 224 | - return 3;
|
| 225 | - }
|
| 226 | +err_closeinout:
|
| 227 | + close(p_in[0]);
|
| 228 | + close(p_in[1]);
|
| 229 | +err_closeout:
|
| 230 | + close(p_out[0]);
|
| 231 | + close(p_out[1]);
|
| 232 | +err_noclose:
|
| 233 | + lua_pushnil(L);
|
| 234 | + return 1;
|
| 235 | }
|
| 236 |
|
| 237 | static int lpc_wait(lua_State *L)
|
| 238 | @@ -116,13 +171,9 @@
|
| 239 | int nonblock = luaL_optinteger(L, 2, 0);
|
| 240 |
|
| 241 | if (waitpid(pid, &ret, (nonblock == 1) ? WNOHANG : 0) == pid)
|
| 242 | - {
|
| 243 | lua_pushnumber(L, ret);
|
| 244 | - }
|
| 245 | else
|
| 246 | - {
|
| 247 | lua_pushnil(L);
|
| 248 | - }
|
| 249 | return 1;
|
| 250 | }
|
| 251 |
|
| 252 | @@ -141,13 +192,9 @@
|
| 253 | FD_SET(fileno(f), &rfds);
|
| 254 | retval = select(1 + fileno(f), &rfds, NULL, NULL, &tv);
|
| 255 | if (retval == 1)
|
| 256 | - {
|
| 257 | lua_pushboolean(L, 1);
|
| 258 | - }
|
| 259 | else
|
| 260 | - {
|
| 261 | lua_pushnil(L);
|
| 262 | - }
|
| 263 | return 1;
|
| 264 | }
|
| 265 |
|
| 266 | @@ -166,13 +213,9 @@
|
| 267 | FD_SET(fileno(f), &wfds);
|
| 268 | retval = select(1 + fileno(f), NULL, &wfds, NULL, &tv);
|
| 269 | if (retval == 1)
|
| 270 | - {
|
| 271 | lua_pushboolean(L, 1);
|
| 272 | - }
|
| 273 | else
|
| 274 | - {
|
| 275 | lua_pushboolean(L, 0);
|
| 276 | - }
|
| 277 | return 1;
|
| 278 | }
|
| 279 |
|
| 280 | @@ -192,7 +235,7 @@
|
| 281 | lua_settable (L, -3);
|
| 282 | }
|
| 283 |
|
| 284 | -static const struct luaL_reg lpclib[] =
|
| 285 | +static const struct luaL_Reg lpclib[] =
|
| 286 | {
|
| 287 | {"run", lpc_run},
|
| 288 | {"wait", lpc_wait},
|
| 289 | @@ -207,15 +250,15 @@
|
| 290 |
|
| 291 | static void createmeta(lua_State *L)
|
| 292 | {
|
| 293 | - luaL_getmetatable(L, LUA_FILEHANDLE); /* get IO's metatable for file handles */
|
| 294 | - luaL_register(L, NULL, io_add_flib); /* file methods */
|
| 295 | + luaL_getmetatable(L, LUA_FILEHANDLE); /* get IO's metatable for file handles */
|
| 296 | + luaL_setfuncs(L, io_add_flib, 0); /* file methods */
|
| 297 | }
|
| 298 |
|
| 299 | -
|
| 300 | int luaopen_lpc (lua_State *L)
|
| 301 | {
|
| 302 | createmeta(L);
|
| 303 |
|
| 304 | +#if LUA_VERSION_NUM < 502
|
| 305 | luaL_openlib(L, "lpc", lpclib, 0);
|
| 306 |
|
| 307 | /* create environment for 'run' */
|
| 308 | @@ -225,6 +268,9 @@
|
| 309 | lua_setfield(L, -2, "__close");
|
| 310 | lua_setfenv(L, -2);
|
| 311 | lua_pop(L, 1); /* pop 'run' */
|
| 312 | +#else
|
| 313 | + luaL_newlib(L, lpclib);
|
| 314 | +#endif
|
| 315 |
|
| 316 | set_info(L);
|
| 317 | return 1;
|