- Restructure plugin module using a "module struct" rather than global variables.

This include plugin module init and exit functions
  New type: clixon_plugin_t exposed via public API while struct clixon_plugin is private
- Makefile changes for static linkage using "LINKAGE=static"
- Moved nacm external init to later stage in backend_main
This commit is contained in:
Olof hagsand 2021-04-19 09:39:07 +02:00
parent 7ebb538ebf
commit b88722fa25
29 changed files with 557 additions and 345 deletions

View file

@ -138,9 +138,9 @@ configure: configure.ac
cd $(srcdir) && autoconf cd $(srcdir) && autoconf
clean: clean:
rm -f *.gcov
for i in $(SUBDIRS) doc example util docker; \ for i in $(SUBDIRS) doc example util docker; \
do (cd $$i && $(MAKE) $(MFLAGS) $@); done; do (cd $$i && $(MAKE) $(MFLAGS) $@); done;
rm -f *.gcov test/*.gcov
# Uninstall and clean all the targets used for testing, but without cloning or # Uninstall and clean all the targets used for testing, but without cloning or
# checking-out from git. Provides a reliabily clean slate for testing changes # checking-out from git. Provides a reliabily clean slate for testing changes

View file

@ -46,7 +46,9 @@ endif
SH_SUFFIX = @SH_SUFFIX@ SH_SUFFIX = @SH_SUFFIX@
INSTALLFLAGS = @INSTALLFLAGS@ INSTALLFLAGS = @INSTALLFLAGS@
LDFLAGS = @LDFLAGS@ LDFLAGS = @LDFLAGS@
ifeq ($(LINKAGE),static)
LDFLAGS += -rdynamic -L.
endif
prefix = @prefix@ prefix = @prefix@
exec_prefix = @exec_prefix@ exec_prefix = @exec_prefix@
bindir = @bindir@ bindir = @bindir@
@ -63,7 +65,7 @@ CLIXON_MINOR = @CLIXON_VERSION_MINOR@
# Use this clixon lib for linking # Use this clixon lib for linking
ifeq ($(LINKAGE),static) ifeq ($(LINKAGE),static)
CLIXON_LIB = libclixon$(SH_SUFFIX) CLIXON_LIB = libclixon.a
else else
CLIXON_LIB = libclixon$(SH_SUFFIX).$(CLIXON_MAJOR).$(CLIXON_MINOR) CLIXON_LIB = libclixon$(SH_SUFFIX).$(CLIXON_MAJOR).$(CLIXON_MINOR)
endif endif
@ -113,6 +115,7 @@ $(top_srcdir)/lib/src/$(CLIXON_LIB):
clean: clean:
rm -f *.core $(APPL) $(APPOBJ) $(LIBOBJ) $(MYLIB) $(MYLIBSO) $(MYLIBLINK) test test.c rm -f *.core $(APPL) $(APPOBJ) $(LIBOBJ) $(MYLIB) $(MYLIBSO) $(MYLIBLINK) test test.c
rm -f *.gcda *.gcno *.gcov # coverage
distclean: clean distclean: clean
rm -f Makefile *~ .depend rm -f Makefile *~ .depend
@ -130,8 +133,8 @@ install-lib: $(MYLIB)
install -m 0644 $(INSTALLFLAGS) $(MYLIB) $(DESTDIR)$(libdir) install -m 0644 $(INSTALLFLAGS) $(MYLIB) $(DESTDIR)$(libdir)
install -d -m 0755 $(DESTDIR)$(libdir)/clixon/plugins/backend install -d -m 0755 $(DESTDIR)$(libdir)/clixon/plugins/backend
ifeq ($(LINKAGE),dynamic) ifeq ($(LINKAGE),dynamic)
ln -sf $(MYLIB) $(DESTDIR)$(libdir)/$(MYLIBSO) # -l:libclixon_config.so.2 ln -sf $(MYLIB) $(DESTDIR)$(libdir)/$(MYLIBSO) # -l:libclixon_backend.so.2
ln -sf $(MYLIBSO) $(DESTDIR)$(libdir)/$(MYLIBLINK) # -l:libclixon_config.so ln -sf $(MYLIBSO) $(DESTDIR)$(libdir)/$(MYLIBLINK) # -l:libclixon_backend.so
endif endif
uninstall: uninstall:
@ -147,7 +150,7 @@ install-include: clixon_backend.h clixon_backend_handle.h clixon_backend_transac
.SUFFIXES: .c .o .SUFFIXES: .c .o
.c.o: .c.o:
$(CC) $(INCLUDES) -D__PROGRAM__=\"$(APPL)\" $(CPPFLAGS) $(CFLAGS) -c $< $(CC) $(INCLUDES) $(CPPFLAGS) -D__PROGRAM__=\"$(APPL)\" $(CFLAGS) -c $<
# Just link test programs # Just link test programs
test.c : test.c :
@ -157,7 +160,11 @@ test: test.c $(LIBOBJ) $(MYLIB)
$(CC) $(INCLUDES) $(LDFLAGS) $< $(LIBOBJ) -L. $(MYLIB) $(LIBS) -o $@ $(CC) $(INCLUDES) $(LDFLAGS) $< $(LIBOBJ) -L. $(MYLIB) $(LIBS) -o $@
$(APPL) : $(APPOBJ) $(MYLIB) $(LIBDEPS) $(APPL) : $(APPOBJ) $(MYLIB) $(LIBDEPS)
ifeq ($(LINKAGE),dynamic)
$(CC) $(LDFLAGS) $(APPOBJ) -L. $(MYLIB) $(LIBS) -o $@ $(CC) $(LDFLAGS) $(APPOBJ) -L. $(MYLIB) $(LIBS) -o $@
else
$(CC) $(LDFLAGS) $(APPOBJ) -L. $(LIBOBJ) $(LIBS) -o $@
endif
$(MYLIBDYNAMIC): $(LIBOBJ) $(LIBDEPS) $(MYLIBDYNAMIC): $(LIBOBJ) $(LIBDEPS)
ifeq ($(HOST_VENDOR),apple) ifeq ($(HOST_VENDOR),apple)

View file

@ -1547,7 +1547,7 @@ from_client_restart_plugin(clicon_handle h,
cxobj **vec = NULL; cxobj **vec = NULL;
size_t veclen; size_t veclen;
int i; int i;
clixon_plugin *cp; clixon_plugin_t *cp;
int ret; int ret;
if (xpath_vec(xe, NULL, "plugin", &vec, &veclen) < 0) if (xpath_vec(xe, NULL, "plugin", &vec, &veclen) < 0)

View file

@ -878,7 +878,7 @@ from_client_validate(clicon_handle h,
*/ */
int int
from_client_restart_one(clicon_handle h, from_client_restart_one(clicon_handle h,
clixon_plugin *cp, clixon_plugin_t *cp,
cbuf *cbret) cbuf *cbret)
{ {
int retval = -1; int retval = -1;
@ -895,7 +895,7 @@ from_client_restart_one(clicon_handle 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 = cp->cp_api.ca_reset) != NULL){ if ((resetfn = clixon_plugin_api_get(cp)->ca_reset) != NULL){
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;

View file

@ -50,6 +50,6 @@ int from_client_commit(clicon_handle h, cxobj *xe, cbuf *cbret, void *arg, void
int from_client_discard_changes(clicon_handle h, cxobj *xe, cbuf *cbret, void *arg, void *regarg); int from_client_discard_changes(clicon_handle h, cxobj *xe, cbuf *cbret, void *arg, void *regarg);
int from_client_cancel_commit(clicon_handle h, cxobj *xe, cbuf *cbret, void *arg, void *regarg); int from_client_cancel_commit(clicon_handle h, cxobj *xe, cbuf *cbret, void *arg, void *regarg);
int from_client_validate(clicon_handle h, cxobj *xe, cbuf *cbret, void *arg, void *regarg); int from_client_validate(clicon_handle h, cxobj *xe, cbuf *cbret, void *arg, void *regarg);
int from_client_restart_one(clicon_handle h, clixon_plugin *cp, cbuf *cbret); int from_client_restart_one(clicon_handle h, clixon_plugin_t *cp, cbuf *cbret);
#endif /* _BACKEND_COMMIT_H_ */ #endif /* _BACKEND_COMMIT_H_ */

View file

@ -125,11 +125,8 @@ backend_terminate(clicon_handle h)
if ((x = clicon_conf_xml(h)) != NULL) if ((x = clicon_conf_xml(h)) != NULL)
xml_free(x); xml_free(x);
stream_publish_exit(); stream_publish_exit();
clixon_plugin_exit_all(h); /* Delete all plugins, RPC callbacks, and upgrade callbacks */
/* Delete all backend plugin RPC callbacks */ clixon_plugin_module_exit(h);
rpc_callback_delete_all(h);
/* Delete all backend plugin upgrade callbacks */
upgrade_callback_delete_all(h);
/* Delete all process-control entries */ /* Delete all process-control entries */
clixon_process_delete_all(h); clixon_process_delete_all(h);
@ -517,7 +514,6 @@ main(int argc,
/* Initiate CLICON handle */ /* Initiate CLICON handle */
if ((h = backend_handle_init()) == NULL) if ((h = backend_handle_init()) == NULL)
return -1; return -1;
foreground = 0; foreground = 0;
once = 0; once = 0;
zap = 0; zap = 0;
@ -582,12 +578,10 @@ main(int argc,
clicon_option_str_set(h, "CLICON_WWWUSER", WWWUSER); clicon_option_str_set(h, "CLICON_WWWUSER", WWWUSER);
clicon_option_str_set(h, "CLICON_WWWDIR", WWWDIR); clicon_option_str_set(h, "CLICON_WWWDIR", WWWDIR);
/* External NACM file? */ /* Initialize plugin module by creating a handle holding plugin and callback lists */
nacm_mode = clicon_option_str(h, "CLICON_NACM_MODE"); if (clixon_plugin_module_init(h) < 0)
if (nacm_mode && strcmp(nacm_mode, "external") == 0) goto done;
if (nacm_load_external(h) < 0)
goto done;
/* Now run through the operational args */ /* Now run through the operational args */
opterr = 1; opterr = 1;
optind = 1; optind = 1;
@ -780,6 +774,14 @@ main(int argc,
if (netconf_module_features(h) < 0) if (netconf_module_features(h) < 0)
goto done; goto done;
/* External NACM file?
* Note, loads yang -> extensions -> plugins
*/
nacm_mode = clicon_option_str(h, "CLICON_NACM_MODE");
if (nacm_mode && strcmp(nacm_mode, "external") == 0)
if (nacm_load_external(h) < 0)
goto done;
/* Create top-level yang spec and store as option */ /* Create top-level yang spec and store as option */
if ((yspec = yspec_new()) == NULL) if ((yspec = yspec_new()) == NULL)
goto done; goto done;

View file

@ -74,18 +74,18 @@
* @retval -1 Error * @retval -1 Error
*/ */
int int
clixon_plugin_reset_one(clixon_plugin *cp, clixon_plugin_reset_one(clixon_plugin_t *cp,
clicon_handle h, clicon_handle h,
char *db) char *db)
{ {
int retval = -1; int retval = -1;
plgreset_t *fn; /* callback */ plgreset_t *fn; /* callback */
if ((fn = cp->cp_api.ca_reset) != NULL){ if ((fn = clixon_plugin_api_get(cp)->ca_reset) != NULL){
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__, cp->cp_name); __FUNCTION__, clixon_plugin_name_get(cp));
goto done; goto done;
} }
} }
@ -106,7 +106,7 @@ clixon_plugin_reset_all(clicon_handle h,
char *db) char *db)
{ {
int retval = -1; int retval = -1;
clixon_plugin *cp = NULL; clixon_plugin_t *cp = NULL;
/* 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) {
@ -125,18 +125,18 @@ clixon_plugin_reset_all(clicon_handle h,
* @retval -1 Error * @retval -1 Error
*/ */
static int static int
clixon_plugin_pre_daemon_one(clixon_plugin *cp, clixon_plugin_pre_daemon_one(clixon_plugin_t *cp,
clicon_handle h) clicon_handle h)
{ {
int retval = -1; int retval = -1;
plgdaemon_t *fn; /* Daemonize plugin callback function */ plgdaemon_t *fn; /* Daemonize plugin callback function */
if ((fn = cp->cp_api.ca_pre_daemon) != NULL){ if ((fn = clixon_plugin_api_get(cp)->ca_pre_daemon) != NULL){
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:\
%s returned -1 but did not make a clicon_err call", %s returned -1 but did not make a clicon_err call",
__FUNCTION__, cp->cp_name); __FUNCTION__, clixon_plugin_name_get(cp));
goto done; goto done;
} }
} }
@ -158,7 +158,7 @@ int
clixon_plugin_pre_daemon_all(clicon_handle h) clixon_plugin_pre_daemon_all(clicon_handle h)
{ {
int retval = -1; int retval = -1;
clixon_plugin *cp = NULL; clixon_plugin_t *cp = NULL;
/* 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) {
@ -177,17 +177,17 @@ clixon_plugin_pre_daemon_all(clicon_handle h)
* @retval -1 Error * @retval -1 Error
*/ */
static int static int
clixon_plugin_daemon_one(clixon_plugin *cp, clixon_plugin_daemon_one(clixon_plugin_t *cp,
clicon_handle h) clicon_handle h)
{ {
int retval = -1; int retval = -1;
plgdaemon_t *fn; /* Daemonize plugin callback function */ plgdaemon_t *fn; /* Daemonize plugin callback function */
if ((fn = cp->cp_api.ca_daemon) != NULL){ if ((fn = clixon_plugin_api_get(cp)->ca_daemon) != NULL){
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__, cp->cp_name); __FUNCTION__, clixon_plugin_name_get(cp));
goto done; goto done;
} }
} }
@ -211,7 +211,7 @@ int
clixon_plugin_daemon_all(clicon_handle h) clixon_plugin_daemon_all(clicon_handle h)
{ {
int retval = -1; int retval = -1;
clixon_plugin *cp = NULL; clixon_plugin_t *cp = NULL;
/* 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) {
@ -244,7 +244,7 @@ clixon_plugin_daemon_all(clicon_handle h)
* @retval 1 OK if callback found (and called) xret is set * @retval 1 OK if callback found (and called) xret is set
*/ */
static int static int
clixon_plugin_statedata_one(clixon_plugin *cp, clixon_plugin_statedata_one(clixon_plugin_t *cp,
clicon_handle h, clicon_handle h,
cvec *nsc, cvec *nsc,
char *xpath, char *xpath,
@ -254,13 +254,13 @@ clixon_plugin_statedata_one(clixon_plugin *cp,
plgstatedata_t *fn; /* Plugin statedata fn */ plgstatedata_t *fn; /* Plugin statedata fn */
cxobj *x = NULL; cxobj *x = NULL;
if ((fn = cp->cp_api.ca_statedata) != NULL){ if ((fn = clixon_plugin_api_get(cp)->ca_statedata) != NULL){
if ((x = xml_new(XML_TOP_SYMBOL, NULL, CX_ELMNT)) == NULL) if ((x = xml_new(XML_TOP_SYMBOL, NULL, CX_ELMNT)) == NULL)
goto done; 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__, cp->cp_name); __FUNCTION__, clixon_plugin_name_get(cp));
goto fail; /* Dont quit here on user callbacks */ goto fail; /* Dont quit here on user callbacks */
} }
@ -298,7 +298,7 @@ clixon_plugin_statedata_all(clicon_handle h,
int retval = -1; int retval = -1;
int ret; int ret;
cxobj *x = NULL; cxobj *x = NULL;
clixon_plugin *cp = NULL; clixon_plugin_t *cp = NULL;
cbuf *cberr = NULL; cbuf *cberr = NULL;
cxobj *xerr = NULL; cxobj *xerr = NULL;
@ -313,7 +313,7 @@ clixon_plugin_statedata_all(clicon_handle h,
} }
/* error reason should be in clicon_err_reason */ /* error reason should be in clicon_err_reason */
cprintf(cberr, "Internal error, state callback in plugin %s returned invalid XML: %s", cprintf(cberr, "Internal error, state callback in plugin %s returned invalid XML: %s",
cp->cp_name, clicon_err_reason); clixon_plugin_name_get(cp), clicon_err_reason);
if (netconf_operation_failed_xml(&xerr, "application", cbuf_get(cberr)) < 0) if (netconf_operation_failed_xml(&xerr, "application", cbuf_get(cberr)) < 0)
goto done; goto done;
xml_free(*xret); xml_free(*xret);
@ -338,7 +338,7 @@ clixon_plugin_statedata_all(clicon_handle h,
if (ret == 0){ if (ret == 0){
if (clixon_netconf_internal_error(xerr, if (clixon_netconf_internal_error(xerr,
". Internal error, state callback returned invalid XML from plugin: ", ". Internal error, state callback returned invalid XML from plugin: ",
cp->cp_name) < 0) clixon_plugin_name_get(cp)) < 0)
goto done; goto done;
xml_free(*xret); xml_free(*xret);
*xret = xerr; *xret = xerr;
@ -432,18 +432,18 @@ transaction_free(transaction_data_t *td)
* @retval -1 Error * @retval -1 Error
*/ */
int int
plugin_transaction_begin_one(clixon_plugin *cp, plugin_transaction_begin_one(clixon_plugin_t *cp,
clicon_handle h, clicon_handle h,
transaction_data_t *td) transaction_data_t *td)
{ {
int retval = -1; int retval = -1;
trans_cb_t *fn; trans_cb_t *fn;
if ((fn = cp->cp_api.ca_trans_begin) != NULL){ if ((fn = clixon_plugin_api_get(cp)->ca_trans_begin) != NULL){
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__, cp->cp_name); __FUNCTION__, clixon_plugin_name_get(cp));
goto done; goto done;
} }
} }
@ -465,7 +465,7 @@ plugin_transaction_begin_all(clicon_handle h,
transaction_data_t *td) transaction_data_t *td)
{ {
int retval = -1; int retval = -1;
clixon_plugin *cp = NULL; clixon_plugin_t *cp = NULL;
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)
@ -484,18 +484,18 @@ plugin_transaction_begin_all(clicon_handle h,
* @retval -1 Error * @retval -1 Error
*/ */
int int
plugin_transaction_validate_one(clixon_plugin *cp, plugin_transaction_validate_one(clixon_plugin_t *cp,
clicon_handle h, clicon_handle h,
transaction_data_t *td) transaction_data_t *td)
{ {
int retval = -1; int retval = -1;
trans_cb_t *fn; trans_cb_t *fn;
if ((fn = cp->cp_api.ca_trans_validate) != NULL){ if ((fn = clixon_plugin_api_get(cp)->ca_trans_validate) != NULL){
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__, cp->cp_name); __FUNCTION__, clixon_plugin_name_get(cp));
goto done; goto done;
} }
} }
@ -515,7 +515,7 @@ plugin_transaction_validate_all(clicon_handle h,
transaction_data_t *td) transaction_data_t *td)
{ {
int retval = -1; int retval = -1;
clixon_plugin *cp = NULL; clixon_plugin_t *cp = NULL;
while ((cp = clixon_plugin_each(h, cp)) != NULL) { while ((cp = clixon_plugin_each(h, cp)) != NULL) {
if (plugin_transaction_validate_one(cp, h, td) < 0) if (plugin_transaction_validate_one(cp, h, td) < 0)
@ -535,18 +535,18 @@ plugin_transaction_validate_all(clicon_handle h,
* @retval -1 Error * @retval -1 Error
*/ */
int int
plugin_transaction_complete_one(clixon_plugin *cp, plugin_transaction_complete_one(clixon_plugin_t *cp,
clicon_handle h, clicon_handle h,
transaction_data_t *td) transaction_data_t *td)
{ {
int retval = -1; int retval = -1;
trans_cb_t *fn; trans_cb_t *fn;
if ((fn = cp->cp_api.ca_trans_complete) != NULL){ if ((fn = clixon_plugin_api_get(cp)->ca_trans_complete) != NULL){
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__, cp->cp_name); __FUNCTION__, clixon_plugin_name_get(cp));
goto done; goto done;
} }
} }
@ -568,7 +568,7 @@ plugin_transaction_complete_all(clicon_handle h,
transaction_data_t *td) transaction_data_t *td)
{ {
int retval = -1; int retval = -1;
clixon_plugin *cp = NULL; clixon_plugin_t *cp = NULL;
while ((cp = clixon_plugin_each(h, cp)) != NULL) { while ((cp = clixon_plugin_each(h, cp)) != NULL) {
if (plugin_transaction_complete_one(cp, h, td) < 0) if (plugin_transaction_complete_one(cp, h, td) < 0)
@ -594,15 +594,15 @@ plugin_transaction_revert_all(clicon_handle h,
int nr) int nr)
{ {
int retval = 0; int retval = 0;
clixon_plugin *cp = NULL; clixon_plugin_t *cp = NULL;
trans_cb_t *fn; trans_cb_t *fn;
while ((cp = clixon_plugin_each_revert(h, cp, nr)) != NULL) { while ((cp = clixon_plugin_each_revert(h, cp, nr)) != NULL) {
if ((fn = cp->cp_api.ca_trans_revert) == NULL) if ((fn = clixon_plugin_api_get(cp)->ca_trans_revert) == NULL)
continue; continue;
if ((retval = fn(h, (transaction_data)td)) < 0){ if ((retval = fn(h, (transaction_data)td)) < 0){
clicon_log(LOG_NOTICE, "%s: Plugin '%s' trans_revert callback failed", clicon_log(LOG_NOTICE, "%s: Plugin '%s' trans_revert callback failed",
__FUNCTION__, cp->cp_name); __FUNCTION__, clixon_plugin_name_get(cp));
break; break;
} }
} }
@ -618,18 +618,18 @@ plugin_transaction_revert_all(clicon_handle h,
* @retval -1 Error * @retval -1 Error
*/ */
int int
plugin_transaction_commit_one(clixon_plugin *cp, plugin_transaction_commit_one(clixon_plugin_t *cp,
clicon_handle h, clicon_handle h,
transaction_data_t *td) transaction_data_t *td)
{ {
int retval = -1; int retval = -1;
trans_cb_t *fn; trans_cb_t *fn;
if ((fn = cp->cp_api.ca_trans_commit) != NULL){ if ((fn = clixon_plugin_api_get(cp)->ca_trans_commit) != NULL){
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__, cp->cp_name); __FUNCTION__, clixon_plugin_name_get(cp));
goto done; goto done;
} }
} }
@ -652,7 +652,7 @@ plugin_transaction_commit_all(clicon_handle h,
transaction_data_t *td) transaction_data_t *td)
{ {
int retval = -1; int retval = -1;
clixon_plugin *cp = NULL; clixon_plugin_t *cp = NULL;
int i=0; int i=0;
while ((cp = clixon_plugin_each(h, cp)) != NULL) { while ((cp = clixon_plugin_each(h, cp)) != NULL) {
@ -677,18 +677,18 @@ plugin_transaction_commit_all(clicon_handle h,
* @retval -1 Error * @retval -1 Error
*/ */
int int
plugin_transaction_commit_done_one(clixon_plugin *cp, plugin_transaction_commit_done_one(clixon_plugin_t *cp,
clicon_handle h, clicon_handle h,
transaction_data_t *td) transaction_data_t *td)
{ {
int retval = -1; int retval = -1;
trans_cb_t *fn; trans_cb_t *fn;
if ((fn = cp->cp_api.ca_trans_commit_done) != NULL){ if ((fn = clixon_plugin_api_get(cp)->ca_trans_commit_done) != NULL){
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__, cp->cp_name); __FUNCTION__, clixon_plugin_name_get(cp));
goto done; goto done;
} }
} }
@ -709,7 +709,7 @@ plugin_transaction_commit_done_all(clicon_handle h,
transaction_data_t *td) transaction_data_t *td)
{ {
int retval = -1; int retval = -1;
clixon_plugin *cp = NULL; clixon_plugin_t *cp = NULL;
while ((cp = clixon_plugin_each(h, cp)) != NULL) { while ((cp = clixon_plugin_each(h, cp)) != NULL) {
if (plugin_transaction_commit_done_one(cp, h, td) < 0) if (plugin_transaction_commit_done_one(cp, h, td) < 0)
@ -728,18 +728,18 @@ plugin_transaction_commit_done_all(clicon_handle h,
* @retval -1 Error * @retval -1 Error
*/ */
int int
plugin_transaction_end_one(clixon_plugin *cp, plugin_transaction_end_one(clixon_plugin_t *cp,
clicon_handle h, clicon_handle h,
transaction_data_t *td) transaction_data_t *td)
{ {
int retval = -1; int retval = -1;
trans_cb_t *fn; trans_cb_t *fn;
if ((fn = cp->cp_api.ca_trans_end) != NULL){ if ((fn = clixon_plugin_api_get(cp)->ca_trans_end) != NULL){
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__, cp->cp_name); __FUNCTION__, clixon_plugin_name_get(cp));
goto done; goto done;
} }
} }
@ -759,7 +759,7 @@ plugin_transaction_end_all(clicon_handle h,
transaction_data_t *td) transaction_data_t *td)
{ {
int retval = -1; int retval = -1;
clixon_plugin *cp = NULL; clixon_plugin_t *cp = NULL;
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)
@ -771,18 +771,18 @@ plugin_transaction_end_all(clicon_handle h,
} }
int int
plugin_transaction_abort_one(clixon_plugin *cp, plugin_transaction_abort_one(clixon_plugin_t *cp,
clicon_handle h, clicon_handle h,
transaction_data_t *td) transaction_data_t *td)
{ {
int retval = -1; int retval = -1;
trans_cb_t *fn; trans_cb_t *fn;
if ((fn = cp->cp_api.ca_trans_abort) != NULL){ if ((fn = clixon_plugin_api_get(cp)->ca_trans_abort) != NULL){
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__, cp->cp_name); __FUNCTION__, clixon_plugin_name_get(cp));
goto done; goto done;
} }
} }
@ -802,7 +802,7 @@ plugin_transaction_abort_all(clicon_handle h,
transaction_data_t *td) transaction_data_t *td)
{ {
int retval = -1; int retval = -1;
clixon_plugin *cp = NULL; clixon_plugin_t *cp = NULL;
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)

View file

@ -69,7 +69,7 @@ typedef struct {
/* /*
* Prototypes * Prototypes
*/ */
int clixon_plugin_reset_one(clixon_plugin *cp, clicon_handle h, char *db); int clixon_plugin_reset_one(clixon_plugin_t *cp, clicon_handle h, char *db);
int clixon_plugin_reset_all(clicon_handle h, char *db); int clixon_plugin_reset_all(clicon_handle h, char *db);
int clixon_plugin_pre_daemon_all(clicon_handle h); int clixon_plugin_pre_daemon_all(clicon_handle h);
@ -80,25 +80,25 @@ int clixon_plugin_statedata_all(clicon_handle h, yang_stmt *yspec, cvec *nsc, ch
transaction_data_t * transaction_new(void); transaction_data_t * transaction_new(void);
int transaction_free(transaction_data_t *); int transaction_free(transaction_data_t *);
int plugin_transaction_begin_one(clixon_plugin *cp, clicon_handle h, transaction_data_t *td); int plugin_transaction_begin_one(clixon_plugin_t *cp, clicon_handle h, transaction_data_t *td);
int plugin_transaction_begin_all(clicon_handle h, transaction_data_t *td); int plugin_transaction_begin_all(clicon_handle h, transaction_data_t *td);
int plugin_transaction_validate_one(clixon_plugin *cp, clicon_handle h, transaction_data_t *td); int plugin_transaction_validate_one(clixon_plugin_t *cp, clicon_handle h, transaction_data_t *td);
int plugin_transaction_validate_all(clicon_handle h, transaction_data_t *td); int plugin_transaction_validate_all(clicon_handle h, transaction_data_t *td);
int plugin_transaction_complete_one(clixon_plugin *cp, clicon_handle h, transaction_data_t *td); int plugin_transaction_complete_one(clixon_plugin_t *cp, clicon_handle h, transaction_data_t *td);
int plugin_transaction_complete_all(clicon_handle h, transaction_data_t *td); int plugin_transaction_complete_all(clicon_handle h, transaction_data_t *td);
int plugin_transaction_commit_one(clixon_plugin *cp, clicon_handle h, transaction_data_t *td); int plugin_transaction_commit_one(clixon_plugin_t *cp, clicon_handle h, transaction_data_t *td);
int plugin_transaction_commit_all(clicon_handle h, transaction_data_t *td); int plugin_transaction_commit_all(clicon_handle h, transaction_data_t *td);
int plugin_transaction_commit_done_one(clixon_plugin *cp, clicon_handle h, transaction_data_t *td); int plugin_transaction_commit_done_one(clixon_plugin_t *cp, clicon_handle h, transaction_data_t *td);
int plugin_transaction_commit_done_all(clicon_handle h, transaction_data_t *td); int plugin_transaction_commit_done_all(clicon_handle h, transaction_data_t *td);
int plugin_transaction_end_one(clixon_plugin *cp, clicon_handle h, transaction_data_t *td); int plugin_transaction_end_one(clixon_plugin_t *cp, clicon_handle h, transaction_data_t *td);
int plugin_transaction_end_all(clicon_handle h, transaction_data_t *td); int plugin_transaction_end_all(clicon_handle h, transaction_data_t *td);
int plugin_transaction_abort_one(clixon_plugin *cp, clicon_handle h, transaction_data_t *td); int plugin_transaction_abort_one(clixon_plugin_t *cp, clicon_handle h, transaction_data_t *td);
int plugin_transaction_abort_all(clicon_handle h, transaction_data_t *td); int plugin_transaction_abort_all(clicon_handle h, transaction_data_t *td);
#endif /* _BACKEND_PLUGIN_H_ */ #endif /* _BACKEND_PLUGIN_H_ */

View file

@ -300,13 +300,13 @@ backend_plugin_restconf_register(clicon_handle h,
yang_stmt *yspec) yang_stmt *yspec)
{ {
int retval = -1; int retval = -1;
clixon_plugin *cp = NULL; clixon_plugin_t *cp = NULL;
if (clixon_pseudo_plugin(h, "restconf pseudo plugin", &cp) < 0) if (clixon_pseudo_plugin(h, "restconf pseudo plugin", &cp) < 0)
goto done; goto done;
cp->cp_api.ca_trans_validate = restconf_pseudo_process_validate; clixon_plugin_api_get(cp)->ca_trans_validate = restconf_pseudo_process_validate;
cp->cp_api.ca_trans_commit = restconf_pseudo_process_commit; clixon_plugin_api_get(cp)->ca_trans_commit = restconf_pseudo_process_commit;
/* Register generic process-control of restconf daemon, ie start/stop restconf */ /* Register generic process-control of restconf daemon, ie start/stop restconf */
if (restconf_pseudo_process_control(h) < 0) if (restconf_pseudo_process_control(h) < 0)

View file

@ -214,7 +214,7 @@ transaction_print(FILE *f,
xn = td->td_avec[i]; xn = td->td_avec[i];
xml_print(f, xn); xml_print(f, xn);
} }
fprintf(stderr, "Changed\n=========\n"); fprintf(f, "Changed\n=========\n");
for (i=0; i<td->td_clen; i++){ for (i=0; i<td->td_clen; i++){
xn = td->td_scvec[i]; xn = td->td_scvec[i];
xml_print(f, xn); xml_print(f, xn);

View file

@ -41,7 +41,7 @@ CFLAGS = @CFLAGS@
LINKAGE = @LINKAGE@ LINKAGE = @LINKAGE@
CPPFLAGS = @CPPFLAGS@ CPPFLAGS = @CPPFLAGS@
ifeq ($(LINKAGE),dynamic) ifeq ($(LINKAGE),dynamic)
CPPFLAGS += -fPIC CPPFLAGS += -fPIC
endif endif
SH_SUFFIX = @SH_SUFFIX@ SH_SUFFIX = @SH_SUFFIX@
INSTALLFLAGS = @INSTALLFLAGS@ INSTALLFLAGS = @INSTALLFLAGS@
@ -66,10 +66,10 @@ CLIXON_MAJOR = @CLIXON_VERSION_MAJOR@
CLIXON_MINOR = @CLIXON_VERSION_MINOR@ CLIXON_MINOR = @CLIXON_VERSION_MINOR@
# Use this clixon lib for linking # Use this clixon lib for linking
ifeq ($(LINKAGE),dynamic) ifeq ($(LINKAGE),static)
CLIXON_LIB = libclixon$(SH_SUFFIX).$(CLIXON_MAJOR).$(CLIXON_MINOR)
else
CLIXON_LIB = libclixon.a CLIXON_LIB = libclixon.a
else
CLIXON_LIB = libclixon$(SH_SUFFIX).$(CLIXON_MAJOR).$(CLIXON_MINOR)
endif endif
# For dependency. A little strange that we rely on it being built in the src dir # For dependency. A little strange that we rely on it being built in the src dir
@ -78,7 +78,6 @@ LIBDEPS = $(top_srcdir)/lib/src/$(CLIXON_LIB)
LIBS = -L$(top_srcdir)/lib/src $(top_srcdir)/lib/src/$(CLIXON_LIB) @LIBS@ LIBS = -L$(top_srcdir)/lib/src $(top_srcdir)/lib/src/$(CLIXON_LIB) @LIBS@
INCLUDES = -I. -I$(top_srcdir)/lib -I$(top_srcdir)/include -I$(top_srcdir) @INCLUDES@ INCLUDES = -I. -I$(top_srcdir)/lib -I$(top_srcdir)/include -I$(top_srcdir) @INCLUDES@
# Name of application # Name of application
@ -118,6 +117,7 @@ $(top_srcdir)/lib/src/$(CLIXON_LIB):
clean: clean:
rm -f $(LIBOBJ) $(APPOBJ) *.core $(APPL) $(MYLIB) $(MYLIBSO) $(MYLIBLINK) test test.c rm -f $(LIBOBJ) $(APPOBJ) *.core $(APPL) $(MYLIB) $(MYLIBSO) $(MYLIBLINK) test test.c
rm -f *.gcda *.gcno *.gcov # coverage
distclean: clean distclean: clean
rm -f Makefile *~ .depend rm -f Makefile *~ .depend

View file

@ -178,7 +178,11 @@ cli_terminate(clicon_handle h)
xml_free(x); xml_free(x);
clicon_data_cvec_del(h, "cli-edit-cvv");; clicon_data_cvec_del(h, "cli-edit-cvv");;
xpath_optimize_exit(); xpath_optimize_exit();
cli_plugin_finish(h); /* Delete all plugins, and RPC callbacks */
clixon_plugin_module_exit(h);
/* Delete CLI syntax et al */
cli_plugin_finish(h);
cli_history_save(h); cli_history_save(h);
cli_handle_exit(h); cli_handle_exit(h);
clixon_err_exit(); clixon_err_exit();
@ -615,6 +619,10 @@ main(int argc,
*/ */
cv_exclude_keys(clicon_cli_varonly(h)); cv_exclude_keys(clicon_cli_varonly(h));
/* Initialize plugin module by creating a handle holding plugin and callback lists */
if (clixon_plugin_module_init(h) < 0)
goto done;
/* Load cli plugins before yangs are loaded (eg extension callbacks) */ /* Load cli plugins before yangs are loaded (eg extension callbacks) */
if ((dir = clicon_cli_dir(h)) != NULL && if ((dir = clicon_cli_dir(h)) != NULL &&
clixon_plugins_load(h, CLIXON_PLUGIN_INIT, dir, NULL) < 0) clixon_plugins_load(h, CLIXON_PLUGIN_INIT, dir, NULL) < 0)
@ -625,7 +633,6 @@ main(int argc,
*/ */
if (netconf_module_features(h) < 0) if (netconf_module_features(h) < 0)
goto done; goto done;
/* Set default namespace according to CLICON_NAMESPACE_NETCONF_DEFAULT */ /* Set default namespace according to CLICON_NAMESPACE_NETCONF_DEFAULT */
xml_nsctx_namespace_netconf_default(h); xml_nsctx_namespace_netconf_default(h);

View file

@ -271,7 +271,7 @@ cli_load_syntax_file(clicon_handle h,
char **vec = NULL; char **vec = NULL;
int i, nvec; int i, nvec;
char *plgnam; char *plgnam;
clixon_plugin *cp; clixon_plugin_t *cp;
if ((pt = pt_new()) == NULL){ if ((pt = pt_new()) == NULL){
clicon_err(OE_UNIX, errno, "pt_new"); clicon_err(OE_UNIX, errno, "pt_new");
@ -313,7 +313,7 @@ cli_load_syntax_file(clicon_handle h,
if (plgnam != NULL) { /* Find plugin for callback resolving */ if (plgnam != NULL) { /* Find plugin for callback resolving */
if ((cp = clixon_plugin_find(h, plgnam)) != NULL) if ((cp = clixon_plugin_find(h, plgnam)) != NULL)
handle = cp->cp_handle; handle = clixon_plugin_handle_get(cp);
if (handle == NULL){ if (handle == NULL){
clicon_err(OE_PLUGIN, 0, "CLICON_PLUGIN set to '%s' in %s but plugin %s.so not found in %s", clicon_err(OE_PLUGIN, 0, "CLICON_PLUGIN set to '%s' in %s but plugin %s.so not found in %s",
plgnam, filename, plgnam, plgnam, filename, plgnam,
@ -393,7 +393,7 @@ cli_syntax_load(clicon_handle h)
cli_syntaxmode_t *m; cli_syntaxmode_t *m;
cligen_susp_cb_t *fns = NULL; cligen_susp_cb_t *fns = NULL;
cligen_interrupt_cb_t *fni = NULL; cligen_interrupt_cb_t *fni = NULL;
clixon_plugin *cp; clixon_plugin_t *cp;
parse_tree *ptall = NULL; /* Universal CLIgen parse tree all modes */ parse_tree *ptall = NULL; /* Universal CLIgen parse tree all modes */
/* Syntax already loaded. XXX should we re-load?? */ /* Syntax already loaded. XXX should we re-load?? */
@ -457,10 +457,10 @@ cli_syntax_load(clicon_handle h)
/* Set susp and interrupt callbacks into CLIgen */ /* Set susp and interrupt callbacks into CLIgen */
cp = NULL; cp = NULL;
while ((cp = clixon_plugin_each(h, cp)) != NULL) { while ((cp = clixon_plugin_each(h, cp)) != NULL) {
if (fns==NULL && (fns = cp->cp_api.ca_suspend) != NULL) if (fns==NULL && (fns = clixon_plugin_api_get(cp)->ca_suspend) != NULL)
if (cli_susp_hook(h, fns) < 0) if (cli_susp_hook(h, fns) < 0)
goto done; goto done;
if (fni==NULL && (fni = cp->cp_api.ca_interrupt) != NULL) if (fni==NULL && (fni = clixon_plugin_api_get(cp)->ca_interrupt) != NULL)
if (cli_interrupt_hook(h, fni) < 0) if (cli_interrupt_hook(h, fni) < 0)
goto done; goto done;
} }
@ -469,7 +469,6 @@ cli_syntax_load(clicon_handle h)
retval = 0; retval = 0;
done: done:
if (retval != 0) { if (retval != 0) {
clixon_plugin_exit_all(h);
cli_syntax_unload(h); cli_syntax_unload(h);
cli_syntax_set(h, NULL); cli_syntax_set(h, NULL);
} }
@ -485,8 +484,6 @@ done:
int int
cli_plugin_finish(clicon_handle h) cli_plugin_finish(clicon_handle h)
{ {
/* Remove all CLI plugins */
clixon_plugin_exit_all(h);
/* Remove all cligen syntax modes */ /* Remove all cligen syntax modes */
cli_syntax_unload(h); cli_syntax_unload(h);
cli_syntax_set(h, NULL); cli_syntax_set(h, NULL);
@ -744,7 +741,7 @@ clicon_cliread(clicon_handle h,
cli_syntaxmode_t *mode; cli_syntaxmode_t *mode;
cli_syntax_t *stx; cli_syntax_t *stx;
cli_prompthook_t *fn; cli_prompthook_t *fn;
clixon_plugin *cp; clixon_plugin_t *cp;
char *promptstr; char *promptstr;
stx = cli_syntax(h); stx = cli_syntax(h);
@ -752,7 +749,7 @@ clicon_cliread(clicon_handle h,
/* Get prompt from plugin callback? */ /* Get prompt from plugin callback? */
cp = NULL; cp = NULL;
while ((cp = clixon_plugin_each(h, cp)) != NULL) { while ((cp = clixon_plugin_each(h, cp)) != NULL) {
if ((fn = cp->cp_api.ca_prompt) == NULL) if ((fn = clixon_plugin_api_get(cp)->ca_prompt) == NULL)
continue; continue;
pfmt = fn(h, mode->csm_name); pfmt = fn(h, mode->csm_name);
break; break;

View file

@ -111,6 +111,7 @@ $(top_srcdir)/lib/src/$(CLIXON_LIB):
clean: clean:
rm -f $(APPL) $(APPOBJ) $(LIBOBJ) *.core $(MYLIB) $(MYLIBSO) $(MYLIBLINK) rm -f $(APPL) $(APPOBJ) $(LIBOBJ) *.core $(MYLIB) $(MYLIBSO) $(MYLIBLINK)
rm -f *.gcda *.gcno *.gcov # coverage
distclean: clean distclean: clean
rm -f Makefile *~ .depend rm -f Makefile *~ .depend

View file

@ -584,8 +584,9 @@ netconf_terminate(clicon_handle h)
cvec *nsctx; cvec *nsctx;
cxobj *x; cxobj *x;
clixon_plugin_exit_all(h); /* Delete all plugins, and RPC callbacks */
rpc_callback_delete_all(h); clixon_plugin_module_exit(h);
clicon_rpc_close_session(h); clicon_rpc_close_session(h);
if ((yspec = clicon_dbspec_yang(h)) != NULL) if ((yspec = clicon_dbspec_yang(h)) != NULL)
ys_free(yspec); ys_free(yspec);
@ -796,6 +797,10 @@ main(int argc,
if (netconf_module_features(h) < 0) if (netconf_module_features(h) < 0)
goto done; goto done;
/* Initialize plugin module by creating a handle holding plugin and callback lists */
if (clixon_plugin_module_init(h) < 0)
goto done;
/* Create top-level yang spec and store as option */ /* Create top-level yang spec and store as option */
if ((yspec = yspec_new()) == NULL) if ((yspec = yspec_new()) == NULL)
goto done; goto done;

View file

@ -78,10 +78,9 @@ LIBDEPS = $(top_srcdir)/lib/src/$(CLIXON_LIB)
LIBS = -L$(top_srcdir)/lib/src $(top_srcdir)/lib/src/$(CLIXON_LIB) @LIBS@ LIBS = -L$(top_srcdir)/lib/src $(top_srcdir)/lib/src/$(CLIXON_LIB) @LIBS@
CPPFLAGS = @CPPFLAGS@
ifeq ($(LINKAGE),dynamic) ifeq ($(LINKAGE),dynamic)
CPPFLAGS = @CPPFLAGS@ -fPIC CPPFLAGS += -fPIC
else
CPPFLAGS = @CPPFLAGS@
endif endif
INCLUDES = -I. -I$(top_srcdir)/lib/src -I$(top_srcdir)/lib -I$(top_srcdir)/include -I$(top_srcdir) @INCLUDES@ INCLUDES = -I. -I$(top_srcdir)/lib/src -I$(top_srcdir)/lib -I$(top_srcdir)/include -I$(top_srcdir) @INCLUDES@
@ -139,6 +138,7 @@ $(top_srcdir)/lib/src/$(CLIXON_LIB):
clean: clean:
rm -f $(LIBOBJ) *.core $(APPL) $(APPOBJ) *.o $(MYLIB) $(MYLIBSO) $(MYLIBLINK) # extra .o to clean residue if with_restconf changes rm -f $(LIBOBJ) *.core $(APPL) $(APPOBJ) *.o $(MYLIB) $(MYLIBSO) $(MYLIBLINK) # extra .o to clean residue if with_restconf changes
rm -f *.gcda *.gcno *.gcov # coverage
distclean: clean distclean: clean
rm -f Makefile *~ .depend rm -f Makefile *~ .depend
@ -201,4 +201,3 @@ depend:
$(CC) $(DEPENDFLAGS) @DEFS@ $(INCLUDES) $(CFLAGS) -MM $(APPFCGI) $(APPSRC) > .depend $(CC) $(DEPENDFLAGS) @DEFS@ $(INCLUDES) $(CFLAGS) -MM $(APPFCGI) $(APPSRC) > .depend
#include .depend #include .depend

View file

@ -247,8 +247,9 @@ restconf_terminate(clicon_handle h)
clicon_debug(1, "%s", __FUNCTION__); clicon_debug(1, "%s", __FUNCTION__);
if ((fs = clicon_socket_get(h)) != -1) if ((fs = clicon_socket_get(h)) != -1)
close(fs); close(fs);
clixon_plugin_exit_all(h); /* Delete all plugins, and RPC callbacks */
rpc_callback_delete_all(h); clixon_plugin_module_exit(h);
clicon_rpc_close_session(h); clicon_rpc_close_session(h);
if ((yspec = clicon_dbspec_yang(h)) != NULL) if ((yspec = clicon_dbspec_yang(h)) != NULL)
ys_free(yspec); ys_free(yspec);

View file

@ -211,7 +211,7 @@ main(int argc,
char *stream_path; char *stream_path;
int finish = 0; int finish = 0;
char *str; char *str;
clixon_plugin *cp = NULL; clixon_plugin_t *cp = NULL;
uint32_t id = 0; uint32_t id = 0;
cvec *nsctx_global = NULL; /* Global namespace context */ cvec *nsctx_global = NULL; /* Global namespace context */
size_t cligen_buflen; size_t cligen_buflen;
@ -362,6 +362,10 @@ main(int argc,
/* Treat unknown XML as anydata */ /* Treat unknown XML as anydata */
if (clicon_option_bool(h, "CLICON_YANG_UNKNOWN_ANYDATA") == 1) if (clicon_option_bool(h, "CLICON_YANG_UNKNOWN_ANYDATA") == 1)
xml_bind_yang_unknown_anydata(1); xml_bind_yang_unknown_anydata(1);
/* Initialize plugin module by creating a handle holding plugin and callback lists */
if (clixon_plugin_module_init(h) < 0)
goto done;
/* Load restconf plugins before yangs are loaded (eg extension callbacks) */ /* Load restconf plugins before yangs are loaded (eg extension callbacks) */
if ((dir = clicon_restconf_dir(h)) != NULL) if ((dir = clicon_restconf_dir(h)) != NULL)
@ -372,7 +376,7 @@ main(int argc,
*/ */
if (clixon_pseudo_plugin(h, "pseudo restconf", &cp) < 0) if (clixon_pseudo_plugin(h, "pseudo restconf", &cp) < 0)
goto done; goto done;
cp->cp_api.ca_extension = restconf_main_extension_cb; clixon_plugin_api_get(cp)->ca_extension = restconf_main_extension_cb;
/* Load Yang modules /* Load Yang modules
* 1. Load a yang module as a specific absolute filename */ * 1. Load a yang module as a specific absolute filename */
@ -427,6 +431,9 @@ main(int argc,
if (dbg) if (dbg)
clicon_option_dump(h, dbg); clicon_option_dump(h, dbg);
/* Initialize plugin module by creating a handle holding plugin and callback lists */
if (clixon_plugin_module_init(h) < 0)
goto done;
/* Call start function in all plugins before we go interactive */ /* Call start function in all plugins before we go interactive */
if (clixon_plugin_start_all(h) < 0) if (clixon_plugin_start_all(h) < 0)
goto done; goto done;

View file

@ -1544,7 +1544,7 @@ restconf_clixon_init(clicon_handle h,
size_t cligen_buflen; size_t cligen_buflen;
size_t cligen_bufthreshold; size_t cligen_bufthreshold;
yang_stmt *yspec = NULL; yang_stmt *yspec = NULL;
clixon_plugin *cp = NULL; clixon_plugin_t *cp = NULL;
char *str; char *str;
cvec *nsctx_global = NULL; /* Global namespace context */ cvec *nsctx_global = NULL; /* Global namespace context */
cxobj *xrestconf; cxobj *xrestconf;
@ -1581,7 +1581,7 @@ restconf_clixon_init(clicon_handle h,
*/ */
if (clixon_pseudo_plugin(h, "pseudo restconf", &cp) < 0) if (clixon_pseudo_plugin(h, "pseudo restconf", &cp) < 0)
goto done; goto done;
cp->cp_api.ca_extension = restconf_main_extension_cb; clixon_plugin_api_get(cp)->ca_extension = restconf_main_extension_cb;
/* Load Yang modules /* Load Yang modules
* 1. Load a yang module as a specific absolute filename */ * 1. Load a yang module as a specific absolute filename */
@ -1614,7 +1614,6 @@ restconf_clixon_init(clicon_handle h,
/* Add netconf yang spec, used as internal protocol */ /* Add netconf yang spec, used as internal protocol */
if (netconf_module_load(h) < 0) if (netconf_module_load(h) < 0)
goto done; goto done;
/* Add system modules */ /* Add system modules */
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC8040") && if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC8040") &&
yang_spec_parse_module(h, "ietf-restconf-monitoring", NULL, yspec)< 0) yang_spec_parse_module(h, "ietf-restconf-monitoring", NULL, yspec)< 0)
@ -1847,6 +1846,9 @@ main(int argc,
if (dbg) if (dbg)
clicon_option_dump(h, dbg); clicon_option_dump(h, dbg);
/* Initialize plugin module by creating a handle holding plugin and callback lists */
if (clixon_plugin_module_init(h) < 0)
goto done;
/* Call start function in all plugins before we go interactive */ /* Call start function in all plugins before we go interactive */
if (clixon_plugin_start_all(h) < 0) if (clixon_plugin_start_all(h) < 0)
goto done; goto done;

View file

@ -32,6 +32,14 @@
# #
# ***** END LICENSE BLOCK ***** # ***** END LICENSE BLOCK *****
# #
# Note, for linkage=static, libclixon is linked twice:
# First static when building:
# libclixon_backend, libclixon_cli, libclixon_restconf and libclixon_netconf
# Second in this Makefile dynamic using -lclixon
# This means global variables used in plugin code is in separate domains and will not work
# Dont know enough about dynamic/static linkage to fix it.
# One way is to not use global variables in libraries, but there are still some, eg in error
# and log modules
VPATH = @srcdir@ VPATH = @srcdir@
srcdir = @srcdir@ srcdir = @srcdir@
top_srcdir = @top_srcdir@ top_srcdir = @top_srcdir@
@ -56,12 +64,12 @@ INSTALLFLAGS = @INSTALLFLAGS@
with_restconf = @with_restconf@ with_restconf = @with_restconf@
INCLUDES = -I$(includedir) @INCLUDES@ INCLUDES = -I$(includedir) @INCLUDES@
LINKAGE = @LINKAGE@
LDFLAGS = @LDFLAGS@ LDFLAGS = @LDFLAGS@
CPPFLAGS = @CPPFLAGS@ CPPFLAGS = @CPPFLAGS@
ifeq ($(LINKAGE),dynamic) ifeq ($(LINKAGE),dynamic)
CPPFLAGS += -fPIC CPPFLAGS += -fPIC
endif endif
LINKAGE = @LINKAGE@
BE_PLUGIN = $(APPNAME)_backend.so BE_PLUGIN = $(APPNAME)_backend.so
BE2_PLUGIN = $(APPNAME)_backend_nacm.so BE2_PLUGIN = $(APPNAME)_backend_nacm.so
@ -93,7 +101,7 @@ BE_SRC = $(APPNAME)_backend.c
BE_OBJ = $(BE_SRC:%.c=%.o) BE_OBJ = $(BE_SRC:%.c=%.o)
$(BE_PLUGIN): $(BE_OBJ) $(BE_PLUGIN): $(BE_OBJ)
ifeq ($(LINKAGE),static) ifeq ($(LINKAGE),static)
$(CC) -Wall -shared $(LDFLAGS) -o $@ -lc $< -lclixon -lclixon_backend $(CC) -Wall -shared $(LDFLAGS) -o $@ -lc $< -lclixon -L ../../apps/backend/ -lclixon_backend
else else
$(CC) -Wall -shared $(LDFLAGS) -o $@ -lc $< -lclixon -lclixon_backend $(CC) -Wall -shared $(LDFLAGS) -o $@ -lc $< -lclixon -lclixon_backend
endif endif
@ -103,7 +111,7 @@ BE2_SRC = $(APPNAME)_backend_nacm.c
BE2_OBJ = $(BE2_SRC:%.c=%.o) BE2_OBJ = $(BE2_SRC:%.c=%.o)
$(BE2_PLUGIN): $(BE2_OBJ) $(BE2_PLUGIN): $(BE2_OBJ)
ifeq ($(LINKAGE),static) ifeq ($(LINKAGE),static)
$(CC) -Wall -shared $(LDFLAGS) -o $@ -lc $< -lclixon -lclixon_backend $(CC) -Wall -shared $(LDFLAGS) -o $@ -lc $< -lclixon -L ../../apps/backend/ -lclixon_backend
else else
$(CC) -Wall -shared $(LDFLAGS) -o $@ -lc $< -lclixon -lclixon_backend $(CC) -Wall -shared $(LDFLAGS) -o $@ -lc $< -lclixon -lclixon_backend
endif endif
@ -147,6 +155,7 @@ OBJS += $(RESTCONF_OBJ)
clean: clean:
rm -f $(PLUGINS) $(OBJS) rm -f $(PLUGINS) $(OBJS)
rm -f *.gcda *.gcno *.gcov # coverage
distclean: clean distclean: clean
rm -f Makefile *~ .depend rm -f Makefile *~ .depend

View file

@ -312,14 +312,9 @@ struct clixon_plugin_api{
typedef struct clixon_plugin_api clixon_plugin_api; typedef struct clixon_plugin_api clixon_plugin_api;
/* Internal plugin structure with dlopen() handle and plugin_api /* This is the external handle type exposed in the API.
*/ * The internal struct is defined in clixon_plugin.c */
struct clixon_plugin{ typedef struct clixon_plugin clixon_plugin_t;
char cp_name[MAXPATHLEN]; /* Plugin filename. Note api ca_name is given by plugin itself */
plghndl_t cp_handle; /* Handle to plugin using dlopen(3) */
clixon_plugin_api cp_api;
};
typedef struct clixon_plugin clixon_plugin;
/* /*
* Prototypes * Prototypes
@ -333,42 +328,43 @@ typedef struct clixon_plugin clixon_plugin;
*/ */
clixon_plugin_api *clixon_plugin_init(clicon_handle h); clixon_plugin_api *clixon_plugin_init(clicon_handle h);
clixon_plugin *clixon_plugin_each(clicon_handle h, clixon_plugin *cpprev);
clixon_plugin *clixon_plugin_each_revert(clicon_handle h, clixon_plugin *cpprev, int nr); clixon_plugin_api *clixon_plugin_api_get(clixon_plugin_t *cp);
char *clixon_plugin_name_get(clixon_plugin_t *cp);
plghndl_t clixon_plugin_handle_get(clixon_plugin_t *cp);
clixon_plugin *clixon_plugin_find(clicon_handle h, const char *name); clixon_plugin_t *clixon_plugin_each(clicon_handle h, clixon_plugin_t *cpprev);
clixon_plugin_t *clixon_plugin_each_revert(clicon_handle h, clixon_plugin_t *cpprev, int nr);
clixon_plugin_t *clixon_plugin_find(clicon_handle h, const char *name);
int clixon_plugins_load(clicon_handle h, const char *function, const char *dir, const char *regexp); int clixon_plugins_load(clicon_handle h, const char *function, const char *dir, const char *regexp);
int clixon_pseudo_plugin(clicon_handle h, const char *name, clixon_plugin **cpp); int clixon_pseudo_plugin(clicon_handle h, const char *name, clixon_plugin_t **cpp);
int clixon_plugin_start_one(clixon_plugin *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);
int clixon_plugin_exit_one(clixon_plugin *cp, clicon_handle h);
int clixon_plugin_exit_all(clicon_handle h);
int clixon_plugin_auth_all(clicon_handle h, void *req, clixon_auth_type_t auth_type, char **authp); int clixon_plugin_auth_all(clicon_handle h, void *req, clixon_auth_type_t auth_type, char **authp);
int clixon_plugin_extension_one(clixon_plugin *cp, clicon_handle h, yang_stmt *yext, yang_stmt *ys); int clixon_plugin_extension_one(clixon_plugin_t *cp, clicon_handle h, yang_stmt *yext, yang_stmt *ys);
int clixon_plugin_extension_all(clicon_handle h, yang_stmt *yext, yang_stmt *ys); int clixon_plugin_extension_all(clicon_handle h, yang_stmt *yext, yang_stmt *ys);
int clixon_plugin_datastore_upgrade_one(clixon_plugin *cp, clicon_handle h, const char *db, cxobj *xt, modstate_diff_t *msd); int clixon_plugin_datastore_upgrade_one(clixon_plugin_t *cp, clicon_handle h, const char *db, cxobj *xt, modstate_diff_t *msd);
int clixon_plugin_datastore_upgrade_all(clicon_handle h, const char *db, cxobj *xt, modstate_diff_t *msd); int clixon_plugin_datastore_upgrade_all(clicon_handle h, const char *db, cxobj *xt, modstate_diff_t *msd);
/* rpc callback API */ /* rpc callback API */
int rpc_callback_register(clicon_handle h, clicon_rpc_cb cb, void *arg, const char *ns, const char *name); int rpc_callback_register(clicon_handle h, clicon_rpc_cb cb, void *arg, const char *ns, const char *name);
int rpc_callback_delete_all(clicon_handle h);
int rpc_callback_call(clicon_handle h, cxobj *xe, cbuf *cbret, void *arg); int rpc_callback_call(clicon_handle h, cxobj *xe, cbuf *cbret, void *arg);
/* upgrade callback API */ /* upgrade callback API */
int upgrade_callback_reg_fn(clicon_handle h, clicon_upgrade_cb cb, const char *strfn, const char *ns, void *arg); int upgrade_callback_reg_fn(clicon_handle h, clicon_upgrade_cb cb, const char *strfn, const char *ns, void *arg);
int upgrade_callback_delete_all(clicon_handle h);
int upgrade_callback_call(clicon_handle h, cxobj *xt, char *ns, uint16_t op, uint32_t from, uint32_t to, cbuf *cbret); int upgrade_callback_call(clicon_handle h, cxobj *xt, char *ns, uint16_t op, uint32_t from, uint32_t to, cbuf *cbret);
const int clixon_auth_type_str2int(char *auth_type); const int clixon_auth_type_str2int(char *auth_type);
const char *clixon_auth_type_int2str(clixon_auth_type_t auth_type); const char *clixon_auth_type_int2str(clixon_auth_type_t auth_type);
int clixon_plugin_module_init(clicon_handle h);
int clixon_plugin_module_exit(clicon_handle h);
#endif /* _CLIXON_PLUGIN_H_ */ #endif /* _CLIXON_PLUGIN_H_ */

View file

@ -155,7 +155,9 @@ typedef enum yang_class yang_class;
struct xml; struct xml;
typedef struct yang_stmt yang_stmt; /* Defined in clixon_yang_internal */ /* This is the external handle type exposed in the API.
* The internal struct is defined in clixon_yang_internal.h */
typedef struct yang_stmt yang_stmt;
/*! Yang apply function worker /*! Yang apply function worker
* @param[in] yn yang node * @param[in] yn yang node

View file

@ -128,6 +128,7 @@ clean:
rm -f lex.clixon_xpath_parse.c rm -f lex.clixon_xpath_parse.c
rm -f lex.clixon_api_path_parse.c rm -f lex.clixon_api_path_parse.c
rm -f lex.clixon_instance_id_parse.c rm -f lex.clixon_instance_id_parse.c
rm -f *.gcda *.gcno *.gcov # coverage
############################################################################# #############################################################################
# Implicit rules for lex and yacc. # Implicit rules for lex and yacc.

View file

@ -46,7 +46,6 @@
#include <dlfcn.h> #include <dlfcn.h>
#include <dirent.h> #include <dirent.h>
#include <syslog.h> #include <syslog.h>
#include <assert.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/param.h> #include <sys/param.h>
@ -67,12 +66,128 @@
#include "clixon_yang_module.h" #include "clixon_yang_module.h"
#include "clixon_plugin.h" #include "clixon_plugin.h"
/* List of plugins XXX /*
* 1. Place in clixon handle not global variables * Private types
* 2. Use qelem circular lists
*/ */
static clixon_plugin *_clixon_plugins = NULL; /* List of plugins (of client) */
static int _clixon_nplugins = 0; /* Number of plugins */ /* Internal plugin structure with dlopen() handle and plugin_api
* This is an internal type, not exposed in the API
* The external type is "clixon_plugin_t" defined in clixon_plugin.h
*/
struct clixon_plugin{
qelem_t cp_q; /* queue header */
char cp_name[MAXPATHLEN]; /* Plugin filename. Note api ca_name is given by plugin itself */
plghndl_t cp_handle; /* Handle to plugin using dlopen(3) */
clixon_plugin_api cp_api;
};
/*
* RPC callbacks for both client/frontend and backend plugins.
* RPC callbacks are explicitly registered in the plugin_init() function
* with a tag and a function
* When the the tag is encountered, the callback is called.
* Primarily backend, but also netconf and restconf frontend plugins.
* CLI frontend so far have direct callbacks, ie functions in the cligen
* specification are directly dlsym:ed to the CLI plugin.
* It would be possible to use this rpc registering API for CLI plugins as well.
*
* When namespace and name match, the callback is made
*/
typedef struct {
qelem_t rc_qelem; /* List header */
clicon_rpc_cb rc_callback; /* RPC Callback */
void *rc_arg; /* Application specific argument to cb */
char *rc_namespace;/* Namespace to combine with name tag */
char *rc_name; /* Xml/json tag/name */
} rpc_callback_t;
/*
* Upgrade callbacks for backend upgrade of datastore
* Register upgrade callbacks in plugin_init() with a module and a "from" and "to"
* revision.
*/
typedef struct {
qelem_t uc_qelem; /* List header */
clicon_upgrade_cb uc_callback; /* RPC Callback */
const char *uc_fnstr; /* Stringified fn name for debug */
void *uc_arg; /* Application specific argument to cb */
char *uc_namespace; /* Module namespace */
} upgrade_callback_t;
/* Internal struct for accessing plugin list and rpc list. This handle is accessed
* via clixon-handle "cdata" structure (see clixon_data.h) using the key "clixon-plugin-handle"."
* It is just a way to avoid using global variables
*/
struct plugin_module_struct {
clixon_plugin_t *ms_plugin_list;
rpc_callback_t *ms_rpc_callbacks;
upgrade_callback_t *ms_upgrade_callbacks;
};
typedef struct plugin_module_struct plugin_module_struct;
/*! Get plugin handle containing plugin and callback lists
* @param[in] h Clicon handle
*/
static plugin_module_struct *
plugin_module_struct_get(clicon_handle h)
{
clicon_hash_t *cdat = clicon_data(h);
size_t len;
void *p;
if ((p = clicon_hash_value(cdat, "plugin-module-struct", &len)) != NULL)
return *(plugin_module_struct **)p;
return NULL;
}
/*! Set plugin handle containing plugin and callback lists
* @param[in] h Clicon handle
* @param[in] pl Clixon plugin handle
*/
static int
plugin_module_struct_set(clicon_handle h,
plugin_module_struct *ms)
{
clicon_hash_t *cdat = clicon_data(h);
/* It is the pointer to ys that should be copied by hash,
so we send a ptr to the ptr to indicate what to copy.
*/
if (clicon_hash_add(cdat, "plugin-module-struct", &ms, sizeof(ms)) == NULL)
return -1;
return 0;
}
/* Access functions */
/*! Get plugin api
* @param[in] cp Clixon plugin handle
*/
clixon_plugin_api *
clixon_plugin_api_get(clixon_plugin_t *cp)
{
return &cp->cp_api;
}
/*! Get plugin name
* @param[in] cp Clixon plugin handle
*/
char *
clixon_plugin_name_get(clixon_plugin_t *cp)
{
return cp->cp_name;
}
/*! Get plugin handle
* @param[in] cp Clixon plugin handle
*/
plghndl_t
clixon_plugin_handle_get(clixon_plugin_t *cp)
{
return cp->cp_handle;
}
/*! Iterator over clixon plugins /*! Iterator over clixon plugins
* *
@ -87,27 +202,24 @@ static int _clixon_nplugins = 0; /* Number of plugins */
* ... * ...
* } * }
* @endcode * @endcode
* @note Not optimized, alwasy iterates from the start of the list * @note Not optimized, always iterates from the start of the list
*/ */
clixon_plugin * clixon_plugin_t *
clixon_plugin_each(clicon_handle h, clixon_plugin_each(clicon_handle h,
clixon_plugin *cpprev) clixon_plugin_t *cpprev)
{ {
int i; clixon_plugin_t *cpnext = NULL;
clixon_plugin *cp; plugin_module_struct *ms = plugin_module_struct_get(h);
clixon_plugin *cpnext = NULL;
if (cpprev == NULL) /* ms == NULL means plugins are not yet initialized */
cpnext = _clixon_plugins; if (ms == NULL || ms->ms_plugin_list == NULL)
cpnext = NULL;
else if (cpprev == NULL)
cpnext = ms->ms_plugin_list;
else{ else{
for (i = 0; i < _clixon_nplugins; i++) { cpnext = NEXTQ(clixon_plugin_t *, cpprev);
cp = &_clixon_plugins[i]; if (cpnext == ms->ms_plugin_list)
if (cp == cpprev) cpnext = NULL;
break;
cp = NULL;
}
if (cp && i < _clixon_nplugins-1)
cpnext = &_clixon_plugins[i+1];
} }
return cpnext; return cpnext;
} }
@ -118,38 +230,47 @@ clixon_plugin_each(clicon_handle h,
* same object recursively * same object recursively
* *
* @param[in] h Clicon handle * @param[in] h Clicon handle
* @param[in] plugin previous plugin, or NULL on init * @param[in] plugin previous plugin, or NULL on init
* @param[in] nr Start from this nr <= lngth of list
* @code * @code
* clicon_plugin *cp = NULL; * clicon_plugin_t *cp = NULL;
* while ((cp = clixon_plugin_each_revert(h, cp, nr)) != NULL) { * while ((cp = clixon_plugin_each_revert(h, cp, nr)) != NULL) {
* ... * ...
* } * }
* @endcode * @endcode
* @note Not optimized, alwasy iterates from the start of the list * @note Not optimized, always iterates from the start of the list
*/ */
clixon_plugin * clixon_plugin_t *
clixon_plugin_each_revert(clicon_handle h, clixon_plugin_each_revert(clicon_handle h,
clixon_plugin *cpprev, clixon_plugin_t *cpprev,
int nr) int nr)
{ {
int i; int i;
clixon_plugin *cp = NULL; clixon_plugin_t *cpnext = NULL;
clixon_plugin *cpnext = NULL; plugin_module_struct *ms = plugin_module_struct_get(h);
if (cpprev == NULL){ if (ms == NULL){
if (nr>0) clicon_err(OE_PLUGIN, EINVAL, "plugin module not initialized");
cpnext = &_clixon_plugins[nr-1]; return NULL;
}
if (ms->ms_plugin_list == NULL)
cpnext = NULL;
else if (cpprev == NULL){
cpnext = ms->ms_plugin_list;
for (i = nr-1; i > 0; i--) {
cpnext = NEXTQ(clixon_plugin_t *, cpnext);
if (cpnext == ms->ms_plugin_list){
cpnext = NULL;
break;
}
}
} }
else{ else{
for (i = nr-1; i >= 0; i--) { if (cpprev == ms->ms_plugin_list)
cp = &_clixon_plugins[i]; cpnext = NULL;
if (cp == cpprev) else
break; cpnext = PREVQ(clixon_plugin_t *, cpprev);
cp = NULL; }
}
if (cp && i > 0)
cpnext = &_clixon_plugins[i-1];
}
return cpnext; return cpnext;
} }
@ -159,21 +280,27 @@ clixon_plugin_each_revert(clicon_handle h,
* @retval p Plugin if found * @retval p Plugin if found
* @retval NULL Not found * @retval NULL Not found
* @code * @code
* clixon_plugin *cp; * clixon_plugin_t *cp;
* cp = clixon_plugin_find(h, "plugin-name"); * cp = clixon_plugin_find(h, "plugin-name");
* @endcode * @endcode
*/ */
clixon_plugin * clixon_plugin_t *
clixon_plugin_find(clicon_handle h, clixon_plugin_find(clicon_handle h,
const char *name) const char *name)
{ {
int i; clixon_plugin_t *cp = NULL;
clixon_plugin *cp = NULL; plugin_module_struct *ms = plugin_module_struct_get(h);
for (i = 0; i < _clixon_nplugins; i++) { if (ms == NULL){
cp = &_clixon_plugins[i]; clicon_err(OE_PLUGIN, EINVAL, "plugin module not initialized");
if (strcmp(cp->cp_name, name) == 0) return NULL;
return cp; }
if ((cp = ms->ms_plugin_list) != NULL){
do {
if (strcmp(cp->cp_name, name) == 0)
return cp;
cp = NEXTQ(clixon_plugin_t *, cp);
} while (cp && cp != ms->ms_plugin_list);
} }
return NULL; return NULL;
} }
@ -194,14 +321,14 @@ plugin_load_one(clicon_handle h,
char *file, /* note modified */ char *file, /* note modified */
const char *function, const char *function,
int dlflags, int dlflags,
clixon_plugin **cpp) clixon_plugin_t **cpp)
{ {
int retval = -1; int retval = -1;
char *error; char *error;
void *handle = NULL; void *handle = NULL;
plginit2_t *initfn; plginit2_t *initfn;
clixon_plugin_api *api = NULL; clixon_plugin_api *api = NULL;
clixon_plugin *cp = NULL; clixon_plugin_t *cp = NULL;
char *name; char *name;
char *p; char *p;
@ -234,7 +361,7 @@ plugin_load_one(clicon_handle h,
} }
} }
/* 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 *)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");
goto done; goto done;
} }
@ -249,13 +376,13 @@ plugin_load_one(clicon_handle h,
snprintf(cp->cp_name, sizeof(cp->cp_name), "%*s", snprintf(cp->cp_name, sizeof(cp->cp_name), "%*s",
(int)strlen(name), name); (int)strlen(name), name);
cp->cp_api = *api; cp->cp_api = *api;
clicon_debug(1, "%s", __FUNCTION__);
if (cp){ if (cp){
*cpp = cp; *cpp = cp;
cp = NULL; cp = NULL;
} }
retval = 1; retval = 1;
done: done:
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
if (retval != 1 && handle) if (retval != 1 && handle)
dlclose(handle); dlclose(handle);
if (cp) if (cp)
@ -282,10 +409,15 @@ clixon_plugins_load(clicon_handle h,
struct dirent *dp = NULL; struct dirent *dp = NULL;
int i; int i;
char filename[MAXPATHLEN]; char filename[MAXPATHLEN];
clixon_plugin *cp = NULL; clixon_plugin_t *cp = NULL;
int ret; int ret;
plugin_module_struct *ms = plugin_module_struct_get(h);
clicon_debug(1, "%s", __FUNCTION__); clicon_debug(1, "%s", __FUNCTION__);
if (ms == NULL){
clicon_err(OE_PLUGIN, EINVAL, "plugin module not initialized");
goto done;
}
/* Get plugin objects names from plugin directory */ /* Get plugin objects names from plugin directory */
if((ndp = clicon_file_dirent(dir, &dp, regexp?regexp:"(.so)$", S_IFREG)) < 0) if((ndp = clicon_file_dirent(dir, &dp, regexp?regexp:"(.so)$", S_IFREG)) < 0)
goto done; goto done;
@ -298,13 +430,7 @@ clixon_plugins_load(clicon_handle h,
goto done; goto done;
if (ret == 0) if (ret == 0)
continue; continue;
_clixon_nplugins++; ADDQ(cp, ms->ms_plugin_list);
if ((_clixon_plugins = realloc(_clixon_plugins, _clixon_nplugins*sizeof(clixon_plugin))) == NULL) {
clicon_err(OE_UNIX, errno, "realloc");
goto done;
}
_clixon_plugins[_clixon_nplugins-1] = *cp;
free(cp);
} }
retval = 0; retval = 0;
done: done:
@ -320,39 +446,37 @@ done:
* @retval 0 OK, with cpp set * @retval 0 OK, with cpp set
* @retval -1 Error * @retval -1 Error
* @code * @code
* clixon_plugin *cp = NULL; * clixon_plugin_t *cp = NULL;
* if (clixon_pseudo_plugin(h, "pseudo plugin", &cp) < 0) * if (clixon_pseudo_plugin(h, "pseudo plugin", &cp) < 0)
* err; * err;
* cp->cp_api.ca_extension = my_ext_cb; * cp->cp_api.ca_extension = my_ext_cb;
* @endcode * @endcode
*/ */
int int
clixon_pseudo_plugin(clicon_handle h, clixon_pseudo_plugin(clicon_handle h,
const char *name, const char *name,
clixon_plugin **cpp) clixon_plugin_t **cpp)
{ {
int retval = -1; int retval = -1;
clixon_plugin *cp = NULL; clixon_plugin_t *cp = NULL;
plugin_module_struct *ms = plugin_module_struct_get(h);
clicon_debug(1, "%s %s", __FUNCTION__, name); clicon_debug(1, "%s %s", __FUNCTION__, name);
if (ms == NULL){
clicon_err(OE_PLUGIN, EINVAL, "plugin module not initialized");
goto done;
}
/* Create a pseudo plugins */ /* Create a pseudo plugins */
/* 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 *)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");
goto done; goto done;
} }
memset(cp, 0, sizeof(struct clixon_plugin)); memset(cp, 0, sizeof(struct clixon_plugin));
snprintf(cp->cp_name, sizeof(cp->cp_name), "%*s", (int)strlen(name), name); snprintf(cp->cp_name, sizeof(cp->cp_name), "%*s", (int)strlen(name), name);
ADDQ(cp, ms->ms_plugin_list);
_clixon_nplugins++; *cpp = cp;
if ((_clixon_plugins = realloc(_clixon_plugins, _clixon_nplugins*sizeof(clixon_plugin))) == NULL) { cp = NULL;
clicon_err(OE_UNIX, errno, "realloc");
goto done;
}
_clixon_plugins[_clixon_nplugins-1] = *cp;
*cpp = &_clixon_plugins[_clixon_nplugins-1];
retval = 0; retval = 0;
done: done:
if (cp) if (cp)
@ -367,7 +491,7 @@ done:
* @retval -1 Error * @retval -1 Error
*/ */
int int
clixon_plugin_start_one(clixon_plugin *cp, clixon_plugin_start_one(clixon_plugin_t *cp,
clicon_handle h) clicon_handle h)
{ {
int retval = -1; int retval = -1;
@ -395,7 +519,7 @@ int
clixon_plugin_start_all(clicon_handle h) clixon_plugin_start_all(clicon_handle h)
{ {
int retval = -1; int retval = -1;
clixon_plugin *cp = NULL; clixon_plugin_t *cp = NULL;
while ((cp = clixon_plugin_each(h, cp)) != NULL) { while ((cp = clixon_plugin_each(h, cp)) != NULL) {
if (clixon_plugin_start_one(cp, h) < 0) if (clixon_plugin_start_one(cp, h) < 0)
@ -413,8 +537,8 @@ clixon_plugin_start_all(clicon_handle h)
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
*/ */
int static int
clixon_plugin_exit_one(clixon_plugin *cp, clixon_plugin_exit_one(clixon_plugin_t *cp,
clicon_handle h) clicon_handle h)
{ {
int retval = -1; int retval = -1;
@ -443,21 +567,21 @@ clixon_plugin_exit_one(clixon_plugin *cp,
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
*/ */
int static int
clixon_plugin_exit_all(clicon_handle h) clixon_plugin_exit_all(clicon_handle h)
{ {
int retval = -1; int retval = -1;
clixon_plugin *cp = NULL; clixon_plugin_t *cp = NULL;
plugin_module_struct *ms = plugin_module_struct_get(h);
while ((cp = clixon_plugin_each(h, cp)) != NULL) {
if (clixon_plugin_exit_one(cp, h) < 0) if (ms != NULL){
goto done; while ((cp = ms->ms_plugin_list) != NULL){
DELQ(cp, ms->ms_plugin_list, clixon_plugin_t *);
if (clixon_plugin_exit_one(cp, h) < 0)
goto done;
free(cp);
}
} }
if (_clixon_plugins){
free(_clixon_plugins);
_clixon_plugins = NULL;
}
_clixon_nplugins = 0;
retval = 0; retval = 0;
done: done:
return retval; return retval;
@ -477,7 +601,7 @@ clixon_plugin_exit_all(clicon_handle h)
* Or no callback was found. * Or no callback was found.
*/ */
static int static int
clixon_plugin_auth_one(clixon_plugin *cp, clixon_plugin_auth_one(clixon_plugin_t *cp,
clicon_handle h, clicon_handle h,
void *req, void *req,
clixon_auth_type_t auth_type, clixon_auth_type_t auth_type,
@ -523,7 +647,7 @@ clixon_plugin_auth_all(clicon_handle h,
char **authp) char **authp)
{ {
int retval = -1; int retval = -1;
clixon_plugin *cp = NULL; clixon_plugin_t *cp = NULL;
int ret = 0; int ret = 0;
clicon_debug(1, "%s", __FUNCTION__); clicon_debug(1, "%s", __FUNCTION__);
@ -556,7 +680,7 @@ clixon_plugin_auth_all(clicon_handle h,
* @retval -1 Error * @retval -1 Error
*/ */
int int
clixon_plugin_extension_one(clixon_plugin *cp, clixon_plugin_extension_one(clixon_plugin_t *cp,
clicon_handle h, clicon_handle h,
yang_stmt *yext, yang_stmt *yext,
yang_stmt *ys) yang_stmt *ys)
@ -595,7 +719,7 @@ clixon_plugin_extension_all(clicon_handle h,
yang_stmt *ys) yang_stmt *ys)
{ {
int retval = -1; int retval = -1;
clixon_plugin *cp = NULL; clixon_plugin_t *cp = NULL;
while ((cp = clixon_plugin_each(h, cp)) != NULL) { while ((cp = clixon_plugin_each(h, cp)) != NULL) {
if (clixon_plugin_extension_one(cp, h, yext, ys) < 0) if (clixon_plugin_extension_one(cp, h, yext, ys) < 0)
@ -618,7 +742,7 @@ clixon_plugin_extension_all(clicon_handle h,
* Upgrade datastore on load before or as an alternative to module-specific upgrading mechanism * Upgrade datastore on load before or as an alternative to module-specific upgrading mechanism
*/ */
int int
clixon_plugin_datastore_upgrade_one(clixon_plugin *cp, clixon_plugin_datastore_upgrade_one(clixon_plugin_t *cp,
clicon_handle h, clicon_handle h,
const char *db, const char *db,
cxobj *xt, cxobj *xt,
@ -658,7 +782,7 @@ clixon_plugin_datastore_upgrade_all(clicon_handle h,
modstate_diff_t *msd) modstate_diff_t *msd)
{ {
int retval = -1; int retval = -1;
clixon_plugin *cp = NULL; clixon_plugin_t *cp = NULL;
while ((cp = clixon_plugin_each(h, cp)) != NULL) { while ((cp = clixon_plugin_each(h, cp)) != NULL) {
if (clixon_plugin_datastore_upgrade_one(cp, h, db, xt, msd) < 0) if (clixon_plugin_datastore_upgrade_one(cp, h, db, xt, msd) < 0)
@ -671,41 +795,21 @@ clixon_plugin_datastore_upgrade_all(clicon_handle h,
/*-------------------------------------------------------------------- /*--------------------------------------------------------------------
* RPC callbacks for both client/frontend and backend plugins. * RPC callbacks for both client/frontend and backend plugins.
* RPC callbacks are explicitly registered in the plugin_init() function
* with a tag and a function
* When the the tag is encountered, the callback is called.
* Primarily backend, but also netconf and restconf frontend plugins.
* CLI frontend so far have direct callbacks, ie functions in the cligen
* specification are directly dlsym:ed to the CLI plugin.
* It would be possible to use this rpc registering API for CLI plugins as well.
*
* When namespace and name match, the callback is made
*/ */
typedef struct {
qelem_t rc_qelem; /* List header */
clicon_rpc_cb rc_callback; /* RPC Callback */
void *rc_arg; /* Application specific argument to cb */
char *rc_namespace;/* Namespace to combine with name tag */
char *rc_name; /* Xml/json tag/name */
} rpc_callback_t;
/* List of rpc callback entries XXX hang on handle */
static rpc_callback_t *rpc_cb_list = NULL;
#if 0 /* Debugging */ #if 0 /* Debugging */
static int static int
rpc_callback_dump(clicon_handle h, rpc_callback_dump(clicon_handle h)
FILE *f)
{ {
rpc_callback_t *rc; rpc_callback_t *rc;
plugin_module_struct *ms = plugin_module_struct_get(h);
if ((rc = rpc_cb_list) != NULL) clicon_debug(1, "%s--------------", __FUNCTION__);
if ((rc = ms->ms_rpc_callbacks) != NULL)
do { do {
fprintf(f, "%s %s\n", __FUNCTION__, rc->rc_name); clicon_debug(1, "%s %s", __FUNCTION__, rc->rc_name);
rc = NEXTQ(rpc_callback_t *, rc); rc = NEXTQ(rpc_callback_t *, rc);
} while (rc != rpc_cb_list); } while (rc != ms->ms_rpc_callbacks);
fprintf(f, "%s--------------\n", __FUNCTION__);
return 0; return 0;
} }
#endif #endif
@ -729,7 +833,13 @@ rpc_callback_register(clicon_handle h,
const char *name) const char *name)
{ {
rpc_callback_t *rc = NULL; rpc_callback_t *rc = NULL;
plugin_module_struct *ms = plugin_module_struct_get(h);
clicon_debug(1, "%s %s", __FUNCTION__, name);
if (ms == NULL){
clicon_err(OE_PLUGIN, EINVAL, "plugin module not initialized");
goto done;
}
if (name == NULL || ns == NULL){ if (name == NULL || ns == NULL){
clicon_err(OE_DB, EINVAL, "name or namespace NULL"); clicon_err(OE_DB, EINVAL, "name or namespace NULL");
goto done; goto done;
@ -743,7 +853,7 @@ rpc_callback_register(clicon_handle h,
rc->rc_arg = arg; rc->rc_arg = arg;
rc->rc_namespace = strdup(ns); rc->rc_namespace = strdup(ns);
rc->rc_name = strdup(name); rc->rc_name = strdup(name);
ADDQ(rc, rpc_cb_list); ADDQ(rc, ms->ms_rpc_callbacks);
return 0; return 0;
done: done:
if (rc){ if (rc){
@ -758,19 +868,21 @@ rpc_callback_register(clicon_handle h,
/*! Delete all RPC callbacks /*! Delete all RPC callbacks
*/ */
int static int
rpc_callback_delete_all(clicon_handle h) rpc_callback_delete_all(clicon_handle h)
{ {
rpc_callback_t *rc; rpc_callback_t *rc;
plugin_module_struct *ms = plugin_module_struct_get(h);
while((rc = rpc_cb_list) != NULL) { if (ms != NULL)
DELQ(rc, rpc_cb_list, rpc_callback_t *); while((rc = ms->ms_rpc_callbacks) != NULL) {
if (rc->rc_namespace) DELQ(rc, ms->ms_rpc_callbacks, rpc_callback_t *);
free(rc->rc_namespace); if (rc->rc_namespace)
if (rc->rc_name) free(rc->rc_namespace);
free(rc->rc_name); if (rc->rc_name)
free(rc); free(rc->rc_name);
} free(rc);
}
return 0; return 0;
} }
@ -800,25 +912,28 @@ rpc_callback_call(clicon_handle h,
char *prefix; char *prefix;
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);
if (rpc_cb_list == NULL) if (ms == NULL){
return 0; clicon_err(OE_PLUGIN, EINVAL, "plugin module not initialized");
goto done;
}
name = xml_name(xe); name = xml_name(xe);
prefix = xml_prefix(xe); prefix = xml_prefix(xe);
xml2ns(xe, prefix, &ns); xml2ns(xe, prefix, &ns);
rc = rpc_cb_list; if ((rc = ms->ms_rpc_callbacks) != NULL)
do { do {
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 (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++; rc = NEXTQ(rpc_callback_t *, rc);
} } while (rc != ms->ms_rpc_callbacks);
rc = NEXTQ(rpc_callback_t *, rc);
} while (rc != rpc_cb_list);
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);
@ -827,19 +942,7 @@ rpc_callback_call(clicon_handle h,
/*-------------------------------------------------------------------- /*--------------------------------------------------------------------
* Upgrade callbacks for backend upgrade of datastore * Upgrade callbacks for backend upgrade of datastore
* Register upgrade callbacks in plugin_init() with a module and a "from" and "to"
* revision.
*/ */
typedef struct {
qelem_t uc_qelem; /* List header */
clicon_upgrade_cb uc_callback; /* RPC Callback */
const char *uc_fnstr; /* Stringified fn name for debug */
void *uc_arg; /* Application specific argument to cb */
char *uc_namespace; /* Module namespace */
} upgrade_callback_t;
/* List of rpc callback entries XXX hang on handle */
static upgrade_callback_t *upgrade_cb_list = NULL;
/*! Register an upgrade callback by appending the new callback to the list /*! Register an upgrade callback by appending the new callback to the list
* *
@ -860,7 +963,12 @@ upgrade_callback_reg_fn(clicon_handle h,
void *arg) void *arg)
{ {
upgrade_callback_t *uc; upgrade_callback_t *uc;
plugin_module_struct *ms = plugin_module_struct_get(h);
if (ms == NULL){
clicon_err(OE_PLUGIN, EINVAL, "plugin module not initialized");
goto done;
}
if ((uc = malloc(sizeof(upgrade_callback_t))) == NULL) { if ((uc = malloc(sizeof(upgrade_callback_t))) == NULL) {
clicon_err(OE_DB, errno, "malloc"); clicon_err(OE_DB, errno, "malloc");
goto done; goto done;
@ -871,7 +979,7 @@ upgrade_callback_reg_fn(clicon_handle h,
uc->uc_arg = arg; uc->uc_arg = arg;
if (ns) if (ns)
uc->uc_namespace = strdup(ns); uc->uc_namespace = strdup(ns);
ADDQ(uc, upgrade_cb_list); ADDQ(uc, ms->ms_upgrade_callbacks);
return 0; return 0;
done: done:
if (uc){ if (uc){
@ -884,17 +992,19 @@ upgrade_callback_reg_fn(clicon_handle h,
/*! Delete all Upgrade callbacks /*! Delete all Upgrade callbacks
*/ */
int static int
upgrade_callback_delete_all(clicon_handle h) upgrade_callback_delete_all(clicon_handle h)
{ {
upgrade_callback_t *uc; upgrade_callback_t *uc;
plugin_module_struct *ms = plugin_module_struct_get(h);
while((uc = upgrade_cb_list) != NULL) { if (ms != NULL)
DELQ(uc, upgrade_cb_list, upgrade_callback_t *); while((uc = ms->ms_upgrade_callbacks) != NULL) {
if (uc->uc_namespace) DELQ(uc, ms->ms_upgrade_callbacks, upgrade_callback_t *);
free(uc->uc_namespace); if (uc->uc_namespace)
free(uc); free(uc->uc_namespace);
} free(uc);
}
return 0; return 0;
} }
@ -925,36 +1035,39 @@ upgrade_callback_call(clicon_handle h,
upgrade_callback_t *uc; upgrade_callback_t *uc;
int nr = 0; /* How many callbacks */ int nr = 0; /* How many callbacks */
int ret; int ret;
plugin_module_struct *ms = plugin_module_struct_get(h);
if (upgrade_cb_list == NULL) if (ms == NULL){
return 1; clicon_err(OE_PLUGIN, EINVAL, "plugin module not initialized");
uc = upgrade_cb_list; goto done;
do { }
/* For matching an upgrade callback: if ((uc = ms->ms_upgrade_callbacks) != NULL)
* - No module name registered (matches all modules) OR do {
* - Names match /* For matching an upgrade callback:
* AND * - No module name registered (matches all modules) OR
* - No registered from revision (matches all revisions) OR * - Names match
* - Registered from revision >= from AND * AND
* - Registered to revision <= to (which includes case both 0) * - No registered from revision (matches all revisions) OR
*/ * - Registered from revision >= from AND
if (uc->uc_namespace == NULL || strcmp(uc->uc_namespace, ns)==0){ * - Registered to revision <= to (which includes case both 0)
if ((ret = uc->uc_callback(h, xt, ns, op, from, to, uc->uc_arg, cbret)) < 0){ */
clicon_debug(1, "%s Error in: %s", __FUNCTION__, uc->uc_namespace); if (uc->uc_namespace == NULL || strcmp(uc->uc_namespace, ns)==0){
goto done; if ((ret = uc->uc_callback(h, xt, ns, op, from, to, uc->uc_arg, cbret)) < 0){
} clicon_debug(1, "%s Error in: %s", __FUNCTION__, uc->uc_namespace);
if (ret == 0){
if (cbuf_len(cbret)==0){
clicon_err(OE_CFG, 0, "Validation fail %s(%s): cbret not set",
uc->uc_fnstr, ns);
goto done; goto done;
} }
goto fail; if (ret == 0){
if (cbuf_len(cbret)==0){
clicon_err(OE_CFG, 0, "Validation fail %s(%s): cbret not set",
uc->uc_fnstr, ns);
goto done;
}
goto fail;
}
nr++;
} }
nr++; uc = NEXTQ(upgrade_callback_t *, uc);
} } while (uc != ms->ms_upgrade_callbacks);
uc = NEXTQ(upgrade_callback_t *, uc);
} while (uc != upgrade_cb_list);
retval = 1; retval = 1;
done: done:
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
@ -990,3 +1103,49 @@ clixon_auth_type_int2str(clixon_auth_type_t auth_type)
{ {
return clicon_int2str(clixon_auth_type, auth_type); return clicon_int2str(clixon_auth_type, auth_type);
} }
/*! Initialize plugin module by creating a handle holding plugin and callback lists
* This should be called once at start by every application
* @param[in] h Clixon handle
* @see clixon_plugin_module_exit
*/
int
clixon_plugin_module_init(clicon_handle h)
{
int retval = -1;
struct plugin_module_struct *ph;
if ((ph = malloc(sizeof(*ph))) == NULL){
clicon_err(OE_UNIX, errno, "malloc");
goto done;
}
memset(ph, 0, sizeof(*ph));
if (plugin_module_struct_set(h, ph) < 0)
goto done;
retval = 0;
done:
return retval;
}
/*! Delete plugin module
* This should be called once at exit by every application
* @param[in] h Clixon handle
*/
int
clixon_plugin_module_exit(clicon_handle h)
{
struct plugin_module_struct *ph;
/* Delete all plugins */
clixon_plugin_exit_all(h);
/* Delete all RPC callbacks */
rpc_callback_delete_all(h);
/* Delete all backend plugin upgrade callbacks (only backend) */
upgrade_callback_delete_all(h);
/* Delete plugin_module itself */
if ((ph = plugin_module_struct_get(h)) != NULL){
free(ph);
plugin_module_struct_set(h, NULL);
}
return 0;
}

View file

@ -2130,7 +2130,10 @@ ys_populate_unknown(clicon_handle h,
return -1; return -1;
} }
#endif #endif
/* Make extension callbacks that may alter yang structure */ /* Make extension callbacks that may alter yang structure
* Note: this may be a "layering" violation: assuming plugins are loaded
* at yang parse time
*/
if (clixon_plugin_extension_all(h, yext, ys) < 0) if (clixon_plugin_extension_all(h, yext, ys) < 0)
goto done; goto done;

View file

@ -60,6 +60,8 @@ struct yang_type_cache{
typedef struct yang_type_cache yang_type_cache; typedef struct yang_type_cache yang_type_cache;
/*! yang statement /*! yang statement
* This is an internal type, not exposed in the API
* The external type is "yang_stmt" defined in clixon_yang.h
*/ */
struct yang_stmt{ struct yang_stmt{
int ys_len; /* Number of children */ int ys_len; /* Number of children */

View file

@ -77,3 +77,6 @@ CLIXON_EXAMPLE_REV="2020-12-01"
# Problem with long keys are they take time to generate, eg on ARM # Problem with long keys are they take time to generate, eg on ARM
CERTKEYLEN=2048 CERTKEYLEN=2048
# Linking: static or dynamic
LINKAGE=@LINKAGE@
SH_SUFFIX=@SH_SUFFIX@

View file

@ -7,6 +7,14 @@ s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
# Eg on FreeBSD use gmake # Eg on FreeBSD use gmake
: ${make:=make} : ${make:=make}
# Check for soft links for .so files in case of dynamic linkage, but .a files f static linking
if [ ${LINKAGE} = static ]; then
LIBOPT=-f
else
LIBOPT=-h
fi
new "Set up installdir $dir" new "Set up installdir $dir"
new "Make DESTDIR install ($dir)" new "Make DESTDIR install ($dir)"
@ -26,18 +34,18 @@ new "Check installed files clixon-config"
if [ ! -f $dir/usr/local/share/clixon/clixon-config* ]; then if [ ! -f $dir/usr/local/share/clixon/clixon-config* ]; then
err $dir/usr/local/share/clixon/clixon-config* err $dir/usr/local/share/clixon/clixon-config*
fi fi
new "Check installed files libclixon.so" new "Check installed files libclixon${SH_SUFFIX}"
# Check both /usr/local/lib and /usr/lib # Check both /usr/local/lib and /usr/lib
# This is a problem on some platforms that dont have /usr/local/ in LD_LIBRARY_PATH # This is a problem on some platforms that dont have /usr/local/ in LD_LIBRARY_PATH
if [ ! -h $dir/usr/local/lib/libclixon.so ]; then if [ ! ${LIBOPT} $dir/usr/local/lib/libclixon${SH_SUFFIX} ]; then
if [ ! -h $dir/usr/lib/libclixon.so ]; then if [ ! ${LIBOPT} $dir/usr/lib/libclixon${SH_SUFFIX} ]; then
err $dir/usr/local/lib/libclixon.so err $dir/usr/local/lib/libclixon${SH_SUFFIX}
fi fi
fi fi
new "Check installed files libclixon_backend.so" new "Check installed files libclixon_backend${SH_SUFFIX}"
if [ ! -h $dir/usr/local/lib/libclixon_backend.so ]; then if [ ! ${LIBOPT} $dir/usr/local/lib/libclixon_backend${SH_SUFFIX} ]; then
if [ ! -h $dir/usr/lib/libclixon_backend.so ]; then if [ ! ${LIBOPT} $dir/usr/lib/libclixon_backend${SH_SUFFIX} ]; then
err $dir/usr/local/lib/libclixon_backend.so err $dir/usr/local/lib/libclixon_backend${SH_SUFFIX}
fi fi
fi fi

View file

@ -105,6 +105,7 @@ $(top_srcdir)/lib/src/$(CLIXON_LIB):
clean: clean:
rm -f $(APPS) clixon_util_stream *.core rm -f $(APPS) clixon_util_stream *.core
rm -f *.gcda *.gcno *.gcov # coverage
# APPS # APPS
clixon_util_xml: clixon_util_xml.c $(LIBDEPS) clixon_util_xml: clixon_util_xml.c $(LIBDEPS)