Browse Source

Merge branch 'smartcom' into mm

Serj Kalichev 11 years ago
parent
commit
978a0e168e

+ 1 - 0
.gitignore

@@ -1,6 +1,7 @@
 .deps
 .dirstamp
 .libs
+.*.swp
 *.o
 *.lo
 *.la

+ 51 - 0
configure.ac

@@ -39,6 +39,57 @@ AC_ARG_ENABLE(debug,
               [enable_debug=no])
 AM_CONDITIONAL(DEBUG,test x$enable_debug = xyes)
 
+################################
+# Check for Lua support
+################################
+AC_ARG_WITH(lua,
+            [AS_HELP_STRING([--with-lua=DIR],
+                            [Build Lua ACTION plugin [default=no]])],
+            [use_lua=$withval],
+            [use_lua=no])
+AM_CONDITIONAL(WITH_LUA,test x$use_lua != xno)
+
+LUA_LDFLAGS=""
+LUA_CFLAGS=""
+LUA_LIBS=""
+
+if test x$use_lua = xyes; then
+    AC_CHECK_LIB([lua],
+                 [lua_close],
+                 [lua_lib_found=yes],
+                 [lua_lib_found=no],
+                 [])
+    if test x$lua_lib_found = xno; then
+        AC_MSG_ERROR([cannot find Lua library])
+    fi
+    LUA_LIBS="-llua -lm"
+    AC_CHECK_HEADER([lua.h],
+                    [lua_h_found=yes],
+                    [lua_h_found=no],
+                    [/* force include check */])
+    if test x$lua_h_found = xno; then
+        AC_MSG_ERROR([cannot find <lua.h> header file])
+    fi
+    AC_CHECK_HEADER([lualib.h],
+                    [lualib_h_found=yes],
+                    [lualib_h_found=no],
+                    [/* force include check */])
+    if test x$lualib_h_found = xno; then
+        AC_MSG_ERROR([cannot find <lualib.h> header file])
+    fi
+    AC_CHECK_HEADER([lauxlib.h],
+                    [lauxlib_h_found=yes],
+                    [lauxlib_h_found=no],
+                    [/* force include check */])
+    if test x$lauxlib_h_found = xno; then
+        AC_MSG_ERROR([cannot find <lauxlib.h> header file])
+    fi
+fi
+
+AC_SUBST(LUA_LDFLAGS)
+AC_SUBST(LUA_CFLAGS)
+AC_SUBST(LUA_LIBS)
+
 ################################
 # Check for the roxml library
 ################################

+ 60 - 0
plugins/lua/lua_action.c

@@ -0,0 +1,60 @@
+#include <stdlib.h>
+#include <sys/wait.h>
+
+#include <konf/buf.h>
+#include <lub/string.h>
+
+#include "private.h"
+
+static int exec_action(lua_State *L, const char *script)
+{
+	int res = 0;
+
+	if ((res = luaL_loadstring(L, script))) {
+		l_print_error(L, __func__, "load", res);
+	} else if ((res = lua_pcall(L, 0, 0, 0))) {
+		l_print_error(L, __func__, "exec", res);
+	}
+
+	lua_gc(L, LUA_GCCOLLECT, 0);
+
+	return res;
+}
+
+CLISH_PLUGIN_SYM(clish_plugin_lua_action)
+{
+	clish_shell_t *shell = clish_context__get_shell(clish_context);
+	lua_State *L = clish_shell__get_udata(shell, LUA_UDATA);
+	konf_buf_t *buf;
+	pid_t childpid;
+	int res = 0, origstdout = -1, fd[2];
+
+	if (!script) /* Nothing to do */
+		return (0);
+
+	if (!out) /* Handle trivial case */
+		return exec_action(L, script);
+
+	pipe(fd);
+
+	if ((childpid = fork()) == -1) {
+		perror("fork");
+		return -1;
+	}
+
+	if (childpid == 0) { /* Child */
+		dup2(fd[1], 1);
+		close(fd[0]);
+		close(fd[1]);
+		exit(exec_action(L, script));
+	} else { /* Parent */
+		close(fd[1]);
+		buf = konf_buf_new(fd[0]);
+		while(konf_buf_read(buf) > 0);
+		*out = konf_buf__dup_line(buf);
+		konf_buf_delete(buf);
+		close(fd[0]);
+	}
+
+	return WEXITSTATUS(res);
+}

+ 85 - 0
plugins/lua/lua_init.c

