static int module_add(irc_connection *con, config_group *group, const char *module_file) { init_module_func mod_generic_init; module_message_handler mod_msg_handler; module_init mod_init; module_close mod_close; if (module_by_name(con, Module_name(module_file), NULL)) return -9; void* module_libfile = dlopen(module_file, RTLD_NOW | RTLD_LOCAL); if (!module_libfile) { Printerr("dlopen: %s\n", dlerror()); return -1; } module_message_handler module_msg_handler = dlsym(module_libfile, "module_message_handler"); if (!module_msg_handler) return -2; LINK_FUNC(mod_generic_init, "init_module_generic", -3); mod_generic_init(irc_send_raw_msg, config_get_value, group); LINK_FUNC(mod_init, "module_init", -4); LINK_FUNC(mod_msg_handler, "module_message_handler", -5); LINK_FUNC(mod_close, "module_close", -6); if (mod_init(con)) return -7; module_listitem *p = malloc(sizeof(module_listitem)); if (!p) return -8; /* Ok, everything seems to be fine. So we can finally populate the * module structure's pointers and add it to the list of * loaded modules! */ p->name = Module_name(module_file); p->next = NULL; p->libhandle = module_libfile; p->init = mod_init; p->handle_msg = module_msg_handler; p->close = mod_close; module_listitem *l = con->modules; if (l) { while (l->next) l = l->next; l->next = p; } else con->modules = p; con->module_count++; return 0; }
int module_unload(irc_connection *con, const char *module_name) { int ret = 0; module_listitem *l = con->modules; module_listitem *l2; l = module_by_name(con, module_name, &l2); if (l == NULL) return -9; // Not found! // Remove item from list if (l2 == NULL) con->modules = l->next; else l2->next = l->next; free_module(l); con->module_count--; return ret; }
/** Resolve polymorphic item's from a module's #CONF_SECTION to a subsection in another module * * This allows certain module sections to reference module sections in other instances * of the same module and share #CONF_DATA associated with them. * * @verbatim example { data { ... } } example inst { data = example } * @endverbatim * * @param[out] out where to write the pointer to a module's config section. May be NULL on success, * indicating the config item was not found within the module #CONF_SECTION * or the chain of module references was followed and the module at the end of the chain * did not a subsection. * @param[in] module #CONF_SECTION. * @param[in] name of the polymorphic sub-section. * @return * - 0 on success with referenced section. * - 1 on success with local section. * - -1 on failure. */ int module_sibling_section_find(CONF_SECTION **out, CONF_SECTION *module, char const *name) { CONF_PAIR *cp; CONF_SECTION *cs; CONF_DATA const *cd; module_instance_t *mi; char const *inst_name; #define FIND_SIBLING_CF_KEY "find_sibling" *out = NULL; /* * Is a real section (not referencing sibling module). */ cs = cf_section_find(module, name, NULL); if (cs) { *out = cs; return 0; } /* * Item omitted completely from module config. */ cp = cf_pair_find(module, name); if (!cp) return 0; if (cf_data_find(module, CONF_SECTION, FIND_SIBLING_CF_KEY)) { cf_log_err(cp, "Module reference loop found"); return -1; } cd = cf_data_add(module, module, FIND_SIBLING_CF_KEY, false); /* * Item found, resolve it to a module instance. * This triggers module loading, so we don't have * instantiation order issues. */ inst_name = cf_pair_value(cp); mi = module_by_name(NULL, inst_name); if (!mi) { cf_log_err(cp, "Unknown module instance \"%s\"", inst_name); return -1; } if (!mi->instantiated) { CONF_SECTION *parent = module; /* * Find the root of the config... */ do { CONF_SECTION *tmp; tmp = cf_item_to_section(cf_parent(parent)); if (!tmp) break; parent = tmp; } while (true); _module_instantiate(module_by_name(NULL, inst_name), NULL); } /* * Remove the config data we added for loop * detection. */ cf_data_remove(module, cd); /* * Check the module instances are of the same type. */ if (strcmp(cf_section_name1(mi->dl_inst->conf), cf_section_name1(module)) != 0) { cf_log_err(cp, "Referenced module is a rlm_%s instance, must be a rlm_%s instance", cf_section_name1(mi->dl_inst->conf), cf_section_name1(module)); return -1; } *out = cf_section_find(mi->dl_inst->conf, name, NULL); return 1; }