diff options
-rw-r--r-- | data/anope.example.conf | 11 | ||||
-rw-r--r-- | data/botserv.example.conf | 2 | ||||
-rw-r--r-- | data/chanserv.example.conf | 2 | ||||
-rw-r--r-- | data/global.example.conf | 2 | ||||
-rw-r--r-- | data/hostserv.example.conf | 2 | ||||
-rw-r--r-- | data/irc2sql.example.conf | 2 | ||||
-rw-r--r-- | data/memoserv.example.conf | 2 | ||||
-rw-r--r-- | data/nickserv.example.conf | 4 | ||||
-rw-r--r-- | data/operserv.example.conf | 2 | ||||
-rw-r--r-- | data/stats.standalone.example.conf | 15 | ||||
-rw-r--r-- | include/config.h | 9 | ||||
-rw-r--r-- | src/config.cpp | 65 |
12 files changed, 83 insertions, 35 deletions
diff --git a/data/anope.example.conf b/data/anope.example.conf index ad85cd364..8c6a96c50 100644 --- a/data/anope.example.conf +++ b/data/anope.example.conf @@ -79,13 +79,16 @@ /* * [OPTIONAL] Defines * - * You can define values to other values, which can be used to easily change - * many values in the configuration at once. + * You can use defines for repeated information, which can be used to easily change many + * values in the configuration at once. + * + * To use a define called foo.bar you use ${foo.bar} in your config file. You can also use + * environment variables by prefixing their name with "env." like ${env.USER}. */ /* * The services.host define is used in multiple different locations throughout the - * configuration for services clients hostnames. + * configuration for the server name and pseudoclient hostnames. */ define { @@ -211,7 +214,7 @@ serverinfo * other server names on the rest of your IRC network. Note that it does not have * to be an existing hostname, just one that isn't on your network already. */ - name = "services.example.com" + name = "${services.host}" /* * The text which should appear as the server's information in /WHOIS and similar diff --git a/data/botserv.example.conf b/data/botserv.example.conf index 8e7346bd1..034b6de40 100644 --- a/data/botserv.example.conf +++ b/data/botserv.example.conf @@ -31,7 +31,7 @@ service /* * The hostname of the BotServ client. */ - host = "services.host" + host = "${services.host}" /* * The realname of the BotServ client. diff --git a/data/chanserv.example.conf b/data/chanserv.example.conf index 1d742ee7b..a666e43ac 100644 --- a/data/chanserv.example.conf +++ b/data/chanserv.example.conf @@ -21,7 +21,7 @@ service /* * The hostname of the ChanServ client. */ - host = "services.host" + host = "${services.host}" /* * The realname of the ChanServ client. diff --git a/data/global.example.conf b/data/global.example.conf index 15b6347e6..6f207a692 100644 --- a/data/global.example.conf +++ b/data/global.example.conf @@ -21,7 +21,7 @@ service /* * The hostname of the Global client. */ - host = "services.host" + host = "${services.host}" /* * The realname of the Global client. diff --git a/data/hostserv.example.conf b/data/hostserv.example.conf index 4a8354a02..4c15e04a1 100644 --- a/data/hostserv.example.conf +++ b/data/hostserv.example.conf @@ -21,7 +21,7 @@ service /* * The hostname of the HostServ client. */ - host = "services.host" + host = "${services.host}" /* * The realname of the HostServ client. diff --git a/data/irc2sql.example.conf b/data/irc2sql.example.conf index f23044dab..5e090d4f2 100644 --- a/data/irc2sql.example.conf +++ b/data/irc2sql.example.conf @@ -18,7 +18,7 @@ service /* * The hostname of the StatServ client. */ - host = "stats.host" + host = "${services.host}" /* * The realname of the StatServ client. diff --git a/data/memoserv.example.conf b/data/memoserv.example.conf index e05e1c14a..7906bc14a 100644 --- a/data/memoserv.example.conf +++ b/data/memoserv.example.conf @@ -21,7 +21,7 @@ service /* * The hostname of the MemoServ client. */ - host = "services.host" + host = "${services.host}" /* * The realname of the MemoServ client. diff --git a/data/nickserv.example.conf b/data/nickserv.example.conf index d4e5c28fe..6ee4d8b15 100644 --- a/data/nickserv.example.conf +++ b/data/nickserv.example.conf @@ -21,7 +21,7 @@ service /* * The hostname of the NickServ client. */ - host = "services.host" + host = "${services.host}" /* * The realname of the NickServ client. @@ -210,7 +210,7 @@ module * hold a nickname. */ enforceruser = "enforcer" - enforcerhost = "services.host" + enforcerhost = "${services.host}" /* * The length of time Anope should hold nicknames for. diff --git a/data/operserv.example.conf b/data/operserv.example.conf index fd7ae6c95..eb85797f2 100644 --- a/data/operserv.example.conf +++ b/data/operserv.example.conf @@ -21,7 +21,7 @@ service /* * The hostname of the OperServ client. */ - host = "services.host" + host = "${services.host}" /* * The realname of the OperServ client. diff --git a/data/stats.standalone.example.conf b/data/stats.standalone.example.conf index 27af0e182..a85099529 100644 --- a/data/stats.standalone.example.conf +++ b/data/stats.standalone.example.conf @@ -79,17 +79,20 @@ /* * [OPTIONAL] Defines * - * You can define values to other values, which can be used to easily change - * many values in the configuration at once. + * You can use defines for repeated information, which can be used to easily change many + * values in the configuration at once. + * + * To use a define called foo.bar you use ${foo.bar} in your config file. You can also use + * environment variables by prefixing their name with "env." like ${env.USER}. */ /* - * The stats.host define is used in multiple different locations throughout the - * configuration for the stats client hostname. + * The services.host define is used in multiple different locations throughout the + * configuration for the server name and pseudoclient hostnames. */ define { - name = "stats.host" + name = "services.host" value = "stats.example.com" } @@ -208,7 +211,7 @@ serverinfo * other server names on the rest of your IRC network. Note that it does not have * to be an existing hostname, just one that isn't on your network already. */ - name = "stats.example.com" + name = "${services.host}" /* * The text which should appear as the server's information in /WHOIS and similar diff --git a/include/config.h b/include/config.h index 7d12d602d..d5fb9b91d 100644 --- a/include/config.h +++ b/include/config.h @@ -83,9 +83,14 @@ namespace Configuration struct Uplink; - struct CoreExport Conf final - : Block + class CoreExport Conf final + : public Block { + private: + /** Replaces defined variables within a string. */ + Anope::string ReplaceVars(const Anope::string &str, const File &file, int linenumber); + + public: /* options:readtimeout */ time_t ReadTimeout; /* If we should default to privmsging clients */ diff --git a/src/config.cpp b/src/config.cpp index e9096599c..94dd8d222 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -939,24 +939,12 @@ void Conf::LoadConf(File &file) } Block *b = block_stack.top(); - if (b) - Log(LOG_DEBUG) << "ln " << linenumber << " EOL: s='" << b->name << "' '" << itemname << "' set to '" << wordbuffer << "'"; - - /* Check defines */ - for (int i = 0; i < this->CountBlock("define"); ++i) { - const Block &define = this->GetBlock("define", i); - - const Anope::string &dname = define.Get<const Anope::string>("name"); - - if (dname == wordbuffer && &define != b) - wordbuffer = define.Get<const Anope::string>("value"); + Log(LOG_DEBUG) << "ln " << linenumber << " EOL: s='" << b->name << "' '" << itemname << "' set to '" << wordbuffer << "'"; + b->items[itemname] = ReplaceVars(wordbuffer, file, linenumber); } - if (b) - b->items[itemname] = wordbuffer; - wordbuffer.clear(); itemname.clear(); } @@ -991,3 +979,52 @@ void Conf::LoadConf(File &file) throw ConfigException("Unterminated commented block at end of file: " + file.GetName()); } } + +Anope::string Conf::ReplaceVars(const Anope::string &str, const File &file, int linenumber) +{ + Anope::string ret; + for (auto it = str.begin(); it != str.end(); ) + { + if (*it != '$') + { + ret.push_back(*it++); + continue; + } + + if (++it == str.end() || *it != '{') + continue; + + it++; + Anope::string var; + while (it != str.end() && *it != '}') + var.push_back(*it++); + + if (it == str.end()) + throw ConfigException("Unterminated variable: " + file.GetName() + ":" + Anope::ToString(linenumber)); + + it++; + if (var.compare(0, 4, "env.", 4) == 0) + { + // This is an environment variable rather than a defined variable + const char* envstr = getenv(var.c_str() + 4); + if (envstr && envstr) + ret.append(envstr); + continue; + } + + for (int i = 0; i < this->CountBlock("define"); ++i) + { + const auto &define = this->GetBlock("define", i); + const auto defname = define.Get<const Anope::string>("name"); + if (defname == var) + { + ret.append(define.Get<const Anope::string>("value")); + break; + } + } + } + + if (!str.equals_cs(ret)) + Log(LOG_DEBUG) << "Expanded \"" << str << "\" to \"" << ret << "\""; + return ret; +} |