Browse Source

Add hooks

Serj Kalichev 11 years ago
parent
commit
6245456c58

+ 3 - 13
bin/clish.c

@@ -34,16 +34,6 @@
 /* #define version(v) printf("%s\n", QUOTE(v)) */
 #define version(v) printf("%s\n", v)
 
-/* Hooks */
-static clish_shell_hooks_t my_hooks = {
-    NULL, /* don't worry about init callback */
-    clish_access_callback,
-    NULL, /* don't worry about cmd_line callback */
-    NULL, /* don't worry about fini callback */
-    clish_config_callback,
-    clish_log_callback
-};
-
 static void help(int status, const char *argv0);
 
 /*--------------------------------------------------------- */
@@ -172,8 +162,8 @@ int main(int argc, char **argv)
 		case 'k':
 			lockless = BOOL_TRUE;
 			dryrun = BOOL_TRUE;
-			my_hooks.config_fn = NULL;
-			break;
+/*			my_hooks.config_fn = NULL;
+*/			break;
 		case 't':
 			istimeout = BOOL_TRUE;
 			timeout = atoi(optarg);
@@ -227,7 +217,7 @@ int main(int argc, char **argv)
 	/* Create shell instance */
 	if (quiet)
 		outfd = fopen("/dev/null", "w");
