version 1.35, 2021/08/20 06:30:57 |
version 1.36, 2021/08/20 09:06:26 |
|
|
u_int line; |
u_int line; |
struct cmd_parse_arguments arguments; |
struct cmd_parse_arguments arguments; |
|
|
int argc; |
|
char **argv; |
|
|
|
TAILQ_ENTRY(cmd_parse_command) entry; |
TAILQ_ENTRY(cmd_parse_command) entry; |
}; |
}; |
TAILQ_HEAD(cmd_parse_commands, cmd_parse_command); |
TAILQ_HEAD(cmd_parse_commands, cmd_parse_command); |
|
|
static void cmd_parse_free_command(struct cmd_parse_command *); |
static void cmd_parse_free_command(struct cmd_parse_command *); |
static struct cmd_parse_commands *cmd_parse_new_commands(void); |
static struct cmd_parse_commands *cmd_parse_new_commands(void); |
static void cmd_parse_free_commands(struct cmd_parse_commands *); |
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_build_commands(struct cmd_parse_commands *, |
static void cmd_parse_print_commands(struct cmd_parse_input *, u_int, |
struct cmd_parse_input *, struct cmd_parse_result *); |
|
static void cmd_parse_print_commands(struct cmd_parse_input *, |
struct cmd_list *); |
struct cmd_list *); |
static void cmd_parse_flatten_command(struct cmd_parse_command *); |
|
|
|
%} |
%} |
|
|
|
|
} |
} |
|
|
static void |
static void |
cmd_parse_print_commands(struct cmd_parse_input *pi, u_int line, |
cmd_parse_print_commands(struct cmd_parse_input *pi, struct cmd_list *cmdlist) |
struct cmd_list *cmdlist) |
|
{ |
{ |
char *s; |
char *s; |
|
|
if (pi->item != NULL && (pi->flags & CMD_PARSE_VERBOSE)) { |
if (pi->item == NULL || (~pi->flags & CMD_PARSE_VERBOSE)) |
s = cmd_list_print(cmdlist, 0); |
return; |
if (pi->file != NULL) |
s = cmd_list_print(cmdlist, 0); |
cmdq_print(pi->item, "%s:%u: %s", pi->file, line, s); |
if (pi->file != NULL) |
else |
cmdq_print(pi->item, "%s:%u: %s", pi->file, pi->line, s); |
cmdq_print(pi->item, "%u: %s", line, s); |
else |
free(s); |
cmdq_print(pi->item, "%u: %s", pi->line, s); |
|
free(s); |
|
} |
|
|
|
static void |
|
cmd_parse_free_argument(struct cmd_parse_argument *arg) |
|
{ |
|
switch (arg->type) { |
|
case CMD_PARSE_STRING: |
|
free(arg->string); |
|
break; |
|
case CMD_PARSE_COMMANDS: |
|
cmd_parse_free_commands(arg->commands); |
|
break; |
} |
} |
|
free(arg); |
} |
} |
|
|
static void |
static void |
|
|
struct cmd_parse_argument *arg, *arg1; |
struct cmd_parse_argument *arg, *arg1; |
|
|
TAILQ_FOREACH_SAFE(arg, args, entry, 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); |
TAILQ_REMOVE(args, arg, entry); |
free(arg); |
cmd_parse_free_argument(arg); |
} |
} |
} |
} |
|
|
static void |
static void |
cmd_parse_free_command(struct cmd_parse_command *cmd) |
cmd_parse_free_command(struct cmd_parse_command *cmd) |
{ |
{ |
cmd_free_argv(cmd->argc, cmd->argv); |
|
cmd_parse_free_arguments(&cmd->arguments); |
cmd_parse_free_arguments(&cmd->arguments); |
free(cmd); |
free(cmd); |
} |
} |
|
|
} |
} |
} |
} |
|
|
static char * |
static int |
cmd_parse_commands_to_string(struct cmd_parse_commands *cmds) |
cmd_parse_expand_alias(struct cmd_parse_command *cmd, |
|
struct cmd_parse_input *pi, struct cmd_parse_result *pr, |
|
struct cmd_list **cmdlist) |
{ |
{ |
struct cmd_parse_command *cmd; |
struct cmd_parse_argument *arg, *arg1, *first, *after; |
char *string = NULL, *s, *line; |
struct cmd_parse_commands *cmds; |
|
struct cmd_parse_command *last; |
|
char *alias, *name, *cause; |
|
|
TAILQ_FOREACH(cmd, cmds, entry) { |
*cmdlist = NULL; |
cmd_parse_flatten_command(cmd); |
|
|
|
line = cmd_stringify_argv(cmd->argc, cmd->argv); |
first = TAILQ_FIRST(&cmd->arguments); |
if (string == NULL) |
if (first == NULL || first->type != CMD_PARSE_STRING) { |
s = line; |
pr->status = CMD_PARSE_EMPTY; |
else { |
return (1); |
xasprintf(&s, "%s ; %s", s, line); |
} |
free(line); |
name = first->string; |
} |
|
|
|
free(string); |
alias = cmd_get_alias(name); |
string = s; |
if (alias == NULL) |
|
return (0); |
|
log_debug("%s: %u alias %s = %s", __func__, pi->line, name, alias); |
|
|
|
cmds = cmd_parse_do_buffer(alias, strlen(alias), pi, &cause); |
|
free(alias); |
|
if (cmds == NULL) { |
|
pr->status = CMD_PARSE_ERROR; |
|
pr->error = cause; |
|
return (1); |
} |
} |
if (string == NULL) |
|
string = xstrdup(""); |
last = TAILQ_LAST(cmds, cmd_parse_commands); |
log_debug("%s: %s", __func__, string); |
if (last == NULL) { |
return (string); |
*cmdlist = cmd_list_new(); |
|
return (1); |
|
} |
|
|
|
TAILQ_REMOVE(&cmd->arguments, first, entry); |
|
cmd_parse_free_argument(first); |
|
|
|
after = TAILQ_NEXT(TAILQ_FIRST(&last->arguments), entry); |
|
TAILQ_FOREACH_SAFE(arg, &cmd->arguments, entry, arg1) { |
|
TAILQ_REMOVE(&cmd->arguments, arg, entry); |
|
if (after == NULL) |
|
TAILQ_INSERT_TAIL(&last->arguments, arg, entry); |
|
else |
|
TAILQ_INSERT_AFTER(&last->arguments, after, arg, entry); |
|
after = arg; |
|
} |
|
cmd_parse_log_commands(cmds, __func__); |
|
|
|
cmd_parse_build_commands(cmds, pi, pr); |
|
if (pr->status != CMD_PARSE_SUCCESS) |
|
*cmdlist = pr->cmdlist; |
|
return (1); |
} |
} |
|
|
static void |
static struct cmd_list * |
cmd_parse_flatten_command(struct cmd_parse_command *cmd) |
cmd_parse_build_command(struct cmd_parse_command *cmd, |
|
struct cmd_parse_input *pi, struct cmd_parse_result *pr) |
{ |
{ |
struct cmd_parse_argument *arg; |
struct cmd_parse_argument *arg; |
char *s; |
struct cmd_list *cmdlist; |
|
struct cmd *add; |
|
char *s, **argv = NULL, *cause; |
|
int argc = 0; |
|
|
cmd->argc = 0; |
if (cmd_parse_expand_alias(cmd, pi, pr, &cmdlist)) |
cmd->argv = NULL; |
return (cmdlist); |
|
|
TAILQ_FOREACH(arg, &cmd->arguments, entry) { |
TAILQ_FOREACH(arg, &cmd->arguments, entry) { |
switch (arg->type) { |
switch (arg->type) { |
case CMD_PARSE_STRING: |
case CMD_PARSE_STRING: |
cmd_append_argv(&cmd->argc, &cmd->argv, arg->string); |
cmd_append_argv(&argc, &argv, arg->string); |
break; |
break; |
case CMD_PARSE_COMMANDS: |
case CMD_PARSE_COMMANDS: |
s = cmd_parse_commands_to_string(arg->commands); |
cmd_parse_build_commands(arg->commands, pi, pr); |
cmd_append_argv(&cmd->argc, &cmd->argv, s); |
if (pr->status != CMD_PARSE_SUCCESS) |
|
return (NULL); |
|
s = cmd_list_print(pr->cmdlist, 0); |
|
cmd_append_argv(&argc, &argv, s); |
free(s); |
free(s); |
break; |
break; |
} |
} |
} |
} |
} |
|
|
|
static struct cmd * |
add = cmd_parse(argc, argv, pi->file, pi->line, &cause); |
cmd_parse_build_command(struct cmd_parse_command *cmd, |
|
struct cmd_parse_input *pi, u_int line, struct cmd_parse_result *pr) |
|
{ |
|
struct cmd *add; |
|
char *cause; |
|
|
|
add = cmd_parse(cmd->argc, cmd->argv, pi->file, line, &cause); |
|
if (add == NULL) { |
if (add == NULL) { |
pr->status = CMD_PARSE_ERROR; |
pr->status = CMD_PARSE_ERROR; |
pr->error = cmd_parse_get_error(pi->file, line, cause); |
pr->error = cmd_parse_get_error(pi->file, pi->line, cause); |
free(cause); |
free(cause); |
return (NULL); |
return (NULL); |
} |
} |
return (add); |
cmdlist = cmd_list_new(); |
|
cmd_list_append(cmdlist, add); |
|
return (cmdlist); |
} |
} |
|
|
static struct cmd_parse_result * |
static void |
cmd_parse_build_commands(struct cmd_parse_commands *cmds, |
cmd_parse_build_commands(struct cmd_parse_commands *cmds, |
struct cmd_parse_input *pi) |
struct cmd_parse_input *pi, struct cmd_parse_result *pr) |
{ |
{ |
static struct cmd_parse_result pr; |
struct cmd_parse_command *cmd; |
struct cmd_parse_commands *cmds2; |
|
struct cmd_parse_command *cmd, *cmd2, *next, *next2, *after; |
|
u_int line = UINT_MAX; |
u_int line = UINT_MAX; |
int i; |
struct cmd_list *current = NULL, *result, *add; |
struct cmd_list *current = NULL, *result; |
char *s; |
struct cmd *add; |
|
char *name, *alias, *cause, *s; |
|
|
|
/* Check for an empty list. */ |
/* Check for an empty list. */ |
if (TAILQ_EMPTY(cmds)) { |
if (TAILQ_EMPTY(cmds)) { |
cmd_parse_free_commands(cmds); |
pr->status = CMD_PARSE_EMPTY; |
pr.status = CMD_PARSE_EMPTY; |
return; |
return (&pr); |
|
} |
} |
|
cmd_parse_log_commands(cmds, __func__); |
|
|
/* 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 |
|
* to the last command, and all commands inserted into the original |
|
* command list. |
|
*/ |
|
TAILQ_FOREACH_SAFE(cmd, cmds, entry, next) { |
|
name = cmd->argv[0]; |
|
|
|
alias = cmd_get_alias(name); |
|
if (alias == NULL) |
|
continue; |
|
|
|
line = cmd->line; |
|
log_debug("%s: %u %s = %s", __func__, line, name, alias); |
|
|
|
pi->line = line; |
|
cmds2 = cmd_parse_do_buffer(alias, strlen(alias), pi, &cause); |
|
free(alias); |
|
if (cmds2 == NULL) { |
|
pr.status = CMD_PARSE_ERROR; |
|
pr.error = cause; |
|
goto out; |
|
} |
|
|
|
cmd2 = TAILQ_LAST(cmds2, cmd_parse_commands); |
|
if (cmd2 == NULL) { |
|
TAILQ_REMOVE(cmds, cmd, entry); |
|
cmd_parse_free_command(cmd); |
|
continue; |
|
} |
|
cmd_parse_flatten_command(cmd2); |
|
for (i = 1; i < cmd->argc; i++) |
|
cmd_append_argv(&cmd2->argc, &cmd2->argv, cmd->argv[i]); |
|
|
|
after = cmd; |
|
TAILQ_FOREACH_SAFE(cmd2, cmds2, entry, next2) { |
|
cmd2->line = line; |
|
TAILQ_REMOVE(cmds2, cmd2, entry); |
|
TAILQ_INSERT_AFTER(cmds, after, cmd2, entry); |
|
after = cmd2; |
|
} |
|
cmd_parse_free_commands(cmds2); |
|
|
|
TAILQ_REMOVE(cmds, cmd, entry); |
|
cmd_parse_free_command(cmd); |
|
} |
|
|
|
/* |
|
* Parse each command into a command list. Create a new command list |
* Parse each command into a command list. Create a new command list |
* for each line (unless the flag is set) so they get a new group (so |
* for each line (unless the flag is set) so they get a new group (so |
* the queue knows which ones to remove if a command fails when |
* the queue knows which ones to remove if a command fails when |
|
|
TAILQ_FOREACH(cmd, cmds, entry) { |
TAILQ_FOREACH(cmd, cmds, entry) { |
if (((~pi->flags & CMD_PARSE_ONEGROUP) && cmd->line != line)) { |
if (((~pi->flags & CMD_PARSE_ONEGROUP) && cmd->line != line)) { |
if (current != NULL) { |
if (current != NULL) { |
cmd_parse_print_commands(pi, line, current); |
cmd_parse_print_commands(pi, current); |
cmd_list_move(result, current); |
cmd_list_move(result, current); |
cmd_list_free(current); |
cmd_list_free(current); |
} |
} |
|
|
} |
} |
if (current == NULL) |
if (current == NULL) |
current = cmd_list_new(); |
current = cmd_list_new(); |
line = cmd->line; |
line = pi->line = cmd->line; |
|
|
add = cmd_parse_build_command(cmd, pi, line, &pr); |
add = cmd_parse_build_command(cmd, pi, pr); |
if (add == NULL) { |
if (add == NULL) { |
cmd_list_free(result); |
cmd_list_free(result); |
cmd_list_free(current); |
cmd_list_free(current); |
goto out; |
return; |
} |
} |
cmd_list_append(current, add); |
cmd_list_move(current, add); |
|
cmd_list_free(add); |
} |
} |
if (current != NULL) { |
if (current != NULL) { |
cmd_parse_print_commands(pi, line, current); |
cmd_parse_print_commands(pi, current); |
cmd_list_move(result, current); |
cmd_list_move(result, current); |
cmd_list_free(current); |
cmd_list_free(current); |
} |
} |
|
|
log_debug("%s: %s", __func__, s); |
log_debug("%s: %s", __func__, s); |
free(s); |
free(s); |
|
|
pr.status = CMD_PARSE_SUCCESS; |
pr->status = CMD_PARSE_SUCCESS; |
pr.cmdlist = result; |
pr->cmdlist = result; |
|
|
out: |
|
cmd_parse_free_commands(cmds); |
|
|
|
return (&pr); |
|
} |
} |
|
|
struct cmd_parse_result * |
struct cmd_parse_result * |
|
|
pr.error = cause; |
pr.error = cause; |
return (&pr); |
return (&pr); |
} |
} |
return (cmd_parse_build_commands(cmds, pi)); |
cmd_parse_build_commands(cmds, pi, &pr); |
|
cmd_parse_free_commands(cmds); |
|
return (&pr); |
|
|
} |
} |
|
|
struct cmd_parse_result * |
struct cmd_parse_result * |
|
|
pr.error = cause; |
pr.error = cause; |
return (&pr); |
return (&pr); |
} |
} |
return (cmd_parse_build_commands(cmds, pi)); |
cmd_parse_build_commands(cmds, pi, &pr); |
|
cmd_parse_free_commands(cmds); |
|
return (&pr); |
} |
} |
|
|
static void |
static void |
|
|
struct cmd_parse_result * |
struct cmd_parse_result * |
cmd_parse_from_arguments(int argc, char **argv, struct cmd_parse_input *pi) |
cmd_parse_from_arguments(int argc, char **argv, struct cmd_parse_input *pi) |
{ |
{ |
|
static struct cmd_parse_result pr; |
struct cmd_parse_input input; |
struct cmd_parse_input input; |
struct cmd_parse_commands *cmds; |
struct cmd_parse_commands *cmds; |
char **copy, **new_argv; |
char **copy, **new_argv; |
|
|
} |
} |
|
|
cmd_free_argv(argc, copy); |
cmd_free_argv(argc, copy); |
return (cmd_parse_build_commands(cmds, pi)); |
cmd_parse_build_commands(cmds, pi, &pr); |
|
cmd_parse_free_commands(cmds); |
|
return (&pr); |
} |
} |
|
|
static int printflike(1, 2) |
static int printflike(1, 2) |