summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Härdeman <david@hardeman.nu>2020-07-01 19:44:19 +0200
committerDavid Härdeman <david@hardeman.nu>2020-07-01 19:44:19 +0200
commit6057bbf9e852103c252bf3429146c5c1309bbc4a (patch)
tree341abfdf6f6d4f91e807fa1825abfc8e83ef4e3c
parente045a7b80cc0cb96b79456f9c74c3705989a12df (diff)
Improve the lint command further
-rw-r--r--minecctl/misc-commands.c102
-rw-r--r--minecctl/rcon-commands.c14
-rw-r--r--minecctl/server.c37
-rw-r--r--minecctl/server.h3
4 files changed, 131 insertions, 25 deletions
diff --git a/minecctl/misc-commands.c b/minecctl/misc-commands.c
index 8dd6bd2..28d9e3a 100644
--- a/minecctl/misc-commands.c
+++ b/minecctl/misc-commands.c
@@ -12,31 +12,119 @@ 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->name);
return true;
}
+static bool saddr_match(struct list_head *la, struct list_head *lb)
+{
+ struct saddr *a, *b;
+
+ list_for_each_entry(a, la, list) {
+ list_for_each_entry(b, lb, list) {
+ if (a->st.ss_family != b->st.ss_family)
+ continue;
+
+ switch (a->st.ss_family) {
+ case AF_INET:
+ if (memcmp(&a->in4.sin_addr,
+ &b->in4.sin_addr,
+ sizeof(a->in4.sin_addr)))
+ continue;
+ if (a->in4.sin_port != b->in4.sin_port)
+ continue;
+ return true;
+
+ case AF_INET6:
+ if (memcmp(&a->in6.sin6_addr,
+ &b->in6.sin6_addr,
+ sizeof(a->in6.sin6_addr)))
+ continue;
+ if (a->in6.sin6_port != b->in6.sin6_port)
+ continue;
+ return true;
+
+ default:
+ continue;
+ }
+ }
+ }
+
+ return false;
+}
+
bool do_lint(struct cfg *cfg)
{
struct server *server;
+ unsigned lineno;
const char *error;
bool rv = true;
+ struct server *a, *b;
+ unsigned ia, ib;
/* server->scfg.filename check excludes servers created from cmdline */
list_for_each_entry(server, &cfg->servers, list) {
if (!server->scfg.filename)
continue;
- info("• %s", server->name);
+ if (!server_read_config(cfg, server, &lineno, &error)) {
+ if (lineno != 0)
+ info("• %s: %sfail%s - line %u: %s",
+ server->name, ansi_red, ansi_normal,
+ lineno, error);
+ else
+ info("• %s: %sfail%s - %s",
+ server->name, ansi_red, ansi_normal,
+ error);
+ rv = false;
+ } else if (!scfg_validate(&server->scfg, &error)) {
+ info("• %s: %sfail%s - %s",
+ server->name, ansi_red, ansi_normal,
+ error);
+ rv = false;
+ } else {
+ info("• %s: %sok%s", server->name, ansi_green,
+ ansi_normal);
+ }
+ }
- /* FIXME: should return bool */
- server_read_config(cfg, server);
+ info("");
- if (!scfg_validate(&server->scfg, &error)) {
- error("%s: invalid (%s)", server->name, error);
- rv = false;
+ ia = 0;
+ list_for_each_entry(a, &cfg->servers, list) {
+ ib = 0;
+ list_for_each_entry(b, &cfg->servers, list) {
+ if (ib <= ia) {
+ ib++;
+ continue;
+ }
+
+ if (a->scfg.announce_port != 0 &&
+ b->scfg.announce_port != 0 &&
+ 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);
+
+ 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);
+
+ 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);
+
+ 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);
+
+ ib++;
}
+ ia++;
}
return rv;
diff --git a/minecctl/rcon-commands.c b/minecctl/rcon-commands.c
index fc5b932..dfe8647 100644
--- a/minecctl/rcon-commands.c
+++ b/minecctl/rcon-commands.c
@@ -371,13 +371,23 @@ bool do_stop(struct cfg *cfg)
bool do_stop_all(struct cfg *cfg)
{
struct server *server;
+ unsigned lineno;
+ const char *error;
+ bool rv = true;
list_for_each_entry(server, &cfg->servers, list) {
- server_read_config(cfg, server);
+ if (!server_read_config(cfg, server, &lineno, &error)) {
+ info("• %s: %sfail%s - invalid configuration file "
+ "(line %u: %s)",
+ server->name, ansi_red, ansi_normal,
+ lineno, error);
+ rv = false;
+ }
+ /* FIXME: error checks */
stop_one_server(cfg, server);
}
- return true;
+ return rv;
}
bool do_rcon_pcount(struct cfg *cfg, unsigned *online, unsigned *max)
diff --git a/minecctl/server.c b/minecctl/server.c
index 93882f1..582c4fd 100644
--- a/minecctl/server.c
+++ b/minecctl/server.c
@@ -8,70 +8,77 @@
#include "server.h"
#include "misc.h"
-void server_read_config(struct cfg *cfg, struct server *server)
+#define INVALID(msg) do { *error = (msg); return false; } while(0)
+
+bool server_read_config(struct cfg *cfg, struct server *server,
+ unsigned *lineno, const char **error)
{
- unsigned lineno;
- const char *error;
char buf[4096];
size_t off = 0;
ssize_t r;
int dfd;
int fd;
- if (!server || !server->scfg.filename || server->file_read)
- return;
+ if (!server || !server->scfg.filename || server->file_read ||
+ !lineno || !error)
+ return false;
+ *lineno = 0;
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);
+ INVALID("failed to open configuration directory");
fd = openat(dfd, server->scfg.filename, O_RDONLY | O_CLOEXEC);
if (fd < 0)
- die("Failed to open %s: %m", server->scfg.filename);
+ INVALID("failed to open configuration file");
close(dfd);
while (true) {
r = read(fd, buf + off, sizeof(buf) - off - 1);
if (r < 0)
- die("Failed to read %s: %m", server->scfg.filename);
+ INVALID("failed to read configuration file");
else if (r == 0)
break;
off += r;
if (off == sizeof(buf) - 1)
- die("Failed to read %s: file too large",
- server->scfg.filename);
+ INVALID("invalid, file too large");
}
buf[off] = '\0';
close(fd);
- if (!scfg_parse(&server->scfg, buf, NULL, &lineno, &error))
- die("Unable to parse %s, line %u: %s", server->scfg.filename,
- lineno, error);
+ if (!scfg_parse(&server->scfg, buf, NULL, lineno, error))
+ return false;
if (!server->scfg.rcon_password)
- verbose("rcon password not found in %s", server->scfg.filename);
+ verbose("rcon password not set");
if (list_empty(&server->scfg.rcons))
verbose("rcon address not found in %s", server->scfg.filename);
if (list_empty(&server->scfg.remotes))
verbose("mc server address not found in %s", server->scfg.filename);
+
+ return true;
}
struct server *server_get_default(struct cfg *cfg)
{
struct server *server;
+ unsigned lineno;
+ const char *error;
server = list_first_entry_or_null(&cfg->servers, struct server, list);
if (!server)
die("No servers defined");
- server_read_config(cfg, server);
+ /* FIXME: error msg */
+ if (!server_read_config(cfg, server, &lineno, &error))
+ return NULL;
return server;
}
diff --git a/minecctl/server.h b/minecctl/server.h
index 61eba5f..2bfb3e8 100644
--- a/minecctl/server.h
+++ b/minecctl/server.h
@@ -12,7 +12,8 @@ struct server {
struct list_head list;
};
-void server_read_config(struct cfg *cfg, struct server *server);
+bool server_read_config(struct cfg *cfg, struct server *server,
+ unsigned *lineno, const char **error);
struct server *server_get_default(struct cfg *cfg);