Merge branch 'master' into feature_openconfig_compress
This commit is contained in:
commit
9d8d9ac042
43 changed files with 997 additions and 139 deletions
|
|
@ -68,6 +68,10 @@ Developers may need to change their code
|
||||||
|
|
||||||
### Minor features
|
### Minor features
|
||||||
|
|
||||||
|
* Plugin context check before and after all callbacks.
|
||||||
|
* Check blocked signals and signal handlers
|
||||||
|
* Check termios settings
|
||||||
|
* Any changes to context are logged at loglevel WARNING
|
||||||
* Added set/get pointer API to clixon_data:
|
* Added set/get pointer API to clixon_data:
|
||||||
* clicon_ptr_get(), clicon_ptr_set(),
|
* clicon_ptr_get(), clicon_ptr_set(),
|
||||||
* Restconf YANG PATCH according to RFC 8072
|
* Restconf YANG PATCH according to RFC 8072
|
||||||
|
|
|
||||||
|
|
@ -931,16 +931,21 @@ from_client_restart_one(clicon_handle h,
|
||||||
yang_stmt *yspec;
|
yang_stmt *yspec;
|
||||||
int i;
|
int i;
|
||||||
cxobj *xn;
|
cxobj *xn;
|
||||||
|
plugin_context_t *pc = NULL;
|
||||||
|
|
||||||
yspec = clicon_dbspec_yang(h);
|
yspec = clicon_dbspec_yang(h);
|
||||||
if (xmldb_db_reset(h, db) < 0)
|
if (xmldb_db_reset(h, db) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Application may define extra xml in its reset function*/
|
/* Application may define extra xml in its reset function*/
|
||||||
if ((resetfn = clixon_plugin_api_get(cp)->ca_reset) != NULL){
|
if ((resetfn = clixon_plugin_api_get(cp)->ca_reset) != NULL){
|
||||||
|
if ((pc = plugin_context_get()) == NULL)
|
||||||
|
goto done;
|
||||||
if ((retval = resetfn(h, db)) < 0) {
|
if ((retval = resetfn(h, db)) < 0) {
|
||||||
clicon_debug(1, "plugin_start() failed");
|
clicon_debug(1, "plugin_start() failed");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
if (plugin_context_check(pc, clixon_plugin_name_get(cp), __FUNCTION__) < 0)
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
/* 1. Start transaction */
|
/* 1. Start transaction */
|
||||||
if ((td = transaction_new()) == NULL)
|
if ((td = transaction_new()) == NULL)
|
||||||
|
|
@ -1021,6 +1026,8 @@ from_client_restart_one(clicon_handle h,
|
||||||
goto fail;
|
goto fail;
|
||||||
retval = 1;
|
retval = 1;
|
||||||
done:
|
done:
|
||||||
|
if (pc)
|
||||||
|
free(pc);
|
||||||
if (td){
|
if (td){
|
||||||
xmldb_get0_free(h, &td->td_target);
|
xmldb_get0_free(h, &td->td_target);
|
||||||
transaction_free(td);
|
transaction_free(td);
|
||||||
|
|
|
||||||
|
|
@ -284,9 +284,10 @@ get_client_statedata(clicon_handle h,
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
* @param[in] yspec Yang spec
|
* @param[in] yspec Yang spec
|
||||||
* @param[in] xret Result XML tree
|
* @param[in] xret Result XML tree
|
||||||
|
* @param[in] xvec xpath lookup result on xret
|
||||||
|
* @param[in] xlen length of xvec
|
||||||
* @param[in] xpath XPath point to object to get
|
* @param[in] xpath XPath point to object to get
|
||||||
* @param[in] nsc Namespace context of xpath
|
* @param[in] nsc Namespace context of xpath
|
||||||
* @param[out] x1p Pointer to first matching object if any
|
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
*/
|
*/
|
||||||
|
|
@ -294,17 +295,14 @@ static int
|
||||||
filter_xpath_again(clicon_handle h,
|
filter_xpath_again(clicon_handle h,
|
||||||
yang_stmt *yspec,
|
yang_stmt *yspec,
|
||||||
cxobj *xret,
|
cxobj *xret,
|
||||||
|
cxobj **xvec,
|
||||||
|
size_t xlen,
|
||||||
char *xpath,
|
char *xpath,
|
||||||
cvec *nsc,
|
cvec *nsc)
|
||||||
cxobj **x1p)
|
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
cxobj **xvec = NULL;
|
|
||||||
size_t xlen;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (xpath_vec(xret, nsc, "%s", &xvec, &xlen, xpath?xpath:"/") < 0)
|
|
||||||
goto done;
|
|
||||||
/* If vectors are specified then mark the nodes found and
|
/* If vectors are specified then mark the nodes found and
|
||||||
* then filter out everything else,
|
* then filter out everything else,
|
||||||
* otherwise return complete tree.
|
* otherwise return complete tree.
|
||||||
|
|
@ -326,12 +324,8 @@ filter_xpath_again(clicon_handle h,
|
||||||
/* Add default recursive values */
|
/* Add default recursive values */
|
||||||
if (xml_default_recurse(xret, 0) < 0)
|
if (xml_default_recurse(xret, 0) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xlen && x1p)
|
|
||||||
*x1p = xvec[0];
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
if (xvec)
|
|
||||||
free(xvec);
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -339,6 +333,8 @@ filter_xpath_again(clicon_handle h,
|
||||||
*
|
*
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
* @param[in] xret Result XML tree
|
* @param[in] xret Result XML tree
|
||||||
|
* @param[in] xvec xpath lookup result on xret
|
||||||
|
* @param[in] xlen length of xvec
|
||||||
* @param[in] xpath XPath point to object to get
|
* @param[in] xpath XPath point to object to get
|
||||||
* @param[in] nsc Namespace context of xpath
|
* @param[in] nsc Namespace context of xpath
|
||||||
* @param[in] username User name for NACM access
|
* @param[in] username User name for NACM access
|
||||||
|
|
@ -350,6 +346,8 @@ filter_xpath_again(clicon_handle h,
|
||||||
static int
|
static int
|
||||||
get_nacm_and_reply(clicon_handle h,
|
get_nacm_and_reply(clicon_handle h,
|
||||||
cxobj *xret,
|
cxobj *xret,
|
||||||
|
cxobj **xvec,
|
||||||
|
size_t xlen,
|
||||||
char *xpath,
|
char *xpath,
|
||||||
cvec *nsc,
|
cvec *nsc,
|
||||||
char *username,
|
char *username,
|
||||||
|
|
@ -357,15 +355,11 @@ get_nacm_and_reply(clicon_handle h,
|
||||||
cbuf *cbret)
|
cbuf *cbret)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
cxobj **xvec = NULL;
|
|
||||||
size_t xlen;
|
|
||||||
cxobj *xnacm = NULL;
|
cxobj *xnacm = NULL;
|
||||||
|
|
||||||
/* Pre-NACM access step */
|
/* Pre-NACM access step */
|
||||||
xnacm = clicon_nacm_cache(h);
|
xnacm = clicon_nacm_cache(h);
|
||||||
if (xnacm != NULL){ /* Do NACM validation */
|
if (xnacm != NULL){ /* Do NACM validation */
|
||||||
if (xpath_vec(xret, nsc, "%s", &xvec, &xlen, xpath?xpath:"/") < 0)
|
|
||||||
goto done;
|
|
||||||
/* NACM datanode/module read validation */
|
/* NACM datanode/module read validation */
|
||||||
if (nacm_datanode_read(h, xret, xvec, xlen, username, xnacm) < 0)
|
if (nacm_datanode_read(h, xret, xvec, xlen, username, xnacm) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -383,8 +377,6 @@ get_nacm_and_reply(clicon_handle h,
|
||||||
cprintf(cbret, "</rpc-reply>");
|
cprintf(cbret, "</rpc-reply>");
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
if (xvec)
|
|
||||||
free(xvec);
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -454,11 +446,7 @@ get_list_pagination(clicon_handle h,
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
uint32_t offset = 0;
|
uint32_t offset = 0;
|
||||||
uint32_t limit = 0;
|
uint32_t limit = 0;
|
||||||
char *direction = NULL;
|
|
||||||
char *sort = NULL;
|
|
||||||
char *where = NULL;
|
|
||||||
cbuf *cbpath = NULL;
|
cbuf *cbpath = NULL;
|
||||||
cxobj *x;
|
|
||||||
int list_config;
|
int list_config;
|
||||||
yang_stmt *ylist;
|
yang_stmt *ylist;
|
||||||
cxobj *xerr = NULL;
|
cxobj *xerr = NULL;
|
||||||
|
|
@ -468,7 +456,15 @@ get_list_pagination(clicon_handle h,
|
||||||
int ret;
|
int ret;
|
||||||
uint32_t iddb; /* DBs lock, if any */
|
uint32_t iddb; /* DBs lock, if any */
|
||||||
int locked;
|
int locked;
|
||||||
cxobj *x1 = NULL;
|
cbuf *cberr = NULL;
|
||||||
|
cxobj **xvec = NULL;
|
||||||
|
size_t xlen;
|
||||||
|
#ifdef NOTYET
|
||||||
|
cxobj *x;
|
||||||
|
char *direction = NULL;
|
||||||
|
char *sort = NULL;
|
||||||
|
char *where = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Check if list/leaf-list */
|
/* Check if list/leaf-list */
|
||||||
if (yang_path_arg(yspec, xpath, &ylist) < 0)
|
if (yang_path_arg(yspec, xpath, &ylist) < 0)
|
||||||
|
|
@ -504,11 +500,6 @@ get_list_pagination(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
#if 0 /* XXX For now state lists are not implemenetd */
|
|
||||||
if (netconf_operation_not_supported(cbret, "protocol", "List pagination for state lists is not yet implemented") < 0)
|
|
||||||
goto done;
|
|
||||||
goto ok;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
/* offset */
|
/* offset */
|
||||||
if ((ret = element2value(h, xe, "offset", "none", cbret, &offset)) < 0)
|
if ((ret = element2value(h, xe, "offset", "none", cbret, &offset)) < 0)
|
||||||
|
|
@ -516,6 +507,7 @@ get_list_pagination(clicon_handle h,
|
||||||
/* limit */
|
/* limit */
|
||||||
if (ret && (ret = element2value(h, xe, "limit", "unbounded", cbret, &limit)) < 0)
|
if (ret && (ret = element2value(h, xe, "limit", "unbounded", cbret, &limit)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
#ifdef NOTYET
|
||||||
/* direction */
|
/* direction */
|
||||||
if (ret && (x = xml_find_type(xe, NULL, "direction", CX_ELMNT)) != NULL){
|
if (ret && (x = xml_find_type(xe, NULL, "direction", CX_ELMNT)) != NULL){
|
||||||
direction = xml_body(x);
|
direction = xml_body(x);
|
||||||
|
|
@ -535,7 +527,7 @@ get_list_pagination(clicon_handle h,
|
||||||
/* where */
|
/* where */
|
||||||
if (ret && (x = xml_find_type(xe, NULL, "where", CX_ELMNT)) != NULL)
|
if (ret && (x = xml_find_type(xe, NULL, "where", CX_ELMNT)) != NULL)
|
||||||
where = xml_body(x);
|
where = xml_body(x);
|
||||||
|
#endif
|
||||||
/* Read config */
|
/* Read config */
|
||||||
switch (content){
|
switch (content){
|
||||||
case CONTENT_CONFIG: /* config data only */
|
case CONTENT_CONFIG: /* config data only */
|
||||||
|
|
@ -553,8 +545,10 @@ get_list_pagination(clicon_handle h,
|
||||||
cprintf(cbpath, "%s", xpath);
|
cprintf(cbpath, "%s", xpath);
|
||||||
else
|
else
|
||||||
cprintf(cbpath, "/");
|
cprintf(cbpath, "/");
|
||||||
|
#ifdef NOTYET
|
||||||
if (where)
|
if (where)
|
||||||
cprintf(cbpath, "[%s]", where);
|
cprintf(cbpath, "[%s]", where);
|
||||||
|
#endif
|
||||||
if (offset){
|
if (offset){
|
||||||
cprintf(cbpath, "[%u <= position()", offset);
|
cprintf(cbpath, "[%u <= position()", offset);
|
||||||
if (limit)
|
if (limit)
|
||||||
|
|
@ -607,11 +601,40 @@ get_list_pagination(clicon_handle h,
|
||||||
offset, limit,
|
offset, limit,
|
||||||
xret)) < 0)
|
xret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0){
|
||||||
|
if ((cberr = cbuf_new()) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
/* error reason should be in clicon_err_reason */
|
||||||
|
cprintf(cberr, "Internal error, pagination state callback invalid return : %s",
|
||||||
|
clicon_err_reason);
|
||||||
|
if (netconf_operation_failed_xml(&xerr, "application", cbuf_get(cberr)) < 0)
|
||||||
|
goto done;
|
||||||
|
if (clicon_xml2cbuf(cbret, xerr, 0, 0, -1) < 0)
|
||||||
|
goto done;
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* System makes the binding */
|
||||||
|
if ((ret = xml_bind_yang(xret, YB_MODULE, yspec, &xerr)) < 0)
|
||||||
|
goto done;
|
||||||
|
if (ret == 0){
|
||||||
|
if (clicon_debug_get() && xret)
|
||||||
|
clicon_log_xml(LOG_DEBUG, xret, "Yang bind pagination state");
|
||||||
|
if (clixon_netconf_internal_error(xerr,
|
||||||
|
". Internal error, state callback returned invalid XML",
|
||||||
|
NULL) < 0)
|
||||||
|
goto done;
|
||||||
|
if (clicon_xml2cbuf(cbret, xerr, 0, 0, -1) < 0)
|
||||||
|
goto done;
|
||||||
|
goto ok;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (xpath_vec(xret, nsc, "%s", &xvec, &xlen, xpath?xpath:"/") < 0)
|
||||||
|
goto done;
|
||||||
/* Help function to filter out anything that is outside of xpath */
|
/* Help function to filter out anything that is outside of xpath */
|
||||||
if (filter_xpath_again(h, yspec, xret, xpath, nsc, &x1) < 0)
|
if (filter_xpath_again(h, yspec, xret, xvec, xlen, xpath, nsc) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
#ifdef LIST_PAGINATION_REMAINING
|
#ifdef LIST_PAGINATION_REMAINING
|
||||||
/* Add remaining attribute Sec 3.1.5:
|
/* Add remaining attribute Sec 3.1.5:
|
||||||
|
|
@ -639,17 +662,21 @@ get_list_pagination(clicon_handle h,
|
||||||
cbuf_free(cba);
|
cbuf_free(cba);
|
||||||
}
|
}
|
||||||
#endif /* LIST_PAGINATION_REMAINING */
|
#endif /* LIST_PAGINATION_REMAINING */
|
||||||
if (get_nacm_and_reply(h, xret, xpath, nsc, username, depth, cbret) < 0)
|
if (get_nacm_and_reply(h, xret, xvec, xlen, xpath, nsc, username, depth, cbret) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
ok:
|
ok:
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (xvec)
|
||||||
|
free(xvec);
|
||||||
if (cbmsg)
|
if (cbmsg)
|
||||||
cbuf_free(cbmsg);
|
cbuf_free(cbmsg);
|
||||||
if (cbpath)
|
if (cbpath)
|
||||||
cbuf_free(cbpath);
|
cbuf_free(cbpath);
|
||||||
if (xerr)
|
if (xerr)
|
||||||
xml_free(xerr);
|
xml_free(xerr);
|
||||||
|
if (cberr)
|
||||||
|
cbuf_free(cberr);
|
||||||
if (xret)
|
if (xret)
|
||||||
xml_free(xret);
|
xml_free(xret);
|
||||||
return retval;
|
return retval;
|
||||||
|
|
@ -696,6 +723,10 @@ get_common(clicon_handle h,
|
||||||
int list_pagination = 0;
|
int list_pagination = 0;
|
||||||
char *valstr;
|
char *valstr;
|
||||||
cxobj *x;
|
cxobj *x;
|
||||||
|
#if 1
|
||||||
|
cxobj **xvec = NULL;
|
||||||
|
size_t xlen;
|
||||||
|
#endif
|
||||||
|
|
||||||
clicon_debug(1, "%s", __FUNCTION__);
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
username = clicon_username_get(h);
|
username = clicon_username_get(h);
|
||||||
|
|
@ -852,14 +883,18 @@ get_common(clicon_handle h,
|
||||||
if (xml_apply(xret, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset, (void*)XML_FLAG_MARK) < 0)
|
if (xml_apply(xret, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset, (void*)XML_FLAG_MARK) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (filter_xpath_again(h, yspec, xret, xpath, nsc, NULL) < 0)
|
if (xpath_vec(xret, nsc, "%s", &xvec, &xlen, xpath?xpath:"/") < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (get_nacm_and_reply(h, xret, xpath, nsc, username, depth, cbret) < 0)
|
if (filter_xpath_again(h, yspec, xret, xvec, xlen, xpath, nsc) < 0)
|
||||||
|
goto done;
|
||||||
|
if (get_nacm_and_reply(h, xret, xvec, xlen, xpath, nsc, username, depth, cbret) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
ok:
|
ok:
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
|
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
|
||||||
|
if (xvec)
|
||||||
|
free(xvec);
|
||||||
if (xret)
|
if (xret)
|
||||||
xml_free(xret);
|
xml_free(xret);
|
||||||
if (cbreason)
|
if (cbreason)
|
||||||
|
|
|
||||||
|
|
@ -80,17 +80,24 @@ clixon_plugin_reset_one(clixon_plugin_t *cp,
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
plgreset_t *fn; /* callback */
|
plgreset_t *fn; /* callback */
|
||||||
|
plugin_context_t *pc = NULL;
|
||||||
|
|
||||||
if ((fn = clixon_plugin_api_get(cp)->ca_reset) != NULL){
|
if ((fn = clixon_plugin_api_get(cp)->ca_reset) != NULL){
|
||||||
|
if ((pc = plugin_context_get()) == NULL)
|
||||||
|
goto done;
|
||||||
if (fn(h, db) < 0) {
|
if (fn(h, db) < 0) {
|
||||||
if (clicon_errno < 0)
|
if (clicon_errno < 0)
|
||||||
clicon_log(LOG_WARNING, "%s: Internal error: Reset callback in plugin: %s returned -1 but did not make a clicon_err call",
|
clicon_log(LOG_WARNING, "%s: Internal error: Reset callback in plugin: %s returned -1 but did not make a clicon_err call",
|
||||||
__FUNCTION__, clixon_plugin_name_get(cp));
|
__FUNCTION__, clixon_plugin_name_get(cp));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
if (plugin_context_check(pc, clixon_plugin_name_get(cp), __FUNCTION__) < 0)
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (pc)
|
||||||
|
free(pc);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -108,6 +115,7 @@ clixon_plugin_reset_all(clicon_handle h,
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
clixon_plugin_t *cp = NULL;
|
clixon_plugin_t *cp = NULL;
|
||||||
|
|
||||||
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
/* Loop through all plugins, call callbacks in each */
|
/* Loop through all plugins, call callbacks in each */
|
||||||
while ((cp = clixon_plugin_each(h, cp)) != NULL) {
|
while ((cp = clixon_plugin_each(h, cp)) != NULL) {
|
||||||
if (clixon_plugin_reset_one(cp, h, db) < 0)
|
if (clixon_plugin_reset_one(cp, h, db) < 0)
|
||||||
|
|
@ -130,8 +138,12 @@ clixon_plugin_pre_daemon_one(clixon_plugin_t *cp,
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
plgdaemon_t *fn; /* Daemonize plugin callback function */
|
plgdaemon_t *fn; /* Daemonize plugin callback function */
|
||||||
|
plugin_context_t *pc = NULL;
|
||||||
|
|
||||||
if ((fn = clixon_plugin_api_get(cp)->ca_pre_daemon) != NULL){
|
if ((fn = clixon_plugin_api_get(cp)->ca_pre_daemon) != NULL){
|
||||||
|
if ((pc = plugin_context_get()) == NULL)
|
||||||
|
goto done;
|
||||||
|
|
||||||
if (fn(h) < 0) {
|
if (fn(h) < 0) {
|
||||||
if (clicon_errno < 0)
|
if (clicon_errno < 0)
|
||||||
clicon_log(LOG_WARNING, "%s: Internal error: Pre-daemon callback in plugin:\
|
clicon_log(LOG_WARNING, "%s: Internal error: Pre-daemon callback in plugin:\
|
||||||
|
|
@ -139,9 +151,13 @@ clixon_plugin_pre_daemon_one(clixon_plugin_t *cp,
|
||||||
__FUNCTION__, clixon_plugin_name_get(cp));
|
__FUNCTION__, clixon_plugin_name_get(cp));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
if (plugin_context_check(pc, clixon_plugin_name_get(cp), __FUNCTION__) < 0)
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (pc)
|
||||||
|
free(pc);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -160,6 +176,7 @@ clixon_plugin_pre_daemon_all(clicon_handle h)
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
clixon_plugin_t *cp = NULL;
|
clixon_plugin_t *cp = NULL;
|
||||||
|
|
||||||
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
/* Loop through all plugins, call callbacks in each */
|
/* Loop through all plugins, call callbacks in each */
|
||||||
while ((cp = clixon_plugin_each(h, cp)) != NULL) {
|
while ((cp = clixon_plugin_each(h, cp)) != NULL) {
|
||||||
if (clixon_plugin_pre_daemon_one(cp, h) < 0)
|
if (clixon_plugin_pre_daemon_one(cp, h) < 0)
|
||||||
|
|
@ -182,17 +199,24 @@ clixon_plugin_daemon_one(clixon_plugin_t *cp,
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
plgdaemon_t *fn; /* Daemonize plugin callback function */
|
plgdaemon_t *fn; /* Daemonize plugin callback function */
|
||||||
|
plugin_context_t *pc = NULL;
|
||||||
|
|
||||||
if ((fn = clixon_plugin_api_get(cp)->ca_daemon) != NULL){
|
if ((fn = clixon_plugin_api_get(cp)->ca_daemon) != NULL){
|
||||||
|
if ((pc = plugin_context_get()) == NULL)
|
||||||
|
goto done;
|
||||||
if (fn(h) < 0) {
|
if (fn(h) < 0) {
|
||||||
if (clicon_errno < 0)
|
if (clicon_errno < 0)
|
||||||
clicon_log(LOG_WARNING, "%s: Internal error: Daemon callback in plugin: %s returned -1 but did not make a clicon_err call",
|
clicon_log(LOG_WARNING, "%s: Internal error: Daemon callback in plugin: %s returned -1 but did not make a clicon_err call",
|
||||||
__FUNCTION__, clixon_plugin_name_get(cp));
|
__FUNCTION__, clixon_plugin_name_get(cp));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
if (plugin_context_check(pc, clixon_plugin_name_get(cp), __FUNCTION__) < 0)
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (pc)
|
||||||
|
free(pc);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -213,6 +237,7 @@ clixon_plugin_daemon_all(clicon_handle h)
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
clixon_plugin_t *cp = NULL;
|
clixon_plugin_t *cp = NULL;
|
||||||
|
|
||||||
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
/* Loop through all plugins, call callbacks in each */
|
/* Loop through all plugins, call callbacks in each */
|
||||||
while ((cp = clixon_plugin_each(h, cp)) != NULL) {
|
while ((cp = clixon_plugin_each(h, cp)) != NULL) {
|
||||||
if (clixon_plugin_daemon_one(cp, h) < 0)
|
if (clixon_plugin_daemon_one(cp, h) < 0)
|
||||||
|
|
@ -258,22 +283,28 @@ clixon_plugin_statedata_one(clixon_plugin_t *cp,
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
plgstatedata_t *fn; /* Plugin statedata fn */
|
plgstatedata_t *fn; /* Plugin statedata fn */
|
||||||
cxobj *x = NULL;
|
cxobj *x = NULL;
|
||||||
|
plugin_context_t *pc = NULL;
|
||||||
|
|
||||||
clicon_debug(1, "%s %s", __FUNCTION__, clixon_plugin_name_get(cp));
|
|
||||||
if ((fn = clixon_plugin_api_get(cp)->ca_statedata) != NULL){
|
if ((fn = clixon_plugin_api_get(cp)->ca_statedata) != NULL){
|
||||||
if ((x = xml_new(DATASTORE_TOP_SYMBOL, NULL, CX_ELMNT)) == NULL)
|
if ((x = xml_new(DATASTORE_TOP_SYMBOL, NULL, CX_ELMNT)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
|
if ((pc = plugin_context_get()) == NULL)
|
||||||
|
goto done;
|
||||||
if (fn(h, nsc, xpath, x) < 0){
|
if (fn(h, nsc, xpath, x) < 0){
|
||||||
if (clicon_errno < 0)
|
if (clicon_errno < 0)
|
||||||
clicon_log(LOG_WARNING, "%s: Internal error: State callback in plugin: %s returned -1 but did not make a clicon_err call",
|
clicon_log(LOG_WARNING, "%s: Internal error: State callback in plugin: %s returned -1 but did not make a clicon_err call",
|
||||||
__FUNCTION__, clixon_plugin_name_get(cp));
|
__FUNCTION__, clixon_plugin_name_get(cp));
|
||||||
goto fail; /* Dont quit here on user callbacks */
|
goto fail; /* Dont quit here on user callbacks */
|
||||||
}
|
}
|
||||||
|
if (plugin_context_check(pc, clixon_plugin_name_get(cp), __FUNCTION__) < 0)
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
if (xp && x)
|
if (xp && x)
|
||||||
*xp = x;
|
*xp = x;
|
||||||
retval = 1;
|
retval = 1;
|
||||||
done:
|
done:
|
||||||
|
if (pc)
|
||||||
|
free(pc);
|
||||||
return retval;
|
return retval;
|
||||||
fail:
|
fail:
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -406,14 +437,20 @@ clixon_plugin_lockdb_one(clixon_plugin_t *cp,
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
plglockdb_t *fn; /* Plugin statedata fn */
|
plglockdb_t *fn; /* Plugin statedata fn */
|
||||||
|
plugin_context_t *pc = NULL;
|
||||||
|
|
||||||
clicon_debug(1, "%s %s", __FUNCTION__, clixon_plugin_name_get(cp));
|
|
||||||
if ((fn = clixon_plugin_api_get(cp)->ca_lockdb) != NULL){
|
if ((fn = clixon_plugin_api_get(cp)->ca_lockdb) != NULL){
|
||||||
|
if ((pc = plugin_context_get()) == NULL)
|
||||||
|
goto done;
|
||||||
if (fn(h, db, lock, id) < 0)
|
if (fn(h, db, lock, id) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
if (plugin_context_check(pc, clixon_plugin_name_get(cp), __FUNCTION__) < 0)
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (pc)
|
||||||
|
free(pc);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -576,17 +613,24 @@ plugin_transaction_begin_one(clixon_plugin_t *cp,
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
trans_cb_t *fn;
|
trans_cb_t *fn;
|
||||||
|
plugin_context_t *pc = NULL;
|
||||||
|
|
||||||
if ((fn = clixon_plugin_api_get(cp)->ca_trans_begin) != NULL){
|
if ((fn = clixon_plugin_api_get(cp)->ca_trans_begin) != NULL){
|
||||||
|
if ((pc = plugin_context_get()) == NULL)
|
||||||
|
goto done;
|
||||||
if (fn(h, (transaction_data)td) < 0){
|
if (fn(h, (transaction_data)td) < 0){
|
||||||
if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */
|
if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */
|
||||||
clicon_log(LOG_NOTICE, "%s: Plugin '%s' callback does not make clicon_err call on error",
|
clicon_log(LOG_NOTICE, "%s: Plugin '%s' callback does not make clicon_err call on error",
|
||||||
__FUNCTION__, clixon_plugin_name_get(cp));
|
__FUNCTION__, clixon_plugin_name_get(cp));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
if (plugin_context_check(pc, clixon_plugin_name_get(cp), __FUNCTION__) < 0)
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (pc)
|
||||||
|
free(pc);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -605,6 +649,7 @@ plugin_transaction_begin_all(clicon_handle h,
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
clixon_plugin_t *cp = NULL;
|
clixon_plugin_t *cp = NULL;
|
||||||
|
|
||||||
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
while ((cp = clixon_plugin_each(h, cp)) != NULL) {
|
while ((cp = clixon_plugin_each(h, cp)) != NULL) {
|
||||||
if (plugin_transaction_begin_one(cp, h, td) < 0)
|
if (plugin_transaction_begin_one(cp, h, td) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -628,17 +673,24 @@ plugin_transaction_validate_one(clixon_plugin_t *cp,
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
trans_cb_t *fn;
|
trans_cb_t *fn;
|
||||||
|
plugin_context_t *pc = NULL;
|
||||||
|
|
||||||
if ((fn = clixon_plugin_api_get(cp)->ca_trans_validate) != NULL){
|
if ((fn = clixon_plugin_api_get(cp)->ca_trans_validate) != NULL){
|
||||||
|
if ((pc = plugin_context_get()) == NULL)
|
||||||
|
goto done;
|
||||||
if (fn(h, (transaction_data)td) < 0){
|
if (fn(h, (transaction_data)td) < 0){
|
||||||
if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */
|
if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */
|
||||||
clicon_log(LOG_NOTICE, "%s: Plugin '%s' callback does not make clicon_err call on error",
|
clicon_log(LOG_NOTICE, "%s: Plugin '%s' callback does not make clicon_err call on error",
|
||||||
__FUNCTION__, clixon_plugin_name_get(cp));
|
__FUNCTION__, clixon_plugin_name_get(cp));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
if (plugin_context_check(pc, clixon_plugin_name_get(cp), __FUNCTION__) < 0)
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (pc)
|
||||||
|
free(pc);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -679,17 +731,24 @@ plugin_transaction_complete_one(clixon_plugin_t *cp,
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
trans_cb_t *fn;
|
trans_cb_t *fn;
|
||||||
|
plugin_context_t *pc = NULL;
|
||||||
|
|
||||||
if ((fn = clixon_plugin_api_get(cp)->ca_trans_complete) != NULL){
|
if ((fn = clixon_plugin_api_get(cp)->ca_trans_complete) != NULL){
|
||||||
|
if ((pc = plugin_context_get()) == NULL)
|
||||||
|
goto done;
|
||||||
if (fn(h, (transaction_data)td) < 0){
|
if (fn(h, (transaction_data)td) < 0){
|
||||||
if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */
|
if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */
|
||||||
clicon_log(LOG_NOTICE, "%s: Plugin '%s' callback does not make clicon_err call on error",
|
clicon_log(LOG_NOTICE, "%s: Plugin '%s' callback does not make clicon_err call on error",
|
||||||
__FUNCTION__, clixon_plugin_name_get(cp));
|
__FUNCTION__, clixon_plugin_name_get(cp));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
if (plugin_context_check(pc, clixon_plugin_name_get(cp), __FUNCTION__) < 0)
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (pc)
|
||||||
|
free(pc);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -762,17 +821,24 @@ plugin_transaction_commit_one(clixon_plugin_t *cp,
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
trans_cb_t *fn;
|
trans_cb_t *fn;
|
||||||
|
plugin_context_t *pc = NULL;
|
||||||
|
|
||||||
if ((fn = clixon_plugin_api_get(cp)->ca_trans_commit) != NULL){
|
if ((fn = clixon_plugin_api_get(cp)->ca_trans_commit) != NULL){
|
||||||
|
if ((pc = plugin_context_get()) == NULL)
|
||||||
|
goto done;
|
||||||
if (fn(h, (transaction_data)td) < 0){
|
if (fn(h, (transaction_data)td) < 0){
|
||||||
if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */
|
if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */
|
||||||
clicon_log(LOG_NOTICE, "%s: Plugin '%s' callback does not make clicon_err call on error",
|
clicon_log(LOG_NOTICE, "%s: Plugin '%s' callback does not make clicon_err call on error",
|
||||||
__FUNCTION__, clixon_plugin_name_get(cp));
|
__FUNCTION__, clixon_plugin_name_get(cp));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
if (plugin_context_check(pc, clixon_plugin_name_get(cp), __FUNCTION__) < 0)
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (pc)
|
||||||
|
free(pc);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -821,17 +887,24 @@ plugin_transaction_commit_done_one(clixon_plugin_t *cp,
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
trans_cb_t *fn;
|
trans_cb_t *fn;
|
||||||
|
plugin_context_t *pc = NULL;
|
||||||
|
|
||||||
if ((fn = clixon_plugin_api_get(cp)->ca_trans_commit_done) != NULL){
|
if ((fn = clixon_plugin_api_get(cp)->ca_trans_commit_done) != NULL){
|
||||||
|
if ((pc = plugin_context_get()) == NULL)
|
||||||
|
goto done;
|
||||||
if (fn(h, (transaction_data)td) < 0){
|
if (fn(h, (transaction_data)td) < 0){
|
||||||
if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */
|
if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */
|
||||||
clicon_log(LOG_NOTICE, "%s: Plugin '%s' callback does not make clicon_err call on error",
|
clicon_log(LOG_NOTICE, "%s: Plugin '%s' callback does not make clicon_err call on error",
|
||||||
__FUNCTION__, clixon_plugin_name_get(cp));
|
__FUNCTION__, clixon_plugin_name_get(cp));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
if (plugin_context_check(pc, clixon_plugin_name_get(cp), __FUNCTION__) < 0)
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (pc)
|
||||||
|
free(pc);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -872,17 +945,24 @@ plugin_transaction_end_one(clixon_plugin_t *cp,
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
trans_cb_t *fn;
|
trans_cb_t *fn;
|
||||||
|
plugin_context_t *pc = NULL;
|
||||||
|
|
||||||
if ((fn = clixon_plugin_api_get(cp)->ca_trans_end) != NULL){
|
if ((fn = clixon_plugin_api_get(cp)->ca_trans_end) != NULL){
|
||||||
|
if ((pc = plugin_context_get()) == NULL)
|
||||||
|
goto done;
|
||||||
if (fn(h, (transaction_data)td) < 0){
|
if (fn(h, (transaction_data)td) < 0){
|
||||||
if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */
|
if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */
|
||||||
clicon_log(LOG_NOTICE, "%s: Plugin '%s' callback does not make clicon_err call on error",
|
clicon_log(LOG_NOTICE, "%s: Plugin '%s' callback does not make clicon_err call on error",
|
||||||
__FUNCTION__, clixon_plugin_name_get(cp));
|
__FUNCTION__, clixon_plugin_name_get(cp));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
if (plugin_context_check(pc, clixon_plugin_name_get(cp), __FUNCTION__) < 0)
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (pc)
|
||||||
|
free(pc);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -899,6 +979,7 @@ plugin_transaction_end_all(clicon_handle h,
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
clixon_plugin_t *cp = NULL;
|
clixon_plugin_t *cp = NULL;
|
||||||
|
|
||||||
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
while ((cp = clixon_plugin_each(h, cp)) != NULL) {
|
while ((cp = clixon_plugin_each(h, cp)) != NULL) {
|
||||||
if (plugin_transaction_end_one(cp, h, td) < 0)
|
if (plugin_transaction_end_one(cp, h, td) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -915,17 +996,24 @@ plugin_transaction_abort_one(clixon_plugin_t *cp,
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
trans_cb_t *fn;
|
trans_cb_t *fn;
|
||||||
|
plugin_context_t *pc = NULL;
|
||||||
|
|
||||||
if ((fn = clixon_plugin_api_get(cp)->ca_trans_abort) != NULL){
|
if ((fn = clixon_plugin_api_get(cp)->ca_trans_abort) != NULL){
|
||||||
|
if ((pc = plugin_context_get()) == NULL)
|
||||||
|
goto done;
|
||||||
if (fn(h, (transaction_data)td) < 0){
|
if (fn(h, (transaction_data)td) < 0){
|
||||||
if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */
|
if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */
|
||||||
clicon_log(LOG_NOTICE, "%s: Plugin '%s' callback does not make clicon_err call on error",
|
clicon_log(LOG_NOTICE, "%s: Plugin '%s' callback does not make clicon_err call on error",
|
||||||
__FUNCTION__, clixon_plugin_name_get(cp));
|
__FUNCTION__, clixon_plugin_name_get(cp));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
if (plugin_context_check(pc, clixon_plugin_name_get(cp), __FUNCTION__) < 0)
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (pc)
|
||||||
|
free(pc);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -942,6 +1030,7 @@ plugin_transaction_abort_all(clicon_handle h,
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
clixon_plugin_t *cp = NULL;
|
clixon_plugin_t *cp = NULL;
|
||||||
|
|
||||||
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
while ((cp = clixon_plugin_each(h, cp)) != NULL) {
|
while ((cp = clixon_plugin_each(h, cp)) != NULL) {
|
||||||
if (plugin_transaction_abort_one(cp, h, td) < 0)
|
if (plugin_transaction_abort_one(cp, h, td) < 0)
|
||||||
; /* dont abort on error */
|
; /* dont abort on error */
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <regex.h>
|
#include <regex.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <regex.h>
|
#include <regex.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -171,7 +171,7 @@ cli_xml2file(cxobj *xn,
|
||||||
if (xn == NULL)
|
if (xn == NULL)
|
||||||
goto ok;
|
goto ok;
|
||||||
/* Look for autocli-op defined in clixon-lib.yang */
|
/* Look for autocli-op defined in clixon-lib.yang */
|
||||||
if (yang_extension_value(xml_spec(xn), "autocli-op", CLIXON_LIB_NS, &opext) < 0) {
|
if (yang_extension_value(xml_spec(xn), "autocli-op", CLIXON_LIB_NS, NULL, &opext) < 0) {
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
if ((opext != NULL) && ((strcmp(opext, "hide-database") == 0) || (strcmp(opext, "hide-database-auto-completion") == 0))){
|
if ((opext != NULL) && ((strcmp(opext, "hide-database") == 0) || (strcmp(opext, "hide-database-auto-completion") == 0))){
|
||||||
|
|
@ -274,7 +274,7 @@ cli_xml2txt(cxobj *xn,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
/* Look for autocli-op defined in clixon-lib.yang */
|
/* Look for autocli-op defined in clixon-lib.yang */
|
||||||
if (yang_extension_value(xml_spec(xn), "autocli-op", CLIXON_LIB_NS, &opext) < 0) {
|
if (yang_extension_value(xml_spec(xn), "autocli-op", CLIXON_LIB_NS, NULL, &opext) < 0) {
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
if ((opext != NULL) && ((strcmp(opext, "hide-database") == 0) || (strcmp(opext, "hide-database-auto-completion") == 0))){
|
if ((opext != NULL) && ((strcmp(opext, "hide-database") == 0) || (strcmp(opext, "hide-database-auto-completion") == 0))){
|
||||||
|
|
@ -342,7 +342,7 @@ cli_xml2cli(cxobj *xn,
|
||||||
if ((ys = xml_spec(xn)) == NULL)
|
if ((ys = xml_spec(xn)) == NULL)
|
||||||
goto ok;
|
goto ok;
|
||||||
/* Look for autocli-op defined in clixon-lib.yang */
|
/* Look for autocli-op defined in clixon-lib.yang */
|
||||||
if (yang_extension_value(xml_spec(xn), "autocli-op", CLIXON_LIB_NS, &opext) < 0) {
|
if (yang_extension_value(xml_spec(xn), "autocli-op", CLIXON_LIB_NS, NULL, &opext) < 0) {
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
if ((opext != NULL) && ((strcmp(opext, "hide-database") == 0) || (strcmp(opext, "hide-database-auto-completion") == 0))){
|
if ((opext != NULL) && ((strcmp(opext, "hide-database") == 0) || (strcmp(opext, "hide-database-auto-completion") == 0))){
|
||||||
|
|
|
||||||
|
|
@ -562,9 +562,10 @@ cli_start_shell(clicon_handle h,
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char bcmd[128];
|
char bcmd[128];
|
||||||
cg_var *cv1 = cvec_i(vars, 1);
|
cg_var *cv1 = cvec_i(vars, 1);
|
||||||
|
sigset_t oldsigset;
|
||||||
|
struct sigaction oldsigaction[32] = {0,};
|
||||||
|
|
||||||
cmd = (cvec_len(vars)>1 ? cv_string_get(cv1) : NULL);
|
cmd = (cvec_len(vars)>1 ? cv_string_get(cv1) : NULL);
|
||||||
|
|
||||||
if ((pw = getpwuid(getuid())) == NULL){
|
if ((pw = getpwuid(getuid())) == NULL){
|
||||||
clicon_err(OE_UNIX, errno, "getpwuid");
|
clicon_err(OE_UNIX, errno, "getpwuid");
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -575,6 +576,9 @@ cli_start_shell(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
endpwent();
|
endpwent();
|
||||||
|
|
||||||
|
if (clixon_signal_save(&oldsigset, oldsigaction) < 0)
|
||||||
|
goto done;
|
||||||
cli_signal_flush(h);
|
cli_signal_flush(h);
|
||||||
cli_signal_unblock(h);
|
cli_signal_unblock(h);
|
||||||
if (cmd){
|
if (cmd){
|
||||||
|
|
@ -598,6 +602,8 @@ cli_start_shell(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (clixon_signal_restore(&oldsigset, oldsigaction) < 0)
|
||||||
|
goto done;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
return retval;
|
return retval;
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,7 @@ You can see which CLISPEC it generates via clixon_cli -D 2:
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
|
||||||
/* cligen */
|
/* cligen */
|
||||||
|
|
@ -120,7 +121,7 @@ cli_expand_var_generate(clicon_handle h,
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *api_path_fmt = NULL, *opext = NULL;
|
char *api_path_fmt = NULL, *opext = NULL;
|
||||||
|
|
||||||
if (yang_extension_value(ys, "autocli-op", CLIXON_LIB_NS, &opext) < 0)
|
if (yang_extension_value(ys, "autocli-op", CLIXON_LIB_NS, NULL, &opext) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (opext && strcmp(opext, "hide-database") == 0) {
|
if (opext && strcmp(opext, "hide-database") == 0) {
|
||||||
retval = 1;
|
retval = 1;
|
||||||
|
|
@ -761,7 +762,7 @@ yang2cli_leaf(clicon_handle h,
|
||||||
}
|
}
|
||||||
cprintf(cb, "%*s", level*3, "");
|
cprintf(cb, "%*s", level*3, "");
|
||||||
/* Look for autocli-op defined in clixon-lib.yang */
|
/* Look for autocli-op defined in clixon-lib.yang */
|
||||||
if (yang_extension_value(ys, "autocli-op", CLIXON_LIB_NS, &opext) < 0)
|
if (yang_extension_value(ys, "autocli-op", CLIXON_LIB_NS, NULL, &opext) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (gt == GT_VARS || gt == GT_ALL || gt == GT_HIDE || gt == GT_OC_COMPRESS){
|
if (gt == GT_VARS || gt == GT_ALL || gt == GT_HIDE || gt == GT_OC_COMPRESS){
|
||||||
cprintf(cb, "%s", yang_argument_get(ys));
|
cprintf(cb, "%s", yang_argument_get(ys));
|
||||||
|
|
@ -867,7 +868,7 @@ yang2cli_container(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
/* Look for autocli-op defined in clixon-lib.yang */
|
/* Look for autocli-op defined in clixon-lib.yang */
|
||||||
if (yang_extension_value(ys, "autocli-op", CLIXON_LIB_NS, &opext) < 0)
|
if (yang_extension_value(ys, "autocli-op", CLIXON_LIB_NS, NULL, &opext) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (opext != NULL && strcmp(opext, "hide") == 0){
|
if (opext != NULL && strcmp(opext, "hide") == 0){
|
||||||
cprintf(cb, ",hide");
|
cprintf(cb, ",hide");
|
||||||
|
|
@ -933,7 +934,7 @@ yang2cli_list(clicon_handle h,
|
||||||
yang2cli_helptext(cb, helptext);
|
yang2cli_helptext(cb, helptext);
|
||||||
}
|
}
|
||||||
/* Look for autocli-op defined in clixon-lib.yang */
|
/* Look for autocli-op defined in clixon-lib.yang */
|
||||||
if (yang_extension_value(ys, "autocli-op", CLIXON_LIB_NS, &opext) < 0)
|
if (yang_extension_value(ys, "autocli-op", CLIXON_LIB_NS, NULL, &opext) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (opext != NULL && strcmp(opext, "hide") == 0){
|
if (opext != NULL && strcmp(opext, "hide") == 0){
|
||||||
cprintf(cb, ",hide");
|
cprintf(cb, ",hide");
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
|
@ -69,7 +70,6 @@
|
||||||
#include "cli_handle.h"
|
#include "cli_handle.h"
|
||||||
#include "cli_generate.h"
|
#include "cli_generate.h"
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Constants
|
* Constants
|
||||||
*/
|
*/
|
||||||
|
|
@ -522,6 +522,53 @@ cli_handler_err(FILE *f)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Variant of eval for context checking
|
||||||
|
* @see cligen_eval
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cligen_clixon_eval(cligen_handle h,
|
||||||
|
cg_obj *co,
|
||||||
|
cvec *cvv)
|
||||||
|
{
|
||||||
|
struct cg_callback *cc;
|
||||||
|
int retval = 0;
|
||||||
|
cvec *argv;
|
||||||
|
plugin_context_t *pc = NULL;
|
||||||
|
|
||||||
|
if (h)
|
||||||
|
cligen_co_match_set(h, co);
|
||||||
|
for (cc = co->co_callbacks; cc; cc=cc->cc_next){
|
||||||
|
/* Vector cvec argument to callback */
|
||||||
|
if (cc->cc_fn_vec){
|
||||||
|
argv = cc->cc_cvec ? cvec_dup(cc->cc_cvec) : NULL;
|
||||||
|
cligen_fn_str_set(h, cc->cc_fn_str);
|
||||||
|
if ((pc = plugin_context_get()) == NULL)
|
||||||
|
break;
|
||||||
|
if ((retval = (*cc->cc_fn_vec)(
|
||||||
|
cligen_userhandle(h)?cligen_userhandle(h):h,
|
||||||
|
cvv,
|
||||||
|
argv)) < 0){
|
||||||
|
if (argv != NULL)
|
||||||
|
cvec_free(argv);
|
||||||
|
cligen_fn_str_set(h, NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (plugin_context_check(pc, "CLIgen", cc->cc_fn_str) < 0)
|
||||||
|
break;
|
||||||
|
if (pc){
|
||||||
|
free(pc);
|
||||||
|
pc = NULL;
|
||||||
|
}
|
||||||
|
if (argv != NULL)
|
||||||
|
cvec_free(argv);
|
||||||
|
cligen_fn_str_set(h, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pc)
|
||||||
|
free(pc);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Evaluate a matched command
|
/*! Evaluate a matched command
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
* @param[in] cmd The command string
|
* @param[in] cmd The command string
|
||||||
|
|
@ -541,7 +588,8 @@ clicon_eval(clicon_handle h,
|
||||||
cli_output_reset();
|
cli_output_reset();
|
||||||
if (!cligen_exiting(cli_cligen(h))) {
|
if (!cligen_exiting(cli_cligen(h))) {
|
||||||
clicon_err_reset();
|
clicon_err_reset();
|
||||||
if ((retval = cligen_eval(cli_cligen(h), match_obj, cvv)) < 0) {
|
|
||||||
|
if ((retval = cligen_clixon_eval(cli_cligen(h), match_obj, cvv)) < 0) {
|
||||||
#if 0 /* This is removed since we get two error messages on failure.
|
#if 0 /* This is removed since we get two error messages on failure.
|
||||||
But maybe only sometime?
|
But maybe only sometime?
|
||||||
Both a real log when clicon_err is called, and the here again.
|
Both a real log when clicon_err is called, and the here again.
|
||||||
|
|
|
||||||
|
|
@ -919,6 +919,7 @@ cli_pagination(clicon_handle h,
|
||||||
uint32_t limit = 0;
|
uint32_t limit = 0;
|
||||||
cxobj **xvec = NULL;
|
cxobj **xvec = NULL;
|
||||||
size_t xlen;
|
size_t xlen;
|
||||||
|
int locked = 0;
|
||||||
|
|
||||||
if (cvec_len(argv) != 5){
|
if (cvec_len(argv) != 5){
|
||||||
clicon_err(OE_PLUGIN, 0, "Expected usage: <xpath> <prefix> <namespace> <format> <limit>");
|
clicon_err(OE_PLUGIN, 0, "Expected usage: <xpath> <prefix> <namespace> <format> <limit>");
|
||||||
|
|
@ -950,6 +951,7 @@ cli_pagination(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
if (clicon_rpc_lock(h, "running") < 0)
|
if (clicon_rpc_lock(h, "running") < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
locked++;
|
||||||
for (i = 0;; i++){
|
for (i = 0;; i++){
|
||||||
if (clicon_rpc_get_pageable_list(h, "running", xpath, nsc,
|
if (clicon_rpc_get_pageable_list(h, "running", xpath, nsc,
|
||||||
CONTENT_ALL,
|
CONTENT_ALL,
|
||||||
|
|
@ -1000,10 +1002,10 @@ cli_pagination(clicon_handle h,
|
||||||
xvec = NULL;
|
xvec = NULL;
|
||||||
}
|
}
|
||||||
} /* for i */
|
} /* for i */
|
||||||
if (clicon_rpc_unlock(h, "running") < 0)
|
|
||||||
goto done;
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (locked)
|
||||||
|
clicon_rpc_unlock(h, "running");
|
||||||
if (xvec)
|
if (xvec)
|
||||||
free(xvec);
|
free(xvec);
|
||||||
if (xret)
|
if (xret)
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
|
||||||
|
|
@ -514,7 +514,10 @@ example_statefile(clicon_handle h,
|
||||||
xml_flag_set(x1, XML_FLAG_MARK);
|
xml_flag_set(x1, XML_FLAG_MARK);
|
||||||
xml_apply_ancestor(x1, (xml_applyfn_t*)xml_flag_set, (void*)XML_FLAG_CHANGE);
|
xml_apply_ancestor(x1, (xml_applyfn_t*)xml_flag_set, (void*)XML_FLAG_CHANGE);
|
||||||
}
|
}
|
||||||
if (xml_copy_marked(xt, xstate) < 0) /* Copy the marked elements */
|
/* Copy the marked elements:
|
||||||
|
* note is yang-aware for copying of keys which means XML must be bound
|
||||||
|
*/
|
||||||
|
if (xml_copy_marked(xt, xstate) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Unmark original tree */
|
/* Unmark original tree */
|
||||||
if (xml_apply(xt, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset, (void*)(XML_FLAG_MARK|XML_FLAG_CHANGE)) < 0)
|
if (xml_apply(xt, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset, (void*)(XML_FLAG_MARK|XML_FLAG_CHANGE)) < 0)
|
||||||
|
|
@ -614,6 +617,9 @@ example_pagination(void *h0,
|
||||||
xml_flag_set(x1, XML_FLAG_MARK);
|
xml_flag_set(x1, XML_FLAG_MARK);
|
||||||
xml_apply_ancestor(x1, (xml_applyfn_t*)xml_flag_set, (void*)XML_FLAG_CHANGE);
|
xml_apply_ancestor(x1, (xml_applyfn_t*)xml_flag_set, (void*)XML_FLAG_CHANGE);
|
||||||
}
|
}
|
||||||
|
/* Copy the marked elements:
|
||||||
|
* note is yang-aware for copying of keys which means XML must be bound
|
||||||
|
*/
|
||||||
if (xml_copy_marked(xt, xstate) < 0) /* Copy the marked elements */
|
if (xml_copy_marked(xt, xstate) < 0) /* Copy the marked elements */
|
||||||
goto done;
|
goto done;
|
||||||
/* Unmark original tree */
|
/* Unmark original tree */
|
||||||
|
|
@ -1160,6 +1166,7 @@ example_daemon(clicon_handle h)
|
||||||
int ret;
|
int ret;
|
||||||
FILE *fp = NULL;
|
FILE *fp = NULL;
|
||||||
yang_stmt *yspec;
|
yang_stmt *yspec;
|
||||||
|
cxobj *xerr = NULL;
|
||||||
|
|
||||||
/* Read state file (or should this be in init/start?) */
|
/* Read state file (or should this be in init/start?) */
|
||||||
if (_state && _state_file && _state_file_cached){
|
if (_state && _state_file && _state_file_cached){
|
||||||
|
|
@ -1168,8 +1175,14 @@ example_daemon(clicon_handle h)
|
||||||
clicon_err(OE_UNIX, errno, "open(%s)", _state_file);
|
clicon_err(OE_UNIX, errno, "open(%s)", _state_file);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((ret = clixon_xml_parse_file(fp, YB_MODULE, yspec, &_state_xml_cache, NULL)) < 1)
|
/* Need to be yang bound for eg xml_copy_marked() in example_pagination
|
||||||
|
*/
|
||||||
|
if ((ret = clixon_xml_parse_file(fp, YB_MODULE, yspec, &_state_xml_cache, &xerr)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
if (ret == 0){
|
||||||
|
xml_print(stderr, xerr);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,43 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2021 Rubicon Communications LLC (Netgate)
|
*
|
||||||
|
***** BEGIN LICENSE BLOCK *****
|
||||||
|
|
||||||
|
Copyright (C) 2021 Rubicon Communications, LLC(Netgate)
|
||||||
|
|
||||||
|
This file is part of CLIXON.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
Alternatively, the contents of this file may be used under the terms of
|
||||||
|
the GNU General Public License Version 3 or later (the "GPL"),
|
||||||
|
in which case the provisions of the GPL are applicable instead
|
||||||
|
of those above. If you wish to allow use of your version of this file only
|
||||||
|
under the terms of the GPL, and not to allow others to
|
||||||
|
use your version of this file under the terms of Apache License version 2,
|
||||||
|
indicate your decision by deleting the provisions above and replace them with
|
||||||
|
the notice and other provisions required by the GPL. If you do not delete
|
||||||
|
the provisions above, a recipient may use your version of this file under
|
||||||
|
the terms of any one of the Apache License version 2 or the GPL.
|
||||||
|
|
||||||
|
***** END LICENSE BLOCK *****
|
||||||
|
|
||||||
* @see https://github.com/dcornejo/dispatcher
|
* @see https://github.com/dcornejo/dispatcher
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef DISPATCH_DISPATCHER_H
|
#ifndef _CLIXON_DISPATCH_DISPATCHER_H
|
||||||
#define DISPATCH_DISPATCHER_H
|
#define _CLIXON_DISPATCH_DISPATCHER_H
|
||||||
|
|
||||||
/*! prototype for a function to handle a path
|
/*! Prototype for a function to handle a path
|
||||||
* minimally needs the path it's working on, but probably
|
* minimally needs the path it's working on, but probably
|
||||||
* we want to hand down cached data somehow
|
* we want to hand down cached data somehow
|
||||||
* @param[in] h Generic handler
|
* @param[in] h Generic handler
|
||||||
|
|
@ -74,5 +105,6 @@ struct _dispatcher_entry {
|
||||||
int dispatcher_register_handler(dispatcher_entry_t **root, dispatcher_definition *x);
|
int dispatcher_register_handler(dispatcher_entry_t **root, dispatcher_definition *x);
|
||||||
int dispatcher_call_handlers(dispatcher_entry_t *root, void *handle, char *path, void *user_args);
|
int dispatcher_call_handlers(dispatcher_entry_t *root, void *handle, char *path, void *user_args);
|
||||||
int dispatcher_free(dispatcher_entry_t *root);
|
int dispatcher_free(dispatcher_entry_t *root);
|
||||||
|
int dispatcher_print(FILE *f, int level, dispatcher_entry_t *root);
|
||||||
|
|
||||||
#endif /* DISPATCH_DISPATCHER_H */
|
#endif /* _CLIXON_DISPATCH_DISPATCHER_H */
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,6 @@
|
||||||
* Types
|
* Types
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/*! Registered RPC callback function
|
/*! Registered RPC callback function
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
* @param[in] xn Request: <rpc><xn></rpc>
|
* @param[in] xn Request: <rpc><xn></rpc>
|
||||||
|
|
@ -201,7 +200,7 @@ typedef int (plgreset_t)(clicon_handle h, const char *db);
|
||||||
* A complete valid XML tree is created by the plugin and sent back via xtop, which is merged
|
* A complete valid XML tree is created by the plugin and sent back via xtop, which is merged
|
||||||
* into a complete state tree by the system.
|
* into a complete state tree by the system.
|
||||||
* The plugin should ensure that xpath is matched (using namspace context nsc)
|
* The plugin should ensure that xpath is matched (using namspace context nsc)
|
||||||
* This callback may be replaced with a "dispatcher" type API in the future where the
|
* XXX: This callback may be replaced with a "dispatcher" type API in the future where the
|
||||||
* XPath binding is stricter, similar to the pagination API.
|
* XPath binding is stricter, similar to the pagination API.
|
||||||
*
|
*
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
|
|
@ -338,6 +337,7 @@ struct clixon_plugin_api{
|
||||||
#define ca_trans_abort u.cau_backend.cb_trans_abort
|
#define ca_trans_abort u.cau_backend.cb_trans_abort
|
||||||
#define ca_datastore_upgrade u.cau_backend.cb_datastore_upgrade
|
#define ca_datastore_upgrade u.cau_backend.cb_datastore_upgrade
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Macros
|
* Macros
|
||||||
*/
|
*/
|
||||||
|
|
@ -349,6 +349,10 @@ typedef struct clixon_plugin_api clixon_plugin_api;
|
||||||
* The internal struct is defined in clixon_plugin.c */
|
* The internal struct is defined in clixon_plugin.c */
|
||||||
typedef struct clixon_plugin clixon_plugin_t;
|
typedef struct clixon_plugin clixon_plugin_t;
|
||||||
|
|
||||||
|
/*! Structure for checking status before and after a plugin call
|
||||||
|
* The internal struct is defined in clixon_plugin.c */
|
||||||
|
typedef struct plugin_context plugin_context_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prototypes
|
* Prototypes
|
||||||
*/
|
*/
|
||||||
|
|
@ -361,7 +365,6 @@ typedef struct clixon_plugin clixon_plugin_t;
|
||||||
*/
|
*/
|
||||||
clixon_plugin_api *clixon_plugin_init(clicon_handle h);
|
clixon_plugin_api *clixon_plugin_init(clicon_handle h);
|
||||||
|
|
||||||
|
|
||||||
clixon_plugin_api *clixon_plugin_api_get(clixon_plugin_t *cp);
|
clixon_plugin_api *clixon_plugin_api_get(clixon_plugin_t *cp);
|
||||||
char *clixon_plugin_name_get(clixon_plugin_t *cp);
|
char *clixon_plugin_name_get(clixon_plugin_t *cp);
|
||||||
plghndl_t clixon_plugin_handle_get(clixon_plugin_t *cp);
|
plghndl_t clixon_plugin_handle_get(clixon_plugin_t *cp);
|
||||||
|
|
@ -376,6 +379,9 @@ int clixon_plugins_load(clicon_handle h, const char *function, const char *dir,
|
||||||
|
|
||||||
int clixon_pseudo_plugin(clicon_handle h, const char *name, clixon_plugin_t **cpp);
|
int clixon_pseudo_plugin(clicon_handle h, const char *name, clixon_plugin_t **cpp);
|
||||||
|
|
||||||
|
plugin_context_t * plugin_context_get(void);
|
||||||
|
int plugin_context_check(plugin_context_t *pc, const char *name, const char *fn);
|
||||||
|
|
||||||
int clixon_plugin_start_one(clixon_plugin_t *cp, clicon_handle h);
|
int clixon_plugin_start_one(clixon_plugin_t *cp, clicon_handle h);
|
||||||
int clixon_plugin_start_all(clicon_handle h);
|
int clixon_plugin_start_all(clicon_handle h);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,8 @@ typedef void (*sigfn_t)(int);
|
||||||
* Prototypes
|
* Prototypes
|
||||||
*/
|
*/
|
||||||
int set_signal(int signo, void (*handler)(int), void (**oldhandler)(int));
|
int set_signal(int signo, void (*handler)(int), void (**oldhandler)(int));
|
||||||
|
int clixon_signal_save(sigset_t *sigset, struct sigaction sigaction_vec[32]);
|
||||||
|
int clixon_signal_restore(sigset_t *sigset, struct sigaction sigaction_vec[32]);
|
||||||
void clicon_signal_block(int);
|
void clicon_signal_block(int);
|
||||||
void clicon_signal_unblock(int);
|
void clicon_signal_unblock(int);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -270,6 +270,6 @@ int yang_type_cache_get(yang_stmt *ytype, yang_stmt **resolved, int *opti
|
||||||
int yang_type_cache_set(yang_stmt *ys, yang_stmt *resolved, int options, cvec *cvv,
|
int yang_type_cache_set(yang_stmt *ys, yang_stmt *resolved, int options, cvec *cvv,
|
||||||
cvec *patterns, uint8_t fraction);
|
cvec *patterns, uint8_t fraction);
|
||||||
yang_stmt *yang_anydata_add(yang_stmt *yp, char *name);
|
yang_stmt *yang_anydata_add(yang_stmt *yp, char *name);
|
||||||
int yang_extension_value(yang_stmt *ys, char *name, char *ns, char **value);
|
int yang_extension_value(yang_stmt *ys, char *name, char *ns, int *exist, char **value);
|
||||||
|
|
||||||
#endif /* _CLIXON_YANG_H_ */
|
#endif /* _CLIXON_YANG_H_ */
|
||||||
|
|
|
||||||
|
|
@ -227,6 +227,11 @@ clicon_data_cvec_set(clicon_handle h,
|
||||||
const char *name,
|
const char *name,
|
||||||
cvec *cvv)
|
cvec *cvv)
|
||||||
{
|
{
|
||||||
|
cvec *cvv0 = NULL;
|
||||||
|
|
||||||
|
clicon_ptr_get(h, name, (void**)&cvv0);
|
||||||
|
if (cvv0)
|
||||||
|
cvec_free(cvv0);
|
||||||
return clicon_ptr_set(h, name, cvv);
|
return clicon_ptr_set(h, name, cvv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -238,6 +243,11 @@ int
|
||||||
clicon_data_cvec_del(clicon_handle h,
|
clicon_data_cvec_del(clicon_handle h,
|
||||||
const char *name)
|
const char *name)
|
||||||
{
|
{
|
||||||
|
cvec *cvv = NULL;
|
||||||
|
|
||||||
|
clicon_ptr_get(h, name, (void**)&cvv);
|
||||||
|
if (cvv)
|
||||||
|
cvec_free(cvv);
|
||||||
return clicon_ptr_del(h, name);
|
return clicon_ptr_del(h, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -377,9 +387,13 @@ clicon_nacm_ext(clicon_handle h)
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
clicon_nacm_ext_set(clicon_handle h,
|
clicon_nacm_ext_set(clicon_handle h,
|
||||||
cxobj *xn)
|
cxobj *x)
|
||||||
{
|
{
|
||||||
return clicon_ptr_set(h, "nacm_xml", xn);
|
cxobj *x0 = NULL;
|
||||||
|
|
||||||
|
if ((x0 = clicon_nacm_ext(h)) != NULL)
|
||||||
|
xml_free(x0);
|
||||||
|
return clicon_ptr_set(h, "nacm_xml", x);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Get NACM (rfc 8341) XML parse tree cache
|
/*! Get NACM (rfc 8341) XML parse tree cache
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,36 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2021 Rubicon Communications LLC (Netgate)
|
*
|
||||||
|
***** BEGIN LICENSE BLOCK *****
|
||||||
|
|
||||||
|
Copyright (C) 2021 Rubicon Communications, LLC(Netgate)
|
||||||
|
|
||||||
|
This file is part of CLIXON.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
Alternatively, the contents of this file may be used under the terms of
|
||||||
|
the GNU General Public License Version 3 or later (the "GPL"),
|
||||||
|
in which case the provisions of the GPL are applicable instead
|
||||||
|
of those above. If you wish to allow use of your version of this file only
|
||||||
|
under the terms of the GPL, and not to allow others to
|
||||||
|
use your version of this file under the terms of Apache License version 2,
|
||||||
|
indicate your decision by deleting the provisions above and replace them with
|
||||||
|
the notice and other provisions required by the GPL. If you do not delete
|
||||||
|
the provisions above, a recipient may use your version of this file under
|
||||||
|
the terms of any one of the Apache License version 2 or the GPL.
|
||||||
|
|
||||||
|
***** END LICENSE BLOCK *****
|
||||||
|
|
||||||
* @see https://github.com/dcornejo/dispatcher
|
* @see https://github.com/dcornejo/dispatcher
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
@ -37,10 +68,6 @@
|
||||||
* [b=]
|
* [b=]
|
||||||
* [b]
|
* [b]
|
||||||
*
|
*
|
||||||
* NOTE 1: there is not a mechanism to free the created structures since
|
|
||||||
* it is intended that this tree is created only at startup. if use case
|
|
||||||
* changes, this function is trivial.
|
|
||||||
*
|
|
||||||
* NOTE 2: there is no attempt to optimize list searching here, sorry. I
|
* NOTE 2: there is no attempt to optimize list searching here, sorry. I
|
||||||
* do not think that the known use cases will get big enough to make the
|
* do not think that the known use cases will get big enough to make the
|
||||||
* tree get too large. I do not recommend that you encode every possible
|
* tree get too large. I do not recommend that you encode every possible
|
||||||
|
|
@ -285,11 +312,8 @@ get_entry(dispatcher_entry_t *root,
|
||||||
|
|
||||||
/* some elements may have keys defined, strip them off */
|
/* some elements may have keys defined, strip them off */
|
||||||
for (int i = 0; i < split_path_len; i++) {
|
for (int i = 0; i < split_path_len; i++) {
|
||||||
char *kptr = strchr(split_path_list[i], '=');
|
char *kptr = split_path_list[i];
|
||||||
|
strsep(&kptr, "=[]");
|
||||||
if ((kptr != NULL) && (*kptr == '=')) {
|
|
||||||
*(kptr + 1) = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* search down the tree */
|
/* search down the tree */
|
||||||
|
|
@ -411,7 +435,7 @@ dispatcher_register_handler(dispatcher_entry_t **root,
|
||||||
*
|
*
|
||||||
* @param[in] handle
|
* @param[in] handle
|
||||||
* @param[in] root
|
* @param[in] root
|
||||||
* @param[in] path
|
* @param[in] path Note must be on the form: /a/b (no keys)
|
||||||
* @retval 1 OK
|
* @retval 1 OK
|
||||||
* @retval 0 Invalid
|
* @retval 0 Invalid
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
|
|
@ -423,8 +447,12 @@ dispatcher_call_handlers(dispatcher_entry_t *root,
|
||||||
void *user_args)
|
void *user_args)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
dispatcher_entry_t *best = get_entry(root, path);
|
dispatcher_entry_t *best;
|
||||||
|
|
||||||
|
if ((best = get_entry(root, path)) == NULL){
|
||||||
|
errno = ENOENT;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if (best->children != NULL) {
|
if (best->children != NULL) {
|
||||||
call_handler_helper(best->children, handle, path, user_args);
|
call_handler_helper(best->children, handle, path, user_args);
|
||||||
}
|
}
|
||||||
|
|
@ -450,3 +478,24 @@ dispatcher_free(dispatcher_entry_t *root)
|
||||||
free(root);
|
free(root);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Pretty-print dispatcher tree
|
||||||
|
*/
|
||||||
|
#define INDENT 3
|
||||||
|
int
|
||||||
|
dispatcher_print(FILE *f,
|
||||||
|
int level,
|
||||||
|
dispatcher_entry_t *de)
|
||||||
|
{
|
||||||
|
fprintf(f, "%*s%s", level*INDENT, "", de->node_name);
|
||||||
|
if (de->handler)
|
||||||
|
fprintf(f, " %p", de->handler);
|
||||||
|
if (de->arg)
|
||||||
|
fprintf(f, " (%p)", de->arg);
|
||||||
|
fprintf(f, "\n");
|
||||||
|
if (de->children)
|
||||||
|
dispatcher_print(f, level+1, de->children);
|
||||||
|
if (de->peer)
|
||||||
|
dispatcher_print(f, level, de->peer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
|
||||||
|
|
@ -43,10 +43,12 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <termios.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
|
||||||
|
|
@ -69,6 +71,15 @@
|
||||||
/*
|
/*
|
||||||
* Private types
|
* Private types
|
||||||
*/
|
*/
|
||||||
|
/*! Structure for checking status before and after a plugin call
|
||||||
|
* Currently signal settings: blocked and handlers, and termios
|
||||||
|
* @see plugin_context_check
|
||||||
|
*/
|
||||||
|
struct plugin_context {
|
||||||
|
sigset_t pc_sigset; /* See sigprocmask(2) */
|
||||||
|
struct sigaction pc_sigaction_vec[32]; /* See sigaction(2) */
|
||||||
|
struct termios pc_termios; /* See termios(3) */
|
||||||
|
};
|
||||||
|
|
||||||
/* Internal plugin structure with dlopen() handle and plugin_api
|
/* Internal plugin structure with dlopen() handle and plugin_api
|
||||||
* This is an internal type, not exposed in the API
|
* This is an internal type, not exposed in the API
|
||||||
|
|
@ -330,6 +341,7 @@ plugin_load_one(clicon_handle h,
|
||||||
clixon_plugin_t *cp = NULL;
|
clixon_plugin_t *cp = NULL;
|
||||||
char *name;
|
char *name;
|
||||||
char *p;
|
char *p;
|
||||||
|
plugin_context_t *pc = NULL;
|
||||||
|
|
||||||
clicon_debug(1, "%s file:%s function:%s", __FUNCTION__, file, function);
|
clicon_debug(1, "%s file:%s function:%s", __FUNCTION__, file, function);
|
||||||
dlerror(); /* Clear any existing error */
|
dlerror(); /* Clear any existing error */
|
||||||
|
|
@ -348,6 +360,9 @@ plugin_load_one(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
clicon_err_reset();
|
clicon_err_reset();
|
||||||
|
if ((pc = plugin_context_get()) < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
if ((api = initfn(h)) == NULL) {
|
if ((api = initfn(h)) == NULL) {
|
||||||
if (!clicon_errno){ /* if clicon_err() is not called then log and continue */
|
if (!clicon_errno){ /* if clicon_err() is not called then log and continue */
|
||||||
clicon_log(LOG_DEBUG, "Warning: failed to initiate %s", strrchr(file,'/')?strchr(file, '/'):file);
|
clicon_log(LOG_DEBUG, "Warning: failed to initiate %s", strrchr(file,'/')?strchr(file, '/'):file);
|
||||||
|
|
@ -359,6 +374,9 @@ plugin_load_one(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (plugin_context_check(pc, file, __FUNCTION__) < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
/* Note: sizeof clixon_plugin_api which is largest of clixon_plugin_api:s */
|
/* Note: sizeof clixon_plugin_api which is largest of clixon_plugin_api:s */
|
||||||
if ((cp = (clixon_plugin_t *)malloc(sizeof(struct clixon_plugin))) == NULL){
|
if ((cp = (clixon_plugin_t *)malloc(sizeof(struct clixon_plugin))) == NULL){
|
||||||
clicon_err(OE_UNIX, errno, "malloc");
|
clicon_err(OE_UNIX, errno, "malloc");
|
||||||
|
|
@ -382,6 +400,8 @@ plugin_load_one(clicon_handle h,
|
||||||
retval = 1;
|
retval = 1;
|
||||||
done:
|
done:
|
||||||
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
|
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
|
||||||
|
if (pc)
|
||||||
|
free(pc);
|
||||||
if (retval != 1 && handle)
|
if (retval != 1 && handle)
|
||||||
dlclose(handle);
|
dlclose(handle);
|
||||||
if (cp)
|
if (cp)
|
||||||
|
|
@ -483,6 +503,157 @@ done:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Get system context, eg signal procmask (for blocking) and sigactions
|
||||||
|
* Call this before a plugin
|
||||||
|
* @retval pc Plugin context structure, use free() to deallocate
|
||||||
|
* @retval NULL Error
|
||||||
|
* @see plugin_context_check
|
||||||
|
* */
|
||||||
|
plugin_context_t *
|
||||||
|
plugin_context_get(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct plugin_context *pc = NULL;
|
||||||
|
|
||||||
|
if ((pc = malloc(sizeof(*pc))) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "malloc");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
memset(pc, 0, sizeof(*pc));
|
||||||
|
|
||||||
|
if (sigprocmask(0, NULL, &pc->pc_sigset) < 0){
|
||||||
|
clicon_err(OE_UNIX, errno, "sigprocmask");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
for (i=1; i<32; i++){
|
||||||
|
if (sigaction(i, NULL, &pc->pc_sigaction_vec[i]) < 0){
|
||||||
|
clicon_err(OE_UNIX, errno, "sigaction");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
/* Mask SA_RESTORER: Not intended for application use.
|
||||||
|
* Note that it may not be included in user space so may be hardcoded below
|
||||||
|
*/
|
||||||
|
#ifdef SA_RESTORER
|
||||||
|
pc->pc_sigaction_vec[i].sa_flags &= ~SA_RESTORER;
|
||||||
|
#else
|
||||||
|
pc->pc_sigaction_vec[i].sa_flags &= ~0x04000000;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (isatty(0) && tcgetattr(0, &pc->pc_termios) < 0){
|
||||||
|
clicon_err(OE_UNIX, errno, "tcgetattr %d", errno);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
return pc;
|
||||||
|
done:
|
||||||
|
if (pc)
|
||||||
|
free(pc);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Given an existing, old plugin context, check if anything has changed
|
||||||
|
*
|
||||||
|
* Make a new check and compare with the old (procided as in-parameter).
|
||||||
|
* Log if there is a difference at loglevel WARNING.
|
||||||
|
* You can modify the code to also fail with assert if you want early fail.
|
||||||
|
*
|
||||||
|
* @param[in,out] oldpc Old plugin context
|
||||||
|
* @param[in] name Name of plugin for logging. Can be other name, context dependent
|
||||||
|
* @param[in] fn Typically name of callback, or caller function
|
||||||
|
* @retval -1 Error
|
||||||
|
* @retval 0 Fail, log on syslog using LOG_WARNING
|
||||||
|
* @retval 1 OK
|
||||||
|
* @note name and fn are context dependent, since the env of callback calls are very different
|
||||||
|
* @see plugin_context_get
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
plugin_context_check(plugin_context_t *oldpc0,
|
||||||
|
const char *name,
|
||||||
|
const char *fn)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
int failed = 0;
|
||||||
|
int i;
|
||||||
|
struct plugin_context *oldpc = oldpc0;
|
||||||
|
struct plugin_context *newpc = NULL;
|
||||||
|
|
||||||
|
if ((newpc = plugin_context_get()) == NULL)
|
||||||
|
goto done;
|
||||||
|
if (oldpc->pc_termios.c_iflag != newpc->pc_termios.c_iflag){
|
||||||
|
clicon_log(LOG_WARNING, "%s Plugin context %s %s: Changed termios input modes from 0x%x to 0x%x", __FUNCTION__,
|
||||||
|
name, fn,
|
||||||
|
oldpc->pc_termios.c_iflag,
|
||||||
|
newpc->pc_termios.c_iflag);
|
||||||
|
failed++;
|
||||||
|
}
|
||||||
|
if (oldpc->pc_termios.c_oflag != newpc->pc_termios.c_oflag){
|
||||||
|
clicon_log(LOG_WARNING, "%s Plugin context %s %s: Changed termios output modes from 0x%x to 0x%x", __FUNCTION__,
|
||||||
|
name, fn,
|
||||||
|
oldpc->pc_termios.c_oflag,
|
||||||
|
newpc->pc_termios.c_oflag);
|
||||||
|
failed++;
|
||||||
|
}
|
||||||
|
if (oldpc->pc_termios.c_cflag != newpc->pc_termios.c_cflag){
|
||||||
|
clicon_log(LOG_WARNING, "%s Plugin context %s %s: Changed termios control modes from 0x%x to 0x%x", __FUNCTION__,
|
||||||
|
name, fn,
|
||||||
|
oldpc->pc_termios.c_cflag,
|
||||||
|
newpc->pc_termios.c_cflag);
|
||||||
|
failed++;
|
||||||
|
}
|
||||||
|
if (oldpc->pc_termios.c_lflag != newpc->pc_termios.c_lflag){
|
||||||
|
clicon_log(LOG_WARNING, "%s Plugin context %s %s: Changed termios local modes from 0x%x to 0x%x", __FUNCTION__,
|
||||||
|
name, fn,
|
||||||
|
oldpc->pc_termios.c_lflag,
|
||||||
|
newpc->pc_termios.c_lflag);
|
||||||
|
failed++;
|
||||||
|
}
|
||||||
|
/* XXX pc_termios.cc_t c_cc[NCCS] not checked */
|
||||||
|
#if 0
|
||||||
|
/* In case you want early detection and crash. But otherwise it is recommended that
|
||||||
|
* the caller looks for retval == 0 */
|
||||||
|
assert(failed == 0);
|
||||||
|
#endif
|
||||||
|
for (i=1; i<32; i++){
|
||||||
|
if (sigismember(&oldpc->pc_sigset, i) != sigismember(&newpc->pc_sigset, i)){
|
||||||
|
clicon_log(LOG_WARNING, "%s Plugin context %s %s: Changed blocking of signal %s(%d) from %d to %d", __FUNCTION__,
|
||||||
|
name, fn, strsignal(i), i,
|
||||||
|
sigismember(&oldpc->pc_sigset, i),
|
||||||
|
sigismember(&newpc->pc_sigset, i)
|
||||||
|
);
|
||||||
|
failed++;
|
||||||
|
}
|
||||||
|
if (oldpc->pc_sigaction_vec[i].sa_flags != newpc->pc_sigaction_vec[i].sa_flags){
|
||||||
|
clicon_log(LOG_WARNING, "%s Plugin context %s %s: Changed flags of signal %s(%d) from 0x%x to 0x%x", __FUNCTION__,
|
||||||
|
name, fn, strsignal(i), i,
|
||||||
|
oldpc->pc_sigaction_vec[i].sa_flags,
|
||||||
|
newpc->pc_sigaction_vec[i].sa_flags);;
|
||||||
|
failed++;
|
||||||
|
}
|
||||||
|
if (oldpc->pc_sigaction_vec[i].sa_sigaction != newpc->pc_sigaction_vec[i].sa_sigaction){
|
||||||
|
clicon_log(LOG_WARNING, "%s Plugin context %s %s: Changed action of signal %s(%d) from %p to %p", __FUNCTION__,
|
||||||
|
name, fn, strsignal(i), i,
|
||||||
|
oldpc->pc_sigaction_vec[i].sa_sigaction,
|
||||||
|
newpc->pc_sigaction_vec[i].sa_sigaction);
|
||||||
|
failed++;
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
/* In case you want early detection and crash. But otherwise it is recommended that
|
||||||
|
* the caller looks for retval == 0 */
|
||||||
|
assert(failed == 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (failed)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
retval = 1; /* OK */
|
||||||
|
done:
|
||||||
|
if (newpc)
|
||||||
|
free(newpc);
|
||||||
|
return retval;
|
||||||
|
fail:
|
||||||
|
retval = 0;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Call single plugin start callback
|
/*! Call single plugin start callback
|
||||||
* @param[in] cp Plugin handle
|
* @param[in] cp Plugin handle
|
||||||
* @param[in] h Clixon handle
|
* @param[in] h Clixon handle
|
||||||
|
|
@ -495,17 +666,24 @@ clixon_plugin_start_one(clixon_plugin_t *cp,
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
plgstart_t *fn; /* Plugin start */
|
plgstart_t *fn; /* Plugin start */
|
||||||
|
plugin_context_t *pc = NULL;
|
||||||
|
|
||||||
if ((fn = cp->cp_api.ca_start) != NULL){
|
if ((fn = cp->cp_api.ca_start) != NULL){
|
||||||
|
if ((pc = plugin_context_get()) == NULL)
|
||||||
|
goto done;
|
||||||
if (fn(h) < 0) {
|
if (fn(h) < 0) {
|
||||||
if (clicon_errno < 0)
|
if (clicon_errno < 0)
|
||||||
clicon_log(LOG_WARNING, "%s: Internal error: Start callback in plugin: %s returned -1 but did not make a clicon_err call",
|
clicon_log(LOG_WARNING, "%s: Internal error: Start callback in plugin: %s returned -1 but did not make a clicon_err call",
|
||||||
__FUNCTION__, cp->cp_name);
|
__FUNCTION__, cp->cp_name);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
if (plugin_context_check(pc, cp->cp_name, __FUNCTION__) < 0)
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (pc)
|
||||||
|
free(pc);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -543,14 +721,19 @@ clixon_plugin_exit_one(clixon_plugin_t *cp,
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *error;
|
char *error;
|
||||||
plgexit_t *fn;
|
plgexit_t *fn;
|
||||||
|
plugin_context_t *pc = NULL;
|
||||||
|
|
||||||
if ((fn = cp->cp_api.ca_exit) != NULL){
|
if ((fn = cp->cp_api.ca_exit) != NULL){
|
||||||
|
if ((pc = plugin_context_get()) == NULL)
|
||||||
|
goto done;
|
||||||
if (fn(h) < 0) {
|
if (fn(h) < 0) {
|
||||||
if (clicon_errno < 0)
|
if (clicon_errno < 0)
|
||||||
clicon_log(LOG_WARNING, "%s: Internal error: Exit callback in plugin: %s returned -1 but did not make a clicon_err call",
|
clicon_log(LOG_WARNING, "%s: Internal error: Exit callback in plugin: %s returned -1 but did not make a clicon_err call",
|
||||||
__FUNCTION__, cp->cp_name);
|
__FUNCTION__, cp->cp_name);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
if (plugin_context_check(pc, cp->cp_name, __FUNCTION__) < 0)
|
||||||
|
goto done;
|
||||||
if (dlclose(cp->cp_handle) != 0) {
|
if (dlclose(cp->cp_handle) != 0) {
|
||||||
error = (char*)dlerror();
|
error = (char*)dlerror();
|
||||||
clicon_err(OE_PLUGIN, errno, "dlclose: %s", error ? error : "Unknown error");
|
clicon_err(OE_PLUGIN, errno, "dlclose: %s", error ? error : "Unknown error");
|
||||||
|
|
@ -558,6 +741,8 @@ clixon_plugin_exit_one(clixon_plugin_t *cp,
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (pc)
|
||||||
|
free(pc);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -608,19 +793,26 @@ clixon_plugin_auth_one(clixon_plugin_t *cp,
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
plgauth_t *fn; /* Plugin auth */
|
plgauth_t *fn; /* Plugin auth */
|
||||||
|
plugin_context_t *pc = NULL;
|
||||||
|
|
||||||
clicon_debug(1, "%s", __FUNCTION__);
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
if ((fn = cp->cp_api.ca_auth) != NULL){
|
if ((fn = cp->cp_api.ca_auth) != NULL){
|
||||||
|
if ((pc = plugin_context_get()) == NULL)
|
||||||
|
goto done;
|
||||||
if ((retval = fn(h, req, auth_type, authp)) < 0) {
|
if ((retval = fn(h, req, auth_type, authp)) < 0) {
|
||||||
if (clicon_errno < 0)
|
if (clicon_errno < 0)
|
||||||
clicon_log(LOG_WARNING, "%s: Internal error: Auth callback in plugin: %s returned -1 but did not make a clicon_err call",
|
clicon_log(LOG_WARNING, "%s: Internal error: Auth callback in plugin: %s returned -1 but did not make a clicon_err call",
|
||||||
__FUNCTION__, cp->cp_name);
|
__FUNCTION__, cp->cp_name);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
if (plugin_context_check(pc, cp->cp_name, __FUNCTION__) < 0)
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
retval = 0; /* Ignored / no callback */
|
retval = 0; /* Ignored / no callback */
|
||||||
done:
|
done:
|
||||||
|
if (pc)
|
||||||
|
free(pc);
|
||||||
clicon_debug(1, "%s retval:%d auth:%s", __FUNCTION__, retval, *authp);
|
clicon_debug(1, "%s retval:%d auth:%s", __FUNCTION__, retval, *authp);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
@ -686,17 +878,24 @@ clixon_plugin_extension_one(clixon_plugin_t *cp,
|
||||||
{
|
{
|
||||||
int retval = 1;
|
int retval = 1;
|
||||||
plgextension_t *fn; /* Plugin extension fn */
|
plgextension_t *fn; /* Plugin extension fn */
|
||||||
|
plugin_context_t *pc = NULL;
|
||||||
|
|
||||||
if ((fn = cp->cp_api.ca_extension) != NULL){
|
if ((fn = cp->cp_api.ca_extension) != NULL){
|
||||||
|
if ((pc = plugin_context_get()) == NULL)
|
||||||
|
goto done;
|
||||||
if (fn(h, yext, ys) < 0) {
|
if (fn(h, yext, ys) < 0) {
|
||||||
if (clicon_errno < 0)
|
if (clicon_errno < 0)
|
||||||
clicon_log(LOG_WARNING, "%s: Internal error: Extension callback in plugin: %s returned -1 but did not make a clicon_err call",
|
clicon_log(LOG_WARNING, "%s: Internal error: Extension callback in plugin: %s returned -1 but did not make a clicon_err call",
|
||||||
__FUNCTION__, cp->cp_name);
|
__FUNCTION__, cp->cp_name);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
if (plugin_context_check(pc, cp->cp_name, __FUNCTION__) < 0)
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (pc)
|
||||||
|
free(pc);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -750,17 +949,24 @@ clixon_plugin_datastore_upgrade_one(clixon_plugin_t *cp,
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
datastore_upgrade_t *fn;
|
datastore_upgrade_t *fn;
|
||||||
|
plugin_context_t *pc = NULL;
|
||||||
|
|
||||||
if ((fn = cp->cp_api.ca_datastore_upgrade) != NULL){
|
if ((fn = cp->cp_api.ca_datastore_upgrade) != NULL){
|
||||||
|
if ((pc = plugin_context_get()) == NULL)
|
||||||
|
goto done;
|
||||||
if (fn(h, db, xt, msd) < 0) {
|
if (fn(h, db, xt, msd) < 0) {
|
||||||
if (clicon_errno < 0)
|
if (clicon_errno < 0)
|
||||||
clicon_log(LOG_WARNING, "%s: Internal error: Datastore upgrade callback in plugin: %s returned -1 but did not make a clicon_err call",
|
clicon_log(LOG_WARNING, "%s: Internal error: Datastore upgrade callback in plugin: %s returned -1 but did not make a clicon_err call",
|
||||||
__FUNCTION__, cp->cp_name);
|
__FUNCTION__, cp->cp_name);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
if (plugin_context_check(pc, cp->cp_name, __FUNCTION__) < 0)
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (pc)
|
||||||
|
free(pc);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -912,6 +1118,7 @@ rpc_callback_call(clicon_handle h,
|
||||||
char *ns;
|
char *ns;
|
||||||
int nr = 0; /* How many callbacks */
|
int nr = 0; /* How many callbacks */
|
||||||
plugin_module_struct *ms = plugin_module_struct_get(h);
|
plugin_module_struct *ms = plugin_module_struct_get(h);
|
||||||
|
plugin_context_t *pc = NULL;
|
||||||
|
|
||||||
if (ms == NULL){
|
if (ms == NULL){
|
||||||
clicon_err(OE_PLUGIN, EINVAL, "plugin module not initialized");
|
clicon_err(OE_PLUGIN, EINVAL, "plugin module not initialized");
|
||||||
|
|
@ -925,17 +1132,27 @@ rpc_callback_call(clicon_handle h,
|
||||||
if (strcmp(rc->rc_name, name) == 0 &&
|
if (strcmp(rc->rc_name, name) == 0 &&
|
||||||
ns && rc->rc_namespace &&
|
ns && rc->rc_namespace &&
|
||||||
strcmp(rc->rc_namespace, ns) == 0){
|
strcmp(rc->rc_namespace, ns) == 0){
|
||||||
|
if ((pc = plugin_context_get()) == NULL)
|
||||||
|
goto done;
|
||||||
if (rc->rc_callback(h, xe, cbret, arg, rc->rc_arg) < 0){
|
if (rc->rc_callback(h, xe, cbret, arg, rc->rc_arg) < 0){
|
||||||
clicon_debug(1, "%s Error in: %s", __FUNCTION__, rc->rc_name);
|
clicon_debug(1, "%s Error in: %s", __FUNCTION__, rc->rc_name);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
nr++;
|
nr++;
|
||||||
|
if (plugin_context_check(pc, rc->rc_name, __FUNCTION__) < 0)
|
||||||
|
goto done;
|
||||||
|
if (pc){
|
||||||
|
free(pc);
|
||||||
|
pc = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
rc = NEXTQ(rpc_callback_t *, rc);
|
rc = NEXTQ(rpc_callback_t *, rc);
|
||||||
} while (rc != ms->ms_rpc_callbacks);
|
} while (rc != ms->ms_rpc_callbacks);
|
||||||
retval = nr; /* 0: none found, >0 nr of handlers called */
|
retval = nr; /* 0: none found, >0 nr of handlers called */
|
||||||
done:
|
done:
|
||||||
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
|
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
|
||||||
|
if (pc)
|
||||||
|
free(pc);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -121,6 +121,58 @@ clicon_signal_unblock(int sig)
|
||||||
sigprocmask(SIG_UNBLOCK, &set, NULL);
|
sigprocmask(SIG_UNBLOCK, &set, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Save complete signal context
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
clixon_signal_save(sigset_t *sigset,
|
||||||
|
struct sigaction sigaction_vec[32])
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (sigprocmask(0, NULL, sigset) < 0){
|
||||||
|
clicon_err(OE_UNIX, errno, "sigprocmask");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
for (i=1; i<32; i++){
|
||||||
|
if (sigaction(i, NULL, &sigaction_vec[i]) < 0){
|
||||||
|
clicon_err(OE_UNIX, errno, "sigaction");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Restore complete signal context
|
||||||
|
*
|
||||||
|
* Note: sigaction may not restore SIGKILL or SIGSTOP, which cannot be caught or ignored.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
clixon_signal_restore(sigset_t *sigset,
|
||||||
|
struct sigaction sigaction_vec[32])
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (sigprocmask(0, sigset, NULL) < 0){
|
||||||
|
clicon_err(OE_UNIX, errno, "sigprocmask");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
for (i=1; i<32; i++){
|
||||||
|
if (i == SIGKILL || i == SIGSTOP)
|
||||||
|
continue;
|
||||||
|
if (sigaction(i, &sigaction_vec[i], NULL) < 0){
|
||||||
|
clicon_err(OE_UNIX, errno, "sigaction");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Read pidfile and return pid using file descriptor
|
/*! Read pidfile and return pid using file descriptor
|
||||||
*
|
*
|
||||||
* @param[in] pidfile Name of pidfile
|
* @param[in] pidfile Name of pidfile
|
||||||
|
|
|
||||||
|
|
@ -3553,15 +3553,20 @@ yang_anydata_add(yang_stmt *yp,
|
||||||
return ys;
|
return ys;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Find extension argument and return extension argument value
|
/*! Find extension argument and return if extension exists and its argument value
|
||||||
|
*
|
||||||
* @param[in] ys Yang statement
|
* @param[in] ys Yang statement
|
||||||
* @param[in] name Name of the extension
|
* @param[in] name Name of the extension
|
||||||
* @param[in] ns The namespace
|
* @param[in] ns The namespace
|
||||||
|
* @param[out] exist The extension exists.
|
||||||
* @param[out] value clispec operator (hide/none) - direct pointer into yang, dont free
|
* @param[out] value clispec operator (hide/none) - direct pointer into yang, dont free
|
||||||
|
* @retval 0 OK: Look in exist and value for return value
|
||||||
|
* @retval -1 Error
|
||||||
* This is for extensions with an argument
|
* This is for extensions with an argument
|
||||||
* @code
|
* @code
|
||||||
* char *value = NULL;
|
* char *value = NULL;
|
||||||
* if (yang_extension_value(ys, "mymode", "urn:example:lib", &value) < 0)
|
* int exist = 0;
|
||||||
|
* if (yang_extension_value(ys, "mymode", "urn:example:lib", &exist, &value) < 0)
|
||||||
* err;
|
* err;
|
||||||
* if (value != NULL){
|
* if (value != NULL){
|
||||||
* // use extension value
|
* // use extension value
|
||||||
|
|
@ -3572,6 +3577,7 @@ int
|
||||||
yang_extension_value(yang_stmt *ys,
|
yang_extension_value(yang_stmt *ys,
|
||||||
char *name,
|
char *name,
|
||||||
char *ns,
|
char *ns,
|
||||||
|
int *exist,
|
||||||
char **value)
|
char **value)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
|
@ -3585,7 +3591,7 @@ yang_extension_value(yang_stmt *ys,
|
||||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
yext = NULL; /* This loop gets complicated in trhe case the extension is augmented */
|
yext = NULL; /* This loop gets complicated in the case the extension is augmented */
|
||||||
while ((yext = yn_each(ys, yext)) != NULL) {
|
while ((yext = yn_each(ys, yext)) != NULL) {
|
||||||
if (yang_keyword_get(yext) != Y_UNKNOWN)
|
if (yang_keyword_get(yext) != Y_UNKNOWN)
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -3593,15 +3599,17 @@ yang_extension_value(yang_stmt *ys,
|
||||||
continue;
|
continue;
|
||||||
if (yang_find_prefix_by_namespace(ymod, ns, &prefix) < 0)
|
if (yang_find_prefix_by_namespace(ymod, ns, &prefix) < 0)
|
||||||
goto ok;
|
goto ok;
|
||||||
|
cbuf_reset(cb);
|
||||||
cprintf(cb, "%s:%s", prefix, name);
|
cprintf(cb, "%s:%s", prefix, name);
|
||||||
if (strcmp(yang_argument_get(yext), cbuf_get(cb)) != 0)
|
if (strcmp(yang_argument_get(yext), cbuf_get(cb)) != 0)
|
||||||
continue;
|
continue;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (yext != NULL){ /* Found */
|
if (yext != NULL){ /* Found */
|
||||||
if ((cv = yang_cv_get(yext)) == NULL)
|
if (exist)
|
||||||
goto ok;
|
*exist = 1;
|
||||||
if (value)
|
if (value &&
|
||||||
|
(cv = yang_cv_get(yext)) != NULL)
|
||||||
*value = cv_string_get(cv);
|
*value = cv_string_get(cv);
|
||||||
}
|
}
|
||||||
ok:
|
ok:
|
||||||
|
|
|
||||||
54
test/test_dispatcher.sh
Executable file
54
test/test_dispatcher.sh
Executable file
|
|
@ -0,0 +1,54 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Test of path dispatcher
|
||||||
|
|
||||||
|
# Magic line must be first in script (see README.md)
|
||||||
|
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
||||||
|
|
||||||
|
: ${clixon_util_dispatcher:="clixon_util_dispatcher"}
|
||||||
|
|
||||||
|
new "null test"
|
||||||
|
expectpart "$($clixon_util_dispatcher)" 0 "^$"
|
||||||
|
|
||||||
|
new "path /, nothing regged. Expect fail"
|
||||||
|
expectpart "$($clixon_util_dispatcher -c /)" 255 "^$"
|
||||||
|
|
||||||
|
new "reg /, path / arg foo"
|
||||||
|
expectpart "$($clixon_util_dispatcher -a foo -p / -r -c /)" 0 "cb1 foo"
|
||||||
|
|
||||||
|
new "reg /foo and /bar same cb1, call /"
|
||||||
|
expectpart "$($clixon_util_dispatcher -a foo -p /foo -r -a bar -p /bar -r -c /)" 0 "cb1 foo" "cb1 bar"
|
||||||
|
|
||||||
|
new "reg /foo and /bar different cb, call /"
|
||||||
|
expectpart "$($clixon_util_dispatcher -i 1 -a foo -p /foo -r -a bar -p /bar -i 2 -r -c /)" 0 "cb1 foo" "cb2 bar"
|
||||||
|
|
||||||
|
new "reg /foo and /bar call /foo"
|
||||||
|
expectpart "$($clixon_util_dispatcher -i 1 -a foo -p /foo -r -a bar -p /bar -i 2 -r -c /foo)" 0 "cb1 foo"
|
||||||
|
|
||||||
|
new "reg /foo and /bar call /bar"
|
||||||
|
expectpart "$($clixon_util_dispatcher -i 1 -a foo -p /foo -r -a bar -p /bar -i 2 -r -c /bar)" 0 "cb2 bar"
|
||||||
|
|
||||||
|
new "reg /route-table ipv4 and ipv6 call /route-table"
|
||||||
|
expectpart "$($clixon_util_dispatcher -i 1 -a ipv4 -p /route-table/ipv4 -r -a ipv6 -p /route-table -i 2 -r -c /route-table)" 0 "cb1 ipv4" "cb2 ipv6"
|
||||||
|
|
||||||
|
new "reg /route-table/ ipv4,ipv6 call /route-table/ipv4"
|
||||||
|
expectpart "$($clixon_util_dispatcher -i 1 -a ipv4 -p /route-table/ipv4 -r -a ipv6 -p /route-table/ipv6 -i 2 -r -c /route-table/ipv4)" 0 "cb1 ipv4" --not-- cb2
|
||||||
|
|
||||||
|
new "reg /route-table/ ipv4,ipv6 call /route-table/ipv6"
|
||||||
|
expectpart "$($clixon_util_dispatcher -i 1 -a ipv4 -p /route-table/ipv4 -r -a ipv6 -p /route-table/ipv6 -i 2 -r -c /route-table/ipv6)" 0 "cb2 ipv6" --not-- cb1
|
||||||
|
|
||||||
|
new "reg /route-table/ ipv4,ipv6 call /route-table[proto='ipv4']/ipv4"
|
||||||
|
expectpart "$($clixon_util_dispatcher -i 1 -a ipv4 -p /route-table/ipv4 -r -a ipv6 -p /route-table/ipv6 -i 2 -r -c /route-table[proto='ipv4']/ipv4)" 0 "cb1 ipv4" --not-- "cb2 ipv6"
|
||||||
|
|
||||||
|
new "reg /route-table/ ipv4,ipv6 call /route-table[proto='ipv6']/ipv6"
|
||||||
|
expectpart "$($clixon_util_dispatcher -i 1 -a ipv4 -p /route-table/ipv4 -r -a ipv6 -p /route-table/ipv6 -i 2 -r -c /route-table[proto='ipv6']/ipv6)" 0 "cb2 ipv6" --not-- "cb1 ipv4"
|
||||||
|
|
||||||
|
new "reg /route-table/ ipv4,ipv6 call /route-table=/ipv4"
|
||||||
|
expectpart "$($clixon_util_dispatcher -i 1 -a ipv4 -p /route-table/ipv4 -r -a ipv6 -p /route-table/ipv6 -i 2 -r -c /route-table=/ipv4)" 0 "cb1 ipv4" --not-- "cb2 ipv6"
|
||||||
|
|
||||||
|
# unset conditional parameters
|
||||||
|
unset clixon_util_dispatcher
|
||||||
|
|
||||||
|
rm -rf $dir
|
||||||
|
|
||||||
|
new "endtest"
|
||||||
|
endtest
|
||||||
|
|
@ -17,8 +17,6 @@ cfg=$dir/conf.xml
|
||||||
fexample=$dir/example-social.yang
|
fexample=$dir/example-social.yang
|
||||||
fstate=$dir/mystate.xml
|
fstate=$dir/mystate.xml
|
||||||
|
|
||||||
xpath=/es:audit-logs/es:audit-log
|
|
||||||
|
|
||||||
# For 1M test,m use an external file since the generation takes considerable time
|
# For 1M test,m use an external file since the generation takes considerable time
|
||||||
#fstate=~/tmp/mystate.xml
|
#fstate=~/tmp/mystate.xml
|
||||||
|
|
||||||
|
|
@ -110,7 +108,7 @@ function testrun_start()
|
||||||
fi
|
fi
|
||||||
sudo pkill -f clixon_backend # to be sure
|
sudo pkill -f clixon_backend # to be sure
|
||||||
|
|
||||||
new "start backend -s init -f $cfg -- -siS $fstate -X $xpath"
|
new "start backend -s init -f $cfg -- -siS $fstate -x $xpath"
|
||||||
start_backend -s init -f $cfg -- -siS $fstate -x $xpath
|
start_backend -s init -f $cfg -- -siS $fstate -x $xpath
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
@ -132,19 +130,26 @@ function testrun_stop()
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
testrun_start "/es:members/es:member[es:member-id='alice']/es:stats/es:numbers"
|
xpath0="/es:members/es:member[es:member-id='alice']/es:stats"
|
||||||
|
xpath="$xpath0/es:numbers"
|
||||||
|
testrun_start $xpath
|
||||||
|
|
||||||
new "NETCONF get leaf-list member/numbers 0-10 alice"
|
new "NETCONF get leaf-list member/numbers 0-10 alice"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get content=\"nonconfig\"><filter type=\"xpath\" select=\"$xpath\" xmlns:es=\"http://example.com/ns/example-social\"/><list-pagination xmlns=\"http://clicon.org/clixon-netconf-list-pagination\">true</list-pagination><offset xmlns=\"http://clicon.org/clixon-netconf-list-pagination\">0</offset><limit xmlns=\"http://clicon.org/clixon-netconf-list-pagination\">10</limit></get></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><data><members xmlns=\"http://example.com/ns/example-social\"><member><member-id>alice</member-id><privacy-settings><post-visibility>public</post-visibility></privacy-settings><stats><numbers>3</numbers><numbers>4</numbers><numbers>5</numbers><numbers>6</numbers><numbers>7</numbers><numbers>8</numbers></stats></member></members></data></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get content=\"nonconfig\"><filter type=\"xpath\" select=\"$xpath\" xmlns:es=\"http://example.com/ns/example-social\"/><list-pagination xmlns=\"http://clicon.org/clixon-netconf-list-pagination\">true</list-pagination><offset xmlns=\"http://clicon.org/clixon-netconf-list-pagination\">0</offset><limit xmlns=\"http://clicon.org/clixon-netconf-list-pagination\">10</limit></get></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><data><members xmlns=\"http://example.com/ns/example-social\"><member><member-id>alice</member-id><privacy-settings><post-visibility>public</post-visibility></privacy-settings><stats><numbers>3</numbers><numbers>4</numbers><numbers>5</numbers><numbers>6</numbers><numbers>7</numbers><numbers>8</numbers></stats></member></members></data></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
# negative
|
# negative
|
||||||
new "NETCONF get container, expect fail"
|
new "NETCONF get container, expect fail"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get content=\"nonconfig\"><filter type=\"xpath\" select=\"/es:members/es:member[es:member-id='alice']/es:stats\" xmlns:es=\"http://example.com/ns/example-social\"/><list-pagination xmlns=\"http://clicon.org/clixon-netconf-list-pagination\">true</list-pagination><offset xmlns=\"http://clicon.org/clixon-netconf-list-pagination\">0</offset><limit xmlns=\"http://clicon.org/clixon-netconf-list-pagination\">10</limit></get></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>invalid-value</error-tag><error-severity>error</error-severity><error-message>list-pagination is enabled but target is not list or leaf-list</error-message></rpc-error></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get content=\"nonconfig\"><filter type=\"xpath\" select=\"$xpath0\" xmlns:es=\"http://example.com/ns/example-social\"/><list-pagination xmlns=\"http://clicon.org/clixon-netconf-list-pagination\">true</list-pagination><offset xmlns=\"http://clicon.org/clixon-netconf-list-pagination\">0</offset><limit xmlns=\"http://clicon.org/clixon-netconf-list-pagination\">10</limit></get></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>invalid-value</error-tag><error-severity>error</error-severity><error-message>list-pagination is enabled but target is not list or leaf-list</error-message></rpc-error></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
xpath="/es:members/es:member[es:member-id='bob']/es:stats/es:numbers"
|
||||||
|
new "NETCONF get leaf-list member/numbers 0-10 bob"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get content=\"nonconfig\"><filter type=\"xpath\" select=\"$xpath\" xmlns:es=\"http://example.com/ns/example-social\"/><list-pagination xmlns=\"http://clicon.org/clixon-netconf-list-pagination\">true</list-pagination><offset xmlns=\"http://clicon.org/clixon-netconf-list-pagination\">0</offset><limit xmlns=\"http://clicon.org/clixon-netconf-list-pagination\">10</limit></get></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><data><members xmlns=\"http://example.com/ns/example-social\"><member><member-id>bob</member-id><privacy-settings><post-visibility>public</post-visibility></privacy-settings><stats><numbers>13</numbers><numbers>14</numbers><numbers>15</numbers><numbers>16</numbers><numbers>17</numbers><numbers>18</numbers></stats></member></members></data></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
testrun_stop
|
testrun_stop
|
||||||
|
|
||||||
#----------------------------
|
#----------------------------
|
||||||
testrun_start "/es:members/es:member/es:stats/es:numbers"
|
xpath="/es:members/es:member/es:stats/es:numbers"
|
||||||
|
testrun_start $xpath
|
||||||
|
|
||||||
new "NETCONF get leaf-list member/numbers all"
|
new "NETCONF get leaf-list member/numbers all"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get content=\"nonconfig\"><filter type=\"xpath\" select=\"$xpath\" xmlns:es=\"http://example.com/ns/example-social\"/><list-pagination xmlns=\"http://clicon.org/clixon-netconf-list-pagination\">true</list-pagination><offset xmlns=\"http://clicon.org/clixon-netconf-list-pagination\">0</offset><limit xmlns=\"http://clicon.org/clixon-netconf-list-pagination\">10</limit></get></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><data><members xmlns=\"http://example.com/ns/example-social\"><member><member-id>alice</member-id><privacy-settings><post-visibility>public</post-visibility></privacy-settings><stats><numbers>3</numbers><numbers>4</numbers><numbers>5</numbers><numbers>6</numbers><numbers>7</numbers><numbers>8</numbers></stats></member><member><member-id>bob</member-id><privacy-settings><post-visibility>public</post-visibility></privacy-settings><stats><numbers>13</numbers><numbers>14</numbers><numbers>15</numbers><numbers>16</numbers></stats></member></members></data></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get content=\"nonconfig\"><filter type=\"xpath\" select=\"$xpath\" xmlns:es=\"http://example.com/ns/example-social\"/><list-pagination xmlns=\"http://clicon.org/clixon-netconf-list-pagination\">true</list-pagination><offset xmlns=\"http://clicon.org/clixon-netconf-list-pagination\">0</offset><limit xmlns=\"http://clicon.org/clixon-netconf-list-pagination\">10</limit></get></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><data><members xmlns=\"http://example.com/ns/example-social\"><member><member-id>alice</member-id><privacy-settings><post-visibility>public</post-visibility></privacy-settings><stats><numbers>3</numbers><numbers>4</numbers><numbers>5</numbers><numbers>6</numbers><numbers>7</numbers><numbers>8</numbers></stats></member><member><member-id>bob</member-id><privacy-settings><post-visibility>public</post-visibility></privacy-settings><stats><numbers>13</numbers><numbers>14</numbers><numbers>15</numbers><numbers>16</numbers></stats></member></members></data></rpc-reply>]]>]]>$"
|
||||||
|
|
@ -169,6 +174,7 @@ fi # interactive
|
||||||
unset validatexml
|
unset validatexml
|
||||||
unset perfnr
|
unset perfnr
|
||||||
unset xpath
|
unset xpath
|
||||||
|
unset xpath0
|
||||||
|
|
||||||
rm -rf $dir
|
rm -rf $dir
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,7 @@ APPSRC += clixon_util_datastore.c
|
||||||
APPSRC += clixon_util_regexp.c
|
APPSRC += clixon_util_regexp.c
|
||||||
APPSRC += clixon_util_socket.c
|
APPSRC += clixon_util_socket.c
|
||||||
APPSRC += clixon_util_validate.c
|
APPSRC += clixon_util_validate.c
|
||||||
|
APPSRC += clixon_util_dispatcher.c
|
||||||
APPSRC += clixon_netconf_ssh_callhome.c
|
APPSRC += clixon_netconf_ssh_callhome.c
|
||||||
APPSRC += clixon_netconf_ssh_callhome_client.c
|
APPSRC += clixon_netconf_ssh_callhome_client.c
|
||||||
ifdef with_restconf
|
ifdef with_restconf
|
||||||
|
|
@ -102,7 +103,6 @@ APPSRC += clixon_util_ssl.c # requires http/2
|
||||||
#APPSRC += clixon_util_grpc.c # work in progress
|
#APPSRC += clixon_util_grpc.c # work in progress
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
APPS = $(APPSRC:.c=)
|
APPS = $(APPSRC:.c=)
|
||||||
|
|
||||||
all: $(APPS)
|
all: $(APPS)
|
||||||
|
|
@ -149,6 +149,9 @@ clixon_util_socket: clixon_util_socket.c $(LIBDEPS)
|
||||||
clixon_util_validate: clixon_util_validate.c $(LIBDEPS)
|
clixon_util_validate: clixon_util_validate.c $(LIBDEPS)
|
||||||
$(CC) $(INCLUDES) $(CPPFLAGS) @CFLAGS@ $(LDFLAGS) $^ -l clixon_backend -o $@ $(LIBS)
|
$(CC) $(INCLUDES) $(CPPFLAGS) @CFLAGS@ $(LDFLAGS) $^ -l clixon_backend -o $@ $(LIBS)
|
||||||
|
|
||||||
|
clixon_util_dispatcher: clixon_util_dispatcher.c $(LIBDEPS)
|
||||||
|
$(CC) $(INCLUDES) $(CPPFLAGS) @CFLAGS@ $(LDFLAGS) $^ -l clixon_backend -o $@ $(LIBS)
|
||||||
|
|
||||||
ifdef with_restconf
|
ifdef with_restconf
|
||||||
clixon_util_stream: clixon_util_stream.c $(LIBDEPS)
|
clixon_util_stream: clixon_util_stream.c $(LIBDEPS)
|
||||||
$(CC) $(INCLUDES) $(CPPFLAGS) @CFLAGS@ $(LDFLAGS) $^ $(LIBS) -lcurl -o $@
|
$(CC) $(INCLUDES) $(CPPFLAGS) @CFLAGS@ $(LDFLAGS) $^ $(LIBS) -lcurl -o $@
|
||||||
|
|
@ -163,7 +166,7 @@ endif
|
||||||
distclean: clean
|
distclean: clean
|
||||||
rm -f Makefile *~ .depend
|
rm -f Makefile *~ .depend
|
||||||
|
|
||||||
install:
|
install: $(APPS)
|
||||||
install -d -m 0755 $(DESTDIR)$(bindir)
|
install -d -m 0755 $(DESTDIR)$(bindir)
|
||||||
install -m 0755 $(INSTALLFLAGS) $(APPS) $(DESTDIR)$(bindir)
|
install -m 0755 $(INSTALLFLAGS) $(APPS) $(DESTDIR)$(bindir)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
|
||||||
191
util/clixon_util_dispatcher.c
Normal file
191
util/clixon_util_dispatcher.c
Normal file
|
|
@ -0,0 +1,191 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
***** BEGIN LICENSE BLOCK *****
|
||||||
|
|
||||||
|
Copyright (C) 2021 Olof Hagsand and Rubicon Communications, LLC(Netgate)
|
||||||
|
|
||||||
|
This file is part of CLIXON.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
Alternatively, the contents of this file may be used under the terms of
|
||||||
|
the GNU General Public License Version 3 or later (the "GPL"),
|
||||||
|
in which case the provisions of the GPL are applicable instead
|
||||||
|
of those above. If you wish to allow use of your version of this file only
|
||||||
|
under the terms of the GPL, and not to allow others to
|
||||||
|
use your version of this file under the terms of Apache License version 2,
|
||||||
|
indicate your decision by deleting the provisions above and replace them with
|
||||||
|
the notice and other provisions required by the GPL. If you do not delete
|
||||||
|
the provisions above, a recipient may use your version of this file under
|
||||||
|
the terms of any one of the Apache License version 2 or the GPL.
|
||||||
|
|
||||||
|
***** END LICENSE BLOCK *****
|
||||||
|
|
||||||
|
* Utility for testing path dispatcher
|
||||||
|
* Everything is run by options and order is significant which makes it a little special.
|
||||||
|
* For example:
|
||||||
|
* clixon_util_dispatcher -r -c / :
|
||||||
|
* Register cb1 with default path "/" and arg NULL, call with path /
|
||||||
|
* clixon_util_dispatcher -i 2 -p /foo -a bar -r -c /bar -c /fie
|
||||||
|
* Register cb2 with path "/foo" and arg bar, call with path /bar then /fie
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "clixon_config.h" /* generated by config & autoconf */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
/* cligen */
|
||||||
|
#include <cligen/cligen.h>
|
||||||
|
|
||||||
|
/* clixon */
|
||||||
|
#include "clixon/clixon.h"
|
||||||
|
#include "clixon/clixon_backend.h"
|
||||||
|
|
||||||
|
/* Command line options to be passed to getopt(3) */
|
||||||
|
#define DISPATCHER_OPTS "hD:a:i:p:rc:"
|
||||||
|
|
||||||
|
static int
|
||||||
|
usage(char *argv0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "usage:%s [options]\n"
|
||||||
|
"where options are\n"
|
||||||
|
"\t-h \t\tHelp\n"
|
||||||
|
"\t-D <level> \t Debug - print dispatch tree\n"
|
||||||
|
"\t-a <string>\t Argument to callback (default: NULL)\n"
|
||||||
|
"\t-i <int> \t Function index: 1..3 (default: 1)\n"
|
||||||
|
"\t-p <path> \t Registered path (default: /)\n"
|
||||||
|
"\t-r \t Register callback (based on -a/-i/-p setting)\n"
|
||||||
|
"\t-c <path> \t Call dispatcher with path\n",
|
||||||
|
argv0
|
||||||
|
);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Function to handle a path
|
||||||
|
*
|
||||||
|
* @param[in] h Generic handler
|
||||||
|
* @param[in] xpath Registered XPath using canonical prefixes
|
||||||
|
* @param[in] userargs Per-call user arguments
|
||||||
|
* @param[in] arg Per-path user argument
|
||||||
|
*(
|
||||||
|
/ * Make a CB() macro to generate simple callbacks that just prints the path and arg
|
||||||
|
*/
|
||||||
|
#define CB(i) static int cb##i(void *h0, char *xpath, void *userargs, void *arg) { fprintf(stdout, "%s %s\n", __FUNCTION__, (char*)arg); return 0; }
|
||||||
|
|
||||||
|
CB(1)
|
||||||
|
CB(2)
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc,
|
||||||
|
char **argv)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
char *argv0 = argv[0];
|
||||||
|
int logdst = CLICON_LOG_STDERR;
|
||||||
|
int dbg = 0;
|
||||||
|
int c;
|
||||||
|
char *arg = NULL;
|
||||||
|
handler_function fn = cb1;
|
||||||
|
dispatcher_entry_t *htable = NULL;
|
||||||
|
int ret;
|
||||||
|
char *regpath = "/"; /* Register path */
|
||||||
|
|
||||||
|
/* In the startup, logs to stderr & debug flag set later */
|
||||||
|
clicon_log_init("dispatcher", LOG_DEBUG, logdst);
|
||||||
|
|
||||||
|
optind = 1;
|
||||||
|
opterr = 0;
|
||||||
|
while ((c = getopt(argc, argv, DISPATCHER_OPTS)) != -1)
|
||||||
|
switch (c) {
|
||||||
|
case 'h':
|
||||||
|
usage(argv0);
|
||||||
|
break;
|
||||||
|
case 'D':
|
||||||
|
if (sscanf(optarg, "%d", &dbg) != 1)
|
||||||
|
usage(argv0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'a' :
|
||||||
|
case 'i' :
|
||||||
|
case 'p' :
|
||||||
|
case 'r' :
|
||||||
|
case 'c' :
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage(argv[0]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Logs, error and debug to stderr or syslog, set debug level
|
||||||
|
*/
|
||||||
|
clicon_log_init("xpath", dbg?LOG_DEBUG:LOG_INFO, logdst);
|
||||||
|
|
||||||
|
clicon_debug_init(dbg, NULL);
|
||||||
|
|
||||||
|
/* Now rest of options */
|
||||||
|
opterr = 0;
|
||||||
|
optind = 1;
|
||||||
|
while ((c = getopt(argc, argv, DISPATCHER_OPTS)) != -1){
|
||||||
|
switch (c) {
|
||||||
|
case 'D' : /* debug */
|
||||||
|
break; /* see above */
|
||||||
|
case 'a' : /* arg string */
|
||||||
|
arg = optarg;
|
||||||
|
break;
|
||||||
|
case 'i' : /* dispatcher function: 1..3 */
|
||||||
|
switch (atoi(optarg)){
|
||||||
|
case 1: fn = cb1; break;
|
||||||
|
case 2: fn = cb2; break;
|
||||||
|
// case 3: fn = cb3; break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'p' : /* register path */
|
||||||
|
regpath = optarg;
|
||||||
|
break;
|
||||||
|
case 'r' :{ /* register callback based on -a/-i/-p*/
|
||||||
|
dispatcher_definition x = {regpath, fn, arg};
|
||||||
|
if (dispatcher_register_handler(&htable, &x) < 0)
|
||||||
|
goto done;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'c':{ /* Execute a call using path */
|
||||||
|
char *path = optarg;
|
||||||
|
if ((ret = dispatcher_call_handlers(htable, NULL, path, NULL)) < 0)
|
||||||
|
goto done;
|
||||||
|
fprintf(stderr, "path:%s ret:%d\n", path, ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
usage(argv[0]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dbg)
|
||||||
|
dispatcher_print(stderr, 0, htable);
|
||||||
|
dispatcher_free(htable);
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
@ -50,6 +50,7 @@
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
/* cligen */
|
/* cligen */
|
||||||
#include <cligen/cligen.h>
|
#include <cligen/cligen.h>
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
/* cligen */
|
/* cligen */
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
#ifdef HAVE_LIBXML2 /* Actually it should check for a header file */
|
#ifdef HAVE_LIBXML2 /* Actually it should check for a header file */
|
||||||
#include <libxml/xmlregexp.h>
|
#include <libxml/xmlregexp.h>
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <netdb.h> /* gethostbyname */
|
#include <netdb.h> /* gethostbyname */
|
||||||
#include <arpa/inet.h> /* inet_pton */
|
#include <arpa/inet.h> /* inet_pton */
|
||||||
#include <netinet/tcp.h> /* TCP_NODELAY */
|
#include <netinet/tcp.h> /* TCP_NODELAY */
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
|
||||||
/* cligen */
|
/* cligen */
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
/* cligen */
|
/* cligen */
|
||||||
#include <cligen/cligen.h>
|
#include <cligen/cligen.h>
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ See https://www.w3.org/TR/xpath/
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
/* cligen */
|
/* cligen */
|
||||||
|
|
@ -126,7 +127,7 @@ main(int argc,
|
||||||
int len;
|
int len;
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
FILE *fp = stdin; /* unless overriden by argv[1] */
|
FILE *fp = stdin; /* unless overriden by -f */
|
||||||
char *yang_file_dir = NULL;
|
char *yang_file_dir = NULL;
|
||||||
yang_stmt *yspec = NULL;
|
yang_stmt *yspec = NULL;
|
||||||
char *xpath = NULL;
|
char *xpath = NULL;
|
||||||
|
|
@ -169,7 +170,7 @@ main(int argc,
|
||||||
case 'f': /* XML file */
|
case 'f': /* XML file */
|
||||||
filename = optarg;
|
filename = optarg;
|
||||||
if ((fp = fopen(filename, "r")) == NULL){
|
if ((fp = fopen(filename, "r")) == NULL){
|
||||||
clicon_err(OE_UNIX, errno, "open(%s)", argv[1]);
|
clicon_err(OE_UNIX, errno, "fopen(%s)", optarg);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -51,11 +51,11 @@
|
||||||
#include <regex.h>
|
#include <regex.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
|
||||||
/* cligen */
|
/* cligen */
|
||||||
#include <cligen/cligen.h>
|
#include <cligen/cligen.h>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue