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@57: * 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@57: assert(strlen(module->info.name) <= MODULE_NAME_MAX); 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@57: if ((*sym = dlsym(module->handle, sym_name)) == NULL) terom@57: return ERR_MODULE_SYM; 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@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@70: module->modules = modules; terom@54: terom@55: // clear dlerrors terom@55: (void) dlerror(); terom@55: terom@55: // load it terom@57: if ((module->handle = dlopen(info->path, RTLD_NOW)) == NULL) terom@57: JUMP_SET_ERROR_STR(err, ERR_MODULE_OPEN, dlerror()); terom@55: terom@57: // load the funcs symbol terom@57: if ((ERROR_CODE(err) = module_symbol(module, (void **) &module->funcs, "funcs"))) terom@57: JUMP_SET_ERROR_STR(err, ERROR_CODE(err), dlerror()); terom@55: terom@57: // call the init func terom@57: if ((module->funcs->init(modules->nexus, &module->ctx, 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@65: if (module_ptr) terom@65: *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@66: struct module* module_get (struct modules *modules, const char *name) terom@66: { terom@66: struct module *module = NULL; terom@66: terom@66: // look for it... terom@66: TAILQ_FOREACH(module, &modules->list, modules_list) { terom@66: if (strcasecmp(module->info.name, name) == 0) terom@66: // found it terom@66: return module; terom@66: } terom@66: terom@66: // no such module terom@66: return NULL; terom@66: } terom@66: terom@56: err_t module_conf (struct module *module, const char *name, char *value, struct error_info *err) terom@55: { terom@57: // call the conf func terom@57: return module->funcs->conf(module->ctx, name, value, err); terom@55: } terom@70: terom@70: err_t module_unload (struct module *module) terom@70: { terom@70: err_t err; terom@70: terom@70: // invoke the unload func terom@70: if ((err = module->funcs->unload(module->ctx))) terom@70: return err; terom@70: terom@70: // ok terom@70: return SUCCESS; terom@70: } terom@70: terom@70: void module_destroy (struct module *module) terom@70: { terom@70: // remove from modules list terom@70: TAILQ_REMOVE(&module->modules->list, module, modules_list); terom@70: terom@70: // unload the dl handle terom@70: if (dlclose(module->handle)) terom@70: log_error("dlclose(%s): %s", module->info.name, dlerror()); terom@70: terom@70: // free the module info terom@70: free(module); terom@70: } terom@70: terom@70: err_t modules_unload (struct modules *modules) terom@70: { terom@70: struct module *module; terom@70: err_t err; terom@70: terom@70: // unload each module in turn terom@70: TAILQ_FOREACH(module, &modules->list, modules_list) { terom@70: if ((err = module_unload(module))) terom@70: log_warn("module_unload(%s) failed: %s", module->info.name, error_name(err)); terom@70: } terom@70: terom@70: // ok terom@70: return SUCCESS; terom@70: } terom@70: