From 3dc8d84af1753b41fe37b3b3954731379dc579aa Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Thu, 9 Jul 2020 22:58:22 +0200 Subject: Implement new command for minecctl --- minecctl/minecctl-commands.h | 5 ++ minecctl/minecctl.c | 14 ++++- minecctl/misc-commands.c | 140 ++++++++++++++++++++++++++++++++++++------- minecctl/misc-commands.h | 2 + 4 files changed, 137 insertions(+), 24 deletions(-) diff --git a/minecctl/minecctl-commands.h b/minecctl/minecctl-commands.h index 16cf511..f50bc6c 100644 --- a/minecctl/minecctl-commands.h +++ b/minecctl/minecctl-commands.h @@ -5,6 +5,7 @@ enum commands { CMD_INVALID = 0, CMD_INIT, + CMD_NEW, CMD_LIST, CMD_LINT, CMD_INFO, @@ -24,6 +25,10 @@ static struct command_list { .name = "init", .cmd = CMD_INIT, }, + { + .name = "new", + .cmd = CMD_NEW, + }, { .name = "list", .cmd = CMD_LIST, diff --git a/minecctl/minecctl.c b/minecctl/minecctl.c index b374f18..3b1da80 100644 --- a/minecctl/minecctl.c +++ b/minecctl/minecctl.c @@ -157,6 +157,7 @@ _noreturn_ static void usage(bool no_error) "\n" "Valid commands:\n" " init perform initial setup\n" + " new SERVER create a new server\n" " list list known servers\n" " lint check validity of server configuration files\n" " info [SERVER] show information about a running SERVER (or all known servers)\n" @@ -178,7 +179,7 @@ _noreturn_ static void usage(bool no_error) " -m, --mc-address=ADDR connect to Minecraft server at ADDR\n" " (only relevant for some commands, can also\n" " use environment variable MC_ADDRESS)\n" - " -c, --cfgdir=DIR look for server configuration files in DIR\n" + " -c, --cfgdir=DIR look for configuration files in DIR\n" " -f, --force stop server even if it has players\n" " -v, --verbose enable extra logging\n" " -d, --debug enable debugging information\n" @@ -324,6 +325,17 @@ static void parse_command(struct cfg *cfg, char *const *argv) } cfg->cmd = do_init; break; + case CMD_NEW: + if (!*argv) { + error("Missing arguments"); + usage(false); + } else if (*(argv + 1)) { + error("Too many arguments"); + usage(false); + } + cfg->commands = strv_copy(argv); + cfg->cmd = do_new; + break; case CMD_LIST: if (*argv) { error("Too many arguments"); diff --git a/minecctl/misc-commands.c b/minecctl/misc-commands.c index 5a6fe3a..34cbedf 100644 --- a/minecctl/misc-commands.c +++ b/minecctl/misc-commands.c @@ -149,26 +149,17 @@ out: return rv; } -static bool create_config_tree(int xfd) +static bool create_server_cfg(int sfd, int cfd, const char *name, + const char *filename) { - int mfd = -1, sfd = -1, efd = -1, cfd = -1; + int efd = -1; bool rv = false; - mfd = open_subdir(xfd, "minecproxy", true); - if (mfd < 0) - goto out; - - sfd = open_subdir(mfd, "servers", true); - if (sfd < 0) - goto out; - - if (!write_cfg_file(sfd, "README.TXT", ___examples_README_TXT, - ___examples_README_TXT_len)) - goto out; - - efd = open_subdir(sfd, "example", true); - if (efd < 0) + efd = open_subdir(sfd, name, true); + if (efd < 0) { + error("Failed to create configuration directory \"%s\"", name); goto out; + } if (!write_cfg_file(efd, "eula.txt", ___examples_eula_txt, ___examples_eula_txt_len)) @@ -182,19 +173,48 @@ static bool create_config_tree(int xfd) if (!create_link(efd, "server.jar", "../server.jar")) goto out; - cfd = open_subdir(mfd, "config", true); - if (cfd < 0) - goto out; - - if (!write_cfg_file(cfd, "example.mcserver", + if (!write_cfg_file(cfd, filename, ___examples_example_mcserver, ___examples_example_mcserver_len)) goto out; + rv = true; + +out: + if (efd >= 0) + close(efd); + + return rv; +} + +static bool create_config_tree(int xfd) +{ + int mfd = -1, sfd = -1, cfd = -1; + bool rv = false; + + mfd = open_subdir(xfd, "minecproxy", true); + if (mfd < 0) + goto out; + + sfd = open_subdir(mfd, "servers", true); + if (sfd < 0) + goto out; + + if (!write_cfg_file(sfd, "README.TXT", ___examples_README_TXT, + ___examples_README_TXT_len)) + goto out; + + cfd = open_subdir(mfd, "config", true); + if (cfd < 0) + goto out; + if (!write_cfg_file(cfd, "minecproxy.conf", ___examples_minecproxy_conf, ___examples_minecproxy_conf_len)) goto out; + if (!create_server_cfg(sfd, cfd, "example", "example.mcserver")) + goto out; + info("Created configuration in $XDG_CONFIG_HOME/minecproxy"); rv = true; @@ -203,8 +223,6 @@ out: close(mfd); if (sfd >= 0) close(sfd); - if (efd >= 0) - close(efd); if (cfd >= 0) close(cfd); return rv; @@ -251,6 +269,82 @@ out: return rv; } +static bool valid_name(const char *name) +{ + const char *f = name; + + if (empty_str(name)) { + error("Empty server name given"); + return false; + } + + while (*f != '\0') { + if ((*f >= 'a' && *f <= 'z') || + (*f >= 'A' && *f <= 'Z') || + (*f >= '0' && *f <= '9') || + (*f == ':') || (*f == '-') || + (*f == '_') || (*f == '.') || + (*f == '\\')) { + f++; + continue; + } + error("Server name \"%s\" contains invalid characters", name); + return false; + } + + if ((f - name) > (256 - STRLEN("minecserver@"))) { + error("Server name \"%s\" is too long", name); + return false; + } + + return true; +} + +bool do_new(struct cfg *cfg) +{ + const char *name = cfg->commands[0]; + struct server *server; + int sfd = -1; + bool rv = false; + + if (!valid_name(name)) + return false; + + char filename[strlen(name) + STRLEN(".mcserver") + 1]; + sprintf(filename, "%s.mcserver", name); + + server_load_all_known(cfg); + + if (!cfg->dir) + goto out; + + list_for_each_entry(server, &cfg->servers, list) { + if (streq(server->name, name)) { + error("Server \"%s\" already exists", name); + goto out; + } + } + + sfd = open_subdir(dirfd(cfg->dir), "../servers", false); + if (sfd < 0) { + error("Failed to open configuration directory \"servers\""); + goto out; + } + + if (!create_server_cfg(sfd, dirfd(cfg->dir), name, filename)) + goto out; + + info("Created server configuration %s", name); + + rv = true; + +out: + if (sfd >= 0) + close(sfd); + + return rv; +} + bool do_list(struct cfg *cfg) { struct server *server; diff --git a/minecctl/misc-commands.h b/minecctl/misc-commands.h index 95d0ba0..d8f62ca 100644 --- a/minecctl/misc-commands.h +++ b/minecctl/misc-commands.h @@ -4,6 +4,8 @@ bool do_init(struct cfg *cfg); +bool do_new(struct cfg *cfg); + bool do_list(struct cfg *cfg); bool do_lint(struct cfg *cfg); -- cgit v1.2.3