diff options
| author | David Härdeman <david@hardeman.nu> | 2020-07-01 19:44:19 +0200 | 
|---|---|---|
| committer | David Härdeman <david@hardeman.nu> | 2020-07-01 19:44:19 +0200 | 
| commit | 6057bbf9e852103c252bf3429146c5c1309bbc4a (patch) | |
| tree | 341abfdf6f6d4f91e807fa1825abfc8e83ef4e3c | |
| parent | e045a7b80cc0cb96b79456f9c74c3705989a12df (diff) | |
Improve the lint command further
| -rw-r--r-- | minecctl/misc-commands.c | 102 | ||||
| -rw-r--r-- | minecctl/rcon-commands.c | 14 | ||||
| -rw-r--r-- | minecctl/server.c | 37 | ||||
| -rw-r--r-- | minecctl/server.h | 3 | 
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);  | 
