diff --git a/apps/cli/cli_show.c b/apps/cli/cli_show.c index 951f0627..282a3d6a 100644 --- a/apps/cli/cli_show.c +++ b/apps/cli/cli_show.c @@ -196,13 +196,15 @@ xpath_append(cbuf *cb0, * @param[in] cvv The command so far. Eg: cvec [0]:"a 5 b"; [1]: x=5; * @param[in] argv Arguments given at the callback: * Name of datastore, such as "running" - * Generated API PATH (this is added implicitly, not actually given in the cvv) + * Generated API PATH (this is sometimes added implicitly) * [] Optional YANG path-arg/xpath from mount-point * @param[out] commands vector of function pointers to callback functions * @param[out] helptxt vector of pointers to helptexts * @retval 0 OK * @retval -1 Error * @see cli_expand_var_generate where api_path_fmt + mt-point are generated + * The syntax of is of RFC8040 api-path with the following extension: + * "%s" represents the values of cvv in order starting from element 1 */ int expand_dbvar(void *h, @@ -451,41 +453,49 @@ expand_dbvar(void *h, return retval; } -/*! Completion callback of variable for yang schema list or container nodes +/*! Completion callback of variable for yang schema list nodes * * Typical yang: - * container foo { list bar; } - * augment foo fie; - * This function expands to bar, fie... + * container foo { list bar; } + * modA: + * augment foo bar; + * modB: + * augment foo fie; + * This function expands foo to: bar, fie... + * Or (if is true): modA:bar, modB:fie... * @param[in] h clicon handle * @param[in] name Name of this function * @param[in] cvv The command so far. Eg: cvec [0]:"a 5 b"; [1]: x=5; * @param[in] argv Arguments given at the callback: - * Absolute YANG schema-node (eg: /ctrl:services) + * Absolute YANG schema-node (eg: /ctrl:services) + * true|false: Show with api-path module-name, eg moda:foo, modb:fie * @param[out] commands vector of function pointers to callback functions * @param[out] helptxt vector of pointers to helptexts * @retval 0 OK * @retval -1 Error */ int -expand_yang(void *h, - char *name, - cvec *cvv, - cvec *argv, - cvec *commands, - cvec *helptexts) +expand_yang_list(void *h, + char *name, + cvec *cvv, + cvec *argv, + cvec *commands, + cvec *helptexts) { - int retval = -1; - int argc = 0; - cg_var *cv; - char *schema_nodeid; - yang_stmt *yspec0 = NULL; - yang_stmt *yres = NULL; - yang_stmt *yn = NULL; - yang_stmt *ydesc; + int retval = -1; + int argc = 0; + cg_var *cv; + char *schema_nodeid; + yang_stmt *yspec0 = NULL; + yang_stmt *yres = NULL; + yang_stmt *yn = NULL; + yang_stmt *ydesc; + yang_stmt *ymod; + int modname = 0; + cbuf *cb = NULL; - if (argv == NULL || cvec_len(argv) != 1){ - clixon_err(OE_PLUGIN, EINVAL, "requires arguments: "); + if (argv == NULL || cvec_len(argv) < 1 || cvec_len(argv) > 2){ + clixon_err(OE_PLUGIN, EINVAL, "requires arguments: []"); goto done; } if ((cv = cvec_i(argv, argc++)) == NULL){ @@ -493,17 +503,32 @@ expand_yang(void *h, goto done; } schema_nodeid = cv_string_get(cv); + if (cvec_len(argv) > argc){ + if (cli_show_option_bool(argv, argc++, &modname) < 0) + goto done; + } if ((yspec0 = clicon_dbspec_yang(h)) == NULL){ clixon_err(OE_FATAL, 0, "No DB_SPEC"); goto done; } if (yang_abs_schema_nodeid(yspec0, schema_nodeid, &yres) < 0) goto done; + if ((cb = cbuf_new()) == NULL){ + clixon_err(OE_UNIX, errno, "cbuf_new"); + goto done; + } yn = NULL; while ((yn = yn_each(yres, yn)) != NULL) { - if (yang_keyword_get(yn) != Y_LIST && yang_keyword_get(yn) != Y_CONTAINER) + if (yang_keyword_get(yn) != Y_LIST) continue; - cvec_add_string(commands, NULL, yang_argument_get(yn)); + cbuf_reset(cb); + if (modname){ + if (ys_real_module(yn, &ymod) < 0) + goto done; + cprintf(cb, "%s:", yang_argument_get(ymod)); + } + cprintf(cb, "%s", yang_argument_get(yn)); + cvec_add_string(commands, NULL, cbuf_get(cb)); if ((ydesc = yang_find(yn, Y_DESCRIPTION, NULL)) != NULL) cvec_add_string(helptexts, NULL, yang_argument_get(ydesc)); else @@ -511,6 +536,8 @@ expand_yang(void *h, } retval = 0; done: + if (cb) + cbuf_free(cb); return retval; } diff --git a/apps/cli/clixon_cli_api.h b/apps/cli/clixon_cli_api.h index 8c50f9bd..31156cac 100644 --- a/apps/cli/clixon_cli_api.h +++ b/apps/cli/clixon_cli_api.h @@ -119,8 +119,8 @@ int cli_process_control(clixon_handle h, cvec *vars, cvec *argv); /* In cli_show.c */ int expand_dbvar(void *h, char *name, cvec *cvv, cvec *argv, cvec *commands, cvec *helptexts); -int expand_yang(void *h, char *name, cvec *cvv, cvec *argv, - cvec *commands, cvec *helptexts); +int expand_yang_list(void *h, char *name, cvec *cvv, cvec *argv, + cvec *commands, cvec *helptexts); int clixon_cli2file(clixon_handle h, FILE *f, cxobj *xn, char *prepend, clicon_output_cb *fn, int skiptop); int clixon_cli2cbuf(clixon_handle h, cbuf *cb, cxobj *xn, char *prepend, int skiptop); /* cli_show.c: CLIgen new vector arg callbacks */ diff --git a/lib/clixon/clixon_string.h b/lib/clixon/clixon_string.h index 3e112ab4..f5a6c815 100644 --- a/lib/clixon/clixon_string.h +++ b/lib/clixon/clixon_string.h @@ -109,6 +109,7 @@ char *clixon_trim(char *str); char *clixon_trim2(char *str, char *trims); int clicon_strcmp(char *s1, char *s2); int clixon_unicode2utf8(char *ucstr, char *utfstr, size_t utflen); +int clixon_str_subst(char *str, cvec *cvv, cbuf *cb); #ifndef HAVE_STRNDUP char *clicon_strndup (const char *, size_t); diff --git a/lib/src/clixon_path.c b/lib/src/clixon_path.c index 147f2078..e24c2a90 100644 --- a/lib/src/clixon_path.c +++ b/lib/src/clixon_path.c @@ -466,7 +466,7 @@ yang2api_path_fmt(yang_stmt *ys, * cvv: foo, bar * api_path: /subif-entry=foo,bar/subid * - * "api-path" is "URI-encoded path expression" definition in RFC8040 3.5.3 + * "api-path" is "URI-encoded path expression" definition in RFC8040 3.5.3 (note only =%s) */ int api_path_fmt2api_path(const char *api_path_fmt, @@ -476,7 +476,9 @@ api_path_fmt2api_path(const char *api_path_fmt, { int retval = -1; char c; - int esc=0; + char cprev; + int esc = 0; + int uri_encode = 0; cbuf *cb = NULL; int i; int j; @@ -491,15 +493,13 @@ api_path_fmt2api_path(const char *api_path_fmt, } j = 1; /* j==0 is cli string */ len = strlen(api_path_fmt); + cprev = 0; for (i=0; i 1){ + i = 0; + while (i < nvec){ + cprintf(cb, "%s", vec[i++]); + if (i == nvec) + break; + var = vec[i++]; + cv = NULL; + while ((cv = cvec_each(cvv, cv)) != NULL){ + if ((varname = cv_name_get(cv)) == NULL) + continue; + if (strcmp(varname, var) != 0) + continue; + varval = cv_string_get(cv); + cprintf(cb, "%s", varval); + break; + } + } + } + else { + cprintf(cb, "%s", str); + } + retval = 0; + done: + if (vec) + free(vec); + return retval; +} + /*! strndup() for systems without it, such as xBSD */ #ifndef HAVE_STRNDUP diff --git a/lib/src/clixon_xml_map.c b/lib/src/clixon_xml_map.c index 4a8d3e0c..0972e3a5 100644 --- a/lib/src/clixon_xml_map.c +++ b/lib/src/clixon_xml_map.c @@ -2107,12 +2107,16 @@ clixon_compare_xmls(cxobj *xc1, /*! XML apply function: replace ${} variables with values from cligen variable vector * + * Example: x=${name}, cvv=["name","bert"] --> bert * @param[in] x XML node * @param[in] arg cvv: vector of name/value pairs - * @retval -1 Error, aborted at first error encounter, return -1 to end user - * @retval 0 OK, continue - * @retval 1 Abort, dont continue with others, return 1 to end user * @retval 2 Locally abort this subtree, continue with others + * @retval 1 Abort, dont continue with others, return 1 to end user + * @retval 0 OK, continue + * @retval -1 Error, aborted at first error encounter, return -1 to end user + * @code + * xml_apply(xtmpl, CX_ELMNT, xml_template_apply, cvv); + * @endcode */ int xml_template_apply(cxobj *x, @@ -2122,50 +2126,20 @@ xml_template_apply(cxobj *x, cvec *cvv = (cvec *)arg; cxobj *xb; char *b; - char *var; - char *varname; - char *varval; cbuf *cb = NULL; - int i; - char **vec = NULL; - int nvec = 0; - cg_var *cv = NULL; if ((xb = xml_body_get(x)) != NULL && (b = xml_value(xb)) != NULL){ - if (clixon_strsep2(b, "${", "}", &vec, &nvec) < 0) + if ((cb = cbuf_new()) == NULL){ + clixon_err(OE_UNIX, errno, "cbuf_new"); goto done; - assert(nvec%2 == 1); /* Must be odd */ - if (nvec > 1){ - if ((cb = cbuf_new()) == NULL){ - clixon_err(OE_UNIX, errno, "cbuf_new"); - goto done; - } - i = 0; - while (i < nvec){ - cprintf(cb, "%s", vec[i++]); - if (i == nvec) - break; - var = vec[i++]; - assert(i < nvec); /* Must be odd */ - cv = NULL; - while ((cv = cvec_each(cvv, cv)) != NULL){ - if ((varname = cv_name_get(cv)) == NULL) - continue; - if (strcmp(varname, var) != 0) - continue; - varval = cv_string_get(cv); - cprintf(cb, "%s", varval); - break; - } - } - xml_value_set(xb, cbuf_get(cb)); } + if (clixon_str_subst(b, cvv, cb) < 0) + goto done; + xml_value_set(xb, cbuf_get(cb)); } retval = 0; done: - if (vec) - free(vec); if (cb) cbuf_free(cb); return retval;