|
|
|
@ -31,58 +31,56 @@
|
|
|
|
|
#include "network.h" |
|
|
|
|
#include "plugins.h" |
|
|
|
|
|
|
|
|
|
static LIST_HEAD(plugin_list); |
|
|
|
|
#define FLAGS_ACTIVE 0x01 |
|
|
|
|
|
|
|
|
|
static char *scratchpad; |
|
|
|
|
static LIST_HEAD(plugin_list); |
|
|
|
|
|
|
|
|
|
static int plugin_init_cb(const char *filename, void *privdata) |
|
|
|
|
{ |
|
|
|
|
int *bufsize = (int *)privdata; |
|
|
|
|
|
|
|
|
|
static const char *plugin_dir; |
|
|
|
|
if (plugin_dir == NULL) |
|
|
|
|
plugin_dir = config_get_string("global", "plugin_dir", "."); |
|
|
|
|
|
|
|
|
|
char *buffer = malloc(PATH_MAX); |
|
|
|
|
if (buffer == NULL) { |
|
|
|
|
char *fullname = malloc(PATH_MAX); |
|
|
|
|
if (fullname == NULL) { |
|
|
|
|
log_print(LOG_ERROR, "plugin_load: out of memory"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int len = snprintf(buffer, PATH_MAX, "%s/%s", plugin_dir, filename); |
|
|
|
|
int len = snprintf(fullname, PATH_MAX, "%s/%s", plugin_dir, filename); |
|
|
|
|
if (len < 0 || len >= PATH_MAX) { |
|
|
|
|
log_print(LOG_ERROR, "plugin_load: file name too long: %s/%s", plugin_dir, filename); |
|
|
|
|
free(buffer); |
|
|
|
|
free(fullname); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
dlerror(); |
|
|
|
|
void *tmp = dlopen(buffer, RTLD_NOW); |
|
|
|
|
if (tmp == NULL) { |
|
|
|
|
void *dlhandle = dlopen(fullname, RTLD_NOW); |
|
|
|
|
if (dlhandle == NULL) { |
|
|
|
|
log_print(LOG_ERROR, "plugin_load: dlopen: %s", dlerror()); |
|
|
|
|
free(buffer); |
|
|
|
|
free(fullname); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
free(buffer); |
|
|
|
|
free(fullname); |
|
|
|
|
|
|
|
|
|
struct sammler_plugin *plugin = dlsym(tmp, "plugin"); |
|
|
|
|
struct sammler_plugin *plugin = dlsym(dlhandle, "plugin"); |
|
|
|
|
if (plugin == NULL) { |
|
|
|
|
log_print(LOG_ERROR, "plugin_load: failed to load '%s'", filename); |
|
|
|
|
dlclose(tmp); |
|
|
|
|
dlclose(dlhandle); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
log_print(LOG_INFO, "Plugin '%s' loaded", plugin->name); |
|
|
|
|
plugin->lastprobe = 0; |
|
|
|
|
|
|
|
|
|
if (plugin->init != NULL && (plugin->init() != 0)) { |
|
|
|
|
log_print(LOG_ERROR, "Plugin '%s': init failed", plugin->name); |
|
|
|
|
dlclose(dlhandle); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (plugin->bufsize > *bufsize) |
|
|
|
|
*bufsize = plugin->bufsize; |
|
|
|
|
log_print(LOG_INFO, "Plugin '%s' loaded", plugin->name); |
|
|
|
|
plugin->lastprobe = 0; |
|
|
|
|
plugin->flags = FLAGS_ACTIVE; |
|
|
|
|
plugin->dlhandle = dlhandle; |
|
|
|
|
|
|
|
|
|
list_add_tail(&plugin->list, &plugin_list); |
|
|
|
|
return 0; |
|
|
|
@ -95,8 +93,14 @@ static int plugins_probe(void *privdata)
|
|
|
|
|
|
|
|
|
|
struct sammler_plugin *plugin; |
|
|
|
|
list_for_each_entry(plugin, &plugin_list, list) { |
|
|
|
|
if (!(plugin->flags & FLAGS_ACTIVE)) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
if (plugin->lastprobe + plugin->interval <= now) { |
|
|
|
|
plugin->probe(); |
|
|
|
|
if (plugin->probe() != 0) { |
|
|
|
|
log_print(LOG_ERROR, "plugin_probe(): plugin %s disabled", plugin->name); |
|
|
|
|
plugin->flags &= ~FLAGS_ACTIVE; |
|
|
|
|
} |
|
|
|
|
plugin->lastprobe = now; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -107,23 +111,12 @@ static int plugins_probe(void *privdata)
|
|
|
|
|
|
|
|
|
|
int plugin_init(void) |
|
|
|
|
{ |
|
|
|
|
int bufsize = 0; |
|
|
|
|
int cnt = config_get_strings("global", "plugin", plugin_init_cb, &bufsize); |
|
|
|
|
int cnt = config_get_strings("global", "plugin", plugin_init_cb, NULL); |
|
|
|
|
if (cnt == 0) { |
|
|
|
|
log_print(LOG_ERROR, "plugin_init(): no working plugins"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
scratchpad = malloc(bufsize); |
|
|
|
|
if (scratchpad == NULL) { |
|
|
|
|
log_print(LOG_ERROR, "plugin_init(): out of memory"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
struct sammler_plugin *plugin; |
|
|
|
|
list_for_each_entry(plugin, &plugin_list, list) |
|
|
|
|
plugin->buffer = scratchpad; |
|
|
|
|
|
|
|
|
|
struct timeval tv; |
|
|
|
|
tv.tv_sec = 1; |
|
|
|
|
tv.tv_usec = 0; |
|
|
|
|