summaryrefslogtreecommitdiff
path: root/modules/core/os_config.cpp
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2011-03-11 00:47:28 -0500
committerAdam <Adam@anope.org>2011-03-11 00:47:28 -0500
commit1ee3d3d81034c2e2d8c1bf55db8963a50e35f363 (patch)
treed8952ff4d27e144eedd63a056971dfc2b1af5411 /modules/core/os_config.cpp
parent97c2e0957d32c87e1055041e43eb13a4a26d0765 (diff)
Added os_config and support for including additional configuration files.
Diffstat (limited to 'modules/core/os_config.cpp')
-rw-r--r--modules/core/os_config.cpp231
1 files changed, 231 insertions, 0 deletions
diff --git a/modules/core/os_config.cpp b/modules/core/os_config.cpp
new file mode 100644
index 000000000..b7335527c
--- /dev/null
+++ b/modules/core/os_config.cpp
@@ -0,0 +1,231 @@
+/* OperServ core functions
+ *
+ * (C) 2003-2011 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 CommandOSConfig : public Command
+{
+ void ChangeHash(ConfigDataHash &hash, const Anope::string &block, const Anope::string &iname, const Anope::string &value)
+ {
+ ConfigDataHash::iterator it = hash.find(block);
+
+ KeyValList &list = it->second;
+ for (unsigned i = 0; i < list.size(); ++i)
+ {
+ const Anope::string &item = list[i].first;
+ if (item == iname)
+ {
+ list[i] = std::make_pair(item, value);
+ break;
+ }
+ }
+ }
+
+ public:
+ CommandOSConfig() : Command("CONFIG", 1, 4, "operserv/config")
+ {
+ this->SetDesc("View and change configuration file settings");
+ }
+
+ CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> &params)
+ {
+ const Anope::string &what = params[0];
+
+ if (what.equals_ci("MODIFY") && params.size() > 3)
+ {
+ ConfigItems configitems(Config);
+
+ for (unsigned i = 0; !configitems.Values[i].tag.empty(); ++i)
+ {
+ ConfigItems::Item *v = &configitems.Values[i];
+ if (v->tag.equals_cs(params[1]) && v->value.equals_cs(params[2]))
+ {
+ try
+ {
+ ValueItem vi(params[3]);
+ if (!v->validation_function(Config, v->tag, v->value, vi))
+ throw ConfigException("Parameter failed to validate.");
+
+ int dt = v->datatype;
+
+ if (dt & DT_NORELOAD)
+ throw ConfigException("This item can not be changed while Anope is running.");
+ bool allow_wild = dt & DT_ALLOW_WILD;
+ dt &= ~(DT_ALLOW_NEWLINE | DT_ALLOW_WILD);
+
+ /* Yay for *massive* copypaste from config.cpp */
+ switch (dt)
+ {
+ case DT_NOSPACES:
+ {
+ ValueContainerString *vcs = debug_cast<ValueContainerString *>(v->val);
+ Config->ValidateNoSpaces(vi.GetValue(), v->tag, v->value);
+ vcs->Set(vi.GetValue());
+ break;
+ }
+ case DT_HOSTNAME:
+ {
+ ValueContainerString *vcs = debug_cast<ValueContainerString *>(v->val);
+ Config->ValidateHostname(vi.GetValue(), v->tag, v->value);
+ vcs->Set(vi.GetValue());
+ break;
+ }
+ case DT_IPADDRESS:
+ {
+ ValueContainerString *vcs = debug_cast<ValueContainerString *>(v->val);
+ Config->ValidateIP(vi.GetValue(), v->tag, v->value, allow_wild);
+ vcs->Set(vi.GetValue());
+ break;
+ }
+ case DT_CHARPTR:
+ {
+ ValueContainerChar *vcc = debug_cast<ValueContainerChar *>(v->val);
+ // Make sure we also copy the null terminator
+ vcc->Set(vi.GetString(), strlen(vi.GetString()) + 1);
+ break;
+ }
+ case DT_STRING:
+ {
+ ValueContainerString *vcs = debug_cast<ValueContainerString *>(v->val);
+ vcs->Set(vi.GetValue());
+ break;
+ }
+ case DT_INTEGER:
+ {
+ int val = vi.GetInteger();
+ ValueContainerInt *vci = debug_cast<ValueContainerInt *>(v->val);
+ vci->Set(&val, sizeof(int));
+ break;
+ }
+ case DT_UINTEGER:
+ {
+ unsigned val = vi.GetInteger();
+ ValueContainerUInt *vci = debug_cast<ValueContainerUInt *>(v->val);
+ vci->Set(&val, sizeof(unsigned));
+ break;
+ }
+ case DT_LUINTEGER:
+ {
+ unsigned long val = vi.GetInteger();
+ ValueContainerLUInt *vci = debug_cast<ValueContainerLUInt *>(v->val);
+ vci->Set(&val, sizeof(unsigned long));
+ break;
+ }
+ case DT_TIME:
+ {
+ time_t time = dotime(vi.GetValue());
+ ValueContainerTime *vci = debug_cast<ValueContainerTime *>(v->val);
+ vci->Set(&time, sizeof(time_t));
+ break;
+ }
+ case DT_BOOLEAN:
+ {
+ bool val = vi.GetBool();
+ ValueContainerBool *vcb = debug_cast<ValueContainerBool *>(v->val);
+ vcb->Set(&val, sizeof(bool));
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ catch (const ConfigException &ex)
+ {
+ source.Reply(_("Error changing configuration value: ") + ex.GetReason());
+ return MOD_CONT;
+ }
+
+ ChangeHash(Config->config_data, params[1], params[2], params[3]);
+
+ Log(LOG_ADMIN, source.u, this) << "to change the configuration value of " << params[1] << ":" << params[2] << " to " << params[3];
+ source.Reply(_("Value of %s:%s changed to %s"), params[1].c_str(), params[2].c_str(), params[3].c_str());
+ return MOD_CONT;
+ }
+ }
+
+ source.Reply("There is no configuration value named %s:%s", params[1].c_str(), params[2].c_str());
+ }
+ else if (what.equals_ci("VIEW"))
+ {
+ /* Blocks we should show */
+ const Anope::string show_blocks[] = { "botserv", "chanserv", "defcon", "global", "memoserv", "nickserv", "networkinfo", "operserv", "options", "" };
+
+ Log(LOG_ADMIN, source.u, this);
+
+ for (ConfigDataHash::const_iterator it = Config->config_data.begin(), it_end = Config->config_data.end(); it != it_end; ++it)
+ {
+ const Anope::string &bname = it->first;
+ const KeyValList &list = it->second;
+
+ bool ok = false;
+ for (unsigned i = 0; !show_blocks[i].empty(); ++i)
+ if (bname == show_blocks[i])
+ ok = true;
+ if (ok == false)
+ continue;
+
+ source.Reply(_("%s settings:"), bname.c_str());
+ for (unsigned i = 0; i < list.size(); ++i)
+ {
+ const Anope::string &first = list[i].first, second = list[i].second;
+
+ if (first == "modules")
+ continue; // Modules list isn't important
+
+ source.Reply(_(" Name: %-15s Value: %s"), first.c_str(), second.c_str());
+ }
+ }
+
+ source.Reply(_("End of configuration."));
+ }
+ else
+ this->OnSyntaxError(source, what);
+
+ return MOD_CONT;
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand)
+ {
+ source.Reply(_("Syntax: \002CONFIG {\037MODIFY\037|\037VIEW\037} [\037block name\037 \037item name\037 \037item value\037]\002\n"
+ "\n"
+ "\002CONFIG\002 allows you to change and view configuration settings.\n"
+ "Settings changed by this command are temporary and will not be reflected\n"
+ "back into the configuration file, and will be lost if Anope is shut down,\n"
+ "restarted, or the RELOAD command is used.\n"
+ " \n"
+ "Example:\n"
+ " \002CONFIG MODIFY nickserv forcemail no\002"));
+ return true;
+ }
+
+ void OnSyntaxError(CommandSource &source, const Anope::string &subcommand)
+ {
+ SyntaxError(source, "CONFIG", _("CONFIG {\037MODIFY\037|\037VIEW\037} [\037block name\037 \037item name\037 \037item value\037]"));
+ }
+};
+
+class OSConfig : public Module
+{
+ CommandOSConfig commandosconfig;
+
+ public:
+ OSConfig(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator)
+ {
+ this->SetAuthor("Anope");
+ this->SetType(CORE);
+
+ this->AddCommand(OperServ, &commandosconfig);
+ }
+};
+
+MODULE_INIT(OSConfig)