diff options
author | Adam <Adam@anope.org> | 2010-10-02 21:09:11 -0400 |
---|---|---|
committer | Adam <Adam@anope.org> | 2010-10-02 21:09:11 -0400 |
commit | 90f0a7c92ac34bc70c0905c20aaf3f7e8a85f289 (patch) | |
tree | a2bf75cc912ed3803157d10761dbea2c2475ffb1 | |
parent | 0d684191e99a689c80560018dd52e6d8fd5dc549 (diff) |
Added os_modreload. Also allow unloading database and encryption modules since there isn't a reason we cant allow reloading them. Soon os_modreload will allow reloading the protocol modules.
-rw-r--r-- | data/example.conf | 2 | ||||
-rw-r--r-- | docs/Changes.conf | 1 | ||||
-rw-r--r-- | include/language.h | 4 | ||||
-rw-r--r-- | include/modules.h | 8 | ||||
-rw-r--r-- | modules/core/os_modload.cpp | 16 | ||||
-rw-r--r-- | modules/core/os_modreload.cpp | 112 | ||||
-rw-r--r-- | modules/core/os_modunload.cpp | 22 | ||||
-rw-r--r-- | src/language.cpp | 10 | ||||
-rw-r--r-- | src/modulemanager.cpp | 47 |
9 files changed, 173 insertions, 49 deletions
diff --git a/data/example.conf b/data/example.conf index 8f86e44a3..f80f9346e 100644 --- a/data/example.conf +++ b/data/example.conf @@ -1339,7 +1339,7 @@ operserv * The core modules to load for OperServ. This is a space separated list that corresponds * to the base names of the modules for OperServ. This directive is optional, but highly recommended. */ - modules = "os_help os_global os_stats os_staff os_mode os_kick os_clearmodes os_akill os_snline os_sqline os_szline os_chanlist os_userlist os_news os_session os_noop os_jupe os_ignore os_set os_reload os_update os_restart os_quit os_shutdown os_defcon os_chankill os_svsnick os_oline os_umode os_modload os_modunload os_modlist os_modinfo" + modules = "os_help os_global os_stats os_staff os_mode os_kick os_clearmodes os_akill os_snline os_sqline os_szline os_chanlist os_userlist os_news os_session os_noop os_jupe os_ignore os_set os_reload os_update os_restart os_quit os_shutdown os_defcon os_chankill os_svsnick os_oline os_umode os_modload os_modunload os_modreload os_modlist os_modinfo" /* * If set, Services Admins will be able to use SUPERADMIN [ON|OFF] which will temporarily grant diff --git a/docs/Changes.conf b/docs/Changes.conf index eddd317b8..bd9c438b0 100644 --- a/docs/Changes.conf +++ b/docs/Changes.conf @@ -18,6 +18,7 @@ m_dnsbl added ** MODIFIED CONFIGURATION DIRECTIVES ** opertype:commands changed operserv/sgline to opserv/snline operserv:modules changed os_sgline to os_snline +operserv:modules added os_modreload operserv:sglineexpiry changed to operserv:snlineexpiry operserv:killonsgline changed to operserv:killonsnline operserv:notifications ossgline changed ossnline diff --git a/include/language.h b/include/language.h index 79e082ebf..a9a88bdde 100644 --- a/include/language.h +++ b/include/language.h @@ -1121,6 +1121,7 @@ enum LanguageString DEFCON_GLOBAL, OPER_MODULE_LOADED, OPER_MODULE_UNLOADED, + OPER_MODULE_RELOADED, OPER_MODULE_LOAD_FAIL, OPER_MODULE_REMOVE_FAIL, OPER_MODULE_NO_UNLOAD, @@ -1128,6 +1129,7 @@ enum LanguageString OPER_MODULE_ISNT_LOADED, OPER_MODULE_LOAD_SYNTAX, OPER_MODULE_UNLOAD_SYNTAX, + OPER_MODULE_RELOAD_SYNTAX, OPER_MODULE_LIST_HEADER, OPER_MODULE_LIST, OPER_MODULE_LIST_FOOTER, @@ -1514,6 +1516,7 @@ enum LanguageString OPER_HELP_CMD_SVSNICK, OPER_HELP_CMD_MODLOAD, OPER_HELP_CMD_MODUNLOAD, + OPER_HELP_CMD_MODRELOAD, OPER_HELP_CMD_MODINFO, OPER_HELP_CMD_MODLIST, OPER_HELP, @@ -1550,6 +1553,7 @@ enum LanguageString OPER_HELP_USERLIST, OPER_HELP_MODLOAD, OPER_HELP_MODUNLOAD, + OPER_HELP_MODRELOAD, OPER_HELP_MODINFO, OPER_HELP_MODLIST, BOT_HELP_CMD_BOTLIST, diff --git a/include/modules.h b/include/modules.h index ab3472132..a48e7385f 100644 --- a/include/modules.h +++ b/include/modules.h @@ -148,7 +148,9 @@ enum ModuleReturn MOD_ERR_UNKNOWN, MOD_ERR_FILE_IO, MOD_ERR_NOSERVICE, - MOD_ERR_NO_MOD_NAME + MOD_ERR_NO_MOD_NAME, + MOD_ERR_EXCEPTION, + MOD_ERR_VERSION }; /** Priority types which can be returned from Module::Prioritize() @@ -1106,14 +1108,14 @@ class CoreExport ModuleManager * @param u the user who loaded it, NULL for auto-load * @return MOD_ERR_OK on success, anything else on fail */ - static int LoadModule(const Anope::string &modname, User *u); + static ModuleReturn LoadModule(const Anope::string &modname, User *u); /** Unload the given module. * @param m the module to unload * @param u the user who unloaded it * @return MOD_ERR_OK on success, anything else on fail */ - static int UnloadModule(Module *m, User * u); + static ModuleReturn UnloadModule(Module *m, User * u); /** Change the priority of one event in a module. * Each module event has a list of modules which are attached to that event type. If you wish to be called before or after other specific modules, you may use this diff --git a/modules/core/os_modload.cpp b/modules/core/os_modload.cpp index b35cf0730..385353993 100644 --- a/modules/core/os_modload.cpp +++ b/modules/core/os_modload.cpp @@ -31,11 +31,21 @@ class CommandOSModLoad : public Command return MOD_CONT; } - int status = ModuleManager::LoadModule(mname, u); - if (status != MOD_ERR_OK) + ModuleReturn status = ModuleManager::LoadModule(mname, u); + if (status == MOD_ERR_OK) { - u->SendMessage(OperServ, OPER_MODULE_LOAD_FAIL, mname.c_str()); + ircdproto->SendGlobops(OperServ, "%s loaded module %s", u->nick.c_str(), mname.c_str()); + u->SendMessage(OperServ, OPER_MODULE_LOADED, mname.c_str()); + + /* If a user is loading this module, then the core databases have already been loaded + * so trigger the event manually + */ + m = FindModule(mname); + if (m) + m->OnPostLoadDatabases(); } + else + u->SendMessage(OperServ, OPER_MODULE_LOAD_FAIL, mname.c_str()); return MOD_CONT; } diff --git a/modules/core/os_modreload.cpp b/modules/core/os_modreload.cpp new file mode 100644 index 000000000..5cb8c60e8 --- /dev/null +++ b/modules/core/os_modreload.cpp @@ -0,0 +1,112 @@ +/* OperServ core functions + * + * (C) 2003-2010 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + */ + +/*************************************************************************/ + +#include "module.h" + +class CommandOSModReLoad : public Command +{ + public: + CommandOSModReLoad() : Command("MODRELOAD", 1, 1, "operserv/modload") + { + } + + CommandReturn Execute(User *u, const std::vector<Anope::string> ¶ms) + { + Anope::string mname = params[0]; + + Module *m = FindModule(mname); + if (!m) + { + u->SendMessage(OperServ, OPER_MODULE_ISNT_LOADED, mname.c_str()); + return MOD_CONT; + } + + if (!m->handle) + { + u->SendMessage(OperServ, OPER_MODULE_REMOVE_FAIL, m->name.c_str()); + return MOD_CONT; + } + + if (m->GetPermanent() || m->type == PROTOCOL) // TODO: make protocol modules reloadable + { + u->SendMessage(OperServ, OPER_MODULE_NO_UNLOAD); + return MOD_CONT; + } + + /* Unrecoverable */ + bool fatal = m->type == PROTOCOL; + ModuleReturn status = ModuleManager::UnloadModule(m, u); + + if (status != MOD_ERR_OK) + { + u->SendMessage(OperServ, OPER_MODULE_REMOVE_FAIL, mname.c_str()); + return MOD_CONT; + } + + status = ModuleManager::LoadModule(mname, u); + if (status == MOD_ERR_OK) + { + ircdproto->SendGlobops(OperServ, "%s reloaded module %s", u->nick.c_str(), mname.c_str()); + u->SendMessage(OperServ, OPER_MODULE_RELOADED, mname.c_str()); + + /* If a user is loading this module, then the core databases have already been loaded + * so trigger the event manually + */ + m = FindModule(mname); + if (m) + m->OnPostLoadDatabases(); + } + else + { + if (fatal) + throw FatalException("Unable to reload module " + mname); + else + u->SendMessage(OperServ, OPER_MODULE_LOAD_FAIL, mname.c_str()); + } + + return MOD_CONT; + } + + bool OnHelp(User *u, const Anope::string &subcommand) + { + u->SendMessage(OperServ, OPER_HELP_MODRELOAD); + return true; + } + + void OnSyntaxError(User *u, const Anope::string &subcommand) + { + SyntaxError(OperServ, u, "MODLOAD", OPER_MODULE_RELOAD_SYNTAX); + } + + void OnServHelp(User *u) + { + u->SendMessage(OperServ, OPER_HELP_CMD_MODRELOAD); + } +}; + +class OSModReLoad : public Module +{ + CommandOSModReLoad commandosmodreload; + + public: + OSModReLoad(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator) + { + this->SetAuthor("Anope"); + this->SetType(CORE); + this->SetPermanent(true); + + this->AddCommand(OperServ, &commandosmodreload); + } +}; + +MODULE_INIT(OSModReLoad) diff --git a/modules/core/os_modunload.cpp b/modules/core/os_modunload.cpp index cf00676c4..f8bbe0461 100644 --- a/modules/core/os_modunload.cpp +++ b/modules/core/os_modunload.cpp @@ -23,7 +23,6 @@ class CommandOSModUnLoad : public Command CommandReturn Execute(User *u, const std::vector<Anope::string> ¶ms) { Anope::string mname = params[0]; - int status; Module *m = FindModule(mname); if (!m) @@ -31,12 +30,29 @@ class CommandOSModUnLoad : public Command u->SendMessage(OperServ, OPER_MODULE_ISNT_LOADED, mname.c_str()); return MOD_CONT; } + + if (!m->handle) + { + u->SendMessage(OperServ, OPER_MODULE_REMOVE_FAIL, m->name.c_str()); + return MOD_CONT; + } + + if (m->GetPermanent() || m->type == PROTOCOL) + { + u->SendMessage(OperServ, OPER_MODULE_NO_UNLOAD); + return MOD_CONT; + } Log() << "Trying to unload module [" << mname << "]"; - status = ModuleManager::UnloadModule(m, u); + ModuleReturn status = ModuleManager::UnloadModule(m, u); - if (status != MOD_ERR_OK) + if (status == MOD_ERR_OK) + { + u->SendMessage(OperServ, OPER_MODULE_UNLOADED, mname.c_str()); + ircdproto->SendGlobops(OperServ, "%s unloaded module %s", u->nick.c_str(), mname.c_str()); + } + else u->SendMessage(OperServ, OPER_MODULE_REMOVE_FAIL, mname.c_str()); return MOD_CONT; diff --git a/src/language.cpp b/src/language.cpp index 8fd15a693..91b28e3df 100644 --- a/src/language.cpp +++ b/src/language.cpp @@ -2430,6 +2430,8 @@ Anope::string language_strings[LANG_STRING_COUNT] = { _("Module %s loaded"), /* OPER_MODULE_UNLOADED */ _("Module %s unloaded"), + /* OPER_MODULE_RELOADED */ + _("Module \002%s\002 reloaded"), /* OPER_MODULE_LOAD_FAIL */ _("Unable to load module %s"), /* OPER_MODULE_REMOVE_FAIL */ @@ -2444,6 +2446,8 @@ Anope::string language_strings[LANG_STRING_COUNT] = { _("MODLOAD FileName"), /* OPER_MODULE_UNLOAD_SYNTAX */ _("MODUNLOAD FileName"), + /* OPER_MODULE_RELOAD_SYNTAX */ + _("MODRELOAD \037FileName\037"), /* OPER_MODULE_LIST_HEADER */ _("Current Module list:"), /* OPER_MODULE_LIST */ @@ -4570,6 +4574,8 @@ Anope::string language_strings[LANG_STRING_COUNT] = { _(" MODLOAD Load a module"), /* OPER_HELP_CMD_MODUNLOAD */ _(" MODUNLOAD Un-Load a module"), + /* OPER_HELP_CMD_MODRELOAD */ + _(" MODRELOAD Reload a module"), /* OPER_HELP_CMD_MODINFO */ _(" MODINFO Info about a loaded module"), /* OPER_HELP_CMD_MODLIST */ @@ -4977,6 +4983,10 @@ Anope::string language_strings[LANG_STRING_COUNT] = { " \n" "This command unloads the module named FileName from the modules\n" "directory."), + /* OPER_HELP_MODRELOAD */ + _("Syntax: \002MODRELOAD\002 \002FileName\002\n" + " \n" + "This command reloads the module named FileName."), /* OPER_HELP_MODINFO */ _("Syntax: MODINFO FileName\n" " \n" diff --git a/src/modulemanager.cpp b/src/modulemanager.cpp index e637d32c6..2c716acf6 100644 --- a/src/modulemanager.cpp +++ b/src/modulemanager.cpp @@ -28,7 +28,7 @@ void ModuleManager::LoadModuleList(std::list<Anope::string> &ModuleList) * @param output the destination to copy the module to * @return MOD_ERR_OK on success */ -static int moduleCopyFile(const Anope::string &name, Anope::string &output) +static ModuleReturn moduleCopyFile(const Anope::string &name, Anope::string &output) { Anope::string input = services_dir + "/modules/" + name + ".so"; FILE *source = fopen(input.c_str(), "rb"); @@ -107,7 +107,7 @@ template <class TYPE> TYPE function_cast(ano_module_t symbol) return cast.function; } -int ModuleManager::LoadModule(const Anope::string &modname, User *u) +ModuleReturn ModuleManager::LoadModule(const Anope::string &modname, User *u) { if (modname.empty()) return MOD_ERR_PARAMS; @@ -121,7 +121,7 @@ int ModuleManager::LoadModule(const Anope::string &modname, User *u) Anope::string pbuf = services_dir + "/modules/runtime/" + modname + ".so.XXXXXX"; /* Don't skip return value checking! -GD */ - int ret = moduleCopyFile(modname, pbuf); + ModuleReturn ret = moduleCopyFile(modname, pbuf); if (ret != MOD_ERR_OK) { /* XXX: This used to assign filename here, but I don't think that was correct.. @@ -167,7 +167,7 @@ int ModuleManager::LoadModule(const Anope::string &modname, User *u) catch (const ModuleException &ex) { Log() << "Error while loading " << modname << ": " << ex.GetReason(); - return MOD_STOP; + return MOD_ERR_EXCEPTION; } m->filename = pbuf; @@ -178,13 +178,13 @@ int ModuleManager::LoadModule(const Anope::string &modname, User *u) { Log() << "Module " << modname << " is compiled against an older version of Anope " << v.GetMajor() << "." << v.GetMinor() << ", this is " << VERSION_MAJOR << "." << VERSION_MINOR; DeleteModule(m); - return MOD_STOP; + return MOD_ERR_VERSION; } else if (v.GetMajor() > VERSION_MAJOR || (v.GetMajor() == VERSION_MAJOR && v.GetMinor() > VERSION_MINOR)) { Log() << "Module " << modname << " is compiled against a newer version of Anope " << v.GetMajor() << "." << v.GetMinor() << ", this is " << VERSION_MAJOR << "." << VERSION_MINOR; DeleteModule(m); - return MOD_STOP; + return MOD_ERR_VERSION; } else if (v.GetBuild() < VERSION_BUILD) Log() << "Module " << modname << " is compiled against an older revision of Anope " << v.GetBuild() << ", this is " << VERSION_BUILD; @@ -197,18 +197,7 @@ int ModuleManager::LoadModule(const Anope::string &modname, User *u) { DeleteModule(m); Log() << "You cannot load two protocol modules"; - return MOD_STOP; - } - - if (u) - { - ircdproto->SendGlobops(OperServ, "%s loaded module %s", u->nick.c_str(), modname.c_str()); - u->SendMessage(OperServ, OPER_MODULE_LOADED, modname.c_str()); - - /* If a user is loading this module, then the core databases have already been loaded - * so trigger the event manually - */ - m->OnPostLoadDatabases(); + return MOD_ERR_UNKNOWN; } FOREACH_MOD(I_OnModuleLoad, OnModuleLoad(u, m)); @@ -216,28 +205,8 @@ int ModuleManager::LoadModule(const Anope::string &modname, User *u) return MOD_ERR_OK; } -int ModuleManager::UnloadModule(Module *m, User *u) +ModuleReturn ModuleManager::UnloadModule(Module *m, User *u) { - if (!m || !m->handle) - { - if (u) - u->SendMessage(OperServ, OPER_MODULE_REMOVE_FAIL, m->name.c_str()); - return MOD_ERR_PARAMS; - } - - if (m->GetPermanent() || m->type == PROTOCOL || m->type == ENCRYPTION || m->type == DATABASE) - { - if (u) - u->SendMessage(OperServ, OPER_MODULE_NO_UNLOAD); - return MOD_ERR_NOUNLOAD; - } - - if (u) - { - ircdproto->SendGlobops(OperServ, "%s unloaded module %s", u->nick.c_str(), m->name.c_str()); - u->SendMessage(OperServ, OPER_MODULE_UNLOADED, m->name.c_str()); - } - FOREACH_MOD(I_OnModuleUnload, OnModuleUnload(u, m)); if (DNSEngine) |