From 772759e42f17a630a86feecf0a937ff9a707274d Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Fri, 1 May 2020 00:42:54 +0200 Subject: [PATCH 1/2] * Compile-time option: `USE_CLIGEN44` for running clixon-45 with cligen-44. * Temporary fix since cligen-45 have some non-backward compatible behaviour. --- CHANGELOG.md | 4 +- apps/cli/cli_handle.c | 9 +++ apps/cli/cli_handle.h | 4 ++ apps/cli/cli_main.c | 38 +++++++++++- apps/cli/cli_plugin.c | 123 +++++++++++++++++++++++++++++++++++++ apps/cli/cli_plugin.h | 6 +- include/clixon_custom.h | 5 ++ lib/clixon/clixon_string.h | 3 + lib/src/clixon_string.c | 63 +++++++++++++++++++ 9 files changed, 252 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d6f3f015..8b2b5d54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,8 @@ Expected: May 2020 ### Minor changes +* Compile-time option: `USE_CLIGEN44` for running clixon-45 with cligen-44. + * Temporary fix since cligen-45 have some non-backward compatible behaviour. * Optimizations * Reduced memory for attribute and body objects, see `XML_NEW_DIFFERENTIATE` compile-time option. * Optimized prefix checks at xml parse time: using many prefixes slowed down parsing considerably @@ -784,7 +786,7 @@ Olof Hagsand * List ordering bug - lists with ints as keys behaved wrongly and slow. * NACM read default rule did not work properly if nacm was enabled AND no groups were defined * Re-inserted `cli_output_reset` for what was erroneuos thought to be an obsolete function - * See in 3.9.0 minro changes: Replaced all calls to (obsolete) `cli_output` with `fprintf` + * See in 3.9.0 minor changes: Replaced all calls to (obsolete) `cli_output` with `fprintf` * Allowed Yang extended Xpath functions (syntax only): * re-match, deref, derived-from, derived-from-or-self, enum-value, bit-is-set * XSD regular expression handling of dash(`-`) diff --git a/apps/cli/cli_handle.c b/apps/cli/cli_handle.c index 70ce3c2d..86a70351 100644 --- a/apps/cli/cli_handle.c +++ b/apps/cli/cli_handle.c @@ -193,6 +193,15 @@ cli_interrupt_hook(clicon_handle h, return cligen_interrupt_hook(ch, fn); } +#ifdef USE_CLIGEN44 +char * +cli_nomatch(clicon_handle h) +{ + cligen_handle ch = cligen(h); + + return cligen_nomatch(ch); +} +#endif int cli_prompt_set(clicon_handle h, char *prompt) diff --git a/apps/cli/cli_handle.h b/apps/cli/cli_handle.h index 20c02321..a9d67cbe 100644 --- a/apps/cli/cli_handle.h +++ b/apps/cli/cli_handle.h @@ -53,6 +53,10 @@ int cli_susp_hook(clicon_handle h, cligen_susp_cb_t *fn); int cli_interrupt_hook(clicon_handle h, cligen_interrupt_cb_t *fn); +#ifdef USE_CLIGEN44 +char *cli_nomatch(clicon_handle h); +#endif + int cli_prompt_set(clicon_handle h, char *prompt); int cli_logsyntax_set(clicon_handle h, int status); diff --git a/apps/cli/cli_main.c b/apps/cli/cli_main.c index d3d49ff6..9ad836ce 100644 --- a/apps/cli/cli_main.c +++ b/apps/cli/cli_main.c @@ -209,6 +209,32 @@ cli_signal_init (clicon_handle h) * @retval -1 * @see cligen_loop */ +#ifdef USE_CLIGEN44 +static int +cli_interactive(clicon_handle h) +{ + int retval = -1; + int res; + char *cmd; + char *new_mode; + int eval; + + /* Loop through all commands */ + while(!cligen_exiting(cli_cligen(h))) { + new_mode = cli_syntax_mode(h); + if ((cmd = clicon_cliread(h)) == NULL) { + cligen_exiting_set(cli_cligen(h), 1); /* EOF */ + goto ok; /* EOF should not be -1 error? */ + } + if ((res = clicon_parse(h, cmd, &new_mode, &eval)) < 0) + goto done; + } + ok: + retval = 0; + done: + return retval; +} +#else /* USE_CLIGEN44 */ static int cli_interactive(clicon_handle h) { @@ -235,7 +261,7 @@ cli_interactive(clicon_handle h) done: return retval; } - +#endif /* USE_CLIGEN44 */ static void usage(clicon_handle h, @@ -608,6 +634,15 @@ main(int argc, char **argv) /* Launch interfactive event loop, unless -1 */ if (restarg != NULL && strlen(restarg)){ char *mode = cli_syntax_mode(h); +#ifdef USE_CLIGEN44 + int result; + + /* */ + if (clicon_parse(h, restarg, &mode, &result) != 1) + goto done; + if (result < 0) + goto done; +#else /* USE_CLIGEN44 */ cligen_result result; /* match result */ int evalresult = 0; /* if result == 1, calback result */ @@ -617,6 +652,7 @@ main(int argc, char **argv) goto done; if (evalresult < 0) goto done; +#endif /* USE_CLIGEN44 */ } /* Go into event-loop unless -1 command-line */ diff --git a/apps/cli/cli_plugin.c b/apps/cli/cli_plugin.c index 3974ed35..b08dab53 100644 --- a/apps/cli/cli_plugin.c +++ b/apps/cli/cli_plugin.c @@ -511,6 +511,94 @@ clicon_eval(clicon_handle h, * @retval 0 OK * @retval -1 Error */ +#ifdef USE_CLIGEN44 +int +clicon_parse(clicon_handle h, + char *cmd, + char **modenamep, + int *evalres) +{ + int retval = -1; + char *modename; + char *modename0; + int r; + cli_syntax_t *stx = NULL; + cli_syntaxmode_t *smode; + parse_tree *pt; /* Orig */ + cg_obj *match_obj; + cvec *cvv = NULL; + FILE *f; + + if (clicon_get_logflags()&CLICON_LOG_STDOUT) + f = stdout; + else + f = stderr; + stx = cli_syntax(h); + if ((modename = *modenamep) == NULL) { + smode = stx->stx_active_mode; + modename = smode->csm_name; + } + else { + if ((smode = syntax_mode_find(stx, modename, 0)) == NULL) { + fprintf(f, "Can't find syntax mode '%s'\n", modename); + goto done; + } + } + if (smode){ + modename0 = NULL; + if ((pt = cligen_tree_active_get(cli_cligen(h))) != NULL) + modename0 = pt->pt_name; + if (cligen_tree_active_set(cli_cligen(h), modename) < 0){ + fprintf(stderr, "No such parse-tree registered: %s\n", modename); + goto done; + } + if ((pt = cligen_tree_active_get(cli_cligen(h))) == NULL){ + fprintf(stderr, "No such parse-tree registered: %s\n", modename); + goto done; + } + if ((cvv = cvec_new(0)) == NULL){ + clicon_err(OE_UNIX, errno, "cvec_new"); + goto done;; + } + retval = cliread_parse(cli_cligen(h), cmd, pt, &match_obj, cvv); + if (retval != CG_MATCH) + pt_expand_cleanup_1(pt); /* XXX change to pt_expand_treeref_cleanup */ + if (modename0){ + cligen_tree_active_set(cli_cligen(h), modename0); + modename0 = NULL; + } + switch (retval) { + case CG_EOF: /* eof */ + case CG_ERROR: + fprintf(f, "CLI parse error: %s\n", cmd); + break; + case CG_NOMATCH: /* no match */ + /* clicon_err(OE_CFG, 0, "CLI syntax error: \"%s\": %s", + cmd, cli_nomatch(h));*/ + fprintf(f, "CLI syntax error: \"%s\": %s\n", cmd, cli_nomatch(h)); + break; + case CG_MATCH: + if (strcmp(modename, *modenamep)){ /* Command in different mode */ + *modenamep = modename; + cli_set_syntax_mode(h, modename); + } + if ((r = clicon_eval(h, cmd, match_obj, cvv)) < 0) + cli_handler_err(stdout); + pt_expand_cleanup_1(pt); /* XXX change to pt_expand_treeref_cleanup */ + if (evalres) + *evalres = r; + break; + default: + fprintf(f, "CLI syntax error: \"%s\" is ambiguous\n", cmd); + break; + } /* switch retval */ + } +done: + if (cvv) + cvec_free(cvv); + return retval; +} +#else /* USE_CLIGEN44 */ int clicon_parse(clicon_handle h, char *cmd, @@ -601,6 +689,7 @@ done: cvec_free(cvv); return retval; } +#endif /* USE_CLIGEN44 */ /*! Read command from CLIgen's cliread() using current syntax mode. * @param[in] h Clicon handle @@ -608,6 +697,38 @@ done: * @retval 0 OK * @retval -1 Error */ +#ifdef USE_CLIGEN44 +char * +clicon_cliread(clicon_handle h) +{ + char *ret; + char *pfmt = NULL; + cli_syntaxmode_t *mode; + cli_syntax_t *stx; + cli_prompthook_t *fn; + clixon_plugin *cp; + + stx = cli_syntax(h); + mode = stx->stx_active_mode; + /* Get prompt from plugin callback? */ + cp = NULL; + while ((cp = clixon_plugin_each(h, cp)) != NULL) { + if ((fn = cp->cp_api.ca_prompt) == NULL) + continue; + pfmt = fn(h, mode->csm_name); + break; + } + if (clicon_quiet_mode(h)) + cli_prompt_set(h, ""); + else + cli_prompt_set(h, cli_prompt(pfmt ? pfmt : mode->csm_prompt)); + cligen_tree_active_set(cli_cligen(h), mode->csm_name); + ret = cliread(cli_cligen(h)); + if (pfmt) + free(pfmt); + return ret; +} +#else int clicon_cliread(clicon_handle h, char **stringp) @@ -634,6 +755,7 @@ clicon_cliread(clicon_handle h, else cli_prompt_set(h, cli_prompt(pfmt ? pfmt : mode->csm_prompt)); cligen_tree_active_set(cli_cligen(h), mode->csm_name); + if (cliread(cli_cligen(h), stringp) < 0){ clicon_err(OE_FATAL, errno, "CLIgen"); goto done; @@ -644,6 +766,7 @@ clicon_cliread(clicon_handle h, free(pfmt); return retval; } +#endif /* USE_CLIGEN44 */ /* * diff --git a/apps/cli/cli_plugin.h b/apps/cli/cli_plugin.h index d911cc4f..270550c5 100644 --- a/apps/cli/cli_plugin.h +++ b/apps/cli/cli_plugin.h @@ -66,9 +66,13 @@ void *clixon_str2fn(char *name, void *handle, char **error); int clicon_eval(clicon_handle h, char *cmd, cg_obj *match_obj, cvec *vr); +#ifdef USE_CLIGEN44 +int clicon_parse(clicon_handle h, char *cmd, char **modenamep, int *evalres); +char *clicon_cliread(clicon_handle h); +#else int clicon_parse(clicon_handle h, char *cmd, char **mode, cligen_result *result, int *evalres); - int clicon_cliread(clicon_handle h, char **stringp); +#endif int cli_plugin_finish(clicon_handle h); diff --git a/include/clixon_custom.h b/include/clixon_custom.h index f9a7e65b..3dc50103 100644 --- a/include/clixon_custom.h +++ b/include/clixon_custom.h @@ -109,3 +109,8 @@ /*! Differentiate creating XML object body/element vs elenmet to reduce space */ #define XML_NEW_DIFFERENTIATE + +/*! Use cligen 4.4 instead of master / cligen 4.5.pre + * Temporary fix + */ +#define USE_CLIGEN44 diff --git a/lib/clixon/clixon_string.h b/lib/clixon/clixon_string.h index ba69d491..5795c690 100644 --- a/lib/clixon/clixon_string.h +++ b/lib/clixon/clixon_string.h @@ -107,6 +107,9 @@ char *clixon_trim(char *str); char *clixon_trim2(char *str, char *trims); int clicon_strcmp(char *s1, char *s2); +#ifdef USE_CLIGEN44 +int cbuf_append_str(cbuf *cb, char *str); +#endif #ifndef HAVE_STRNDUP char *clicon_strndup (const char *, size_t); #endif /* ! HAVE_STRNDUP */ diff --git a/lib/src/clixon_string.c b/lib/src/clixon_string.c index 15e11e58..75b87f8a 100644 --- a/lib/src/clixon_string.c +++ b/lib/src/clixon_string.c @@ -814,6 +814,69 @@ clicon_strndup(const char *str, } #endif /* ! HAVE_STRNDUP */ +#ifdef USE_CLIGEN44 + +#define CBUFLEN_THRESHOLD 65536 +struct cbuf { + char *cb_buffer; /* pointer to buffer */ + size_t cb_buflen; /* allocated bytes of buffer */ + size_t cb_strlen; /* length of string in buffer (< buflen) */ +}; + +static int +cbuf_realloc(cbuf *cb, + size_t sz) +{ + int retval = -1; + int diff; + + diff = cb->cb_buflen - (cb->cb_strlen + sz + 1); + if (diff <= 0){ + while (diff <= 0){ + if (cb->cb_buflen < CBUFLEN_THRESHOLD) + cb->cb_buflen *= 2; /* Double the space - exponential */ + else + cb->cb_buflen += CBUFLEN_THRESHOLD; /* Add - linear growth*/ + diff = cb->cb_buflen - (cb->cb_strlen + sz + 1); + } + if ((cb->cb_buffer = realloc(cb->cb_buffer, cb->cb_buflen)) == NULL) + goto done; + } + retval = 0; + done: + return retval; +} + +/*! Append a string to a cbuf + * + * An optimized special case of cprintf + * @param [in] cb cligen buffer allocated by cbuf_new(), may be reallocated. + * @param [in] str string + * @retval 0 OK + * @retval -1 Error + * @see cprintf for the generic function + */ +int +cbuf_append_str(cbuf *cb, + char *str) +{ + size_t len0; + size_t len; + + if (str == NULL){ + errno = EINVAL; + return -1; + } + len0 = strlen(str); + len = cb->cb_strlen + len0; + /* Ensure buffer is large enough */ + if (cbuf_realloc(cb, len) < 0) + return -1; + strncpy(cb->cb_buffer+cb->cb_strlen, str, len0+1); + cb->cb_strlen = len;; + return 0; +} +#endif /* * Turn this on for uni-test programs From b8a408808cd78787887c5bd548adbbb7bb237fe2 Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Fri, 1 May 2020 00:44:25 +0200 Subject: [PATCH 2/2] default cligen44 off --- include/clixon_custom.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/clixon_custom.h b/include/clixon_custom.h index 3dc50103..435432f3 100644 --- a/include/clixon_custom.h +++ b/include/clixon_custom.h @@ -113,4 +113,4 @@ /*! Use cligen 4.4 instead of master / cligen 4.5.pre * Temporary fix */ -#define USE_CLIGEN44 +#undef USE_CLIGEN44