From 09d88fc3db9265732c7960ee52240b1196dcee71 Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Fri, 26 Jun 2020 22:26:14 +0200 Subject: Split off all server functionality to a separate file --- minecctl/meson.build | 1 + minecctl/minecctl-rcon.c | 3 +- minecctl/minecctl.c | 200 +++-------------------------------------------- minecctl/minecctl.h | 14 ---- minecctl/server.c | 198 ++++++++++++++++++++++++++++++++++++++++++++++ minecctl/server.h | 28 +++++++ 6 files changed, 238 insertions(+), 206 deletions(-) create mode 100644 minecctl/server.c create mode 100644 minecctl/server.h diff --git a/minecctl/meson.build b/minecctl/meson.build index 6db6489..a3a0813 100644 --- a/minecctl/meson.build +++ b/minecctl/meson.build @@ -1,6 +1,7 @@ minecctl_sources = [ 'minecctl.c', 'minecctl-rcon.c', + 'server.c', 'misc.c', ] diff --git a/minecctl/minecctl-rcon.c b/minecctl/minecctl-rcon.c index 96d3522..237ef51 100644 --- a/minecctl/minecctl-rcon.c +++ b/minecctl/minecctl-rcon.c @@ -12,6 +12,7 @@ #include "utils.h" #include "minecctl.h" #include "minecctl-rcon.h" +#include "server.h" #include "rcon-protocol.h" #include "misc.h" @@ -366,7 +367,7 @@ do_stop_all(struct cfg *cfg) { struct server *server; list_for_each_entry(server, &cfg->servers, list) { - read_server_config(server); + read_server_config(cfg, server); stop_one_server(cfg, server); } } diff --git a/minecctl/minecctl.c b/minecctl/minecctl.c index 90939ee..27c2066 100644 --- a/minecctl/minecctl.c +++ b/minecctl/minecctl.c @@ -16,9 +16,9 @@ #include "minecctl.h" #include "minecctl-commands.h" #include "minecctl-rcon.h" -#include "config-parser.h" -#include "server-config-options.h" +#include "server.h" #include "misc.h" +#include "config-parser.h" #include "config.h" static struct cfg *cfg = NULL; @@ -55,93 +55,6 @@ dump_config() info("============="); } -void -read_server_config(struct server *server) -{ - char buf[4096]; - size_t off = 0; - ssize_t r; - int dfd; - int fd; - char *pos = buf; - - if (!server || !server->filename || server->file_read) - return; - - server->file_read = true; - - dfd = open(cfg->cfgdir, O_DIRECTORY | O_PATH | O_CLOEXEC); - if (dfd < 0) - die("Failed to open %s: %m", cfg->cfgdir); - - fd = openat(dfd, server->filename, O_RDONLY | O_CLOEXEC); - if (fd < 0) - die("Failed to open %s: %m", server->filename); - - close(dfd); - - while (true) { - r = read(fd, buf + off, sizeof(buf) - off - 1); - if (r < 0) - die("Failed to read %s: %m", server->filename); - else if (r == 0) - break; - - off += r; - if (off == sizeof(buf) - 1) - die("Failed to read %s: file too large", server->filename); - } - - buf[off] = '\0'; - close(fd); - - if (!config_parse_header(SERVER_CFG_HEADER, &pos)) - die("Unable to parse %s: invalid/missing header", - server->filename); - - /* FIXME: this will cause superflous DNS lookups of other cfg entries */ - while (true) { - int key; - const char *keyname; - struct cfg_value value; - - if (!config_parse_line(server->filename, &pos, scfg_key_map, - &key, &keyname, &value, false)) - break; - - switch (key) { - case SCFG_KEY_RCON: - if (!list_empty(&server->rcon_addrs)) - die("rcon address defined twice in %s", - server->filename); - list_replace(&value.saddrs, &server->rcon_addrs); - break; - case SCFG_KEY_RCON_PASSWORD: - if (server->rcon_password) - die("rcon password defined twice in %s", - server->filename); - server->rcon_password = xstrdup(value.str); - break; - case SCFG_KEY_REMOTE: - if (!list_empty(&server->mc_addrs)) - die("rcon address defined twice in %s", - server->filename); - list_replace(&value.saddrs, &server->mc_addrs); - default: - continue; - } - } - - if (!server->rcon_password) - verbose("rcon password not found in %s", server->filename); - - if (list_empty(&server->rcon_addrs)) - verbose("rcon address not found in %s", server->filename); - - if (list_empty(&server->mc_addrs)) - verbose("mc server address not found in %s", server->filename); -} - _noreturn_ static void usage(bool no_error) { @@ -180,74 +93,6 @@ usage(bool no_error) exit(no_error ? EXIT_FAILURE : EXIT_SUCCESS); } -static struct server * -server_new() -{ - struct server *server; - - server = zmalloc(sizeof(*server)); - INIT_LIST_HEAD(&server->rcon_addrs); - INIT_LIST_HEAD(&server->mc_addrs); - INIT_LIST_HEAD(&server->list); - - return server; -} - -static void -server_free(struct server *server) -{ - struct saddr *saddr, *tmp; - - xfree(server->name); - xfree(server->filename); - free_password(&server->rcon_password); - - list_for_each_entry_safe(saddr, tmp, &server->rcon_addrs, list) { - list_del(&saddr->list); - xfree(saddr); - } - - list_for_each_entry_safe(saddr, tmp, &server->mc_addrs, list) { - list_del(&saddr->list); - xfree(saddr); - } - - xfree(server); -} - -static void -get_servers() -{ - struct dirent *dent; - DIR *dir; - - dir = opendir(cfg->cfgdir); - if (!dir) { - info("Can't open config directory %s: %m", cfg->cfgdir); - return; - } - - while ((dent = readdir(dir))) { - struct server *server; - char *suffix; - - if (!is_valid_server_config_filename(dent, NULL)) - continue; - - server = server_new(); - server->filename = xstrdup(dent->d_name); - - suffix = strrchr(dent->d_name, '.'); - assert_die(suffix, "Error parsing filename"); - *suffix = '\0'; - server->name = xstrdup(dent->d_name); - - list_add(&server->list, &cfg->servers); - } - - closedir(dir); -} - static bool str_to_addrs(const char *str, struct list_head *list) { @@ -334,38 +179,6 @@ do_list(struct cfg *cfg) info("%s", server->name); } -struct server * -get_default_server(struct cfg *cfg) -{ - struct server *server; - - server = list_first_entry_or_null(&cfg->servers, struct server, list); - if (!server) - die("No servers defined"); - - read_server_config(server); - - return server; -} - -static void -set_default_server(const char *name) -{ - struct server *server; - - assert_die(cfg, "invalid arguments"); - - list_for_each_entry(server, &cfg->servers, list) { - if (streq(name, server->name)) { - list_rotate_to_front(&server->list, &cfg->servers); - return; - } - } - - error("\"%s\" is not a known server or command", name); - usage(false); -} - static inline void get_optional_server_arg(char * const **argv, bool more) { @@ -374,7 +187,12 @@ get_optional_server_arg(char * const **argv, bool more) error("Missing arguments"); usage(false); } - set_default_server(**argv); + + if (!set_default_server(cfg, **argv)) { + error("\"%s\" is not a known server or command", **argv); + usage(false); + } + (*argv)++; } @@ -571,7 +389,7 @@ main(int argc, char **argv) parse_cmdline(argc, argv); - get_servers(); + get_servers(cfg); parse_command(&argv[optind]); diff --git a/minecctl/minecctl.h b/minecctl/minecctl.h index 9e3d79b..0b8b2cf 100644 --- a/minecctl/minecctl.h +++ b/minecctl/minecctl.h @@ -1,16 +1,6 @@ #ifndef foominecctlhfoo #define foominecctlhfoo -struct server { - bool file_read; - char *name; - char *filename; - char *rcon_password; - struct list_head rcon_addrs; - struct list_head mc_addrs; - struct list_head list; -}; - struct cfg { /* command line arguments */ const char *cfgdir; @@ -25,9 +15,5 @@ struct cfg { struct list_head servers; }; -void read_server_config(struct server *server); - -struct server *get_default_server(struct cfg *cfg); - #endif diff --git a/minecctl/server.c b/minecctl/server.c new file mode 100644 index 0000000..8a32486 --- /dev/null +++ b/minecctl/server.c @@ -0,0 +1,198 @@ +#include +#include +#include +#include + +#include "utils.h" +#include "minecctl.h" +#include "server.h" +#include "misc.h" +#include "config-parser.h" +#include "server-config-options.h" + +void +read_server_config(struct cfg *cfg, struct server *server) +{ + char buf[4096]; + size_t off = 0; + ssize_t r; + int dfd; + int fd; + char *pos = buf; + + if (!server || !server->filename || server->file_read) + return; + + server->file_read = true; + + dfd = open(cfg->cfgdir, O_DIRECTORY | O_PATH | O_CLOEXEC); + if (dfd < 0) + die("Failed to open %s: %m", cfg->cfgdir); + + fd = openat(dfd, server->filename, O_RDONLY | O_CLOEXEC); + if (fd < 0) + die("Failed to open %s: %m", server->filename); + + close(dfd); + + while (true) { + r = read(fd, buf + off, sizeof(buf) - off - 1); + if (r < 0) + die("Failed to read %s: %m", server->filename); + else if (r == 0) + break; + + off += r; + if (off == sizeof(buf) - 1) + die("Failed to read %s: file too large", server->filename); + } + + buf[off] = '\0'; + close(fd); + + if (!config_parse_header(SERVER_CFG_HEADER, &pos)) + die("Unable to parse %s: invalid/missing header", + server->filename); + + /* FIXME: this will cause superflous DNS lookups of other cfg entries */ + while (true) { + int key; + const char *keyname; + struct cfg_value value; + + if (!config_parse_line(server->filename, &pos, scfg_key_map, + &key, &keyname, &value, false)) + break; + + switch (key) { + case SCFG_KEY_RCON: + if (!list_empty(&server->rcon_addrs)) + die("rcon address defined twice in %s", + server->filename); + list_replace(&value.saddrs, &server->rcon_addrs); + break; + case SCFG_KEY_RCON_PASSWORD: + if (server->rcon_password) + die("rcon password defined twice in %s", + server->filename); + server->rcon_password = xstrdup(value.str); + break; + case SCFG_KEY_REMOTE: + if (!list_empty(&server->mc_addrs)) + die("rcon address defined twice in %s", + server->filename); + list_replace(&value.saddrs, &server->mc_addrs); + default: + continue; + } + } + + if (!server->rcon_password) + verbose("rcon password not found in %s", server->filename); + + if (list_empty(&server->rcon_addrs)) + verbose("rcon address not found in %s", server->filename); + + if (list_empty(&server->mc_addrs)) + verbose("mc server address not found in %s", server->filename); +} + +struct server * +get_default_server(struct cfg *cfg) +{ + struct server *server; + + server = list_first_entry_or_null(&cfg->servers, struct server, list); + if (!server) + die("No servers defined"); + + read_server_config(cfg, server); + + return server; +} + +bool +set_default_server(struct cfg *cfg, const char *name) +{ + struct server *server; + + assert_die(cfg, "invalid arguments"); + + list_for_each_entry(server, &cfg->servers, list) { + if (streq(name, server->name)) { + list_rotate_to_front(&server->list, &cfg->servers); + return true; + } + } + + return false; +} + +void +get_servers(struct cfg *cfg) +{ + struct dirent *dent; + DIR *dir; + + dir = opendir(cfg->cfgdir); + if (!dir) { + info("Can't open config directory %s: %m", cfg->cfgdir); + return; + } + + while ((dent = readdir(dir))) { + struct server *server; + char *suffix; + + if (!is_valid_server_config_filename(dent, NULL)) + continue; + + server = server_new(); + server->filename = xstrdup(dent->d_name); + + suffix = strrchr(dent->d_name, '.'); + assert_die(suffix, "Error parsing filename"); + *suffix = '\0'; + server->name = xstrdup(dent->d_name); + + list_add(&server->list, &cfg->servers); + } + + closedir(dir); +} + +void +server_free(struct server *server) +{ + struct saddr *saddr, *tmp; + + xfree(server->name); + xfree(server->filename); + free_password(&server->rcon_password); + + list_for_each_entry_safe(saddr, tmp, &server->rcon_addrs, list) { + list_del(&saddr->list); + xfree(saddr); + } + + list_for_each_entry_safe(saddr, tmp, &server->mc_addrs, list) { + list_del(&saddr->list); + xfree(saddr); + } + + xfree(server); +} + +struct server * +server_new() +{ + struct server *server; + + server = zmalloc(sizeof(*server)); + INIT_LIST_HEAD(&server->rcon_addrs); + INIT_LIST_HEAD(&server->mc_addrs); + INIT_LIST_HEAD(&server->list); + + return server; +} + diff --git a/minecctl/server.h b/minecctl/server.h new file mode 100644 index 0000000..368c1db --- /dev/null +++ b/minecctl/server.h @@ -0,0 +1,28 @@ +#ifndef fooserverhfoo +#define fooserverhfoo + +#include + +struct server { + bool file_read; + char *name; + char *filename; + char *rcon_password; + struct list_head rcon_addrs; + struct list_head mc_addrs; + struct list_head list; +}; + +void read_server_config(struct cfg *cfg, struct server *server); + +struct server *get_default_server(struct cfg *cfg); + +bool set_default_server(struct cfg *cfg, const char *name); + +void get_servers(struct cfg *cfg); + +void server_free(struct server *server); + +struct server *server_new(); + +#endif -- cgit v1.2.3