summaryrefslogtreecommitdiff
path: root/minecctl
diff options
context:
space:
mode:
authorDavid Härdeman <david@hardeman.nu>2020-07-12 02:30:31 +0200
committerDavid Härdeman <david@hardeman.nu>2020-07-12 02:30:31 +0200
commitf06ff46151c38b2259c5ee4ae83d38c6f6fc0c8c (patch)
tree44f6d00604a153300eb3be9dcec96d17030727b8 /minecctl
parentd198326ef6ec3031afbe7ee47b727cc52fc1198a (diff)
Teach minecctl to create proper mcserver files, auto-generate systemd service names as necessary
Diffstat (limited to 'minecctl')
-rw-r--r--minecctl/minecctl.c8
-rw-r--r--minecctl/misc-commands.c118
-rw-r--r--minecctl/misc.c2
-rw-r--r--minecctl/rcon-commands.c26
-rw-r--r--minecctl/server.c21
-rw-r--r--minecctl/server.h1
6 files changed, 95 insertions, 81 deletions
diff --git a/minecctl/minecctl.c b/minecctl/minecctl.c
index 4a6bf0f..c2d6c19 100644
--- a/minecctl/minecctl.c
+++ b/minecctl/minecctl.c
@@ -28,7 +28,7 @@ static void dump_server(struct server *server)
info("│");
info("│ ▷ server");
info("│ ┌─────");
- info("│ │ name : %s", server->name);
+ info("│ │ name : %s", server->scfg.name);
info("│ │ file_read : %s", server->file_read ? "yes" : "no");
info("│ │ filename : %s", server->scfg.filename);
@@ -237,7 +237,7 @@ static bool create_server_from_cmdline_args(struct cfg *cfg)
if (!str_to_addrs(cfg->rcon_addrstr, &server->scfg.rcons))
goto error;
- server->name = cfg->rcon_addrstr;
+ server->scfg.name = cfg->rcon_addrstr;
cfg->rcon_addrstr = NULL;
}
@@ -245,8 +245,8 @@ static bool create_server_from_cmdline_args(struct cfg *cfg)
if (!str_to_addrs(cfg->mc_addrstr, &server->scfg.remotes))
goto error;
- if (!server->name)
- server->name = cfg->mc_addrstr;
+ if (!server->scfg.name)
+ server->scfg.name = cfg->mc_addrstr;
else
xfree(cfg->mc_addrstr);
diff --git a/minecctl/misc-commands.c b/minecctl/misc-commands.c
index 1133e55..34dd990 100644
--- a/minecctl/misc-commands.c
+++ b/minecctl/misc-commands.c
@@ -20,7 +20,6 @@
#include "misc.h"
#include "examples/eula.txt.h"
-#include "examples/example.mcserver.h"
#include "examples/minecctl.conf.h"
#include "examples/minecproxy.conf.h"
#include "examples/minecproxy.service.h"
@@ -142,10 +141,12 @@ static bool create_user_service(int xfd, const char *service,
return true;
}
-static bool create_server_cfg(struct cfg *cfg, const char *name,
- const char *filename,
- const unsigned char *properties,
- size_t properties_len)
+static bool write_server_cfg(struct cfg *cfg, const char *name,
+ const char *filename,
+ const unsigned char *properties,
+ size_t properties_len,
+ const unsigned char *mcserver,
+ size_t mcserver_len)
{
_cleanup_close_ int sfd = -1;
int cfd, dfd;
@@ -156,17 +157,15 @@ static bool create_server_cfg(struct cfg *cfg, const char *name,
cfd = dirfd(cfg->cfg_dir);
dfd = dirfd(cfg->data_dir);
- if (!write_cfg_file(cfd, filename,
- ___examples_example_mcserver,
- ___examples_example_mcserver_len))
- return false;
-
sfd = open_subdir(dfd, name, true);
if (sfd < 0) {
error("Failed to create server directory \"%s\"", name);
return false;
}
+ if (!write_cfg_file(cfd, filename, mcserver, mcserver_len))
+ return false;
+
if (!write_cfg_file(sfd, "eula.txt", ___examples_eula_txt,
___examples_eula_txt_len))
return false;
@@ -299,18 +298,37 @@ static bool generate_random_password(char *buf, size_t len)
}
*d = '\0';
- info("Hex = %s", buf);
return true;
}
+static unsigned char *create_mc_server(const char *name, uint16_t local_port,
+ size_t *len)
+{
+ char *mcserver;
+
+ /* FIXME: Add comments, commented out options */
+ mcserver = xsprintf(len,
+ "[server]\n"
+ "type = proxy\n"
+ "name = %s\n"
+ "local = %" PRIu16 "\n"
+ "idle_timeout = 600\n"
+ "start_method = systemd\n"
+ "stop_method = systemd\n",
+ name, local_port);
+ if (!mcserver)
+ error("xsprintf: %m");
+
+ return (unsigned char *)mcserver;
+}
+
static unsigned char *create_mc_properties(const char *name, uint16_t mc_port,
uint16_t rcon_port,
const char *rcon_password,
size_t *len)
{
char hexrnd[16 + 1];
- char *properties;
- int r;
+ char *prop;
if (!rcon_password) {
if (!generate_random_password(hexrnd, sizeof(hexrnd))) {
@@ -319,27 +337,24 @@ static unsigned char *create_mc_properties(const char *name, uint16_t mc_port,
}
}
- /* FIXME: server-ip= */
- r = asprintf(&properties,
- "#Minecraft server properties\n"
- "# This is a partial file, it will be replaced with a\n"
- "# fleshed out version the first time the Minecraft\n"
- "# server is executed.\n"
- "motd=%s\n"
- "server-port=%" PRIu16 "\n"
- "enable-rcon=true\n"
- "rcon.port=%" PRIu16 "\n"
- "rcon.password=%s",
- name, mc_port, rcon_port,
- rcon_password ? rcon_password : hexrnd);
- if (r < 0) {
- error("asprintf failed: %m");
- return NULL;
- }
-
- if (len)
- *len = r;
- return (unsigned char *)properties;
+ prop = xsprintf(len,
+ "#Minecraft server properties\n"
+ "# This is a partial file, it will be replaced with a\n"
+ "# fleshed out version the first time the Minecraft\n"
+ "# server is executed.\n"
+ "motd=%s\n"
+ "#maybe uncomment the next line if you use minecproxy\n"
+ "#server-ip=127.0.0.1\n"
+ "server-port=%" PRIu16 "\n"
+ "enable-rcon=true\n"
+ "rcon.port=%" PRIu16 "\n"
+ "rcon.password=%s\n",
+ name, mc_port, rcon_port,
+ rcon_password ? rcon_password : hexrnd);
+ if (!prop)
+ error("xsprintf: %m");
+
+ return (unsigned char *)prop;
}
static uint16_t get_port(struct list_head *list)
@@ -461,10 +476,12 @@ bool do_new(struct cfg *cfg)
const char *name = cfg->commands[0];
struct server *server;
struct server *defserver = NULL;
+ uint16_t local_port = 0, mc_port = 0, rcon_port = 0;
+ const char *rcon_password = NULL;
_cleanup_free_ unsigned char *properties = NULL;
size_t properties_len;
- uint16_t rcon_port = 0, mc_port = 0;
- const char *rcon_password = NULL;
+ _cleanup_free_ unsigned char *mcserver = NULL;
+ size_t mcserver_len;
if (!valid_name(name))
return false;
@@ -494,7 +511,6 @@ bool do_new(struct cfg *cfg)
}
if (defserver) {
- /* FIXME: check list empty and tailor error msg */
rcon_port = get_port(&defserver->scfg.rcons);
mc_port = get_port(&defserver->scfg.remotes);
rcon_password = defserver->scfg.rcon_password;
@@ -503,8 +519,8 @@ bool do_new(struct cfg *cfg)
dump_config(cfg);
- if (!select_free_ports(cfg, NULL, &mc_port, &rcon_port)) {
- error("Failed to find a free port");
+ if (!select_free_ports(cfg, &local_port, &mc_port, &rcon_port)) {
+ error("Failed to find free port(s)");
return false;
}
@@ -513,10 +529,13 @@ bool do_new(struct cfg *cfg)
if (!properties)
return false;
- error("Created config file (%zu):\n%s", properties_len, properties);
+ mcserver = create_mc_server(name, local_port, &mcserver_len);
+ if (!mcserver)
+ return false;
- if (!create_server_cfg(cfg, name, filename, properties,
- properties_len))
+ if (!write_server_cfg(cfg, name, filename,
+ properties, properties_len,
+ mcserver, mcserver_len))
return false;
info("Created server configuration %s", name);
@@ -532,7 +551,7 @@ bool do_list(struct cfg *cfg)
/* server->scfg.filename check excludes servers created from cmdline */
list_for_each_entry(server, &cfg->servers, list)
if (server->scfg.filename)
- info("• %s", server->name);
+ info("• %s", server->scfg.name);
return true;
}
@@ -598,22 +617,25 @@ bool do_lint(struct cfg *cfg)
a->scfg.announce_port == b->scfg.announce_port)
info("%sNote:%s %s and %s appear to have the "
"same announce port", ansi_red,
- ansi_normal, a->name, b->name);
+ ansi_normal, a->scfg.name, b->scfg.name);
if (saddr_match(&a->scfg.locals, &b->scfg.locals))
info("%sNote:%s %s and %s appear to share at "
"least one local address/port pair",
- ansi_red, ansi_normal, a->name, b->name);
+ ansi_red, ansi_normal, a->scfg.name,
+ b->scfg.name);
if (saddr_match(&a->scfg.remotes, &b->scfg.remotes))
info("%sNote:%s %s and %s appear to share at "
"least one remote address/port pair",
- ansi_red, ansi_normal, a->name, b->name);
+ ansi_red, ansi_normal, a->scfg.name,
+ b->scfg.name);
if (saddr_match(&a->scfg.rcons, &b->scfg.rcons))
info("%sNote:%s %s and %s appear to share at "
"least one rcon address/port pair",
- ansi_red, ansi_normal, a->name, b->name);
+ ansi_red, ansi_normal, a->scfg.name,
+ b->scfg.name);
ib++;
}
@@ -648,7 +670,7 @@ static bool do_one_status(struct cfg *cfg, struct server *server)
const char *error;
bool rv = true;
- info("• %s", server->name);
+ info("• %s", server->scfg.name);
if (list_empty(&server->scfg.rcons))
info(" rcon : not configured");
diff --git a/minecctl/misc.c b/minecctl/misc.c
index 26cbc86..90189dc 100644
--- a/minecctl/misc.c
+++ b/minecctl/misc.c
@@ -335,7 +335,7 @@ char *__xstrndup(const char *fn, int line, const char *s, size_t n)
"invalid arguments");
ptr = strndup(s, n);
- if (ptr)
+ if (!ptr)
die("strdup: %m");
return ptr;
}
diff --git a/minecctl/rcon-commands.c b/minecctl/rcon-commands.c
index cb6ea45..cdbf868 100644
--- a/minecctl/rcon-commands.c
+++ b/minecctl/rcon-commands.c
@@ -96,22 +96,22 @@ static int rcon_login(struct cfg *cfg, struct server *server)
assert_die(cfg && server, "invalid arguments");
if (list_empty(&server->scfg.rcons)) {
- error("%s: rcon address unknown", server->name);
+ error("%s: rcon address unknown", server->scfg.name);
goto error;
}
fd = connect_any(&server->scfg.rcons, &saddr, &error);
if (fd < 0) {
- verbose("%s: unable to connect - %s", server->name, error);
+ verbose("%s: unable to connect - %s", server->scfg.name, error);
goto error;
} else
- verbose("%s: connected to %s", server->name, saddr->addrstr);
+ verbose("%s: connected to %s", server->scfg.name, saddr->addrstr);
if (!server->scfg.rcon_password)
server->scfg.rcon_password = ask_password();
if (!server->scfg.rcon_password) {
- error("%s: can't login - password missing", server->name);
+ error("%s: can't login - password missing", server->scfg.name);
goto error;
}
@@ -123,10 +123,10 @@ static int rcon_login(struct cfg *cfg, struct server *server)
if (!rcon_protocol_verify_response(1, 1, RCON_PACKET_LOGIN,
rtype, &error)) {
- error("%s: invalid response - %s", server->name, error);
+ error("%s: invalid response - %s", server->scfg.name, error);
goto error;
} else
- verbose("%s: login ok", server->name);
+ verbose("%s: login ok", server->scfg.name);
return fd;
@@ -230,7 +230,7 @@ static bool do_one_info(struct cfg *cfg, struct server *server)
if (fd < 0)
return false;
- info("• %s", server->name);
+ info("• %s", server->scfg.name);
if (get_one_status(fd, buf, sizeof(buf), "seed", 1, "Seed : [ %[^]]]",
&reply, tbuf))
info(" Seed: %s", tbuf);
@@ -336,7 +336,7 @@ static bool stop_one_server(struct cfg *cfg, struct server *server)
fd = rcon_login(cfg, server);
if (fd < 0) {
info("• %s: %sfail%s - unable to login",
- server->name, ansi_red, ansi_normal);
+ server->scfg.name, ansi_red, ansi_normal);
return false;
}
@@ -345,17 +345,17 @@ static bool stop_one_server(struct cfg *cfg, struct server *server)
if (!get_player_count(fd, &current, NULL)) {
info("• %s: %sfail%s - unable to get player count",
- server->name, ansi_red, ansi_normal);
+ server->scfg.name, ansi_red, ansi_normal);
return false;
} else if (current > 0) {
info("• %s: %sfail%s - has active players "
"(use -f to force)",
- server->name, ansi_red, ansi_normal);
+ server->scfg.name, ansi_red, ansi_normal);
return false;
}
}
- info("• %s: sending stop command", server->name);
+ info("• %s: sending stop command", server->scfg.name);
rv = send_cmd(fd, "stop");
close(fd);
@@ -419,9 +419,9 @@ bool do_console(struct cfg *cfg)
return false;
prompt = alloca(strlen(program_invocation_short_name) + STRLEN(" (") +
- strlen(server->name) + STRLEN("): ") + 1);
+ strlen(server->scfg.name) + STRLEN("): ") + 1);
sprintf(prompt, "%s (%s): ", program_invocation_short_name,
- server->name);
+ server->scfg.name);
while (true) {
char *tmp;
diff --git a/minecctl/server.c b/minecctl/server.c
index 8bd7b51..3acc537 100644
--- a/minecctl/server.c
+++ b/minecctl/server.c
@@ -71,18 +71,12 @@ void server_load_all_known(struct cfg *cfg)
while ((dent = readdir(cfg->cfg_dir))) {
struct server *server;
- char *suffix;
if (!config_valid_server_filename(dent, NULL))
continue;
server = server_new(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);
}
}
@@ -153,7 +147,7 @@ bool server_read_config(struct cfg *cfg, struct server *server,
return false;
/* fill in missing parameters from server.properties */
- dfd = open_subdir(dirfd(cfg->data_dir), server->name, false);
+ dfd = open_subdir(dirfd(cfg->data_dir), server->scfg.name, false);
if (dfd < 0)
goto out;
@@ -193,21 +187,21 @@ bool server_read_all_configs(struct cfg *cfg, bool print_results)
if (!server_read_config(cfg, server, &lineno, &error)) {
if (lineno != 0 && print_results)
info("• %s: %sfail%s - line %u: %s",
- server->name, ansi_red, ansi_normal,
+ server->scfg.name, ansi_red, ansi_normal,
lineno, error);
else if (print_results)
info("• %s: %sfail%s - %s",
- server->name, ansi_red, ansi_normal,
+ server->scfg.name, ansi_red, ansi_normal,
error);
rv = false;
} else if (!scfg_validate(&server->scfg, &error) &&
print_results) {
info("• %s: %sfail%s - %s",
- server->name, ansi_red, ansi_normal,
+ server->scfg.name, ansi_red, ansi_normal,
error);
rv = false;
} else if (print_results) {
- info("• %s: %sok%s", server->name, ansi_green,
+ info("• %s: %sok%s", server->scfg.name, ansi_green,
ansi_normal);
}
}
@@ -226,7 +220,7 @@ struct server *server_get_default(struct cfg *cfg)
die("No servers defined");
if (!server_read_config(cfg, server, &lineno, &error)) {
- error("%s: server_read_config error - %s", server->name, error);
+ error("%s: server_read_config error - %s", server->scfg.name, error);
return NULL;
}
@@ -242,7 +236,7 @@ bool server_set_default(struct cfg *cfg, const char *name)
server_load_all_known(cfg);
list_for_each_entry(server, &cfg->servers, list) {
- if (streq(name, server->name)) {
+ if (streq(name, server->scfg.name)) {
list_rotate_to_front(&server->list, &cfg->servers);
cfg->default_set = true;
return true;
@@ -263,7 +257,6 @@ void server_free_all(struct cfg *cfg)
void server_free(struct server *server)
{
scfg_delete(&server->scfg);
- xfree(server->name);
xfree(server);
}
diff --git a/minecctl/server.h b/minecctl/server.h
index 4520d34..47682a5 100644
--- a/minecctl/server.h
+++ b/minecctl/server.h
@@ -8,7 +8,6 @@
struct server {
bool file_read;
- char *name;
struct server_config scfg;
struct list_head list;
};