summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Ipsum <richard.ipsum@codethink.co.uk>2013-10-04 17:49:14 +0000
committerRichard Ipsum <richard.ipsum@codethink.co.uk>2013-10-04 17:49:14 +0000
commitbe9d125080b9ff2376273e21b75669b65dc88d46 (patch)
tree73f8a70842b655fb50a190015600e874b4f43e23
parent1640e840e704d97e69edc1c3ddff2ebe4f5326ce (diff)
parent3f5ac6036aab342dcfe3719d8c6740b01179a94d (diff)
downloadluxio-be9d125080b9ff2376273e21b75669b65dc88d46.tar.gz
Merge remote-tracking branch 'remotes/origin/trunk' into richardipsumbaserock/morph
Conflicts: Makefile
-rw-r--r--.bzrignore2
-rw-r--r--LICENCE21
-rw-r--r--Makefile105
-rw-r--r--README2
-rw-r--r--config.h14
-rwxr-xr-xexamples/mq-read.lua22
-rwxr-xr-xexamples/mq-write.lua14
-rwxr-xr-xexamples/simple-socket.lua24
-rwxr-xr-xexamples/subprocess.lua20
-rw-r--r--lua-5.1.c416
-rw-r--r--lua-5.2.c522
-rw-r--r--luxio.c456
-rw-r--r--luxio/mq.lua6
-rw-r--r--luxio_constants.h.in38
-rw-r--r--tests/test-mqueue-read.lua29
-rw-r--r--tests/test-mqueue-write.lua15
-rw-r--r--tests/test-syslog.lua32
17 files changed, 1549 insertions, 189 deletions
diff --git a/.bzrignore b/.bzrignore
index ee29aa9..f010c02 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -1 +1,3 @@
luxio_constants.h
+luxio-5.1
+luxio-5.2
diff --git a/LICENCE b/LICENCE
new file mode 100644
index 0000000..993bb1e
--- /dev/null
+++ b/LICENCE
@@ -0,0 +1,21 @@
+Copyright 2012, 2013 Rob Kendrick <rjek+luxio@rjek.com>
+Copyright 2012 Daniel Silverstone <dsilvers@digital-scurf.org>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/Makefile b/Makefile
index 71e4ae8..2fa7ca4 100644
--- a/Makefile
+++ b/Makefile
@@ -2,12 +2,59 @@ all: lua-5.1-try lua-5.2-try
install: lua-5.1-try-install lua-5.2-try-install
+ifeq ($(strip $(shell which pkg-config > /dev/null || echo NONE)),NONE)
+ $(error This makefile requires pkg-config)
+endif
+
+ifeq ($(strip $(shell which $(CC) > /dev/null || echo NONE)),NONE)
+ $(info Luxio: Hmm, CC make variable contains nonsense. Overriding to gcc.)
+ CC := gcc
+endif
+
+# This isn't nice. Find a nice way.
+HOST_OS := $(shell uname -s)
+
+ifeq ($(HOST_OS),Linux)
+ EXTRA_LIBS := -lrt
+else
+ EXTRA_LIBS :=
+endif
+
+NAKED_LUA_VER := $(shell (pkg-config --exists lua && \
+ pkg-config --modversion lua || \
+ pkg-config --variable V lua) | cut -d. -f1-2)
+
+# fine appropriate Lua interpreter
+LUA_REPL := $(shell (which lua5.1 > /dev/null 2>&1 && echo lua5.1) || \
+ (which lua-5.1 > /dev/null 2>&1 && echo lua-5.1) || \
+ (which lua51 > /dev/null 2>&1 && echo lua51) || \
+ (lua -e"print(_VERSION)" | grep -q 5.1 && echo lua) || \
+ (which lua-5.2 > /dev/null 2>&1 && echo lua-5.2) || \
+ (which lua52 > /dev/null 2>&1 && echo lua52))
+
# find appropriate Lua libraries
LUA51_PKG := $(shell (pkg-config --exists lua5.1 && echo lua5.1) || \
- (pkg-config --exists lua-5.1 && echo lua-5.1))
-ifneq ($(LUA51_PKG),)
+ (pkg-config --exists lua-5.1 && echo lua-5.1) || \
+ (pkg-config --exists lua51 && echo lua51) || \
+ (echo "NONE"))
+
+
+LUA51_PKG := $(strip $(LUA51_PKG))
+
+ifeq ($(LUA51_PKG),NONE)
+ ifeq ($(NAKED_LUA_VER),5.1)
+ LUA51_PKG := lua
+ endif
+endif
+
+ifneq ($(LUA51_PKG),NONE)
+ $(info Luxio: Lua 5.1 package name on this system is $(LUA51_PKG))
+ LUA51_HAS_MODINST := $(shell test x`pkg-config --variable INSTALL_LMOD $(LUA51_PKG)` != x && echo YES)
LUA51_INC := $(shell pkg-config --cflags $(LUA51_PKG))
LUA51_LIB := $(shell pkg-config --libs $(LUA51_PKG))
+ ifeq ($(LUA51_HAS_MODINST),)
+ LOCAL := YES
+ endif
ifeq ($(LOCAL),)
LUA51_LMOD_INST := $(shell pkg-config --variable=INSTALL_LMOD $(LUA51_PKG))
LUA51_CMOD_INST := $(shell pkg-config --variable=INSTALL_CMOD $(LUA51_PKG))
@@ -19,16 +66,32 @@ ifneq ($(LUA51_PKG),)
lua-5.1-try-install: lua-5.1-install
else
lua-5.1-try:
- @echo Lua 5.1 could not be found, so luxio was not built for it.
+ @echo Luxio: Lua 5.1 could not be found, so luxio was not built for it.
lua-5.1-try-install:
- @echo Lua 5.1 could not be found, so luxio was not installed for it.
+ @echo Luxio: Lua 5.1 could not be found, so luxio was not installed for it.
endif
LUA52_PKG := $(shell (pkg-config --exists lua5.2 && echo lua5.2) || \
- (pkg-config --exists lua-5.2 && echo lua-5.2))
-ifneq ($(LUA52_PKG),)
+ (pkg-config --exists lua-5.2 && echo lua-5.2) || \
+ (pkg-config --exists lua52 && echo lua52) || \
+ (echo "NONE"))
+
+LUA52_PKG := $(strip $(LUA52_PKG))
+
+ifeq ($(LUA52_PKG),NONE)
+ ifeq ($(NAKED_LUA_VER),5.2)
+ LUA52_PKG := lua
+ endif
+endif
+
+ifneq ($(LUA52_PKG),NONE)
+ $(info Luxio: Lua 5.2 package name on this system is $(LUA52_PKG))
+ LUA52_HAS_MODINST := $(shell test x`pkg-config --variable INSTALL_LMOD $(LUA52_PKG)` != x && echo YES)
LUA52_INC := $(shell pkg-config --cflags $(LUA52_PKG))
LUA52_LIB := $(shell pkg-config --libs $(LUA52_PKG))
+ ifeq ($(LUA52_HAS_MODINST),)
+ LOCAL := YES
+ endif
ifeq ($(LOCAL),)
LUA52_LMOD_INST := $(shell pkg-config --variable=INSTALL_LMOD $(LUA52_PKG))
LUA52_CMOD_INST := $(shell pkg-config --variable=INSTALL_CMOD $(LUA52_PKG))
@@ -40,14 +103,13 @@ ifneq ($(LUA52_PKG),)
lua-5.2-try-install: lua-5.2-install
else
lua-5.2-try:
- @echo Lua 5.2 could not be found, so luxio was not built for it.
+ @echo Luxio: Lua 5.2 could not be found, so luxio was not built for it.
lua-5.2-try-install:
- @echo Lua 5.2 could not be found, so luxio was not installed for it.
+ @echo Luxio: Lua 5.2 could not be found, so luxio was not installed for it.
endif
CFLAGS ?= -O2 -Wall
-CC ?= gcc
INSTALL := /usr/bin/install
LUALIBS := $(patsubst %,luxio/%.lua, \
@@ -55,12 +117,12 @@ LUALIBS := $(patsubst %,luxio/%.lua, \
clean:
- $(RM) *.so *.o luxio_constants.h
+ $(RM) *.so *.o luxio_constants.h luxio-5.1 luxio-5.2
luxio_constants.h: luxio_constants.h.in const-proc.lua
- lua5.1 ./const-proc.lua < $^ > $@
+ $(LUA_REPL) ./const-proc.lua < $^ > $@
-lua-5.1: luxio-5.1.so
+lua-5.1: luxio-5.1.so luxio-5.1
ln -s -f luxio-5.1.so luxio.so
lua-5.1-install: lua-5.1
@@ -68,11 +130,16 @@ lua-5.1-install: lua-5.1
$(INSTALL) -m 755 luxio-5.1.so $(DESTDIR)$(LUA51_CMOD_INST)/luxio.so
$(INSTALL) -d $(DESTDIR)$(LUA51_LMOD_INST)/luxio
$(INSTALL) -m 644 $(LUALIBS) $(DESTDIR)$(LUA51_LMOD_INST)/luxio/
+ $(INSTALL) -d $(DESTDIR)$(PREFIX)/bin
+ $(INSTALL) luxio-5.1 $(DESTDIR)$(PREFIX)/bin/luxio-5.1
luxio-5.1.so: luxio-5.1.o
- $(CC) $(LDFLAGS) -shared -Wl,--no-as-needed -o luxio-5.1.so $(LUA51_LIB) -lrt $^
+ $(CC) $(LDFLAGS) -shared -o luxio-5.1.so $^ $(LUA51_LIB) $(EXTRA_LIBS)
+
+luxio-5.1: lua-5.1.c luxio-5.1.o
+ $(CC) -o luxio-5.1 $(CFLAGS) $(LUA51_INC) $(LDFLAGS) lua-5.1.c luxio-5.1.o $(LUA51_LIB) $(EXTRA_LIBS)
-lua-5.2: luxio-5.2.so
+lua-5.2: luxio-5.2.so luxio-5.2
ln -s -f luxio-5.2.so luxio.so
lua-5.2-install: lua-5.2
@@ -80,10 +147,16 @@ lua-5.2-install: lua-5.2
$(INSTALL) -m 755 luxio-5.2.so $(DESTDIR)$(LUA52_CMOD_INST)/luxio.so
$(INSTALL) -d $(DESTDIR)$(LUA52_LMOD_INST)/luxio
$(INSTALL) -m 644 $(LUALIBS) $(DESTDIR)$(LUA52_LMOD_INST)/luxio/
-
+ $(INSTALL) -d $(DESTDIR)$(PREFIX)/bin
+ $(INSTALL) luxio-5.2 $(DESTDIR)$(PREFIX)/bin/luxio-5.2
luxio-5.2.so: luxio-5.2.o
- $(CC) $(LDFLAGS) -shared -Wl,--no-as-needed -o luxio-5.2.so $(LUA52_LIB) -lrt $^
+ $(CC) $(LDFLAGS) -shared -o luxio-5.2.so $^ $(LUA52_LIB) $(EXTRA_LIBS)
+
+luxio-5.2: lua-5.2.c luxio-5.2.o
+ $(CC) -o luxio-5.2 $(CFLAGS) $(LDFLAGS) $(LUA52_INC) lua-5.2.c luxio-5.2.o $(LUA52_LIB) $(EXTRA_LIBS)
+
+###
luxio-5.1.o: luxio.c luxio_constants.h
$(CC) $(CFLAGS) -fPIC $(LUA51_INC) -c $< -o $@
diff --git a/README b/README
index e4455bc..b496d17 100644
--- a/README
+++ b/README
@@ -18,7 +18,7 @@ Now:
6. Sub-process handling library (read/write io.popen with job control).
7. A prototype POSIX Message Queue-based IPC scheme that can serialise
most simple Lua values. (No closures, userdata, etc)
- 8. Liberal licence. (Same as Lua's.)
+ 8. Liberal licence. (Same as Lua's. See the file LICENCE.)
Future:
0. Well-documented.
diff --git a/config.h b/config.h
index 91e5a83..68930dd 100644
--- a/config.h
+++ b/config.h
@@ -11,11 +11,25 @@
# define HAVE_SENDFILE 1
# define HAVE_SPLICE 1
# define HAVE_D_TYPE 1
+# define HAVE_FDATASYNC 1
# define _GNU_SOURCE
# define _LARGEFILE64_SOURCE
# define _POSIX_SOURCE
# define _POSIX_C_SOURCE 1
#endif
+#ifndef _POSIX_PTHREAD_SEMANTICS
+ /* Solaris horror */
+# define _POSIX_PTHREAD_SEMANTICS 1
+#endif
+
+#ifndef LOGIN_NAME_MAX
+# define LOGIN_NAME_MAX 9
+#endif
+
+#ifndef IFNAMSIZ
+/* MINIX does not have this */
+# define IFNAMSIZ 128
+#endif
#endif /* LUXIO_CONFIG_H */
diff --git a/examples/mq-read.lua b/examples/mq-read.lua
new file mode 100755
index 0000000..3b3703b
--- /dev/null
+++ b/examples/mq-read.lua
@@ -0,0 +1,22 @@
+#!/usr/bin/lua
+
+local sio = require "luxio.simple"
+local mq = require "luxio.mq"
+
+h = mq.open("/luxio-mq", "r", sio.tomode "0777")
+
+print(h)
+
+while true do
+ local msg = assert(h:pull())
+ for k, v in pairs(msg) do
+ print(k, v)
+ end
+
+ if msg.die then
+ h:close()
+ mq.unlink "/luxio-mq"
+ os.exit()
+ end
+end
+
diff --git a/examples/mq-write.lua b/examples/mq-write.lua
new file mode 100755
index 0000000..0a243fd
--- /dev/null
+++ b/examples/mq-write.lua
@@ -0,0 +1,14 @@
+#!/usr/bin/lua
+
+local sio = require "luxio.simple"
+local mq = require "luxio.mq"
+
+h = mq.open("/luxio-mq", "w", sio.tomode "0777")
+
+print(h)
+
+h:push { cat = "meow", dog = "woof", horse = "neigh", webmonkey = "AJAX!" }
+h:push { die = true }
+
+h:close()
+
diff --git a/examples/simple-socket.lua b/examples/simple-socket.lua
new file mode 100755
index 0000000..0885c55
--- /dev/null
+++ b/examples/simple-socket.lua
@@ -0,0 +1,24 @@
+#!../luxio-5.1
+
+package.path = package.path .. ":../?.lua"
+package.cpath = package.cpath .. ":../?.so"
+
+sio = require "luxio.simple"
+
+mysock = assert(sio.connect("www.rjek.com", "http"))
+print("mysock: " .. tostring(mysock))
+
+print "Sending request..."
+assert(mysock:writev("GET / HTTP/1.1\r\n",
+ "Host: www.rjek.com\r\n",
+ "Connection: close\r\n",
+ "\r\n"))
+
+print "Reading reply..."
+
+print(assert(mysock:read "*a"))
+
+print "Closing socket..."
+
+assert(mysock:close())
+
diff --git a/examples/subprocess.lua b/examples/subprocess.lua
new file mode 100755
index 0000000..24cc11a
--- /dev/null
+++ b/examples/subprocess.lua
@@ -0,0 +1,20 @@
+#!../luxio-5.1
+
+package.path = package.path .. ":../?.lua"
+package.cpath = package.cpath .. ":../?.so"
+
+sio = require "luxio.simple"
+sp = require "luxio.subprocess"
+
+mytr = sp.spawn_simple {
+ "tr", "[a-z]", "[A-Z]",
+ stdin = sp.PIPE,
+ stdout = sp.PIPE,
+}
+
+mytr.stdin:write "Hello, world!\n"
+mytr.stdin:close()
+
+print(mytr.stdout:read "*a")
+
+print(mytr:wait())
diff --git a/lua-5.1.c b/lua-5.1.c
new file mode 100644
index 0000000..dad0bdc
--- /dev/null
+++ b/lua-5.1.c
@@ -0,0 +1,416 @@
+/*
+** $Id: lua.c,v 1.160.1.2 2007/12/28 15:32:23 roberto Exp $
+** Lua stand-alone interpreter
+** See Copyright Notice in lua.h
+*/
+
+/* Copyright notice from Lua 5.1's lua.h:
+ * Copyright (C) 1994-2012 Lua.org, PUC-Rio. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define lua_c
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+extern int luaopen_luxio(lua_State *L);
+
+static lua_State *globalL = NULL;
+
+static const char *progname = LUA_PROGNAME;
+
+
+
+static void lstop (lua_State *L, lua_Debug *ar) {
+ (void)ar; /* unused arg. */
+ lua_sethook(L, NULL, 0, 0);
+ luaL_error(L, "interrupted!");
+}
+
+
+static void laction (int i) {
+ signal(i, SIG_DFL); /* if another SIGINT happens before lstop,
+ terminate process (default action) */
+ lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
+}
+
+
+static void print_usage (void) {
+ fprintf(stderr,
+ "usage: %s [options] [script [args]].\n"
+ "Available options are:\n"
+ " -e stat execute string " LUA_QL("stat") "\n"
+ " -l name require library " LUA_QL("name") "\n"
+ " -i enter interactive mode after executing " LUA_QL("script") "\n"
+ " -v show version information\n"
+ " -- stop handling options\n"
+ " - execute stdin and stop handling options\n"
+ ,
+ progname);
+ fflush(stderr);
+}
+
+
+static void l_message (const char *pname, const char *msg) {
+ if (pname) fprintf(stderr, "%s: ", pname);
+ fprintf(stderr, "%s\n", msg);
+ fflush(stderr);
+}
+
+
+static int report (lua_State *L, int status) {
+ if (status && !lua_isnil(L, -1)) {
+ const char *msg = lua_tostring(L, -1);
+ if (msg == NULL) msg = "(error object is not a string)";
+ l_message(progname, msg);
+ lua_pop(L, 1);
+ }
+ return status;
+}
+
+
+static int traceback (lua_State *L) {
+ if (!lua_isstring(L, 1)) /* 'message' not a string? */
+ return 1; /* keep it intact */
+ lua_getfield(L, LUA_GLOBALSINDEX, "debug");
+ if (!lua_istable(L, -1)) {
+ lua_pop(L, 1);
+ return 1;
+ }
+ lua_getfield(L, -1, "traceback");
+ if (!lua_isfunction(L, -1)) {
+ lua_pop(L, 2);
+ return 1;
+ }
+ lua_pushvalue(L, 1); /* pass error message */
+ lua_pushinteger(L, 2); /* skip this function and traceback */
+ lua_call(L, 2, 1); /* call debug.traceback */
+ return 1;
+}
+
+
+static int docall (lua_State *L, int narg, int clear) {
+ int status;
+ int base = lua_gettop(L) - narg; /* function index */
+ lua_pushcfunction(L, traceback); /* push traceback function */
+ lua_insert(L, base); /* put it under chunk and args */
+ signal(SIGINT, laction);
+ status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base);
+ signal(SIGINT, SIG_DFL);
+ lua_remove(L, base); /* remove traceback function */
+ /* force a complete garbage collection in case of errors */
+ if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0);
+ return status;
+}
+
+
+static void print_version (void) {
+ l_message(NULL, LUA_RELEASE " " LUA_COPYRIGHT);
+ l_message(NULL, "Built with Luxio, Copyright 2012 Rob Kendrick <rjek+luxio@rjek.com>, Daniel Silverstone <dsilvers@digital-scurf.org>");
+}
+
+
+static int getargs (lua_State *L, char **argv, int n) {
+ int narg;
+ int i;
+ int argc = 0;
+ while (argv[argc]) argc++; /* count total number of arguments */
+ narg = argc - (n + 1); /* number of arguments to the script */
+ luaL_checkstack(L, narg + 3, "too many arguments to script");
+ for (i=n+1; i < argc; i++)
+ lua_pushstring(L, argv[i]);
+ lua_createtable(L, narg, n + 1);
+ for (i=0; i < argc; i++) {
+ lua_pushstring(L, argv[i]);
+ lua_rawseti(L, -2, i - n);
+ }
+ return narg;
+}
+
+
+static int dofile (lua_State *L, const char *name) {
+ int status = luaL_loadfile(L, name) || docall(L, 0, 1);
+ return report(L, status);
+}
+
+
+static int dostring (lua_State *L, const char *s, const char *name) {
+ int status = luaL_loadbuffer(L, s, strlen(s), name) || docall(L, 0, 1);
+ return report(L, status);
+}
+
+
+static int dolibrary (lua_State *L, const char *name) {
+ lua_getglobal(L, "require");
+ lua_pushstring(L, name);
+ return report(L, docall(L, 1, 1));
+}
+
+
+static const char *get_prompt (lua_State *L, int firstline) {
+ const char *p;
+ lua_getfield(L, LUA_GLOBALSINDEX, firstline ? "_PROMPT" : "_PROMPT2");
+ p = lua_tostring(L, -1);
+ if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2);
+ lua_pop(L, 1); /* remove global */
+ return p;
+}
+
+
+static int incomplete (lua_State *L, int status) {
+ if (status == LUA_ERRSYNTAX) {
+ size_t lmsg;
+ const char *msg = lua_tolstring(L, -1, &lmsg);
+ const char *tp = msg + lmsg - (sizeof(LUA_QL("<eof>")) - 1);
+ if (strstr(msg, LUA_QL("<eof>")) == tp) {
+ lua_pop(L, 1);
+ return 1;
+ }
+ }
+ return 0; /* else... */
+}
+
+
+static int pushline (lua_State *L, int firstline) {
+ char buffer[LUA_MAXINPUT];
+ char *b = buffer;
+ size_t l;
+ const char *prmt = get_prompt(L, firstline);
+ if (lua_readline(L, b, prmt) == 0)
+ return 0; /* no input */
+ l = strlen(b);
+ if (l > 0 && b[l-1] == '\n') /* line ends with newline? */
+ b[l-1] = '\0'; /* remove it */
+ if (firstline && b[0] == '=') /* first line starts with `=' ? */
+ lua_pushfstring(L, "return %s", b+1); /* change it to `return' */
+ else
+ lua_pushstring(L, b);
+ lua_freeline(L, b);
+ return 1;
+}
+
+
+static int loadline (lua_State *L) {
+ int status;
+ lua_settop(L, 0);
+ if (!pushline(L, 1))
+ return -1; /* no input */
+ for (;;) { /* repeat until gets a complete line */
+ status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin");
+ if (!incomplete(L, status)) break; /* cannot try to add lines? */
+ if (!pushline(L, 0)) /* no more input? */
+ return -1;
+ lua_pushliteral(L, "\n"); /* add a new line... */
+ lua_insert(L, -2); /* ...between the two lines */
+ lua_concat(L, 3); /* join them */
+ }
+ lua_saveline(L, 1);
+ lua_remove(L, 1); /* remove line */
+ return status;
+}
+
+
+static void dotty (lua_State *L) {
+ int status;
+ const char *oldprogname = progname;
+ progname = NULL;
+ while ((status = loadline(L)) != -1) {
+ if (status == 0) status = docall(L, 0, 0);
+ report(L, status);
+ if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */
+ lua_getglobal(L, "print");
+ lua_insert(L, 1);
+ if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0)
+ l_message(progname, lua_pushfstring(L,
+ "error calling " LUA_QL("print") " (%s)",
+ lua_tostring(L, -1)));
+ }
+ }
+ lua_settop(L, 0); /* clear stack */
+ fputs("\n", stdout);
+ fflush(stdout);
+ progname = oldprogname;
+}
+
+
+static int handle_script (lua_State *L, char **argv, int n) {
+ int status;
+ const char *fname;
+ int narg = getargs(L, argv, n); /* collect arguments */
+ lua_setglobal(L, "arg");
+ fname = argv[n];
+ if (strcmp(fname, "-") == 0 && strcmp(argv[n-1], "--") != 0)
+ fname = NULL; /* stdin */
+ status = luaL_loadfile(L, fname);
+ lua_insert(L, -(narg+1));
+ if (status == 0)
+ status = docall(L, narg, 0);
+ else
+ lua_pop(L, narg);
+ return report(L, status);
+}
+
+
+/* check that argument has no extra characters at the end */
+#define notail(x) {if ((x)[2] != '\0') return -1;}
+
+
+static int collectargs (char **argv, int *pi, int *pv, int *pe) {
+ int i;
+ for (i = 1; argv[i] != NULL; i++) {
+ if (argv[i][0] != '-') /* not an option? */
+ return i;
+ switch (argv[i][1]) { /* option */
+ case '-':
+ notail(argv[i]);
+ return (argv[i+1] != NULL ? i+1 : 0);
+ case '\0':
+ return i;
+ case 'i':
+ notail(argv[i]);
+ *pi = 1; /* go through */
+ case 'v':
+ notail(argv[i]);
+ *pv = 1;
+ break;
+ case 'e':
+ *pe = 1; /* go through */
+ case 'l':
+ if (argv[i][2] == '\0') {
+ i++;
+ if (argv[i] == NULL) return -1;
+ }
+ break;
+ default: return -1; /* invalid option */
+ }
+ }
+ return 0;
+}
+
+
+static int runargs (lua_State *L, char **argv, int n) {
+ int i;
+ for (i = 1; i < n; i++) {
+ if (argv[i] == NULL) continue;
+ lua_assert(argv[i][0] == '-');
+ switch (argv[i][1]) { /* option */
+ case 'e': {
+ const char *chunk = argv[i] + 2;
+ if (*chunk == '\0') chunk = argv[++i];
+ lua_assert(chunk != NULL);
+ if (dostring(L, chunk, "=(command line)") != 0)
+ return 1;
+ break;
+ }
+ case 'l': {
+ const char *filename = argv[i] + 2;
+ if (*filename == '\0') filename = argv[++i];
+ lua_assert(filename != NULL);
+ if (dolibrary(L, filename))
+ return 1; /* stop if file fails */
+ break;
+ }
+ default: break;
+ }
+ }
+ return 0;
+}
+
+
+static int handle_luainit (lua_State *L) {
+ const char *init = getenv(LUA_INIT);
+ if (init == NULL) return 0; /* status OK */
+ else if (init[0] == '@')
+ return dofile(L, init+1);
+ else
+ return dostring(L, init, "=" LUA_INIT);
+}
+
+
+struct Smain {
+ int argc;
+ char **argv;
+ int status;
+};
+
+
+static int pmain (lua_State *L) {
+ struct Smain *s = (struct Smain *)lua_touserdata(L, 1);
+ char **argv = s->argv;
+ int script;
+ int has_i = 0, has_v = 0, has_e = 0;
+ globalL = L;
+ if (argv[0] && argv[0][0]) progname = argv[0];
+ lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */
+ luaL_openlibs(L); /* open libraries */
+ luaopen_luxio(L); /* open luxio */
+ lua_gc(L, LUA_GCRESTART, 0);
+ s->status = handle_luainit(L);
+ if (s->status != 0) return 0;
+ script = collectargs(argv, &has_i, &has_v, &has_e);
+ if (script < 0) { /* invalid args? */
+ print_usage();
+ s->status = 1;
+ return 0;
+ }
+ if (has_v) print_version();
+ s->status = runargs(L, argv, (script > 0) ? script : s->argc);
+ if (s->status != 0) return 0;
+ if (script)
+ s->status = handle_script(L, argv, script);
+ if (s->status != 0) return 0;
+ if (has_i)
+ dotty(L);
+ else if (script == 0 && !has_e && !has_v) {
+ if (lua_stdin_is_tty()) {
+ print_version();
+ dotty(L);
+ }
+ else dofile(L, NULL); /* executes stdin as a file */
+ }
+ return 0;
+}
+
+
+int main (int argc, char **argv) {
+ int status;
+ struct Smain s;
+ lua_State *L = lua_open(); /* create state */
+ if (L == NULL) {
+ l_message(argv[0], "cannot create state: not enough memory");
+ return EXIT_FAILURE;
+ }
+ s.argc = argc;
+ s.argv = argv;
+ status = lua_cpcall(L, &pmain, &s);
+ report(L, status);
+ lua_close(L);
+ return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+
diff --git a/lua-5.2.c b/lua-5.2.c
new file mode 100644
index 0000000..502bd78
--- /dev/null
+++ b/lua-5.2.c
@@ -0,0 +1,522 @@
+/*
+** $Id: lua.c,v 1.205 2012/05/23 15:37:09 roberto Exp $
+** Lua stand-alone interpreter
+** See Copyright Notice in lua.h
+*/
+
+/* Copyright notice from Lua 5.2's lua.h:
+ * Copyright (C) 1994-2012 Lua.org, PUC-Rio.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define lua_c
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+#if !defined(LUA_PROMPT)
+#define LUA_PROMPT "> "
+#define LUA_PROMPT2 ">> "
+#endif
+
+#if !defined(LUA_PROGNAME)
+#define LUA_PROGNAME "lua"
+#endif
+
+#if !defined(LUA_MAXINPUT)
+#define LUA_MAXINPUT 512
+#endif
+
+#if !defined(LUA_INIT)
+#define LUA_INIT "LUA_INIT"
+#endif
+
+#define LUA_INITVERSION \
+ LUA_INIT "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR
+
+
+/*
+** lua_stdin_is_tty detects whether the standard input is a 'tty' (that
+** is, whether we're running lua interactively).
+*/
+#if defined(LUA_USE_ISATTY)
+#include <unistd.h>
+#define lua_stdin_is_tty() isatty(0)
+#elif defined(LUA_WIN)
+#include <io.h>
+#include <stdio.h>
+#define lua_stdin_is_tty() _isatty(_fileno(stdin))
+#else
+#define lua_stdin_is_tty() 1 /* assume stdin is a tty */
+#endif
+
+
+/*
+** lua_readline defines how to show a prompt and then read a line from
+** the standard input.
+** lua_saveline defines how to "save" a read line in a "history".
+** lua_freeline defines how to free a line read by lua_readline.
+*/
+#if defined(LUA_USE_READLINE)
+
+#include <stdio.h>
+#include <readline/readline.h>
+#include <readline/history.h>
+#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL)
+#define lua_saveline(L,idx) \
+ if (lua_rawlen(L,idx) > 0) /* non-empty line? */ \
+ add_history(lua_tostring(L, idx)); /* add it to history */
+#define lua_freeline(L,b) ((void)L, free(b))
+
+#elif !defined(lua_readline)
+
+#define lua_readline(L,b,p) \
+ ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \
+ fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */
+#define lua_saveline(L,idx) { (void)L; (void)idx; }
+#define lua_freeline(L,b) { (void)L; (void)b; }
+
+#endif
+
+
+
+
+static lua_State *globalL = NULL;
+
+static const char *progname = LUA_PROGNAME;
+
+extern int luaopen_luxio(lua_State *L);
+
+static void lstop (lua_State *L, lua_Debug *ar) {
+ (void)ar; /* unused arg. */
+ lua_sethook(L, NULL, 0, 0);
+ luaL_error(L, "interrupted!");
+}
+
+
+static void laction (int i) {
+ signal(i, SIG_DFL); /* if another SIGINT happens before lstop,
+ terminate process (default action) */
+ lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
+}
+
+
+static void print_usage (const char *badoption) {
+ luai_writestringerror("%s: ", progname);
+ if (badoption[1] == 'e' || badoption[1] == 'l')
+ luai_writestringerror("'%s' needs argument\n", badoption);
+ else
+ luai_writestringerror("unrecognized option '%s'\n", badoption);
+ luai_writestringerror(
+ "usage: %s [options] [script [args]]\n"
+ "Available options are:\n"
+ " -e stat execute string " LUA_QL("stat") "\n"
+ " -i enter interactive mode after executing " LUA_QL("script") "\n"
+ " -l name require library " LUA_QL("name") "\n"
+ " -v show version information\n"
+ " -E ignore environment variables\n"
+ " -- stop handling options\n"
+ " - stop handling options and execute stdin\n"
+ ,
+ progname);
+}
+
+
+static void l_message (const char *pname, const char *msg) {
+ if (pname) luai_writestringerror("%s: ", pname);
+ luai_writestringerror("%s\n", msg);
+}
+
+
+static int report (lua_State *L, int status) {
+ if (status != LUA_OK && !lua_isnil(L, -1)) {
+ const char *msg = lua_tostring(L, -1);
+ if (msg == NULL) msg = "(error object is not a string)";
+ l_message(progname, msg);
+ lua_pop(L, 1);
+ /* force a complete garbage collection in case of errors */
+ lua_gc(L, LUA_GCCOLLECT, 0);
+ }
+ return status;
+}
+
+
+/* the next function is called unprotected, so it must avoid errors */
+static void finalreport (lua_State *L, int status) {
+ if (status != LUA_OK) {
+ const char *msg = (lua_type(L, -1) == LUA_TSTRING) ? lua_tostring(L, -1)
+ : NULL;
+ if (msg == NULL) msg = "(error object is not a string)";
+ l_message(progname, msg);
+ lua_pop(L, 1);
+ }
+}
+
+
+static int traceback (lua_State *L) {
+ const char *msg = lua_tostring(L, 1);
+ if (msg)
+ luaL_traceback(L, L, msg, 1);
+ else if (!lua_isnoneornil(L, 1)) { /* is there an error object? */
+ if (!luaL_callmeta(L, 1, "__tostring")) /* try its 'tostring' metamethod */
+ lua_pushliteral(L, "(no error message)");
+ }
+ return 1;
+}
+
+
+static int docall (lua_State *L, int narg, int nres) {
+ int status;
+ int base = lua_gettop(L) - narg; /* function index */
+ lua_pushcfunction(L, traceback); /* push traceback function */
+ lua_insert(L, base); /* put it under chunk and args */
+ globalL = L; /* to be available to 'laction' */
+ signal(SIGINT, laction);
+ status = lua_pcall(L, narg, nres, base);
+ signal(SIGINT, SIG_DFL);
+ lua_remove(L, base); /* remove traceback function */
+ return status;
+}
+
+#define LUXIO_COPYRIGHT "Built with Luxio, Copyright 2012 Rob Kendrick <rjek+luxio@rjek.com>, Daniel Silverstone <dsilvers@digital-scurf.org>"
+static void print_version (void) {
+ luai_writestring(LUA_COPYRIGHT, strlen(LUA_COPYRIGHT));
+ luai_writeline();
+ luai_writestring(LUXIO_COPYRIGHT, sizeof(LUXIO_COPYRIGHT) - 1);
+ luai_writeline();
+}
+
+
+static int getargs (lua_State *L, char **argv, int n) {
+ int narg;
+ int i;
+ int argc = 0;
+ while (argv[argc]) argc++; /* count total number of arguments */
+ narg = argc - (n + 1); /* number of arguments to the script */
+ luaL_checkstack(L, narg + 3, "too many arguments to script");
+ for (i=n+1; i < argc; i++)
+ lua_pushstring(L, argv[i]);
+ lua_createtable(L, narg, n + 1);
+ for (i=0; i < argc; i++) {
+ lua_pushstring(L, argv[i]);
+ lua_rawseti(L, -2, i - n);
+ }
+ return narg;
+}
+
+
+static int dofile (lua_State *L, const char *name) {
+ int status = luaL_loadfile(L, name);
+ if (status == LUA_OK) status = docall(L, 0, 0);
+ return report(L, status);
+}
+
+
+static int dostring (lua_State *L, const char *s, const char *name) {
+ int status = luaL_loadbuffer(L, s, strlen(s), name);
+ if (status == LUA_OK) status = docall(L, 0, 0);
+ return report(L, status);
+}
+
+
+static int dolibrary (lua_State *L, const char *name) {
+ int status;
+ lua_getglobal(L, "require");
+ lua_pushstring(L, name);
+ status = docall(L, 1, 1); /* call 'require(name)' */
+ if (status == LUA_OK)
+ lua_setglobal(L, name); /* global[name] = require return */
+ return report(L, status);
+}
+
+
+static const char *get_prompt (lua_State *L, int firstline) {
+ const char *p;
+ lua_getglobal(L, firstline ? "_PROMPT" : "_PROMPT2");
+ p = lua_tostring(L, -1);
+ if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2);
+ lua_pop(L, 1); /* remove global */
+ return p;
+}
+
+/* mark in error messages for incomplete statements */
+#define EOFMARK "<eof>"
+#define marklen (sizeof(EOFMARK)/sizeof(char) - 1)
+
+static int incomplete (lua_State *L, int status) {
+ if (status == LUA_ERRSYNTAX) {
+ size_t lmsg;
+ const char *msg = lua_tolstring(L, -1, &lmsg);
+ if (lmsg >= marklen && strcmp(msg + lmsg - marklen, EOFMARK) == 0) {
+ lua_pop(L, 1);
+ return 1;
+ }
+ }
+ return 0; /* else... */
+}
+
+
+static int pushline (lua_State *L, int firstline) {
+ char buffer[LUA_MAXINPUT];
+ char *b = buffer;
+ size_t l;
+ const char *prmt = get_prompt(L, firstline);
+ if (lua_readline(L, b, prmt) == 0)
+ return 0; /* no input */
+ l = strlen(b);
+ if (l > 0 && b[l-1] == '\n') /* line ends with newline? */
+ b[l-1] = '\0'; /* remove it */
+ if (firstline && b[0] == '=') /* first line starts with `=' ? */
+ lua_pushfstring(L, "return %s", b+1); /* change it to `return' */
+ else
+ lua_pushstring(L, b);
+ lua_freeline(L, b);
+ return 1;
+}
+
+
+static int loadline (lua_State *L) {
+ int status;
+ lua_settop(L, 0);
+ if (!pushline(L, 1))
+ return -1; /* no input */
+ for (;;) { /* repeat until gets a complete line */
+ size_t l;
+ const char *line = lua_tolstring(L, 1, &l);
+ status = luaL_loadbuffer(L, line, l, "=stdin");
+ if (!incomplete(L, status)) break; /* cannot try to add lines? */
+ if (!pushline(L, 0)) /* no more input? */
+ return -1;
+ lua_pushliteral(L, "\n"); /* add a new line... */
+ lua_insert(L, -2); /* ...between the two lines */
+ lua_concat(L, 3); /* join them */
+ }
+ lua_saveline(L, 1);
+ lua_remove(L, 1); /* remove line */
+ return status;
+}
+
+
+static void dotty (lua_State *L) {
+ int status;
+ const char *oldprogname = progname;
+ progname = NULL;
+ while ((status = loadline(L)) != -1) {
+ if (status == LUA_OK) status = docall(L, 0, LUA_MULTRET);
+ report(L, status);
+ if (status == LUA_OK && lua_gettop(L) > 0) { /* any result to print? */
+ luaL_checkstack(L, LUA_MINSTACK, "too many results to print");
+ lua_getglobal(L, "print");
+ lua_insert(L, 1);
+ if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != LUA_OK)
+ l_message(progname, lua_pushfstring(L,
+ "error calling " LUA_QL("print") " (%s)",
+ lua_tostring(L, -1)));
+ }
+ }
+ lua_settop(L, 0); /* clear stack */
+ luai_writeline();
+ progname = oldprogname;
+}
+
+
+static int handle_script (lua_State *L, char **argv, int n) {
+ int status;
+ const char *fname;
+ int narg = getargs(L, argv, n); /* collect arguments */
+ lua_setglobal(L, "arg");
+ fname = argv[n];
+ if (strcmp(fname, "-") == 0 && strcmp(argv[n-1], "--") != 0)
+ fname = NULL; /* stdin */
+ status = luaL_loadfile(L, fname);
+ lua_insert(L, -(narg+1));
+ if (status == LUA_OK)
+ status = docall(L, narg, LUA_MULTRET);
+ else
+ lua_pop(L, narg);
+ return report(L, status);
+}
+
+
+/* check that argument has no extra characters at the end */
+#define noextrachars(x) {if ((x)[2] != '\0') return -1;}
+
+
+/* indices of various argument indicators in array args */
+#define has_i 0 /* -i */
+#define has_v 1 /* -v */
+#define has_e 2 /* -e */
+#define has_E 3 /* -E */
+
+#define num_has 4 /* number of 'has_*' */
+
+
+static int collectargs (char **argv, int *args) {
+ int i;
+ for (i = 1; argv[i] != NULL; i++) {
+ if (argv[i][0] != '-') /* not an option? */
+ return i;
+ switch (argv[i][1]) { /* option */
+ case '-':
+ noextrachars(argv[i]);
+ return (argv[i+1] != NULL ? i+1 : 0);
+ case '\0':
+ return i;
+ case 'E':
+ args[has_E] = 1;
+ break;
+ case 'i':
+ noextrachars(argv[i]);
+ args[has_i] = 1; /* go through */
+ case 'v':
+ noextrachars(argv[i]);
+ args[has_v] = 1;
+ break;
+ case 'e':
+ args[has_e] = 1; /* go through */
+ case 'l': /* both options need an argument */
+ if (argv[i][2] == '\0') { /* no concatenated argument? */
+ i++; /* try next 'argv' */
+ if (argv[i] == NULL || argv[i][0] == '-')
+ return -(i - 1); /* no next argument or it is another option */
+ }
+ break;
+ default: /* invalid option; return its index... */
+ return -i; /* ...as a negative value */
+ }
+ }
+ return 0;
+}
+
+
+static int runargs (lua_State *L, char **argv, int n) {
+ int i;
+ for (i = 1; i < n; i++) {
+ lua_assert(argv[i][0] == '-');
+ switch (argv[i][1]) { /* option */
+ case 'e': {
+ const char *chunk = argv[i] + 2;
+ if (*chunk == '\0') chunk = argv[++i];
+ lua_assert(chunk != NULL);
+ if (dostring(L, chunk, "=(command line)") != LUA_OK)
+ return 0;
+ break;
+ }
+ case 'l': {
+ const char *filename = argv[i] + 2;
+ if (*filename == '\0') filename = argv[++i];
+ lua_assert(filename != NULL);
+ if (dolibrary(L, filename) != LUA_OK)
+ return 0; /* stop if file fails */
+ break;
+ }
+ default: break;
+ }
+ }
+ return 1;
+}
+
+
+static int handle_luainit (lua_State *L) {
+ const char *name = "=" LUA_INITVERSION;
+ const char *init = getenv(name + 1);
+ if (init == NULL) {
+ name = "=" LUA_INIT;
+ init = getenv(name + 1); /* try alternative name */
+ }
+ if (init == NULL) return LUA_OK;
+ else if (init[0] == '@')
+ return dofile(L, init+1);
+ else
+ return dostring(L, init, name);
+}
+
+
+static int pmain (lua_State *L) {
+ int argc = (int)lua_tointeger(L, 1);
+ char **argv = (char **)lua_touserdata(L, 2);
+ int script;
+ int args[num_has];
+ args[has_i] = args[has_v] = args[has_e] = args[has_E] = 0;
+ if (argv[0] && argv[0][0]) progname = argv[0];
+ script = collectargs(argv, args);
+ if (script < 0) { /* invalid arg? */
+ print_usage(argv[-script]);
+ return 0;
+ }
+ if (args[has_v]) print_version();
+ if (args[has_E]) { /* option '-E'? */
+ lua_pushboolean(L, 1); /* signal for libraries to ignore env. vars. */
+ lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
+ }
+ /* open standard libraries */
+ luaL_checkversion(L);
+ lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */
+ luaL_openlibs(L); /* open libraries */
+ luaopen_luxio(L); /* open luxio */
+ lua_setglobal(L, "luxio");
+ lua_gc(L, LUA_GCRESTART, 0);
+ if (!args[has_E] && handle_luainit(L) != LUA_OK)
+ return 0; /* error running LUA_INIT */
+ /* execute arguments -e and -l */
+ if (!runargs(L, argv, (script > 0) ? script : argc)) return 0;
+ /* execute main script (if there is one) */
+ if (script && handle_script(L, argv, script) != LUA_OK) return 0;
+ if (args[has_i]) /* -i option? */
+ dotty(L);
+ else if (script == 0 && !args[has_e] && !args[has_v]) { /* no arguments? */
+ if (lua_stdin_is_tty()) {
+ print_version();
+ dotty(L);
+ }
+ else dofile(L, NULL); /* executes stdin as a file */
+ }
+ lua_pushboolean(L, 1); /* signal no errors */
+ return 1;
+}
+
+
+int main (int argc, char **argv) {
+ int status, result;
+ lua_State *L = luaL_newstate(); /* create state */
+ if (L == NULL) {
+ l_message(argv[0], "cannot create state: not enough memory");
+ return EXIT_FAILURE;
+ }
+ /* call 'pmain' in protected mode */
+ lua_pushcfunction(L, &pmain);
+ lua_pushinteger(L, argc); /* 1st argument */
+ lua_pushlightuserdata(L, argv); /* 2nd argument */
+ status = lua_pcall(L, 2, 1, 0);
+ result = lua_toboolean(L, -1); /* get result */
+ finalreport(L, status);
+ lua_close(L);
+ return (result && status == LUA_OK) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
diff --git a/luxio.c b/luxio.c
index 29195e8..61ac0d6 100644
--- a/luxio.c
+++ b/luxio.c
@@ -6,10 +6,10 @@
* Distributed under the same terms as Lua itself (MIT).
*/
-#define LUXIO_RELEASE 1 /* clients use to check for features/bug fixes */
+#define LUXIO_RELEASE 6 /* clients use to check for features/bug fixes */
#define LUXIO_ABI 0 /* clients use to check the ABI of calls is same */
-#define LUXIO_COPYRIGHT "Copyright 2012 Rob Kendrick <rjek+luxio@rjek.com>\n" \
- "Copyright 2012 Daniel Silverstone <dsilvers@digital-scurf.org>"
+#define LUXIO_COPYRIGHT "Copyright 2013 Rob Kendrick <rjek+luxio@rjek.com>\n" \
+ "Copyright 2014 Daniel Silverstone <dsilvers@digital-scurf.org>"
#include "config.h"
@@ -39,6 +39,8 @@
#include <dirent.h>
#include <time.h>
#include <limits.h>
+#include <signal.h>
+#include <syslog.h>
#ifdef HAVE_SENDFILE
# include <sys/sendfile.h>
@@ -104,7 +106,7 @@ luxio__exec(lua_State *L, bool usep)
}
args[c] = NULL;
-
+
if (usep) {
ret = execvp(path, args);
} else {
@@ -115,7 +117,7 @@ luxio__exec(lua_State *L, bool usep)
free(args);
lua_pushinteger(L, ret);
lua_pushinteger(L, errno);
-
+
return 2;
}
@@ -155,7 +157,7 @@ luxio_waitpid(lua_State *L) /* 3.2.1 */
int options = luaL_checkinteger(L, 2);
int status;
pid_t proc;
-
+
proc = waitpid(pid, &status, options);
lua_pushinteger(L, proc);
if (proc == -1) {
@@ -235,9 +237,9 @@ static int
luxio__exit(lua_State *L) /* 3.2.2 */
{
int ret = luaL_optinteger(L, 1, 0);
-
+
_exit(ret);
-
+
return 0;
}
@@ -281,7 +283,7 @@ luxio_alarm(lua_State *L) /* 3.4.1 */
{
unsigned int seconds = luaL_checkinteger(L, 1);
lua_pushinteger(L, alarm(seconds));
-
+
return 1;
}
@@ -294,7 +296,7 @@ luxio_pause(lua_State *L) /* 3.4.2 */
{
lua_pushinteger(L, pause());
lua_pushinteger(L, errno);
-
+
return 2;
}
@@ -308,7 +310,7 @@ luxio_sleep(lua_State *L) /* 3.4.3 */
unsigned int seconds = luaL_checkinteger(L, 1);
lua_pushinteger(L, sleep(seconds));
-
+
return 1;
}
@@ -322,7 +324,7 @@ static int
luxio_getpid(lua_State *L) /* 4.1.1 */
{
lua_pushinteger(L, getpid());
-
+
return 1;
}
@@ -334,7 +336,7 @@ static int
luxio_getppid(lua_State *L) /* 4.1.1 */
{
lua_pushinteger(L, getppid());
-
+
return 1;
}
@@ -348,7 +350,7 @@ static int
luxio_getuid(lua_State *L) /* 4.2.1 */
{
lua_pushinteger(L, getuid());
-
+
return 1;
}
@@ -360,7 +362,7 @@ static int
luxio_geteuid(lua_State *L) /* 4.2.1 */
{
lua_pushinteger(L, geteuid());
-
+
return 1;
}
@@ -372,7 +374,7 @@ static int
luxio_getgid(lua_State *L) /* 4.2.1 */
{
lua_pushinteger(L, getgid());
-
+
return 1;
}
@@ -384,7 +386,7 @@ static int
luxio_getegid(lua_State *L) /* 4.2.1 */
{
lua_pushinteger(L, getegid());
-
+
return 1;
}
@@ -399,7 +401,7 @@ luxio_setuid(lua_State *L) /* 4.2.2 */
lua_pushinteger(L, setuid(uid));
lua_pushinteger(L, errno);
-
+
return 2;
}
@@ -414,7 +416,7 @@ luxio_setgid(lua_State *L) /* 4.2.2 */
lua_pushinteger(L, setgid(gid));
lua_pushinteger(L, errno);
-
+
return 2;
}
@@ -430,7 +432,7 @@ luxio_getlogin(lua_State *L) /* 4.2.4 */
{
char buf[LOGIN_NAME_MAX];
int r = getlogin_r(buf, sizeof(buf));
-
+
if (r != 0) {
lua_pushinteger(L, r);
lua_pushinteger(L, errno);
@@ -549,14 +551,14 @@ static int
luxio_getenv(lua_State *L) /* 4.6.1 */
{
const char *envvar = luaL_checkstring(L, 1);
-
+
char *envval = getenv(envvar);
-
+
if (envval == NULL)
return 0;
-
+
lua_pushstring(L, envval);
-
+
return 1;
}
@@ -570,10 +572,10 @@ luxio_setenv(lua_State *L) /* POSIX.1-2001 */
const char *envvar = luaL_checkstring(L, 1);
const char *envval = luaL_checkstring(L, 2);
int overwrite = luaL_optint(L, 3, 1);
-
+
lua_pushinteger(L, setenv(envvar, envval, overwrite));
lua_pushinteger(L, errno);
-
+
return 2;
}
@@ -585,10 +587,10 @@ static int
luxio_unsetenv(lua_State *L) /* POSIX.1-2001 */
{
const char *envvar = luaL_checkstring(L, 1);
-
+
lua_pushinteger(L, unsetenv(envvar));
lua_pushinteger(L, errno);
-
+
return 2;
}
@@ -619,10 +621,10 @@ static int
luxio_readdir_gc(lua_State *L)
{
luxio_readdir_state *s = luaL_checkudata(L, 1, LUXIO_READDIR_METATABLE);
-
+
closedir(s->dirp);
free(s->buf);
-
+
return 0;
}
@@ -637,7 +639,7 @@ luxio_readdir_tostring(lua_State *L)
*/
snprintf(buf, sizeof(buf), "dirent: %p", s);
lua_pushstring(L, buf);
-
+
return 1;
}
@@ -659,7 +661,7 @@ luxio__bless_readdir(lua_State *L)
* handle = opendir(path);
* nil, errno = opendir(path)
* handle, errno = opendir(path)
- */
+ */
static int
luxio_opendir(lua_State *L) /* 5.1.2 */
{
@@ -741,7 +743,7 @@ luxio_closedir(lua_State *L) /* 5.1.2 */
free(s->buf);
s->buf = NULL;
-
+
return 0;
}
@@ -755,7 +757,7 @@ luxio_readdir(lua_State *L) /* 5.1.2 */
{
luxio_readdir_state *s = luaL_checkudata(L, 1, LUXIO_READDIR_METATABLE);
int err;
-
+
err = readdir_r(s->dirp, s->buf, &s->ent);
if (err == 0 && s->ent != NULL) {
@@ -854,12 +856,12 @@ luxio_open(lua_State *L) /* 5.3.1 */
lua_pushstring(L, "open with O_CREAT called with no mode");
lua_error(L);
}
-
+
if (mode == INVALID_MODE)
result = open(pathname, flags);
else
result = open(pathname, flags, mode);
-
+
lua_pushinteger(L, result);
lua_pushinteger(L, errno);
@@ -962,10 +964,10 @@ luxio_mkfifo(lua_State *L) /* 5.4.2 */
{
const char *pathname = luaL_checkstring(L, 1);
mode_t mode = luaL_checkinteger(L, 2);
-
+
lua_pushinteger(L, mkfifo(pathname, mode));
lua_pushinteger(L, errno);
-
+
return 2;
}
@@ -979,7 +981,7 @@ static int
luxio_unlink(lua_State *L) /* 5.5.1 */
{
const char *s = luaL_checkstring(L, 1);
-
+
lua_pushinteger(L, unlink(s));
lua_pushinteger(L, errno);
@@ -994,7 +996,7 @@ static int
luxio_rmdir(lua_State *L) /* 5.5.2 */
{
const char *pathname = luaL_checkstring(L, 1);
-
+
lua_pushinteger(L, rmdir(pathname));
lua_pushinteger(L, errno);
@@ -1055,7 +1057,7 @@ luxio_stat(lua_State *L) /* 5.6.2 */
const char *pathname = luaL_checkstring(L, 1);
struct stat s;
int r = stat(pathname, &s);
-
+
lua_pushinteger(L, r);
if (r < 0) {
@@ -1077,7 +1079,7 @@ luxio_fstat(lua_State *L) /* 5.6.2 */
int fd = luaL_checkinteger(L, 1);
struct stat s;
int r = fstat(fd, &s);
-
+
lua_pushinteger(L, r);
if (r < 0) {
@@ -1101,7 +1103,7 @@ luxio_lstat(lua_State *L) /* POSIX.1-2001 */
int r = lstat(pathname, &s);
lua_pushinteger(L, r);
-
+
if (r < 0) {
lua_pushinteger(L, errno);
} else {
@@ -1249,7 +1251,7 @@ luxio_pipe(lua_State *L) /* 6.1.1 */
{
int res, pipefd[2];
luaL_checktype(L, 1, LUA_TTABLE);
-
+
res = pipe(pipefd);
if (res == 0) {
lua_pushinteger(L, pipefd[0]);
@@ -1257,10 +1259,10 @@ luxio_pipe(lua_State *L) /* 6.1.1 */
lua_pushinteger(L, pipefd[1]);
lua_rawseti(L, 1, 2);
}
-
+
lua_pushinteger(L, res);
lua_pushinteger(L, errno);
-
+
return 2;
}
@@ -1275,10 +1277,10 @@ luxio_pipe2(lua_State *L) /* GNU extension */
{
int res, pipefd[2];
int flags;
-
+
luaL_checktype(L, 1, LUA_TTABLE);
flags = luaL_checkinteger(L, 2);
-
+
res = pipe2(pipefd, flags);
if (res == 0) {
lua_pushinteger(L, pipefd[0]);
@@ -1286,10 +1288,10 @@ luxio_pipe2(lua_State *L) /* GNU extension */
lua_pushinteger(L, pipefd[1]);
lua_rawseti(L, 1, 2);
}
-
+
lua_pushinteger(L, res);
lua_pushinteger(L, errno);
-
+
return 2;
}
#endif
@@ -1307,7 +1309,7 @@ luxio_socketpair(lua_State *L) /* POSIX.1-2001 */
int sv[2];
int res;
luaL_checktype(L, 4, LUA_TTABLE);
-
+
res = socketpair(domain, type, protocol, sv);
if (res == 0) {
lua_pushinteger(L, sv[0]);
@@ -1319,7 +1321,7 @@ luxio_socketpair(lua_State *L) /* POSIX.1-2001 */
lua_pushinteger(L, res);
lua_pushinteger(L, errno);
- return 2;
+ return 2;
}
/**# File descriptor manipulation ********************************************/
@@ -1332,7 +1334,7 @@ static int
luxio_dup(lua_State *L) /* 6.2.1 */
{
int oldfd = luaL_checkint(L, 1);
-
+
lua_pushinteger(L, dup(oldfd));
lua_pushinteger(L, errno);
@@ -1348,11 +1350,11 @@ luxio_dup2(lua_State *L) /* 6.2.1 */
{
int oldfd = luaL_checkint(L, 1);
int newfd = luaL_checkint(L, 2);
-
+
lua_pushinteger(L, dup2(oldfd, newfd));
lua_pushinteger(L, errno);
- return 2;
+ return 2;
}
#ifdef _GNU_SOURCE
@@ -1366,7 +1368,7 @@ luxio_dup3(lua_State *L) /* GNU extension */
int oldfd = luaL_checkint(L, 1);
int newfd = luaL_checkint(L, 2);
int flags = luaL_checkint(L, 3);
-
+
lua_pushinteger(L, dup3(oldfd, newfd, flags));
lua_pushinteger(L, errno);
@@ -1403,14 +1405,14 @@ luxio_read(lua_State *L) /* 6.4.1 */
int count = luaL_checkint(L, 2);
ssize_t result;
char *buf = malloc(count);
-
+
if (buf == NULL) {
lua_pushstring(L, "unable to allocate read buffer: memory exhausted");
lua_error(L);
}
-
+
result = read(fd, buf, count);
-
+
if (result == -1) {
lua_pushinteger(L, result);
lua_pushinteger(L, errno);
@@ -1426,7 +1428,7 @@ luxio_read(lua_State *L) /* 6.4.1 */
lua_pushlstring(L, buf, result);
lua_pushinteger(L, errno);
}
-
+
free(buf);
return 2;
@@ -1443,9 +1445,9 @@ luxio_write(lua_State *L) /* 6.4.2 */
size_t count;
const char *buf = luaL_checklstring(L, 2, &count);
size_t offset = luaL_optinteger(L, 3, 0);
-
+
if (offset > count) offset = count;
-
+
lua_pushinteger(L, write(fd, buf + offset, count - offset));
lua_pushinteger(L, errno);
@@ -1463,22 +1465,22 @@ luxio_writev(lua_State *L) /* POSIX.1-2001 */
int blks = lua_gettop(L) - 1;
int c;
struct iovec *iov;
-
+
/* check there is at least one string to write */
luaL_checkstring(L, 2);
-
+
iov = malloc(blks * sizeof(*iov));
-
+
for (c = 0; c < blks; c++) {
iov[c].iov_base = (void *)luaL_checkstring(L, c + 2);
iov[c].iov_len = lua_rawlen(L, c + 2);
}
-
+
lua_pushinteger(L, writev(fd, iov, blks));
lua_pushinteger(L, errno);
-
+
free(iov);
-
+
return 2;
}
@@ -1502,7 +1504,7 @@ luxio_sendfile(lua_State *L) /* Linux-specific */
lua_pushinteger(L, errno);
return 2;
}
-
+
offset = luaL_checkint(L, 3);
r = sendfile(out_fd, in_fd, &offset, count);
lua_pushinteger(L, r);
@@ -1560,7 +1562,7 @@ luxio_fcntl(lua_State *L) /* 6.5.2 */
int cmd = luaL_checkint(L, 2);
long arg_long;
struct flock flock;
-
+
switch (cmd) {
/* commands that take no argument */
case F_GETFD:
@@ -1593,7 +1595,7 @@ luxio_fcntl(lua_State *L) /* 6.5.2 */
case F_SETLKW:
case F_GETLK:
luaL_checktype(L, 3, LUA_TTABLE);
-
+
lua_getfield(L, 3, "l_type");
lua_getfield(L, 3, "l_whence");
lua_getfield(L, 3, "l_start");
@@ -1603,7 +1605,7 @@ luxio_fcntl(lua_State *L) /* 6.5.2 */
flock.l_start = lua_tonumber(L, -2);
flock.l_len = lua_tonumber(L, -1);
flock.l_pid = 0;
-
+
lua_pushinteger(L, fcntl(fd, cmd, &flock));
lua_pushinteger(L, errno);
@@ -1621,12 +1623,12 @@ luxio_fcntl(lua_State *L) /* 6.5.2 */
}
return 2;
-
+
default:
lua_pushstring(L, "unhandled fcntl() command");
lua_error(L);
}
-
+
return 0; /* never get here, but keep compiler happy */
}
@@ -1637,7 +1639,7 @@ luxio_lseek(lua_State *L) /* 6.5.3 */
int fd = luaL_checkint(L, 1);
off64_t offset = (off64_t)luaL_checknumber(L, 2); /* 56b is enough! */
int whence = luaL_checkint(L, 3);
-
+
lua_pushinteger(L, (lua_Number)lseek64(fd, offset, whence));
lua_pushinteger(L, errno);
@@ -1654,7 +1656,7 @@ luxio_lseek(lua_State *L) /* 6.5.3 */
int fd = luaL_checkint(L, 1);
off_t offset = luaL_checkinteger(L, 2);
int whence = luaL_checkint(L, 3);
-
+
lua_pushinteger(L, lseek(fd, offset, whence));
lua_pushinteger(L, errno);
@@ -1672,13 +1674,14 @@ static int
luxio_fsync(lua_State *L) /* 6.6.1 */
{
int fildes = luaL_checkinteger(L, 1);
-
+
lua_pushinteger(L, fsync(fildes));
lua_pushinteger(L, errno);
return 2;
}
+#ifdef HAVE_FDATASYNC
/**% fdatasync
* retval = fdatasync(filedes);
* retval = fdatasync(filedes)
@@ -1687,12 +1690,13 @@ static int
luxio_fdatasync(lua_State *L) /* 6.6.2 */
{
int fildes = luaL_checkinteger(L, 1);
-
+
lua_pushinteger(L, fdatasync(fildes));
lua_pushinteger(L, errno);
return 2;
}
+#endif
/* 6.7 Asynchronous input and output */
@@ -1789,15 +1793,36 @@ luxio_nanosleep(lua_State *L) /* 14.2.5 */
lua_pushinteger(L, rem.tv_sec);
lua_pushinteger(L, rem.tv_nsec);
- return 4;
+ return 4;
}
/**# Message passing *********************************************************/
-#ifdef _POSIX_MESSAGE_PASSING
+#if defined(_POSIX_MESSAGE_PASSING)
#include <mqueue.h>
+#define LUXIO_MQ_METATABLE_NAME "luxio.mq"
+
+struct luxio_mq_data {
+ mqd_t mq;
+ char name[NAME_MAX];
+};
+
+static int
+luxio__mq_tostring(lua_State *L)
+{
+ char buf[NAME_MAX + 64];
+
+ struct luxio_mq_data *m =
+ luaL_checkudata(L, 1, LUXIO_MQ_METATABLE_NAME);
+
+ sprintf(buf, "<mq %p %s>", (void *)(intptr_t)m->mq, m->name);
+
+ lua_pushstring(L, buf);
+ return 1;
+}
+
/**% mq_open
* retval = mq_open(name, oflag[, mode, attr]);
* retval, errno = mq_open(name, oflag[, mode])
@@ -1809,19 +1834,36 @@ luxio_mq_open(lua_State *L) /* 15.2.1 */
int oflag = luaL_checkinteger(L, 2);
mode_t mode = luaL_optinteger(L, 3, INVALID_MODE);
mqd_t mq;
+ struct luxio_mq_data *m;
if ((oflag & O_CREAT) && mode == INVALID_MODE) {
lua_pushstring(L, "mq_open with O_CREATE called with no mode");
lua_error(L);
}
-
+
if (oflag & O_CREAT) {
mq = mq_open(name, oflag, mode, NULL);
} else {
mq = mq_open(name, oflag);
}
- lua_pushinteger(L, mq);
+ if (mq == (mqd_t)-1) {
+ lua_pushnumber(L, -1);
+ lua_pushinteger(L, errno);
+
+ return 2;
+ }
+
+ m = lua_newuserdata(L, sizeof(*m));
+ m->mq = mq;
+ strncpy(m->name, name, NAME_MAX);
+
+ if (luaL_newmetatable(L, LUXIO_MQ_METATABLE_NAME) != 0) {
+ lua_pushcfunction(L, luxio__mq_tostring);
+ lua_setfield(L, -2, "__tostring");
+ }
+
+ lua_setmetatable(L, -2);
lua_pushinteger(L, errno);
return 2;
@@ -1834,9 +1876,10 @@ luxio_mq_open(lua_State *L) /* 15.2.1 */
static int
luxio_mq_close(lua_State *L) /* 15.2.2 */
{
- mqd_t mq = luaL_checkinteger(L, 1);
+ struct luxio_mq_data *m =
+ luaL_checkudata(L, 1, LUXIO_MQ_METATABLE_NAME);
- lua_pushinteger(L, mq_close(mq));
+ lua_pushinteger(L, mq_close(m->mq));
lua_pushinteger(L, errno);
return 2;
}
@@ -1852,7 +1895,7 @@ luxio_mq_unlink(lua_State *L) /* 15.2.3 */
lua_pushinteger(L, mq_unlink(name));
lua_pushinteger(L, errno);
- return 2;
+ return 2;
}
/**% mq_send
@@ -1862,12 +1905,13 @@ luxio_mq_unlink(lua_State *L) /* 15.2.3 */
static int
luxio_mq_send(lua_State *L) /* 15.2.4 */
{
- mqd_t mq = luaL_checkinteger(L, 1);
+ struct luxio_mq_data *m =
+ luaL_checkudata(L, 1, LUXIO_MQ_METATABLE_NAME);
size_t msg_len;
const char *msg_ptr = luaL_checklstring(L, 2, &msg_len);
unsigned int msg_prio = luaL_checkinteger(L, 3);
- lua_pushinteger(L, mq_send(mq, msg_ptr, msg_len, msg_prio));
+ lua_pushinteger(L, mq_send(m->mq, msg_ptr, msg_len, msg_prio));
lua_pushinteger(L, errno);
return 2;
}
@@ -1879,18 +1923,19 @@ luxio_mq_send(lua_State *L) /* 15.2.4 */
static int
luxio_mq_receive(lua_State *L) /* 15.2.5 */
{
- mqd_t mq = luaL_checkinteger(L, 1);
+ struct luxio_mq_data *m =
+ luaL_checkudata(L, 1, LUXIO_MQ_METATABLE_NAME);
unsigned int msg_prio;
struct mq_attr attr;
/* Find out the maximum size of a message */
- if (mq_getattr(mq, &attr) == -1) {
+ if (mq_getattr(m->mq, &attr) == -1) {
lua_pushinteger(L, -1);
lua_pushinteger(L, errno);
return 2;
} else {
char msg_ptr[attr.mq_msgsize];
- int r = mq_receive(mq, msg_ptr, sizeof(msg_ptr), &msg_prio);
+ int r = mq_receive(m->mq, msg_ptr, sizeof(msg_ptr), &msg_prio);
lua_pushinteger(L, r);
lua_pushinteger(L, errno);
if (r == -1) {
@@ -1932,11 +1977,12 @@ luxio_make_attr_table(lua_State *L, struct mq_attr *attr)
static int
luxio_mq_setattr(lua_State *L) /* 15.2.7 */
{
- mqd_t mq = luaL_checkinteger(L, 1);
+ struct luxio_mq_data *m =
+ luaL_checkudata(L, 1, LUXIO_MQ_METATABLE_NAME);
struct mq_attr mqstat = { luaL_checkinteger(L, 2), 0, 0, 0 };
struct mq_attr omqstat = { 0, 0, 0, 0 };
-
- lua_pushinteger(L, mq_setattr(mq, &mqstat, &omqstat));
+
+ lua_pushinteger(L, mq_setattr(m->mq, &mqstat, &omqstat));
lua_pushinteger(L, errno);
luxio_make_attr_table(L, &omqstat);
@@ -1950,10 +1996,11 @@ luxio_mq_setattr(lua_State *L) /* 15.2.7 */
static int
luxio_mq_getattr(lua_State *L) /* 15.2.8 */
{
- mqd_t mq = luaL_checkinteger(L, 1);
+ struct luxio_mq_data *m =
+ luaL_checkudata(L, 1, LUXIO_MQ_METATABLE_NAME);
struct mq_attr mqstat;
- lua_pushinteger(L, mq_getattr(mq, &mqstat));
+ lua_pushinteger(L, mq_getattr(m->mq, &mqstat));
lua_pushinteger(L, errno);
luxio_make_attr_table(L, &mqstat);
@@ -1969,7 +2016,8 @@ luxio_mq_getattr(lua_State *L) /* 15.2.8 */
static int
luxio_mq_timedsend(lua_State *L) /* POSIX.1-2001 */
{
- mqd_t mq = luaL_checkinteger(L, 1);
+ struct luxio_mq_data *m =
+ luaL_checkudata(L, 1, LUXIO_MQ_METATABLE_NAME);
size_t msg_len;
const char *msg_ptr = luaL_checklstring(L, 2, &msg_len);
unsigned int msg_prio = luaL_checkinteger(L, 3);
@@ -1977,10 +2025,10 @@ luxio_mq_timedsend(lua_State *L) /* POSIX.1-2001 */
long tv_nsec = luaL_checkinteger(L, 5);
struct timespec abs_timeout = { tv_secs, tv_nsec };
- lua_pushinteger(L, mq_timedsend(mq, msg_ptr, msg_len, msg_prio,
+ lua_pushinteger(L, mq_timedsend(m->mq, msg_ptr, msg_len, msg_prio,
&abs_timeout));
lua_pushinteger(L, errno);
- return 2;
+ return 2;
}
/**% mq_timedreceive
@@ -1990,7 +2038,8 @@ luxio_mq_timedsend(lua_State *L) /* POSIX.1-2001 */
static int
luxio_mq_timedreceive(lua_State *L) /* POSIX.1-2001 */
{
- mqd_t mq = luaL_checkinteger(L, 1);
+ struct luxio_mq_data *m =
+ luaL_checkudata(L, 1, LUXIO_MQ_METATABLE_NAME);
unsigned int msg_prio;
struct mq_attr attr;
time_t tv_secs = luaL_checkinteger(L, 2);
@@ -1998,14 +2047,14 @@ luxio_mq_timedreceive(lua_State *L) /* POSIX.1-2001 */
struct timespec abs_timeout = { tv_secs, tv_nsec };
/* Find out the maximum size of a message */
- if (mq_getattr(mq, &attr) == -1) {
+ if (mq_getattr(m->mq, &attr) == -1) {
lua_pushinteger(L, -1);
lua_pushinteger(L, errno);
return 2;
} else {
char msg_ptr[attr.mq_msgsize];
- int r = mq_timedreceive(mq, msg_ptr, sizeof(msg_ptr), &msg_prio,
- &abs_timeout);
+ int r = mq_timedreceive(m->mq, msg_ptr, sizeof(msg_ptr),
+ &msg_prio, &abs_timeout);
lua_pushinteger(L, r);
lua_pushinteger(L, errno);
if (r == -1) {
@@ -2334,7 +2383,7 @@ luxio_getsockopt(lua_State *L)
int res, r_int;
char r_ifname[IFNAMSIZ];
socklen_t l;
-
+
switch (level) {
case SOL_SOCKET:
switch (optname) {
@@ -2352,7 +2401,7 @@ luxio_getsockopt(lua_State *L)
}
return 2;
-
+
/* other options probably expect integers */
default:
l = sizeof(r_int);
@@ -2363,7 +2412,7 @@ luxio_getsockopt(lua_State *L)
} else {
lua_pushinteger(L, r_int);
}
-
+
return 2;
}
case IPPROTO_IP:
@@ -2385,7 +2434,7 @@ luxio_getsockopt(lua_State *L)
} else {
lua_pushinteger(L, r_int);
}
-
+
return 2;
default:
@@ -2393,7 +2442,7 @@ luxio_getsockopt(lua_State *L)
optname);
}
}
-
+
return luaL_error(L, "unhandled socket level %d", level);
}
@@ -2411,7 +2460,7 @@ luxio_setsockopt(lua_State *L)
const char *r_ifname;
socklen_t l;
size_t sz;
-
+
switch (level) {
case SOL_SOCKET:
switch (optname) {
@@ -2433,7 +2482,7 @@ luxio_setsockopt(lua_State *L)
res = setsockopt(sockfd, level, optname, &r_int, l);
lua_pushinteger(L, res);
lua_pushinteger(L, errno);
-
+
return 2;
}
case IPPROTO_IP:
@@ -2452,7 +2501,7 @@ luxio_setsockopt(lua_State *L)
res = setsockopt(sockfd, level, optname, &r_int, l);
lua_pushinteger(L, res);
lua_pushinteger(L, errno);
-
+
return 2;
default:
@@ -2460,7 +2509,7 @@ luxio_setsockopt(lua_State *L)
optname);
}
}
-
+
return luaL_error(L, "unhandled socket level %d", level);
}
@@ -2497,7 +2546,7 @@ luxio_getaddrinfo(lua_State *L)
if (node[0] == '\0')
node = NULL;
-
+
if (serv[0] == '\0')
serv = NULL;
@@ -2507,7 +2556,7 @@ luxio_getaddrinfo(lua_State *L)
if (r < 0)
return 1;
-
+
lua_newtable(L); /* table we return with entries */
for (rp = results, c = 1; rp != NULL; rp = rp->ai_next, c++) {
@@ -2524,7 +2573,7 @@ luxio_getaddrinfo(lua_State *L)
lua_pushliteral(L, "ai_socktype");
lua_pushinteger(L, rp->ai_socktype);
lua_rawset(L, -3);
-
+
lua_pushliteral(L, "ai_protocol");
lua_pushinteger(L, rp->ai_protocol);
lua_rawset(L, -3);
@@ -2536,12 +2585,12 @@ luxio_getaddrinfo(lua_State *L)
lua_pushliteral(L, "ai_addr");
luxio__makesockaddr(L, rp->ai_addr, rp->ai_addrlen);
lua_rawset(L, -3);
-
+
lua_rawseti(L, -2, c);
}
freeaddrinfo(results);
-
+
return 2;
}
@@ -2681,13 +2730,13 @@ luxio_bitop_or(lua_State *L)
{
int value = luaL_checkint(L, 1);
int n = lua_gettop(L);
-
+
while (n > 1) {
value |= luaL_checkint(L, n--);
}
-
+
lua_pushnumber(L, value);
-
+
return 1;
}
@@ -2696,13 +2745,13 @@ luxio_bitop_and(lua_State *L)
{
int value = luaL_checkint(L, 1);
int n = lua_gettop(L);
-
+
while (n > 1) {
value &= luaL_checkint(L, n--);
}
-
+
lua_pushnumber(L, value);
-
+
return 1;
}
@@ -2711,13 +2760,13 @@ luxio_bitop_clear(lua_State *L)
{
int value = luaL_checkint(L, 1);
int n = lua_gettop(L);
-
+
while (n > 1) {
value &= ~luaL_checkint(L, n--);
}
-
+
lua_pushnumber(L, value);
-
+
return 1;
}
@@ -2726,7 +2775,7 @@ luxio_bitop_invert(lua_State *L)
{
int value = luaL_checkint(L, 1);
int n = lua_gettop(L);
-
+
/* Special case, passed 1 value, we invert that rather than
* inverting the other bits supplied
*/
@@ -2737,9 +2786,9 @@ luxio_bitop_invert(lua_State *L)
value ^= luaL_checkint(L, n--);
}
}
-
+
lua_pushnumber(L, value);
-
+
return 1;
}
@@ -2749,11 +2798,11 @@ luxio_bitop_test(lua_State *L)
int value = luaL_checkint(L, 1);
int goal = 0;
int n = lua_gettop(L);
-
+
while (n > 1) {
goal |= luaL_checkint(L, n--);
}
-
+
lua_pushboolean(L, (value & goal) == goal);
return 1;
@@ -2768,9 +2817,9 @@ luxio_timeval_lt(lua_State *L)
{
struct timeval *a = luaL_checkudata(L, 1, LUXIO_TIMEVAL_METATABLE);
struct timeval *b = luaL_checkudata(L, 2, LUXIO_TIMEVAL_METATABLE);
-
+
lua_pushboolean(L, timercmp(a, b, <));
-
+
return 1;
}
@@ -2779,10 +2828,10 @@ luxio_timeval_le(lua_State *L)
{
struct timeval *a = luaL_checkudata(L, 1, LUXIO_TIMEVAL_METATABLE);
struct timeval *b = luaL_checkudata(L, 2, LUXIO_TIMEVAL_METATABLE);
-
+
/* <= is not portable, so use ! > */
lua_pushboolean(L, !timercmp(a, b, >));
-
+
return 1;
}
@@ -2791,10 +2840,10 @@ luxio_timeval_eq(lua_State *L)
{
struct timeval *a = luaL_checkudata(L, 1, LUXIO_TIMEVAL_METATABLE);
struct timeval *b = luaL_checkudata(L, 2, LUXIO_TIMEVAL_METATABLE);
-
+
/* == is not portable, so use ! != */
lua_pushboolean(L, !timercmp(a, b, !=));
-
+
return 1;
}
@@ -2804,12 +2853,12 @@ luxio_timeval_tostring(lua_State *L)
{
struct timeval *a = luaL_checkudata(L, 1, LUXIO_TIMEVAL_METATABLE);
char buffer[LUXIO_TIME_BUFLEN];
-
+
snprintf(buffer, LUXIO_TIME_BUFLEN, "timeval: %ld.%06ld",
- a->tv_sec, a->tv_usec);
+ (long)a->tv_sec, (long)a->tv_usec);
lua_pushstring(L, buffer);
-
+
return 1;
}
@@ -2818,19 +2867,19 @@ luxio_timeval_index(lua_State *L)
{
struct timeval *a = luaL_checkudata(L, 1, LUXIO_TIMEVAL_METATABLE);
const char *s = luaL_checkstring(L, 2);
-
+
if (strcmp(s, "tv_sec") == 0)
lua_pushinteger(L, a->tv_sec);
else if (strcmp(s, "tv_usec") == 0)
lua_pushinteger(L, a->tv_usec);
else if (strcmp(s, "seconds") == 0)
- lua_pushnumber(L, (lua_Number)(a->tv_sec) +
+ lua_pushnumber(L, (lua_Number)(a->tv_sec) +
((lua_Number)(a->tv_usec) / 1000000));
else if (strcmp(s, "useconds") == 0)
lua_pushinteger(L, a->tv_usec + (a->tv_sec * 1000000));
else
luaL_error(L, "Unknown field %s in timeval", s);
-
+
return 1;
}
@@ -2839,7 +2888,7 @@ luxio_timeval_newindex(lua_State *L)
{
struct timeval *a = luaL_checkudata(L, 1, LUXIO_TIMEVAL_METATABLE);
const char *s = luaL_checkstring(L, 2);
-
+
if (strcmp(s, "tv_sec") == 0)
a->tv_sec = luaL_checkinteger(L, 3);
else if (strcmp(s, "tv_usec") == 0)
@@ -2854,7 +2903,7 @@ luxio_timeval_newindex(lua_State *L)
a->tv_usec = (suseconds_t)v % 1000000;
} else
luaL_error(L, "Unknown field %s in timeval", s);
-
+
return 0;
}
@@ -2866,11 +2915,11 @@ luxio_timeval_add(lua_State *L)
struct timeval *a = luaL_checkudata(L, 1, LUXIO_TIMEVAL_METATABLE);
struct timeval *b = luaL_checkudata(L, 2, LUXIO_TIMEVAL_METATABLE);
struct timeval *ret = lua_newuserdata(L, sizeof(*ret));
-
+
timeradd(a, b, ret);
-
+
luxio__bless_timeval(L);
-
+
return 1;
}
@@ -2880,11 +2929,11 @@ luxio_timeval_sub(lua_State *L)
struct timeval *a = luaL_checkudata(L, 1, LUXIO_TIMEVAL_METATABLE);
struct timeval *b = luaL_checkudata(L, 2, LUXIO_TIMEVAL_METATABLE);
struct timeval *ret = lua_newuserdata(L, sizeof(*ret));
-
+
timersub(a, b, ret);
-
+
luxio__bless_timeval(L);
-
+
return 1;
}
@@ -2892,7 +2941,7 @@ static void
luxio__bless_timeval(lua_State *L)
{
int create = luaL_newmetatable(L, LUXIO_TIMEVAL_METATABLE);
-
+
if (create) {
lua_pushcfunction(L, luxio_timeval_le);
lua_setfield(L, -2, "__le");
@@ -2911,7 +2960,7 @@ luxio__bless_timeval(lua_State *L)
lua_pushcfunction(L, luxio_timeval_sub);
lua_setfield(L, -2, "__sub");
}
-
+
lua_setmetatable(L, -2);
}
@@ -2919,11 +2968,11 @@ static int
luxio_timeval_zero(lua_State *L)
{
struct timeval *r = lua_newuserdata(L, sizeof(*r));
-
+
timerclear(r);
-
+
luxio__bless_timeval(L);
-
+
return 1;
}
@@ -2931,17 +2980,17 @@ static int
luxio_gettimeofday(lua_State *L)
{
struct timeval *r = lua_newuserdata(L, sizeof(*r));
-
+
int ret = gettimeofday(r, NULL);
-
+
if (ret == -1) {
lua_pushinteger(L, -1);
lua_pushinteger(L, errno);
return 2;
}
-
+
luxio__bless_timeval(L);
-
+
return 1;
}
@@ -2959,6 +3008,72 @@ luxio_strerror(lua_State *L)
return 1;
}
+static char *luxio_openlog_ident = NULL;
+
+static int
+luxio_openlog(lua_State *L)
+{
+ size_t len;
+ const char *ident = luaL_checklstring(L, 1, &len);
+ int option = luaL_checkint(L, 2);
+ int facility = luaL_checkint(L, 3);
+
+ /* openlog doesn't make its own copy of ident
+ * and lua could garbage collect ident
+ * so take a copy of ident
+ */
+ free(luxio_openlog_ident);
+ luxio_openlog_ident = malloc(len);
+ strncpy(luxio_openlog_ident, ident, len);
+
+ openlog(ident, option, facility);
+
+ return 0;
+}
+
+static int
+luxio_syslog(lua_State *L)
+{
+ int priority = luaL_checkint(L, 1);
+ const char *msg = luaL_checkstring(L, 2);
+
+ syslog(priority, "%s", msg);
+
+ return 0;
+}
+
+static int
+luxio_closelog(lua_State *L)
+{
+ free(luxio_openlog_ident);
+ luxio_openlog_ident = NULL;
+ closelog();
+
+ return 0;
+}
+
+static int
+luxio_setlogmask(lua_State *L)
+{
+ int mask = luaL_checkint(L, 1);
+
+ int oldmask = setlogmask(mask);
+ lua_pushinteger(L, oldmask);
+
+ return 1;
+}
+
+static int
+luxio_LOG_MASK(lua_State *L)
+{
+ int priority = luaL_checkint(L, 1);
+
+ int mask = LOG_MASK(priority);
+ lua_pushinteger(L, mask);
+
+ return 1;
+}
+
static const struct luaL_Reg
luxio_functions[] = {
{ "open", luxio_open },
@@ -2969,7 +3084,9 @@ luxio_functions[] = {
{ "lseek", luxio_lseek },
{ "ftruncate", luxio_ftruncate },
{ "fsync", luxio_fsync },
+#ifdef HAVE_FDATASYNC
{ "fdatasync", luxio_fdatasync },
+#endif
{ "rename", luxio_rename },
{ "link", luxio_link },
{ "unlink", luxio_unlink },
@@ -3037,7 +3154,7 @@ luxio_functions[] = {
{ "pollfds_setslot", luxio_pollfds_set_slot },
{ "pollfds_getslot", luxio_pollfds_get_slot },
{ "poll", luxio_poll },
-
+
{ "zero_timeval", luxio_timeval_zero },
{ "gettimeofday", luxio_gettimeofday },
@@ -3045,7 +3162,7 @@ luxio_functions[] = {
{ "exec", luxio_exec },
{ "execp", luxio_execp },
{ "waitpid", luxio_waitpid },
-
+
#define WAITPID_STATUS_ENTRY(x) { #x, luxio_##x }
WAITPID_STATUS_ENTRY(WIFEXITED),
WAITPID_STATUS_ENTRY(WEXITSTATUS),
@@ -3065,7 +3182,7 @@ luxio_functions[] = {
{ "strerror", luxio_strerror },
{ "_exit", luxio__exit },
-
+
{ "setenv", luxio_setenv },
{ "unsetenv", luxio_unsetenv },
{ "getenv", luxio_getenv },
@@ -3082,7 +3199,7 @@ luxio_functions[] = {
{ "alarm", luxio_alarm },
{ "pause", luxio_pause },
{ "sleep", luxio_sleep },
-
+
{ "getpid", luxio_getpid },
{ "getppid", luxio_getppid },
@@ -3104,6 +3221,8 @@ luxio_functions[] = {
{ "nanosleep", luxio_nanosleep },
+#if defined(_POSIX_MESSAGE_PASSING) && defined(__linux__)
+
#if _XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L
{ "mq_timedsend", luxio_mq_timedsend },
{ "mq_timedreceive", luxio_mq_timedreceive },
@@ -3115,7 +3234,12 @@ luxio_functions[] = {
{ "mq_receive", luxio_mq_receive },
{ "mq_setattr", luxio_mq_setattr },
{ "mq_getattr", luxio_mq_getattr },
-
+#endif
+ { "openlog", luxio_openlog },
+ { "syslog", luxio_syslog },
+ { "closelog", luxio_closelog },
+ { "setlogmask", luxio_setlogmask },
+ { "LOG_MASK", luxio_LOG_MASK },
{ NULL, NULL }
};
@@ -3126,7 +3250,7 @@ luxio_bitop_functions[] = {
{ "binvert", luxio_bitop_invert },
{ "btest", luxio_bitop_test },
{ "bclear", luxio_bitop_clear },
-
+
{ NULL, NULL }
};
@@ -3148,7 +3272,7 @@ luaopen_luxio(lua_State *L)
luaL_newlib(L, luxio_bitop_functions);
#else
luaL_register(L, "luxio", luxio_functions);
- lua_createtable(L, 0, (sizeof(luxio_bitop_functions) /
+ lua_createtable(L, 0, (sizeof(luxio_bitop_functions) /
sizeof(struct luaL_Reg)) - 1);
luaL_register(L, NULL, luxio_bitop_functions);
#endif
diff --git a/luxio/mq.lua b/luxio/mq.lua
index 4ba8c65..6e11f8d 100644
--- a/luxio/mq.lua
+++ b/luxio/mq.lua
@@ -101,8 +101,8 @@ local mq_mt = {
end,
__tostring = function(x)
- return ("message queue: %s %s (%d)%s"):format(
- x.rw_mode, x.path, x.desc, x.closed and " closed" or "")
+ return ("message queue: %s %s (%s)%s"):format(
+ x.rw_mode, x.path, tostring(x.desc), x.closed and " closed" or "")
end,
__gc = mq_meta_gc
@@ -155,7 +155,7 @@ local function open(path, rw, mode)
mq, errno = l.mq_open(path, rw_mode)
end
- if mq < 0 then
+ if type(mq) == "number" and mq == -1 then
return err("mq_open", errno)
end
diff --git a/luxio_constants.h.in b/luxio_constants.h.in
index 05a73d9..07a4f03 100644
--- a/luxio_constants.h.in
+++ b/luxio_constants.h.in
@@ -49,13 +49,13 @@ static const struct {
E(O_WRONLY),
E(O_RDWR),
E(O_APPEND),
- E(O_ASYNC),
- E(O_CLOEXEC),
+? E(O_ASYNC),
+? E(O_CLOEXEC),
E(O_CREAT),
E(O_EXCL),
E(O_NOCTTY),
E(O_NONBLOCK),
- E(O_SYNC),
+? E(O_SYNC),
E(O_TRUNC),
? E(O_DIRECT),
? E(O_NOFOLLOW),
@@ -145,6 +145,7 @@ static const struct {
? E(SO_REUSEADDR),
? E(SO_TIMESTAMP),
? E(SO_TYPE),
+? E(SO_REUSEPORT),
E(IPPROTO_IP),
? E(TCP_CORK),
@@ -273,6 +274,37 @@ static const struct {
? E(_POSIX_TIMER_MAX),
? E(_POSIX_TZNAME_MAX),
+ E(LOG_PID),
+ E(LOG_CONS),
+ E(LOG_NDELAY),
+ E(LOG_ODELAY),
+ E(LOG_NOWAIT),
+ E(LOG_KERN),
+ E(LOG_USER),
+ E(LOG_MAIL),
+ E(LOG_NEWS),
+ E(LOG_UUCP),
+ E(LOG_DAEMON),
+ E(LOG_AUTH),
+ E(LOG_CRON),
+ E(LOG_LPR),
+ E(LOG_LOCAL0),
+ E(LOG_LOCAL1),
+ E(LOG_LOCAL2),
+ E(LOG_LOCAL3),
+ E(LOG_LOCAL4),
+ E(LOG_LOCAL5),
+ E(LOG_LOCAL6),
+ E(LOG_LOCAL7),
+ E(LOG_EMERG),
+ E(LOG_ALERT),
+ E(LOG_CRIT),
+ E(LOG_ERR),
+ E(LOG_WARNING),
+ E(LOG_NOTICE),
+ E(LOG_INFO),
+ E(LOG_DEBUG),
+
E(EXIT_SUCCESS),
E(EXIT_FAILURE),
diff --git a/tests/test-mqueue-read.lua b/tests/test-mqueue-read.lua
new file mode 100644
index 0000000..d8aeb90
--- /dev/null
+++ b/tests/test-mqueue-read.lua
@@ -0,0 +1,29 @@
+l = require "luxio"
+s = require "luxio.simple"
+
+local mq, errno
+
+mq, errno = l.mq_open("/luxio.test", l.bit.bor(l.O_RDONLY, l.O_CREAT), s.tomode "0777")
+
+if mq == -1 then
+ error(l.strerror(errno))
+end
+
+
+io.stdout:write(tostring(mq) .. " attributes:\n")
+
+r, errno, attr = l.mq_getattr(mq)
+
+for i, v in pairs(attr) do
+ io.stdout:write(" ", i, " ", v, "\n")
+end
+
+local message, bytes, priority
+
+repeat
+ bytes, errno, message, priority = l.mq_receive(mq)
+ print(bytes, errno, message, priority)
+until message == "QUIT" or bytes == -1
+
+l.mq_close(mq)
+l.mq_unlink "/luxio-test"
diff --git a/tests/test-mqueue-write.lua b/tests/test-mqueue-write.lua
new file mode 100644
index 0000000..42eff87
--- /dev/null
+++ b/tests/test-mqueue-write.lua
@@ -0,0 +1,15 @@
+l = require "luxio"
+s = require "luxio.simple"
+
+local mq, errno
+
+mq, errno = l.mq_open("/luxio.test", l.O_WRONLY)
+
+if mq == -1 then
+ error(l.strerror(errno))
+end
+
+r, errno = l.mq_send(mq, table.concat({ ... }, " "), 42)
+
+print(r)
+
diff --git a/tests/test-syslog.lua b/tests/test-syslog.lua
new file mode 100644
index 0000000..c5d2c98
--- /dev/null
+++ b/tests/test-syslog.lua
@@ -0,0 +1,32 @@
+local l = require "luxio"
+
+math.randomseed(os.time())
+
+local f = io.open("/var/log/syslog", "r")
+if f == nil then
+ print "Need to read syslog, are you root?"
+ os.exit(1)
+end
+
+l.openlog("test-syslog", 0, l.LOG_DAEMON)
+
+local randomstrs = {}
+
+for i=1,10 do
+ randomstrs[i] = tostring(math.random(1, 1000))
+end
+
+local randomstr = table.concat(randomstrs)
+
+l.syslog(l.LOG_DAEMON, randomstr)
+l.closelog()
+
+local text = f:read("*all")
+
+s, e = string.find(text, randomstr)
+
+if string.sub(text, s, e) == randomstr then
+ print("TEST PASSES")
+else
+ print("TEST FAILS")
+end