summaryrefslogtreecommitdiff
path: root/minecctl
diff options
context:
space:
mode:
authorDavid Härdeman <david@hardeman.nu>2020-06-26 22:26:14 +0200
committerDavid Härdeman <david@hardeman.nu>2020-06-26 22:26:14 +0200
commit09d88fc3db9265732c7960ee52240b1196dcee71 (patch)
treef2324fc368f23baa379b2240bd044a6f1a7b06ab /minecctl
parent591b03bd3cfd52b33a5e8512fef466494cf329f6 (diff)
Split off all server functionality to a separate file
Diffstat (limited to 'minecctl')
-rw-r--r--minecctl/meson.build1
-rw-r--r--minecctl/minecctl-rcon.c3
-rw-r--r--minecctl/minecctl.c200
-rw-r--r--minecctl/minecctl.h14
-rw-r--r--minecctl/server.c198
-rw-r--r--minecctl/server.h28
6 files changed, 238 insertions, 206 deletions
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 <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#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 <stdbool.h>
+
+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