Merge branch 'obsd-master' into master

This commit is contained in:
Thomas Adam 2021-08-18 12:01:19 +01:00
commit c587ad027f

View File

@ -42,8 +42,23 @@ struct cmd_parse_scope {
TAILQ_ENTRY (cmd_parse_scope) entry;
};
enum cmd_parse_argument_type {
CMD_PARSE_STRING,
CMD_PARSE_COMMANDS
};
struct cmd_parse_argument {
enum cmd_parse_argument_type type;
char *string;
struct cmd_parse_commands *commands;
TAILQ_ENTRY(cmd_parse_argument) entry;
};
TAILQ_HEAD(cmd_parse_arguments, cmd_parse_argument);
struct cmd_parse_command {
u_int line;
struct cmd_parse_arguments arguments;
int argc;
char **argv;
@ -80,16 +95,15 @@ static void cmd_parse_free_commands(struct cmd_parse_commands *);
static char *cmd_parse_commands_to_string(struct cmd_parse_commands *);
static void cmd_parse_print_commands(struct cmd_parse_input *, u_int,
struct cmd_list *);
static void cmd_parse_flatten_command(struct cmd_parse_command *);
%}
%union
{
char *token;
struct {
int argc;
char **argv;
} arguments;
struct cmd_parse_arguments *arguments;
struct cmd_parse_argument *argument;
int flag;
struct {
int flag;
@ -107,8 +121,9 @@ static void cmd_parse_print_commands(struct cmd_parse_input *, u_int,
%token ENDIF
%token <token> FORMAT TOKEN EQUALS
%type <token> argument expanded format
%type <token> expanded format
%type <arguments> arguments
%type <argument> argument
%type <flag> if_open if_elif
%type <elif> elif elif1
%type <commands> argument_statements statements statement
@ -360,7 +375,7 @@ commands : command
struct cmd_parse_state *ps = &parse_state;
$$ = cmd_parse_new_commands();
if ($1->argc != 0 &&
if (!TAILQ_EMPTY(&$1->arguments) &&
(ps->scope == NULL || ps->scope->flag))
TAILQ_INSERT_TAIL($$, $1, entry);
else
@ -380,7 +395,7 @@ commands : command
{
struct cmd_parse_state *ps = &parse_state;
if ($3->argc != 0 &&
if (!TAILQ_EMPTY(&$3->arguments) &&
(ps->scope == NULL || ps->scope->flag)) {
$$ = $1;
TAILQ_INSERT_TAIL($$, $3, entry);
@ -401,27 +416,38 @@ command : assignment
$$ = xcalloc(1, sizeof *$$);
$$->line = ps->input->line;
TAILQ_INIT(&$$->arguments);
}
| optional_assignment TOKEN
{
struct cmd_parse_state *ps = &parse_state;
struct cmd_parse_argument *arg;
$$ = xcalloc(1, sizeof *$$);
$$->line = ps->input->line;
TAILQ_INIT(&$$->arguments);
cmd_prepend_argv(&$$->argc, &$$->argv, $2);
arg = xcalloc(1, sizeof *arg);
arg->type = CMD_PARSE_STRING;
arg->string = xstrdup($2);
TAILQ_INSERT_HEAD(&$$->arguments, arg, entry);
}
| optional_assignment TOKEN arguments
{
struct cmd_parse_state *ps = &parse_state;
struct cmd_parse_argument *arg;
$$ = xcalloc(1, sizeof *$$);
$$->line = ps->input->line;
TAILQ_INIT(&$$->arguments);
$$->argc = $3.argc;
$$->argv = $3.argv;
cmd_prepend_argv(&$$->argc, &$$->argv, $2);
TAILQ_CONCAT(&$$->arguments, $3, entry);
free($3);
arg = xcalloc(1, sizeof *arg);
arg->type = CMD_PARSE_STRING;
arg->string = xstrdup($2);
TAILQ_INSERT_HEAD(&$$->arguments, arg, entry);
}
condition1 : if_open commands if_close
@ -505,30 +531,34 @@ elif1 : if_elif commands
arguments : argument
{
$$.argc = 1;
$$.argv = xreallocarray(NULL, 1, sizeof *$$.argv);
$$ = xcalloc(1, sizeof *$$);
TAILQ_INIT($$);
$$.argv[0] = $1;
TAILQ_INSERT_HEAD($$, $1, entry);
}
| argument arguments
{
cmd_prepend_argv(&$2.argc, &$2.argv, $1);
free($1);
TAILQ_INSERT_HEAD($2, $1, entry);
$$ = $2;
}
argument : TOKEN
{
$$ = $1;
$$ = xcalloc(1, sizeof *$$);
$$->type = CMD_PARSE_STRING;
$$->string = xstrdup($1);
}
| EQUALS
{
$$ = $1;
$$ = xcalloc(1, sizeof *$$);
$$->type = CMD_PARSE_STRING;
$$->string = xstrdup($1);
}
| '{' argument_statements
{
$$ = cmd_parse_commands_to_string($2);
cmd_parse_free_commands($2);
$$ = xcalloc(1, sizeof *$$);
$$->type = CMD_PARSE_COMMANDS;
$$->commands = $2;
}
argument_statements : statement '}'
@ -572,10 +602,30 @@ cmd_parse_print_commands(struct cmd_parse_input *pi, u_int line,
}
}
static void
cmd_parse_free_arguments(struct cmd_parse_arguments *args)
{
struct cmd_parse_argument *arg, *arg1;
TAILQ_FOREACH_SAFE(arg, args, entry, arg1) {
switch (arg->type) {
case CMD_PARSE_STRING:
free(arg->string);
break;
case CMD_PARSE_COMMANDS:
cmd_parse_free_commands(arg->commands);
break;
}
TAILQ_REMOVE(args, arg, entry);
free(arg);
}
}
static void
cmd_parse_free_command(struct cmd_parse_command *cmd)
{
cmd_free_argv(cmd->argc, cmd->argv);
cmd_parse_free_arguments(&cmd->arguments);
free(cmd);
}
@ -585,7 +635,7 @@ cmd_parse_new_commands(void)
struct cmd_parse_commands *cmds;
cmds = xmalloc(sizeof *cmds);
TAILQ_INIT (cmds);
TAILQ_INIT(cmds);
return (cmds);
}
@ -601,30 +651,6 @@ cmd_parse_free_commands(struct cmd_parse_commands *cmds)
free(cmds);
}
static char *
cmd_parse_commands_to_string(struct cmd_parse_commands *cmds)
{
struct cmd_parse_command *cmd;
char *string = NULL, *s, *line;
TAILQ_FOREACH(cmd, cmds, entry) {
line = cmd_stringify_argv(cmd->argc, cmd->argv);
if (string == NULL)
s = line;
else {
xasprintf(&s, "%s ; %s", s, line);
free(line);
}
free(string);
string = s;
}
if (string == NULL)
string = xstrdup("");
log_debug("%s: %s", __func__, string);
return (string);
}
static struct cmd_parse_commands *
cmd_parse_run_parser(char **cause)
{
@ -674,6 +700,84 @@ cmd_parse_do_buffer(const char *buf, size_t len, struct cmd_parse_input *pi,
return (cmd_parse_run_parser(cause));
}
static void
cmd_parse_log_commands(struct cmd_parse_commands *cmds, const char *prefix)
{
struct cmd_parse_command *cmd;
struct cmd_parse_argument *arg;
u_int i, j;
char *s;
i = 0;
TAILQ_FOREACH(cmd, cmds, entry) {
j = 0;
TAILQ_FOREACH(arg, &cmd->arguments, entry) {
switch (arg->type) {
case CMD_PARSE_STRING:
log_debug("%s %u:%u: %s", prefix, i, j,
arg->string);
break;
case CMD_PARSE_COMMANDS:
xasprintf(&s, "%s %u:%u", prefix, i, j);
cmd_parse_log_commands(arg->commands, s);
free(s);
break;
}
j++;
}
i++;
}
}
static char *
cmd_parse_commands_to_string(struct cmd_parse_commands *cmds)
{
struct cmd_parse_command *cmd;
char *string = NULL, *s, *line;
TAILQ_FOREACH(cmd, cmds, entry) {
cmd_parse_flatten_command(cmd);
line = cmd_stringify_argv(cmd->argc, cmd->argv);
if (string == NULL)
s = line;
else {
xasprintf(&s, "%s ; %s", s, line);
free(line);
}
free(string);
string = s;
}
if (string == NULL)
string = xstrdup("");
log_debug("%s: %s", __func__, string);
return (string);
}
static void
cmd_parse_flatten_command(struct cmd_parse_command *cmd)
{
struct cmd_parse_argument *arg;
char *s;
cmd->argc = 0;
cmd->argv = NULL;
TAILQ_FOREACH(arg, &cmd->arguments, entry) {
switch (arg->type) {
case CMD_PARSE_STRING:
cmd_append_argv(&cmd->argc, &cmd->argv, arg->string);
break;
case CMD_PARSE_COMMANDS:
s = cmd_parse_commands_to_string(arg->commands);
cmd_append_argv(&cmd->argc, &cmd->argv, s);
free(s);
break;
}
}
}
static struct cmd_parse_result *
cmd_parse_build_commands(struct cmd_parse_commands *cmds,
struct cmd_parse_input *pi)
@ -694,6 +798,11 @@ cmd_parse_build_commands(struct cmd_parse_commands *cmds,
return (&pr);
}
/* Flatten command arguments. */
cmd_parse_log_commands(cmds, __func__);
TAILQ_FOREACH(cmd, cmds, entry)
cmd_parse_flatten_command(cmd);
/*
* Walk the commands and expand any aliases. Each alias is parsed
* individually to a new command list, any trailing arguments appended
@ -918,12 +1027,35 @@ cmd_parse_from_buffer(const void *buf, size_t len, struct cmd_parse_input *pi)
return (cmd_parse_build_commands(cmds, pi));
}
static void
cmd_parse_add_command(struct cmd_parse_commands *cmds,
struct cmd_parse_input *pi, int argc, char **argv)
{
struct cmd_parse_command *cmd;
struct cmd_parse_argument *arg;
int i;
cmd_log_argv(argc, argv, "%s", __func__);
cmd = xcalloc(1, sizeof *cmd);
cmd->line = pi->line;
TAILQ_INIT(&cmd->arguments);
for (i = 0; i < argc; i++) {
arg = xcalloc(1, sizeof *arg);
arg->type = CMD_PARSE_STRING;
arg->string = xstrdup(argv[i]);
TAILQ_INSERT_TAIL(&cmd->arguments, arg, entry);
}
TAILQ_INSERT_TAIL(cmds, cmd, entry);
}
struct cmd_parse_result *
cmd_parse_from_arguments(int argc, char **argv, struct cmd_parse_input *pi)
{
struct cmd_parse_input input;
struct cmd_parse_commands *cmds;
struct cmd_parse_command *cmd;
char **copy, **new_argv;
size_t size;
int i, last, new_argc;
@ -958,37 +1090,16 @@ cmd_parse_from_arguments(int argc, char **argv, struct cmd_parse_input *pi)
if (size != 0)
new_argc++;
if (new_argc != 0) {
cmd_log_argv(new_argc, new_argv, "%s: at %u", __func__,
i);
cmd = xcalloc(1, sizeof *cmd);
cmd->line = pi->line;
cmd->argc = new_argc;
cmd->argv = cmd_copy_argv(new_argc, new_argv);
TAILQ_INSERT_TAIL(cmds, cmd, entry);
}
if (new_argc != 0)
cmd_parse_add_command(cmds, pi, new_argc, new_argv);
last = i + 1;
}
if (last != argc) {
new_argv = copy + last;
new_argc = argc - last;
if (new_argc != 0) {
cmd_log_argv(new_argc, new_argv, "%s: at %u", __func__,
last);
cmd = xcalloc(1, sizeof *cmd);
cmd->line = pi->line;
cmd->argc = new_argc;
cmd->argv = cmd_copy_argv(new_argc, new_argv);
TAILQ_INSERT_TAIL(cmds, cmd, entry);
}
if (new_argc != 0)
cmd_parse_add_command(cmds, pi, new_argc, new_argv);
}
cmd_free_argv(argc, copy);