cleaned up string functions
This commit is contained in:
parent
75e1ea7c1c
commit
236b661e43
18 changed files with 245 additions and 427 deletions
|
|
@ -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;
|
goto done;
|
||||||
cprintf(cbret, "<rpc-reply><ok/></rpc-reply>");
|
cprintf(cbret, "<rpc-reply><ok/></rpc-reply>");
|
||||||
ok:
|
ok:
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@
|
||||||
#include "backend_handle.h"
|
#include "backend_handle.h"
|
||||||
|
|
||||||
/* Command line options to be passed to getopt(3) */
|
/* 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 */
|
/*! Terminate. Cannot use h after this */
|
||||||
static int
|
static int
|
||||||
|
|
@ -426,6 +426,9 @@ main(int argc, char **argv)
|
||||||
case 't' : /* Print alternative dbspec format (eg if YANG, print KEY) */
|
case 't' : /* Print alternative dbspec format (eg if YANG, print KEY) */
|
||||||
printalt++;
|
printalt++;
|
||||||
break;
|
break;
|
||||||
|
case 'y' : /* yang module */
|
||||||
|
clicon_option_str_set(h, "CLICON_YANG_MODULE_MAIN", optarg);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
usage(argv[0], h);
|
usage(argv[0], h);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -162,7 +162,7 @@ backend_notify(clicon_handle h,
|
||||||
/* Then go thru all global (handle) subscriptions and find matches */
|
/* Then go thru all global (handle) subscriptions and find matches */
|
||||||
hs = NULL;
|
hs = NULL;
|
||||||
while ((hs = subscription_each(h, hs)) != NULL){
|
while ((hs = subscription_each(h, hs)) != NULL){
|
||||||
if (hs->hs_format != MSG_NOTIFY_TXT)
|
if (hs->hs_format != FORMAT_TEXT)
|
||||||
continue;
|
continue;
|
||||||
if (strcmp(hs->hs_stream, stream))
|
if (strcmp(hs->hs_stream, stream))
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -240,7 +240,7 @@ backend_notify_xml(clicon_handle h,
|
||||||
/* Then go thru all global (handle) subscriptions and find matches */
|
/* Then go thru all global (handle) subscriptions and find matches */
|
||||||
hs = NULL;
|
hs = NULL;
|
||||||
while ((hs = subscription_each(h, hs)) != NULL){
|
while ((hs = subscription_each(h, hs)) != NULL){
|
||||||
if (hs->hs_format != MSG_NOTIFY_XML)
|
if (hs->hs_format != FORMAT_XML)
|
||||||
continue;
|
continue;
|
||||||
if (strcmp(hs->hs_stream, stream))
|
if (strcmp(hs->hs_stream, stream))
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,7 @@
|
||||||
|
|
||||||
#include "cli_common.h"
|
#include "cli_common.h"
|
||||||
|
|
||||||
|
|
||||||
/*! Register log notification stream
|
/*! Register log notification stream
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
* @param[in] stream Event stream. CLICON is predefined, others are application-defined
|
* @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;
|
int ret = -1;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
char **vecp;
|
char **vecp = NULL;
|
||||||
char *filename;
|
char *filename;
|
||||||
int replace;
|
int replace;
|
||||||
cg_var *cv;
|
cg_var *cv;
|
||||||
|
|
@ -668,6 +669,13 @@ load_config_filev(clicon_handle h,
|
||||||
ret = 0;
|
ret = 0;
|
||||||
done:
|
done:
|
||||||
unchunk_group(__FUNCTION__);
|
unchunk_group(__FUNCTION__);
|
||||||
|
if (vecp){
|
||||||
|
if (vecp[0])
|
||||||
|
free(vecp[0]);
|
||||||
|
if (vecp[1])
|
||||||
|
free(vecp[1]);
|
||||||
|
free(vecp);
|
||||||
|
}
|
||||||
if (xt)
|
if (xt)
|
||||||
xml_free(xt);
|
xml_free(xt);
|
||||||
if (fd != -1)
|
if (fd != -1)
|
||||||
|
|
@ -803,14 +811,6 @@ db_copy(clicon_handle h,
|
||||||
return clicon_rpc_copy_config(h, db1, db2);
|
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
|
/*! 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] s UNIX socket from backend where message should be read
|
||||||
* param[in] arg format: txt, xml, xml2txt, xml2json
|
* param[in] arg format: txt, xml, xml2txt, xml2json
|
||||||
|
|
@ -824,11 +824,7 @@ cli_notification_cb(int s,
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
cxobj *xt = NULL;
|
cxobj *xt = NULL;
|
||||||
cxobj *xe;
|
cxobj *xe;
|
||||||
char *format = (char*)arg;
|
enum format_enum format = (enum format_enum)arg;
|
||||||
#if 0
|
|
||||||
char *eventstr = NULL;
|
|
||||||
cxobj *xn;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* get msg (this is the reason this function is called) */
|
/* get msg (this is the reason this function is called) */
|
||||||
if (clicon_msg_rcv(s, &reply, &eof) < 0)
|
if (clicon_msg_rcv(s, &reply, &eof) < 0)
|
||||||
|
|
@ -840,40 +836,25 @@ cli_notification_cb(int s,
|
||||||
event_unreg_fd(s, cli_notification_cb);
|
event_unreg_fd(s, cli_notification_cb);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (format == NULL)
|
|
||||||
goto done;
|
|
||||||
if (clicon_msg_decode(reply, &xt) < 0)
|
if (clicon_msg_decode(reply, &xt) < 0)
|
||||||
goto done;
|
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)
|
if (xml_print(stdout, xe) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
break;
|
||||||
#ifdef notyet /* Broke in new version */
|
case FORMAT_TEXT:
|
||||||
if (strcmp(format, SHOWAS_TXT) == 0){
|
if (xml2txt(stdout, xe, 0) < 0)
|
||||||
fprintf(stdout, "%s\n", eventstr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if (strcmp(format, SHOWAS_XML) == 0){
|
|
||||||
if (clicon_xml_parse_string(&eventstr, &xt) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
if ((xn = xml_child_i(xt, 0)) != NULL)
|
break;
|
||||||
if (xml_print(stdout, xn) < 0)
|
case FORMAT_JSON:
|
||||||
|
if (xml2json(stdout, xe, 0) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
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;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
if (xt)
|
if (xt)
|
||||||
|
|
@ -905,7 +886,7 @@ cli_notifyv(clicon_handle h,
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
int status;
|
int status;
|
||||||
char *formatstr = NULL;
|
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){
|
if (cvec_len(argv) != 2 && cvec_len(argv) != 3){
|
||||||
clicon_err(OE_PLUGIN, 0, "%s Requires arguments: <logstream> <status> [<format>]", __FUNCTION__);
|
clicon_err(OE_PLUGIN, 0, "%s Requires arguments: <logstream> <status> [<format>]", __FUNCTION__);
|
||||||
|
|
@ -915,12 +896,7 @@ cli_notifyv(clicon_handle h,
|
||||||
status = atoi(cv_string_get(cvec_i(argv, 1)));
|
status = atoi(cv_string_get(cvec_i(argv, 1)));
|
||||||
if (cvec_len(argv) > 2){
|
if (cvec_len(argv) > 2){
|
||||||
formatstr = cv_string_get(cvec_i(argv, 2));
|
formatstr = cv_string_get(cvec_i(argv, 2));
|
||||||
if (strcmp(formatstr, "SHOWAS_TXT") != 0)
|
format = format_str2int(formatstr);
|
||||||
format = MSG_NOTIFY_XML;
|
|
||||||
if ((formatstr = strdup(formatstr)) == NULL){ /* XXX */
|
|
||||||
clicon_err(OE_PLUGIN, 0, "%s Requires arguments: <logstream> <status> [<format>]", __FUNCTION__);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (cli_notification_register(h,
|
if (cli_notification_register(h,
|
||||||
stream,
|
stream,
|
||||||
|
|
@ -928,7 +904,7 @@ cli_notifyv(clicon_handle h,
|
||||||
"",
|
"",
|
||||||
status,
|
status,
|
||||||
cli_notification_cb,
|
cli_notification_cb,
|
||||||
formatstr) < 0)
|
(void*)format) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -1046,7 +1022,7 @@ load_config_file(clicon_handle h,
|
||||||
cvec *argv;
|
cvec *argv;
|
||||||
cg_var *cv;
|
cg_var *cv;
|
||||||
char *str;
|
char *str;
|
||||||
char **vec;
|
char **vec = NULL;
|
||||||
int nvec;
|
int nvec;
|
||||||
|
|
||||||
/* Split string into two parts and build a cvec of it and supply that to
|
/* 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__);
|
clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((vec = clicon_strsplit(str, " ", &nvec, __FUNCTION__)) == NULL){
|
if ((vec = clicon_strsep(str, " ", &nvec)) == NULL)
|
||||||
clicon_err(OE_PLUGIN, errno, "clicon_strsplit");
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
|
||||||
if (nvec != 2){
|
if (nvec != 2){
|
||||||
clicon_err(OE_PLUGIN, 0, "Arg syntax is <varname> <replace|merge>");
|
clicon_err(OE_PLUGIN, 0, "Arg syntax is <varname> <replace|merge>");
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1076,7 +1050,8 @@ load_config_file(clicon_handle h,
|
||||||
|
|
||||||
retval = load_config_filev(h, cvv, argv);
|
retval = load_config_filev(h, cvv, argv);
|
||||||
done:
|
done:
|
||||||
unchunk_group(__FUNCTION__);
|
if (vec)
|
||||||
|
free(vec);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
int
|
int
|
||||||
|
|
@ -1088,7 +1063,7 @@ save_config_file(clicon_handle h,
|
||||||
cvec *argv;
|
cvec *argv;
|
||||||
cg_var *cv;
|
cg_var *cv;
|
||||||
char *str;
|
char *str;
|
||||||
char **vec;
|
char **vec = NULL;
|
||||||
int nvec;
|
int nvec;
|
||||||
|
|
||||||
/* Split string into two parts and build a cvec of it and supply that to
|
/* 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__);
|
clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((vec = clicon_strsplit(str, " ", &nvec, __FUNCTION__)) == NULL){
|
if ((vec = clicon_strsep(str, " ", &nvec)) == NULL)
|
||||||
clicon_err(OE_PLUGIN, errno, "clicon_strsplit");
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
|
||||||
if (nvec != 2){
|
if (nvec != 2){
|
||||||
clicon_err(OE_PLUGIN, 0, "Arg syntax is <dbname> <varname>");
|
clicon_err(OE_PLUGIN, 0, "Arg syntax is <dbname> <varname>");
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1118,7 +1091,8 @@ save_config_file(clicon_handle h,
|
||||||
|
|
||||||
retval = save_config_filev(h, cvv, argv);
|
retval = save_config_filev(h, cvv, argv);
|
||||||
done:
|
done:
|
||||||
unchunk_group(__FUNCTION__);
|
if (vec)
|
||||||
|
free(vec);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1131,7 +1105,7 @@ cli_notify(clicon_handle h,
|
||||||
cvec *argv;
|
cvec *argv;
|
||||||
cg_var *cv;
|
cg_var *cv;
|
||||||
char *str;
|
char *str;
|
||||||
char **vec;
|
char **vec = NULL;
|
||||||
int nvec;
|
int nvec;
|
||||||
|
|
||||||
/* Split string into two parts and build a cvec of it and supply that to
|
/* 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__);
|
clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((vec = clicon_strsplit(str, " ", &nvec, __FUNCTION__)) == NULL){
|
if ((vec = clicon_strsep(str, " ", &nvec)) == NULL)
|
||||||
clicon_err(OE_PLUGIN, errno, "clicon_strsplit");
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
|
||||||
if (nvec != 2 && nvec != 3){
|
if (nvec != 2 && nvec != 3){
|
||||||
clicon_err(OE_PLUGIN, 0, "Arg syntax is <logstream> <status> [<format>]");
|
clicon_err(OE_PLUGIN, 0, "Arg syntax is <logstream> <status> [<format>]");
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1166,7 +1138,8 @@ cli_notify(clicon_handle h,
|
||||||
}
|
}
|
||||||
retval = cli_notifyv(h, cvv, argv);
|
retval = cli_notifyv(h, cvv, argv);
|
||||||
done:
|
done:
|
||||||
unchunk_group(__FUNCTION__);
|
if (vec)
|
||||||
|
free(vec);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -174,7 +174,7 @@ main(int argc, char **argv)
|
||||||
int help = 0;
|
int help = 0;
|
||||||
char *treename;
|
char *treename;
|
||||||
int logdst = CLICON_LOG_STDERR;
|
int logdst = CLICON_LOG_STDERR;
|
||||||
char *restarg; /* what remains after options */
|
char *restarg = NULL; /* what remains after options */
|
||||||
|
|
||||||
/* Defaults */
|
/* Defaults */
|
||||||
|
|
||||||
|
|
@ -366,7 +366,7 @@ main(int argc, char **argv)
|
||||||
clicon_option_dump(h, debug);
|
clicon_option_dump(h, debug);
|
||||||
|
|
||||||
/* Join rest of argv to a single command */
|
/* 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 */
|
/* If several cligen object variables match same preference, select first */
|
||||||
cligen_match_cgvar_same(1);
|
cligen_match_cgvar_same(1);
|
||||||
|
|
@ -389,6 +389,8 @@ main(int argc, char **argv)
|
||||||
if (!once)
|
if (!once)
|
||||||
cli_interactive(h);
|
cli_interactive(h);
|
||||||
done:
|
done:
|
||||||
|
if (restarg)
|
||||||
|
free(restarg);
|
||||||
unchunk_group(__FUNCTION__);
|
unchunk_group(__FUNCTION__);
|
||||||
// Gets in your face if we log on stderr
|
// Gets in your face if we log on stderr
|
||||||
clicon_log_init(__PROGRAM__, LOG_INFO, 0); /* Log on syslog no stderr */
|
clicon_log_init(__PROGRAM__, LOG_INFO, 0); /* Log on syslog no stderr */
|
||||||
|
|
|
||||||
|
|
@ -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);
|
clicon_err(OE_PLUGIN, 0, "No syntax mode specified in %s", filepath);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((vec = clicon_strsplit(mode, ":", &nvec, __FUNCTION__)) == NULL) {
|
if ((vec = clicon_strsep(mode, ":", &nvec)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
|
||||||
for (i = 0; i < nvec; i++) {
|
for (i = 0; i < nvec; i++) {
|
||||||
if (syntax_append(h, cli_syntax(h), vec[i], pt) < 0) {
|
if (syntax_append(h, cli_syntax(h), vec[i], pt) < 0) {
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -415,6 +414,8 @@ cli_load_syntax(clicon_handle h, const char *filename, const char *clispec_dir)
|
||||||
done:
|
done:
|
||||||
if (vr)
|
if (vr)
|
||||||
cvec_free(vr);
|
cvec_free(vr);
|
||||||
|
if (vec)
|
||||||
|
free(vec);
|
||||||
unchunk_group(__FUNCTION__);
|
unchunk_group(__FUNCTION__);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
@ -1020,7 +1021,7 @@ cli_ptpush(clicon_handle h, char *mode, char *string, char *op)
|
||||||
return 0;
|
return 0;
|
||||||
pt = &co_cmd->co_pt;
|
pt = &co_cmd->co_pt;
|
||||||
/* vec is the command, eg 'edit policy_option' */
|
/* 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;
|
goto catch;
|
||||||
co = NULL;
|
co = NULL;
|
||||||
found = 0;
|
found = 0;
|
||||||
|
|
@ -1050,7 +1051,8 @@ cli_ptpush(clicon_handle h, char *mode, char *string, char *op)
|
||||||
co_up_set(cc, co_cmd);
|
co_up_set(cc, co_cmd);
|
||||||
}
|
}
|
||||||
catch:
|
catch:
|
||||||
unchunk_group(__FUNCTION__) ;
|
if (vec)
|
||||||
|
free(vec);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -787,10 +787,8 @@ expand_dbvar(void *h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
/* In the example, str = "candidate /x/m1/%s/b" */
|
/* In the example, str = "candidate /x/m1/%s/b" */
|
||||||
if ((vec = clicon_strsplit(str, " ", &nvec, __FUNCTION__)) == NULL){
|
if ((vec = clicon_strsep(str, " ", &nvec)) == NULL)
|
||||||
clicon_err(OE_PLUGIN, errno, "clicon_strsplit");
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
|
||||||
dbstr = vec[0];
|
dbstr = vec[0];
|
||||||
if (strcmp(dbstr, "running") != 0 &&
|
if (strcmp(dbstr, "running") != 0 &&
|
||||||
strcmp(dbstr, "candidate") != 0 &&
|
strcmp(dbstr, "candidate") != 0 &&
|
||||||
|
|
@ -856,7 +854,8 @@ expand_dbvar(void *h,
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
unchunk_group(__FUNCTION__);
|
if (vec)
|
||||||
|
free(vec);
|
||||||
if (xvec)
|
if (xvec)
|
||||||
free(xvec);
|
free(xvec);
|
||||||
if (xt)
|
if (xt)
|
||||||
|
|
@ -905,10 +904,8 @@ show_conf_as(clicon_handle h,
|
||||||
clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__);
|
clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((vec = clicon_strsplit(str, " ", &nvec, __FUNCTION__)) == NULL){
|
if ((vec = clicon_strsep(str, " ", &nvec)) == NULL)
|
||||||
clicon_err(OE_PLUGIN, errno, "clicon_strsplit");
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
|
||||||
if (nvec != 2 && nvec != 3){
|
if (nvec != 2 && nvec != 3){
|
||||||
clicon_err(OE_PLUGIN, 0, "format error \"%s\" - expected <dbname> <xpath> [<attr>] got %d arg", str, nvec);
|
clicon_err(OE_PLUGIN, 0, "format error \"%s\" - expected <dbname> <xpath> [<attr>] got %d arg", str, nvec);
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -956,7 +953,8 @@ done:
|
||||||
free(val);
|
free(val);
|
||||||
if (cbx)
|
if (cbx)
|
||||||
cbuf_free(cbx);
|
cbuf_free(cbx);
|
||||||
unchunk_group(__FUNCTION__);
|
if (vec)
|
||||||
|
free(vec);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,7 @@ request_process(clicon_handle h,
|
||||||
char *path;
|
char *path;
|
||||||
char *query;
|
char *query;
|
||||||
char *method;
|
char *method;
|
||||||
char **pvec;
|
char **pvec = NULL;
|
||||||
int pn;
|
int pn;
|
||||||
cvec *qvec = NULL;
|
cvec *qvec = NULL;
|
||||||
cvec *dvec = NULL;
|
cvec *dvec = NULL;
|
||||||
|
|
@ -141,7 +141,7 @@ request_process(clicon_handle h,
|
||||||
clicon_debug(1, "%s", __FUNCTION__);
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
path = FCGX_GetParam("DOCUMENT_URI", r->envp);
|
path = FCGX_GetParam("DOCUMENT_URI", r->envp);
|
||||||
query = FCGX_GetParam("QUERY_STRING", 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;
|
goto done;
|
||||||
|
|
||||||
if (str2cvec(query, '&', '=', &qvec) < 0)
|
if (str2cvec(query, '&', '=', &qvec) < 0)
|
||||||
|
|
@ -171,7 +171,6 @@ request_process(clicon_handle h,
|
||||||
if (auth == 0)
|
if (auth == 0)
|
||||||
goto done;
|
goto done;
|
||||||
clicon_debug(1, "%s credentials ok 2", __FUNCTION__);
|
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 */
|
if (strcmp(method, "data") == 0) /* restconf, skip /api/data */
|
||||||
retval = api_data(h, r, path, pcvec, 2, qvec, data);
|
retval = api_data(h, r, path, pcvec, 2, qvec, data);
|
||||||
|
|
@ -181,6 +180,8 @@ request_process(clicon_handle h,
|
||||||
retval = notfound(r);
|
retval = notfound(r);
|
||||||
done:
|
done:
|
||||||
clicon_debug(1, "%s retval:%d K", __FUNCTION__, retval);
|
clicon_debug(1, "%s retval:%d K", __FUNCTION__, retval);
|
||||||
|
if (pvec)
|
||||||
|
free(pvec);
|
||||||
if (dvec)
|
if (dvec)
|
||||||
cvec_free(dvec);
|
cvec_free(dvec);
|
||||||
if (qvec)
|
if (qvec)
|
||||||
|
|
@ -189,7 +190,6 @@ request_process(clicon_handle h,
|
||||||
cvec_free(pcvec);
|
cvec_free(pcvec);
|
||||||
if (cb)
|
if (cb)
|
||||||
cbuf_free(cb);
|
cbuf_free(cb);
|
||||||
unchunk_group(__FUNCTION__);
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ load("Load configuration from XML file") <filename:string>("Filename (local file
|
||||||
}
|
}
|
||||||
example("This is a comment") <var:int32>("Just a random number"), mycallback("myarg");
|
example("This is a comment") <var:int32>("Just a random number"), mycallback("myarg");
|
||||||
downcall("This is a downcall") <str:rest>, downcall();
|
downcall("This is a downcall") <str:rest>, 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");
|
no("Negate") notify("Get notifications from backend"), cli_notifyv("ROUTING", "0", "xml");
|
||||||
lock,cli_lock("candidate");
|
lock,cli_lock("candidate");
|
||||||
unlock,cli_unlock("candidate");
|
unlock,cli_unlock("candidate");
|
||||||
|
|
@ -42,8 +42,11 @@
|
||||||
* Types
|
* Types
|
||||||
*/
|
*/
|
||||||
enum format_enum{
|
enum format_enum{
|
||||||
MSG_NOTIFY_TXT, /* means filter works on strings */
|
FORMAT_XML,
|
||||||
MSG_NOTIFY_XML, /* means filter works on xml */
|
FORMAT_JSON,
|
||||||
|
FORMAT_TEXT,
|
||||||
|
FORMAT_CLI,
|
||||||
|
FORMAT_NETCONF
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Protocol message header */
|
/* Protocol message header */
|
||||||
|
|
@ -55,6 +58,9 @@ struct clicon_msg {
|
||||||
/*
|
/*
|
||||||
* Prototypes
|
* Prototypes
|
||||||
*/
|
*/
|
||||||
|
char *format_int2str(enum format_enum showas);
|
||||||
|
enum format_enum format_str2int(char *str);
|
||||||
|
|
||||||
struct clicon_msg *clicon_msg_encode(char *format, ...);
|
struct clicon_msg *clicon_msg_encode(char *format, ...);
|
||||||
int clicon_msg_decode(struct clicon_msg *msg, cxobj **xml);
|
int clicon_msg_decode(struct clicon_msg *msg, cxobj **xml);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,17 +54,10 @@ static inline char * strdup4(char *str)
|
||||||
/*
|
/*
|
||||||
* Prototypes
|
* 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_strsep(char *string, char *delim, int *nvec0);
|
||||||
char *clicon_strjoin (int argc, char **argv, char *delim, const char *label);
|
char *clicon_strjoin (int argc, char **argv, char *delim);
|
||||||
char *clicon_strtrim(char *str, const char *label);
|
|
||||||
int clicon_sep(char *s, const char sep[2], const char *label, char**a0, char **b0);
|
|
||||||
#ifndef HAVE_STRNDUP
|
#ifndef HAVE_STRNDUP
|
||||||
char *clicon_strndup (const char *, size_t);
|
char *clicon_strndup (const char *, size_t);
|
||||||
#endif /* ! HAVE_STRNDUP */
|
#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_ */
|
#endif /* _CLIXON_STRING_H_ */
|
||||||
|
|
|
||||||
|
|
@ -62,19 +62,22 @@
|
||||||
#include "clixon_string.h"
|
#include "clixon_string.h"
|
||||||
#include "clixon_file.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
|
* 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
|
* 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
|
* entry is the resolved path and the second is the part of the path which
|
||||||
* actually exist.
|
* actually exist.
|
||||||
|
* @retval vec
|
||||||
*/
|
*/
|
||||||
char **
|
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 **ret = NULL;
|
||||||
char *rest;
|
char *rest;
|
||||||
char **vec, **vec2;
|
char **vec = NULL;
|
||||||
|
char **vec2;
|
||||||
int nvec, nvec2;
|
int nvec, nvec2;
|
||||||
char *p;
|
char *p;
|
||||||
char *rp = NULL;
|
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
|
/* Split path based on '/'. Loop through vector from the end and copy
|
||||||
each entry into a new vector, skipping '..' and it's previous directory
|
each entry into a new vector, skipping '..' and it's previous directory
|
||||||
as well as all '.' */
|
as well as all '.' */
|
||||||
vec = clicon_strsplit (p, "/", &nvec, __FUNCTION__);
|
if ((vec = clicon_strsep(p, "/", &nvec)) == NULL)
|
||||||
vec2 = chunk(nvec * sizeof(char *), __FUNCTION__);
|
goto catch;
|
||||||
|
if ((vec2 = malloc(nvec * sizeof(char *))) == NULL)
|
||||||
|
goto catch;
|
||||||
nvec2 = i = nvec;
|
nvec2 = i = nvec;
|
||||||
while(--i >= 0) {
|
while(--i >= 0) {
|
||||||
if(strcmp(vec[i], "..") == 0)
|
if(strcmp(vec[i], "..") == 0)
|
||||||
|
|
@ -135,14 +140,14 @@ clicon_realpath(const char *cwd, char *path, const char *label)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create resulting vector */
|
/* Create resulting vector */
|
||||||
if ((ret = chunk(sizeof(char *) * 2, label)) != NULL) {
|
if ((ret = malloc(sizeof(char *) * 2)) != NULL) {
|
||||||
if((ret[0] = clicon_strjoin(nvec-nvec2, &vec2[nvec2], "/", label)) == NULL) {
|
if((ret[0] = clicon_strjoin(nvec-nvec2, &vec2[nvec2], "/")) == NULL) {
|
||||||
unchunk(ret);
|
free(ret);
|
||||||
ret = NULL;
|
ret = NULL;
|
||||||
}
|
}
|
||||||
if ((ret[1] = chunkdup(rp, strlen(rp)+1, label)) == NULL) {
|
if ((ret[1] = strdup(rp)) == NULL) {
|
||||||
unchunk(ret[0]);
|
free(ret[0]);
|
||||||
unchunk(ret);
|
free(ret);
|
||||||
ret = NULL;
|
ret = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -150,6 +155,10 @@ clicon_realpath(const char *cwd, char *path, const char *label)
|
||||||
catch:
|
catch:
|
||||||
if(rp)
|
if(rp)
|
||||||
free(rp);
|
free(rp);
|
||||||
|
if(vec)
|
||||||
|
free(vec);
|
||||||
|
if(vec2)
|
||||||
|
free(vec2);
|
||||||
unchunk_group(__FUNCTION__);
|
unchunk_group(__FUNCTION__);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -121,14 +121,13 @@ clicon_proc_run (char *cmd,
|
||||||
sigfn_t oldhandler = NULL;
|
sigfn_t oldhandler = NULL;
|
||||||
sigset_t oset;
|
sigset_t oset;
|
||||||
|
|
||||||
argv = clicon_sepsplit (cmd, " \t", &argc, __FUNCTION__);
|
argv = clicon_strsep(cmd, " \t", &argc);
|
||||||
if (!argv)
|
if (!argv)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (pipe (outfd) == -1)
|
if (pipe (outfd) == -1)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
|
||||||
signal_get_mask(&oset);
|
signal_get_mask(&oset);
|
||||||
set_signal(SIGINT, clicon_proc_sigint, &oldhandler);
|
set_signal(SIGINT, clicon_proc_sigint, &oldhandler);
|
||||||
|
|
||||||
|
|
@ -194,7 +193,8 @@ clicon_proc_run (char *cmd,
|
||||||
signal_set_mask (&oset);
|
signal_set_mask (&oset);
|
||||||
set_signal(SIGINT, oldhandler, NULL);
|
set_signal(SIGINT, oldhandler, NULL);
|
||||||
|
|
||||||
unchunk_group (__FUNCTION__);
|
if(argv)
|
||||||
|
free(argv);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -216,7 +216,7 @@ clicon_proc_daemon (char *cmd)
|
||||||
struct rlimit
|
struct rlimit
|
||||||
rlim;
|
rlim;
|
||||||
|
|
||||||
argv = clicon_sepsplit (cmd, " \t", &argc, NULL);
|
argv = clicon_strsep(cmd, " \t", &argc);
|
||||||
if (!argv)
|
if (!argv)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
|
@ -260,7 +260,8 @@ clicon_proc_daemon (char *cmd)
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
unchunk_group(__FUNCTION__);
|
if (argv)
|
||||||
|
free(argv);
|
||||||
return (retval);
|
return (retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,46 @@
|
||||||
|
|
||||||
static int _atomicio_sig = 0;
|
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
|
/*! Encode a clicon netconf message
|
||||||
* @param[in] param Variable agrument list format an XML netconf string
|
* @param[in] param Variable agrument list format an XML netconf string
|
||||||
* @retval msg Clicon message to send to eg clicon_msg_send()
|
* @retval msg Clicon message to send to eg clicon_msg_send()
|
||||||
|
|
|
||||||
|
|
@ -53,117 +53,6 @@
|
||||||
#include "clixon_string.h"
|
#include "clixon_string.h"
|
||||||
#include "clixon_err.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
|
/*! Split string into a vector based on character delimiters. Using malloc
|
||||||
*
|
*
|
||||||
|
|
@ -189,14 +78,20 @@ clicon_strsep(char *string,
|
||||||
char *p;
|
char *p;
|
||||||
int nvec = 1;
|
int nvec = 1;
|
||||||
int i;
|
int i;
|
||||||
|
char *s;
|
||||||
|
char *d;
|
||||||
|
|
||||||
for (i=0; i<strlen(string); i++)
|
if ((s = string)==NULL)
|
||||||
if (index(delim, string[i]))
|
goto done;
|
||||||
|
while (*s){
|
||||||
|
if ((d = index(delim, *s)) != NULL)
|
||||||
nvec++;
|
nvec++;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
/* alloc vector and append copy of string */
|
/* alloc vector and append copy of string */
|
||||||
if ((vec = (char**)malloc(nvec* sizeof(char*) + strlen(string)+1)) == NULL){
|
if ((vec = (char**)malloc(nvec* sizeof(char*) + strlen(string)+1)) == NULL){
|
||||||
clicon_err(OE_YANG, errno, "malloc");
|
clicon_err(OE_UNIX, errno, "malloc");
|
||||||
goto err;
|
goto done;
|
||||||
}
|
}
|
||||||
ptr = (char*)vec + nvec* sizeof(char*); /* this is where ptr starts */
|
ptr = (char*)vec + nvec* sizeof(char*); /* this is where ptr starts */
|
||||||
strncpy(ptr, string, strlen(string)+1);
|
strncpy(ptr, string, strlen(string)+1);
|
||||||
|
|
@ -204,23 +99,20 @@ clicon_strsep(char *string,
|
||||||
while ((p = strsep(&ptr, delim)) != NULL)
|
while ((p = strsep(&ptr, delim)) != NULL)
|
||||||
vec[i++] = p;
|
vec[i++] = p;
|
||||||
*nvec0 = nvec;
|
*nvec0 = nvec;
|
||||||
err:
|
done:
|
||||||
return vec;
|
return vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Concatenate elements of a string array into a string.
|
/*! Concatenate elements of a string array into a string.
|
||||||
* An optional delimiter string can be specified which will be inserted betwen
|
* An optional delimiter string can be specified which will be inserted betwen
|
||||||
* each element.
|
* each element.
|
||||||
* @param[in] label Chunk label for returned vector
|
* @retval str Joined string. Free after use.
|
||||||
* @retval str Joined string. Free with unchunk()
|
|
||||||
* @retval NULL Failure
|
* @retval NULL Failure
|
||||||
*/
|
*/
|
||||||
char *
|
char *
|
||||||
clicon_strjoin (int argc,
|
clicon_strjoin(int argc,
|
||||||
char **argv,
|
char **argv,
|
||||||
char *delim,
|
char *delim)
|
||||||
const char *label)
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int len;
|
int len;
|
||||||
|
|
@ -232,95 +124,17 @@ clicon_strjoin (int argc,
|
||||||
if (delim)
|
if (delim)
|
||||||
len += (strlen(delim) * argc);
|
len += (strlen(delim) * argc);
|
||||||
len += 1; /* '\0' */
|
len += 1; /* '\0' */
|
||||||
|
if ((str = malloc(len)) == NULL)
|
||||||
if ((str = chunk (len, label)) == NULL)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
memset (str, '\0', len);
|
memset (str, '\0', len);
|
||||||
|
|
||||||
for (i = 0; i < argc; i++) {
|
for (i = 0; i < argc; i++) {
|
||||||
if (i != 0)
|
if (i != 0)
|
||||||
strncat (str, delim, len - strlen(str));
|
strncat (str, delim, len - strlen(str));
|
||||||
strncat (str, argv[i], len - strlen(str));
|
strncat (str, argv[i], len - strlen(str));
|
||||||
}
|
}
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Trim whitespace in beginning and end of string.
|
|
||||||
*
|
|
||||||
* @param[in] label Chunk label for returned vector
|
|
||||||
* @retval str Trimmed string. Free with unchunk()
|
|
||||||
* @retval NULL Failure
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
clicon_strtrim(char *str,
|
|
||||||
const char *label)
|
|
||||||
{
|
|
||||||
char *start, *end, *new;
|
|
||||||
|
|
||||||
start = str;
|
|
||||||
while (*start != '\0' && isspace(*start))
|
|
||||||
start++;
|
|
||||||
if (!strlen(start))
|
|
||||||
return (char *)chunkdup("\0", 1, label);
|
|
||||||
|
|
||||||
end = str + strlen(str) ;
|
|
||||||
while (end > 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 len;
|
|
||||||
int retval = -1;
|
|
||||||
|
|
||||||
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';
|
|
||||||
}
|
|
||||||
|
|
||||||
*a0 = a;
|
|
||||||
*b0 = b;
|
|
||||||
retval = 0;
|
|
||||||
catch:
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*! strndup() for systems without it, such as xBSD
|
/*! strndup() for systems without it, such as xBSD
|
||||||
*/
|
*/
|
||||||
|
|
@ -346,82 +160,48 @@ clicon_strndup (const char *str,
|
||||||
}
|
}
|
||||||
#endif /* ! HAVE_STRNDUP */
|
#endif /* ! HAVE_STRNDUP */
|
||||||
|
|
||||||
/*! Match string against regexp.
|
/*
|
||||||
*
|
* Turn this on for uni-test programs
|
||||||
* If a match pointer is given, the matching substring
|
* Usage: clixon_string join
|
||||||
* will be allocated 'match' will be pointing to it. The match string must
|
* Example compile:
|
||||||
* be free:ed by the application.
|
gcc -g -o clixon_string -I. -I../clixon ./clixon_string.c -lclixon -lcligen
|
||||||
* @retval -1 Failure
|
* Example run:
|
||||||
* @retval 0 No match
|
*/
|
||||||
* @retval >0 Match: Length of matching substring
|
#if 0 /* Test program */
|
||||||
*/
|
|
||||||
|
static int
|
||||||
|
usage(char *argv0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "usage:%s <string>\n", argv0);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
clicon_strmatch(const char *str,
|
main(int argc, char **argv)
|
||||||
const char *regexp,
|
|
||||||
char **match)
|
|
||||||
{
|
{
|
||||||
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;
|
int nvec;
|
||||||
char *new;
|
char **vec;
|
||||||
char *retval = NULL;
|
char *str0;
|
||||||
|
char *str1;
|
||||||
|
int i;
|
||||||
|
|
||||||
if ((vec = clicon_strsplit(str, from, &nvec, __FUNCTION__)) == NULL) {
|
if (argc != 2){
|
||||||
clicon_err(OE_UNIX, errno, "Failed to split string");
|
usage(argv[0]);
|
||||||
goto done;
|
return 0;
|
||||||
}
|
}
|
||||||
|
str0 = argv[1];
|
||||||
if ((new = clicon_strjoin (nvec, vec, to, __FUNCTION__)) == NULL) {
|
if ((vec = clicon_strsep("a b\tc", " \t", &nvec)) == NULL)
|
||||||
clicon_err(OE_UNIX, errno, "Failed to split string");
|
return -1;
|
||||||
goto done;
|
fprintf(stderr, "nvec: %d\n", nvec);
|
||||||
}
|
for (i=0; i<nvec; i++)
|
||||||
|
fprintf(stderr, "vec[%d]: %s\n", i, vec[i]);
|
||||||
retval = strdup(new);
|
if ((str1 = clicon_strjoin(nvec, vec, " ")) == NULL)
|
||||||
|
return -1;
|
||||||
done:
|
fprintf(stderr, "join: %s\n", str1);
|
||||||
unchunk_group(__FUNCTION__);
|
free(vec);
|
||||||
return retval;
|
free(str1);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* Test program */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -665,9 +665,9 @@ get(char *dbname,
|
||||||
cxobj *xt)
|
cxobj *xt)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char **vec;
|
char **vec = NULL;
|
||||||
int nvec;
|
int nvec;
|
||||||
char **valvec;
|
char **valvec = NULL;
|
||||||
int nvalvec;
|
int nvalvec;
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
|
|
@ -691,7 +691,7 @@ get(char *dbname,
|
||||||
clicon_err(OE_DB, 0, "Invalid key: %s", xk);
|
clicon_err(OE_DB, 0, "Invalid key: %s", xk);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((vec = clicon_strsplit(xk, "/", &nvec, __FUNCTION__)) == NULL)
|
if ((vec = clicon_strsep(xk, "/", &nvec)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
/* Element 0 is NULL '/',
|
/* Element 0 is NULL '/',
|
||||||
Element 1 is top symbol and needs to find subs in all modules:
|
Element 1 is top symbol and needs to find subs in all modules:
|
||||||
|
|
@ -759,7 +759,9 @@ get(char *dbname,
|
||||||
cvi = NULL;
|
cvi = NULL;
|
||||||
/* Iterate over individual yang keys */
|
/* Iterate over individual yang keys */
|
||||||
cprintf(cb, "%s", name);
|
cprintf(cb, "%s", name);
|
||||||
if ((valvec = clicon_strsplit(restval, ",", &nvalvec, __FUNCTION__)) == NULL)
|
if (valvec)
|
||||||
|
free(valvec);
|
||||||
|
if ((valvec = clicon_strsep(restval, ",", &nvalvec)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (cvec_len(cvk)!=nvalvec){
|
if (cvec_len(cvk)!=nvalvec){
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -834,7 +836,10 @@ get(char *dbname,
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
unchunk_group(__FUNCTION__);
|
if (vec)
|
||||||
|
free(vec);
|
||||||
|
if (valvec)
|
||||||
|
free(valvec);
|
||||||
if (cvk)
|
if (cvk)
|
||||||
cvec_free(cvk);
|
cvec_free(cvk);
|
||||||
return retval;
|
return retval;
|
||||||
|
|
@ -1210,9 +1215,9 @@ xmldb_put_xkey(clicon_handle h,
|
||||||
cxobj *x = NULL;
|
cxobj *x = NULL;
|
||||||
yang_stmt *y = NULL;
|
yang_stmt *y = NULL;
|
||||||
yang_stmt *ykey;
|
yang_stmt *ykey;
|
||||||
char **vec;
|
char **vec = NULL;
|
||||||
int nvec;
|
int nvec;
|
||||||
char **valvec;
|
char **valvec = NULL;
|
||||||
int nvalvec;
|
int nvalvec;
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
|
|
@ -1246,7 +1251,7 @@ xmldb_put_xkey(clicon_handle h,
|
||||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((vec = clicon_strsplit(xk, "/", &nvec, __FUNCTION__)) == NULL)
|
if ((vec = clicon_strsep(xk, "/", &nvec)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (nvec < 2){
|
if (nvec < 2){
|
||||||
clicon_err(OE_XML, 0, "Malformed key: %s", xk);
|
clicon_err(OE_XML, 0, "Malformed key: %s", xk);
|
||||||
|
|
@ -1305,7 +1310,9 @@ xmldb_put_xkey(clicon_handle h,
|
||||||
clicon_err(OE_XML, 0, "malformed key, expected '=<restval>'");
|
clicon_err(OE_XML, 0, "malformed key, expected '=<restval>'");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((valvec = clicon_strsplit(restval, ",", &nvalvec, __FUNCTION__)) == NULL)
|
if (valvec)
|
||||||
|
free(valvec);
|
||||||
|
if ((valvec = clicon_strsep(restval, ",", &nvalvec)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
if (cvec_len(cvk) != nvalvec){
|
if (cvec_len(cvk) != nvalvec){
|
||||||
|
|
@ -1398,6 +1405,11 @@ xmldb_put_xkey(clicon_handle h,
|
||||||
cbuf_free(crx);
|
cbuf_free(crx);
|
||||||
if (cvk)
|
if (cvk)
|
||||||
cvec_free(cvk);
|
cvec_free(cvk);
|
||||||
|
if (vec)
|
||||||
|
free(vec);
|
||||||
|
if (valvec)
|
||||||
|
free(valvec);
|
||||||
|
|
||||||
unchunk_group(__FUNCTION__);
|
unchunk_group(__FUNCTION__);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
@ -1431,7 +1443,7 @@ xmldb_put_restconf_api_path(clicon_handle h,
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
yang_stmt *y = NULL;
|
yang_stmt *y = NULL;
|
||||||
yang_stmt *ykey;
|
yang_stmt *ykey;
|
||||||
char **vec;
|
char **vec = NULL;
|
||||||
int nvec;
|
int nvec;
|
||||||
int i;
|
int i;
|
||||||
char *name;
|
char *name;
|
||||||
|
|
@ -1466,7 +1478,7 @@ xmldb_put_restconf_api_path(clicon_handle h,
|
||||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((vec = clicon_strsplit(api_path, "/", &nvec, __FUNCTION__)) == NULL)
|
if ((vec = clicon_strsep(api_path, "/", &nvec)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (nvec < 2){
|
if (nvec < 2){
|
||||||
clicon_err(OE_XML, 0, "Malformed key: %s", api_path);
|
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);
|
cbuf_free(crx);
|
||||||
if (cvk)
|
if (cvk)
|
||||||
cvec_free(cvk);
|
cvec_free(cvk);
|
||||||
|
if (vec)
|
||||||
|
free(vec);
|
||||||
unchunk_group(__FUNCTION__);
|
unchunk_group(__FUNCTION__);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1695,11 +1695,9 @@ yang_xpath_abs(yang_node *yn,
|
||||||
char *prefix = NULL;
|
char *prefix = NULL;
|
||||||
|
|
||||||
if ((vec = clicon_strsep(xpath, "/", &nvec)) == 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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Assume path looks like: "/prefix:id[/prefix:id]*" */
|
/* Assume path looks like: "/prefix:id[/prefix:id]*" */
|
||||||
if (nvec < 2){
|
if (nvec < 2){
|
||||||
clicon_err(OE_YANG, 0, "%s: NULL or truncated path: %s",
|
clicon_err(OE_YANG, 0, "%s: NULL or truncated path: %s",
|
||||||
|
|
@ -1955,16 +1953,14 @@ cvec *
|
||||||
yang_arg2cvec(yang_stmt *ys,
|
yang_arg2cvec(yang_stmt *ys,
|
||||||
char *delim)
|
char *delim)
|
||||||
{
|
{
|
||||||
char **vec;
|
char **vec = NULL;
|
||||||
int i;
|
int i;
|
||||||
int nvec;
|
int nvec;
|
||||||
cvec *cvv = NULL;
|
cvec *cvv = NULL;
|
||||||
cg_var *cv;
|
cg_var *cv;
|
||||||
|
|
||||||
if ((vec = clicon_strsplit(ys->ys_argument, " ", &nvec, __FUNCTION__)) == NULL){
|
if ((vec = clicon_strsep(ys->ys_argument, " ", &nvec)) == NULL)
|
||||||
clicon_err(OE_YANG, errno, "clicon_strsplit");
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
|
||||||
if ((cvv = cvec_new(nvec)) == NULL){
|
if ((cvv = cvec_new(nvec)) == NULL){
|
||||||
clicon_err(OE_YANG, errno, "cvec_new");
|
clicon_err(OE_YANG, errno, "cvec_new");
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1979,7 +1975,8 @@ yang_arg2cvec(yang_stmt *ys,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
unchunk_group(__FUNCTION__);
|
if (vec)
|
||||||
|
free(vec);
|
||||||
return cvv;
|
return cvv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ if [ $? -ne 0 ]; then
|
||||||
err
|
err
|
||||||
fi
|
fi
|
||||||
new "netconf get empty config"
|
new "netconf get empty config"
|
||||||
expecteof "valgrind $clixon_netconf -qf $clixon_cf" "<rpc message-id=\"101\"><get-config><source><candidate/></source></get-config></rpc>]]>]]>" "^<rpc-reply message-id=\"101\"><data/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $clixon_cf" "<rpc message-id=\"101\"><get-config><source><candidate/></source></get-config></rpc>]]>]]>" "^<rpc-reply message-id=\"101\"><data/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "netconf edit config"
|
new "netconf edit config"
|
||||||
expecteof "$clixon_netconf -qf $clixon_cf" "<rpc><edit-config><target><candidate/></target><config><interfaces><interface><name>eth0</name></interface><interface><name>eth1</name><enabled>true</enabled><ipv4><address><ip>9.2.3.4</ip><prefix-length>24</prefix-length></address></ipv4></interface></interfaces></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $clixon_cf" "<rpc><edit-config><target><candidate/></target><config><interfaces><interface><name>eth0</name></interface><interface><name>eth1</name><enabled>true</enabled><ipv4><address><ip>9.2.3.4</ip><prefix-length>24</prefix-length></address></ipv4></interface></interfaces></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue