static void do_modlist(struct Client *, const char *);
static void do_modrestart(struct Client *);
+extern void modules_do_reload(void *); /* end of ircd/modules.c */
+extern void modules_do_restart(void *); /* end of ircd/modules.c */
+
struct Message modload_msgtab = {
"MODLOAD", 0, 0, 0, 0,
{mg_unreg, mg_not_oper, mg_ignore, mg_ignore, {me_modload, 2}, {mo_modload, 2}}
static void
me_modload(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char **parv)
{
- if(!find_shared_conf(source_p->username, source_p->host, source_p->servptr->name, SHARED_MODULE))
- {
- sendto_one_notice(source_p, ":*** You do not have an appropriate shared block "
- "to load modules on this server.");
- return;
- }
-
do_modload(source_p, parv[1]);
}
static void
me_modunload(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char **parv)
{
- if(!find_shared_conf(source_p->username, source_p->host, source_p->servptr->name, SHARED_MODULE))
- {
- sendto_one_notice(source_p, ":*** You do not have an appropriate shared block "
- "to load modules on this server.");
- return;
- }
-
do_modunload(source_p, parv[1]);
}
static void
me_modreload(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char **parv)
{
- if(!find_shared_conf(source_p->username, source_p->host, source_p->servptr->name, SHARED_MODULE))
- {
- sendto_one_notice(source_p, ":*** You do not have an appropriate shared block "
- "to load modules on this server.");
- return;
- }
-
do_modreload(source_p, parv[1]);
}
static void
me_modlist(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char **parv)
{
- if(!find_shared_conf(source_p->username, source_p->host, source_p->servptr->name, SHARED_MODULE))
- {
- sendto_one_notice(source_p, ":*** You do not have an appropriate shared block "
- "to load modules on this server.");
- return;
- }
-
do_modlist(source_p, parv[1]);
}
static void
me_modrestart(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char **parv)
{
- if(!find_shared_conf(source_p->username, source_p->host, source_p->servptr->name, SHARED_MODULE))
- {
- sendto_one_notice(source_p, ":*** You do not have an appropriate shared block "
- "to load modules on this server.");
- return;
- }
-
do_modrestart(source_p);
}
char *m_bn = rb_basename(module);
int origin;
- if(findmodule_byname(m_bn) != -1)
+ if(findmodule_byname(m_bn) != NULL)
{
sendto_one_notice(source_p, ":Module %s is already loaded", m_bn);
rb_free(m_bn);
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);
}
static void
do_modunload(struct Client *source_p, const char *module)
{
- int modindex;
+ struct module *mod;
char *m_bn = rb_basename(module);
- if((modindex = findmodule_byname(m_bn)) == -1)
+ if((mod = findmodule_byname(m_bn)) == NULL)
{
sendto_one_notice(source_p, ":Module %s is not loaded", m_bn);
rb_free(m_bn);
return;
}
- if(modlist[modindex]->core)
+ if(mod->core)
{
sendto_one_notice(source_p, ":Module %s is a core module and may not be unloaded", m_bn);
rb_free(m_bn);
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);
}
static void
do_modreload(struct Client *source_p, const char *module)
{
- int modindex;
- int check_core;
- char *m_bn = rb_basename(module);
-
- if((modindex = findmodule_byname(m_bn)) == -1)
- {
- sendto_one_notice(source_p, ":Module %s is not loaded", m_bn);
- rb_free(m_bn);
- return;
- }
-
- check_core = modlist[modindex]->core;
-
- if(unload_one_module(m_bn, true) == false)
- {
- sendto_one_notice(source_p, ":Module %s is not loaded", m_bn);
- rb_free(m_bn);
- return;
- }
-
- if((load_one_module(m_bn, modlist[modindex]->origin, check_core) == false) && check_core)
- {
- sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
- "Error reloading core module: %s: terminating ircd", m_bn);
- ilog(L_MAIN, "Error loading core module %s: terminating ircd", m_bn);
- exit(0);
- }
-
- rb_free(m_bn);
+ struct modreload *info = rb_malloc(sizeof *info);
+ strcpy(info->module, module);
+ strcpy(info->id, source_p->id);
+ rb_event_addonce("modules_do_reload", modules_do_reload, info, 1);
}
static void
do_modrestart(struct Client *source_p)
{
- int modnum;
-
sendto_one_notice(source_p, ":Reloading all modules");
- modnum = num_mods;
- while (num_mods)
- unload_one_module(modlist[0]->name, false);
-
- load_all_modules(false);
- load_core_modules(false);
- rehash(false);
-
- sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
- "Module Restart: %d modules unloaded, %d modules loaded",
- modnum, num_mods);
- ilog(L_MAIN, "Module Restart: %d modules unloaded, %d modules loaded", modnum, num_mods);
+ /*
+ * If a remote MODRESTART is received, m_encap.so will be reloaded,
+ * but ms_encap is in the call stack (it indirectly calls this
+ * function). Also, this function is itself in a module.
+ *
+ * This will go horribly wrong if either module is reloaded to a
+ * different address.
+ *
+ * So, defer the restart to the event loop and return now.
+ */
+ rb_event_addonce("modules_do_restart", modules_do_restart, NULL, 1);
}
static void
do_modlist(struct Client *source_p, const char *pattern)
{
- int i;
+ rb_dlink_node *ptr;
- for (i = 0; i < num_mods; i++)
+ RB_DLINK_FOREACH(ptr, module_list.head)
{
+ struct module *mod = ptr->data;
const char *origin;
- switch (modlist[i]->origin)
+ switch (mod->origin)
{
case MAPI_ORIGIN_EXTENSION:
origin = "extension";
if(pattern)
{
- if(match(pattern, modlist[i]->name))
+ if(match(pattern, mod->name))
{
sendto_one(source_p, form_str(RPL_MODLIST),
me.name, source_p->name,
- modlist[i]->name,
- (unsigned long)(uintptr_t)modlist[i]->address, origin,
- modlist[i]->core ? " (core)" : "", modlist[i]->version, modlist[i]->description);
+ mod->name,
+ (unsigned long)(uintptr_t)mod->address, origin,
+ mod->core ? " (core)" : "", mod->version, mod->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, origin,
- modlist[i]->core ? " (core)" : "", modlist[i]->version, modlist[i]->description);
+ me.name, source_p->name, mod->name,
+ (unsigned long)(uintptr_t)mod->address, origin,
+ mod->core ? " (core)" : "", mod->version, mod->description);
}
}