@@ -0,0 +1,85 @@
+#include <dirent.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <lub/string.h>
+
+#include "private.h"
+
+extern char *scripts_path = NULL;
+
+static bool_t
+load_scripts(lua_State *L, char *path)
+{
+	struct dirent *entry;
+	DIR *dir = opendir(path);
+	bool_t result = BOOL_FALSE;
+	int res = 0;
+
+	const char *ext_lua = ".lua";
+	const char *ext_bin = ".bin";
+
+	if (!dir) {
+		printf("%s: Failed to open '%s' directory\n", __func__, path);
+		return BOOL_FALSE;
+	}
+
+	for (entry = readdir(dir); entry; entry = readdir(dir)) {
+		const char *extension = strrchr(entry->d_name, '.');
+		/* check the filename */
+		if ((extension) &&
+		    ((!strcmp(ext_lua, extension)) ||
+		     (!strcmp(ext_bin, extension)))) {
+			char *filename = NULL;
+			lub_string_cat(&filename, path);
+			lub_string_cat(&filename, "/");
+			lub_string_cat(&filename, entry->d_name);
+
+			result = BOOL_FALSE;
+			if ((res = luaL_loadfile(L, filename))) {
+				l_print_error(L, __func__, "load", res);
+			} else if ((res = lua_pcall(L, 0, 0, 0))) {
+				l_print_error(L, __func__, "exec", res);
+			} else
+				result = BOOL_TRUE;
+
+			lub_string_free(filename);
+
+			/* Shouldn't happen, but we can't be too sure ;-) */
+			while(lua_gettop(L))
+				lua_pop(L, 1);
+
+			if (!result)
+				break;
+		}
+	}
+
+	closedir(dir);
+
+	return result;
+}
+
+int clish_plugin_init_lua(clish_shell_t *shell)
+{
+	lua_State *L = NULL;
+
+	if (!(L = luaL_newstate())) {
+		printf("%s: Failed to instantiate Lua interpreter\n", __func__);
+		return (-1);
+	}
+
+	luaL_openlibs(L);
+
+	if (scripts_path && !load_scripts(L, scripts_path)) {
+		free(scripts_path);
+		return (-1);
+	}
+	free(scripts_path);
+
+	clish_shell__set_udata(shell, LUA_UDATA, L);
+
+	lua_pushlightuserdata(L, shell);
+	lua_setglobal(L, "clish_shell");
+
+	return (0);
+}

+ 28 - 0
plugins/lua/lua_print_error.c

@@ -0,0 +1,28 @@
+#include "private.h"
+
+void
+l_print_error(lua_State *L, const char *func, const char *when, int res)
+{
+	switch (res) {
+		case LUA_ERRRUN:
+			printf("%s (%s):\n%s\n", func, when,
+					lua_tostring(L, -1));
+			break;
+		case LUA_ERRSYNTAX:
+			printf("%s (%s):\n%s\n", func, when,
+					lua_tostring(L, -1));
+			break;
+		case LUA_ERRMEM:
+			printf("%s (%s):\nmem alloc error\n", func, when);
+			break;
+		case LUA_ERRERR:
+			printf("%s (%s):\nerror handler error\n", func, when);
+			break;
+		case LUA_ERRFILE:
+			printf("%s (%s):\ncouldn't open file\n", func, when);
+			break;
+		default:
+			printf("%s (%s):\nunknown error\n", func, when);
+			break;
+	}
+}

+ 28 - 0
plugins/lua/module.am

@@ -0,0 +1,28 @@
+lib_LTLIBRARIES			+= clish_plugin_lua.la
+clish_plugin_lua_la_SOURCES	 = 
+clish_plugin_lua_la_LIBADD	 = @LUA_LIBS@
+clish_plugin_lua_la_LDFLAGS	 = -avoid-version -module -shared
+clish_plugin_lua_la_LDFLAGS	+= -export-symbols-regex "^clish_plugin_lua_"
+
+clish_plugin_lua_la_LDFLAGS	+= @LUA_LDFLAGS@
+clish_plugin_lua_la_CFLAGS	 = @LUA_CFLAGS@
+
+clish_plugin_lua_la_LIBADD	+= \
+	liblub.la \
+	libclish.la \
+	libkonf.la
+
+clish_plugin_lua_la_DEPENDENCIES = \
+	liblub.la \
+	libclish.la \
+	libkonf.la
+
+nobase_include_HEADERS		+= \
+	plugins/lua/private.h
+
+clish_plugin_lua_la_SOURCES	+= \
+	plugins/lua/plugin_init.c \
+	plugins/lua/plugin_fini.c \
+	plugins/lua/lua_init.c \
+	plugins/lua/lua_action.c \
+	plugins/lua/lua_print_error.c

+ 13 - 0
plugins/lua/plugin_fini.c

@@ -0,0 +1,13 @@
+#include <stdlib.h>
+
+#include "private.h"
+
+CLISH_PLUGIN_FINI
+{
+	lua_State *L = clish_shell__del_udata(clish_shell, LUA_UDATA);
+
+	if (L)
+		lua_close(L);
+
+	return (0);
+}

+ 42 - 0
plugins/lua/plugin_init.c

@@ -0,0 +1,42 @@
+#include <string.h>
+
+#include "private.h"
+
+static char * trim(char *str)
+{
+	size_t len = 0;
+	const char *first = str;
+	char *last = str + strlen(str) - 1;
+	char *new = NULL;
+	int i = 0;
+
+	while (first < last && isspace(*first))
+		++first;
+	while (first < last && isspace(*last))
+		--last;
+
+	len = last - first + 1;
+	new = malloc(len + 1);
+	memcpy(new, first, len);
+	new[len] = '\0';
+
+	return new;
+}
+
+CLISH_PLUGIN_INIT
+{
+	char *conf = clish_plugin__get_conf(plugin);
+
+	if (conf) {
+		scripts_path = trim(conf);
+	}
+
+	if(clish_plugin_init_lua(clish_shell))
+		return (-1);
+
+	clish_plugin__set_name(plugin, "lua_hooks");
+
+	clish_plugin_add_sym(plugin, clish_plugin_lua_action, "hook_action");
+
+	return 0;
+}

