Better version.

This commit is contained in:
Nicholas Marriott
2026-06-30 18:33:36 +01:00
parent 8ac29f6587
commit 36273fde4f

View File

@@ -756,65 +756,6 @@ cmd_parse_from_arguments_add(struct cmd_parse_node *seq,
TAILQ_INSERT_TAIL(&(*cmd)->children, child, entry); TAILQ_INSERT_TAIL(&(*cmd)->children, child, entry);
} }
/*
* Add one argv string, splitting unescaped ; as command separators:
*
* A single ; starts another command in the same sequence.
* A double ;; starts another sequence.
* A \; is kept as a literal semicolon in the argument.
*/
static void
cmd_parse_from_argument_string(struct cmd_parse_node *root,
struct cmd_parse_node **seq, struct cmd_parse_node **cmd, const char *s)
{
char *buf;
size_t len = 0;
struct cmd_parse_node *child;
const char *cp;
buf = xmalloc(1);
*buf = '\0';
for (cp = s; *cp != '\0'; cp++) {
if (*cp == '\\' && cp[1] != '\0') {
cp++;
buf = xrealloc(buf, len + 2);
buf[len++] = *cp;
buf[len] = '\0';
continue;
}
if (*cp != ';') {
buf = xrealloc(buf, len + 2);
buf[len++] = *cp;
buf[len] = '\0';
continue;
}
if (len != 0) {
child = cmd_parse_new_string_node(buf, 0);
cmd_parse_from_arguments_add(*seq, cmd, child);
len = 0;
*buf = '\0';
}
if (cp[1] == ';') {
*cmd = NULL;
*seq = cmd_parse_new_node(CMD_PARSE_SEQUENCE, 0);
TAILQ_INSERT_TAIL(&root->children, *seq, entry);
cp++;
} else
*cmd = NULL;
}
if (len != 0) {
child = cmd_parse_new_string_node(buf, 0);
cmd_parse_from_arguments_add(*seq, cmd, child);
}
free(buf);
}
/* Build a parse tree directly from existing argument values. */ /* Build a parse tree directly from existing argument values. */
struct cmd_parse_tree * struct cmd_parse_tree *
cmd_parse_from_arguments(struct args_value *values, u_int count) cmd_parse_from_arguments(struct args_value *values, u_int count)
@@ -822,18 +763,37 @@ cmd_parse_from_arguments(struct args_value *values, u_int count)
struct cmd_parse_tree *new; struct cmd_parse_tree *new;
struct cmd_parse_node *root, *seq, *cmd = NULL, *child; struct cmd_parse_node *root, *seq, *cmd = NULL, *child;
u_int i; u_int i;
char *copy;
size_t size;
int end;
root = cmd_parse_new_node(CMD_PARSE_ROOT, 0); root = cmd_parse_new_node(CMD_PARSE_ROOT, 0);
seq = cmd_parse_new_node(CMD_PARSE_SEQUENCE, 0); seq = cmd_parse_new_node(CMD_PARSE_SEQUENCE, 0);
TAILQ_INSERT_TAIL(&root->children, seq, entry); TAILQ_INSERT_TAIL(&root->children, seq, entry);
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
end = 0;
switch (values[i].type) { switch (values[i].type) {
case ARGS_NONE: case ARGS_NONE:
continue; continue;
case ARGS_STRING: case ARGS_STRING:
cmd_parse_from_argument_string(root, &seq, &cmd, copy = xstrdup(values[i].string);
values[i].string); size = strlen(copy);
if (size != 0 && copy[size - 1] == ';') {
copy[--size] = '\0';
if (size > 0 && copy[size - 1] == '\\')
copy[size - 1] = ';';
else
end = 1;
}
if (!end || size != 0) {
child = cmd_parse_new_string_node(copy, 0);
cmd_parse_from_arguments_add(seq, &cmd, child);
}
free(copy);
break; break;
case ARGS_COMMANDS: case ARGS_COMMANDS:
child = cmd_parse_new_commands_node(values[i].cmd, 0); child = cmd_parse_new_commands_node(values[i].cmd, 0);
@@ -842,6 +802,9 @@ cmd_parse_from_arguments(struct args_value *values, u_int count)
default: default:
fatalx("unknown argument type"); fatalx("unknown argument type");
} }
if (end)
cmd = NULL;
} }
new = xcalloc(1, sizeof *new); new = xcalloc(1, sizeof *new);