diff --git a/include/modules.h b/include/modules.h index 141d78e0..bfc502f1 100644 --- a/include/modules.h +++ b/include/modules.h @@ -122,6 +122,10 @@ struct mapi_mheader_av2 void mod_add_path(const char *path); void mod_clear_paths(void); +/* cap-notify utilities */ +extern void mod_remember_clicaps(void); +extern void mod_notify_clicaps(void); + /* load a module */ extern void load_module(char *path); diff --git a/ircd/modules.c b/ircd/modules.c index e1d9a564..b477e182 100644 --- a/ircd/modules.c +++ b/ircd/modules.c @@ -80,6 +80,29 @@ init_modules(void) mod_add_path(ircd_paths[IRCD_PATH_AUTOLOAD_MODULES]); } +static unsigned int prev_caps; + +void +mod_remember_clicaps(void) +{ + prev_caps = capability_index_mask(cli_capindex); +} + +void +mod_notify_clicaps(void) +{ + unsigned int cur_caps = capability_index_mask(cli_capindex); + unsigned int del = prev_caps & ~cur_caps; + unsigned int new = cur_caps & ~prev_caps; + + if (del) + sendto_local_clients_with_capability(CLICAP_CAP_NOTIFY, ":%s CAP * DEL :%s", + me.name, capability_index_list(cli_capindex, del)); + if (new) + sendto_local_clients_with_capability(CLICAP_CAP_NOTIFY, ":%s CAP * NEW :%s", + me.name, capability_index_list(cli_capindex, new)); +} + /* mod_find_path() * * input - path @@ -382,10 +405,7 @@ unload_one_module(const char *name, bool warn) } if (m->cap_id != NULL) - { capability_orphan(idx, m->cap_name); - sendto_local_clients_with_capability(CLICAP_CAP_NOTIFY, ":%s CAP * DEL :%s", me.name, m->cap_name); - } } } break; @@ -600,10 +620,7 @@ load_a_module(const char *path, bool warn, int origin, bool core) result = capability_put(idx, m->cap_name, m->cap_ownerdata); if (m->cap_id != NULL) - { *(m->cap_id) = result; - sendto_local_clients_with_capability(CLICAP_CAP_NOTIFY, ":%s CAP * ADD :%s", me.name, m->cap_name); - } } } } @@ -671,6 +688,8 @@ modules_do_restart(void *unused) unsigned int modnum = 0; rb_dlink_node *ptr, *nptr; + mod_remember_clicaps(); + RB_DLINK_FOREACH_SAFE(ptr, nptr, module_list.head) { struct module *mod = ptr->data; @@ -694,6 +713,8 @@ modules_do_restart(void *unused) load_core_modules(false); rehash(false); + mod_notify_clicaps(); + sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Module Restart: %u modules unloaded, %lu modules loaded", modnum, rb_dlink_list_length(&module_list)); diff --git a/modules/core/m_modules.c b/modules/core/m_modules.c index 312d26d1..ecc54b2d 100644 --- a/modules/core/m_modules.c +++ b/modules/core/m_modules.c @@ -274,9 +274,13 @@ do_modload(struct Client *source_p, const char *module) return; } + mod_remember_clicaps(); + origin = strcmp(module, m_bn) == 0 ? MAPI_ORIGIN_CORE : MAPI_ORIGIN_EXTENSION; load_one_module(module, origin, false); + mod_notify_clicaps(); + rb_free(m_bn); } @@ -300,9 +304,13 @@ do_modunload(struct Client *source_p, const char *module) return; } + mod_remember_clicaps(); + if(unload_one_module(m_bn, true) == false) sendto_one_notice(source_p, ":Module %s is not loaded", m_bn); + mod_notify_clicaps(); + rb_free(m_bn); } @@ -322,6 +330,8 @@ do_modreload(struct Client *source_p, const char *module) check_core = mod->core; + mod_remember_clicaps(); + if(unload_one_module(m_bn, true) == false) { sendto_one_notice(source_p, ":Module %s is not loaded", m_bn); @@ -337,6 +347,8 @@ do_modreload(struct Client *source_p, const char *module) exit(0); } + mod_notify_clicaps(); + rb_free(m_bn); }