diff --git a/CHANGELOG.md b/CHANGELOG.md index e82e5dfe..6353a40e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Clixon Changelog +## 4.3.0 (Expected: ~December 2019) + +### Minor changes +* Added wildcard `*` as a mode to `CLICON_MODE` in clispec files + * If you set "CLICON_MODE="*";" in a clispec file it means that syntax will appear in all CLI spec modes. + +### Corrected Bugs +* [Add missing includes](https://github.com/clicon/clixon/pulls) + ## 4.2.0 (October 27 2019) ### Summary @@ -12,7 +21,7 @@ The main improvement in thus release concerns security in terms of priveleges an * use `-U ` clixon_backend command-line option to drop to `user` * Generic options are the following: * `CLICON_BACKEND_USER` sets the user to drop priveleges to - * CLICON_BACKEND_PRIVELEGES can have the following values: + * `CLICON_BACKEND_PRIVELEGES` can have the following values: * `none` Make no drop/change in privileges. This is currently the default. * `drop_perm` After initialization, drop privileges permanently * `drop_perm` After initialization, drop privileges temporarily (to a euid) diff --git a/apps/backend/clixon_backend_handle.c b/apps/backend/clixon_backend_handle.c index cd320bd2..6f5ca55e 100644 --- a/apps/backend/clixon_backend_handle.c +++ b/apps/backend/clixon_backend_handle.c @@ -46,7 +46,6 @@ #include #include #include -#include #include #include #include diff --git a/apps/cli/cli_handle.c b/apps/cli/cli_handle.c index 01fd3e32..7b0ebc79 100644 --- a/apps/cli/cli_handle.c +++ b/apps/cli/cli_handle.c @@ -162,10 +162,10 @@ cli_cligen(clicon_handle h) int cli_parse_file(clicon_handle h, - FILE *f, - char *name, /* just for errs */ - parse_tree *pt, - cvec *globals) + FILE *f, + char *name, /* just for errs */ + parse_tree *pt, + cvec *globals) { cligen_handle ch = cligen(h); @@ -182,7 +182,7 @@ cli_susp_hook(clicon_handle h, return cligen_susp_hook(ch, fn); } int -cli_interrupt_hook(clicon_handle h, +cli_interrupt_hook(clicon_handle h, cligen_interrupt_cb_t *fn) { cligen_handle ch = cligen(h); @@ -200,14 +200,16 @@ cli_nomatch(clicon_handle h) } int -cli_prompt_set(clicon_handle h, char *prompt) +cli_prompt_set(clicon_handle h, + char *prompt) { cligen_handle ch = cligen(h); return cligen_prompt_set(ch, prompt); } int -cli_logsyntax_set(clicon_handle h, int status) +cli_logsyntax_set(clicon_handle h, + int status) { cligen_handle ch = cligen(h); return cligen_logsyntax_set(ch, status); diff --git a/apps/cli/cli_plugin.c b/apps/cli/cli_plugin.c index 31331f21..964c4497 100644 --- a/apps/cli/cli_plugin.c +++ b/apps/cli/cli_plugin.c @@ -45,7 +45,6 @@ #include #include #include -#include #include #include #include @@ -209,27 +208,29 @@ clixon_str2fn(char *name, return NULL; } -/*! Append to syntax mode from file - * @param[in] h Clixon handle - * @param[in] filename Name of file where syntax is specified (in syntax-group dir) - * @param[in] dir Name of dir, or NULL +/*! Load a file containing syntax and append to specified modes, also load C plugin + * @param[in] h Clixon handle + * @param[in] filename Name of file where syntax is specified (in syntax-group dir) + * @param[in] dir Name of dir, or NULL + * @param[out] allpt Universal CLIgen parse tree: apply to all modes */ static int -cli_load_syntax(clicon_handle h, - const char *filename, - const char *dir) +cli_load_syntax_file(clicon_handle h, + const char *filename, + const char *dir, + parse_tree *ptall) { - void *handle = NULL; /* Handle to plugin .so module */ - char *mode = NULL; /* Name of syntax mode to append new syntax */ - parse_tree pt = {0,}; - int retval = -1; - FILE *f; - char filepath[MAXPATHLEN]; - cvec *cvv = NULL; - char *prompt = NULL; - char **vec = NULL; - int i, nvec; - char *plgnam; + void *handle = NULL; /* Handle to plugin .so module */ + char *mode = NULL; /* Name of syntax mode to append new syntax */ + parse_tree pt = {0,}; + int retval = -1; + FILE *f; + char filepath[MAXPATHLEN]; + cvec *cvv = NULL; + char *prompt = NULL; + char **vec = NULL; + int i, nvec; + char *plgnam; clixon_plugin *cp; if (dir) @@ -253,10 +254,18 @@ cli_load_syntax(clicon_handle h, goto done; } fclose(f); - /* Get CLICON specific global variables */ + /* Get CLICON specific global variables: + * CLICON_MODE: which mode(s) this syntax applies to + * CLICON_PROMPT: Cli prompt in this mode + * CLICON_PLUGIN: Name of C API plugin + * Note: the base case is that it is: + * (1) a single mode or + * (2) "*" all modes or "m1:m2" - a list of modes + * but for (2), prompt and plgnam may have unclear semantics + */ + mode = cvec_find_str(cvv, "CLICON_MODE"); prompt = cvec_find_str(cvv, "CLICON_PROMPT"); plgnam = cvec_find_str(cvv, "CLICON_PLUGIN"); - mode = cvec_find_str(cvv, "CLICON_MODE"); if (plgnam != NULL) { /* Find plugin for callback resolving */ if ((cp = clixon_plugin_find(h, plgnam)) != NULL) @@ -288,8 +297,19 @@ cli_load_syntax(clicon_handle h, goto done; } } + /* Find all modes in CLICON_MODE string: where to append the pt syntax tree */ if ((vec = clicon_strsep(mode, ":", &nvec)) == NULL) goto done; + + if (nvec == 1 && strcmp(vec[0], "*") == 0){ + /* Special case: Add this to all modes. Add to special "universal" syntax + * and add to all syntaxes after all files have been loaded. At this point + * all modes may not be known (not yet loaded) + */ + if (cligen_parsetree_merge(ptall, NULL, pt) < 0) + return -1; + } + else { for (i = 0; i < nvec; i++) { if (syntax_append(h, cli_syntax(h), @@ -300,6 +320,7 @@ cli_load_syntax(clicon_handle h, if (prompt) cli_set_prompt(h, vec[i], prompt); } + } cligen_parsetree_free(pt, 1); retval = 0; @@ -329,6 +350,7 @@ cli_syntax_load(clicon_handle h) cligen_susp_cb_t *fns = NULL; cligen_interrupt_cb_t *fni = NULL; clixon_plugin *cp; + parse_tree ptall = {0,}; /* Universal CLIgen parse tree all modes */ /* Syntax already loaded. XXX should we re-load?? */ if ((stx = cli_syntax(h)) != NULL) @@ -347,30 +369,38 @@ cli_syntax_load(clicon_handle h) cli_syntax_set(h, stx); + /* Load single specific clispec file */ if (clispec_file){ - if (cli_load_syntax(h, clispec_file, NULL) < 0) + if (cli_load_syntax_file(h, clispec_file, NULL, &ptall) < 0) goto done; } + /* Load all clispec .cli files in directory */ if (clispec_dir){ - /* load syntaxfiles */ + /* Get directory list of files */ if ((ndp = clicon_file_dirent(clispec_dir, &dp, "(.cli)$", S_IFREG)) < 0) goto done; - /* Load the rest */ + /* Load the syntax parse trees into cli_syntax stx structure */ for (i = 0; i < ndp; i++) { clicon_debug(1, "DEBUG: Loading syntax '%.*s'", (int)strlen(dp[i].d_name)-4, dp[i].d_name); - if (cli_load_syntax(h, dp[i].d_name, clispec_dir) < 0) + if (cli_load_syntax_file(h, dp[i].d_name, clispec_dir, &ptall) < 0) goto done; } } - /* Did we successfully load any syntax modes? */ + /* Were any syntax modes successfully loaded? If not, leave */ if (stx->stx_nmodes <= 0) { retval = 0; goto done; } - /* Parse syntax tree for all modes */ + + /* Go thorugh all modes and : + * 1) Add the universal syntax + * 2) add syntax tree (of those modes - "activate" syntax from stx to CLIgen) + */ m = stx->stx_modes; do { + if (cligen_parsetree_merge(&m->csm_pt, NULL, ptall) < 0) + return -1; if (gen_parse_tree(h, m) != 0) goto done; m = NEXTQ(cli_syntaxmode_t *, m); @@ -389,13 +419,13 @@ cli_syntax_load(clicon_handle h) /* All good. We can now proudly return a new group */ retval = 0; - done: if (retval != 0) { clixon_plugin_exit(h); cli_syntax_unload(h); cli_syntax_set(h, NULL); } + cligen_parsetree_free(ptall, 1); if (dp) free(dp); return retval; diff --git a/configure b/configure index 2bf8b1a8..124aadbc 100755 --- a/configure +++ b/configure @@ -2172,9 +2172,9 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu : ${INSTALLFLAGS="-s"} CLIXON_VERSION_MAJOR="4" -CLIXON_VERSION_MINOR="2" +CLIXON_VERSION_MINOR="3" CLIXON_VERSION_PATCH="0" -CLIXON_VERSION="\"${CLIXON_VERSION_MAJOR}.${CLIXON_VERSION_MINOR}.${CLIXON_VERSION_PATCH}\"" +CLIXON_VERSION="\"${CLIXON_VERSION_MAJOR}.${CLIXON_VERSION_MINOR}.${CLIXON_VERSION_PATCH}.PRE\"" # Check CLIgen if test "$prefix" = "NONE"; then diff --git a/configure.ac b/configure.ac index fa281d81..c3cd8d3e 100644 --- a/configure.ac +++ b/configure.ac @@ -43,9 +43,9 @@ AC_INIT(lib/clixon/clixon.h.in) : ${INSTALLFLAGS="-s"} CLIXON_VERSION_MAJOR="4" -CLIXON_VERSION_MINOR="2" +CLIXON_VERSION_MINOR="3" CLIXON_VERSION_PATCH="0" -CLIXON_VERSION="\"${CLIXON_VERSION_MAJOR}.${CLIXON_VERSION_MINOR}.${CLIXON_VERSION_PATCH}\"" +CLIXON_VERSION="\"${CLIXON_VERSION_MAJOR}.${CLIXON_VERSION_MINOR}.${CLIXON_VERSION_PATCH}.PRE\"" # Check CLIgen if test "$prefix" = "NONE"; then diff --git a/doc/DEVELOP.md b/doc/DEVELOP.md index 46b69d74..834c1e58 100644 --- a/doc/DEVELOP.md +++ b/doc/DEVELOP.md @@ -122,6 +122,12 @@ After release: ``` * Run autoconf +Create release branch: +``` + git checkout -b release-4.2 4.2.0 + git push origin release-4.2 +``` + ## Use of constants etc -Use MAXPATHLEN (not PATH_MAX) \ No newline at end of file +Use MAXPATHLEN (not PATH_MAX) diff --git a/example/main/example_cli.c b/example/main/example_cli.c index 8cc88abf..04658d2e 100644 --- a/example/main/example_cli.c +++ b/example/main/example_cli.c @@ -43,7 +43,6 @@ #include #include #include -#include /* matching strings */ #include /* matching strings */ /* clicon */ diff --git a/lib/clixon/clixon.h.in b/lib/clixon/clixon.h.in index c810acd9..7de4a0d0 100644 --- a/lib/clixon/clixon.h.in +++ b/lib/clixon/clixon.h.in @@ -51,20 +51,14 @@ #include /* MAXPATHLEN */ /* - * CLIXON version macros + * CLIXON version macros, set in configure and resolved when expanding to + * clixon.h */ - #undef CLIXON_VERSION_STRING #undef CLIXON_VERSION_MAJOR #undef CLIXON_VERSION_MINOR #undef CLIXON_VERSION_PATCH -/* - * Use this constant to disable some prototypes that should not be visible outside the lib. - * This is an alternative to use separate internal include files. - */ -#define LIBCLIXON_API 1 - #include #include #include diff --git a/lib/clixon/clixon_string.h b/lib/clixon/clixon_string.h index 90717b74..10ff73a3 100644 --- a/lib/clixon/clixon_string.h +++ b/lib/clixon/clixon_string.h @@ -58,6 +58,10 @@ typedef struct map_str2int map_str2int; /*! A malloc version that aligns on 4 bytes. To avoid warning from valgrind */ #define align4(s) (((s)/4)*4 + 4) +/* Required for the inline to compile */ +#include +#include + /*! A strdup version that aligns on 4 bytes. To avoid warning from valgrind */ static inline char * strdup4(char *str) { diff --git a/lib/src/clixon_datastore_read.c b/lib/src/clixon_datastore_read.c index 2150502c..62921c6b 100644 --- a/lib/src/clixon_datastore_read.c +++ b/lib/src/clixon_datastore_read.c @@ -42,7 +42,6 @@ #include #include #include -#include #include #include #include diff --git a/lib/src/clixon_datastore_write.c b/lib/src/clixon_datastore_write.c index 8ddc69fb..b6f294da 100644 --- a/lib/src/clixon_datastore_write.c +++ b/lib/src/clixon_datastore_write.c @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include diff --git a/lib/src/clixon_json.c b/lib/src/clixon_json.c index 6d989e42..d4fb484c 100644 --- a/lib/src/clixon_json.c +++ b/lib/src/clixon_json.c @@ -47,7 +47,6 @@ #include #include #include -#include #include #include #include diff --git a/lib/src/clixon_nacm.c b/lib/src/clixon_nacm.c index 3e2848e1..b0da26e6 100644 --- a/lib/src/clixon_nacm.c +++ b/lib/src/clixon_nacm.c @@ -44,7 +44,6 @@ #include #include #include -#include #include #include #include diff --git a/lib/src/clixon_netconf_lib.c b/lib/src/clixon_netconf_lib.c index 3e7e3c8a..e8601af4 100644 --- a/lib/src/clixon_netconf_lib.c +++ b/lib/src/clixon_netconf_lib.c @@ -46,7 +46,6 @@ #include #include #include -#include #include #include diff --git a/lib/src/clixon_xml.c b/lib/src/clixon_xml.c index 38723f7b..947647e7 100644 --- a/lib/src/clixon_xml.c +++ b/lib/src/clixon_xml.c @@ -46,7 +46,6 @@ #include #include #include -#include #include #include diff --git a/lib/src/clixon_xml_changelog.c b/lib/src/clixon_xml_changelog.c index f74ab713..80cbb0fc 100644 --- a/lib/src/clixon_xml_changelog.c +++ b/lib/src/clixon_xml_changelog.c @@ -45,7 +45,6 @@ #include #include #include -#include #include #include #include diff --git a/lib/src/clixon_xml_nsctx.c b/lib/src/clixon_xml_nsctx.c index c65cab5b..e588c204 100644 --- a/lib/src/clixon_xml_nsctx.c +++ b/lib/src/clixon_xml_nsctx.c @@ -50,7 +50,6 @@ #include #include #include -#include #include #include diff --git a/lib/src/clixon_xml_sort.c b/lib/src/clixon_xml_sort.c index 83b19a61..74e33291 100644 --- a/lib/src/clixon_xml_sort.c +++ b/lib/src/clixon_xml_sort.c @@ -44,7 +44,6 @@ #include #include #include -#include #include #include #include diff --git a/lib/src/clixon_xpath.c b/lib/src/clixon_xpath.c index 3e7a7056..33b094f9 100644 --- a/lib/src/clixon_xpath.c +++ b/lib/src/clixon_xpath.c @@ -65,7 +65,6 @@ #include #include #include -#include #include #include #include diff --git a/lib/src/clixon_xpath_ctx.c b/lib/src/clixon_xpath_ctx.c index 30f44af6..cf8d6a0b 100644 --- a/lib/src/clixon_xpath_ctx.c +++ b/lib/src/clixon_xpath_ctx.c @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include diff --git a/lib/src/clixon_xpath_eval.c b/lib/src/clixon_xpath_eval.c index d6b0eb7b..077c4fb2 100644 --- a/lib/src/clixon_xpath_eval.c +++ b/lib/src/clixon_xpath_eval.c @@ -63,7 +63,6 @@ #include #include #include -#include #include #include #include diff --git a/lib/src/clixon_xpath_parse.y b/lib/src/clixon_xpath_parse.y index f014b6a4..0fdeac5e 100644 --- a/lib/src/clixon_xpath_parse.y +++ b/lib/src/clixon_xpath_parse.y @@ -105,7 +105,6 @@ #include #include #include -#include #include #include #include diff --git a/test/test_cli_submodes.sh b/test/test_cli_submodes.sh new file mode 100755 index 00000000..af77d92e --- /dev/null +++ b/test/test_cli_submodes.sh @@ -0,0 +1,125 @@ +#!/usr/bin/env bash +# CLIgen mode tests +# Have two modes: AAA and BBB +# Have the following clispec files with syntax for: +# 1) * 2) AAA, 3) BBB, 4) CCC, 5) AAA:BBB, 6) BBB:CCC +# Verify then that modes AAA and BBB have right syntax (also negative) +# AAA should have syntax from 1,2,5 (and not 3,4,6) +# BBB should have syntax from 1,3,5,6 (and not 2,4) + +# Magic line must be first in script (see README.md) +s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi + +APPNAME=example + +# include err() and new() functions and creates $dir + +cfg=$dir/conf_yang.xml +clidir=$dir/clidir + +if [ ! -d $clidir ]; then + mkdir $clidir +fi + +# Use yang in example + +cat < $cfg + + $cfg + /usr/local/share/clixon + $IETFRFC + clixon-example + /usr/local/lib/$APPNAME/backend + $clidir + /usr/local/lib/$APPNAME/cli + /usr/local/var/$APPNAME/$APPNAME.sock + /usr/local/var/$APPNAME/$APPNAME.pidfile + /usr/local/var/$APPNAME + +EOF + +# clispec files 1..6 for submodes AAA and BBB as described in top comment + +cat < $clidir/cli1.cli + CLICON_MODE="*"; + cmd1; +EOF + +cat < $clidir/cli2.cli + CLICON_MODE="AAA"; + cmd2; +EOF + +cat < $clidir/cli3.cli + CLICON_MODE="BBB"; + cmd3; +EOF + +cat < $clidir/cli4.cli + CLICON_MODE="CCC"; + cmd4; +EOF + +cat < $clidir/cli5.cli + CLICON_MODE="AAA:BBB"; + cmd5; +EOF + +cat < $clidir/cli6.cli + CLICON_MODE="BBB:CCC"; + cmd6; +EOF + +new "test params: -f $cfg" +if [ $BE -ne 0 ]; then + new "kill old backend" + sudo clixon_backend -z -f $cfg + if [ $? -ne 0 ]; then + err + fi + new "start backend -s init -f $cfg" + start_backend -s init -f $cfg + + new "waiting" + wait_backend +fi + + +m=AAA +# Tests using mode AAA that should pass +for c in 1 2 5; do + new "cli mode $m 1 cmd$c OK" + expectfn "$clixon_cli -1 -m $m -f $cfg cmd$c" 0 "^$" +done +# Tests using mode AAA that should fail +for c in 3 4 6; do + new "cli mode $m 1 cmd$c Not OK" + expectfn "$clixon_cli -1 -m $m -f $cfg cmd$c" 255 "^$" +done + +m=BBB +# Tests using mode BBB that should pass +for c in 1 3 5 6; do + new "cli mode $m 1 cmd$c OK" + expectfn "$clixon_cli -1 -m $m -f $cfg cmd$c" 0 "^$" +done +# Tests using mode BBB that should fail +for c in 2 4; do + new "cli mode $m 1 cmd$c Not OK" + expectfn "$clixon_cli -1 -m $m -f $cfg cmd$c" 255 "^$" +done + +if [ $BE -eq 0 ]; then + exit # BE +fi + +new "Kill backend" +# Check if premature kill +pid=$(pgrep -u root -f clixon_backend) +if [ -z "$pid" ]; then + err "backend already dead" +fi +# kill backend +stop_backend -f $cfg + +rm -rf $dir diff --git a/util/clixon_util_insert.c b/util/clixon_util_insert.c index f4e86e83..d2a6a444 100644 --- a/util/clixon_util_insert.c +++ b/util/clixon_util_insert.c @@ -44,7 +44,6 @@ #include #include #include -#include #include #include #include diff --git a/util/clixon_util_json.c b/util/clixon_util_json.c index c1083690..4c333c96 100644 --- a/util/clixon_util_json.c +++ b/util/clixon_util_json.c @@ -47,7 +47,6 @@ #include #include #include -#include #include #include #include diff --git a/util/clixon_util_stream.c b/util/clixon_util_stream.c index 6b52fb3e..511c62ea 100644 --- a/util/clixon_util_stream.c +++ b/util/clixon_util_stream.c @@ -46,7 +46,6 @@ #include #include #include -#include #include #include #include diff --git a/util/clixon_util_xpath.c b/util/clixon_util_xpath.c index 57d5cac6..de760508 100644 --- a/util/clixon_util_xpath.c +++ b/util/clixon_util_xpath.c @@ -46,7 +46,6 @@ See https://www.w3.org/TR/xpath/ #include #include #include -#include #include #include #include diff --git a/yang/clixon/clixon-config@2019-09-11.yang b/yang/clixon/clixon-config@2019-09-11.yang index 7eb343cd..7dedec8f 100644 --- a/yang/clixon/clixon-config@2019-09-11.yang +++ b/yang/clixon/clixon-config@2019-09-11.yang @@ -338,20 +338,21 @@ module clixon-config { leaf CLICON_CLI_DIR { type string; description - "Location of cli frontend .so plugins. Load all .so - plugins in this dir as CLI object plugins"; + "Directory containing frontend cli loadable plugins. Load all .so + plugins in this directory as CLI object plugins"; } leaf CLICON_CLISPEC_DIR { type string; description - "Location of frontend .cli cligen spec files. Load all .cli - files in this dir as CLI specification files"; + "Directory containing frontend cligen spec files. Load all .cli + files in this directory as CLI specification files. + See also CLICON_CLISPEC_FILE."; } leaf CLICON_CLISPEC_FILE { type string; - description "Specific frontend .cli cligen spec file as simple - alternative to CLICON_CLISPEC_DIR. Also available as - -c in clixon_cli."; + description + "Specific frontend cligen spec file as aletrnative or complement + to CLICON_CLISPEC_DIR. Also available as -c in clixon_cli."; } leaf CLICON_CLI_MODE { type string;