diff --git a/apps/backend/backend_client.c b/apps/backend/backend_client.c
index f30467dd..f347e6f9 100644
--- a/apps/backend/backend_client.c
+++ b/apps/backend/backend_client.c
@@ -694,7 +694,7 @@ from_client_create_subscription(clicon_handle h,
}
}
}
- if (client_subscription_add(ce, stream, MSG_NOTIFY_XML, filter) == NULL)
+ if (client_subscription_add(ce, stream, FORMAT_XML, filter) == NULL)
goto done;
cprintf(cbret, "");
ok:
diff --git a/apps/backend/backend_main.c b/apps/backend/backend_main.c
index 2832af7d..ce68fca5 100644
--- a/apps/backend/backend_main.c
+++ b/apps/backend/backend_main.c
@@ -72,7 +72,7 @@
#include "backend_handle.h"
/* Command line options to be passed to getopt(3) */
-#define BACKEND_OPTS "hD:f:d:Fzu:P:1IRCc:rg:pt"
+#define BACKEND_OPTS "hD:f:d:Fzu:P:1IRCc:rg:pty:"
/*! Terminate. Cannot use h after this */
static int
@@ -426,6 +426,9 @@ main(int argc, char **argv)
case 't' : /* Print alternative dbspec format (eg if YANG, print KEY) */
printalt++;
break;
+ case 'y' : /* yang module */
+ clicon_option_str_set(h, "CLICON_YANG_MODULE_MAIN", optarg);
+ break;
default:
usage(argv[0], h);
break;
diff --git a/apps/backend/clixon_backend_handle.c b/apps/backend/clixon_backend_handle.c
index 84ecebbe..720337e8 100644
--- a/apps/backend/clixon_backend_handle.c
+++ b/apps/backend/clixon_backend_handle.c
@@ -162,7 +162,7 @@ backend_notify(clicon_handle h,
/* Then go thru all global (handle) subscriptions and find matches */
hs = NULL;
while ((hs = subscription_each(h, hs)) != NULL){
- if (hs->hs_format != MSG_NOTIFY_TXT)
+ if (hs->hs_format != FORMAT_TEXT)
continue;
if (strcmp(hs->hs_stream, stream))
continue;
@@ -240,7 +240,7 @@ backend_notify_xml(clicon_handle h,
/* Then go thru all global (handle) subscriptions and find matches */
hs = NULL;
while ((hs = subscription_each(h, hs)) != NULL){
- if (hs->hs_format != MSG_NOTIFY_XML)
+ if (hs->hs_format != FORMAT_XML)
continue;
if (strcmp(hs->hs_stream, stream))
continue;
diff --git a/apps/cli/cli_common.c b/apps/cli/cli_common.c
index c41bf3e1..0ea1383c 100644
--- a/apps/cli/cli_common.c
+++ b/apps/cli/cli_common.c
@@ -74,6 +74,7 @@
#include "cli_common.h"
+
/*! Register log notification stream
* @param[in] h Clicon handle
* @param[in] stream Event stream. CLICON is predefined, others are application-defined
@@ -594,7 +595,7 @@ load_config_filev(clicon_handle h,
{
int ret = -1;
struct stat st;
- char **vecp;
+ char **vecp = NULL;
char *filename;
int replace;
cg_var *cv;
@@ -668,6 +669,13 @@ load_config_filev(clicon_handle h,
ret = 0;
done:
unchunk_group(__FUNCTION__);
+ if (vecp){
+ if (vecp[0])
+ free(vecp[0]);
+ if (vecp[1])
+ free(vecp[1]);
+ free(vecp);
+ }
if (xt)
xml_free(xt);
if (fd != -1)
@@ -803,14 +811,6 @@ db_copy(clicon_handle h,
return clicon_rpc_copy_config(h, db1, db2);
}
-/* These are strings that can be used as 3rd argument to cli_setlog */
-#ifdef notused // broke in new version
-static const char *SHOWAS_TXT = "txt";
-static const char *SHOWAS_XML = "xml";
-static const char *SHOWAS_XML2TXT = "xml2txt";
-static const char *SHOWAS_XML2JSON = "xml2json";
-#endif
-
/*! This is the callback used by cli_setlog to print log message in CLI
* param[in] s UNIX socket from backend where message should be read
* param[in] arg format: txt, xml, xml2txt, xml2json
@@ -824,11 +824,7 @@ cli_notification_cb(int s,
int retval = -1;
cxobj *xt = NULL;
cxobj *xe;
- char *format = (char*)arg;
-#if 0
- char *eventstr = NULL;
- cxobj *xn;
-#endif
+ enum format_enum format = (enum format_enum)arg;
/* get msg (this is the reason this function is called) */
if (clicon_msg_rcv(s, &reply, &eof) < 0)
@@ -840,40 +836,25 @@ cli_notification_cb(int s,
event_unreg_fd(s, cli_notification_cb);
goto done;
}
- if (format == NULL)
- goto done;
if (clicon_msg_decode(reply, &xt) < 0)
goto done;
- if ((xe = xpath_first(xt, "//event")) != NULL){
+ xe = xpath_first(xt, "//event");
+ switch (format){
+ case FORMAT_XML:
if (xml_print(stdout, xe) < 0)
goto done;
+ break;
+ case FORMAT_TEXT:
+ if (xml2txt(stdout, xe, 0) < 0)
+ goto done;
+ break;
+ case FORMAT_JSON:
+ if (xml2json(stdout, xe, 0) < 0)
+ goto done;
+ break;
+ default:
+ break;
}
-#ifdef notyet /* Broke in new version */
- if (strcmp(format, SHOWAS_TXT) == 0){
- fprintf(stdout, "%s\n", eventstr);
- }
- else
- if (strcmp(format, SHOWAS_XML) == 0){
- if (clicon_xml_parse_string(&eventstr, &xt) < 0)
- goto done;
- if ((xn = xml_child_i(xt, 0)) != NULL)
- if (xml_print(stdout, xn) < 0)
- goto done;
- }
- else
- if (strcmp(format, SHOWAS_XML2TXT) == 0){
- if ((xn = xml_child_i(xe, 0)) != NULL)
- if (xml2txt(stdout, xn, 0) < 0)
- goto done;
- }
- else
- if (strcmp(format, SHOWAS_XML2JSON) == 0){
- if ((xn = xml_child_i(xe, 0)) != NULL){
- if (xml2json(stdout, xn, 0) < 0)
- goto done;
- }
- }
-#endif
retval = 0;
done:
if (xt)
@@ -905,7 +886,7 @@ cli_notifyv(clicon_handle h,
int retval = -1;
int status;
char *formatstr = NULL;
- enum format_enum format = MSG_NOTIFY_TXT;
+ enum format_enum format = FORMAT_TEXT;
if (cvec_len(argv) != 2 && cvec_len(argv) != 3){
clicon_err(OE_PLUGIN, 0, "%s Requires arguments: []", __FUNCTION__);
@@ -915,12 +896,7 @@ cli_notifyv(clicon_handle h,
status = atoi(cv_string_get(cvec_i(argv, 1)));
if (cvec_len(argv) > 2){
formatstr = cv_string_get(cvec_i(argv, 2));
- if (strcmp(formatstr, "SHOWAS_TXT") != 0)
- format = MSG_NOTIFY_XML;
- if ((formatstr = strdup(formatstr)) == NULL){ /* XXX */
- clicon_err(OE_PLUGIN, 0, "%s Requires arguments: []", __FUNCTION__);
- goto done;
- }
+ format = format_str2int(formatstr);
}
if (cli_notification_register(h,
stream,
@@ -928,7 +904,7 @@ cli_notifyv(clicon_handle h,
"",
status,
cli_notification_cb,
- formatstr) < 0)
+ (void*)format) < 0)
goto done;
retval = 0;
@@ -1046,7 +1022,7 @@ load_config_file(clicon_handle h,
cvec *argv;
cg_var *cv;
char *str;
- char **vec;
+ char **vec = NULL;
int nvec;
/* Split string into two parts and build a cvec of it and supply that to
@@ -1055,10 +1031,8 @@ load_config_file(clicon_handle h,
clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__);
goto done;
}
- if ((vec = clicon_strsplit(str, " ", &nvec, __FUNCTION__)) == NULL){
- clicon_err(OE_PLUGIN, errno, "clicon_strsplit");
+ if ((vec = clicon_strsep(str, " ", &nvec)) == NULL)
goto done;
- }
if (nvec != 2){
clicon_err(OE_PLUGIN, 0, "Arg syntax is ");
goto done;
@@ -1076,7 +1050,8 @@ load_config_file(clicon_handle h,
retval = load_config_filev(h, cvv, argv);
done:
- unchunk_group(__FUNCTION__);
+ if (vec)
+ free(vec);
return retval;
}
int
@@ -1088,7 +1063,7 @@ save_config_file(clicon_handle h,
cvec *argv;
cg_var *cv;
char *str;
- char **vec;
+ char **vec = NULL;
int nvec;
/* Split string into two parts and build a cvec of it and supply that to
@@ -1097,10 +1072,8 @@ save_config_file(clicon_handle h,
clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__);
goto done;
}
- if ((vec = clicon_strsplit(str, " ", &nvec, __FUNCTION__)) == NULL){
- clicon_err(OE_PLUGIN, errno, "clicon_strsplit");
+ if ((vec = clicon_strsep(str, " ", &nvec)) == NULL)
goto done;
- }
if (nvec != 2){
clicon_err(OE_PLUGIN, 0, "Arg syntax is ");
goto done;
@@ -1118,7 +1091,8 @@ save_config_file(clicon_handle h,
retval = save_config_filev(h, cvv, argv);
done:
- unchunk_group(__FUNCTION__);
+ if (vec)
+ free(vec);
return retval;
}
@@ -1131,7 +1105,7 @@ cli_notify(clicon_handle h,
cvec *argv;
cg_var *cv;
char *str;
- char **vec;
+ char **vec = NULL;
int nvec;
/* Split string into two parts and build a cvec of it and supply that to
@@ -1140,10 +1114,8 @@ cli_notify(clicon_handle h,
clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__);
goto done;
}
- if ((vec = clicon_strsplit(str, " ", &nvec, __FUNCTION__)) == NULL){
- clicon_err(OE_PLUGIN, errno, "clicon_strsplit");
+ if ((vec = clicon_strsep(str, " ", &nvec)) == NULL)
goto done;
- }
if (nvec != 2 && nvec != 3){
clicon_err(OE_PLUGIN, 0, "Arg syntax is []");
goto done;
@@ -1166,7 +1138,8 @@ cli_notify(clicon_handle h,
}
retval = cli_notifyv(h, cvv, argv);
done:
- unchunk_group(__FUNCTION__);
+ if (vec)
+ free(vec);
return retval;
}
diff --git a/apps/cli/cli_main.c b/apps/cli/cli_main.c
index 78cb7879..4a47ba78 100644
--- a/apps/cli/cli_main.c
+++ b/apps/cli/cli_main.c
@@ -174,7 +174,7 @@ main(int argc, char **argv)
int help = 0;
char *treename;
int logdst = CLICON_LOG_STDERR;
- char *restarg; /* what remains after options */
+ char *restarg = NULL; /* what remains after options */
/* Defaults */
@@ -366,7 +366,7 @@ main(int argc, char **argv)
clicon_option_dump(h, debug);
/* Join rest of argv to a single command */
- restarg = clicon_strjoin(argc, argv, " ", __FUNCTION__);
+ restarg = clicon_strjoin(argc, argv, " ");
/* If several cligen object variables match same preference, select first */
cligen_match_cgvar_same(1);
@@ -389,6 +389,8 @@ main(int argc, char **argv)
if (!once)
cli_interactive(h);
done:
+ if (restarg)
+ free(restarg);
unchunk_group(__FUNCTION__);
// Gets in your face if we log on stderr
clicon_log_init(__PROGRAM__, LOG_INFO, 0); /* Log on syslog no stderr */
diff --git a/apps/cli/cli_plugin.c b/apps/cli/cli_plugin.c
index d60c052f..4c3f75bf 100644
--- a/apps/cli/cli_plugin.c
+++ b/apps/cli/cli_plugin.c
@@ -398,9 +398,8 @@ cli_load_syntax(clicon_handle h, const char *filename, const char *clispec_dir)
clicon_err(OE_PLUGIN, 0, "No syntax mode specified in %s", filepath);
goto done;
}
- if ((vec = clicon_strsplit(mode, ":", &nvec, __FUNCTION__)) == NULL) {
+ if ((vec = clicon_strsep(mode, ":", &nvec)) == NULL)
goto done;
- }
for (i = 0; i < nvec; i++) {
if (syntax_append(h, cli_syntax(h), vec[i], pt) < 0) {
goto done;
@@ -415,6 +414,8 @@ cli_load_syntax(clicon_handle h, const char *filename, const char *clispec_dir)
done:
if (vr)
cvec_free(vr);
+ if (vec)
+ free(vec);
unchunk_group(__FUNCTION__);
return retval;
}
@@ -1020,7 +1021,7 @@ cli_ptpush(clicon_handle h, char *mode, char *string, char *op)
return 0;
pt = &co_cmd->co_pt;
/* vec is the command, eg 'edit policy_option' */
- if ((vec = clicon_strsplit(string, " ", &nvec, __FUNCTION__)) == NULL)
+ if ((vec = clicon_strsep(string, " ", &nvec)) == NULL)
goto catch;
co = NULL;
found = 0;
@@ -1050,7 +1051,8 @@ cli_ptpush(clicon_handle h, char *mode, char *string, char *op)
co_up_set(cc, co_cmd);
}
catch:
- unchunk_group(__FUNCTION__) ;
+ if (vec)
+ free(vec);
return 0;
}
diff --git a/apps/cli/cli_show.c b/apps/cli/cli_show.c
index 561ed85e..cdba9012 100644
--- a/apps/cli/cli_show.c
+++ b/apps/cli/cli_show.c
@@ -787,10 +787,8 @@ expand_dbvar(void *h,
goto done;
}
/* In the example, str = "candidate /x/m1/%s/b" */
- if ((vec = clicon_strsplit(str, " ", &nvec, __FUNCTION__)) == NULL){
- clicon_err(OE_PLUGIN, errno, "clicon_strsplit");
+ if ((vec = clicon_strsep(str, " ", &nvec)) == NULL)
goto done;
- }
dbstr = vec[0];
if (strcmp(dbstr, "running") != 0 &&
strcmp(dbstr, "candidate") != 0 &&
@@ -856,7 +854,8 @@ expand_dbvar(void *h,
}
retval = 0;
done:
- unchunk_group(__FUNCTION__);
+ if (vec)
+ free(vec);
if (xvec)
free(xvec);
if (xt)
@@ -905,10 +904,8 @@ show_conf_as(clicon_handle h,
clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__);
goto done;
}
- if ((vec = clicon_strsplit(str, " ", &nvec, __FUNCTION__)) == NULL){
- clicon_err(OE_PLUGIN, errno, "clicon_strsplit");
+ if ((vec = clicon_strsep(str, " ", &nvec)) == NULL)
goto done;
- }
if (nvec != 2 && nvec != 3){
clicon_err(OE_PLUGIN, 0, "format error \"%s\" - expected [] got %d arg", str, nvec);
goto done;
@@ -956,7 +953,8 @@ done:
free(val);
if (cbx)
cbuf_free(cbx);
- unchunk_group(__FUNCTION__);
+ if (vec)
+ free(vec);
return retval;
}
diff --git a/apps/restconf/restconf_main.c b/apps/restconf/restconf_main.c
index 043d6c63..41619c31 100644
--- a/apps/restconf/restconf_main.c
+++ b/apps/restconf/restconf_main.c
@@ -129,7 +129,7 @@ request_process(clicon_handle h,
char *path;
char *query;
char *method;
- char **pvec;
+ char **pvec = NULL;
int pn;
cvec *qvec = NULL;
cvec *dvec = NULL;
@@ -141,7 +141,7 @@ request_process(clicon_handle h,
clicon_debug(1, "%s", __FUNCTION__);
path = FCGX_GetParam("DOCUMENT_URI", r->envp);
query = FCGX_GetParam("QUERY_STRING", r->envp);
- if ((pvec = clicon_strsplit(path, "/", &pn, __FUNCTION__)) == NULL)
+ if ((pvec = clicon_strsep(path, "/", &pn)) == NULL)
goto done;
if (str2cvec(query, '&', '=', &qvec) < 0)
@@ -171,7 +171,6 @@ request_process(clicon_handle h,
if (auth == 0)
goto done;
clicon_debug(1, "%s credentials ok 2", __FUNCTION__);
- clicon_debug(1, "%s credentials ok 3", __FUNCTION__);
if (strcmp(method, "data") == 0) /* restconf, skip /api/data */
retval = api_data(h, r, path, pcvec, 2, qvec, data);
@@ -181,6 +180,8 @@ request_process(clicon_handle h,
retval = notfound(r);
done:
clicon_debug(1, "%s retval:%d K", __FUNCTION__, retval);
+ if (pvec)
+ free(pvec);
if (dvec)
cvec_free(dvec);
if (qvec)
@@ -189,7 +190,6 @@ request_process(clicon_handle h,
cvec_free(pcvec);
if (cb)
cbuf_free(cb);
- unchunk_group(__FUNCTION__);
return retval;
}
diff --git a/example/routing_cli.cli b/example/routing_cli.cli
index b596ee22..4b0b2342 100644
--- a/example/routing_cli.cli
+++ b/example/routing_cli.cli
@@ -45,7 +45,7 @@ load("Load configuration from XML file") ("Filename (local file
}
example("This is a comment") ("Just a random number"), mycallback("myarg");
downcall("This is a downcall") , downcall();
-notify("Get notifications from backend"), cli_notifyv("ROUTING", "1", "txt");
+notify("Get notifications from backend"), cli_notifyv("ROUTING", "1", "text");
no("Negate") notify("Get notifications from backend"), cli_notifyv("ROUTING", "0", "xml");
lock,cli_lock("candidate");
unlock,cli_unlock("candidate");
\ No newline at end of file
diff --git a/lib/clixon/clixon_proto.h b/lib/clixon/clixon_proto.h
index e892788f..85342170 100644
--- a/lib/clixon/clixon_proto.h
+++ b/lib/clixon/clixon_proto.h
@@ -42,8 +42,11 @@
* Types
*/
enum format_enum{
- MSG_NOTIFY_TXT, /* means filter works on strings */
- MSG_NOTIFY_XML, /* means filter works on xml */
+ FORMAT_XML,
+ FORMAT_JSON,
+ FORMAT_TEXT,
+ FORMAT_CLI,
+ FORMAT_NETCONF
};
/* Protocol message header */
@@ -55,6 +58,9 @@ struct clicon_msg {
/*
* Prototypes
*/
+char *format_int2str(enum format_enum showas);
+enum format_enum format_str2int(char *str);
+
struct clicon_msg *clicon_msg_encode(char *format, ...);
int clicon_msg_decode(struct clicon_msg *msg, cxobj **xml);
diff --git a/lib/clixon/clixon_string.h b/lib/clixon/clixon_string.h
index 55ec7a6f..86c22e6d 100644
--- a/lib/clixon/clixon_string.h
+++ b/lib/clixon/clixon_string.h
@@ -54,17 +54,10 @@ static inline char * strdup4(char *str)
/*
* Prototypes
*/
-char **clicon_sepsplit (char *string, char *delim, int *nvec, const char *label);
-char **clicon_strsplit (char *string, char *delim, int *nvec, const char *label);
char **clicon_strsep(char *string, char *delim, int *nvec0);
-char *clicon_strjoin (int argc, char **argv, char *delim, const char *label);
-char *clicon_strtrim(char *str, const char *label);
-int clicon_sep(char *s, const char sep[2], const char *label, char**a0, char **b0);
+char *clicon_strjoin (int argc, char **argv, char *delim);
#ifndef HAVE_STRNDUP
char *clicon_strndup (const char *, size_t);
#endif /* ! HAVE_STRNDUP */
-int clicon_strmatch(const char *str, const char *regexp, char **match);
-char *clicon_strsub(char *str, char *from, char *to);
-
#endif /* _CLIXON_STRING_H_ */
diff --git a/lib/src/clixon_file.c b/lib/src/clixon_file.c
index 3280c0c9..1b96ed08 100644
--- a/lib/src/clixon_file.c
+++ b/lib/src/clixon_file.c
@@ -62,19 +62,22 @@
#include "clixon_string.h"
#include "clixon_file.h"
-/*
- * Resolve the real path of a given 'path', following symbolic links and '../'.
+/*! Resolve the real path of a given 'path', following symbolic links and '../'.
* If 'path' relative, it will be resolved based on the currnt working
* directory 'cwd'. The response is a 2 entry vector of strings. The first
* entry is the resolved path and the second is the part of the path which
* actually exist.
+ * @retval vec
*/
char **
-clicon_realpath(const char *cwd, char *path, const char *label)
+clicon_realpath(const char *cwd,
+ char *path,
+ const char *label)
{
char **ret = NULL;
char *rest;
- char **vec, **vec2;
+ char **vec = NULL;
+ char **vec2;
int nvec, nvec2;
char *p;
char *rp = NULL;
@@ -122,8 +125,10 @@ clicon_realpath(const char *cwd, char *path, const char *label)
/* Split path based on '/'. Loop through vector from the end and copy
each entry into a new vector, skipping '..' and it's previous directory
as well as all '.' */
- vec = clicon_strsplit (p, "/", &nvec, __FUNCTION__);
- vec2 = chunk(nvec * sizeof(char *), __FUNCTION__);
+ if ((vec = clicon_strsep(p, "/", &nvec)) == NULL)
+ goto catch;
+ if ((vec2 = malloc(nvec * sizeof(char *))) == NULL)
+ goto catch;
nvec2 = i = nvec;
while(--i >= 0) {
if(strcmp(vec[i], "..") == 0)
@@ -135,14 +140,14 @@ clicon_realpath(const char *cwd, char *path, const char *label)
}
/* Create resulting vector */
- if ((ret = chunk(sizeof(char *) * 2, label)) != NULL) {
- if((ret[0] = clicon_strjoin(nvec-nvec2, &vec2[nvec2], "/", label)) == NULL) {
- unchunk(ret);
+ if ((ret = malloc(sizeof(char *) * 2)) != NULL) {
+ if((ret[0] = clicon_strjoin(nvec-nvec2, &vec2[nvec2], "/")) == NULL) {
+ free(ret);
ret = NULL;
}
- if ((ret[1] = chunkdup(rp, strlen(rp)+1, label)) == NULL) {
- unchunk(ret[0]);
- unchunk(ret);
+ if ((ret[1] = strdup(rp)) == NULL) {
+ free(ret[0]);
+ free(ret);
ret = NULL;
}
}
@@ -150,6 +155,10 @@ clicon_realpath(const char *cwd, char *path, const char *label)
catch:
if(rp)
free(rp);
+ if(vec)
+ free(vec);
+ if(vec2)
+ free(vec2);
unchunk_group(__FUNCTION__);
return ret;
}
diff --git a/lib/src/clixon_proc.c b/lib/src/clixon_proc.c
index 9d3d9472..41dd9f8b 100644
--- a/lib/src/clixon_proc.c
+++ b/lib/src/clixon_proc.c
@@ -121,13 +121,12 @@ clicon_proc_run (char *cmd,
sigfn_t oldhandler = NULL;
sigset_t oset;
- argv = clicon_sepsplit (cmd, " \t", &argc, __FUNCTION__);
+ argv = clicon_strsep(cmd, " \t", &argc);
if (!argv)
return -1;
if (pipe (outfd) == -1)
goto done;
-
signal_get_mask(&oset);
set_signal(SIGINT, clicon_proc_sigint, &oldhandler);
@@ -194,7 +193,8 @@ clicon_proc_run (char *cmd,
signal_set_mask (&oset);
set_signal(SIGINT, oldhandler, NULL);
- unchunk_group (__FUNCTION__);
+ if(argv)
+ free(argv);
return retval;
}
@@ -216,7 +216,7 @@ clicon_proc_daemon (char *cmd)
struct rlimit
rlim;
- argv = clicon_sepsplit (cmd, " \t", &argc, NULL);
+ argv = clicon_strsep(cmd, " \t", &argc);
if (!argv)
return -1;
@@ -260,7 +260,8 @@ clicon_proc_daemon (char *cmd)
retval = 0;
done:
- unchunk_group(__FUNCTION__);
+ if (argv)
+ free(argv);
return (retval);
}
diff --git a/lib/src/clixon_proto.c b/lib/src/clixon_proto.c
index e74e28b1..21c2b0ed 100644
--- a/lib/src/clixon_proto.c
+++ b/lib/src/clixon_proto.c
@@ -74,6 +74,46 @@
static int _atomicio_sig = 0;
+/*! Formats (showas) derived from XML
+ */
+struct formatvec{
+ char *fv_str;
+ int fv_int;
+};
+
+static struct formatvec _FORMATS[] = {
+ {"xml", FORMAT_XML},
+ {"text", FORMAT_TEXT},
+ {"json", FORMAT_JSON},
+ {"cli", FORMAT_CLI},
+ {"netconf", FORMAT_NETCONF},
+ {NULL, -1}
+};
+
+/*! Translate from numeric error to string representation
+ */
+char *
+format_int2str(enum format_enum showas)
+{
+ struct formatvec *fv;
+
+ for (fv=_FORMATS; fv->fv_int != -1; fv++)
+ if (fv->fv_int == showas)
+ break;
+ return fv?(fv->fv_str?fv->fv_str:"unknown"):"unknown";
+}
+
+enum format_enum
+format_str2int(char *str)
+{
+ struct formatvec *fv;
+
+ for (fv=_FORMATS; fv->fv_int != -1; fv++)
+ if (strcmp(fv->fv_str, str) == 0)
+ break;
+ return fv?fv->fv_int:-1;
+}
+
/*! Encode a clicon netconf message
* @param[in] param Variable agrument list format an XML netconf string
* @retval msg Clicon message to send to eg clicon_msg_send()
diff --git a/lib/src/clixon_string.c b/lib/src/clixon_string.c
index 139fdeff..ecf1431b 100644
--- a/lib/src/clixon_string.c
+++ b/lib/src/clixon_string.c
@@ -53,117 +53,6 @@
#include "clixon_string.h"
#include "clixon_err.h"
-/*! Split string into a vector based on character delimiters
- *
- * The given string is split into a vector where the delimiter can be
- * any of the characters in the specified delimiter string.
- *
- * The vector returned is one single memory chunk that must be unchunked
- * by the caller
- *
- * @param[in] string String to be split
- * @param[in] delim String of delimiter characters
- * @param[out] nvec Number of entries in returned vector
- * @param[in] label Chunk label for returned vector
- * @retval vec Vector of strings. Free with unchunk
- * @retval NULL Error
- * @see clicon_strsplit Operates on full string delimiters rather than
- * individual character delimiters.
- * @see clicon_strsep Use malloc instead of chunk
- */
-char **
-clicon_sepsplit (char *string,
- char *delim,
- int *nvec,
- const char *label)
-{
- int idx;
- size_t siz;
- char *s, *s0;
- char **vec, *vecp;
-
- *nvec = 0;
- s0 = s = chunkdup (string, strlen(string)+1, __FUNCTION__);
- while (strsep(&s, delim))
- (*nvec)++;
- unchunk (s0);
-
- siz = ((*nvec +1) * sizeof (char *)) + strlen(string) + 1;
- vec = (char **) chunk (siz, label);
- if (!vec) {
- return NULL;
- }
- bzero (vec, siz);
-
- vecp = (char *)&vec[*nvec +1];
- bcopy (string, vecp, strlen (string));
-
- for (idx = 0; idx < *nvec; idx++) {
- vec[idx] = vecp;
- strsep (&vecp, delim);
- }
-
- return vec;
-}
-
-/*! Split string into a vector based on a string delimiter
- *
- * The given string is split into a vector where the delimited by the
- * the full delimiter string. The matched delimiters are not part of the
- * resulting vector.
- *
- * The vector returned is one single memory chunk that must be unchunked
- * by the caller
- *
- * @param[in] string String to be split
- * @param[in] delim String of delimiter characters
- * @param[out] nvec Number of entries in returned vector
- * @param[in] label Chunk label for returned vector
- * @retval vec Vector of strings. Free with unchunk
- * @retval NULL Error
- * @see clicon_sepsplit Operates on individual character delimiters rather
- * than full string delimiter.
- * @see clicon_strsep Use malloc instead of chunk
- */
-char **
-clicon_strsplit (char *string,
- char *delim,
- int *nvec,
- const char *label)
-{
- int idx;
- size_t siz;
- char *s;
- char **vec, *vecp;
-
- *nvec = 1;
- s = string;
- while ((s = strstr(s, delim))) {
- s += strlen(delim);
- (*nvec)++;
- }
-
- siz = ((*nvec +1) * sizeof (char *)) + strlen(string) + 1;
- vec = (char **) chunk (siz, label);
- if (!vec) {
- return NULL;
- }
- bzero (vec, siz);
-
- vecp = (char *)&vec[*nvec +1];
- bcopy (string, vecp, strlen (string));
-
- s = vecp;
- for (idx = 0; idx < *nvec; idx++) {
- vec[idx] = s;
- if ((s = strstr(s, delim)) != NULL) {
- *s = '\0';
- s += strlen(delim);
- }
- }
-
- return vec;
-}
/*! Split string into a vector based on character delimiters. Using malloc
*
@@ -189,14 +78,20 @@ clicon_strsep(char *string,
char *p;
int nvec = 1;
int i;
-
- for (i=0; i str && isspace(*(end-1)))
- end--;
- if((new = chunkdup (start, end-start+1, label)))
- new[end-start] = '\0';
-
- return new;
-}
-
-/*! Given a string s, on format: a[b], separate it into two parts: a and b
- * [] are separators.
- * alterative use:
- * a/b -> a and b (where sep = "/")
- * @param[in] label Chunk label for returned vector
- */
-int
-clicon_sep(char *s,
- const char sep[2],
- const char *label,
- char **a0,
- char **b0)
-{
- char *a = NULL;
- char *b = NULL;
- char *ptr;
+ int i;
int len;
- int retval = -1;
+ char *str;
- ptr = s;
- /* move forward to last char of element name */
- while (*ptr && *ptr != sep[0] && *ptr != sep[1] )
- ptr++;
- /* Copy first element name */
- len = ptr-s;
- if ((a = chunkdup(s, len+1, label)) == NULL)
- goto catch;
- a[len] = '\0';
- /* Do we have an extended format? */
- if (*ptr == sep[0]) {
- b = ++ptr;
- /* move forward to end extension */
- while (*ptr && *ptr != sep[1])
- ptr++;
- /* Copy extension */
- len = ptr-b;
- if ((b = chunkdup(b, len+1, label)) == NULL)
- goto catch;
- b[len] = '\0';
+ len = 0;
+ for (i = 0; i < argc; i++)
+ len += strlen(argv[i]);
+ if (delim)
+ len += (strlen(delim) * argc);
+ len += 1; /* '\0' */
+ if ((str = malloc(len)) == NULL)
+ return NULL;
+ memset (str, '\0', len);
+ for (i = 0; i < argc; i++) {
+ if (i != 0)
+ strncat (str, delim, len - strlen(str));
+ strncat (str, argv[i], len - strlen(str));
}
-
- *a0 = a;
- *b0 = b;
- retval = 0;
- catch:
- return retval;
+ return str;
}
@@ -346,82 +160,48 @@ clicon_strndup (const char *str,
}
#endif /* ! HAVE_STRNDUP */
-/*! Match string against regexp.
- *
- * If a match pointer is given, the matching substring
- * will be allocated 'match' will be pointing to it. The match string must
- * be free:ed by the application.
- * @retval -1 Failure
- * @retval 0 No match
- * @retval >0 Match: Length of matching substring
- */
+/*
+ * Turn this on for uni-test programs
+ * Usage: clixon_string join
+ * Example compile:
+ gcc -g -o clixon_string -I. -I../clixon ./clixon_string.c -lclixon -lcligen
+ * Example run:
+*/
+#if 0 /* Test program */
+
+static int
+usage(char *argv0)
+{
+ fprintf(stderr, "usage:%s \n", argv0);
+ exit(0);
+}
+
int
-clicon_strmatch(const char *str,
- const char *regexp,
- char **match)
+main(int argc, char **argv)
{
- size_t len;
- int status;
- regex_t re;
- char rxerr[128];
- size_t nmatch = 1;
- regmatch_t pmatch[1];
-
- if (match)
- *match = NULL;
-
- if ((status = regcomp(&re, regexp, REG_EXTENDED)) != 0) {
- regerror(status, &re, rxerr, sizeof(rxerr));
- clicon_err(OE_REGEX, errno, "%s", rxerr);
- return -1;
- }
-
- status = regexec(&re, str, nmatch, pmatch, 0);
- regfree(&re);
- if (status != 0)
- return 0; /* No match */
-
- len = pmatch[0].rm_eo - pmatch[0].rm_so;
-/* If we've specified a match pointer, allocate and populate it. */
- if (match) {
- if ((*match = malloc(len + 1)) == NULL) {
- clicon_err(OE_UNIX, errno, "Failed to allocate string");
- return -1;
- }
- memset(*match, '\0', len + 1);
- strncpy(*match, str + pmatch[0].rm_so, len);
- }
-
- return len;
-}
-
-/*! Substitute pattern in string.
- * @retval str Malloc:ed string on success, use free to deallocate
- * @retval NULL Failure.
- */
-char *
-clicon_strsub(char *str,
- char *from,
- char *to)
-{
- char **vec;
int nvec;
- char *new;
- char *retval = NULL;
+ char **vec;
+ char *str0;
+ char *str1;
+ int i;
- if ((vec = clicon_strsplit(str, from, &nvec, __FUNCTION__)) == NULL) {
- clicon_err(OE_UNIX, errno, "Failed to split string");
- goto done;
+ if (argc != 2){
+ usage(argv[0]);
+ return 0;
}
-
- if ((new = clicon_strjoin (nvec, vec, to, __FUNCTION__)) == NULL) {
- clicon_err(OE_UNIX, errno, "Failed to split string");
- goto done;
- }
-
- retval = strdup(new);
-
- done:
- unchunk_group(__FUNCTION__);
- return retval;
+ str0 = argv[1];
+ if ((vec = clicon_strsep("a b\tc", " \t", &nvec)) == NULL)
+ return -1;
+ fprintf(stderr, "nvec: %d\n", nvec);
+ for (i=0; i'");
goto done;
}
- if ((valvec = clicon_strsplit(restval, ",", &nvalvec, __FUNCTION__)) == NULL)
+ if (valvec)
+ free(valvec);
+ if ((valvec = clicon_strsep(restval, ",", &nvalvec)) == NULL)
goto done;
if (cvec_len(cvk) != nvalvec){
@@ -1398,6 +1405,11 @@ xmldb_put_xkey(clicon_handle h,
cbuf_free(crx);
if (cvk)
cvec_free(cvk);
+ if (vec)
+ free(vec);
+ if (valvec)
+ free(valvec);
+
unchunk_group(__FUNCTION__);
return retval;
}
@@ -1431,7 +1443,7 @@ xmldb_put_restconf_api_path(clicon_handle h,
int retval = -1;
yang_stmt *y = NULL;
yang_stmt *ykey;
- char **vec;
+ char **vec = NULL;
int nvec;
int i;
char *name;
@@ -1466,7 +1478,7 @@ xmldb_put_restconf_api_path(clicon_handle h,
clicon_err(OE_UNIX, errno, "cbuf_new");
goto done;
}
- if ((vec = clicon_strsplit(api_path, "/", &nvec, __FUNCTION__)) == NULL)
+ if ((vec = clicon_strsep(api_path, "/", &nvec)) == NULL)
goto done;
if (nvec < 2){
clicon_err(OE_XML, 0, "Malformed key: %s", api_path);
@@ -1611,6 +1623,8 @@ xmldb_put_restconf_api_path(clicon_handle h,
cbuf_free(crx);
if (cvk)
cvec_free(cvk);
+ if (vec)
+ free(vec);
unchunk_group(__FUNCTION__);
return retval;
}
diff --git a/lib/src/clixon_yang.c b/lib/src/clixon_yang.c
index 6ab33816..7e0d0bf4 100644
--- a/lib/src/clixon_yang.c
+++ b/lib/src/clixon_yang.c
@@ -1695,11 +1695,9 @@ yang_xpath_abs(yang_node *yn,
char *prefix = NULL;
if ((vec = clicon_strsep(xpath, "/", &nvec)) == NULL){
- clicon_err(OE_YANG, errno, "%s: strsplit", __FUNCTION__);
+ clicon_err(OE_YANG, errno, "%s: strsep", __FUNCTION__);
return NULL;
}
-
-
/* Assume path looks like: "/prefix:id[/prefix:id]*" */
if (nvec < 2){
clicon_err(OE_YANG, 0, "%s: NULL or truncated path: %s",
@@ -1955,16 +1953,14 @@ cvec *
yang_arg2cvec(yang_stmt *ys,
char *delim)
{
- char **vec;
+ char **vec = NULL;
int i;
int nvec;
cvec *cvv = NULL;
cg_var *cv;
- if ((vec = clicon_strsplit(ys->ys_argument, " ", &nvec, __FUNCTION__)) == NULL){
- clicon_err(OE_YANG, errno, "clicon_strsplit");
+ if ((vec = clicon_strsep(ys->ys_argument, " ", &nvec)) == NULL)
goto done;
- }
if ((cvv = cvec_new(nvec)) == NULL){
clicon_err(OE_YANG, errno, "cvec_new");
goto done;
@@ -1979,7 +1975,8 @@ yang_arg2cvec(yang_stmt *ys,
}
}
done:
- unchunk_group(__FUNCTION__);
+ if (vec)
+ free(vec);
return cvv;
}
diff --git a/test/test2.sh b/test/test2.sh
index f23b070d..ef16c0cb 100755
--- a/test/test2.sh
+++ b/test/test2.sh
@@ -21,7 +21,7 @@ if [ $? -ne 0 ]; then
err
fi
new "netconf get empty config"
-expecteof "valgrind $clixon_netconf -qf $clixon_cf" "]]>]]>" "^]]>]]>$"
+expecteof "$clixon_netconf -qf $clixon_cf" "]]>]]>" "^]]>]]>$"
new "netconf edit config"
expecteof "$clixon_netconf -qf $clixon_cf" "eth0eth1true9.2.3.424]]>]]>" "^]]>]]>$"