src/module.c
author Tero Marttila <terom@fixme.fi>
Sun, 15 Mar 2009 23:22:57 +0200
branchmodules
changeset 57 ce1accba5fc7
parent 56 942370000450
child 65 d7508879ad01
permissions -rw-r--r--
slight cleanup to move module funcs to a 'struct module_funcs'
#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);
}