X-Git-Url: https://jfr.im/git/solanum.git/blobdiff_plain/7baa37a9ef4c66708d7505dfda182339461232cf..ea111ea5449c763e08ca441b4bf1243af23a8b7c:/ircd/modules.c diff --git a/ircd/modules.c b/ircd/modules.c index 5887a014..09fc4a98 100644 --- a/ircd/modules.c +++ b/ircd/modules.c @@ -20,8 +20,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA - * - * $Id: modules.c 3161 2007-01-25 07:23:01Z nenolod $ */ #include "stdinc.h" @@ -37,6 +35,7 @@ #include "ircd_defs.h" #include "match.h" #include "s_serv.h" +#include "capability.h" #include @@ -59,6 +58,8 @@ static const char *core_module_table[] = { NULL }; +#define MOD_WARN_DELTA (90 * 86400) /* time in seconds, 86400 seconds in a day */ + #define MODS_INCREMENT 10 int num_mods = 0; int max_mods = MODS_INCREMENT; @@ -244,7 +245,7 @@ load_all_modules(int warn) if((len > 3) && !strcmp(ldirent->d_name+len-3, ".la")) { (void) snprintf(module_fq_name, sizeof(module_fq_name), "%s/%s", AUTOMODPATH, ldirent->d_name); - (void) load_a_module(module_fq_name, warn, 0); + (void) load_a_module(module_fq_name, warn, MAPI_ORIGIN_CORE, 0); } } @@ -269,7 +270,7 @@ load_core_modules(int warn) snprintf(module_name, sizeof(module_name), "%s/%s%s", MODPATH, core_module_table[i], ".la"); - if(load_a_module(module_name, warn, 1) == -1) + if(load_a_module(module_name, warn, MAPI_ORIGIN_CORE, 1) == -1) { ilog(L_MAIN, "Error loading core module %s%s: terminating ircd", @@ -286,7 +287,7 @@ load_core_modules(int warn) * side effects - */ int -load_one_module(const char *path, int coremodule) +load_one_module(const char *path, int origin, int coremodule) { char modpath[PATH_MAX]; rb_dlink_node *pathst; @@ -297,6 +298,12 @@ load_one_module(const char *path, int coremodule) if (server_state_foreground == 1) inotice("loading module %s ...", path); + if(coremodule != 0) + { + coremodule = 1; + origin = MAPI_ORIGIN_CORE; + } + RB_DLINK_FOREACH(pathst, mod_paths.head) { mpath = pathst->data; @@ -309,10 +316,7 @@ load_one_module(const char *path, int coremodule) if(S_ISREG(statbuf.st_mode)) { /* Regular files only please */ - if(coremodule) - return load_a_module(modpath, 1, 1); - else - return load_a_module(modpath, 1, 0); + return load_a_module(modpath, 1, origin, coremodule); } } @@ -363,6 +367,7 @@ static int do_modload(struct Client *source_p, const char *module) { char *m_bn = rb_basename(module); + int origin; if(findmodule_byname(m_bn) != -1) { @@ -371,7 +376,8 @@ do_modload(struct Client *source_p, const char *module) return 0; } - load_one_module(module, 0); + origin = strcmp(module, m_bn) == 0 ? MAPI_ORIGIN_CORE : MAPI_ORIGIN_EXTENSION; + load_one_module(module, origin, 0); rb_free(m_bn); @@ -501,7 +507,7 @@ do_modreload(struct Client *source_p, const char *module) return 0; } - if((load_one_module(m_bn, check_core) == -1) && check_core) + if((load_one_module(m_bn, modlist[modindex]->origin, check_core) == -1) && check_core) { sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Error reloading core module: %s: terminating ircd", m_bn); @@ -555,6 +561,20 @@ do_modlist(struct Client *source_p, const char *pattern) for (i = 0; i < num_mods; i++) { + const char *origin; + switch (modlist[i]->origin) + { + case MAPI_ORIGIN_EXTENSION: + origin = "extension"; + break; + case MAPI_ORIGIN_CORE: + origin = "builtin"; + break; + default: + origin = "unknown"; + break; + } + if(pattern) { if(match(pattern, modlist[i]->name)) @@ -562,16 +582,16 @@ do_modlist(struct Client *source_p, const char *pattern) sendto_one(source_p, form_str(RPL_MODLIST), me.name, source_p->name, modlist[i]->name, - (unsigned long)(uintptr_t)modlist[i]->address, - modlist[i]->version, modlist[i]->core ? "(core)" : ""); + (unsigned long)(uintptr_t)modlist[i]->address, origin, + modlist[i]->core ? " (core)" : "", modlist[i]->version, modlist[i]->description); } } else { sendto_one(source_p, form_str(RPL_MODLIST), me.name, source_p->name, modlist[i]->name, - (unsigned long)(uintptr_t)modlist[i]->address, modlist[i]->version, - modlist[i]->core ? "(core)" : ""); + (unsigned long)(uintptr_t)modlist[i]->address, origin, + modlist[i]->core ? " (core)" : "", modlist[i]->version, modlist[i]->description); } } @@ -642,6 +662,7 @@ static void increase_modlist(void); #define MODS_INCREMENT 10 static char unknown_ver[] = ""; +static char unknown_description[] = ""; /* unload_one_module() * @@ -695,6 +716,60 @@ unload_one_module(const char *name, int warn) mheader->mapi_unregister(); break; } + case 2: + { + struct mapi_mheader_av2 *mheader = modlist[modindex]->mapi_header; + + /* XXX duplicate code :( */ + if(mheader->mapi_command_list) + { + struct Message **m; + for (m = mheader->mapi_command_list; *m; ++m) + mod_del_cmd(*m); + } + + /* hook events are never removed, we simply lose the + * ability to call them --fl + */ + if(mheader->mapi_hfn_list) + { + mapi_hfn_list_av1 *m; + for (m = mheader->mapi_hfn_list; m->hapi_name; ++m) + remove_hook(m->hapi_name, m->fn); + } + + if(mheader->mapi_unregister) + mheader->mapi_unregister(); + + if(mheader->mapi_cap_list) + { + mapi_cap_list_av2 *m; + for (m = mheader->mapi_cap_list; m->cap_name; ++m) + { + struct CapabilityIndex *idx; + + switch (m->cap_index) + { + case MAPI_CAP_CLIENT: + idx = cli_capindex; + break; + case MAPI_CAP_SERVER: + idx = serv_capindex; + break; + default: + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "Unknown/unsupported CAP index found of type %d on capability %s when unloading %s", + m->cap_index, m->cap_name, modlist[modindex]->name); + ilog(L_MAIN, + "Unknown/unsupported CAP index found of type %d on capability %s when unloading %s", + m->cap_index, m->cap_name, modlist[modindex]->name); + continue; + } + + capability_orphan(idx, m->cap_name); + } + } + } default: sendto_realops_snomask(SNO_GENERAL, L_ALL, "Unknown/unsupported MAPI version %d when unloading %s!", @@ -723,20 +798,19 @@ unload_one_module(const char *name, int warn) return 0; } - /* * load_a_module() * - * inputs - path name of module, int to notice, int of core + * inputs - path name of module, int to notice, int of origin, int of core * output - -1 if error 0 if success * side effects - loads a module if successful */ int -load_a_module(const char *path, int warn, int core) +load_a_module(const char *path, int warn, int origin, int core) { lt_dlhandle tmpptr; char *mod_basename; - const char *ver; + const char *ver, *description = NULL; int *mapi_version; @@ -816,7 +890,102 @@ load_a_module(const char *path, int warn, int core) ver = mheader->mapi_module_version; break; } + case 2: + { + struct mapi_mheader_av2 *mheader = (struct mapi_mheader_av2 *)(void *)mapi_version; /* see above */ + + /* XXX duplicated code :( */ + if(mheader->mapi_register && (mheader->mapi_register() == -1)) + { + ilog(L_MAIN, "Module %s indicated failure during load.", + mod_basename); + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "Module %s indicated failure during load.", + mod_basename); + lt_dlclose(tmpptr); + rb_free(mod_basename); + return -1; + } + + /* Basic date code checks + * + * Don't make them fatal, but do complain about differences within a certain time frame. + * Later on if there are major API changes we can add fatal checks. + * -- Elizafox + */ + if(mheader->mapi_datecode != datecode && mheader->mapi_datecode > 0) + { + long int delta = datecode - mheader->mapi_datecode; + if (delta > MOD_WARN_DELTA) + { + delta /= 86400; + iwarn("Module %s build date is out of sync with ircd build date by %ld days, expect problems", + mod_basename, delta); + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "Module %s build date is out of sync with ircd build date by %ld days, expect problems", + mod_basename, delta); + } + } + + if(mheader->mapi_command_list) + { + struct Message **m; + for (m = mheader->mapi_command_list; *m; ++m) + mod_add_cmd(*m); + } + + if(mheader->mapi_hook_list) + { + mapi_hlist_av1 *m; + for (m = mheader->mapi_hook_list; m->hapi_name; ++m) + *m->hapi_id = register_hook(m->hapi_name); + } + + if(mheader->mapi_hfn_list) + { + mapi_hfn_list_av1 *m; + for (m = mheader->mapi_hfn_list; m->hapi_name; ++m) + add_hook(m->hapi_name, m->fn); + } + + /* New in MAPI v2 - version replacement */ + ver = mheader->mapi_module_version ? mheader->mapi_module_version : ircd_version; + description = mheader->mapi_module_description; + + if(mheader->mapi_cap_list) + { + mapi_cap_list_av2 *m; + for (m = mheader->mapi_cap_list; m->cap_name; ++m) + { + struct CapabilityIndex *idx; + int result; + + switch (m->cap_index) + { + case MAPI_CAP_CLIENT: + idx = cli_capindex; + break; + case MAPI_CAP_SERVER: + idx = serv_capindex; + break; + default: + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "Unknown/unsupported CAP index found of type %d on capability %s when loading %s", + m->cap_index, m->cap_name, mod_basename); + ilog(L_MAIN, + "Unknown/unsupported CAP index found of type %d on capability %s when loading %s", + m->cap_index, m->cap_name, mod_basename); + continue; + } + + result = capability_put(idx, m->cap_name, m->cap_ownerdata); + if (m->cap_id != NULL) + *(m->cap_id) = result; + } + } + } + break; default: ilog(L_MAIN, "Module %s has unknown/unsupported MAPI version %d.", mod_basename, MAPI_VERSION(*mapi_version)); @@ -831,25 +1000,45 @@ load_a_module(const char *path, int warn, int core) if(ver == NULL) ver = unknown_ver; + if(description == NULL) + description = unknown_description; + increase_modlist(); modlist[num_mods] = rb_malloc(sizeof(struct module)); modlist[num_mods]->address = tmpptr; modlist[num_mods]->version = ver; + modlist[num_mods]->description = description; modlist[num_mods]->core = core; modlist[num_mods]->name = rb_strdup(mod_basename); modlist[num_mods]->mapi_header = mapi_version; modlist[num_mods]->mapi_version = MAPI_VERSION(*mapi_version); + modlist[num_mods]->origin = origin; num_mods++; if(warn == 1) { + const char *o; + + switch (origin) + { + case MAPI_ORIGIN_EXTENSION: + o = "extension"; + break; + case MAPI_ORIGIN_CORE: + o = "core"; + break; + default: + o = "unknown"; + break; + } + sendto_realops_snomask(SNO_GENERAL, L_ALL, - "Module %s [version: %s; MAPI version: %d] loaded at 0x%lx", - mod_basename, ver, MAPI_VERSION(*mapi_version), + "Module %s [version: %s; MAPI version: %d; origin: %s; description: \"%s\"] loaded at 0x%lx", + mod_basename, ver, MAPI_VERSION(*mapi_version), o, description, (unsigned long) tmpptr); - ilog(L_MAIN, "Module %s [version: %s; MAPI version: %d] loaded at 0x%lx", - mod_basename, ver, MAPI_VERSION(*mapi_version), (unsigned long) tmpptr); + ilog(L_MAIN, "Module %s [version: %s; MAPI version: %d; origin: %s; description: \"%s\"] loaded at 0x%lx", + mod_basename, ver, MAPI_VERSION(*mapi_version), o, description, (unsigned long) tmpptr); } rb_free(mod_basename); return 0;