-	shell = clish_shell_new(&my_hooks, NULL, NULL, outfd, stop_on_error);
+	shell = clish_shell_new(NULL, NULL, outfd, stop_on_error);
 	if (!shell) {
 		fprintf(stderr, "Error: Can't run clish.\n");
 		goto end;

+ 36 - 0
clish/builtin/builtin_init.c

@@ -0,0 +1,36 @@
+/*
+ * builtin_init.c
+ */
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "clish/plugin.h"
+#include "private.h"
+
+/*----------------------------------------------------------- */
+/* Initialize internal pseudo-plugin */
+CLISH_PLUGIN_INIT
+{
+	/* Add hooks */
+	clish_plugin_add_hook(plugin, clish_hook_access,
+		"clish_hook_access", CLISH_SYM_TYPE_ACCESS);
+	clish_plugin_add_hook(plugin, clish_hook_config,
+		"clish_hook_config", CLISH_SYM_TYPE_CONFIG);
+	clish_plugin_add_hook(plugin, clish_hook_log,
+		"clish_hook_log", CLISH_SYM_TYPE_LOG);
+
+	/* Add builtin syms */
+	clish_plugin_add_psym(plugin, clish_close, "clish_close");
+	clish_plugin_add_psym(plugin, clish_overview, "clish_overview");
+	clish_plugin_add_psym(plugin, clish_source, "clish_source");
+	clish_plugin_add_psym(plugin, clish_source_nostop, "clish_source_nostop");
+	clish_plugin_add_psym(plugin, clish_history, "clish_history");
+	clish_plugin_add_psym(plugin, clish_nested_up, "clish_nested_up");
+	clish_plugin_add_psym(plugin, clish_nop, "clish_nop");
+	clish_plugin_add_psym(plugin, clish_wdog, "clish_wdog");
+	clish_plugin_add_sym(plugin, clish_script, "clish_script");
+
+	return 0;
+}
+
+/*----------------------------------------------------------- */

+ 2 - 2
clish/callback_access.c → clish/builtin/hook_access.c

@@ -22,10 +22,10 @@
 
 #include "lub/string.h"
 #include "lub/db.h"
-#include "internal.h"
+#include "clish/shell.h"
 
 /*--------------------------------------------------------- */
-bool_t clish_access_callback(const clish_shell_t * shell, const char *access)
+CLISH_HOOK_ACCESS(clish_hook_access)
 {
 	bool_t allowed = BOOL_FALSE; /* assume the user is not allowed */
 #ifdef HAVE_GRP_H

+ 3 - 2
clish/callback_config.c → clish/builtin/hook_config.c

@@ -14,11 +14,11 @@
 #include <limits.h>
 #include <string.h>
 
-#include "internal.h"
 #include "konf/net.h"
 #include "konf/buf.h"
 #include "konf/query.h"
 #include "lub/string.h"
+#include "clish/shell.h"
 
 static int send_request(konf_client_t * client, char *command);
 
@@ -45,8 +45,9 @@ static unsigned short str2ushort(const char *str)
 }
 
 /*--------------------------------------------------------- */
-bool_t clish_config_callback(clish_context_t *context)
+CLISH_HOOK_CONFIG(clish_hook_config)
 {
+	clish_context_t *context = (clish_context_t *)clish_context;
 	clish_shell_t *this = context->shell;
 	const clish_command_t *cmd = context->cmd;
 	clish_config_t *config;

+ 3 - 3
clish/callback_log.c → clish/builtin/hook_log.c

@@ -9,15 +9,15 @@
 #include <sys/types.h>
 #include <pwd.h>
 
-#include "internal.h"
+#include "clish/shell.h"
 
 #define SYSLOG_IDENT "klish"
 #define SYSLOG_FACILITY LOG_LOCAL0
 
 /*--------------------------------------------------------- */
-int clish_log_callback(clish_context_t *context, const char *line,
-	int retcode)
+CLISH_HOOK_LOG(clish_hook_log)
 {
+	clish_context_t *context = (clish_context_t *)clish_context;
 	clish_shell_t *this = context->shell;
 	struct passwd *user = NULL;
 	char *uname = "unknown";

+ 8 - 0
clish/builtin/module.am

@@ -0,0 +1,8 @@
+libclish_la_SOURCES += \
+	clish/builtin/builtin_init.c \
+	clish/builtin/hook_access.c \
+	clish/builtin/hook_config.c \
+	clish/builtin/hook_log.c \
+	clish/builtin/sym_navy.c \
+	clish/builtin/sym_script.c
+

+ 23 - 0
clish/builtin/private.h

@@ -0,0 +1,23 @@
+/*
+ * builtin private.h
+ */
+
+#include "clish/plugin.h"
+#include "clish/shell.h"
+#include "clish/shell/private.h"
+
+/* Hooks */
+CLISH_HOOK_ACCESS(clish_hook_access);
+CLISH_HOOK_CONFIG(clish_hook_config);
+CLISH_HOOK_LOG(clish_hook_log);
+
+/* Navy syms */
+CLISH_PLUGIN_SYM(clish_close);
+CLISH_PLUGIN_SYM(clish_source);
+CLISH_PLUGIN_SYM(clish_source_nostop);
+CLISH_PLUGIN_SYM(clish_overview);
+CLISH_PLUGIN_SYM(clish_history);
+CLISH_PLUGIN_SYM(clish_nested_up);
+CLISH_PLUGIN_SYM(clish_nop);
+CLISH_PLUGIN_SYM(clish_wdog);
+CLISH_PLUGIN_SYM(clish_script);

+ 1 - 18
clish/shell/shell_internal.c → clish/builtin/sym_navy.c

@@ -1,5 +1,5 @@
 /*
- * shell_internal.c
+ * sym_navy.c
  */
 #include "private.h"
 #include "lub/string.h"
@@ -184,20 +184,3 @@ CLISH_PLUGIN_SYM(clish_wdog)
 }
 
 /*----------------------------------------------------------- */
-/* Initialize internal pseudo-plugin */
-CLISH_PLUGIN_INIT
-{
-	clish_plugin_add_psym(plugin, clish_close, "clish_close");
-	clish_plugin_add_psym(plugin, clish_overview, "clish_overview");
-	clish_plugin_add_psym(plugin, clish_source, "clish_source");
-	clish_plugin_add_psym(plugin, clish_source_nostop, "clish_source_nostop");
-	clish_plugin_add_psym(plugin, clish_history, "clish_history");
-	clish_plugin_add_psym(plugin, clish_nested_up, "clish_nested_up");
-	clish_plugin_add_psym(plugin, clish_nop, "clish_nop");
-	clish_plugin_add_psym(plugin, clish_wdog, "clish_wdog");
-	clish_plugin_add_sym(plugin, clish_script, "clish_script");
-
-	return 0;
-}
-
-/*----------------------------------------------------------- */

+ 1 - 1
clish/shell/shell_script.c → clish/builtin/sym_script.c

@@ -1,5 +1,5 @@
 /*
- * shell_script.c
+ * sym_script.c
  *
  * Function to execute a shell script.
  */

+ 0 - 22
clish/internal.h

@@ -1,22 +0,0 @@
-/*
- * internal.h
- */
-#ifndef _clish_internal_h
-#define _clish_internal_h
-
-#include "lub/c_decl.h"
-#include "clish/shell.h"
-
-_BEGIN_C_DECL
-
-/* storage */
-extern struct termios clish_default_tty_termios;
-
-/* Standard clish callback functions */
-extern clish_shell_access_fn_t clish_access_callback;
-extern clish_shell_config_fn_t clish_config_callback;
-extern clish_shell_log_fn_t clish_log_callback;
-
-_END_C_DECL
-
-#endif /* _clish_internal_h */

+ 3 - 5
clish/module.am

@@ -2,9 +2,6 @@
 lib_LTLIBRARIES += libclish.la
 
 libclish_la_SOURCES = \
-    clish/callback_access.c \
-    clish/callback_config.c \
-    clish/callback_log.c \
     clish/private.h
 
 libclish_la_LDFLAGS = @XML_LDFLAGS@
@@ -31,8 +28,7 @@ nobase_include_HEADERS += \
 	clish/action.h \
 	clish/config.h \
 	clish/hotkey.h \
-	clish/plugin.h \
-	clish/internal.h
+	clish/plugin.h
 
 EXTRA_DIST += \
 	clish/command/module.am \
@@ -47,6 +43,7 @@ EXTRA_DIST += \
 	clish/config/module.am \
 	clish/hotkey/module.am \
 	clish/plugin/module.am \
+	clish/builtin/module.am \
 	clish/README
 
 include $(top_srcdir)/clish/command/module.am
@@ -61,3 +58,4 @@ include $(top_srcdir)/clish/action/module.am
 include $(top_srcdir)/clish/config/module.am
 include $(top_srcdir)/clish/hotkey/module.am
 include $(top_srcdir)/clish/plugin/module.am
+include $(top_srcdir)/clish/builtin/module.am

+ 37 - 11
clish/plugin.h

@@ -9,13 +9,16 @@
 /* Symbol */
 
 /* Symbol types. Functions with different definition. */
-#define CLISH_SYM_TYPE_NONE	0 /* None */
-#define CLISH_SYM_TYPE_FN	1 /* Common builtin symbol */
-#define CLISH_SYM_TYPE_INIT	2
-#define CLISH_SYM_TYPE_FINI	3
-#define CLISH_SYM_TYPE_ACCESS	4
-#define CLISH_SYM_TYPE_CONFIG	5
-#define CLISH_SYM_TYPE_LOG	6
+typedef enum {
+	CLISH_SYM_TYPE_NONE = 0, /* None */
+	CLISH_SYM_TYPE_ACTION, /* Common builtin symbol */
+	CLISH_SYM_TYPE_INIT,
+	CLISH_SYM_TYPE_FINI,
+	CLISH_SYM_TYPE_ACCESS,
+	CLISH_SYM_TYPE_CONFIG,
+	CLISH_SYM_TYPE_LOG,
+	CLISH_SYM_TYPE_MAX /* Number of elements */
+} clish_sym_type_e;
 
 typedef struct clish_sym_s clish_sym_t;
 typedef struct clish_plugin_s clish_plugin_t;
@@ -27,11 +30,32 @@ typedef struct clish_plugin_s clish_plugin_t;
 #define CLISH_PLUGIN_INIT_NAME "clish_plugin_init"
 #define CLISH_PLUGIN_INIT_FUNC(name) int name(clish_plugin_t *plugin)
 #define CLISH_PLUGIN_INIT CLISH_PLUGIN_INIT_FUNC(CLISH_PLUGIN_INIT_FNAME)
+
 #define CLISH_PLUGIN_SYM(name) int name(void *clish_context, const char *script, char **out)
+#define CLISH_HOOK_INIT(name) int name(void *clish_context)
+#define CLISH_HOOK_FINI(name) int name(void *clish_context)
+#define CLISH_HOOK_ACCESS(name) int name(void *clish_context, const char *access)
+#define CLISH_HOOK_CONFIG(name) int name(void *clish_context)
+#define CLISH_HOOK_LOG(name) int name(void *clish_context, const char *line, int retcode)
+
+/* Default syms */
 #define CLISH_DEFAULT_SYM "clish_script@clish" /* Builtin symbol to use by default */
+#define CLISH_DEFAULT_ACCESS "clish_hook_access@clish"
+#define CLISH_DEFAULT_CONFIG "clish_hook_config@clish"
+#define CLISH_DEFAULT_LOG "clish_hook_log@clish"
+
+/* typedef void clish_shell_cmd_line_fn_t(clish_context_t *context, const char *cmd_line); */
 
-typedef CLISH_PLUGIN_SYM(clish_plugin_fn_t);
 typedef CLISH_PLUGIN_INIT_FUNC(clish_plugin_init_t);
+typedef CLISH_PLUGIN_SYM(clish_hook_action_fn_t);
+typedef CLISH_HOOK_INIT(clish_hook_init_fn_t);
+typedef CLISH_HOOK_FINI(clish_hook_fini_fn_t);
+typedef CLISH_HOOK_ACCESS(clish_hook_access_fn_t);
+typedef CLISH_HOOK_CONFIG(clish_hook_config_fn_t);
+typedef CLISH_HOOK_LOG(clish_hook_log_fn_t);
+
+/* Helpers */
+#define SYM_FN(TYPE,SYM) (*((clish_hook_##TYPE##_fn_t *)(clish_sym__get_func(SYM))))
 
 /* Symbol */
 
@@ -39,7 +63,7 @@ int clish_sym_compare(const void *first, const void *second);
 clish_sym_t *clish_sym_new(const char *name, void *func, int type);
 void clish_sym_free(clish_sym_t *instance);
 void clish_sym__set_func(clish_sym_t *instance, void *func);
-clish_plugin_fn_t *clish_sym__get_func(clish_sym_t *instance);
+void *clish_sym__get_func(clish_sym_t *instance);
 void clish_sym__set_name(clish_sym_t *instance, const char *name);
 char *clish_sym__get_name(clish_sym_t *instance);
 void clish_sym__set_permanent(clish_sym_t *instance, bool_t permanent);
@@ -60,9 +84,11 @@ clish_sym_t *clish_plugin_get_sym(clish_plugin_t *instance,
 clish_sym_t *clish_plugin_add_generic(clish_plugin_t *instance,
 	void *func, const char *name, int type);
 clish_sym_t *clish_plugin_add_sym(clish_plugin_t *instance,
-	clish_plugin_fn_t *func, const char *name);
+	clish_hook_action_fn_t *func, const char *name);
 clish_sym_t *clish_plugin_add_psym(clish_plugin_t *instance,
-	clish_plugin_fn_t *func, const char *name);
+	clish_hook_action_fn_t *func, const char *name);
+clish_sym_t *clish_plugin_add_hook(clish_plugin_t *instance,
+	void *func, const char *name, int type);
 void clish_plugin_dump(const clish_plugin_t *instance);
 char *clish_plugin__get_name(const clish_plugin_t *instance);
 char *clish_plugin__get_file(const clish_plugin_t *instance);

+ 12 - 4
clish/plugin/plugin.c

@@ -54,7 +54,7 @@ void clish_sym__set_func(clish_sym_t *this, void *func)
 }
 
 /*--------------------------------------------------------- */
