#include "module.h"
#include "log.h"
#include <stdlib.h>
#include <dlfcn.h>
#include <string.h>
#include <assert.h>
err_t modules_create (struct modules **modules_ptr, struct nexus *nexus)
{
struct modules *modules;
// alloc
if ((modules = calloc(1, sizeof(*modules))) == NULL)
return ERR_CALLOC;
// init
TAILQ_INIT(&modules->list);
// store
modules->nexus = nexus;
// ok
*modules_ptr = modules;
return SUCCESS;
}
/**
* Load the symbol named "<module>_<suffix>".
*/
static err_t module_symbol (struct module *module, void **sym, const char *suffix)
{
char sym_name[MODULE_SYMBOL_MAX];
// validate the length of the suffix
assert(strlen(module->info.name) <= MODULE_NAME_MAX);
assert(strlen(suffix) <= MODULE_SUFFIX_MAX);
// format
sprintf(sym_name, "%s_%s", module->info.name, suffix);
// load
if ((*sym = dlsym(module->handle, sym_name)) == NULL)
return ERR_MODULE_SYM;
// ok
return SUCCESS;
}
err_t module_load (struct modules *modules, struct module **module_ptr, const struct module_info *info, struct error_info *err)
{
struct module *module;
// validate the module name
if (strlen(info->name) > MODULE_NAME_MAX)
return SET_ERROR(err, ERR_MODULE_NAME);
// alloc
if ((module = calloc(1, sizeof(*module))) == NULL)
return SET_ERROR(err, ERR_CALLOC);
// store
module->info = *info;
// clear dlerrors
(void) dlerror();
// load it
if ((module->handle = dlopen(info->path, RTLD_NOW)) == NULL)
JUMP_SET_ERROR_STR(err, ERR_MODULE_OPEN, dlerror());
// load the funcs symbol
if ((ERROR_CODE(err) = module_symbol(module, (void **) &module->funcs, "funcs")))
JUMP_SET_ERROR_STR(err, ERROR_CODE(err), dlerror());
// call the init func
if ((module->funcs->init(modules->nexus, &module->ctx, err)))
goto error;
// add to modules list
TAILQ_INSERT_TAIL(&modules->list, module, modules_list);
// ok
*module_ptr = module;
return SUCCESS;
error:
// XXX: cleanup
free(module);
return ERROR_CODE(err);
}
err_t module_conf (struct module *module, const char *name, char *value, struct error_info *err)
{
// call the conf func
return module->funcs->conf(module->ctx, name, value, err);
}