From 1e026b9771711c028967d9300190f515f4c16f4c Mon Sep 17 00:00:00 2001 From: Victor Seva Date: Wed, 2 Dec 2015 14:43:00 +0100 Subject: [PATCH] Imported Upstream version 2.1.1 --- bin/clish.c | 21 ++- bin/konfd.c | 2 +- clish.xsd | 4 + clish/command.h | 2 +- clish/command/command.c | 2 +- clish/config.h | 6 +- clish/config/config.c | 4 +- clish/config/private.h | 2 +- clish/nspace.h | 6 +- clish/nspace/nspace.c | 4 +- clish/pargv.h | 2 +- clish/pargv/pargv.c | 4 +- clish/plugin.h | 28 +++- clish/plugin/plugin.c | 65 ++++++++- clish/plugin/plugin_dump.c | 13 +- clish/plugin/private.h | 2 + clish/shell.h | 35 +++-- clish/shell/private.h | 10 +- clish/shell/shell_command.c | 2 +- clish/shell/shell_execute.c | 216 +++++++++++++++++++++++------ clish/shell/shell_expat.c | 15 +- clish/shell/shell_help.c | 2 +- clish/shell/shell_libxml2.c | 109 ++++++++++++++- clish/shell/shell_parse.c | 12 +- clish/shell/shell_roxml.c | 11 ++ clish/shell/shell_tinyrl.c | 8 +- clish/shell/shell_var.c | 27 ++-- clish/shell/shell_xml.c | 160 +++++++++++++-------- clish/shell/xmlapi.h | 49 ++++++- clish/view.h | 8 +- clish/view/private.h | 2 +- clish/view/view.c | 6 +- config.h.in | 3 + configure | 105 ++++++++++++-- configure.ac | 40 +++++- contrib/debian/clish/root-view.xml | 16 --- contrib/debian/clish/startup.xml | 51 ------- contrib/debian/konfd | 137 ------------------ contrib/openwrt/Makefile | 39 +++--- konf/buf.h | 1 + konf/buf/buf.c | 6 + konf/query.h | 4 +- konf/query/private.h | 2 +- konf/query/query.c | 2 +- plugins/clish/builtin_init.c | 2 +- plugins/clish/hook_config.c | 2 +- plugins/clish/private.h | 2 +- plugins/clish/sym_script.c | 63 +-------- tinyrl/vt100.h | 4 +- tinyrl/vt100/vt100.c | 6 +- 50 files changed, 842 insertions(+), 482 deletions(-) delete mode 100644 contrib/debian/clish/root-view.xml delete mode 100644 contrib/debian/clish/startup.xml delete mode 100755 contrib/debian/konfd diff --git a/bin/clish.c b/bin/clish.c index d96b1cd..7298baf 100644 --- a/bin/clish.c +++ b/bin/clish.c @@ -67,6 +67,7 @@ int main(int argc, char **argv) const char *xml_path = getenv("CLISH_PATH"); const char *view = getenv("CLISH_VIEW"); const char *viewid = getenv("CLISH_VIEWID"); + const char *xslt_file = NULL; FILE *outfd = stdout; bool_t istimeout = BOOL_FALSE; @@ -83,7 +84,7 @@ int main(int argc, char **argv) struct sigaction sigpipe_act; sigset_t sigpipe_set; - static const char *shortopts = "hvs:ledx:w:i:bqu8oO:kt:c:f:z:"; + static const char *shortopts = "hvs:ledx:w:i:bqu8oO:kt:c:f:z:p:"; #ifdef HAVE_GETOPT_LONG static const struct option longopts[] = { {"help", 0, NULL, 'h'}, @@ -106,6 +107,7 @@ int main(int argc, char **argv) {"command", 1, NULL, 'c'}, {"histfile", 1, NULL, 'f'}, {"histsize", 1, NULL, 'z'}, + {"xslt", 1, NULL, 'p'}, {NULL, 0, NULL, 0} }; #endif @@ -214,6 +216,14 @@ int main(int argc, char **argv) histsize = itmp; } break; + case 'p': +#ifdef HAVE_LIB_LIBXSLT + xslt_file = optarg; +#else + fprintf(stderr, "Error: The klish was built without XSLT support.\n"); + goto end; +#endif + break; case 'h': help(0, argv[0]); exit(0); @@ -247,7 +257,8 @@ int main(int argc, char **argv) goto end; } /* Load the XML files */ - if (clish_shell_load_scheme(shell, xml_path)) + clish_xmldoc_start(); + if (clish_shell_load_scheme(shell, xml_path, xslt_file)) goto end; /* Set communication to the konfd */ clish_shell__set_socket(shell, socket_path); @@ -363,6 +374,9 @@ end: } lub_list_free(cmds); + /* Stop XML engine */ + clish_xmldoc_stop(); + return result; } @@ -400,6 +414,9 @@ static void help(int status, const char *argv0) printf("\t-q, --quiet\tDisable echo while executing commands\n\t\tfrom the file stream.\n"); printf("\t-d, --dry-run\tDon't actually execute ACTION scripts.\n"); printf("\t-x , --xml-path=\tPath to XML scheme files.\n"); +#ifdef HAVE_LIB_LIBXSLT + printf("\t-p , --xslt=\tProcess XML with specified XSLT stylesheet.\n"); +#endif printf("\t-w , --view=\tSet the startup view.\n"); printf("\t-i , --viewid=\tSet the startup viewid variables.\n"); printf("\t-u, --utf8\tForce UTF-8 encoding.\n"); diff --git a/bin/konfd.c b/bin/konfd.c index 9e2702b..b47399d 100644 --- a/bin/konfd.c +++ b/bin/konfd.c @@ -389,7 +389,7 @@ static char * process_query(konf_buf_t *tbuf, konf_tree_t * conf, char *str) konf_tree_t *tmpconf; konf_query_t *query; char *retval = NULL; - konf_query_op_t ret = KONF_QUERY_OP_ERROR; + konf_query_op_e ret = KONF_QUERY_OP_ERROR; #ifdef DEBUG fprintf(stderr, "REQUEST: %s\n", str); diff --git a/clish.xsd b/clish.xsd index 9bf8764..d7341ed 100644 --- a/clish.xsd +++ b/clish.xsd @@ -530,6 +530,9 @@ ******************************************************* * is used to dynamically load plugins * +* [rtld_global] - A boolean RTLD_GLOBAL flag for dlopen() +* while plugin loading. Default is "false". +* ******************************************************** --> @@ -538,6 +541,7 @@ + diff --git a/clish/command.h b/clish/command.h index 308e161..e498c6b 100644 --- a/clish/command.h +++ b/clish/command.h @@ -73,7 +73,7 @@ void clish_command__set_pview(clish_command_t * instance, clish_view_t * view); clish_view_t *clish_command__get_pview(const clish_command_t * instance); int clish_command__get_depth(const clish_command_t * instance); clish_config_t *clish_command__get_config(const clish_command_t *instance); -clish_view_restore_t clish_command__get_restore(const clish_command_t * instance); +clish_view_restore_e clish_command__get_restore(const clish_command_t * instance); const clish_command_t * clish_command__get_orig(const clish_command_t * instance); const clish_command_t * clish_command__get_cmd(const clish_command_t * instance); bool_t clish_command__get_lock(const clish_command_t * instance); diff --git a/clish/command/command.c b/clish/command/command.c index f0ac3e3..4f84c4b 100644 --- a/clish/command/command.c +++ b/clish/command/command.c @@ -382,7 +382,7 @@ int clish_command__get_depth(const clish_command_t * this) } /*--------------------------------------------------------- */ -clish_view_restore_t clish_command__get_restore(const clish_command_t * this) +clish_view_restore_e clish_command__get_restore(const clish_command_t * this) { if (!this->pview) return CLISH_RESTORE_NONE; diff --git a/clish/config.h b/clish/config.h index a13ebe3..6e7f519 100644 --- a/clish/config.h +++ b/clish/config.h @@ -14,7 +14,7 @@ typedef enum { CLISH_CONFIG_SET, CLISH_CONFIG_UNSET, CLISH_CONFIG_DUMP -} clish_config_op_t; +} clish_config_op_e; /*===================================== * COMMAND INTERFACE @@ -32,8 +32,8 @@ void clish_config_dump(const clish_config_t *instance); /*----------------- * attributes *----------------- */ -void clish_config__set_op(clish_config_t *instance, clish_config_op_t op); -clish_config_op_t clish_config__get_op(const clish_config_t *instance); +void clish_config__set_op(clish_config_t *instance, clish_config_op_e op); +clish_config_op_e clish_config__get_op(const clish_config_t *instance); void clish_config__set_priority(clish_config_t *instance, unsigned short priority); unsigned short clish_config__get_priority(const clish_config_t *instance); void clish_config__set_pattern(clish_config_t *instance, const char *pattern); diff --git a/clish/config/config.c b/clish/config/config.c index 41b553a..b2d1d85 100644 --- a/clish/config/config.c +++ b/clish/config/config.c @@ -63,13 +63,13 @@ void clish_config_delete(clish_config_t *this) /*--------------------------------------------------------- * PUBLIC ATTRIBUTES *--------------------------------------------------------- */ -void clish_config__set_op(clish_config_t *this, clish_config_op_t op) +void clish_config__set_op(clish_config_t *this, clish_config_op_e op) { this->op = op; } /*--------------------------------------------------------- */ -clish_config_op_t clish_config__get_op(const clish_config_t *this) +clish_config_op_e clish_config__get_op(const clish_config_t *this) { return this->op; } diff --git a/clish/config/private.h b/clish/config/private.h index 44dd522..dec76ee 100644 --- a/clish/config/private.h +++ b/clish/config/private.h @@ -8,7 +8,7 @@ * PRIVATE TYPES *--------------------------------------------------------- */ struct clish_config_s { - clish_config_op_t op; /* CONFIG operation */ + clish_config_op_e op; /* CONFIG operation */ unsigned short priority; char *pattern; char *file; diff --git a/clish/nspace.h b/clish/nspace.h index 2019fcb..af8589d 100644 --- a/clish/nspace.h +++ b/clish/nspace.h @@ -22,7 +22,7 @@ typedef enum { CLISH_NSPACE_HELP, CLISH_NSPACE_COMPLETION, CLISH_NSPACE_CHELP -} clish_nspace_visibility_t; +} clish_nspace_visibility_e; #include @@ -41,7 +41,7 @@ clish_nspace_t *clish_nspace_new(const char *view_name); void clish_nspace_delete(clish_nspace_t * instance); const clish_command_t *clish_nspace_find_next_completion(clish_nspace_t * instance, const char *iter_cmd, const char *line, - clish_nspace_visibility_t field); + clish_nspace_visibility_e field); clish_command_t *clish_nspace_find_command(clish_nspace_t * instance, const char *name); void clish_nspace_dump(const clish_nspace_t * instance); clish_command_t * clish_nspace_create_prefix_cmd(clish_nspace_t * instance, @@ -61,7 +61,7 @@ bool_t clish_nspace__get_completion(const clish_nspace_t * instance); bool_t clish_nspace__get_context_help(const clish_nspace_t * instance); bool_t clish_nspace__get_inherit(const clish_nspace_t * instance); bool_t clish_nspace__get_visibility(const clish_nspace_t * instance, - clish_nspace_visibility_t field); + clish_nspace_visibility_e field); void clish_nspace__set_prefix(clish_nspace_t * instance, const char *prefix); void clish_nspace__set_help(clish_nspace_t * instance, bool_t help); void clish_nspace__set_completion(clish_nspace_t * instance, bool_t help); diff --git a/clish/nspace/nspace.c b/clish/nspace/nspace.c index cc52f24..97ba3b4 100644 --- a/clish/nspace/nspace.c +++ b/clish/nspace/nspace.c @@ -213,7 +213,7 @@ clish_command_t *clish_nspace_find_command(clish_nspace_t * this, const char *na /*--------------------------------------------------------- */ const clish_command_t *clish_nspace_find_next_completion(clish_nspace_t * this, const char *iter_cmd, const char *line, - clish_nspace_visibility_t field) + clish_nspace_visibility_e field) { const clish_command_t *cmd = NULL, *retval = NULL; clish_view_t *view = clish_nspace__get_view(this); @@ -383,7 +383,7 @@ bool_t clish_nspace__get_inherit(const clish_nspace_t * this) /*--------------------------------------------------------- */ bool_t clish_nspace__get_visibility(const clish_nspace_t * instance, - clish_nspace_visibility_t field) + clish_nspace_visibility_e field) { bool_t result = BOOL_FALSE; diff --git a/clish/pargv.h b/clish/pargv.h index bbd0ad9..885f65b 100644 --- a/clish/pargv.h +++ b/clish/pargv.h @@ -19,7 +19,7 @@ typedef enum { CLISH_BAD_CMD, CLISH_BAD_PARAM, CLISH_BAD_HISTORY -} clish_pargv_status_t; +} clish_pargv_status_e; typedef struct clish_pargv_s clish_pargv_t; typedef struct clish_parg_s clish_parg_t; diff --git a/clish/pargv/pargv.c b/clish/pargv/pargv.c index 23f57b4..40c5b31 100644 --- a/clish/pargv/pargv.c +++ b/clish/pargv/pargv.c @@ -112,11 +112,11 @@ unsigned clish_pargv__get_count(clish_pargv_t * this) } /*--------------------------------------------------------- */ -clish_parg_t *clish_pargv__get_parg(clish_pargv_t * this, unsigned index) +clish_parg_t *clish_pargv__get_parg(clish_pargv_t * this, unsigned int index) { if (!this) return NULL; - if (index > this->pargc) + if (index >= this->pargc) return NULL; return this->pargv[index]; } diff --git a/clish/plugin.h b/clish/plugin.h index 960c2d6..27d3635 100644 --- a/clish/plugin.h +++ b/clish/plugin.h @@ -12,16 +12,22 @@ /* Symbol */ -/* Symbol types. Functions with different definition. */ +/* Symbol types. Functions with different purposes. */ typedef enum { CLISH_SYM_TYPE_NONE = 0, /* None */ - CLISH_SYM_TYPE_ACTION, /* Common builtin symbol */ - CLISH_SYM_TYPE_ACCESS, - CLISH_SYM_TYPE_CONFIG, - CLISH_SYM_TYPE_LOG, + CLISH_SYM_TYPE_ACTION, /* Common builtin symbol for ACTION tag */ + CLISH_SYM_TYPE_ACCESS, /* Callback for "access" field */ + CLISH_SYM_TYPE_CONFIG, /* Callback for CONFIG tag */ + CLISH_SYM_TYPE_LOG, /* Callback for logging */ CLISH_SYM_TYPE_MAX /* Number of elements */ } clish_sym_type_e; +/* External functions APIs. */ +typedef enum { + CLISH_SYM_API_SIMPLE = 0, /* Simple (may be single) API */ + CLISH_SYM_API_STDOUT /* Symbol for ACTION tag without "out" argument */ +} clish_sym_api_e; + typedef struct clish_sym_s clish_sym_t; typedef struct clish_plugin_s clish_plugin_t; @@ -36,6 +42,7 @@ typedef struct clish_plugin_s clish_plugin_t; #define CLISH_PLUGIN_FINI(name) int name(void *clish_shell, clish_plugin_t *plugin) #define CLISH_PLUGIN_SYM(name) int name(void *clish_context, const char *script, char **out) +#define CLISH_PLUGIN_OSYM(name) int name(void *clish_context, const char *script) #define CLISH_HOOK_ACCESS(name) int name(void *clish_shell, 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) @@ -43,6 +50,7 @@ typedef struct clish_plugin_s clish_plugin_t; typedef CLISH_PLUGIN_INIT_FUNC(clish_plugin_init_t); typedef CLISH_PLUGIN_FINI(clish_plugin_fini_t); typedef CLISH_PLUGIN_SYM(clish_hook_action_fn_t); +typedef CLISH_PLUGIN_OSYM(clish_hook_oaction_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); @@ -72,7 +80,9 @@ bool_t clish_sym__get_permanent(clish_sym_t *instance); void clish_sym__set_plugin(clish_sym_t *instance, clish_plugin_t *plugin); clish_plugin_t *clish_sym__get_plugin(clish_sym_t *instance); void clish_sym__set_type(clish_sym_t *instance, int type); -int clish_sym__get_type(clish_sym_t *instance); +int clish_sym__get_type(const clish_sym_t *instance); +void clish_sym__set_api(clish_sym_t *instance, clish_sym_api_e api); +clish_sym_api_e clish_sym__get_api(const clish_sym_t *instance); int clish_sym_clone(clish_sym_t *dst, clish_sym_t *src); /* Plugin */ @@ -88,6 +98,10 @@ clish_sym_t *clish_plugin_add_sym(clish_plugin_t *instance, clish_hook_action_fn_t *func, const char *name); clish_sym_t *clish_plugin_add_psym(clish_plugin_t *instance, clish_hook_action_fn_t *func, const char *name); +clish_sym_t *clish_plugin_add_osym(clish_plugin_t *instance, + clish_hook_oaction_fn_t *func, const char *name); +clish_sym_t *clish_plugin_add_posym(clish_plugin_t *instance, + clish_hook_oaction_fn_t *func, const char *name); clish_sym_t *clish_plugin_add_hook(clish_plugin_t *instance, void *func, const char *name, int type); clish_sym_t *clish_plugin_add_phook(clish_plugin_t *instance, @@ -109,6 +123,8 @@ void clish_plugin__set_builtin_flag(clish_plugin_t *instance, bool_t builtin_fla bool_t clish_plugin__get_builtin_flag(const clish_plugin_t *instance); void clish_plugin__set_conf(clish_plugin_t *instance, const char *conf); char *clish_plugin__get_conf(const clish_plugin_t *instance); +void clish_plugin__set_rtld_global(clish_plugin_t *instance, bool_t rtld_global); +bool_t clish_plugin__get_rtld_global(const clish_plugin_t *instance); #endif /* _clish_plugin_h */ /** @} clish_plugin */ diff --git a/clish/plugin/plugin.c b/clish/plugin/plugin.c index d326d4c..1f32236 100644 --- a/clish/plugin/plugin.c +++ b/clish/plugin/plugin.c @@ -40,6 +40,7 @@ clish_sym_t *clish_sym_new(const char *name, void *func, int type) this->name = lub_string_dup(name); this->func = func; this->type = type; + this->api = CLISH_SYM_API_SIMPLE; this->permanent = BOOL_FALSE; return this; @@ -110,11 +111,23 @@ void clish_sym__set_type(clish_sym_t *this, int type) } /*--------------------------------------------------------- */ -int clish_sym__get_type(clish_sym_t *this) +int clish_sym__get_type(const clish_sym_t *this) { return this->type; } +/*--------------------------------------------------------- */ +void clish_sym__set_api(clish_sym_t *this, clish_sym_api_e api) +{ + this->api = api; +} + +/*--------------------------------------------------------- */ +clish_sym_api_e clish_sym__get_api(const clish_sym_t *this) +{ + return this->api; +} + /*--------------------------------------------------------- */ int clish_sym_clone(clish_sym_t *dst, clish_sym_t *src) { @@ -151,6 +164,8 @@ clish_plugin_t *clish_plugin_new(const char *name) /* Constructor and destructor */ this->init = NULL; this->fini = NULL; + /* Flags */ + this->rtld_global = BOOL_FALSE; /* The dlopen() use RTLD_LOCAL by default */ return this; } @@ -223,6 +238,35 @@ clish_sym_t *clish_plugin_add_psym(clish_plugin_t *this, name, CLISH_SYM_TYPE_ACTION, BOOL_TRUE); } +/*--------------------------------------------------------- */ +clish_sym_t *clish_plugin_add_osym(clish_plugin_t *this, + clish_hook_oaction_fn_t *func, const char *name) +{ + clish_sym_t *s; + + if (!(s = clish_plugin_add_generic(this, func, + name, CLISH_SYM_TYPE_ACTION, BOOL_FALSE))) + return s; + clish_sym__set_api(s, CLISH_SYM_API_STDOUT); + + return s; +} + +/*--------------------------------------------------------- */ +/* Add permanent symbol (can't be turned off by dry-run) */ +clish_sym_t *clish_plugin_add_posym(clish_plugin_t *this, + clish_hook_oaction_fn_t *func, const char *name) +{ + clish_sym_t *s; + + if (!(s = clish_plugin_add_generic(this, func, + name, CLISH_SYM_TYPE_ACTION, BOOL_TRUE))) + return s; + clish_sym__set_api(s, CLISH_SYM_API_STDOUT); + + return s; +} + /*--------------------------------------------------------- */ clish_sym_t *clish_plugin_add_hook(clish_plugin_t *this, void *func, const char *name, int type) @@ -292,6 +336,7 @@ static int clish_plugin_load_shared(clish_plugin_t *this) #ifdef HAVE_DLFCN_H char *file = NULL; /* Plugin so file name */ char *init_name = NULL; /* Init function name */ + int flag = RTLD_NOW; if (this->file) { file = lub_string_dup(this->file); @@ -302,7 +347,11 @@ static int clish_plugin_load_shared(clish_plugin_t *this) } /* Open dynamic library */ - this->dlhan = dlopen(file, RTLD_NOW | RTLD_LOCAL); + if (clish_plugin__get_rtld_global(this)) + flag |= RTLD_GLOBAL; + else + flag |= RTLD_LOCAL; + this->dlhan = dlopen(file, flag); lub_string_free(file); if (!this->dlhan) { fprintf(stderr, "Error: Can't open plugin \"%s\": %s\n", @@ -422,3 +471,15 @@ char *clish_plugin__get_conf(const clish_plugin_t *this) } /*--------------------------------------------------------- */ +void clish_plugin__set_rtld_global(clish_plugin_t *this, bool_t rtld_global) +{ + this->rtld_global = rtld_global; +} + +/*--------------------------------------------------------- */ +bool_t clish_plugin__get_rtld_global(const clish_plugin_t *this) +{ + return this->rtld_global; +} + +/*--------------------------------------------------------- */ diff --git a/clish/plugin/plugin_dump.c b/clish/plugin/plugin_dump.c index b868eed..276c846 100644 --- a/clish/plugin/plugin_dump.c +++ b/clish/plugin/plugin_dump.c @@ -52,12 +52,13 @@ void clish_plugin_dump(const clish_plugin_t *this) lub_dump_printf("plugin(%p)\n", this); lub_dump_indent(); - lub_dump_printf("name : %s\n", LUB_DUMP_STR(this->name)); - lub_dump_printf("alias : %s\n", LUB_DUMP_STR(this->alias)); - lub_dump_printf("conf : %s\n", LUB_DUMP_STR(this->conf)); - lub_dump_printf("dlhan : %p\n", this->dlhan); - lub_dump_printf("init : %p\n", this->init); - lub_dump_printf("fini : %p\n", this->fini); + lub_dump_printf("name : %s\n", LUB_DUMP_STR(this->name)); + lub_dump_printf("alias : %s\n", LUB_DUMP_STR(this->alias)); + lub_dump_printf("conf : %s\n", LUB_DUMP_STR(this->conf)); + lub_dump_printf("dlhan : %p\n", this->dlhan); + lub_dump_printf("init : %p\n", this->init); + lub_dump_printf("fini : %p\n", this->fini); + lub_dump_printf("rtld_global : %s\n", LUB_DUMP_BOOL(this->rtld_global)); lub_dump_indent(); /* Iterate child elements */ for(iter = lub_list__get_head(this->syms); diff --git a/clish/plugin/private.h b/clish/plugin/private.h index 907277a..2575cf4 100644 --- a/clish/plugin/private.h +++ b/clish/plugin/private.h @@ -13,6 +13,7 @@ struct clish_sym_s { char *name; /* Symbol name */ void *func; /* Function address */ int type; /* Function type */ + clish_sym_api_e api; /* Function API */ bool_t permanent; /* If permanent the dry-run can't switch it off */ clish_plugin_t *plugin; /* Parent plugin */ }; @@ -27,4 +28,5 @@ struct clish_plugin_s { void *dlhan; /* Handler of dlopen() */ clish_plugin_init_t *init; /* Init function (constructor) != NULL */ clish_plugin_fini_t *fini; /* Fini function (destructor) */ + bool_t rtld_global; /* RTLD_GLOBAL flag for dlopen() */ }; diff --git a/clish/shell.h b/clish/shell.h index 48dbc07..c8cfa1c 100644 --- a/clish/shell.h +++ b/clish/shell.h @@ -29,6 +29,9 @@ #define CLISH_LOCK_PATH "/tmp/clish.lock" #define CLISH_LOCK_WAIT 20 +#define CLISH_STDOUT_CHUNK 1024 +#define CLISH_STDOUT_MAXBUF (CLISH_STDOUT_CHUNK * 1024) + #define CLISH_XML_ERROR_STR "Error parsing XML: " #define CLISH_XML_ERROR_ATTR(attr) CLISH_XML_ERROR_STR"The \""attr"\" attribute is required.\n" @@ -61,13 +64,22 @@ typedef enum { SHELL_STATE_HELPING = 7, SHELL_STATE_EOF = 8, /* EOF of input stream */ SHELL_STATE_CLOSING = 9 -} clish_shell_state_t; +} clish_shell_state_e; typedef enum { SHELL_VAR_NONE, /* Nothing to escape */ SHELL_VAR_ACTION, /* Variable expanding for ACTION script */ SHELL_VAR_REGEX /* Variable expanding for regex usage */ -} clish_shell_var_t; +} clish_shell_var_e; + +typedef enum { + SHELL_EXPAND_PARAM = 1, + SHELL_EXPAND_VIEW = 2, + SHELL_EXPAND_CONTEXT = 4, + SHELL_EXPAND_VAR = 8, + SHELL_EXPAND_ENV = 16, + SHELL_EXPAND_ALL = 255 +} clish_shell_expand_e; _BEGIN_C_DECL @@ -96,9 +108,8 @@ clish_ptype_t *clish_shell_find_create_ptype(clish_shell_t * instance, clish_ptype_preprocess_e preprocess); clish_ptype_t *clish_shell_find_ptype(clish_shell_t *instance, const char *name); -int clish_shell_xml_read(clish_shell_t * instance, const char *filename); void clish_shell_help(clish_shell_t * instance, const char *line); -int clish_shell_exec_action(clish_context_t *context, char **out); +int clish_shell_exec_action(clish_context_t *context, char **out, bool_t intr); int clish_shell_execute(clish_context_t *context, char **out); int clish_shell_forceline(clish_shell_t *instance, const char *line, char ** out); int clish_shell_readline(clish_shell_t *instance, char ** out); @@ -119,7 +130,8 @@ int clish_shell_push_fd(clish_shell_t * instance, FILE * file, void clish_shell_insert_var(clish_shell_t *instance, clish_var_t *var); clish_var_t *clish_shell_find_var(clish_shell_t *instance, const char *name); char *clish_shell_expand_var(const char *name, clish_context_t *context); -char *clish_shell_expand(const char *str, clish_shell_var_t vtype, clish_context_t *context); +char *clish_shell_expand_var_ex(const char *name, clish_context_t *context, clish_shell_expand_e flags); +char *clish_shell_expand(const char *str, clish_shell_var_e vtype, clish_context_t *context); /*----------------- * attributes @@ -144,11 +156,11 @@ FILE *clish_shell__get_ostream(const clish_shell_t * instance); void clish_shell__set_lockfile(clish_shell_t * instance, const char * path); char * clish_shell__get_lockfile(clish_shell_t * instance); int clish_shell__set_socket(clish_shell_t * instance, const char * path); -int clish_shell_load_scheme(clish_shell_t * instance, const char * xml_path); +int clish_shell_load_scheme(clish_shell_t * instance, const char * xml_path, const char *xslt_path); int clish_shell_loop(clish_shell_t * instance); -clish_shell_state_t clish_shell__get_state(const clish_shell_t * instance); +clish_shell_state_e clish_shell__get_state(const clish_shell_t * instance); void clish_shell__set_state(clish_shell_t * instance, - clish_shell_state_t state); + clish_shell_state_e state); void clish_shell__set_startup_view(clish_shell_t * instance, const char * viewname); void clish_shell__set_startup_viewid(clish_shell_t * instance, const char * viewid); void clish_shell__set_default_shebang(clish_shell_t * instance, const char * shebang); @@ -211,6 +223,13 @@ int clish_shell__set_udata(clish_shell_t *instance, /* Access functions */ int clish_shell_prepare(clish_shell_t *instance); +/* + * Non shell specific functions. + * Start and Stop XML parser engine. + */ +int clish_xmldoc_start(void); +int clish_xmldoc_stop(void); + _END_C_DECL #endif /* _clish_shell_h */ diff --git a/clish/shell/private.h b/clish/shell/private.h index 4169286..64d2bf1 100644 --- a/clish/shell/private.h +++ b/clish/shell/private.h @@ -22,7 +22,7 @@ */ typedef struct { const char *last_cmd; - clish_nspace_visibility_t field; + clish_nspace_visibility_e field; } clish_shell_iterator_t; /* this is used to maintain a stack of file handles */ @@ -68,7 +68,7 @@ struct clish_shell_s { unsigned int wdog_timeout; /* Watchdog timeout */ bool_t wdog_active; /* If watchdog is active now */ - clish_shell_state_t state; /* The current state */ + clish_shell_state_e state; /* The current state */ char *overview; /* Overview text for this shell */ tinyrl_t *tinyrl; /* Tiny readline instance */ clish_shell_file_t *current_file; /* file currently in use for input */ @@ -101,7 +101,7 @@ struct clish_shell_s { */ void clish_shell_iterator_init(clish_shell_iterator_t * iter, - clish_nspace_visibility_t field); + clish_nspace_visibility_e field); /** * get the next command which is an extension of the specified line @@ -121,9 +121,9 @@ int clish_shell_pop_file(clish_shell_t * instance); clish_view_t *clish_shell_find_view(clish_shell_t * instance, const char *name); void clish_shell_insert_view(clish_shell_t * instance, clish_view_t * view); -clish_pargv_status_t clish_shell_parse(clish_shell_t * instance, +clish_pargv_status_e clish_shell_parse(clish_shell_t * instance, const char *line, const clish_command_t ** cmd, clish_pargv_t ** pargv); -clish_pargv_status_t clish_shell_parse_pargv(clish_pargv_t *pargv, +clish_pargv_status_e clish_shell_parse_pargv(clish_pargv_t *pargv, const clish_command_t *cmd, void *context, clish_paramv_t *paramv, diff --git a/clish/shell/shell_command.c b/clish/shell/shell_command.c index fd8d884..912fdab 100644 --- a/clish/shell/shell_command.c +++ b/clish/shell/shell_command.c @@ -9,7 +9,7 @@ /*-------------------------------------------------------- */ void clish_shell_iterator_init(clish_shell_iterator_t * iter, - clish_nspace_visibility_t field) + clish_nspace_visibility_e field) { iter->last_cmd = NULL; iter->field = field; diff --git a/clish/shell/shell_execute.c b/clish/shell/shell_execute.c index 6184775..1bd49f6 100644 --- a/clish/shell/shell_execute.c +++ b/clish/shell/shell_execute.c @@ -14,9 +14,18 @@ #include #include #include +#include +#include #include #include +/* Empty signal handler to ignore signal but don't use SIG_IGN. */ +static void sigignore(int signo) +{ + signo = signo; /* Happy compiler */ + return; +} + /*-------------------------------------------------------- */ static int clish_shell_lock(const char *lock_path) { @@ -85,8 +94,6 @@ int clish_shell_execute(clish_context_t *context, char **out) int result = 0; char *lock_path = clish_shell__get_lockfile(this); int lock_fd = -1; - sigset_t old_sigs; - struct sigaction old_sigint, old_sigquit, old_sighup; clish_view_t *cur_view = clish_shell__get_view(this); unsigned int saved_wdog_timeout = this->wdog_timeout; @@ -94,7 +101,7 @@ int clish_shell_execute(clish_context_t *context, char **out) /* Pre-change view if the command is from another depth/view */ { - clish_view_restore_t restore = clish_command__get_restore(cmd); + clish_view_restore_e restore = clish_command__get_restore(cmd); if ((CLISH_RESTORE_VIEW == restore) && (clish_command__get_pview(cmd) != cur_view)) { clish_view_t *view = clish_command__get_pview(cmd); @@ -114,42 +121,10 @@ int clish_shell_execute(clish_context_t *context, char **out) } } - /* Ignore and block SIGINT, SIGQUIT, SIGHUP */ - if (!clish_command__get_interrupt(cmd)) { - struct sigaction sa; - sigset_t sigs; - sa.sa_flags = 0; - sigemptyset(&sa.sa_mask); - sa.sa_handler = SIG_IGN; - sigaction(SIGINT, &sa, &old_sigint); - sigaction(SIGQUIT, &sa, &old_sigquit); - sigaction(SIGHUP, &sa, &old_sighup); - sigemptyset(&sigs); - sigaddset(&sigs, SIGINT); - sigaddset(&sigs, SIGQUIT); - sigaddset(&sigs, SIGHUP); - sigprocmask(SIG_BLOCK, &sigs, &old_sigs); - } - /* Execute ACTION */ clish_context__set_action(context, clish_command__get_action(cmd)); - result = clish_shell_exec_action(context, out); - - /* Restore SIGINT, SIGQUIT, SIGHUP */ - if (!clish_command__get_interrupt(cmd)) { - sigprocmask(SIG_SETMASK, &old_sigs, NULL); - /* Is the signals delivery guaranteed here (before - sigaction restore) for previously blocked and - pending signals? The simple test is working well. - I don't want to use sigtimedwait() function bacause - it needs a realtime extensions. The sigpending() with - the sleep() is not nice too. Report bug if clish will - get the SIGINT after non-interruptable action. - */ - sigaction(SIGINT, &old_sigint, NULL); - sigaction(SIGQUIT, &old_sigquit, NULL); - sigaction(SIGHUP, &old_sighup, NULL); - } + result = clish_shell_exec_action(context, out, + clish_command__get_interrupt(cmd)); /* Call config callback */ if (!result) @@ -203,14 +178,123 @@ error: } /*----------------------------------------------------------- */ -int clish_shell_exec_action(clish_context_t *context, char **out) +/* Execute oaction. It suppose the forked process to get + * script's stdout. Then forked process write the output back + * to klish. + */ +static int clish_shell_exec_oaction(clish_hook_oaction_fn_t func, + void *context, const char *script, char **out) +{ + int result = -1; + int real_stdout; /* Saved stdout handler */ + int pipe1[2], pipe2[2]; + pid_t cpid = -1; + konf_buf_t *buf; + + if (pipe(pipe1)) + return -1; + if (pipe(pipe2)) + goto stdout_error; + + /* Create process to read script's stdout */ + cpid = fork(); + if (cpid == -1) { + fprintf(stderr, "Error: Can't fork the stdout-grabber process.\n" + "Error: The ACTION will be not executed.\n"); + goto stdout_error; + } + + /* Child: read action's stdout */ + if (cpid == 0) { + lub_list_t *l; + lub_list_node_t *node; + struct iovec *iov; + const int rsize = CLISH_STDOUT_CHUNK; /* Read chunk size */ + size_t cur_size = 0; + + close(pipe1[1]); + close(pipe2[0]); + l = lub_list_new(NULL); + + /* Read the result of script execution */ + while (1) { + ssize_t ret; + iov = malloc(sizeof(*iov)); + iov->iov_len = rsize; + iov->iov_base = malloc(iov->iov_len); + do { + ret = readv(pipe1[0], iov, 1); + } while ((ret < 0) && (errno == EINTR)); + if (ret <= 0) { /* Error or EOF */ + free(iov->iov_base); + free(iov); + break; + } + iov->iov_len = ret; + lub_list_add(l, iov); + /* Check the max size of buffer */ + cur_size += ret; + if (cur_size >= CLISH_STDOUT_MAXBUF) + break; + } + close(pipe1[0]); + + /* Write the result of script back to klish */ + while ((node = lub_list__get_head(l))) { + iov = lub_list_node__get_data(node); + lub_list_del(l, node); + lub_list_node_free(node); + write(pipe2[1], iov->iov_base, iov->iov_len); + free(iov->iov_base); + free(iov); + } + close(pipe2[1]); + + lub_list_free(l); + _exit(0); + } + + real_stdout = dup(STDOUT_FILENO); + dup2(pipe1[1], STDOUT_FILENO); + close(pipe1[0]); + close(pipe1[1]); + close(pipe2[1]); + + result = func(context, script); + + /* Restore real stdout */ + dup2(real_stdout, STDOUT_FILENO); + close(real_stdout); + /* Read the result of script execution */ + buf = konf_buf_new(pipe2[0]); + while (konf_buf_read(buf) > 0); + *out = konf_buf__dup_line(buf); + konf_buf_delete(buf); + close(pipe2[0]); + /* Wait for the stdout-grabber process */ + waitpid(cpid, NULL, 0); + + return result; + +stdout_error: + close(pipe1[0]); + close(pipe1[1]); + return -1; +} + +/*----------------------------------------------------------- */ +int clish_shell_exec_action(clish_context_t *context, char **out, bool_t intr) { int result = -1; clish_sym_t *sym; char *script; - clish_hook_action_fn_t *func = NULL; + void *func = NULL; /* We don't know the func API at this time */ const clish_action_t *action = clish_context__get_action(context); clish_shell_t *shell = clish_context__get_shell(context); + /* Signal vars */ + struct sigaction old_sigint, old_sigquit, old_sighup; + struct sigaction sa; + sigset_t old_sigs; if (!(sym = clish_action__get_builtin(action))) return 0; @@ -221,7 +305,59 @@ int clish_shell_exec_action(clish_context_t *context, char **out) return -1; } script = clish_shell_expand(clish_action__get_script(action), SHELL_VAR_ACTION, context); - result = func(context, script, out); + + /* Ignore and block SIGINT, SIGQUIT, SIGHUP. + * The SIG_IGN is not a case because it will be inherited + * while a fork(). It's necessary to ignore signals because + * the klish itself and ACTION script share the same terminal. + */ + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + sa.sa_handler = sigignore; /* Empty signal handler */ + sigaction(SIGINT, &sa, &old_sigint); + sigaction(SIGQUIT, &sa, &old_sigquit); + sigaction(SIGHUP, &sa, &old_sighup); + /* Block signals for children processes. The block state is inherited. */ + if (!intr) { + sigset_t sigs; + sigemptyset(&sigs); + sigaddset(&sigs, SIGINT); + sigaddset(&sigs, SIGQUIT); + sigaddset(&sigs, SIGHUP); + sigprocmask(SIG_BLOCK, &sigs, &old_sigs); + } + + /* Find out the function API */ + /* CLISH_SYM_API_SIMPLE */ + if (clish_sym__get_api(sym) == CLISH_SYM_API_SIMPLE) { + result = ((clish_hook_action_fn_t *)func)(context, script, out); + + /* CLISH_SYM_API_STDOUT and output is not needed */ + } else if ((clish_sym__get_api(sym) == CLISH_SYM_API_STDOUT) && (!out)) { + result = ((clish_hook_oaction_fn_t *)func)(context, script); + + /* CLISH_SYM_API_STDOUT and outpus is needed */ + } else if (clish_sym__get_api(sym) == CLISH_SYM_API_STDOUT) { + result = clish_shell_exec_oaction((clish_hook_oaction_fn_t *)func, + context, script, out); + } + + /* Restore SIGINT, SIGQUIT, SIGHUP */ + if (!intr) { + sigprocmask(SIG_SETMASK, &old_sigs, NULL); + /* Is the signals delivery guaranteed here (before + sigaction restore) for previously blocked and + pending signals? The simple test is working well. + I don't want to use sigtimedwait() function because + it needs a realtime extensions. The sigpending() with + the sleep() is not nice too. Report bug if clish will + get the SIGINT after non-interruptable action. + */ + } + sigaction(SIGINT, &old_sigint, NULL); + sigaction(SIGQUIT, &old_sigquit, NULL); + sigaction(SIGHUP, &old_sighup, NULL); + lub_string_free(script); return result; diff --git a/clish/shell/shell_expat.c b/clish/shell/shell_expat.c index 2abb2ca..7ffa0cc 100644 --- a/clish/shell/shell_expat.c +++ b/clish/shell/shell_expat.c @@ -53,7 +53,7 @@ struct clish_xmlnode_s { clish_xmlnode_t *next; /**< next sibling */ clish_xmlnode_t *attributes; /**< attributes are nodes too */ char *content; /**< !NULL for text and attributes nodes */ - clish_xmlnodetype_t type; /**< node type */ + clish_xmlnodetype_e type; /**< node type */ int depth; /**< node depth */ clish_xmldoc_t *doc; }; @@ -148,7 +148,7 @@ static void clish_expat_add_attrlist(clish_xmlnode_t *node, const char **attr) * @return a new node or NULL on error */ static clish_xmlnode_t *clish_expat_make_node(clish_xmlnode_t *parent, - clish_xmlnodetype_t type, + clish_xmlnodetype_e type, const char *n, const char *v, const char **attr) @@ -307,6 +307,17 @@ static void clish_expat_free_node(clish_xmlnode_t *cur) /* * Public interface */ + +int clish_xmldoc_start(void) +{ + return 0; +} + +int clish_xmldoc_stop(void) +{ + return 0; +} + clish_xmldoc_t *clish_xmldoc_read(const char *filename) { clish_xmldoc_t *doc; diff --git a/clish/shell/shell_help.c b/clish/shell/shell_help.c index de5b5cb..247f61a 100644 --- a/clish/shell/shell_help.c +++ b/clish/shell/shell_help.c @@ -48,7 +48,7 @@ static int available_params(clish_shell_t *this, clish_pargv_t *completion, *pargv; unsigned i; unsigned cnt = 0; - clish_pargv_status_t status = CLISH_LINE_OK; + clish_pargv_status_e status = CLISH_LINE_OK; clish_context_t context; /* Empty line */ diff --git a/clish/shell/shell_libxml2.c b/clish/shell/shell_libxml2.c index 7a25ad9..7acca05 100644 --- a/clish/shell/shell_libxml2.c +++ b/clish/shell/shell_libxml2.c @@ -19,6 +19,19 @@ #include #include "xmlapi.h" +#ifdef HAVE_LIB_LIBXSLT +#include +#include +#include +#include +extern int xmlLoadExtDtdDefaultValue; + +/* dummy stuff ; really a xsltStylesheet */ +struct clish_xslt_s { + int dummy; +}; +#endif + /* dummy stuff ; really a xmlDoc */ struct clish_xmldoc_s { int dummy; @@ -52,18 +65,40 @@ static inline clish_xmlnode_t *node_to_xmlnode(xmlNode *node) /* * public interface */ + +int clish_xmldoc_start(void) +{ +#ifdef HAVE_LIB_LIBXSLT + /* The XSLT example contain these settings but I doubt + * it's really necessary. + */ +/* xmlSubstituteEntitiesDefault(1); + xmlLoadExtDtdDefaultValue = 1; +*/ +#endif + return 0; +} + +int clish_xmldoc_stop(void) +{ +#ifdef HAVE_LIB_LIBXSLT + xsltCleanupGlobals(); +#endif + xmlCleanupParser(); + return 0; +} + clish_xmldoc_t *clish_xmldoc_read(const char *filename) { - xmlDoc *doc = xmlReadFile(filename, NULL, 0); + xmlDoc *doc; + doc = xmlReadFile(filename, NULL, 0); return doc_to_xmldoc(doc); } void clish_xmldoc_release(clish_xmldoc_t *doc) { - if (doc) { + if (doc) xmlFreeDoc(xmldoc_to_doc(doc)); - xmlCleanupParser(); - } } int clish_xmldoc_is_valid(clish_xmldoc_t *doc) @@ -199,7 +234,8 @@ int clish_xmlnode_get_content(clish_xmlnode_t *node, char *content, /* first, get the content length */ c = n->children; while (c) { - if (c->type == XML_TEXT_NODE && !xmlIsBlankNode(c)) { + if ((c->type == XML_TEXT_NODE || c->type == XML_CDATA_SECTION_NODE) + && !xmlIsBlankNode(c)) { rlen += strlen((char*)c->content); } c = c->next; @@ -209,7 +245,8 @@ int clish_xmlnode_get_content(clish_xmlnode_t *node, char *content, if (rlen <= *contentlen) { c = n->children; while (c) { - if (c->type == XML_TEXT_NODE && !xmlIsBlankNode(c)) { + if ((c->type == XML_TEXT_NODE || c->type == XML_CDATA_SECTION_NODE) + && !xmlIsBlankNode(c)) { strcat(content, (char*)c->content); } c = c->next; @@ -275,5 +312,65 @@ void clish_xml_release(void *p) /* do we allocate memory? not yet. */ } +#ifdef HAVE_LIB_LIBXSLT + +static inline xsltStylesheet *xslt_to_xsltStylesheet(clish_xslt_t *xslt) +{ + return (xsltStylesheet*)xslt; +} + +static inline clish_xslt_t *xsltStylesheet_to_xslt(xsltStylesheet *xslt) +{ + return (clish_xslt_t*)xslt; +} + +int clish_xslt_is_valid(clish_xslt_t *stylesheet) +{ + return stylesheet != NULL; +} + +clish_xmldoc_t *clish_xslt_apply(clish_xmldoc_t *xmldoc, clish_xslt_t *stylesheet) +{ + xmlDoc *doc = xmldoc_to_doc(xmldoc); + xsltStylesheetPtr cur = xslt_to_xsltStylesheet(stylesheet); + xmlDoc *res; + + if (!doc || !cur) + return doc_to_xmldoc(NULL); + res = xsltApplyStylesheet(cur, doc, NULL); + + return doc_to_xmldoc(res); +} + +clish_xslt_t *clish_xslt_read(const char *filename) +{ + xsltStylesheet* cur = NULL; + + cur = xsltParseStylesheetFile((const xmlChar *)filename); + + return xsltStylesheet_to_xslt(cur); +} + +clish_xslt_t *clish_xslt_read_embedded(clish_xmldoc_t *xmldoc) +{ + xsltStylesheet* cur = NULL; + xmlDoc *doc = xmldoc_to_doc(xmldoc); + + cur = xsltLoadStylesheetPI(doc); + + return xsltStylesheet_to_xslt(cur); +} + +void clish_xslt_release(clish_xslt_t *stylesheet) +{ + xsltStylesheet* cur = xslt_to_xsltStylesheet(stylesheet); + + if (!cur) + return; + xsltFreeStylesheet(cur); +} + +#endif /* HAVE_LIB_LIBXSLT */ + #endif /* HAVE_LIB_LIBXML2 */ diff --git a/clish/shell/shell_parse.c b/clish/shell/shell_parse.c index f050d1a..1dc7bc3 100644 --- a/clish/shell/shell_parse.c +++ b/clish/shell/shell_parse.c @@ -10,11 +10,11 @@ #include "private.h" /*----------------------------------------------------------- */ -clish_pargv_status_t clish_shell_parse( +clish_pargv_status_e clish_shell_parse( clish_shell_t *this, const char *line, const clish_command_t **ret_cmd, clish_pargv_t **pargv) { - clish_pargv_status_t result = CLISH_BAD_CMD; + clish_pargv_status_e result = CLISH_BAD_CMD; clish_context_t context; const clish_command_t *cmd; lub_argv_t *argv = NULL; @@ -67,7 +67,7 @@ static bool_t line_test(const clish_param_t *param, void *context) } /*--------------------------------------------------------- */ -clish_pargv_status_t clish_shell_parse_pargv(clish_pargv_t *pargv, +clish_pargv_status_e clish_shell_parse_pargv(clish_pargv_t *pargv, const clish_command_t *cmd, void *context, clish_paramv_t *paramv, @@ -79,7 +79,7 @@ clish_pargv_status_t clish_shell_parse_pargv(clish_pargv_t *pargv, unsigned nopt_index = 0; clish_param_t *nopt_param = NULL; unsigned i; - clish_pargv_status_t retval; + clish_pargv_status_e retval; unsigned paramc = clish_paramv__get_count(paramv); int up_level = 0; /* Is it a first level of param nesting? */ @@ -317,14 +317,14 @@ clish_pargv_status_t clish_shell_parse_pargv(clish_pargv_t *pargv, } /*----------------------------------------------------------- */ -clish_shell_state_t clish_shell__get_state(const clish_shell_t *this) +clish_shell_state_e clish_shell__get_state(const clish_shell_t *this) { return this->state; } /*----------------------------------------------------------- */ void clish_shell__set_state(clish_shell_t *this, - clish_shell_state_t state) + clish_shell_state_e state) { assert(this); this->state = state; diff --git a/clish/shell/shell_roxml.c b/clish/shell/shell_roxml.c index 5184d80..271d045 100644 --- a/clish/shell/shell_roxml.c +++ b/clish/shell/shell_roxml.c @@ -50,6 +50,17 @@ static inline clish_xmlnode_t *node_to_xmlnode(node_t *node) /* * public interface */ + +int clish_xmldoc_start(void) +{ + return 0; +} + +int clish_xmldoc_stop(void) +{ + return 0; +} + clish_xmldoc_t *clish_xmldoc_read(const char *filename) { node_t *doc = roxml_load_doc((char*)filename); diff --git a/clish/shell/shell_tinyrl.c b/clish/shell/shell_tinyrl.c index 02ba35a..3e21838 100644 --- a/clish/shell/shell_tinyrl.c +++ b/clish/shell/shell_tinyrl.c @@ -70,9 +70,9 @@ static bool_t clish_shell_tinyrl_key_help(tinyrl_t *this, int key) /* * Expand the current line with any history substitutions */ -static clish_pargv_status_t clish_shell_tinyrl_expand(tinyrl_t *this) +static clish_pargv_status_e clish_shell_tinyrl_expand(tinyrl_t *this) { - clish_pargv_status_t status = CLISH_LINE_OK; + clish_pargv_status_e status = CLISH_LINE_OK; #if 0 int rtn; char *buffer; @@ -153,7 +153,7 @@ static bool_t clish_shell_tinyrl_key_space(tinyrl_t *this, int key) clish_context_t *context = tinyrl__get_context(this); clish_shell_t *shell = clish_context__get_shell(context); const char *line = tinyrl__get_line(this); - clish_pargv_status_t arg_status; + clish_pargv_status_e arg_status; const clish_command_t *cmd = NULL; clish_pargv_t *pargv = NULL; @@ -270,7 +270,7 @@ static bool_t clish_shell_tinyrl_key_enter(tinyrl_t *this, int key) } } if (cmd) { - clish_pargv_status_t arg_status; + clish_pargv_status_e arg_status; tinyrl_multi_crlf(this); /* we've got a command so check the syntax */ arg_status = clish_shell_parse(shell, diff --git a/clish/shell/shell_var.c b/clish/shell/shell_var.c index 8974479..a417ce9 100644 --- a/clish/shell/shell_var.c +++ b/clish/shell/shell_var.c @@ -173,7 +173,7 @@ static char *find_var(const char *name, lub_bintree_t *tree, clish_context_t *co if (!res) { char *out = NULL; clish_context__set_action(context, clish_var__get_action(var)); - if (clish_shell_exec_action(context, &out)) { + if (clish_shell_exec_action(context, &out, BOOL_FALSE)) { lub_string_free(out); return NULL; } @@ -378,7 +378,7 @@ static char *expand_nextsegment(const char **string, const char *escape_chars, * subtituting each occurance of a "${FRED}" type variable sub-string * with the appropriate value. */ -char *clish_shell_expand(const char *str, clish_shell_var_t vtype, clish_context_t *context) +char *clish_shell_expand(const char *str, clish_shell_var_e vtype, clish_context_t *context) { char *seg, *result = NULL; const char *escape_chars = NULL; @@ -479,6 +479,12 @@ char *clish_shell__get_full_line(clish_context_t *context) /*--------------------------------------------------------- */ char *clish_shell_expand_var(const char *name, clish_context_t *context) +{ + return clish_shell_expand_var_ex(name, context, SHELL_EXPAND_ALL); +} + +/*----------------------------------------------------------- */ +char *clish_shell_expand_var_ex(const char *name, clish_context_t *context, clish_shell_expand_e flags) { clish_shell_t *this; const clish_command_t *cmd; @@ -494,26 +500,31 @@ char *clish_shell_expand_var(const char *name, clish_context_t *context) pargv = clish_context__get_pargv(context); /* try and substitute a parameter value */ - if (pargv) { + if (pargv && (flags & SHELL_EXPAND_PARAM)) { const clish_parg_t *parg = clish_pargv_find_arg(pargv, name); if (parg) tmp = clish_parg__get_value(parg); } + /* try and substitute the param's default */ - if (!tmp && cmd) + if (!tmp && cmd && (flags & SHELL_EXPAND_PARAM)) tmp = clish_paramv_find_default( clish_command__get_paramv(cmd), name); + /* try and substitute a viewId variable */ - if (!tmp && this) + if (!tmp && this && (flags & SHELL_EXPAND_VIEW)) tmp = string = find_viewid_var(name, context); + /* try and substitute context fixed variable */ - if (!tmp) + if (!tmp && (flags & SHELL_EXPAND_CONTEXT)) tmp = string = find_context_var(name, context); + /* try and substitute a global var value */ - if (!tmp && this) + if (!tmp && this && (flags & SHELL_EXPAND_VAR)) tmp = string = find_global_var(name, context); + /* get the contents of an environment variable */ - if (!tmp) + if (!tmp && (flags & SHELL_EXPAND_ENV)) tmp = getenv(name); if (string) diff --git a/clish/shell/shell_xml.c b/clish/shell/shell_xml.c index 16bf57f..0a9c665 100644 --- a/clish/shell/shell_xml.c +++ b/clish/shell/shell_xml.c @@ -72,28 +72,45 @@ static clish_xml_cb_t xml_elements[] = { */ const char *default_path = "/etc/clish;~/.clish"; +static int process_node(clish_shell_t *shell, clish_xmlnode_t *node, + void *parent); + /*-------------------------------------------------------- */ -int clish_shell_load_scheme(clish_shell_t *this, const char *xml_path) +int clish_shell_load_scheme(clish_shell_t *this, const char *xml_path, const char *xslt_path) { const char *path = xml_path; char *buffer; char *dirname; char *saveptr = NULL; - int res = 0; + int res = -1; + clish_xmldoc_t *doc = NULL; + DIR *dir; + +#ifdef HAVE_LIB_LIBXSLT + clish_xslt_t *xslt = NULL; + + /* Load global XSLT stylesheet */ + if (xslt_path) { + xslt = clish_xslt_read(xslt_path); + if (!clish_xslt_is_valid(xslt)) { + fprintf(stderr, CLISH_XML_ERROR_STR"Can't load XSLT file %s\n", + xslt_path); + return -1; + } + } +#endif - /* use the default path */ + /* Use the default path */ if (!path) path = default_path; - /* take a copy of the path */ buffer = lub_system_tilde_expand(path); - /* now loop though each directory */ + /* Loop though each directory */ for (dirname = strtok_r(buffer, ";", &saveptr); dirname; dirname = strtok_r(NULL, ";", &saveptr)) { - DIR *dir; struct dirent *entry; - /* search this directory for any XML files */ + /* Search this directory for any XML files */ dir = opendir(dirname); if (NULL == dir) { #ifdef DEBUG @@ -105,37 +122,91 @@ int clish_shell_load_scheme(clish_shell_t *this, const char *xml_path) } for (entry = readdir(dir); entry; entry = readdir(dir)) { const char *extension = strrchr(entry->d_name, '.'); - /* check the filename */ - if ((NULL != extension) && - (0 == strcmp(".xml", extension))) { - char *filename = NULL; + char *filename = NULL; + clish_xmlnode_t *root; + int r; - /* build the filename */ - lub_string_cat(&filename, dirname); - lub_string_cat(&filename, "/"); - lub_string_cat(&filename, entry->d_name); + /* Check the filename */ + if (!extension || strcmp(".xml", extension)) + continue; + + /* Build the filename */ + lub_string_cat(&filename, dirname); + lub_string_cat(&filename, "/"); + lub_string_cat(&filename, entry->d_name); #ifdef DEBUG - fprintf(stderr, "Parse XML-file: %s\n", filename); + fprintf(stderr, "Parse XML-file: %s\n", filename); #endif - /* load this file */ - res = clish_shell_xml_read(this, filename); - /* Error message */ - if (res) - fprintf(stderr, CLISH_XML_ERROR_STR"File %s\n", - filename); - /* release the resource */ + /* Load current XML file */ + doc = clish_xmldoc_read(filename); + if (!clish_xmldoc_is_valid(doc)) { + int errcaps = clish_xmldoc_error_caps(doc); + printf("Unable to open file '%s'", filename); + if ((errcaps & CLISH_XMLERR_LINE) == CLISH_XMLERR_LINE) + printf(", at line %d", clish_xmldoc_get_err_line(doc)); + if ((errcaps & CLISH_XMLERR_COL) == CLISH_XMLERR_COL) + printf(", at column %d", clish_xmldoc_get_err_col(doc)); + if ((errcaps & CLISH_XMLERR_DESC) == CLISH_XMLERR_DESC) + printf(", message is %s", clish_xmldoc_get_err_msg(doc)); + printf("\n"); + goto error; + } +#ifdef HAVE_LIB_LIBXSLT + /* Use embedded stylesheet if stylesheet + * filename is not specified. + */ + if (!xslt_path) + xslt = clish_xslt_read_embedded(doc); + + if (clish_xslt_is_valid(xslt)) { + clish_xmldoc_t *tmp = NULL; + tmp = clish_xslt_apply(doc, xslt); + if (!clish_xmldoc_is_valid(tmp)) { + fprintf(stderr, CLISH_XML_ERROR_STR"Can't load XSLT file %s\n", xslt_path); + goto error; + } + clish_xmldoc_release(doc); + doc = tmp; + } + + if (!xslt_path && clish_xslt_is_valid(xslt)) + clish_xslt_release(xslt); +#endif + root = clish_xmldoc_get_root(doc); + r = process_node(this, root, NULL); + clish_xmldoc_release(doc); + + /* Error message */ + if (r) { + fprintf(stderr, CLISH_XML_ERROR_STR"File %s\n", + filename); lub_string_free(filename); + goto error; } - if (res) - break; + lub_string_free(filename); } - /* all done for this directory */ closedir(dir); - if (res) - break; } + +/* To don't free memory twice on cleanup */ +#ifdef HAVE_LIB_LIBXSLT + if (!xslt_path) + xslt = NULL; +#endif + doc = NULL; + dir = NULL; + res = 0; /* Success */ +error: lub_string_free(buffer); + if (dir) + closedir(dir); + if (clish_xmldoc_is_valid(doc)) + clish_xmldoc_release(doc); +#ifdef HAVE_LIB_LIBXSLT + if (clish_xslt_is_valid(xslt)) + clish_xslt_release(xslt); +#endif return res; } @@ -224,34 +295,6 @@ static int process_children(clish_shell_t *shell, return 0; } -/* ------------------------------------------------------ */ -int clish_shell_xml_read(clish_shell_t *shell, const char *filename) -{ - int ret = -1; - clish_xmldoc_t *doc; - - doc = clish_xmldoc_read(filename); - - if (clish_xmldoc_is_valid(doc)) { - clish_xmlnode_t *root = clish_xmldoc_get_root(doc); - ret = process_node(shell, root, NULL); - } else { - int errcaps = clish_xmldoc_error_caps(doc); - printf("Unable to open file '%s'", filename); - if ((errcaps & CLISH_XMLERR_LINE) == CLISH_XMLERR_LINE) - printf(", at line %d", clish_xmldoc_get_err_line(doc)); - if ((errcaps & CLISH_XMLERR_COL) == CLISH_XMLERR_COL) - printf(", at column %d", clish_xmldoc_get_err_col(doc)); - if ((errcaps & CLISH_XMLERR_DESC) == CLISH_XMLERR_DESC) - printf(", message is %s", clish_xmldoc_get_err_msg(doc)); - printf("\n"); - } - - clish_xmldoc_release(doc); - - return ret; -} - /* ------------------------------------------------------ */ static int process_clish_module(clish_shell_t *shell, clish_xmlnode_t *element, void *parent) @@ -1130,6 +1173,7 @@ static int process_plugin(clish_shell_t *shell, clish_xmlnode_t *element, char *file = clish_xmlnode_fetch_attr(element, "file"); char *name = clish_xmlnode_fetch_attr(element, "name"); char *alias = clish_xmlnode_fetch_attr(element, "alias"); + char *rtld_global = clish_xmlnode_fetch_attr(element, "rtld_global"); int res = -1; char *text; @@ -1154,6 +1198,9 @@ static int process_plugin(clish_shell_t *shell, clish_xmlnode_t *element, if (file && *file) clish_plugin__set_file(plugin, file); + if (rtld_global && lub_string_nocasecmp(rtld_global, "true") == 0) + clish_plugin__set_rtld_global(plugin, BOOL_TRUE); + /* Get PLUGIN body content */ text = clish_xmlnode_get_all_content(element); if (text && *text) @@ -1166,6 +1213,7 @@ error: clish_xml_release(file); clish_xml_release(name); clish_xml_release(alias); + clish_xml_release(rtld_global); parent = parent; /* Happy compiler */ diff --git a/clish/shell/xmlapi.h b/clish/shell/xmlapi.h index d1419ab..fd6b10f 100644 --- a/clish/shell/xmlapi.h +++ b/clish/shell/xmlapi.h @@ -7,6 +7,10 @@ #ifndef clish_xmlapi_included_h #define clish_xmlapi_included_h +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include /* need for FILE */ @@ -23,6 +27,13 @@ typedef struct clish_xmldoc_s clish_xmldoc_t; */ typedef struct clish_xmlnode_s clish_xmlnode_t; +/* + * Start and Stop XML parser engine. + * Some parsers need a global cleanup at the end of the programm. + */ +int clish_xmldoc_start(void); +int clish_xmldoc_stop(void); + /* * read an XML document */ @@ -48,7 +59,7 @@ typedef enum { CLISH_XMLERR_LINE = 0x10, CLISH_XMLERR_COL = 0x20, CLISH_XMLERR_DESC = 0x40 -} clish_xmlerrcaps_t; +} clish_xmlerrcaps_e; /* * does this specific implementation define any error? @@ -65,7 +76,7 @@ typedef enum { CLISH_XMLNODE_PI, CLISH_XMLNODE_DECL, CLISH_XMLNODE_UNKNOWN, -} clish_xmlnodetype_t; +} clish_xmlnodetype_e; /* * get error description, when available @@ -193,5 +204,39 @@ void clish_xml_release(void *p); */ void clish_xmlnode_print(clish_xmlnode_t *node, FILE *out); +#ifdef HAVE_LIB_LIBXSLT + +/* + * XSLT stylesheet (opaque type) + * The real type is defined by the selected external API + */ +typedef struct clish_xslt_s clish_xslt_t; + +/* + * Load an XSLT stylesheet + */ +clish_xslt_t *clish_xslt_read(const char *filename); + +/* + * Load an embedded XSLT stylesheet from already + * loaded XML document. + */ +clish_xslt_t *clish_xslt_read_embedded(clish_xmldoc_t *xmldoc); + +/* Apply XSLT stylesheet */ +clish_xmldoc_t *clish_xslt_apply(clish_xmldoc_t *xmldoc, clish_xslt_t *stylesheet); + +/* + * Release a previously opened XSLT stylesheet + */ +void clish_xslt_release(clish_xslt_t *stylesheet); + +/* + * Check if a stylesheet is valid (i.e. it loaded successfully) + */ +int clish_xslt_is_valid(clish_xslt_t *stylesheet); + +#endif /* HAVE_LIB_LIBXSLT */ + #endif /* clish_xmlapi_included_h */ diff --git a/clish/view.h b/clish/view.h index 8e85efa..2113a50 100644 --- a/clish/view.h +++ b/clish/view.h @@ -22,7 +22,7 @@ typedef enum { CLISH_RESTORE_NONE, CLISH_RESTORE_DEPTH, CLISH_RESTORE_VIEW -} clish_view_restore_t; +} clish_view_restore_e; #include "lub/list.h" #include "clish/command.h" @@ -52,7 +52,7 @@ clish_command_t *clish_view_find_command(clish_view_t * instance, const char *name, bool_t inherit); const clish_command_t *clish_view_find_next_completion(clish_view_t * instance, const char *iter_cmd, const char *line, - clish_nspace_visibility_t field, bool_t inherit); + clish_nspace_visibility_e field, bool_t inherit); clish_command_t *clish_view_resolve_command(clish_view_t * instance, const char *line, bool_t inherit); clish_command_t *clish_view_resolve_prefix(clish_view_t * instance, @@ -70,8 +70,8 @@ char *clish_view__get_prompt(const clish_view_t *instance); void clish_view__set_depth(clish_view_t * instance, unsigned depth); unsigned clish_view__get_depth(const clish_view_t * instance); void clish_view__set_restore(clish_view_t * instance, - clish_view_restore_t restore); -clish_view_restore_t clish_view__get_restore(const clish_view_t * instance); + clish_view_restore_e restore); +clish_view_restore_e clish_view__get_restore(const clish_view_t * instance); int clish_view_insert_hotkey(const clish_view_t *instance, const char *key, const char *cmd); const char *clish_view_find_hotkey(const clish_view_t *instance, int code); void clish_view__set_access(clish_view_t *instance, const char *access); diff --git a/clish/view/private.h b/clish/view/private.h index 2040707..84e1160 100644 --- a/clish/view/private.h +++ b/clish/view/private.h @@ -18,5 +18,5 @@ struct clish_view_s { lub_list_t *nspaces; clish_hotkeyv_t *hotkeys; unsigned int depth; - clish_view_restore_t restore; + clish_view_restore_e restore; }; diff --git a/clish/view/view.c b/clish/view/view.c index 041cd40..af01113 100644 --- a/clish/view/view.c +++ b/clish/view/view.c @@ -285,7 +285,7 @@ static const clish_command_t *find_next_completion(clish_view_t * this, /*--------------------------------------------------------- */ const clish_command_t *clish_view_find_next_completion(clish_view_t * this, const char *iter_cmd, const char *line, - clish_nspace_visibility_t field, bool_t inherit) + clish_nspace_visibility_e field, bool_t inherit) { const clish_command_t *result, *cmd; clish_nspace_t *nspace; @@ -379,13 +379,13 @@ unsigned clish_view__get_depth(const clish_view_t * this) /*--------------------------------------------------------- */ void clish_view__set_restore(clish_view_t * this, - clish_view_restore_t restore) + clish_view_restore_e restore) { this->restore = restore; } /*--------------------------------------------------------- */ -clish_view_restore_t clish_view__get_restore(const clish_view_t * this) +clish_view_restore_e clish_view__get_restore(const clish_view_t * this) { return this->restore; } diff --git a/config.h.in b/config.h.in index 976429d..8f6f271 100644 --- a/config.h.in +++ b/config.h.in @@ -33,6 +33,9 @@ /* libxml2-based XML backend */ #undef HAVE_LIB_LIBXML2 +/* libxslt XML transform engine */ +#undef HAVE_LIB_LIBXSLT + /* libroxml-based XML backend */ #undef HAVE_LIB_ROXML diff --git a/configure b/configure index e05452b..0cc55e1 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for klish 2.0.3. +# Generated by GNU Autoconf 2.69 for klish 2.1.1. # # Report bugs to . # @@ -590,8 +590,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='klish' PACKAGE_TARNAME='klish' -PACKAGE_VERSION='2.0.3' -PACKAGE_STRING='klish 2.0.3' +PACKAGE_VERSION='2.1.1' +PACKAGE_STRING='klish 2.1.1' PACKAGE_BUGREPORT='serj.kalichev at gmail dot com' PACKAGE_URL='' @@ -784,6 +784,7 @@ with_lua with_libroxml with_libexpat with_libxml2 +with_libxslt with_internal_getopt ' ac_precious_vars='build_alias @@ -1337,7 +1338,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures klish 2.0.3 to adapt to many kinds of systems. +\`configure' configures klish 2.1.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1407,7 +1408,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of klish 2.0.3:";; + short | recursive ) echo "Configuration of klish 2.1.1:";; esac cat <<\_ACEOF @@ -1446,6 +1447,8 @@ Optional Packages: [default=no] --with-libxml2=DIR Use libxml2 as the XML parser implementation [default=no] + --with-libxslt=DIR Use libxslt as the XSLT transform engine + [default=no]. Depend on libxml2 library. --with-internal-getopt Use internal implementation of getopt [default=no] Some influential environment variables: @@ -1526,7 +1529,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -klish configure 2.0.3 +klish configure 2.1.1 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2078,7 +2081,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by klish $as_me 2.0.3, which was +It was created by klish $as_me 2.1.1, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -12420,7 +12423,7 @@ fi # Define the identity of the package. PACKAGE='klish' - VERSION='2.0.3' + VERSION='2.1.1' cat >>confdefs.h <<_ACEOF @@ -13952,6 +13955,88 @@ if test $count_xml_backends -eq 0; then $as_echo "$as_me: I found a suitable XML backend: $found_xml_backend" >&6;} fi +# LIBXSLT + +# Check whether --with-libxslt was given. +if test "${with_libxslt+set}" = set; then : + withval=$with_libxslt; use_libxslt=$withval +else + use_libxslt=no +fi + + +if test "x$use_libxslt" != "xno" -a "$found_xml_backend" != "libxml2"; then + as_fn_error $? "The libxml2 is necessary for libxslt" "$LINENO" 5 +fi + +################################ +# Check for the libxslt transform engine +################################ + +if test x$use_libxslt != xno; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for xsltApplyStylesheet in -lxslt" >&5 +$as_echo_n "checking for xsltApplyStylesheet in -lxslt... " >&6; } +if ${ac_cv_lib_xslt_xsltApplyStylesheet+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lxslt $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char xsltApplyStylesheet (); +int +main () +{ +return xsltApplyStylesheet (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_xslt_xsltApplyStylesheet=yes +else + ac_cv_lib_xslt_xsltApplyStylesheet=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_xslt_xsltApplyStylesheet" >&5 +$as_echo "$ac_cv_lib_xslt_xsltApplyStylesheet" >&6; } +if test "x$ac_cv_lib_xslt_xsltApplyStylesheet" = xyes; then : + libxslt_lib_found=yes +else + libxslt_lib_found=no +fi + + if test "x$libxslt_lib_found" != "xyes"; then + as_fn_error $? "Can't find an XSLT library" "$LINENO" 5 + fi + XSLT_CFLAGS="`pkg-config libxslt --cflags 2>/dev/null`" + XSLT_LDFLAGS="`pkg-config libxslt --libs-only-L 2>/dev/null`" + XSLT_LIBS="`pkg-config libxslt --libs-only-l 2>/dev/null`" + if test "x${XSLT_LIBS}" = "x"; then + XSLT_LIBS="-lxslt" + fi + XML_CFLAGS="${XML_CFLAGS} ${XSLT_CFLAGS}" + XML_LDFLAGS="${XML_LDFLAGS} ${XSLT_LDFLAGS}" + XML_LIBS="${XML_LIBS} ${XSLT_LIBS}" + +$as_echo "#define HAVE_LIB_LIBXSLT /**/" >>confdefs.h + +fi + +################################ +# Common XML related subst +################################ + @@ -14849,7 +14934,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by klish $as_me 2.0.3, which was +This file was extended by klish $as_me 2.1.1, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -14915,7 +15000,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -klish config.status 2.0.3 +klish config.status 2.1.1 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 5afb29f..2b534bc 100644 --- a/configure.ac +++ b/configure.ac @@ -1,8 +1,8 @@ # -*- Autoconf -*- # Process this file with autoconf to produce a configure script. m4_define([MAJOR_VERSION], 2) -m4_define([MINOR_VERSION], 0) -m4_define([MICRO_VERSION], 3) +m4_define([MINOR_VERSION], 1) +m4_define([MICRO_VERSION], 1) AC_PREREQ(2.59) AC_INIT([klish], @@ -475,6 +475,42 @@ if test $count_xml_backends -eq 0; then AC_MSG_NOTICE([I found a suitable XML backend: $found_xml_backend]) fi +# LIBXSLT +AC_ARG_WITH(libxslt, + [AS_HELP_STRING([--with-libxslt=DIR], + [Use libxslt as the XSLT transform engine [default=no]. Depend on libxml2 library.])], + [use_libxslt=$withval], + [use_libxslt=no]) + +if test "x$use_libxslt" != "xno" -a "$found_xml_backend" != "libxml2"; then + AC_MSG_ERROR([The libxml2 is necessary for libxslt]) +fi + +################################ +# Check for the libxslt transform engine +################################ + +if test x$use_libxslt != xno; then + AC_CHECK_LIB([xslt], [xsltApplyStylesheet], [libxslt_lib_found=yes], [libxslt_lib_found=no]) + if test "x$libxslt_lib_found" != "xyes"; then + AC_MSG_ERROR([Can't find an XSLT library]) + fi + XSLT_CFLAGS="`pkg-config libxslt --cflags 2>/dev/null`" + XSLT_LDFLAGS="`pkg-config libxslt --libs-only-L 2>/dev/null`" + XSLT_LIBS="`pkg-config libxslt --libs-only-l 2>/dev/null`" + if test "x${XSLT_LIBS}" = "x"; then + XSLT_LIBS="-lxslt" + fi + XML_CFLAGS="${XML_CFLAGS} ${XSLT_CFLAGS}" + XML_LDFLAGS="${XML_LDFLAGS} ${XSLT_LDFLAGS}" + XML_LIBS="${XML_LIBS} ${XSLT_LIBS}" + AC_DEFINE([HAVE_LIB_LIBXSLT], [], [libxslt XML transform engine]) +fi + +################################ +# Common XML related subst +################################ + AC_SUBST(XML_LIBS) AC_SUBST(XML_LDFLAGS) AC_SUBST(XML_CFLAGS) diff --git a/contrib/debian/clish/root-view.xml b/contrib/debian/clish/root-view.xml deleted file mode 100644 index 71be612..0000000 --- a/contrib/debian/clish/root-view.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - diff --git a/contrib/debian/clish/startup.xml b/contrib/debian/clish/startup.xml deleted file mode 100644 index ad30749..0000000 --- a/contrib/debian/clish/startup.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - -CONTEXT SENSITIVE HELP -[?] - Display context sensitive help. This is either a list of possible - command completions with summaries, or the full syntax of the - current command. A subsequent repeat of this key, when a command - has been resolved, will display a detailed reference. - -AUTO-COMPLETION -The following keys both perform auto-completion for the current command line. -If the command prefix is not unique then the bell will ring and a subsequent -repeat of the key will display possible completions. - -[enter] - Auto-completes, syntax-checks then executes a command. If there is - a syntax error then offending part of the command line will be - highlighted and explained. - -[space] - Auto-completes, or if the command is already resolved inserts a space. - -MOVEMENT KEYS -[CTRL-A] - Move to the start of the line -[CTRL-E] - Move to the end of the line. -[up] - Move to the previous command line held in history. -[down] - Move to the next command line held in history. -[left] - Move the insertion point left one character. -[right] - Move the insertion point right one character. - -DELETION KEYS -[CTRL-C] - Delete and abort the current line -[CTRL-D] - Delete the character to the right on the insertion point. -[CTRL-K] - Delete all the characters to the right of the insertion point. -[CTRL-U] - Delete the whole line. -[backspace] - Delete the character to the left of the insertion point. - -ESCAPE SEQUENCES -!! - Subsitute the the last command line. -!N - Substitute the Nth command line (absolute as per 'history' command) -!-N - Substitute the command line entered N lines before (relative) - - - - Welcome to Clish - - - - diff --git a/contrib/debian/konfd b/contrib/debian/konfd deleted file mode 100755 index 38a4d1d..0000000 --- a/contrib/debian/konfd +++ /dev/null @@ -1,137 +0,0 @@ -#! /bin/sh -### BEGIN INIT INFO -# Provides: kondf -# Required-Start: $remote_fs -# Required-Stop: $remote_fs -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: Konfd initscript -# Description: Klish configuration daemon -### END INIT INFO - -# Author: Nixus Networks -# -# Please remove the "Author" lines above and replace them -# with your own name if you copy and modify this script. - -# Do NOT "set -e" - -# PATH should only include /usr/* if it runs after the mountnfs.sh script -PATH=/sbin:/usr/sbin:/bin:/usr/bin -DESC="Klish configuration daemon" -NAME=gluff -DAEMON=/usr/sbin/$NAME -PIDFILE=/var/run/$NAME.pid -SCRIPTNAME=/etc/init.d/$NAME - -# Exit if the package is not installed -[ -x "$DAEMON" ] || exit 0 - -# Read configuration variable file if it is present -[ -r /etc/default/$NAME ] && . /etc/default/$NAME - -# Load the VERBOSE setting and other rcS variables -. /lib/init/vars.sh - -# Define LSB log_* functions. -# Depend on lsb-base (>= 3.2-14) to ensure that this file is present -# and status_of_proc is working. -. /lib/lsb/init-functions - -DAEMON_ARGS="-l $QUEUE_DB -h $MYSQL_HOST -u $MYSQL_USER -p $MYSQL_PASSWD -d $MYSQL_DB $OPTIONS" - -# -# Function that starts the daemon/service -# -do_start() -{ - log_daemon_msg "Starting $DESC" "$NAME" - start-stop-daemon --start --quiet --exec $DAEMON -- $DAEMON_ARGS - ps -fe | grep $DAEMON | head -n1 | cut -d" " -f 6 > ${PIDFILE} - - log_end_msg $? -} - -# -# Function that stops the daemon/service -# -do_stop() -{ - log_daemon_msg "Stopping $DESC" "$NAME" - start-stop-daemon --stop --quiet --pidfile "$PIDFILE" - log_end_msg $? - rm -f "$PIDFILE" -} - - -# -# Function that sends a SIGHUP to the daemon/service -# -do_reload() { - # - # If the daemon can reload its configuration without - # restarting (for example, when it is sent a SIGHUP), - # then implement that here. - # - start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME - return 0 -} - -case "$1" in - start) - [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" - do_start - case "$?" in - 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; - 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; - esac - ;; - stop) - [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" - do_stop - case "$?" in - 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; - 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; - esac - ;; - status) - status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? - ;; - #reload|force-reload) - # - # If do_reload() is not implemented then leave this commented out - # and leave 'force-reload' as an alias for 'restart'. - # - #log_daemon_msg "Reloading $DESC" "$NAME" - #do_reload - #log_end_msg $? - #;; - restart|force-reload) - # - # If the "reload" option is implemented then remove the - # 'force-reload' alias - # - do_stop - case "$?" in - 0|1) - do_start - case "$?" in - 0) log_end_msg 0 ;; - 1) log_end_msg 1 ;; # Old process is still running - *) log_end_msg 1 ;; # Failed to start - esac - ;; - *) - # Failed to stop - log_end_msg 1 - ;; - esac - ;; - *) - #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2 - echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2 - exit 3 - ;; -esac - -: diff --git a/contrib/openwrt/Makefile b/contrib/openwrt/Makefile index 895820d..2b4f743 100644 --- a/contrib/openwrt/Makefile +++ b/contrib/openwrt/Makefile @@ -1,5 +1,5 @@ # -# Copyright (C) 2012 OpenWrt.org +# Copyright (C) 2014-2015 Emmanuel Deloget # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=klish -PKG_VERSION:=1.5.4 +PKG_VERSION:=2.0.4 PKG_RELEASE:=1 -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 -PKG_SOURCE_URL:=http://klish.googlecode.com/files -PKG_MD5SUM:=c98a1c65f7538c3f4687c6f8039295df +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz +PKG_SOURCE_URL:=http://libcode.org/attachments/download/55/ +PKG_MD5SUM:=f71d9948705da50094d7b7129fe39275 PKG_INSTALL:=1 @@ -28,7 +28,7 @@ endef define Package/klish $(call Package/klish/default,main tool) - DEPENDS:=+libstdcpp + DEPENDS:=+libroxml endef define Package/konf @@ -56,20 +56,23 @@ define Package/konf/description More information about these tools is to be found on the klish web site. endef +CONFIGURE_ARGS += \ + --with-libroxml + define Package/klish/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/clish $(1)/usr/bin/ - $(INSTALL_DIR) $(1)/usr/lib - $(CP) $(PKG_INSTALL_DIR)/usr/lib/*.so* $(1)/usr/lib/ + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/clish $(1)/usr/bin/ + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/*.so* $(1)/usr/lib/ endef define Package/konf/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/konf $(1)/usr/bin/ - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/konfd $(1)/usr/bin/ - $(INSTALL_DIR) $(1)/usr/lib - $(CP) $(PKG_INSTALL_DIR)/usr/lib/libkonf.so* $(1)/usr/lib/ - $(CP) $(PKG_INSTALL_DIR)/usr/lib/liblub.so* $(1)/usr/lib/ + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/konf $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/konfd $(1)/usr/bin/ + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libkonf.so* $(1)/usr/lib/ + $(CP) $(PKG_INSTALL_DIR)/usr/lib/liblub.so* $(1)/usr/lib/ endef $(eval $(call BuildPackage,klish)) @@ -89,8 +92,8 @@ define Package/klish-xml-files/description endef define Package/klish-xml-files/install - $(INSTALL_DIR) $(1)/etc/clish - $(CP) $(PKG_BUILD_DIR)/xml-examples/clish $(1)/etc/clish/ + $(INSTALL_DIR) $(1)/etc/clish + $(CP) $(PKG_BUILD_DIR)/xml-examples/clish $(1)/etc/clish/ endef $(eval $(call BuildPackage,klish-xml-files)) diff --git a/konf/buf.h b/konf/buf.h index e7a74de..49aef9f 100644 --- a/konf/buf.h +++ b/konf/buf.h @@ -43,6 +43,7 @@ int konf_buf_lseek(konf_buf_t *instance, int newpos); int konf_buf__get_fd(const konf_buf_t *instance); int konf_buf__get_len(const konf_buf_t *instance); char * konf_buf__dup_line(const konf_buf_t *instance); +char * konf_buf__get_buf(const konf_buf_t *instance); void * konf_buf__get_data(const konf_buf_t *instance); void konf_buf__set_data(konf_buf_t *instance, void *data); diff --git a/konf/buf/buf.c b/konf/buf/buf.c index 5fe4ca9..677e13b 100644 --- a/konf/buf/buf.c +++ b/konf/buf/buf.c @@ -239,6 +239,12 @@ char * konf_buf__dup_line(const konf_buf_t *this) return str; } +/*--------------------------------------------------------- */ +char * konf_buf__get_buf(const konf_buf_t *this) +{ + return this->buf; +} + /*--------------------------------------------------------- */ void * konf_buf__get_data(const konf_buf_t *this) { diff --git a/konf/query.h b/konf/query.h index a894204..b975272 100644 --- a/konf/query.h +++ b/konf/query.h @@ -12,7 +12,7 @@ typedef enum KONF_QUERY_OP_UNSET, KONF_QUERY_OP_STREAM, KONF_QUERY_OP_DUMP -} konf_query_op_t; +} konf_query_op_e; typedef struct konf_query_s konf_query_t; @@ -24,7 +24,7 @@ void konf_query_dump(konf_query_t *instance); char *konf_query__get_pwd(konf_query_t *instance, unsigned index); int konf_query__get_pwdc(konf_query_t *instance); -konf_query_op_t konf_query__get_op(konf_query_t *instance); +konf_query_op_e konf_query__get_op(konf_query_t *instance); char * konf_query__get_path(konf_query_t *instance); const char * konf_query__get_pattern(konf_query_t *instance); const char * konf_query__get_line(konf_query_t *instance); diff --git a/konf/query/private.h b/konf/query/private.h index 21de935..7e8e65f 100644 --- a/konf/query/private.h +++ b/konf/query/private.h @@ -5,7 +5,7 @@ #include "lub/types.h" struct konf_query_s { - konf_query_op_t op; + konf_query_op_e op; char *pattern; unsigned short priority; bool_t seq; /* sequence aka auto priority */ diff --git a/konf/query/query.c b/konf/query/query.c index 1b5008a..0ec618f 100644 --- a/konf/query/query.c +++ b/konf/query/query.c @@ -259,7 +259,7 @@ int konf_query__get_pwdc(konf_query_t *this) } /*-------------------------------------------------------- */ -konf_query_op_t konf_query__get_op(konf_query_t *this) +konf_query_op_e konf_query__get_op(konf_query_t *this) { return this->op; } diff --git a/plugins/clish/builtin_init.c b/plugins/clish/builtin_init.c index 84e8147..c2fb9fd 100644 --- a/plugins/clish/builtin_init.c +++ b/plugins/clish/builtin_init.c @@ -29,7 +29,7 @@ CLISH_PLUGIN_INIT(clish) clish_plugin_add_psym(plugin, clish_nop, "clish_nop"); clish_plugin_add_psym(plugin, clish_wdog, "clish_wdog"); clish_plugin_add_psym(plugin, clish_macros, "clish_macros"); - clish_plugin_add_sym(plugin, clish_script, "clish_script"); + clish_plugin_add_osym(plugin, clish_script, "clish_script"); clish_shell = clish_shell; /* Happy compiler */ diff --git a/plugins/clish/hook_config.c b/plugins/clish/hook_config.c index ffd4a0a..a59c4df 100644 --- a/plugins/clish/hook_config.c +++ b/plugins/clish/hook_config.c @@ -62,7 +62,7 @@ CLISH_HOOK_CONFIG(clish_hook_config) char *str = NULL; char *tstr; char tmp[PATH_MAX + 100]; - clish_config_op_t op; + clish_config_op_e op; unsigned int num; const char *escape_chars = lub_string_esc_quoted; diff --git a/plugins/clish/private.h b/plugins/clish/private.h index 479cee1..0348264 100644 --- a/plugins/clish/private.h +++ b/plugins/clish/private.h @@ -19,5 +19,5 @@ 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); +CLISH_PLUGIN_OSYM(clish_script); CLISH_PLUGIN_SYM(clish_macros); diff --git a/plugins/clish/sym_script.c b/plugins/clish/sym_script.c index 5d0560f..df13ce1 100644 --- a/plugins/clish/sym_script.c +++ b/plugins/clish/sym_script.c @@ -21,7 +21,7 @@ #include /*--------------------------------------------------------- */ -CLISH_PLUGIN_SYM(clish_script) +CLISH_PLUGIN_OSYM(clish_script) { clish_shell_t *this = clish_context__get_shell(clish_context); const clish_action_t *action = clish_context__get_action(clish_context); @@ -29,15 +29,9 @@ CLISH_PLUGIN_SYM(clish_script) pid_t cpid = -1; int res; const char *fifo_name; - FILE *rpipe, *wpipe; + FILE *wpipe; char *command = NULL; - /* Signal vars */ - struct sigaction sig_old_int; - struct sigaction sig_old_quit; - struct sigaction sig_new; - sigset_t sig_set; - assert(this); if (!script) /* Nothing to do */ return 0; @@ -75,7 +69,7 @@ CLISH_PLUGIN_SYM(clish_script) wpipe = fopen(fifo_name, "w"); if (!wpipe) _exit(-1); - fwrite(script, strlen(script) + 1, 1, wpipe); + fwrite(script, strlen(script), 1, wpipe); fclose(wpipe); _exit(0); } @@ -86,53 +80,12 @@ CLISH_PLUGIN_SYM(clish_script) lub_string_cat(&command, " "); lub_string_cat(&command, fifo_name); - /* If the stdout of script is needed */ - if (out) { - konf_buf_t *buf; - - /* Ignore SIGINT and SIGQUIT */ - sigemptyset(&sig_set); - sig_new.sa_flags = 0; - sig_new.sa_mask = sig_set; - sig_new.sa_handler = SIG_IGN; - sigaction(SIGINT, &sig_new, &sig_old_int); - sigaction(SIGQUIT, &sig_new, &sig_old_quit); - - /* Execute shebang with FIFO as argument */ - rpipe = popen(command, "r"); - if (!rpipe) { - fprintf(stderr, "Error: Can't fork the script.\n" - "Error: The ACTION will be not executed.\n"); - lub_string_free(command); - kill(cpid, SIGTERM); - waitpid(cpid, NULL, 0); - - /* Restore SIGINT and SIGQUIT */ - sigaction(SIGINT, &sig_old_int, NULL); - sigaction(SIGQUIT, &sig_old_quit, NULL); + res = system(command); - return -1; - } - /* Read the result of script execution */ - buf = konf_buf_new(fileno(rpipe)); - while (konf_buf_read(buf) > 0); - *out = konf_buf__dup_line(buf); - konf_buf_delete(buf); - /* Wait for the writing process */ - kill(cpid, SIGTERM); - waitpid(cpid, NULL, 0); - /* Wait for script */ - res = pclose(rpipe); + /* Wait for the writing process */ + kill(cpid, SIGTERM); + waitpid(cpid, NULL, 0); - /* Restore SIGINT and SIGQUIT */ - sigaction(SIGINT, &sig_old_int, NULL); - sigaction(SIGQUIT, &sig_old_quit, NULL); - } else { - res = system(command); - /* Wait for the writing process */ - kill(cpid, SIGTERM); - waitpid(cpid, NULL, 0); - } lub_string_free(command); #ifdef DEBUG @@ -140,5 +93,3 @@ CLISH_PLUGIN_SYM(clish_script) #endif /* DEBUG */ return WEXITSTATUS(res); } - -/*--------------------------------------------------------- */ diff --git a/tinyrl/vt100.h b/tinyrl/vt100.h index ca344da..ebac002 100644 --- a/tinyrl/vt100.h +++ b/tinyrl/vt100.h @@ -78,7 +78,7 @@ typedef enum { tinyrl_vt100_DELETE, /**< Delete character on the right */ tinyrl_vt100_PGUP, /**< No action at the moment */ tinyrl_vt100_PGDOWN /**< No action at the moment */ -} tinyrl_vt100_escape_t; +} tinyrl_vt100_escape_e; /* Return values from vt100_getchar() */ #define VT100_EOF -1 @@ -108,7 +108,7 @@ tinyrl_vt100__set_istream(tinyrl_vt100_t * instance, FILE * istream); extern FILE *tinyrl_vt100__get_istream(const tinyrl_vt100_t * instance); extern FILE *tinyrl_vt100__get_ostream(const tinyrl_vt100_t * instance); -extern tinyrl_vt100_escape_t +extern tinyrl_vt100_escape_e tinyrl_vt100_escape_decode(const tinyrl_vt100_t * instance, const char *esc_seq); extern void tinyrl_vt100_ding(const tinyrl_vt100_t * instance); extern void tinyrl_vt100_attribute_reset(const tinyrl_vt100_t * instance); diff --git a/tinyrl/vt100/vt100.c b/tinyrl/vt100/vt100.c index e952c97..15b71d1 100644 --- a/tinyrl/vt100/vt100.c +++ b/tinyrl/vt100/vt100.c @@ -14,7 +14,7 @@ typedef struct { const char* sequence; - tinyrl_vt100_escape_t code; + tinyrl_vt100_escape_e code; } vt100_decode_t; /* This table maps the vt100 escape codes to an enumeration */ @@ -34,10 +34,10 @@ static vt100_decode_t cmds[] = { }; /*--------------------------------------------------------- */ -tinyrl_vt100_escape_t tinyrl_vt100_escape_decode(const tinyrl_vt100_t *this, +tinyrl_vt100_escape_e tinyrl_vt100_escape_decode(const tinyrl_vt100_t *this, const char *esc_seq) { - tinyrl_vt100_escape_t result = tinyrl_vt100_UNKNOWN; + tinyrl_vt100_escape_e result = tinyrl_vt100_UNKNOWN; unsigned int i; /* Decode the sequence to macros */