-clish_plugin_fn_t *clish_sym__get_func(clish_sym_t *this)
+void *clish_sym__get_func(clish_sym_t *this)
 {
 	return this->func;
 }
@@ -193,16 +193,24 @@ clish_sym_t *clish_plugin_add_generic(clish_plugin_t *this,
 
 /*--------------------------------------------------------- */
 clish_sym_t *clish_plugin_add_sym(clish_plugin_t *this,
-	clish_plugin_fn_t *func, const char *name)
+	clish_hook_action_fn_t *func, const char *name)
 {
 	return clish_plugin_add_generic(this, func,
-		name, CLISH_SYM_TYPE_FN);
+		name, CLISH_SYM_TYPE_ACTION);
+}
+
+/*--------------------------------------------------------- */
+clish_sym_t *clish_plugin_add_hook(clish_plugin_t *this,
+	void *func, const char *name, int type)
+{
+	return clish_plugin_add_generic(this, func,
+		name, type);
 }
 
 /*--------------------------------------------------------- */
 /* Add permanent symbol (can't be turned off by dry-run) */
 clish_sym_t *clish_plugin_add_psym(clish_plugin_t *this,
-	clish_plugin_fn_t *func, const char *name)
+	clish_hook_action_fn_t *func, const char *name)
 {
 	clish_sym_t *sym;
 

+ 2 - 2
clish/plugin/plugin_dump.c

@@ -22,8 +22,8 @@ void clish_sym_dump(const clish_sym_t *this)
 	case CLISH_SYM_TYPE_NONE:
 		type = "none";
 		break;
-	case CLISH_SYM_TYPE_FN:
-		type = "fn";
+	case CLISH_SYM_TYPE_ACTION:
+		type = "action";
 		break;
 	case CLISH_SYM_TYPE_INIT:
 		type = "init";

+ 1 - 130
clish/shell.h

@@ -61,140 +61,11 @@ typedef enum {
 
 _BEGIN_C_DECL
 
-/*=====================================
- * SHELL INTERFACE
- *===================================== */
- /**
-  * A hook function used during the spawning of a new shell.
-  * 
-  * This will be invoked from the context of the spawned shell's thread
-  * and will be invoked just after the shell instance is created.
-  *
-  * This enables the client-specific initialisation of the spawned shell's
-  * thread
-  * e.g. to map the I/O streams, authenticate a user.
-  *
-  * N.B. It is possible for a client to have this invoked multiple times 
-  * if the user is spawning new shells using a commmand which uses the 
-  * "clish_spawn" builtin function. Hence the client should remember the 
-  * shell which first calls this function, and only assign resource (e.g. 
-  * setting up a script interpreter) for that call.
-  *
-  * \return
-  * - BOOL_TRUE if everything is OK
-  * - BOOL_FALSE if the shell should be immediately shut down.
-  *
-  */
-typedef bool_t clish_shell_init_fn_t(
-	/** 
-         * The shell instance which invoked this call
-         */
-					    const clish_shell_t * shell);
-
- /**
-  * A hook function used during the shutting down of a spawned shell
-  * 
-  * This will be invoked from the context of the spawned shell's thread
-  * and will be invoked just before the shell is destroyed.
-  *
-  * This enables the client-specific finalisation to occur.
-  * e.g. releasing any resource held by the cookie,
-  * shutting down telnet connections
-  *
-  * NB. This function may be called multiple times if a user is spawning
-  * new commands (via the "clish_spawn" builtin command), hence should use
-  * the reference to the root shell (remembered by the first call to clish_shell_init_fn_t callback)
-  * to signal when the cleanup should occur.
-  */
-typedef void clish_shell_fini_fn_t(
-	/** 
-         * The shell instance which invoked this call
-         */
-					  const clish_shell_t * shell);
-
- /**
-  * A hook function used to indicate a command line has been executed and the 
-  * shell is about to prompt for the next command.
-  * 
-  * This will be invoked from the context of the spawned shell's thread
-  * and will be called once an ACTION has been performed.
-  * 
-  * A client may use this as a periodic indicator of CLI activity, 
-  * e.g. to manage session timeouts. In addition any required logging of 
-  * commands may be performed.
-  */
-typedef void clish_shell_cmd_line_fn_t(
-	/** 
-         * The shell instance which invoked this call
-         */
-					      clish_context_t *context,
-	/** 
-         * The text of the command line entered
-         */
-					      const char *cmd_line);
-
-/**
-  * A hook function used to control config file write
-  * 
-  */
-typedef bool_t clish_shell_config_fn_t(
-	clish_context_t *context);
-
- /**
-  * A hook function used to control access for the current user.
-  * 
-  * This will be invoked from the context of the spawned shell's thread
-  * and will be called during the parsing of the XML files.
-  * 
-  * The clish component will only insert a command into a view if the access 
-  * call is sucessfull.
-  *
-  * The client may choose to implement invocation of the script in a number of
-  * ways, which may include forking a sub-process or thread. It is important 
-  * that the call doesn't return until the script has been fully evaluated.
-  *
-  * \return
-  * - BOOL_TRUE  - if the user of the current CLISH session is permitted access
-  * - BOOL_FALSE - if the user of the current CLISH session is not permitted access
-  *
-  * \post
-  * - If access is granted then the associated command will be inserted into the
-  *   appropriate view.
-  */
-typedef bool_t clish_shell_access_fn_t(
-	/** 
-         * The shell instance which invoked this call
-         */
-					      const clish_shell_t * instance,
-	/**
-         * A textual string which describes a limitation for a command. This
-         * string typically may be the name of a user group, of which the
-         * current user must be a member to grant access to a command.  
-         */
-					      const char *access);
-typedef int clish_shell_log_fn_t(
-	clish_context_t *context,
-	const char *line, int retcode);
-
-/** 
- * A client of libclish will provide hooks for the control of the CLI within 
- * a particular system.
- * They will populate an instance of this structure and pass it into the 
- */
-typedef struct {
-	clish_shell_init_fn_t *init_fn;         /* Initialisation call */
-	clish_shell_access_fn_t *access_fn;     /* Access control call */
-	clish_shell_cmd_line_fn_t *cmd_line_fn; /* Command line logging call */
-	clish_shell_fini_fn_t *fini_fn;         /* Finalization call */
-	clish_shell_config_fn_t *config_fn;     /* Config call */
-	clish_shell_log_fn_t *log_fn;           /* Logging call */
-} clish_shell_hooks_t;
-
 /*-----------------
  * meta functions
  *----------------- */
 
-clish_shell_t *clish_shell_new(const clish_shell_hooks_t * hooks,
+clish_shell_t *clish_shell_new(
 	void *cookie,
 	FILE * istream,
 	FILE * ostream,

+ 0 - 2
clish/shell/module.am

@@ -5,8 +5,6 @@ libclish_la_SOURCES += \
 	clish/shell/shell_command.c \
 	clish/shell/shell_dump.c \
 	clish/shell/shell_execute.c \
-	clish/shell/shell_internal.c \
-	clish/shell/shell_script.c \
 	clish/shell/shell_help.c \
 	clish/shell/shell_new.c \
 	clish/shell/shell_parse.c \

+ 10 - 2
clish/shell/private.h

@@ -44,7 +44,16 @@ struct clish_shell_s {
 	lub_bintree_t view_tree; /* Tree of views */
 	lub_bintree_t ptype_tree; /* Tree of ptypes */
 	lub_bintree_t var_tree; /* Tree of global variables */
-	const clish_shell_hooks_t *hooks; /* Client callback hooks */
+
+	/* Hooks */
+	clish_sym_t *hooks[CLISH_SYM_TYPE_MAX]; /* Callback hooks */
+#define hooks_fn hooks[CLISH_SYM_TYPE_ACTION]
+#define hooks_init hooks[CLISH_SYM_TYPE_INIT]
+#define hooks_fini hooks[CLISH_SYM_TYPE_FINI]
+#define hooks_access hooks[CLISH_SYM_TYPE_ACCESS]
+#define hooks_config hooks[CLISH_SYM_TYPE_CONFIG]
+#define hooks_log hooks[CLISH_SYM_TYPE_LOG]
+
 	void *client_cookie; /* Client callback cookie */
 	clish_view_t *global; /* Reference to the global view. */
 	clish_command_t *startup; /* This is the startup command */
@@ -76,7 +85,6 @@ struct clish_shell_s {
 	/* Plugins and symbols */
 	lub_list_t *plugins; /* List of plugins */
 	lub_list_t *syms; /* List of all used symbols. Must be resolved. */
-	clish_sym_t *default_sym; /* The sym to use when builtin is not specified */
 
 	/* Static params for var expanding. The refactoring is needed. */
 	clish_param_t *param_depth;

+ 5 - 5
clish/shell/shell_execute.c

@@ -149,13 +149,13 @@ int clish_shell_execute(clish_context_t *context, char **out)
 	}
 
 	/* Call config callback */
-	if (!result && this->hooks->config_fn)
-		this->hooks->config_fn(context);
+	if (!result && this->hooks_config)
+		SYM_FN(config,this->hooks_config)(context);
 
 	/* Call logging callback */
-	if (clish_shell__get_log(this) && this->hooks->log_fn) {
+	if (clish_shell__get_log(this) && this->hooks_log) {
 		char *full_line = clish_shell__get_full_line(context);
-		this->hooks->log_fn(context, full_line, result);
+		SYM_FN(log,this->hooks_log)(context, full_line, result);
 		lub_string_free(full_line);
 	}
 
@@ -196,7 +196,7 @@ int clish_shell_exec_action(clish_context_t *context, char **out)
 	int result = -1;
 	clish_sym_t *sym;
 	char *script;
-	clish_plugin_fn_t *func = NULL;
+	clish_hook_action_fn_t *func = NULL;
 	const clish_action_t *action = context->action;
 	clish_shell_t *shell = context->shell;
 

+ 20 - 15
clish/shell/shell_new.c

@@ -15,7 +15,6 @@
 
 /*-------------------------------------------------------- */
 static void clish_shell_init(clish_shell_t * this,
-	const clish_shell_hooks_t * hooks,
 	void *cookie, FILE * istream,
 	FILE * ostream,
 	bool_t stop_on_error)
@@ -47,14 +46,20 @@ static void clish_shell_init(clish_shell_t * this,
 	/* Initialise the list of unresolved (yet) symbols */
 	this->syms = lub_list_new(clish_sym_compare);
 
-	/* Add default syms and save them to shell structure */
-	this->default_sym = clish_sym_new(
-		CLISH_DEFAULT_SYM, NULL, CLISH_SYM_TYPE_FN);
-
-	assert(NULL != hooks);
+	/* Default syms and hooks */
+	this->hooks[CLISH_SYM_TYPE_NONE] = NULL;
+	this->hooks[CLISH_SYM_TYPE_ACTION] = clish_sym_new(
+		CLISH_DEFAULT_SYM, NULL, CLISH_SYM_TYPE_ACTION);
+	this->hooks[CLISH_SYM_TYPE_INIT] = NULL;
+	this->hooks[CLISH_SYM_TYPE_FINI] = NULL;
+	this->hooks[CLISH_SYM_TYPE_ACCESS] = clish_sym_new(
+		CLISH_DEFAULT_ACCESS, NULL, CLISH_SYM_TYPE_ACCESS);
+	this->hooks[CLISH_SYM_TYPE_CONFIG] = clish_sym_new(
+		CLISH_DEFAULT_CONFIG, NULL, CLISH_SYM_TYPE_CONFIG);
+	this->hooks[CLISH_SYM_TYPE_LOG] = clish_sym_new(
+		CLISH_DEFAULT_LOG, NULL, CLISH_SYM_TYPE_LOG);
 
 	/* set up defaults */
-	this->hooks = hooks;
 	this->client_cookie = cookie;
 	this->global = NULL;
 	this->startup = NULL;
@@ -192,7 +197,7 @@ static void clish_shell_fini(clish_shell_t * this)
 }
 
 /*-------------------------------------------------------- */
-clish_shell_t *clish_shell_new(const clish_shell_hooks_t * hooks,
+clish_shell_t *clish_shell_new(
 	void *cookie,
 	FILE * istream,
 	FILE * ostream,
@@ -201,13 +206,13 @@ clish_shell_t *clish_shell_new(const clish_shell_hooks_t * hooks,
 	clish_shell_t *this = malloc(sizeof(clish_shell_t));
 
 	if (this) {
-		clish_shell_init(this, hooks, cookie,
+		clish_shell_init(this, cookie,
 			istream, ostream, stop_on_error);
-		if (hooks->init_fn) {
+//		if (hooks->init_fn) {
 			/* now call the client initialisation */
-			if (BOOL_TRUE != hooks->init_fn(this))
-				this->state = SHELL_STATE_CLOSING;
-		}
+//			if (BOOL_TRUE != hooks->init_fn(this))
+//				this->state = SHELL_STATE_CLOSING;
+//		}
 	}
 
 	return this;
@@ -217,8 +222,8 @@ clish_shell_t *clish_shell_new(const clish_shell_hooks_t * hooks,
 void clish_shell_delete(clish_shell_t * this)
 {
 	/* now call the client finalisation */
-	if (this->hooks->fini_fn)
-		this->hooks->fini_fn(this);
+	if (this->hooks[CLISH_SYM_TYPE_FINI])
+		SYM_FN(fini,this->hooks_fini)(this);
 	clish_shell_fini(this);
 
 	free(this);

+ 2 - 2
clish/shell/shell_startup.c

@@ -25,8 +25,8 @@ int clish_shell_startup(clish_shell_t *this)
 	context.pargv = NULL;
 	
 	/* Call log initialize */
-	if (clish_shell__get_log(this) && this->hooks->log_fn)
-		this->hooks->log_fn(&context, NULL, 0);
+	if (clish_shell__get_log(this) && this->hooks_log)
+		SYM_FN(log,this->hooks_log)(&context, NULL, 0);
 	/* Call startup script */
 	res = clish_shell_execute(&context, NULL);
 

+ 2 - 2
clish/shell/shell_tinyrl.c

@@ -523,8 +523,8 @@ static int clish_shell_execline(clish_shell_t *this, const char *line, char **ou
 		tinyrl_history_add(history, str);
 	}
 	/* Let the client know the command line has been entered */
-	if (this->hooks->cmd_line_fn)
-		this->hooks->cmd_line_fn(&context, str);
+//	if (this->hooks->cmd_line_fn)
+//		this->hooks->cmd_line_fn(&context, str);
 	free(str);
 
 	/* Execute the provided command */

+ 87 - 31
clish/shell/shell_xml.c

@@ -47,7 +47,8 @@ static PROCESS_FN
 	process_var,
 	process_wdog,
 	process_hotkey,
-	process_plugin;
+	process_plugin,
+	process_hook;
 
 static clish_xml_cb_t xml_elements[] = {
 	{"CLISH_MODULE", process_clish_module},
@@ -65,6 +66,7 @@ static clish_xml_cb_t xml_elements[] = {
 	{"WATCHDOG", process_wdog},
 	{"HOTKEY", process_hotkey},
 	{"PLUGIN", process_plugin},
+	{"HOOK", process_hook},
 	{NULL, NULL}
 };
 
@@ -81,6 +83,7 @@ int clish_shell_load_scheme(clish_shell_t *this, const char *xml_path)
 	char *dirname;
 	char *saveptr;
 	int res = 0;
+	int i = 0;
 
 	/* use the default path */
 	if (!path)
@@ -140,7 +143,10 @@ int clish_shell_load_scheme(clish_shell_t *this, const char *xml_path)
 	lub_string_free(buffer);
 
 	/* Add default syms to unresolved table */
-	lub_list_add(this->syms, this->default_sym);
+	for (i = 0; i < CLISH_SYM_TYPE_MAX; i++) {
+		if (this->hooks[i])
+			lub_list_add(this->syms, this->hooks[i]);
+	}
 
 #ifdef DEBUG
 	clish_shell_dump(this);
@@ -274,7 +280,7 @@ process_clish_module(clish_shell_t * shell, clish_xmlnode_t * element, void *par
 static int process_view(clish_shell_t * shell, clish_xmlnode_t * element, void *parent)
 {
 	clish_view_t *view;
-	int allowed = 1;
+//	int allowed = 1;
 	int res = -1;
 
 	char *name = clish_xmlnode_fetch_attr(element, "name");
@@ -284,13 +290,13 @@ static int process_view(clish_shell_t * shell, clish_xmlnode_t * element, void *
 	char *access = clish_xmlnode_fetch_attr(element, "access");
 
 	/* Check permissions */
-	if (access) {
-		allowed = 0;
-		if (shell->hooks->access_fn)
-			allowed = shell->hooks->access_fn(shell, access);
-	}
-	if (!allowed)
-		goto process_view_end;
+//	if (access) {
+//		allowed = 0;
+//		if (shell->hooks->access_fn)
+//			allowed = shell->hooks->access_fn(shell, access);
+//	}
+//	if (!allowed)
+//		goto process_view_end;
 
 	/* Check syntax */
 	if (!name) {
@@ -315,7 +321,7 @@ static int process_view(clish_shell_t * shell, clish_xmlnode_t * element, void *
 			clish_view__set_restore(view, CLISH_RESTORE_NONE);
 	}
 
-process_view_end:
+//process_view_end:
 	res = process_children(shell, element, view);
 error:
 	clish_xml_release(name);
@@ -411,7 +417,7 @@ process_command(clish_shell_t * shell, clish_xmlnode_t * element, void *parent)
 	clish_command_t *old;
 	char *alias_name = NULL;
 	clish_view_t *alias_view = NULL;
-	int allowed = 1;
+//	int allowed = 1;
 	int res = -1;
 
 	char *access = clish_xmlnode_fetch_attr(element, "access");
@@ -437,13 +443,13 @@ process_command(clish_shell_t * shell, clish_xmlnode_t * element, void *parent)
 	}
 
 	/* Check permissions */
-	if (access) {
-		allowed = 0;
-		if (shell->hooks->access_fn)
-			allowed = shell->hooks->access_fn(shell, access);
-	}
-	if (!allowed)
-		goto process_command_end;
+//	if (access) {
+//		allowed = 0;
+//		if (shell->hooks->access_fn)
+//			allowed = shell->hooks->access_fn(shell, access);
+//	}
+//	if (!allowed)
+//		goto process_command_end;
 
 	/* check this command doesn't already exist */
 	old = clish_view_find_command(v, name, BOOL_FALSE);
@@ -543,7 +549,7 @@ process_command(clish_shell_t * shell, clish_xmlnode_t * element, void *parent)
 		lub_string_free(alias_name);
 	}
 
-process_command_end:
+//process_command_end:
 	res = process_children(shell, element, cmd);
 error:
 	clish_xml_release(access);
@@ -606,7 +612,8 @@ process_startup(clish_shell_t * shell, clish_xmlnode_t * element, void *parent)
 		clish_shell__set_default_shebang(shell, default_shebang);
 
 	if (default_builtin)
-		clish_sym__set_name(shell->default_sym, default_builtin);
+		clish_sym__set_name(shell->hooks[CLISH_SYM_TYPE_ACTION],
+			default_builtin);
 
 	if (timeout)
 		clish_shell__set_timeout(shell, atoi(timeout));
@@ -843,9 +850,9 @@ process_action(clish_shell_t *shell, clish_xmlnode_t *element, void *parent)
 
 	if (builtin)
 		sym = clish_shell_add_unresolved_sym(shell, builtin,
-			CLISH_SYM_TYPE_FN);
+			CLISH_SYM_TYPE_ACTION);
 	else
-		sym = shell->default_sym;
+		sym = shell->hooks[CLISH_SYM_TYPE_ACTION];
 	clish_action__set_builtin(action, sym);
 	if (shebang)
 		clish_action__set_shebang(action, shebang);
@@ -893,15 +900,15 @@ process_namespace(clish_shell_t * shell, clish_xmlnode_t * element, void *parent
 	char *inherit = clish_xmlnode_fetch_attr(element, "inherit");
 	char *access = clish_xmlnode_fetch_attr(element, "access");
 
-	int allowed = 1;
+//	int allowed = 1;
 
-	if (access) {
-		allowed = 0;
-		if (shell->hooks->access_fn)
-			allowed = shell->hooks->access_fn(shell, access);
-	}
-	if (!allowed)
-		goto process_namespace_end;
+//	if (access) {
+//		allowed = 0;
+//		if (shell->hooks->access_fn)
+//			allowed = shell->hooks->access_fn(shell, access);
+//	}
+//	if (!allowed)
+//		goto process_namespace_end;
 
 	/* Check syntax */
 	if (!view) {
@@ -1181,3 +1188,52 @@ error:
 }
 
 /* ------------------------------------------------------ */
+static int
+process_hook(clish_shell_t *shell, clish_xmlnode_t* element, void *parent)
+{
+	char *name = clish_xmlnode_fetch_attr(element, "name");
+	char *builtin = clish_xmlnode_fetch_attr(element, "builtin");
+	int res = -1;
+	int type = CLISH_SYM_TYPE_NONE;
+
+	/* Check syntax */
+	if (!name) {
+		fprintf(stderr, CLISH_XML_ERROR_ATTR("name"));
+		goto error;
+	}
+	/* Find out HOOK type */
+	if (!strcmp(name, "init"))
+		type = CLISH_SYM_TYPE_INIT;
+	else if (!strcmp(name, "fini"))
+		type = CLISH_SYM_TYPE_FINI;
+	else if (!strcmp(name, "access"))
+		type = CLISH_SYM_TYPE_ACCESS;
+	else if (!strcmp(name, "config"))
+		type = CLISH_SYM_TYPE_CONFIG;
+	else if (!strcmp(name, "log"))
+		type = CLISH_SYM_TYPE_LOG;
+	if (CLISH_SYM_TYPE_NONE == type) {
+		fprintf(stderr, CLISH_XML_ERROR_STR"Unknown HOOK name %s.\n", name);
+		goto error;
+	}
+
+	if (builtin) {
+		if (shell->hooks[type])
+			clish_sym__set_name(shell->hooks[type], builtin);
+		else
+			shell->hooks[type] = clish_sym_new(builtin, NULL, type);
+	} else {
+		if (shell->hooks[type])
+			clish_sym_free(shell->hooks[type]);
+		shell->hooks[type] = NULL;
+	}
+
+	res = 0;
+error:
+	clish_xml_release(name);
+	clish_xml_release(builtin);
+
+	return res;
+}
+
+/* ------------------------------------------------------ */