common plugin code, removed clixon_proc.c
This commit is contained in:
parent
2758a30bb7
commit
85af4342dc
13 changed files with 142 additions and 542 deletions
|
|
@ -152,7 +152,7 @@ config_plugin_init(clicon_handle h)
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
plugin_unload(clicon_handle h,
|
backend_plugin_unload(clicon_handle h,
|
||||||
struct plugin *plg)
|
struct plugin *plg)
|
||||||
{
|
{
|
||||||
char *error;
|
char *error;
|
||||||
|
|
@ -182,37 +182,16 @@ plugin_unload(clicon_handle h,
|
||||||
* @retval NULL Error
|
* @retval NULL Error
|
||||||
*/
|
*/
|
||||||
static struct plugin *
|
static struct plugin *
|
||||||
plugin_load (clicon_handle h,
|
backend_plugin_load (clicon_handle h,
|
||||||
char *file,
|
char *file,
|
||||||
int dlflags)
|
int dlflags)
|
||||||
{
|
{
|
||||||
char *error;
|
|
||||||
void *handle;
|
void *handle;
|
||||||
char *name;
|
char *name;
|
||||||
struct plugin *new;
|
struct plugin *new = NULL;
|
||||||
plginit_t *initfun;
|
|
||||||
|
|
||||||
dlerror(); /* Clear any existing error */
|
|
||||||
if ((handle = dlopen (file, dlflags)) == NULL) {
|
|
||||||
error = (char*)dlerror();
|
|
||||||
clicon_err(OE_UNIX, 0, "dlopen: %s", error?error:"Unknown error");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
initfun = dlsym(handle, PLUGIN_INIT);
|
|
||||||
if ((error = (char*)dlerror()) != NULL) {
|
|
||||||
clicon_err(OE_UNIX, 0, "dlsym: %s: %s", file, error);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (initfun(h) != 0) {
|
|
||||||
dlclose(handle);
|
|
||||||
if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */
|
|
||||||
clicon_err(OE_DB, 0, "Unknown error: %s: plugin_init does not make clicon_err call on error",
|
|
||||||
file);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if ((handle = plugin_load(h, file, dlflags)) == NULL)
|
||||||
|
goto done;
|
||||||
if ((new = malloc(sizeof(*new))) == NULL) {
|
if ((new = malloc(sizeof(*new))) == NULL) {
|
||||||
clicon_err(OE_UNIX, errno, "dhunk: %s", strerror(errno));
|
clicon_err(OE_UNIX, errno, "dhunk: %s", strerror(errno));
|
||||||
dlclose(handle);
|
dlclose(handle);
|
||||||
|
|
@ -224,7 +203,6 @@ plugin_load (clicon_handle h,
|
||||||
snprintf(new->p_name, sizeof(new->p_name), "%*s",
|
snprintf(new->p_name, sizeof(new->p_name), "%*s",
|
||||||
(int)strlen(name)-2, name);
|
(int)strlen(name)-2, name);
|
||||||
new->p_handle = handle;
|
new->p_handle = handle;
|
||||||
new->p_init = initfun;
|
|
||||||
if ((new->p_start = dlsym(handle, PLUGIN_START)) != NULL)
|
if ((new->p_start = dlsym(handle, PLUGIN_START)) != NULL)
|
||||||
clicon_debug(2, "%s callback registered.", PLUGIN_START);
|
clicon_debug(2, "%s callback registered.", PLUGIN_START);
|
||||||
if ((new->p_exit = dlsym(handle, PLUGIN_EXIT)) != NULL)
|
if ((new->p_exit = dlsym(handle, PLUGIN_EXIT)) != NULL)
|
||||||
|
|
@ -244,7 +222,7 @@ plugin_load (clicon_handle h,
|
||||||
if ((new->p_trans_abort = dlsym(handle, PLUGIN_TRANS_ABORT)) != NULL)
|
if ((new->p_trans_abort = dlsym(handle, PLUGIN_TRANS_ABORT)) != NULL)
|
||||||
clicon_debug(2, "%s callback registered.", PLUGIN_TRANS_ABORT);
|
clicon_debug(2, "%s callback registered.", PLUGIN_TRANS_ABORT);
|
||||||
clicon_debug(2, "Plugin '%s' loaded.\n", name);
|
clicon_debug(2, "Plugin '%s' loaded.\n", name);
|
||||||
|
done:
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -338,7 +316,7 @@ plugin_append(struct plugin *p)
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
config_plugin_load_dir(clicon_handle h,
|
backend_plugin_load_dir(clicon_handle h,
|
||||||
const char *dir)
|
const char *dir)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
|
@ -374,7 +352,7 @@ config_plugin_load_dir(clicon_handle h,
|
||||||
clicon_debug(1, "Loading master plugin '%.*s' ...",
|
clicon_debug(1, "Loading master plugin '%.*s' ...",
|
||||||
(int)strlen(filename), filename);
|
(int)strlen(filename), filename);
|
||||||
|
|
||||||
new = plugin_load(h, filename, RTLD_NOW|RTLD_GLOBAL);
|
new = backend_plugin_load(h, filename, RTLD_NOW|RTLD_GLOBAL);
|
||||||
if (new == NULL)
|
if (new == NULL)
|
||||||
goto quit;
|
goto quit;
|
||||||
if (plugin_append(new) < 0)
|
if (plugin_append(new) < 0)
|
||||||
|
|
@ -387,7 +365,7 @@ config_plugin_load_dir(clicon_handle h,
|
||||||
continue; /* Skip master now */
|
continue; /* Skip master now */
|
||||||
snprintf(filename, MAXPATHLEN-1, "%s/%s", dir, dp[i].d_name);
|
snprintf(filename, MAXPATHLEN-1, "%s/%s", dir, dp[i].d_name);
|
||||||
clicon_debug(1, "Loading plugin '%.*s' ...", (int)strlen(filename), filename);
|
clicon_debug(1, "Loading plugin '%.*s' ...", (int)strlen(filename), filename);
|
||||||
new = plugin_load(h, filename, RTLD_NOW);
|
new = backend_plugin_load(h, filename, RTLD_NOW);
|
||||||
if (new == NULL)
|
if (new == NULL)
|
||||||
goto quit;
|
goto quit;
|
||||||
/* Append to 'plugins' */
|
/* Append to 'plugins' */
|
||||||
|
|
@ -405,7 +383,7 @@ quit:
|
||||||
while (--np >= 0){
|
while (--np >= 0){
|
||||||
if ((p = &plugins[np]) == NULL)
|
if ((p = &plugins[np]) == NULL)
|
||||||
continue;
|
continue;
|
||||||
plugin_unload(h, p);
|
backend_plugin_unload(h, p);
|
||||||
free(p);
|
free(p);
|
||||||
}
|
}
|
||||||
free(plugins);
|
free(plugins);
|
||||||
|
|
@ -428,7 +406,7 @@ plugin_initiate(clicon_handle h)
|
||||||
char *dir;
|
char *dir;
|
||||||
|
|
||||||
/* First load CLICON system plugins */
|
/* First load CLICON system plugins */
|
||||||
if (config_plugin_load_dir(h, CLIXON_BACKEND_SYSDIR) < 0)
|
if (backend_plugin_load_dir(h, CLIXON_BACKEND_SYSDIR) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Then load application plugins */
|
/* Then load application plugins */
|
||||||
|
|
@ -436,7 +414,7 @@ plugin_initiate(clicon_handle h)
|
||||||
clicon_err(OE_PLUGIN, 0, "backend_dir not defined");
|
clicon_err(OE_PLUGIN, 0, "backend_dir not defined");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (config_plugin_load_dir(h, dir) < 0)
|
if (backend_plugin_load_dir(h, dir) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -455,7 +433,7 @@ plugin_finish(clicon_handle h)
|
||||||
|
|
||||||
for (i = 0; i < nplugins; i++) {
|
for (i = 0; i < nplugins; i++) {
|
||||||
p = &plugins[i];
|
p = &plugins[i];
|
||||||
plugin_unload(h, p);
|
backend_plugin_unload(h, p);
|
||||||
}
|
}
|
||||||
if (plugins){
|
if (plugins){
|
||||||
free(plugins);
|
free(plugins);
|
||||||
|
|
|
||||||
|
|
@ -162,31 +162,6 @@ syntax_append(clicon_handle h,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Unload a plugin
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
plugin_unload(clicon_handle h, void *handle)
|
|
||||||
{
|
|
||||||
int retval = 0;
|
|
||||||
char *error;
|
|
||||||
plgexit_t *exitfun;
|
|
||||||
|
|
||||||
/* Call exit function is it exists */
|
|
||||||
exitfun = dlsym(handle, PLUGIN_EXIT);
|
|
||||||
if (dlerror() == NULL)
|
|
||||||
exitfun(h);
|
|
||||||
|
|
||||||
dlerror(); /* Clear any existing error */
|
|
||||||
if (dlclose(handle) != 0) {
|
|
||||||
error = (char*)dlerror();
|
|
||||||
cli_output (stderr, "dlclose: %s\n", error ? error : "Unknown error");
|
|
||||||
/* Just report */
|
|
||||||
}
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Unload all plugins in a group
|
* Unload all plugins in a group
|
||||||
*/
|
*/
|
||||||
|
|
@ -275,41 +250,22 @@ cli_plugin_load(clicon_handle h,
|
||||||
char *file,
|
char *file,
|
||||||
int dlflags)
|
int dlflags)
|
||||||
{
|
{
|
||||||
char *error;
|
|
||||||
char *name;
|
char *name;
|
||||||
void *handle = NULL;
|
plghndl_t handle = NULL;
|
||||||
plginit_t *initfun;
|
|
||||||
struct cli_plugin *cp = NULL;
|
struct cli_plugin *cp = NULL;
|
||||||
|
|
||||||
dlerror(); /* Clear any existing error */
|
if ((handle = plugin_load(h, file, dlflags)) == NULL)
|
||||||
if ((handle = dlopen (file, dlflags)) == NULL) {
|
|
||||||
error = (char*)dlerror();
|
|
||||||
cli_output (stderr, "dlopen: %s\n", error ? error : "Unknown error");
|
|
||||||
goto quit;
|
goto quit;
|
||||||
}
|
|
||||||
/* call plugin_init() if defined */
|
|
||||||
if ((initfun = dlsym(handle, PLUGIN_INIT)) != NULL) {
|
|
||||||
if (initfun(h) != 0) {
|
|
||||||
cli_output (stderr, "Failed to initiate %s\n", strrchr(file,'/')?strchr(file, '/'):file);
|
|
||||||
goto quit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((cp = malloc(sizeof (struct cli_plugin))) == NULL) {
|
if ((cp = malloc(sizeof (struct cli_plugin))) == NULL) {
|
||||||
perror("malloc");
|
perror("malloc");
|
||||||
goto quit;
|
goto quit;
|
||||||
}
|
}
|
||||||
memset (cp, 0, sizeof(*cp));
|
memset (cp, 0, sizeof(*cp));
|
||||||
|
|
||||||
name = basename(file);
|
name = basename(file);
|
||||||
snprintf(cp->cp_name, sizeof(cp->cp_name), "%.*s", (int)strlen(name)-3, name);
|
snprintf(cp->cp_name, sizeof(cp->cp_name), "%.*s", (int)strlen(name)-3, name);
|
||||||
cp->cp_handle = handle;
|
cp->cp_handle = handle;
|
||||||
|
|
||||||
quit:
|
quit:
|
||||||
if (cp == NULL) {
|
|
||||||
if (handle)
|
|
||||||
dlclose(handle);
|
|
||||||
}
|
|
||||||
return cp;
|
return cp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -75,60 +75,6 @@ struct netconf_reg {
|
||||||
};
|
};
|
||||||
typedef struct netconf_reg netconf_reg_t;
|
typedef struct netconf_reg netconf_reg_t;
|
||||||
|
|
||||||
/*! Unload a plugin
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
plugin_unload(clicon_handle h, void *handle)
|
|
||||||
{
|
|
||||||
int retval = 0;
|
|
||||||
char *error;
|
|
||||||
plgexit_t *exitfn;
|
|
||||||
|
|
||||||
/* Call exit function is it exists */
|
|
||||||
exitfn = dlsym(handle, PLUGIN_EXIT);
|
|
||||||
if (dlerror() == NULL)
|
|
||||||
exitfn(h);
|
|
||||||
|
|
||||||
dlerror(); /* Clear any existing error */
|
|
||||||
if (dlclose(handle) != 0) {
|
|
||||||
error = (char*)dlerror();
|
|
||||||
clicon_err(OE_PLUGIN, errno, "dlclose: %s\n", error ? error : "Unknown error");
|
|
||||||
/* Just report */
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Load a dynamic plugin object and call it's init-function
|
|
||||||
* Note 'file' may be destructively modified
|
|
||||||
*/
|
|
||||||
static plghndl_t
|
|
||||||
plugin_load (clicon_handle h, char *file, int dlflags)
|
|
||||||
{
|
|
||||||
char *error;
|
|
||||||
void *handle = NULL;
|
|
||||||
plginit_t *initfn;
|
|
||||||
|
|
||||||
dlerror(); /* Clear any existing error */
|
|
||||||
if ((handle = dlopen (file, dlflags)) == NULL) {
|
|
||||||
error = (char*)dlerror();
|
|
||||||
clicon_err(OE_PLUGIN, errno, "dlopen: %s\n", error ? error : "Unknown error");
|
|
||||||
goto quit;
|
|
||||||
}
|
|
||||||
/* call plugin_init() if defined */
|
|
||||||
if ((initfn = dlsym(handle, PLUGIN_INIT)) != NULL) {
|
|
||||||
if (initfn(h) != 0) {
|
|
||||||
clicon_err(OE_PLUGIN, errno, "Failed to initiate %s\n", strrchr(file,'/')?strchr(file, '/'):file);
|
|
||||||
goto quit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
quit:
|
|
||||||
|
|
||||||
return handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int nplugins = 0;
|
static int nplugins = 0;
|
||||||
static plghndl_t *plugins = NULL;
|
static plghndl_t *plugins = NULL;
|
||||||
static netconf_reg_t *deps = NULL;
|
static netconf_reg_t *deps = NULL;
|
||||||
|
|
|
||||||
|
|
@ -269,44 +269,6 @@ static int nplugins = 0;
|
||||||
static plghndl_t *plugins = NULL;
|
static plghndl_t *plugins = NULL;
|
||||||
static credentials_t *p_credentials = NULL; /* Credentials callback */
|
static credentials_t *p_credentials = NULL; /* Credentials callback */
|
||||||
|
|
||||||
/*! Load a dynamic plugin object and call it's init-function
|
|
||||||
* Note 'file' may be destructively modified
|
|
||||||
*/
|
|
||||||
static plghndl_t
|
|
||||||
plugin_load (clicon_handle h,
|
|
||||||
char *file,
|
|
||||||
int dlflags)
|
|
||||||
{
|
|
||||||
char *error;
|
|
||||||
void *handle = NULL;
|
|
||||||
plginit_t *initfn;
|
|
||||||
|
|
||||||
clicon_debug(1, "%s", __FUNCTION__);
|
|
||||||
dlerror(); /* Clear any existing error */
|
|
||||||
if ((handle = dlopen (file, dlflags)) == NULL) {
|
|
||||||
error = (char*)dlerror();
|
|
||||||
clicon_err(OE_PLUGIN, errno, "dlopen: %s\n", error ? error : "Unknown error");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
/* call plugin_init() if defined */
|
|
||||||
if ((initfn = dlsym(handle, PLUGIN_INIT)) == NULL){
|
|
||||||
clicon_err(OE_PLUGIN, errno, "Failed to find plugin_init when loading restconf plugin %s", file);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (initfn(h) != 0) {
|
|
||||||
clicon_err(OE_PLUGIN, errno, "Failed to initiate %s", strrchr(file,'/')?strchr(file, '/'):file);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
p_credentials = dlsym(handle, "restconf_credentials");
|
|
||||||
done:
|
|
||||||
return handle;
|
|
||||||
err:
|
|
||||||
if (handle)
|
|
||||||
dlclose(handle);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*! Load all plugins you can find in CLICON_RESTCONF_DIR
|
/*! Load all plugins you can find in CLICON_RESTCONF_DIR
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
|
|
@ -335,6 +297,7 @@ restconf_plugin_load(clicon_handle h)
|
||||||
(int)strlen(filename), filename);
|
(int)strlen(filename), filename);
|
||||||
if ((handle = plugin_load(h, filename, RTLD_NOW)) == NULL)
|
if ((handle = plugin_load(h, filename, RTLD_NOW)) == NULL)
|
||||||
goto quit;
|
goto quit;
|
||||||
|
p_credentials = dlsym(handle, "restconf_credentials");
|
||||||
if ((plugins = realloc(plugins, (nplugins+1) * sizeof (*plugins))) == NULL) {
|
if ((plugins = realloc(plugins, (nplugins+1) * sizeof (*plugins))) == NULL) {
|
||||||
clicon_err(OE_UNIX, errno, "realloc");
|
clicon_err(OE_UNIX, errno, "realloc");
|
||||||
goto quit;
|
goto quit;
|
||||||
|
|
@ -348,28 +311,6 @@ quit:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Unload a plugin
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
plugin_unload(clicon_handle h, void *handle)
|
|
||||||
{
|
|
||||||
int retval = 0;
|
|
||||||
char *error;
|
|
||||||
plgexit_t *exitfn;
|
|
||||||
|
|
||||||
/* Call exit function is it exists */
|
|
||||||
exitfn = dlsym(handle, PLUGIN_EXIT);
|
|
||||||
if (dlerror() == NULL)
|
|
||||||
exitfn(h);
|
|
||||||
|
|
||||||
dlerror(); /* Clear any existing error */
|
|
||||||
if (dlclose(handle) != 0) {
|
|
||||||
error = (char*)dlerror();
|
|
||||||
clicon_err(OE_PLUGIN, errno, "dlclose: %s\n", error ? error : "Unknown error");
|
|
||||||
/* Just report */
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Unload all restconf plugins */
|
/*! Unload all restconf plugins */
|
||||||
int
|
int
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,6 @@
|
||||||
#include <clixon/clixon_xml.h>
|
#include <clixon/clixon_xml.h>
|
||||||
#include <clixon/clixon_proto.h>
|
#include <clixon/clixon_proto.h>
|
||||||
#include <clixon/clixon_proto_client.h>
|
#include <clixon/clixon_proto_client.h>
|
||||||
#include <clixon/clixon_proc.h>
|
|
||||||
#include <clixon/clixon_options.h>
|
#include <clixon/clixon_options.h>
|
||||||
#include <clixon/clixon_xml_map.h>
|
#include <clixon/clixon_xml_map.h>
|
||||||
#include <clixon/clixon_xml_db.h>
|
#include <clixon/clixon_xml_db.h>
|
||||||
|
|
|
||||||
|
|
@ -42,4 +42,6 @@ int clicon_file_dirent(const char *dir, struct dirent **ent,
|
||||||
|
|
||||||
int clicon_file_copy(char *src, char *target);
|
int clicon_file_copy(char *src, char *target);
|
||||||
|
|
||||||
|
int group_name2gid(char *name, gid_t *gid);
|
||||||
|
|
||||||
#endif /* _CLIXON_FILE_H_ */
|
#endif /* _CLIXON_FILE_H_ */
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ typedef void *(find_plugin_t)(clicon_handle, char *);
|
||||||
* Prototypes
|
* Prototypes
|
||||||
*/
|
*/
|
||||||
/* Common plugin function names, function types and signatures.
|
/* Common plugin function names, function types and signatures.
|
||||||
* This set of plugins is extended in
|
* This plugin code is exytended by backend, cli, netconf, restconf plugins
|
||||||
* Cli see cli_plugin.c
|
* Cli see cli_plugin.c
|
||||||
* Backend see config_plugin.c
|
* Backend see config_plugin.c
|
||||||
*/
|
*/
|
||||||
|
|
@ -77,4 +77,8 @@ typedef int (plgexit_t)(clicon_handle); /* Plugin exit */
|
||||||
/* Find a function in global namespace or a plugin. XXX clicon internal */
|
/* Find a function in global namespace or a plugin. XXX clicon internal */
|
||||||
void *clicon_find_func(clicon_handle h, char *plugin, char *func);
|
void *clicon_find_func(clicon_handle h, char *plugin, char *func);
|
||||||
|
|
||||||
|
plghndl_t plugin_load (clicon_handle h, char *file, int dlflags);
|
||||||
|
|
||||||
|
int plugin_unload(clicon_handle h, plghndl_t *handle);
|
||||||
|
|
||||||
#endif /* _CLIXON_PLUGIN_H_ */
|
#endif /* _CLIXON_PLUGIN_H_ */
|
||||||
|
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
***** BEGIN LICENSE BLOCK *****
|
|
||||||
|
|
||||||
Copyright (C) 2009-2017 Olof Hagsand and Benny Holmgren
|
|
||||||
|
|
||||||
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 *****
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _CLIXON_PROC_H_
|
|
||||||
#define _CLIXON_PROC_H_
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Prototypes
|
|
||||||
*/
|
|
||||||
int clicon_proc_run (char *, void (outcb)(char *), int doerr);
|
|
||||||
int clicon_proc_daemon (char *);
|
|
||||||
int group_name2gid(char *name, gid_t *gid);
|
|
||||||
|
|
||||||
#endif /* _CLIXON_PROC_H_ */
|
|
||||||
|
|
@ -61,7 +61,7 @@ CPPFLAGS = @CPPFLAGS@
|
||||||
|
|
||||||
INCLUDES = -I. @INCLUDES@ -I$(top_srcdir)/lib/clixon -I$(top_srcdir)/include -I$(top_srcdir)
|
INCLUDES = -I. @INCLUDES@ -I$(top_srcdir)/lib/clixon -I$(top_srcdir)/include -I$(top_srcdir)
|
||||||
|
|
||||||
SRC = clixon_sig.c clixon_log.c clixon_err.c clixon_event.c clixon_proc.c \
|
SRC = clixon_sig.c clixon_log.c clixon_err.c clixon_event.c \
|
||||||
clixon_string.c clixon_handle.c \
|
clixon_string.c clixon_handle.c \
|
||||||
clixon_xml.c clixon_xml_map.c clixon_file.c \
|
clixon_xml.c clixon_xml_map.c clixon_file.c \
|
||||||
clixon_json.c clixon_yang.c clixon_yang_type.c \
|
clixon_json.c clixon_yang.c clixon_yang_type.c \
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <grp.h>
|
||||||
|
|
||||||
/* cligen */
|
/* cligen */
|
||||||
#include <cligen/cligen.h>
|
#include <cligen/cligen.h>
|
||||||
|
|
@ -229,3 +230,34 @@ clicon_file_copy(char *src,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Translate group name to gid. Return -1 if error or not found.
|
||||||
|
* @param[in] name Name of group
|
||||||
|
* @param[out] gid Group id
|
||||||
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error. or not found
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
group_name2gid(char *name,
|
||||||
|
gid_t *gid)
|
||||||
|
{
|
||||||
|
char buf[1024];
|
||||||
|
struct group g0;
|
||||||
|
struct group *gr = &g0;
|
||||||
|
struct group *gtmp;
|
||||||
|
|
||||||
|
gr = &g0;
|
||||||
|
/* This leaks memory in ubuntu */
|
||||||
|
if (getgrnam_r(name, gr, buf, sizeof(buf), >mp) < 0){
|
||||||
|
clicon_err(OE_UNIX, errno, "%s: getgrnam_r(%s): %s",
|
||||||
|
__FUNCTION__, name, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (gtmp == NULL){
|
||||||
|
clicon_err(OE_UNIX, 0, "%s: No such group: %s", __FUNCTION__, name);
|
||||||
|
fprintf(stderr, "No such group %s\n", name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (gid)
|
||||||
|
*gid = gr->gr_gid;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@
|
||||||
#include "clixon_err.h"
|
#include "clixon_err.h"
|
||||||
#include "clixon_queue.h"
|
#include "clixon_queue.h"
|
||||||
#include "clixon_hash.h"
|
#include "clixon_hash.h"
|
||||||
|
#include "clixon_log.h"
|
||||||
#include "clixon_handle.h"
|
#include "clixon_handle.h"
|
||||||
#include "clixon_plugin.h"
|
#include "clixon_plugin.h"
|
||||||
|
|
||||||
|
|
@ -84,3 +85,76 @@ clicon_find_func(clicon_handle h, char *plugin, char *func)
|
||||||
|
|
||||||
return dlsym(dlhandle, func);
|
return dlsym(dlhandle, func);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Load a dynamic plugin object and call its init-function
|
||||||
|
* Note 'file' may be destructively modified
|
||||||
|
* @param[in] h Clicon handle
|
||||||
|
* @param[in] file Which plugin to load
|
||||||
|
* @param[in] dlflags See man(3) dlopen
|
||||||
|
*/
|
||||||
|
plghndl_t
|
||||||
|
plugin_load (clicon_handle h,
|
||||||
|
char *file,
|
||||||
|
int dlflags)
|
||||||
|
{
|
||||||
|
char *error;
|
||||||
|
void *handle = NULL;
|
||||||
|
plginit_t *initfn;
|
||||||
|
|
||||||
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
|
dlerror(); /* Clear any existing error */
|
||||||
|
if ((handle = dlopen (file, dlflags)) == NULL) {
|
||||||
|
error = (char*)dlerror();
|
||||||
|
clicon_err(OE_PLUGIN, errno, "dlopen: %s\n", error ? error : "Unknown error");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
/* call plugin_init() if defined */
|
||||||
|
if ((initfn = dlsym(handle, PLUGIN_INIT)) == NULL){
|
||||||
|
clicon_err(OE_PLUGIN, errno, "Failed to find plugin_init when loading restconf plugin %s", file);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if ((error = (char*)dlerror()) != NULL) {
|
||||||
|
clicon_err(OE_UNIX, 0, "dlsym: %s: %s", file, error);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (initfn(h) != 0) {
|
||||||
|
clicon_err(OE_PLUGIN, errno, "Failed to initiate %s", strrchr(file,'/')?strchr(file, '/'):file);
|
||||||
|
if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */
|
||||||
|
clicon_err(OE_DB, 0, "Unknown error: %s: plugin_init does not make clicon_err call on error",
|
||||||
|
file);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
return handle;
|
||||||
|
err:
|
||||||
|
if (handle)
|
||||||
|
dlclose(handle);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Unload a plugin
|
||||||
|
* @param[in] h Clicon handle
|
||||||
|
* @param[in] handle Clicon handle
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
plugin_unload(clicon_handle h,
|
||||||
|
plghndl_t *handle)
|
||||||
|
{
|
||||||
|
int retval = 0;
|
||||||
|
char *error;
|
||||||
|
plgexit_t *exitfn;
|
||||||
|
|
||||||
|
/* Call exit function is it exists */
|
||||||
|
exitfn = dlsym(handle, PLUGIN_EXIT);
|
||||||
|
if (dlerror() == NULL)
|
||||||
|
exitfn(h);
|
||||||
|
|
||||||
|
dlerror(); /* Clear any existing error */
|
||||||
|
if (dlclose(handle) != 0) {
|
||||||
|
error = (char*)dlerror();
|
||||||
|
clicon_err(OE_PLUGIN, errno, "dlclose: %s\n", error ? error : "Unknown error");
|
||||||
|
/* Just report */
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,293 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
***** BEGIN LICENSE BLOCK *****
|
|
||||||
|
|
||||||
Copyright (C) 2009-2017 Olof Hagsand and Benny Holmgren
|
|
||||||
|
|
||||||
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 *****
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "clixon_config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <grp.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <sys/user.h>
|
|
||||||
#include <sys/sysctl.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/resource.h>
|
|
||||||
|
|
||||||
/* clicon */
|
|
||||||
#include "clixon_err.h"
|
|
||||||
#include "clixon_log.h"
|
|
||||||
#include "clixon_sig.h"
|
|
||||||
#include "clixon_string.h"
|
|
||||||
#include "clixon_queue.h"
|
|
||||||
#include "clixon_proc.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Macros
|
|
||||||
*/
|
|
||||||
#define signal_set_mask(set) sigprocmask(SIG_SETMASK, (set), NULL)
|
|
||||||
#define signal_get_mask(set) sigprocmask (0, NULL, (set))
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Child process ID
|
|
||||||
* XXX Really shouldn't be a global variable
|
|
||||||
*/
|
|
||||||
static int _clicon_proc_child = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make sure child is killed by ctrl-C
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
clicon_proc_sigint(int sig)
|
|
||||||
{
|
|
||||||
if (_clicon_proc_child > 0)
|
|
||||||
kill (_clicon_proc_child, SIGINT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Fork a child process, setup a pipe between parent and child.
|
|
||||||
* Allowing parent to read the output of the child.
|
|
||||||
* @param[in] doerr If non-zero, stderr will be directed to the pipe as well.
|
|
||||||
* The pipe for the parent to write
|
|
||||||
* to the child is closed and cannot be used.
|
|
||||||
*
|
|
||||||
* When child process is done with the pipe setup, execute the specified
|
|
||||||
* command, execv(argv[0], argv).
|
|
||||||
*
|
|
||||||
* When parent is done with the pipe setup it will read output from the child
|
|
||||||
* until eof. The read output will be sent to the specified output callback,
|
|
||||||
* 'outcb' function.
|
|
||||||
*
|
|
||||||
* @retval number Matches (processes affected).
|
|
||||||
* @retval -1 Error.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
clicon_proc_run (char *cmd,
|
|
||||||
void (outcb)(char *),
|
|
||||||
int doerr)
|
|
||||||
{
|
|
||||||
char
|
|
||||||
**argv,
|
|
||||||
buf[512];
|
|
||||||
int
|
|
||||||
outfd[2] = { -1, -1 };
|
|
||||||
int
|
|
||||||
n,
|
|
||||||
argc,
|
|
||||||
status,
|
|
||||||
retval = -1;
|
|
||||||
pid_t
|
|
||||||
child;
|
|
||||||
sigfn_t oldhandler = NULL;
|
|
||||||
sigset_t oset;
|
|
||||||
|
|
||||||
argv = clicon_strsep(cmd, " \t", &argc);
|
|
||||||
if (!argv)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (pipe (outfd) == -1)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
signal_get_mask(&oset);
|
|
||||||
set_signal(SIGINT, clicon_proc_sigint, &oldhandler);
|
|
||||||
|
|
||||||
|
|
||||||
if ((child = fork ()) < 0) {
|
|
||||||
retval = -1;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (child == 0) { /* Child */
|
|
||||||
|
|
||||||
/* Unblock all signals except TSTP */
|
|
||||||
clicon_signal_unblock (0);
|
|
||||||
signal (SIGTSTP, SIG_IGN);
|
|
||||||
|
|
||||||
close (outfd[0]); /* Close unused read ends */
|
|
||||||
outfd[0] = -1;
|
|
||||||
|
|
||||||
/* Divert stdout and stderr to pipes */
|
|
||||||
dup2 (outfd[1], STDOUT_FILENO);
|
|
||||||
if (doerr)
|
|
||||||
dup2 (outfd[1], STDERR_FILENO);
|
|
||||||
|
|
||||||
execvp (argv[0], argv);
|
|
||||||
perror("execvp");
|
|
||||||
_exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Parent */
|
|
||||||
|
|
||||||
/* Close unused write ends */
|
|
||||||
close (outfd[1]);
|
|
||||||
outfd[1] = -1;
|
|
||||||
|
|
||||||
/* Read from pipe */
|
|
||||||
while ((n = read (outfd[0], buf, sizeof (buf)-1)) != 0) {
|
|
||||||
if (n < 0) {
|
|
||||||
if (errno == EINTR)
|
|
||||||
continue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
buf[n] = '\0';
|
|
||||||
/* Pass read data to callback function is defined */
|
|
||||||
if (outcb)
|
|
||||||
outcb (buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wait for child to finish */
|
|
||||||
if(waitpid (child, &status, 0) == child)
|
|
||||||
retval = WEXITSTATUS(status);
|
|
||||||
else
|
|
||||||
retval = -1;
|
|
||||||
|
|
||||||
done:
|
|
||||||
|
|
||||||
/* Clean up all pipes */
|
|
||||||
if (outfd[0] != -1)
|
|
||||||
close (outfd[0]);
|
|
||||||
if (outfd[1] != -1)
|
|
||||||
close (outfd[1]);
|
|
||||||
|
|
||||||
/* Restore sigmask and fn */
|
|
||||||
signal_set_mask (&oset);
|
|
||||||
set_signal(SIGINT, oldhandler, NULL);
|
|
||||||
|
|
||||||
if(argv)
|
|
||||||
free(argv);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Spawn command and report exit status
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
clicon_proc_daemon (char *cmd)
|
|
||||||
{
|
|
||||||
char
|
|
||||||
**argv;
|
|
||||||
int
|
|
||||||
i,
|
|
||||||
argc,
|
|
||||||
retval = -1,
|
|
||||||
status, status2;
|
|
||||||
pid_t
|
|
||||||
child,
|
|
||||||
pid;
|
|
||||||
struct rlimit
|
|
||||||
rlim;
|
|
||||||
|
|
||||||
argv = clicon_strsep(cmd, " \t", &argc);
|
|
||||||
if (!argv)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if ((child = fork ()) < 0) {
|
|
||||||
clicon_err(OE_UNIX, errno, "fork");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (child == 0) { /* Child */
|
|
||||||
|
|
||||||
clicon_signal_unblock (0);
|
|
||||||
if ((pid = fork ()) < 0) {
|
|
||||||
clicon_err(OE_UNIX, errno, "fork");
|
|
||||||
return -1;
|
|
||||||
_exit(1);
|
|
||||||
}
|
|
||||||
if (pid == 0) { /* Grandchild, create new session */
|
|
||||||
setsid();
|
|
||||||
if (chdir("/") < 0){
|
|
||||||
clicon_err(OE_UNIX, errno, "chdirq");
|
|
||||||
_exit(1);
|
|
||||||
}
|
|
||||||
/* Close open descriptors */
|
|
||||||
if ( ! getrlimit (RLIMIT_NOFILE, &rlim))
|
|
||||||
for (i = 0; i < rlim.rlim_cur; i++)
|
|
||||||
close(i);
|
|
||||||
|
|
||||||
if (execv (argv[0], argv) < 0) {
|
|
||||||
clicon_err(OE_UNIX, errno, "execv");
|
|
||||||
_exit(1);
|
|
||||||
}
|
|
||||||
/* Not reached */
|
|
||||||
}
|
|
||||||
|
|
||||||
waitpid (pid, &status2, 0);
|
|
||||||
_exit(status2);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (waitpid (child, &status, 0) > 0)
|
|
||||||
retval = 0;
|
|
||||||
|
|
||||||
done:
|
|
||||||
if (argv)
|
|
||||||
free(argv);
|
|
||||||
return (retval);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*! Translate group name to gid. Return -1 if error or not found.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
group_name2gid(char *name, gid_t *gid)
|
|
||||||
{
|
|
||||||
char buf[1024];
|
|
||||||
struct group g0;
|
|
||||||
struct group *gr = &g0;
|
|
||||||
struct group *gtmp;
|
|
||||||
|
|
||||||
gr = &g0;
|
|
||||||
/* This leaks memory in ubuntu */
|
|
||||||
if (getgrnam_r(name, gr, buf, sizeof(buf), >mp) < 0){
|
|
||||||
clicon_err(OE_UNIX, errno, "%s: getgrnam_r(%s): %s",
|
|
||||||
__FUNCTION__, name, strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (gtmp == NULL){
|
|
||||||
clicon_err(OE_UNIX, 0, "%s: No such group: %s", __FUNCTION__, name);
|
|
||||||
fprintf(stderr, "No such group %s\n", name);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (gid)
|
|
||||||
*gid = gr->gr_gid;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -170,13 +170,16 @@ percent_encode(char *str,
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *esc = NULL;
|
char *esc = NULL;
|
||||||
|
int len;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
/* This is max */
|
/* This is max */
|
||||||
if ((esc = malloc(strlen(str)*3+1)) == NULL){
|
len = strlen(str)*3+1;
|
||||||
|
if ((esc = malloc(len)) == NULL){
|
||||||
clicon_err(OE_UNIX, errno, "malloc");
|
clicon_err(OE_UNIX, errno, "malloc");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
memset(esc, 0, len);
|
||||||
j = 0;
|
j = 0;
|
||||||
for (i=0; i<strlen(str); i++){
|
for (i=0; i<strlen(str); i++){
|
||||||
if (unreserved(str[i]))
|
if (unreserved(str[i]))
|
||||||
|
|
@ -205,13 +208,16 @@ percent_decode(char *esc,
|
||||||
char *str = NULL;
|
char *str = NULL;
|
||||||
int i, j;
|
int i, j;
|
||||||
char hstr[3];
|
char hstr[3];
|
||||||
|
int len;
|
||||||
char *ptr;
|
char *ptr;
|
||||||
|
|
||||||
/* This is max */
|
/* This is max */
|
||||||
if ((str = malloc(strlen(esc)+1)) == NULL){
|
len = strlen(esc)+1;
|
||||||
|
if ((str = malloc(len)) == NULL){
|
||||||
clicon_err(OE_UNIX, errno, "malloc");
|
clicon_err(OE_UNIX, errno, "malloc");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
memset(str, 0, len);
|
||||||
j = 0;
|
j = 0;
|
||||||
for (i=0; i<strlen(esc); i++){
|
for (i=0; i<strlen(esc); i++){
|
||||||
if (esc[i] == '%' && strlen(esc)-i > 2 &&
|
if (esc[i] == '%' && strlen(esc)-i > 2 &&
|
||||||
|
|
@ -226,6 +232,7 @@ percent_decode(char *esc,
|
||||||
str[j] = esc[i];
|
str[j] = esc[i];
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
|
str[j++] = '\0';
|
||||||
*strp = str;
|
*strp = str;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue