2015-10-22 11:39:11 +02:00
|
|
|
#include "plugin_manager.h"
|
|
|
|
/**
|
|
|
|
* Plugin table to store the loaded plugin
|
|
|
|
*/
|
|
|
|
static struct plugin_entry *plugin_table[HASHSIZE];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Locate a plugin in the plugin table
|
|
|
|
* @param s plugin name
|
|
|
|
* @return a plugin entry in the plugin table
|
|
|
|
*/
|
|
|
|
struct plugin_entry *plugin_lookup(char *s)
|
|
|
|
{
|
|
|
|
struct plugin_entry *np;
|
2015-11-24 17:58:32 +01:00
|
|
|
for (np = plugin_table[hash(s, HASHSIZE)]; np != NULL; np = np->next)
|
2015-10-22 11:39:11 +02:00
|
|
|
if (strcmp(s, np->pname) == 0)
|
|
|
|
return np; /* found */
|
|
|
|
return NULL; /* not found */
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Load a plugin to the plugin table
|
|
|
|
* Only load when not available in the plugin table
|
|
|
|
* @param name plugin name
|
|
|
|
* @return pointer to the loaded plugin
|
|
|
|
*/
|
|
|
|
struct plugin_entry *plugin_load(char *name)
|
|
|
|
{
|
|
|
|
struct plugin_entry *np;
|
|
|
|
unsigned hashval;
|
|
|
|
if ((np = plugin_lookup(name)) == NULL) { /* not found */
|
|
|
|
np = (struct plugin_entry *) malloc(sizeof(*np));
|
|
|
|
if (np == NULL || (np->pname = strdup(name)) == NULL)
|
2018-10-05 19:01:39 +02:00
|
|
|
{
|
|
|
|
if(np) free(np);
|
|
|
|
return NULL;
|
|
|
|
}
|
2015-10-22 11:39:11 +02:00
|
|
|
if ((np->handle = plugin_from_file(name)) == NULL)
|
2018-10-05 19:01:39 +02:00
|
|
|
{
|
|
|
|
if(np) free(np);
|
2015-10-22 11:39:11 +02:00
|
|
|
return NULL;
|
2018-10-05 19:01:39 +02:00
|
|
|
}
|
|
|
|
hashval = hash(name,HASHSIZE);
|
2015-10-22 11:39:11 +02:00
|
|
|
np->next = plugin_table[hashval];
|
|
|
|
plugin_table[hashval] = np;
|
|
|
|
} else /* already there */
|
|
|
|
{
|
2019-12-11 23:17:42 +01:00
|
|
|
LOG("The plugin %s id already loaded", name);
|
2015-10-22 11:39:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return np;
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* Find a plugin in a file, and load it in to the plugin table
|
|
|
|
* @param name Name of the plugin
|
|
|
|
* @return
|
|
|
|
*/
|
|
|
|
void * plugin_from_file(char* name)
|
|
|
|
{
|
|
|
|
void *lib_handle;
|
|
|
|
char* error;
|
2018-10-05 19:01:39 +02:00
|
|
|
char* path = __s("%s%s%s",config()->plugins_dir,name,config()->plugins_ext);
|
2018-02-10 11:22:41 +01:00
|
|
|
void (*fn)(const char*, config_t*);
|
2019-11-14 18:48:44 +01:00
|
|
|
lib_handle = dlopen(path, RTLD_NOW| RTLD_GLOBAL);
|
2015-10-22 11:39:11 +02:00
|
|
|
if (!lib_handle)
|
|
|
|
{
|
2019-12-11 23:17:42 +01:00
|
|
|
ERROR("Cannot load plugin '%s' : '%s'",name,dlerror());
|
2018-03-02 19:04:00 +01:00
|
|
|
if(path)
|
|
|
|
free(path);
|
2015-10-22 11:39:11 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
// set database path
|
2018-02-10 11:22:41 +01:00
|
|
|
fn = (void (*)(const char *, config_t*))dlsym(lib_handle, "__init_plugin__");
|
2015-10-22 11:39:11 +02:00
|
|
|
if ((error = dlerror()) != NULL)
|
2019-12-11 23:17:42 +01:00
|
|
|
ERROR("Problem when finding plugin init function for %s : %s", name,error);
|
2015-10-22 11:39:11 +02:00
|
|
|
else
|
2018-10-05 19:01:39 +02:00
|
|
|
(*fn)(name,config());
|
2017-07-30 01:00:36 +02:00
|
|
|
if(path)
|
2015-10-22 11:39:11 +02:00
|
|
|
free(path);
|
|
|
|
return lib_handle;
|
|
|
|
}
|
|
|
|
|
2016-03-04 11:38:08 +01:00
|
|
|
void unload_plugin(struct plugin_entry* np)
|
|
|
|
{
|
|
|
|
char* error;
|
|
|
|
void (*fn)() = NULL;
|
|
|
|
// find and execute the exit function
|
2018-10-05 19:01:39 +02:00
|
|
|
fn = (void(*)()) dlsym(np->handle, "__release__");
|
2018-03-02 19:04:00 +01:00
|
|
|
if ((error = dlerror()) != NULL)
|
|
|
|
{
|
2019-12-11 23:17:42 +01:00
|
|
|
ERROR("Cant not release plugin %s : %s", np->pname,error);
|
2018-03-02 19:04:00 +01:00
|
|
|
}
|
|
|
|
if(fn)
|
|
|
|
{
|
|
|
|
(*fn)();
|
|
|
|
}
|
2016-03-04 11:38:08 +01:00
|
|
|
dlclose(np->handle);
|
|
|
|
//free((void *) np->handle);
|
|
|
|
free((void *) np->pname);
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
Unload a plugin by its name
|
|
|
|
*/
|
|
|
|
void unload_plugin_by_name(const char* name)
|
|
|
|
{
|
|
|
|
struct plugin_entry *np;
|
|
|
|
int hasval = hash(name, HASHSIZE);
|
|
|
|
np = plugin_table[hasval];
|
|
|
|
if(strcmp(np->pname,name) == 0)
|
|
|
|
{
|
|
|
|
unload_plugin(np);
|
|
|
|
plugin_table[hasval] = np->next;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-12-11 23:17:42 +01:00
|
|
|
for (np ; np != NULL; np = np->next)
|
|
|
|
{
|
2016-03-04 11:38:08 +01:00
|
|
|
if (np->next != NULL && strcmp(name, np->next->pname) == 0)
|
2019-12-11 23:17:42 +01:00
|
|
|
{
|
2016-03-04 11:38:08 +01:00
|
|
|
break;
|
2019-12-11 23:17:42 +01:00
|
|
|
}
|
|
|
|
}
|
2016-03-04 11:38:08 +01:00
|
|
|
if(np == NULL) return; // the plugin is is not loaded
|
|
|
|
unload_plugin(np->next);
|
|
|
|
np->next = np->next->next;
|
|
|
|
}
|
|
|
|
}
|
2015-10-22 11:39:11 +02:00
|
|
|
/**
|
|
|
|
* Unload all the plugin loaded on the plugin table
|
|
|
|
*/
|
|
|
|
void unload_all_plugin()
|
|
|
|
{
|
2019-12-11 23:17:42 +01:00
|
|
|
LOG("Unload all plugins");
|
2015-10-22 11:39:11 +02:00
|
|
|
for(int i=0;i<HASHSIZE;i++)
|
|
|
|
{
|
2018-03-02 19:04:00 +01:00
|
|
|
struct plugin_entry **np, *curr;
|
|
|
|
np = &plugin_table[i];
|
|
|
|
|
|
|
|
while((curr = *np) != NULL)
|
|
|
|
{
|
|
|
|
(*np) = (*np)->next;
|
|
|
|
unload_plugin(curr);
|
|
|
|
free(curr);
|
|
|
|
}
|
2015-10-22 11:39:11 +02:00
|
|
|
plugin_table[i] = NULL;
|
|
|
|
}
|
2015-10-22 23:13:53 +02:00
|
|
|
exit(0);
|
2015-10-22 11:39:11 +02:00
|
|
|
}
|
|
|
|
|