268 lines
6.7 KiB
C
268 lines
6.7 KiB
C
#if HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
|
|
#if HAVE_SYSLOG_H
|
|
#include <syslog.h>
|
|
#endif
|
|
|
|
#if HAVE_STRING_H
|
|
#include <string.h>
|
|
#endif
|
|
|
|
#if STDC_HEADERS
|
|
#include <stdlib.h>
|
|
#endif
|
|
|
|
#if HAVE_DLFCN_H
|
|
#include <dlfcn.h>
|
|
#endif
|
|
|
|
#include "containers.h"
|
|
#include "cfg.h"
|
|
#include "smmapd.h"
|
|
|
|
|
|
#define CFG_SECTION_GLOBAL "global"
|
|
#define CFG_NAME_PLUGIN_DIR "plugin_dir"
|
|
#define CFG_NAME_PLUGINS "plugins"
|
|
#define CFG_PLUGINS_DELIMITER " "
|
|
#define CFG_NAME_OBJ "obj"
|
|
|
|
extern cfg_t *cfg;
|
|
|
|
classes_t classes_root = {NULL, 0, NULL, NULL};
|
|
classes_t *classes_head = &classes_root;
|
|
|
|
|
|
|
|
int containers_setup(container_handle_t **ch) {
|
|
*ch = (container_handle_t*)malloc(sizeof(container_handle_t));
|
|
(*ch)->worker_handle_root.next = NULL;
|
|
return 0;
|
|
}
|
|
|
|
int containers_destroy(container_handle_t *ch) {
|
|
worker_handle_t *wh, *wh2;
|
|
classes_t *classes;
|
|
int err;
|
|
|
|
syslog(LOG_DEBUG, "containers_destroy: going to free container_handle, first the worker handles");
|
|
|
|
wh = ch->worker_handle_root.next;
|
|
while (NULL != wh) {
|
|
for (classes = classes_root.next; classes != NULL; classes = classes->next) {
|
|
if (classes->id == wh->id) {
|
|
if (NULL != classes->descr->work_destroy_function) {
|
|
syslog(LOG_DEBUG, "containers_destroy: calling work_destroy_function for class %s (%d)",
|
|
classes->descr->name, classes->id);
|
|
err = (*classes->descr->work_destroy_function)(classes->handle, wh->handle);
|
|
}
|
|
}
|
|
}
|
|
wh2 = wh;
|
|
wh = wh->next;
|
|
free(wh2);
|
|
}
|
|
|
|
free(ch);
|
|
syslog(LOG_DEBUG, "containers_destroy: all freed");
|
|
}
|
|
|
|
|
|
int containers_dispatcher(container_handle_t *ch, char *input, char *output) {
|
|
char *class;
|
|
char *data;
|
|
classes_t *classes;
|
|
int result, err;
|
|
worker_handle_t *wh, *wh_last, *wh2;
|
|
|
|
syslog(LOG_DEBUG, "dispatcher: input: %s", input);
|
|
|
|
data = strchr(input, ' ');
|
|
if (NULL == data) {
|
|
syslog(LOG_ERR, "dispatcher: illegal input (%s)", input);
|
|
return SMM_ILLEGAL_INPUT;
|
|
}
|
|
|
|
data++; /* skip the blank */
|
|
|
|
class = input;
|
|
class[strlen(class)-strlen(data)-1] = '\0';
|
|
|
|
syslog(LOG_DEBUG, "dispatcher: class: %s, data: %s", class, data);
|
|
|
|
for (classes = classes_root.next; classes != NULL; classes = classes->next) {
|
|
if (0 == strcmp(class, classes->descr->name)) {
|
|
syslog(LOG_DEBUG, "dispatcher: yes, we support it, it's id=%d", classes->id);
|
|
for (wh = ch->worker_handle_root.next, wh_last = &ch->worker_handle_root, wh2 = NULL;
|
|
wh != NULL;
|
|
wh = wh->next) {
|
|
wh_last = wh;
|
|
if (wh->id == classes->id) {
|
|
syslog(LOG_DEBUG, "dispatcher: we already have a worker handle");
|
|
wh2 = wh;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ((NULL == wh_last->next) && (NULL == wh2)) {
|
|
syslog(LOG_DEBUG, "dispatcher: we haven't one, we create one");
|
|
wh2 = (worker_handle_t*)malloc(sizeof(worker_handle_t));
|
|
wh2->id = classes->id;
|
|
if (NULL != classes->descr->work_setup_function) {
|
|
err = (*classes->descr->work_setup_function)(classes->handle, &(wh2->handle));
|
|
} else {
|
|
wh2->handle = NULL;
|
|
}
|
|
wh2->next = NULL;
|
|
wh_last->next = wh2;
|
|
}
|
|
|
|
|
|
result = (*classes->descr->work_function)(classes->handle, wh2->handle, data, output);
|
|
syslog(LOG_DEBUG, "dispatcher: worker output: (%d, %s)", result, output);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (NULL == classes) {
|
|
syslog(LOG_ERR, "dispatcher: unknown class: %s", class);
|
|
return SMM_UNKNOWN_CLASS;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static int register_class(int id, class_descriptor_t *class_descriptor) {
|
|
int result = 0;
|
|
cfgl_t *c;
|
|
classes_t *w;
|
|
|
|
|
|
syslog(LOG_DEBUG, "register_class: registering class %s", class_descriptor->name);
|
|
|
|
c = findcfgsection(cfg, class_descriptor->name);
|
|
if (NULL == c) {
|
|
syslog(LOG_ERR, "register_class: no configuration section for this plugin available");
|
|
return -1;
|
|
}
|
|
|
|
w = (classes_t *) malloc(sizeof(classes_t));
|
|
if (NULL == w) {
|
|
syslog(LOG_ERR, "register_class: unable to alloc memory");
|
|
return -2;
|
|
}
|
|
|
|
if (NULL != class_descriptor->init_function) {
|
|
syslog(LOG_DEBUG, "register_class: initializing class %s", class_descriptor->name);
|
|
result = (*class_descriptor->init_function)(c, &w->handle);
|
|
if (0 != result) {
|
|
syslog(LOG_ERR, "register_class: unable to init class %s, exit", class_descriptor->name);
|
|
return -3;
|
|
}
|
|
} else {
|
|
w->handle = NULL;
|
|
}
|
|
|
|
w->descr = class_descriptor;
|
|
w->id = id;
|
|
w->next = NULL;
|
|
|
|
classes_head->next = w;
|
|
classes_head = w;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int unregister_class(classes_t *class) {
|
|
int result = 0;
|
|
|
|
syslog(LOG_DEBUG, "unregister_class: unregistering class %s", class->descr->name);
|
|
|
|
if (NULL != class->descr->destroy_function) {
|
|
syslog(LOG_DEBUG, "unregister_class: destroying class");
|
|
result = (*class->descr->destroy_function)(&class->handle);
|
|
syslog(LOG_ERR, "unregister_class: destroy function returns %d", result);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int unregister_all() {
|
|
classes_t *classes, *cf;
|
|
|
|
classes = classes_root.next;
|
|
while (NULL != classes) {
|
|
cf = classes;
|
|
classes = classes->next;
|
|
|
|
unregister_class(cf);
|
|
free(cf);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
int register_all() {
|
|
void *dl_handle;
|
|
class_descriptor_t * class_descriptor;
|
|
char *cfg_plugin_dir, *cfg_plugins, *cfg_plugin, *cfg_obj;
|
|
char *obj_name;
|
|
const char *err_msg;
|
|
int err;
|
|
int id = 0;
|
|
|
|
cfg_plugin_dir = findcfg(cfg, CFG_SECTION_GLOBAL, CFG_NAME_PLUGIN_DIR);
|
|
if (NULL == cfg_plugin_dir) {
|
|
syslog(LOG_ERR, "register_all: no plugin dir configured");
|
|
return -1;
|
|
}
|
|
|
|
cfg_plugins = findcfg(cfg, CFG_SECTION_GLOBAL, CFG_NAME_PLUGINS);
|
|
if (NULL == cfg_plugins) {
|
|
syslog(LOG_ERR, "register_all: no plugins configured");
|
|
return -2;
|
|
}
|
|
|
|
while (NULL != (cfg_plugin = strtok(cfg_plugins, CFG_PLUGINS_DELIMITER))) {
|
|
cfg_plugins = NULL; /* this is for subsequence calls of strtok */
|
|
dlerror(); /* this is to clear old errors */
|
|
|
|
cfg_obj = findcfg(cfg, cfg_plugin, CFG_NAME_OBJ);
|
|
if (NULL == cfg_obj) {
|
|
syslog(LOG_ERR, "register_all: obj for plugin %s not configured", cfg_plugin);
|
|
return -3;
|
|
}
|
|
|
|
obj_name = (char*) malloc(strlen(cfg_plugin_dir) + strlen(cfg_obj) + 5);
|
|
obj_name[0] = '\0';
|
|
strcat(obj_name, cfg_plugin_dir);
|
|
strcat(obj_name, "/");
|
|
strcat(obj_name, cfg_obj);
|
|
|
|
dl_handle = dlopen(obj_name, RTLD_NOW);
|
|
if (NULL == dl_handle) {
|
|
syslog(LOG_ERR, "register_all: error when dlopen: %s", dlerror());
|
|
free(obj_name);
|
|
return -4;
|
|
}
|
|
free(obj_name);
|
|
|
|
class_descriptor = (class_descriptor_t*) dlsym(dl_handle, cfg_plugin);
|
|
if (NULL != (err_msg = dlerror())) {
|
|
syslog(LOG_ERR, "register_all: plugin %s not found, error %s", cfg_plugin, err_msg);
|
|
return -5;
|
|
}
|
|
|
|
err = register_class(id++, class_descriptor);
|
|
if (0 != err) {
|
|
syslog(LOG_ERR, "register_all: unable to initialize plugin %s, error %d", cfg_plugin, err);
|
|
return -6;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|