summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Härdeman <david@hardeman.nu>2020-06-28 19:25:20 +0200
committerDavid Härdeman <david@hardeman.nu>2020-06-28 19:25:20 +0200
commit8f29a4d23dd13a80aa26951b17e2a71f4e651cb1 (patch)
treed09dee2d148e781d31ffd7e95581bf155a9f050f
parent105ad577b367cfda224f0cbcf9f7e688615437e0 (diff)
Introduce the possibility of specifying serveral commands in one go
-rw-r--r--minecctl/minecctl-commands.h5
-rw-r--r--minecctl/minecctl.c23
-rw-r--r--minecctl/minecctl.h5
-rw-r--r--minecctl/misc.c77
-rw-r--r--minecctl/misc.h6
-rw-r--r--minecctl/rcon-commands.c20
-rw-r--r--minecctl/rcon-commands.h2
7 files changed, 114 insertions, 24 deletions
diff --git a/minecctl/minecctl-commands.h b/minecctl/minecctl-commands.h
index 2805a51..e8bb132 100644
--- a/minecctl/minecctl-commands.h
+++ b/minecctl/minecctl-commands.h
@@ -10,6 +10,7 @@ enum commands {
CMD_STOPALL,
CMD_PCOUNT,
CMD_COMMAND,
+ CMD_COMMANDS,
CMD_CONSOLE,
};
@@ -45,6 +46,10 @@ static struct command_list {
.cmd = CMD_COMMAND,
},
{
+ .name = "cmds",
+ .cmd = CMD_COMMANDS,
+ },
+ {
.name = "console",
.cmd = CMD_CONSOLE,
},
diff --git a/minecctl/minecctl.c b/minecctl/minecctl.c
index 5ac3942..3d21ae6 100644
--- a/minecctl/minecctl.c
+++ b/minecctl/minecctl.c
@@ -34,7 +34,10 @@ static void dump_config(struct cfg *cfg)
info("rcon_password : %s", cfg->rcon_password);
info("rcon_addrstr : %s", cfg->rcon_addrstr);
info("mc_addrstr : %s", cfg->mc_addrstr);
- info("cmdstr : %s", cfg->cmdstr);
+ if (cfg->commands) {
+ for (char *const *cmd = cfg->commands; *cmd; cmd++)
+ info("command : %s", *cmd);
+ }
info("cmd : %p", cfg->cmd);
info("force stop : %s", cfg->force_stop ? "yes" : "no");
@@ -81,6 +84,7 @@ _noreturn_ static void usage(bool no_error)
" pcount [SERVER] get player count for SERVER\n"
" console [SERVER] interactive command line for SERVER\n"
" cmd [SERVER] CMD send CMD to SERVER\n"
+ " cmds [SERVER] CMDS... send multiple CMDS to SERVER\n"
" [SERVER] CMD shorthand for \"cmd [SERVER] CMD\"\n"
" [SERVER] shorthand for \"console [SERVER]\"\n"
"\n"
@@ -249,6 +253,8 @@ static void parse_command(struct cfg *cfg, char *const *argv)
cfg->cmd = do_console;
break;
case CMD_COMMAND:
+ _fallthrough_;
+ case CMD_COMMANDS:
get_optional_server_arg(cfg, &argv, true);
if (!*argv) {
@@ -256,8 +262,11 @@ static void parse_command(struct cfg *cfg, char *const *argv)
usage(false);
}
- cfg->cmdstr = strv_join(argv);
- cfg->cmd = do_command;
+ if (cmd == CMD_COMMANDS)
+ cfg->commands = strv_copy(argv);
+ else
+ cfg->commands = strv_from_strs(strv_join(argv), NULL);
+ cfg->cmd = do_commands;
break;
case CMD_INVALID:
/* shorthand notation */
@@ -268,8 +277,8 @@ static void parse_command(struct cfg *cfg, char *const *argv)
cfg->cmd = do_console;
} else {
/* CMD... */
- cfg->cmdstr = strv_join(argv);
- cfg->cmd = do_command;
+ cfg->commands = strv_from_strs(strv_join(argv), NULL);
+ cfg->cmd = do_commands;
}
break;
default:
@@ -360,7 +369,7 @@ static void parse_cmdline(struct cfg *cfg, int argc, char *const *argv)
}
}
-int main(int argc, char **argv)
+int main(int argc, char *const *argv)
{
struct cfg cfg = {
.servers = LIST_HEAD_INIT(cfg.servers),
@@ -393,8 +402,8 @@ int main(int argc, char **argv)
out:
server_free_all(&cfg);
free_password(&cfg.rcon_password);
+ strv_free(cfg.commands);
xfree(cfg.rcon_addrstr);
xfree(cfg.mc_addrstr);
- xfree(cfg.cmdstr);
exit(success ? EXIT_SUCCESS : EXIT_FAILURE);
}
diff --git a/minecctl/minecctl.h b/minecctl/minecctl.h
index 259ac52..898a93f 100644
--- a/minecctl/minecctl.h
+++ b/minecctl/minecctl.h
@@ -2,15 +2,12 @@
#define foominecctlhfoo
struct cfg {
- /* command line arguments */
const char *cfgdir;
char *rcon_password;
char *rcon_addrstr;
char *mc_addrstr;
- char *cmdstr;
+ char **commands;
bool force_stop;
-
- /* bookkeeping */
bool (*cmd)(struct cfg *cfg);
struct list_head servers;
};
diff --git a/minecctl/misc.c b/minecctl/misc.c
index 8f0761f..e2d6b02 100644
--- a/minecctl/misc.c
+++ b/minecctl/misc.c
@@ -36,27 +36,86 @@ void set_use_colors()
use_colors = true;
}
+char **strv_copy(char *const *strv)
+{
+ size_t len = 1;
+ char **rv;
+ char **to;
+
+ for (char *const *str = strv; *str; str++)
+ len++;
+
+ rv = zmalloc(len * sizeof(char *));
+ to = rv;
+
+ for (char *const *str = strv; *str; str++)
+ *(to++) = xstrdup(*str);
+
+ return rv;
+}
+
+char **strv_from_strs(const char *first, ...)
+{
+ size_t len = 1;
+ va_list ap;
+ char **rv, **to;
+
+ if (first) {
+ va_start(ap, first);
+ while (va_arg(ap, const char *))
+ len++;
+ va_end(ap);
+ }
+
+ rv = zmalloc(len * sizeof(char *));
+ to = rv;
+ *(to++) = first ? xstrdup(first) : NULL;
+
+ if (first) {
+ const char *str;
+
+ va_start(ap, first);
+ while ((str = va_arg(ap, const char *)))
+ *(to++) = xstrdup(str);
+ va_end(ap);
+ *to = NULL;
+ }
+
+ return rv;
+}
+
char *strv_join(char *const *strv)
{
size_t len = 0;
- char *r, *to;
+ char *rv, *to;
- for (unsigned i = 0; strv[i]; i++)
- len += strlen(strv[i]) + 1;
+ for (char *const *str = strv; *str; str++)
+ len += strlen(*str) + 1;
if (len == 0)
return NULL;
- r = zmalloc(len);
- to = r;
+ rv = zmalloc(len);
+ to = rv;
- for (unsigned i = 0; strv[i]; i++) {
- if (i > 0)
+ for (char *const *str = strv; *str; str++) {
+ if (str != strv)
*(to++) = ' ';
- to = stpcpy(to, strv[i]);
+ to = stpcpy(to, *str);
}
- return r;
+ return rv;
+}
+
+void strv_free(char **strv)
+{
+ if (!strv)
+ return;
+
+ for (char **str = strv; *str; str++)
+ xfree(*str);
+
+ xfree(strv);
}
int connect_any(struct list_head *addrs, bool may_fail)
diff --git a/minecctl/misc.h b/minecctl/misc.h
index 6abed5e..c8254df 100644
--- a/minecctl/misc.h
+++ b/minecctl/misc.h
@@ -5,8 +5,14 @@ extern bool use_colors;
void set_use_colors();
+char **strv_copy(char *const *strv);
+
+char **strv_from_strs(const char *first, ...);
+
char *strv_join(char *const *strv);
+void strv_free(char **strv);
+
int connect_any(struct list_head *addrs, bool may_fail);
char *ask_password();
diff --git a/minecctl/rcon-commands.c b/minecctl/rcon-commands.c
index b6a216f..5f98b72 100644
--- a/minecctl/rcon-commands.c
+++ b/minecctl/rcon-commands.c
@@ -449,15 +449,29 @@ bool do_console(struct cfg *cfg)
return true;
}
-bool do_command(struct cfg *cfg)
+bool do_commands(struct cfg *cfg)
{
- int fd;
struct server *server;
+ bool rv = true;
+ int fd;
+
+ if (!cfg->commands) {
+ error("No commands to send");
+ return false;
+ }
server = server_get_default(cfg);
fd = rcon_login(cfg, server);
if (fd < 0)
return false;
- return send_cmd(fd, cfg->cmdstr);
+ for (char *const *cmd = cfg->commands; *cmd; cmd++) {
+ if (!send_cmd(fd, *cmd)) {
+ rv = false;
+ break;
+ }
+ }
+
+ close(fd);
+ return rv;
}
diff --git a/minecctl/rcon-commands.h b/minecctl/rcon-commands.h
index 1714dd5..c77e6fe 100644
--- a/minecctl/rcon-commands.h
+++ b/minecctl/rcon-commands.h
@@ -13,6 +13,6 @@ bool do_rcon_pcount(struct cfg *cfg, unsigned *online, unsigned *max);
bool do_console(struct cfg *cfg);
-bool do_command(struct cfg *cfg);
+bool do_commands(struct cfg *cfg);
#endif