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