+ 18 - 0
plugins/lua/private.h

@@ -0,0 +1,18 @@
+#ifndef _PLUGIN_H_
+#define _PLUGIN_H_
+
+#include <clish/shell.h>
+
+#include <lua.h>
+#include <lualib.h>
+#include <lauxlib.h>
+
+#define LUA_UDATA	"lua state"
+
+extern char *scripts_path;
+void l_print_error(lua_State *, const char *, const char *, int);
+int clish_plugin_init_lua(clish_shell_t *shell);
+
+CLISH_PLUGIN_SYM(clish_plugin_lua_action);
+
+#endif /* _PLUGIN_H_ */

+ 4 - 0
plugins/module.am

@@ -1,6 +1,10 @@
 ## Process this file with automake to produce Makefile.in
 
 EXTRA_DIST += \
+	plugins/lua/module.am \
 	plugins/default/module.am
 
 include $(top_srcdir)/plugins/default/module.am
+if WITH_LUA
+include $(top_srcdir)/plugins/lua/module.am
+endif

+ 13 - 0
xml-examples/lua/startup.xml

@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CLISH_MODULE xmlns="http://clish.sourceforge.net/XMLSchema" 
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+ xsi:schemaLocation="http://clish.sourceforge.net/XMLSchema
+                     http://clish.sourceforge.net/XMLSchema/clish.xsd">
+
+     <PLUGIN name="lua_hooks" file="clish_plugin_lua.so">
+	 /usr2/klish-rw/xml-examples/lua
+     </PLUGIN>
+     <STARTUP view="test-view" default_builtin="hook_action@lua_hooks"/>
+
+</CLISH_MODULE>
+

+ 7 - 0
xml-examples/lua/test.lua

@@ -0,0 +1,7 @@
+echo = print
+
+shell = os.execute
+
+function hello_world()
+	print("Hello world from Lua!")
+end

+ 98 - 0
xml-examples/lua/test.xml

@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CLISH_MODULE xmlns="http://clish.sourceforge.net/XMLSchema" 
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+ xsi:schemaLocation="http://clish.sourceforge.net/XMLSchema
+                     http://clish.sourceforge.net/XMLSchema/clish.xsd">
+	<!--=======================================================-->
+
+<PTYPE name="STRING" pattern=".+" help="String"/>
+
+<VIEW name="test-view"
+	prompt="${SYSTEM_NAME}# ">
+
+	<COMMAND name="exit" help="Exit from the CLI" lock="false">
+		<ACTION builtin="clish_close"/>
+	</COMMAND>
+
+	<COMMAND name="test1" help="" lock="false">
+		<ACTION> echo "Empty attribute" </ACTION>
+	</COMMAND>
+
+	<COMMAND name="test2" help='Single quotes' lock="false">
+		<ACTION> echo "Single quotes" </ACTION>
+	</COMMAND>
+
+	<COMMAND name="test3" help='"Single quotes with nested common quotes"' lock="false">
+		<ACTION> echo "Single quotes with nested common quotes" </ACTION>
+	</COMMAND>
+
+	<COMMAND name="test4" help="'Common quotes with nested single quotes'" lock="false">
+		<ACTION> echo "Common quotes with nested single quotes" </ACTION>
+	</COMMAND>
+
+	<COMMAND name="test5" help="Broken comment. Problem with libroxml.">
+<!-- - '
+-->
+		<PARAM name="test5.param2" help="Help test5.param2" ptype="STRING" optional="true" order="true"/>
+		<ACTION> echo "Broken comment. Problem with libroxml." </ACTION>
+	</COMMAND>
+
+	<COMMAND name="test6" help="Long ACTION. libexpat hangs">
+		<ACTION>
+			shell [[
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+			]]
+		</ACTION>
+	</COMMAND>
+
+	<COMMAND help="The > within attribute value" name="test7" lock="false">
+		<ACTION> echo "The > within attribute value" </ACTION>
+	</COMMAND>
+
+	<COMMAND name="test8" help="Call a Lua function">
+		<ACTION builtin="hook_action@lua_hooks">hello_world()</ACTION>
+	</COMMAND>
+
+	<COMMAND name="eval" help="Evaluate a string as Lua chunk">
+		<PARAM name="str" help="String to evaluate" ptype="STRING"/>
+		<ACTION builtin="hook_action@lua_hooks">
+			loadstring("${str}")()
+		</ACTION>
+	</COMMAND>
+
+	<COMMAND name="test9" ref="eval" help="Alias for the eval command"/>
+
+</VIEW>
+
+</CLISH_MODULE>