diff options
-rw-r--r-- | src/poison.hpp | 1 | ||||
-rw-r--r-- | src/tool/eathena-monitor.cpp | 204 |
2 files changed, 87 insertions, 118 deletions
diff --git a/src/poison.hpp b/src/poison.hpp index 282d04d..d196bc6 100644 --- a/src/poison.hpp +++ b/src/poison.hpp @@ -21,4 +21,5 @@ #pragma GCC poison calloc #pragma GCC poison realloc #pragma GCC poison free +#pragma GCC poison strdup #endif diff --git a/src/tool/eathena-monitor.cpp b/src/tool/eathena-monitor.cpp index 30e7184..2a3e117 100644 --- a/src/tool/eathena-monitor.cpp +++ b/src/tool/eathena-monitor.cpp @@ -13,9 +13,8 @@ #include <unistd.h> #include <csignal> -#include <cstdlib> -#include <cstring> -#include <ctime> + +#include <fstream> #include "../common/cxxstdio.hpp" #include "../common/utils.hpp" @@ -29,138 +28,80 @@ #define LOGFILE "log/eathena-monitor.log" -static -void SKIP_BLANK(char *& ptr) -{ - while ( - (*ptr == ' ') || - (*ptr == '\b') || - (*ptr == '\n') || - (*ptr == '\r') - ) - ptr++; -} - -static -void GOTO_EQL(char *& ptr) { - while ( - (*ptr != '\0') && - (*ptr != '=') && - (*ptr != '\n') && - (*ptr != '\r') - ) - ptr++; -} - -static -void GOTO_EOL(char *& ptr) { - while ( - (*ptr != '\0') && - (*ptr != '\n') && - (*ptr != '\r') - ) - ptr++; -} - // initialiized to $HOME/tmwserver static -const char *workdir; +std::string workdir; //the rest are relative to workdir static -const char *login_server = LOGIN_SERVER; -static -const char *map_server = MAP_SERVER; -static -const char *char_server = CHAR_SERVER; +std::string login_server = LOGIN_SERVER; static -const char *logfile = LOGFILE; -// this variable is hard-coded, but the command-line is checked first +std::string map_server = MAP_SERVER; static -const char *config = CONFIG; +std::string char_server = CHAR_SERVER; static pid_t pid_login, pid_map, pid_char; static -const char* make_path(const char* base, const char* path) { - size_t base_len = strlen(base); - size_t path_len = strlen(path); - char* out = (char *)malloc(base_len + 1 + path_len + 1); - memcpy(out, base, base_len); - out[base_len] = '/'; - memcpy(out + base_len + 1, path, path_len); - out[base_len + 1 + path_len] = '\0'; +std::string make_path(const std::string& base, const std::string& path) +{ + std::string out(base.size() + 1 + path.size(), '\0'); + std::string::iterator it = std::copy(base.begin(), base.end(), out.begin()); + *it++ = '/'; + std::copy(path.begin(), path.end(), it); return out; } static -void parse_option(char *name, char *value) { - if (!strcasecmp(name, "login_server")) { - login_server = strdup(value); - } else if (!strcasecmp(name, "map_server")) { - map_server = strdup(value); - } else if (!strcasecmp(name, "char_server")) { - char_server = strdup(value); - } else if (!strcasecmp(name, "workdir")) { - workdir = strdup(value); - } else if (!strcasecmp(name, "logfile")) { - logfile = strdup(value); - } else { - FPRINTF(stderr, "WARNING: ingnoring invalid option '%s' = '%s'\n", name, value); - } +void parse_option(const std::string& name, const std::string& value) +{ + if (name == "login_server") + login_server = value; + else if (name == "map_server") + map_server = value; + else if (name == "char_server") + char_server = value; + else if (name == "workdir") + workdir = value; + else + FPRINTF(stderr, "WARNING: ingnoring invalid option '%s' : '%s'\n", name, value); } static -void read_config(const char *filename) { - FILE *input; - char string[1000]; - - if (!(input = fopen(filename,"r")) && !(input = fopen(config, "r"))) { - perror("Unable to load config file"); - return; +void read_config(const std::string& filename) +{ + std::ifstream in(filename); + if (!in.is_open()) + { + FPRINTF(stderr, "Monitor config file not found: %s\n", filename); + exit(1); } - while (1) { - if (fgets(string, sizeof(string) - 1, input) == NULL) - break; - char *str = string, *name, *value; - SKIP_BLANK(str); - string[sizeof(string) - 1] = '\0'; - if (*str == '#') - continue; - if (*str == '\0') - continue; - name = str; - - GOTO_EQL(str); - - if (*str != '=') { + std::string line; + while (std::getline(in, line)) + { + std::string name, value; + if (!split_key_value(line, &name, &value)) continue; - } - *str++ = '\0'; - SKIP_BLANK(str); - value = str; - GOTO_EOL(str); - *str = '\0'; parse_option(name, value); } - - fclose(input); } static -pid_t start_process(const char *exec) { - const char *args[2] = {exec, NULL}; +pid_t start_process(const std::string& exec) { + const char *args[2] = {exec.c_str(), NULL}; pid_t pid = fork(); - if (pid == -1) { + if (pid == -1) + { FPRINTF(stderr, "Failed to fork"); return 0; } - if (pid == 0) { + if (pid == 0) + { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" - execv(exec, (char**)args); + execv(exec.c_str(), (char**)args); #pragma GCC diagnostic pop perror("Failed to exec"); kill(getppid(), SIGABRT); @@ -171,15 +112,20 @@ pid_t start_process(const char *exec) { // Kill all children with the same signal we got, then ourself. static -void stop_process(int sig) { - if (pid_map) kill(pid_map, sig); - if (pid_login) kill(pid_login, sig); - if (pid_char) kill(pid_char, sig); +void stop_process(int sig) +{ + if (pid_map) + kill(pid_map, sig); + if (pid_login) + kill(pid_login, sig); + if (pid_char) + kill(pid_char, sig); signal(sig, SIG_DFL); raise(sig); } -int main(int argc, char *argv[]) { +int main(int argc, char *argv[]) +{ // These are all the signals we are likely to get // The shell handles stop/cont signal(SIGTERM, stop_process); @@ -189,9 +135,16 @@ int main(int argc, char *argv[]) { workdir = make_path(getenv("HOME"), "tmwserver"); - read_config(argc>1 ? argv[1] : NULL); + std::string config = CONFIG; + if (argc > 1) + config = argv[1]; + read_config(config); - if (chdir(workdir) < 0) perror("Failed to change directory"), exit(1); + if (chdir(workdir.c_str()) < 0) + { + perror("Failed to change directory"); + exit(1); + } PRINTF("Starting:\n"); PRINTF("* workdir: %s\n", workdir); @@ -206,32 +159,47 @@ int main(int argc, char *argv[]) { if (close(fd) == 0) FPRINTF(stderr, "close fd %d\n", fd); fd = open("/dev/null", O_RDWR); - if (fd < 0) perror("open /dev/null"), exit(1); + if (fd < 0) + { + perror("open /dev/null"); + exit(1); + } dup2(fd, 0); dup2(fd, 1); close(fd); } - while (1) { + while (1) + { // write stuff to stderr timestamp_seconds_buffer timestamp; stamp_time(timestamp); - if (!pid_login) { + if (!pid_login) + { pid_login = start_process(login_server); FPRINTF(stderr, "[%s] forked login server: %lu\n", timestamp, (unsigned long)pid_login); } - if (!pid_char) { + if (!pid_char) + { pid_char = start_process(char_server); FPRINTF(stderr, "[%s] forked char server: %lu\n", timestamp, (unsigned long)pid_char); } - if (!pid_map) { + if (!pid_map) + { pid_map = start_process(map_server); FPRINTF(stderr, "[%s] forked map server: %lu\n", timestamp, (unsigned long)pid_map); } pid_t dead = wait(NULL); - if (dead < 0) perror("Failed to wait for child"), exit(1); - if (pid_login == dead) pid_login = 0; - if (pid_char == dead) pid_char = 0; - if (pid_map == dead) pid_map = 0; + if (dead == -1) + { + perror("Failed to wait for child"); + exit(1); + } + if (pid_login == dead) + pid_login = 0; + if (pid_char == dead) + pid_char = 0; + if (pid_map == dead) + pid_map = 0; } } |