diff options
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/config_parse.cpp | 154 | ||||
-rw-r--r-- | src/common/config_parse.hpp | 36 | ||||
-rw-r--r-- | src/common/core.cpp | 18 | ||||
-rw-r--r-- | src/common/core.hpp | 5 | ||||
-rw-r--r-- | src/common/utils.cpp | 22 | ||||
-rw-r--r-- | src/common/utils.hpp | 2 | ||||
-rw-r--r-- | src/common/version.cpp | 18 | ||||
-rw-r--r-- | src/common/version.hpp | 35 |
8 files changed, 258 insertions, 32 deletions
diff --git a/src/common/config_parse.cpp b/src/common/config_parse.cpp new file mode 100644 index 0000000..d677d8e --- /dev/null +++ b/src/common/config_parse.cpp @@ -0,0 +1,154 @@ +#include "config_parse.hpp" +// config_parse.hpp - Framework for per-server config parsers. +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../strings/xstring.hpp" +#include "../strings/zstring.hpp" + +#include "../io/cxxstdio.hpp" +#include "../io/line.hpp" + +#include "version.hpp" + +#include "../poison.hpp" + +bool is_comment(XString line) +{ + return not line or line.startswith("//"); +} + +template<class ZS> +inline +bool config_split_impl(ZS line, XString *key, ZS *value) +{ + // unconditionally fail if line contains control characters + if (std::find_if(line.begin(), line.end(), + [](unsigned char c) { return c < ' '; } + ) != line.end()) + return false; + // try to find a colon, fail if not found + typename ZS::iterator colon = std::find(line.begin(), line.end(), ':'); + if (colon == line.end()) + return false; + + *key = line.xislice_h(colon).strip(); + // move past the colon and any spaces + ++colon; + *value = line.xislice_t(colon).lstrip(); + return true; +} + +// eventually this should go away +bool config_split(ZString line, XString *key, ZString *value) +{ + return config_split_impl(line, key, value); +} +// and use this instead +bool config_split(XString line, XString *key, XString *value) +{ + return config_split_impl(line, key, value); +} + +/// Master config parser. This handles 'import' and 'version-ge' etc. +/// Then it defers to the inferior parser for a line it does not understand. +bool load_config_file(ZString filename, ConfigItemParser slave) +{ + io::LineReader in(filename); + if (!in.is_open()) + { + PRINTF("Unable to open file: %s\n", filename); + return false; + } + io::Line line; + bool rv = true; + while (in.read_line(line)) + { + if (is_comment(line.text)) + continue; + XString key; + ZString value; + if (!config_split(line.text, &key, &value)) + { + line.error("Bad config line"); + rv = false; + continue; + } + if (key == "import") + { + rv &= load_config_file(value, slave); + continue; + } + else if (key == "version-lt") + { + Version vers; + if (!extract(value, &vers)) + { + rv = false; + continue; + } + if (CURRENT_VERSION < vers) + continue; + break; + } + else if (key == "version-le") + { + Version vers; + if (!extract(value, &vers)) + { + rv = false; + continue; + } + if (CURRENT_VERSION <= vers) + continue; + break; + } + else if (key == "version-gt") + { + Version vers; + if (!extract(value, &vers)) + { + rv = false; + continue; + } + if (CURRENT_VERSION > vers) + continue; + break; + } + else if (key == "version-ge") + { + Version vers; + if (!extract(value, &vers)) + { + rv = false; + continue; + } + if (CURRENT_VERSION >= vers) + continue; + break; + } + else if (!slave(key, value)) + { + line.error("Bad config key or value"); + rv = false; + continue; + } + // nothing to see here, move along + } + return rv; +} diff --git a/src/common/config_parse.hpp b/src/common/config_parse.hpp new file mode 100644 index 0000000..6a55174 --- /dev/null +++ b/src/common/config_parse.hpp @@ -0,0 +1,36 @@ +#ifndef TMWA_COMMON_CONFIG_PARSE_HPP +#define TMWA_COMMON_CONFIG_PARSE_HPP +// config_parse.hpp - Framework for per-server config parsers. +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +# include "../sanity.hpp" + +# include "../strings/fwd.hpp" + +typedef bool (*ConfigItemParser)(XString key, ZString value); + +bool is_comment(XString line); +bool config_split(ZString line, XString *key, ZString *value); +bool config_split(XString line, XString *key, XString *value); + +/// Master config parser. This handles 'import' and 'version-ge' etc. +/// Then it defers to the inferior parser for a line it does not understand. +bool load_config_file(ZString filename, ConfigItemParser slave); + +#endif // TMWA_COMMON_CONFIG_PARSE_HPP diff --git a/src/common/core.cpp b/src/common/core.cpp index 727babd..fe2f660 100644 --- a/src/common/core.cpp +++ b/src/common/core.cpp @@ -10,6 +10,8 @@ #include "../strings/zstring.hpp" +#include "../io/cxxstdio.hpp" + #include "random.hpp" #include "socket.hpp" #include "timer.hpp" @@ -46,12 +48,15 @@ sigfunc compat_signal(int signo, sigfunc func) return oact.sa_handler; } +volatile +bool runflag = true; + static void chld_proc(int) { wait(NULL); } -static __attribute__((noreturn)) +static void sig_proc(int) { for (int i = 1; i < 31; ++i) @@ -59,12 +64,9 @@ void sig_proc(int) #pragma GCC diagnostic ignored "-Wold-style-cast" compat_signal(i, SIG_IGN); #pragma GCC diagnostic pop - term_func(); - _exit(0); + runflag = false; } -bool runflag = true; - /* Note about fatal signals: @@ -83,6 +85,12 @@ int main(int argc, char **argv) for (int i = 0; i < argc; ++i) args[i] = ZString(strings::really_construct_from_a_pointer, argv[i], nullptr); do_init(argc, args); + + if (!runflag) + { + PRINTF("Fatal error during startup; exiting\n"); + return 1; + } // set up exit handlers *after* the initialization has happened. // This is because term_func is likely to depend on successful init. diff --git a/src/common/core.hpp b/src/common/core.hpp index f93f5a1..8141e9c 100644 --- a/src/common/core.hpp +++ b/src/common/core.hpp @@ -8,9 +8,8 @@ /// core.c contains a server-independent main() function /// and then runs a do_sendrecv loop -/// When this is cleared, the server exits gracefully -/// only used by map server's GM command: @mapexit -extern bool runflag; +/// When this is cleared, the server exits gracefully. +extern volatile bool runflag; /// This is an external function defined by each server /// This function must register stuff for the parse loop diff --git a/src/common/utils.cpp b/src/common/utils.cpp index 7f9a7ee..3a26e6d 100644 --- a/src/common/utils.cpp +++ b/src/common/utils.cpp @@ -65,28 +65,6 @@ int config_switch(ZString str) abort(); } -bool split_key_value(ZString line, XString *w1, ZString *w2) -{ - if (line.startswith("//")) - return false; - if (!line) - return false; - - if (std::find_if(line.begin(), line.end(), - [](unsigned char c) { return c < ' '; } - ) != line.end()) - return false; - ZString::iterator colon = std::find(line.begin(), line.end(), ':'); - if (colon == line.end()) - return false; - *w1 = line.xislice_h(colon); - ++colon; - while (std::isspace(*colon)) - ++colon; - *w2 = line.xislice_t(colon); - return true; -} - static_assert(sizeof(timestamp_seconds_buffer) == 20, "seconds buffer"); static_assert(sizeof(timestamp_milliseconds_buffer) == 24, "millis buffer"); diff --git a/src/common/utils.hpp b/src/common/utils.hpp index f975e34..161cbd4 100644 --- a/src/common/utils.hpp +++ b/src/common/utils.hpp @@ -29,8 +29,6 @@ struct is_trivially_copyable bool e_mail_check(XString email); int config_switch (ZString str); -bool split_key_value(ZString line, XString *w1, ZString *w2); - inline void really_memcpy(uint8_t *dest, const uint8_t *src, size_t n) { diff --git a/src/common/version.cpp b/src/common/version.cpp index 1ee4071..811ffdf 100644 --- a/src/common/version.cpp +++ b/src/common/version.cpp @@ -2,6 +2,18 @@ #include "../conf/version.hpp" +#include "../strings/xstring.hpp" + +#include "extract.hpp" + +Version CURRENT_VERSION = +{ + VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, + VERSION_DEVEL, + + 0, 0, + VENDOR_VERSION, +}; Version CURRENT_LOGIN_SERVER_VERSION = { VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, @@ -33,3 +45,9 @@ Version CURRENT_MAP_SERVER_VERSION = const char CURRENT_VERSION_STRING[] = "TMWA " S(VERSION_MAJOR) "." S(VERSION_MINOR) "." S(VERSION_PATCH) " dev" S(VERSION_DEVEL) " (" VENDOR " " S(VENDOR_VERSION) ")"; + +bool extract(XString str, Version *vers) +{ + *vers = {}; + return extract(str, record<'.'>(&vers->major, &vers->minor, &vers->patch)); +} diff --git a/src/common/version.hpp b/src/common/version.hpp index 677806b..a2c4e05 100644 --- a/src/common/version.hpp +++ b/src/common/version.hpp @@ -3,6 +3,8 @@ # include <cstdint> +# include "../strings/fwd.hpp" + // TODO make these bitwise enums # define TMWA_FLAG_REGISTRATION 0x01 @@ -25,10 +27,43 @@ struct Version }; static_assert(sizeof(Version) == 8, "this is sent over the network, can't change"); +extern Version CURRENT_VERSION; + extern Version CURRENT_LOGIN_SERVER_VERSION; extern Version CURRENT_CHAR_SERVER_VERSION; extern Version CURRENT_MAP_SERVER_VERSION; extern const char CURRENT_VERSION_STRING[]; +bool extract(XString str, Version *vers); + +constexpr +bool operator < (Version l, Version r) +{ + return (l.major < r.major + || (l.major == r.major + && (l.minor < r.minor + || (l.minor == r.minor + && (l.patch < r.patch + || (l.patch == r.patch + && (l.devel < r.devel + || (l.devel == r.devel + && l.vend < r.vend)))))))); +} +constexpr +bool operator > (Version l, Version r) +{ + return r < l; +} +constexpr +bool operator <= (Version l, Version r) +{ + return !(r < l); +} +constexpr +bool operator >= (Version l, Version r) +{ + return !(l < r); +} + #endif // TMWA_COMMON_VERSION_HPP |