summaryrefslogtreecommitdiff
path: root/minecctl/minecctl.c
diff options
context:
space:
mode:
authorDavid Härdeman <david@hardeman.nu>2020-06-25 19:14:50 +0200
committerDavid Härdeman <david@hardeman.nu>2020-06-25 19:14:50 +0200
commita71d847b0a752375e8fa2c82c634a800bede2f9b (patch)
tree3b31c7f6eac81ec320e56fba03cf7aebc3d44356 /minecctl/minecctl.c
parent28606456dd6b110326c3027ea078b0409afeba3b (diff)
Only check for password if/when required
Diffstat (limited to 'minecctl/minecctl.c')
-rw-r--r--minecctl/minecctl.c115
1 files changed, 67 insertions, 48 deletions
diff --git a/minecctl/minecctl.c b/minecctl/minecctl.c
index e71a1cb..ed91fdf 100644
--- a/minecctl/minecctl.c
+++ b/minecctl/minecctl.c
@@ -57,9 +57,19 @@ __debug(_unused_ enum debug_lvl lvl, const char *fmt, ...)
{
va_list ap;
+ if (use_colors) {
+ if (lvl & DBG_ERROR)
+ fprintf(stderr, ANSI_RED);
+ else if (!(lvl & (DBG_INFO | DBG_VERBOSE)))
+ fprintf(stderr, ANSI_GREY);
+ }
+
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
+
+ if (use_colors && !(lvl & (DBG_INFO | DBG_VERBOSE)))
+ fprintf(stderr, ANSI_NORMAL);
}
_noreturn_ void
@@ -133,39 +143,12 @@ dump_config()
info("cmdstr : %s", cfg->cmdstr);
info("server : %p", cfg->server);
info("cmd : %p", cfg->cmd);
+ info("force stop : %s", cfg->force_stop ? "yes" : "no");
info("addrs : %sempty", list_empty(&cfg->addrs) ? "" : "not ");
+ info("mcaddrs : %sempty", list_empty(&cfg->mcaddrs) ? "" : "not ");
info("known_servers : %sempty", list_empty(&cfg->addrs) ? "" : "not ");
}
-static int
-connect_any(struct list_head *addrs)
-{
- struct saddr *saddr;
- bool connected = false;
- int sfd;
-
- list_for_each_entry(saddr, addrs, list) {
- sfd = socket(saddr->storage.ss_family, SOCK_STREAM | SOCK_CLOEXEC, 0);
- if (sfd < 0)
- die("socket: %m");
-
- socket_set_low_latency(sfd, true, true, true);
-
- if (connect(sfd, (struct sockaddr *)&saddr->storage, saddr->addrlen) < 0) {
- close(sfd);
- continue;
- }
-
- connected = true;
- break;
- }
-
- if (!connected)
- die("Failed to connect to remote host");
-
- return sfd;
-}
-
static void
parse_server_config(char *buf, const char *filename,
struct list_head *addrs)
@@ -253,7 +236,7 @@ _noreturn_ static void
usage(bool invalid)
{
if (invalid)
- info("Invalid option(s)");
+ error("Invalid option(s)");
info("Usage: %s [OPTION...] COMMAND\n"
"\n"
@@ -262,8 +245,11 @@ usage(bool invalid)
" (or use environment variable RCON_PASSWORD)\n"
" -a, --address=ADDR connect to rcon at ADDR\n"
" (or use environment variable RCON_ADDRESS)\n"
+ " -A, --mcaddress=ADDR connect to Minecraft server at ADDR\n"
+ " (potentially used for ping, status, pcount)\n"
" -c, --cfgdir=DIR look for server configurations in DIR\n"
" (default: %s)\n"
+ " -f, --force stop server even if it has players\n"
" -v, --verbose enable extra logging\n"
" -h, --help print this information\n"
"\n"
@@ -400,8 +386,8 @@ set_server(const char *name)
usage(true);
}
-static char *
-prompt_password()
+char *
+ask_password()
{
struct termios old, new;
char *password = NULL;
@@ -440,13 +426,49 @@ prompt_password()
return password;
}
+int
+connect_any(struct list_head *addrs, bool may_fail)
+{
+ struct saddr *saddr;
+ bool connected = false;
+ int sfd;
+
+ if (list_empty(addrs))
+ die("No address to connect to");
+
+ list_for_each_entry(saddr, addrs, list) {
+ sfd = socket(saddr->storage.ss_family, SOCK_STREAM | SOCK_CLOEXEC, 0);
+ if (sfd < 0)
+ die("socket: %m");
+
+ socket_set_low_latency(sfd, true, true, true);
+
+ if (connect(sfd, (struct sockaddr *)&saddr->storage, saddr->addrlen) < 0) {
+ close(sfd);
+ continue;
+ }
+
+ connected = true;
+ break;
+ }
+
+ if (!connected) {
+ if (may_fail)
+ sfd = -1;
+ else
+ die("Failed to connect to remote host");
+ }
+
+ return sfd;
+}
+
static void
parse_verb(int index, int remain, char **argv)
{
enum command_args args;
enum commands cmd;
- assert_die(index >= 0 && remain >= 0 && argv && cfg, "invalid arguments");
+ assert_die(index >= 0 && remain >= 0 && argv, "invalid arguments");
cmd = CMD_INVALID;
@@ -609,13 +631,15 @@ parse_cmdline(int argc, char **argv)
static struct option long_options[] = {
{ "password", required_argument, 0, 'p' },
{ "address", required_argument, 0, 'a' },
+ { "mcaddress", required_argument, 0, 'A' },
{ "cfgdir", required_argument, 0, 'c' },
{ "verbose", no_argument, 0, 'v' },
+ { "force", no_argument, 0, 'f' },
{ "help", no_argument, 0, 'h' },
{ 0, 0, 0, 0 }
};
- c = getopt_long(argc, argv, ":p:a:c:vh",
+ c = getopt_long(argc, argv, ":p:a:A:c:fvh",
long_options, &option_index);
if (c == -1)
@@ -628,9 +652,15 @@ parse_cmdline(int argc, char **argv)
case 'a':
cfg->addrstr = xstrdup(optarg);
break;
+ case 'A':
+ cfg->mcaddrstr = xstrdup(optarg);
+ break;
case 'c':
cfg->cfgdir = optarg;
break;
+ case 'f':
+ cfg->force_stop = true;
+ break;
case 'v':
debug_mask |= DBG_VERBOSE;
break;
@@ -669,8 +699,8 @@ main(int argc, char **argv)
set_use_colors();
cfg = zmalloc(sizeof(*cfg));
- cfg->fd = -1;
list_init(&cfg->addrs);
+ list_init(&cfg->mcaddrs);
list_init(&cfg->known_servers);
parse_cmdline(argc, argv);
@@ -688,8 +718,9 @@ main(int argc, char **argv)
} else if (cfg->addrstr) {
struct cfg_value value;
+ /* FIXME: create a struct server here, fill in details like name */
if (!strtosockaddrs(cfg->addrstr, &value, false))
- die("Unable to connect");
+ die("Unable to parse address: %s", cfg->addrstr);
if (value.type != CFG_VAL_TYPE_ADDRS)
die("Unexpected return value from strtosockaddrs");
@@ -700,18 +731,6 @@ main(int argc, char **argv)
list_replace(&value.saddrs, &cfg->addrs);
}
- info("here %p", cfg->password);
- if (!cfg->password)
- cfg->password = prompt_password();
- info("here %p", cfg->password);
-
- dump_config();
-
- if (list_empty(&cfg->addrs))
- die("Remote address not found");
-
- cfg->fd = connect_any(&cfg->addrs);
-
cfg->cmd(cfg);
xfree(cfg);