diff --git a/include/modules.h b/include/modules.h index 3447e92d..bc90ed81 100644 --- a/include/modules.h +++ b/include/modules.h @@ -136,4 +136,9 @@ extern bool load_a_module(const char *, bool, int, bool); extern int findmodule_byname(const char *); extern void modules_init(void); +/* Misc externs */ +extern struct module **modlist; +extern int num_mods; +extern int max_mods; + #endif /* INCLUDED_modules_h */ diff --git a/ircd/modules.c b/ircd/modules.c index d1c24990..7f7aa5ba 100644 --- a/ircd/modules.c +++ b/ircd/modules.c @@ -54,6 +54,7 @@ static const char *core_module_table[] = { "m_kill", "m_message", "m_mode", + "m_modules", "m_nick", "m_part", "m_quit", @@ -70,49 +71,6 @@ int max_mods = MODS_INCREMENT; static rb_dlink_list mod_paths; -static void mo_modload(struct MsgBuf *, struct Client *, struct Client *, int, const char **); -static void mo_modlist(struct MsgBuf *, struct Client *, struct Client *, int, const char **); -static void mo_modreload(struct MsgBuf *, struct Client *, struct Client *, int, const char **); -static void mo_modunload(struct MsgBuf *, struct Client *, struct Client *, int, const char **); -static void mo_modrestart(struct MsgBuf *, struct Client *, struct Client *, int, const char **); - -static void me_modload(struct MsgBuf *, struct Client *, struct Client *, int, const char **); -static void me_modlist(struct MsgBuf *, struct Client *, struct Client *, int, const char **); -static void me_modreload(struct MsgBuf *, struct Client *, struct Client *, int, const char **); -static void me_modunload(struct MsgBuf *, struct Client *, struct Client *, int, const char **); -static void me_modrestart(struct MsgBuf *, struct Client *, struct Client *, int, const char **); - -static void do_modload(struct Client *, const char *); -static void do_modunload(struct Client *, const char *); -static void do_modreload(struct Client *, const char *); -static void do_modlist(struct Client *, const char *); -static void do_modrestart(struct Client *); - -struct Message modload_msgtab = { - "MODLOAD", 0, 0, 0, 0, - {mg_unreg, mg_not_oper, mg_ignore, mg_ignore, {me_modload, 2}, {mo_modload, 2}} -}; - -struct Message modunload_msgtab = { - "MODUNLOAD", 0, 0, 0, 0, - {mg_unreg, mg_not_oper, mg_ignore, mg_ignore, {me_modunload, 2}, {mo_modunload, 2}} -}; - -struct Message modreload_msgtab = { - "MODRELOAD", 0, 0, 0, 0, - {mg_unreg, mg_not_oper, mg_ignore, mg_ignore, {me_modreload, 2}, {mo_modreload, 2}} -}; - -struct Message modlist_msgtab = { - "MODLIST", 0, 0, 0, 0, - {mg_unreg, mg_not_oper, mg_ignore, mg_ignore, {me_modlist, 0}, {mo_modlist, 0}} -}; - -struct Message modrestart_msgtab = { - "MODRESTART", 0, 0, 0, 0, - {mg_unreg, mg_not_oper, mg_ignore, mg_ignore, {me_modrestart, 0}, {mo_modrestart, 0}} -}; - void modules_init(void) { @@ -122,12 +80,6 @@ modules_init(void) exit(0); } - mod_add_cmd(&modload_msgtab); - mod_add_cmd(&modunload_msgtab); - mod_add_cmd(&modreload_msgtab); - mod_add_cmd(&modlist_msgtab); - mod_add_cmd(&modrestart_msgtab); - /* Add the default paths we look in to the module system --nenolod */ mod_add_path(ircd_paths[IRCD_PATH_MODULES]); mod_add_path(ircd_paths[IRCD_PATH_AUTOLOAD_MODULES]); @@ -333,327 +285,6 @@ load_one_module(const char *path, int origin, bool coremodule) return false; } - -/* load a module .. */ -static void -mo_modload(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char **parv) -{ - if(!IsOperAdmin(source_p)) - { - sendto_one(source_p, form_str(ERR_NOPRIVS), - me.name, source_p->name, "admin"); - return; - } - - if(parc > 2) - { - sendto_match_servs(source_p, parv[2], CAP_ENCAP, NOCAPS, - "ENCAP %s MODLOAD %s", parv[2], parv[1]); - if(match(parv[2], me.name) == 0) - return; - } - - do_modload(source_p, parv[1]); -} - -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]); -} - - -/* unload a module .. */ -static void -mo_modunload(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char **parv) -{ - if(!IsOperAdmin(source_p)) - { - sendto_one(source_p, form_str(ERR_NOPRIVS), - me.name, source_p->name, "admin"); - return; - } - - if(parc > 2) - { - sendto_match_servs(source_p, parv[2], CAP_ENCAP, NOCAPS, - "ENCAP %s MODUNLOAD %s", parv[2], parv[1]); - if(match(parv[2], me.name) == 0) - return; - } - - do_modunload(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]); -} - -/* unload and load in one! */ -static void -mo_modreload(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char **parv) -{ - if(!IsOperAdmin(source_p)) - { - sendto_one(source_p, form_str(ERR_NOPRIVS), - me.name, source_p->name, "admin"); - return; - } - - if(parc > 2) - { - sendto_match_servs(source_p, parv[2], CAP_ENCAP, NOCAPS, - "ENCAP %s MODRELOAD %s", parv[2], parv[1]); - if(match(parv[2], me.name) == 0) - return; - } - - do_modreload(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]); -} - -/* list modules .. */ -static void -mo_modlist(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char **parv) -{ - if(!IsOperAdmin(source_p)) - { - sendto_one(source_p, form_str(ERR_NOPRIVS), - me.name, source_p->name, "admin"); - return; - } - - if(parc > 2) - { - sendto_match_servs(source_p, parv[2], CAP_ENCAP, NOCAPS, - "ENCAP %s MODLIST %s", parv[2], parv[1]); - if(match(parv[2], me.name) == 0) - return; - } - - do_modlist(source_p, parc > 1 ? parv[1] : 0); -} - -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]); -} - -/* unload and reload all modules */ -static void -mo_modrestart(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char **parv) -{ - if(!IsOperAdmin(source_p)) - { - sendto_one(source_p, form_str(ERR_NOPRIVS), - me.name, source_p->name, "admin"); - return; - } - - if(parc > 1) - { - sendto_match_servs(source_p, parv[1], CAP_ENCAP, NOCAPS, - "ENCAP %s MODRESTART", parv[1]); - if(match(parv[1], me.name) == 0) - return; - } - - do_modrestart(source_p); -} - -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); -} - -static void -do_modload(struct Client *source_p, const char *module) -{ - char *m_bn = rb_basename(module); - int origin; - - if(findmodule_byname(m_bn) != -1) - { - sendto_one_notice(source_p, ":Module %s is already loaded", m_bn); - rb_free(m_bn); - return; - } - - origin = strcmp(module, m_bn) == 0 ? MAPI_ORIGIN_CORE : MAPI_ORIGIN_EXTENSION; - load_one_module(module, origin, false); - - rb_free(m_bn); -} - -static void -do_modunload(struct Client *source_p, const char *module) -{ - int modindex; - 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; - } - - if(modlist[modindex]->core) - { - sendto_one_notice(source_p, ":Module %s is a core module and may not be unloaded", m_bn); - rb_free(m_bn); - return; - } - - if(unload_one_module(m_bn, true) == false) - sendto_one_notice(source_p, ":Module %s is not loaded", m_bn); - - 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); -} - -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); -} - -static void -do_modlist(struct Client *source_p, const char *pattern) -{ - int i; - - 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)) - { - 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); - } - } - 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); - } - } - - sendto_one(source_p, form_str(RPL_ENDOFMODLIST), me.name, source_p->name); -} - static void increase_modlist(void); #define MODS_INCREMENT 10 diff --git a/modules/Makefile.am b/modules/Makefile.am index ed975134..82653821 100644 --- a/modules/Makefile.am +++ b/modules/Makefile.am @@ -87,6 +87,7 @@ module_LTLIBRARIES = \ core/m_kill.la \ core/m_message.la \ core/m_mode.la \ + core/m_modules.la \ core/m_nick.la \ core/m_part.la \ core/m_quit.la \ diff --git a/modules/core/m_modules.c b/modules/core/m_modules.c new file mode 100644 index 00000000..36233a75 --- /dev/null +++ b/modules/core/m_modules.c @@ -0,0 +1,404 @@ +/* modules/m_modules.c - module for module loading + * Copyright (c) 2016 Elizabeth Myers + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "stdinc.h" +#include "client.h" +#include "parse.h" +#include "msg.h" +#include "modules.h" +#include "s_newconf.h" +#include "s_conf.h" +#include "s_serv.h" +#include "hash.h" +#include "ircd.h" +#include "match.h" +#include "numeric.h" +#include "send.h" +#include "packet.h" +#include "logger.h" + +static const char modules_desc[] = "Provides module management commands"; + +static void mo_modload(struct MsgBuf *, struct Client *, struct Client *, int, const char **); +static void mo_modlist(struct MsgBuf *, struct Client *, struct Client *, int, const char **); +static void mo_modreload(struct MsgBuf *, struct Client *, struct Client *, int, const char **); +static void mo_modunload(struct MsgBuf *, struct Client *, struct Client *, int, const char **); +static void mo_modrestart(struct MsgBuf *, struct Client *, struct Client *, int, const char **); + +static void me_modload(struct MsgBuf *, struct Client *, struct Client *, int, const char **); +static void me_modlist(struct MsgBuf *, struct Client *, struct Client *, int, const char **); +static void me_modreload(struct MsgBuf *, struct Client *, struct Client *, int, const char **); +static void me_modunload(struct MsgBuf *, struct Client *, struct Client *, int, const char **); +static void me_modrestart(struct MsgBuf *, struct Client *, struct Client *, int, const char **); + +static void do_modload(struct Client *, const char *); +static void do_modunload(struct Client *, const char *); +static void do_modreload(struct Client *, const char *); +static void do_modlist(struct Client *, const char *); +static void do_modrestart(struct Client *); + +struct Message modload_msgtab = { + "MODLOAD", 0, 0, 0, 0, + {mg_unreg, mg_not_oper, mg_ignore, mg_ignore, {me_modload, 2}, {mo_modload, 2}} +}; + +struct Message modunload_msgtab = { + "MODUNLOAD", 0, 0, 0, 0, + {mg_unreg, mg_not_oper, mg_ignore, mg_ignore, {me_modunload, 2}, {mo_modunload, 2}} +}; + +struct Message modreload_msgtab = { + "MODRELOAD", 0, 0, 0, 0, + {mg_unreg, mg_not_oper, mg_ignore, mg_ignore, {me_modreload, 2}, {mo_modreload, 2}} +}; + +struct Message modlist_msgtab = { + "MODLIST", 0, 0, 0, 0, + {mg_unreg, mg_not_oper, mg_ignore, mg_ignore, {me_modlist, 0}, {mo_modlist, 0}} +}; + +struct Message modrestart_msgtab = { + "MODRESTART", 0, 0, 0, 0, + {mg_unreg, mg_not_oper, mg_ignore, mg_ignore, {me_modrestart, 0}, {mo_modrestart, 0}} +}; + +mapi_clist_av1 modules_clist[] = { &modload_msgtab, &modunload_msgtab, &modreload_msgtab, &modlist_msgtab, &modrestart_msgtab, NULL }; + +DECLARE_MODULE_AV2(modules, NULL, NULL, modules_clist, NULL, NULL, NULL, NULL, modules_desc); + +/* load a module .. */ +static void +mo_modload(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char **parv) +{ + if(!IsOperAdmin(source_p)) + { + sendto_one(source_p, form_str(ERR_NOPRIVS), + me.name, source_p->name, "admin"); + return; + } + + if(parc > 2) + { + sendto_match_servs(source_p, parv[2], CAP_ENCAP, NOCAPS, + "ENCAP %s MODLOAD %s", parv[2], parv[1]); + if(match(parv[2], me.name) == 0) + return; + } + + do_modload(source_p, parv[1]); +} + +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]); +} + + +/* unload a module .. */ +static void +mo_modunload(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char **parv) +{ + if(!IsOperAdmin(source_p)) + { + sendto_one(source_p, form_str(ERR_NOPRIVS), + me.name, source_p->name, "admin"); + return; + } + + if(parc > 2) + { + sendto_match_servs(source_p, parv[2], CAP_ENCAP, NOCAPS, + "ENCAP %s MODUNLOAD %s", parv[2], parv[1]); + if(match(parv[2], me.name) == 0) + return; + } + + do_modunload(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]); +} + +/* unload and load in one! */ +static void +mo_modreload(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char **parv) +{ + if(!IsOperAdmin(source_p)) + { + sendto_one(source_p, form_str(ERR_NOPRIVS), + me.name, source_p->name, "admin"); + return; + } + + if(parc > 2) + { + sendto_match_servs(source_p, parv[2], CAP_ENCAP, NOCAPS, + "ENCAP %s MODRELOAD %s", parv[2], parv[1]); + if(match(parv[2], me.name) == 0) + return; + } + + do_modreload(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]); +} + +/* list modules .. */ +static void +mo_modlist(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char **parv) +{ + if(!IsOperAdmin(source_p)) + { + sendto_one(source_p, form_str(ERR_NOPRIVS), + me.name, source_p->name, "admin"); + return; + } + + if(parc > 2) + { + sendto_match_servs(source_p, parv[2], CAP_ENCAP, NOCAPS, + "ENCAP %s MODLIST %s", parv[2], parv[1]); + if(match(parv[2], me.name) == 0) + return; + } + + do_modlist(source_p, parc > 1 ? parv[1] : 0); +} + +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]); +} + +/* unload and reload all modules */ +static void +mo_modrestart(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char **parv) +{ + if(!IsOperAdmin(source_p)) + { + sendto_one(source_p, form_str(ERR_NOPRIVS), + me.name, source_p->name, "admin"); + return; + } + + if(parc > 1) + { + sendto_match_servs(source_p, parv[1], CAP_ENCAP, NOCAPS, + "ENCAP %s MODRESTART", parv[1]); + if(match(parv[1], me.name) == 0) + return; + } + + do_modrestart(source_p); +} + +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); +} + +static void +do_modload(struct Client *source_p, const char *module) +{ + char *m_bn = rb_basename(module); + int origin; + + if(findmodule_byname(m_bn) != -1) + { + sendto_one_notice(source_p, ":Module %s is already loaded", m_bn); + rb_free(m_bn); + return; + } + + origin = strcmp(module, m_bn) == 0 ? MAPI_ORIGIN_CORE : MAPI_ORIGIN_EXTENSION; + load_one_module(module, origin, false); + + rb_free(m_bn); +} + +static void +do_modunload(struct Client *source_p, const char *module) +{ + int modindex; + 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; + } + + if(modlist[modindex]->core) + { + sendto_one_notice(source_p, ":Module %s is a core module and may not be unloaded", m_bn); + rb_free(m_bn); + return; + } + + if(unload_one_module(m_bn, true) == false) + sendto_one_notice(source_p, ":Module %s is not loaded", m_bn); + + 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); +} + +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); +} + +static void +do_modlist(struct Client *source_p, const char *pattern) +{ + int i; + + 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)) + { + 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); + } + } + 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); + } + } + + sendto_one(source_p, form_str(RPL_ENDOFMODLIST), me.name, source_p->name); +}