src/module.c
branchmodules
changeset 55 6f7f6ae729d0
parent 54 9f74e924b01a
child 56 942370000450
--- a/src/module.c	Fri Mar 13 17:38:23 2009 +0200
+++ b/src/module.c	Sun Mar 15 01:17:22 2009 +0200
@@ -1,26 +1,118 @@
 #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 moduels *modules;
+    struct modules *modules;
 
     // alloc
     if ((modules = calloc(1, sizeof(*modules))) == NULL)
         return ERR_CALLOC;
     
     // init
-    TAILQ_INIT
+    TAILQ_INIT(&modules->list);
 
     // store
     modules->nexus = nexus;
+
+    // ok
+    *modules_ptr = modules;
+
+    return SUCCESS;
 }
 
-err_t module_load (struct module **module_ptr, struct nexus *nexus, const struct module_info *info, struct error_info *err)
+/**
+ * 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(suffix) <= MODULE_SUFFIX_MAX);
+
+    // format
+    sprintf(sym_name, "%s_%s", module->info.name, suffix);
+
+    // load
+    if ((*sym = dlsym(module->handle, sym_name)) == NULL) {
+        log_error("dlsym(%s, %s) failed: %s", module->info.name, sym_name, dlerror());
+
+        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;
+    module_init_func_t init_func;
 
+    // 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;
+    module->modules = modules;
 
+    // clear dlerrors
+    (void) dlerror();
+
+    // load it
+    if ((module->handle = dlopen(info->path, RTLD_NOW)) == NULL) {
+        log_error("dlopen(%s) failed: %s", info->path, dlerror());
+
+        JUMP_SET_ERROR(err, ERR_MODULE_OPEN);
+    }
+    
+    // load the init symbol    
+    if ((ERROR_CODE(err) = module_symbol(module, (void *) &init_func, "init")))
+        JUMP_SET_ERROR(err, ERR_MODULE_INIT_FUNC);
+
+    // call it
+    if ((module->ctx = init_func(modules, 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)
+{
+    module_conf_func_t conf_func;
+    err_t err;
+
+    // load the conf symbol
+    if ((err = module_symbol(module, (void *) &conf_func, "conf")))
+        return err;
+
+    // call it
+    if ((err = conf_func(module, name, value)))
+        return err;
+
+    // ok
+    return SUCCESS;
+}