diff --git a/system/nxinit/action.c b/system/nxinit/action.c index f1d1d2bfd..6b2d166b7 100644 --- a/system/nxinit/action.c +++ b/system/nxinit/action.c @@ -223,6 +223,83 @@ static int event_callback(FAR struct action_manager_s *am, return event->pending; } +static FAR char *parse_operator(FAR char *pos, + FAR enum action_cmd_op_e *op) +{ + bool in_quotes = false; + + for (; *pos != '\0'; pos++) + { + if (*pos == '"') + { + in_quotes = !in_quotes; + continue; + } + + if (in_quotes) + { + continue; + } + + if (*pos == '&' && *(pos + 1) == '&') + { + *op = CMD_OP_AND; + *pos = '\0'; + return pos + 2; + } + + if (*pos == '|' && *(pos + 1) == '|') + { + *op = CMD_OP_OR; + *pos = '\0'; + return pos + 2; + } + } + + *op = CMD_OP_NONE; + return pos; +} + +static int parse_command(FAR char *pos, + FAR struct list_node *cmds) +{ + FAR enum action_cmd_op_e op = CMD_OP_NONE; + FAR enum action_cmd_op_e next_op; + FAR struct action_cmd_s *cmd; + FAR char *next_pos; + + while (*pos) + { + next_pos = parse_operator(pos, &next_op); + + cmd = calloc(1, sizeof(*cmd)); + if (cmd == NULL) + { + return -errno; + } + + cmd->argc = init_parse_arguments(pos, true, + nitems(cmd->argv) - 1, + cmd->argv); + if (cmd->argc < 1) + { + free(cmd); + init_err("invalid argument"); + return -EINVAL; + } + + cmd->op = op; + list_add_tail(cmds, &cmd->node); + init_debug("add command %p(%s) to list %p", cmd, cmd->argv[0], cmds); + init_dump_args(cmd->argc, cmd->argv); + + op = next_op; + pos = next_pos; + } + + return 0; +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -315,6 +392,15 @@ int init_action_run_command(FAR struct action_manager_s *am) struct action_cmd_s, node); } + if ((am->running->op == CMD_OP_AND && ready->prev_ret != 0) || + (am->running->op == CMD_OP_OR && ready->prev_ret == 0)) + { + init_debug("Skipping command due to op (prev_ret %d)", + ready->prev_ret); + init_action_reap_command(am, ready->prev_ret); + return 0; + } + #if defined(CONFIG_SYSTEM_NXINIT_ACTION_WARN_SLOW) && \ CONFIG_SYSTEM_NXINIT_ACTION_WARN_SLOW > 0 clock_gettime(CLOCK_MONOTONIC, &am->time_run); @@ -326,13 +412,13 @@ int init_action_run_command(FAR struct action_manager_s *am) } else { - init_action_reap_command(am); + init_action_reap_command(am, ret); } return 0; } -void init_action_reap_command(FAR struct action_manager_s *am) +void init_action_reap_command(FAR struct action_manager_s *am, int ret) { FAR struct action_s *ready = list_peek_head_type(&am->ready_actions, struct action_s, @@ -361,6 +447,7 @@ void init_action_reap_command(FAR struct action_manager_s *am) #endif am->pid_running = -1; + ready->prev_ret = ret; if (list_is_tail(&ready->cmds, &am->running->node)) { am->running = NULL; @@ -377,7 +464,6 @@ int init_action_parse(FAR const struct parser_s *parser, { FAR struct action_manager_s *am = parser->priv; FAR char *argv[2 * CONFIG_SYSTEM_NXINIT_ACTION_EVENTS_MAX]; - FAR struct action_cmd_s *cmd; FAR struct action_s *a; int ret; @@ -435,26 +521,15 @@ int init_action_parse(FAR const struct parser_s *parser, } else { - cmd = calloc(1, sizeof(*cmd)); - if (cmd == NULL) - { - init_err("Alloc action command"); - return -errno; - } - - cmd->argc = init_parse_arguments(buf, true, nitems(cmd->argv) - 1, - cmd->argv); - if (cmd->argc < 1) - { - free(cmd); - init_err("Invalid command argument"); - return -EINVAL; - } - a = list_last_entry(&am->actions, struct action_s, node); - list_add_tail(&a->cmds, &cmd->node); - init_debug("Add command %p(%s) to action %p", cmd, cmd->argv[0], a); - init_dump_args(cmd->argc, cmd->argv); + ret = parse_command(buf, &a->cmds); + if (ret < 0) + { + init_err("failed to parse command line: %s", buf); + return ret; + } + + init_debug("add command line to action %p", a); } return 0; diff --git a/system/nxinit/action.h b/system/nxinit/action.h index a13637ed2..48f672951 100644 --- a/system/nxinit/action.h +++ b/system/nxinit/action.h @@ -37,11 +37,19 @@ * Public Types ****************************************************************************/ +enum action_cmd_op_e +{ + CMD_OP_NONE, + CMD_OP_AND, + CMD_OP_OR, +}; + struct action_cmd_s { struct list_node node; /* Command list node */ int argc; FAR char *argv[CONFIG_SYSTEM_NXINIT_ACTION_CMD_ARGS_MAX]; + enum action_cmd_op_e op; }; struct action_event_s @@ -58,6 +66,7 @@ struct action_s struct list_node ready_node; /* Ready list node */ struct action_event_s events[CONFIG_SYSTEM_NXINIT_ACTION_EVENTS_MAX]; struct list_node cmds; /* Command header, struct action_cmd_s */ + int prev_ret; }; struct action_manager_s @@ -102,7 +111,7 @@ typedef CODE int (*init_action_event_cb)(FAR struct action_manager_s *, int init_action_add_event(FAR struct action_manager_s *am, FAR const char *name); int init_action_run_command(FAR struct action_manager_s *am); -void init_action_reap_command(FAR struct action_manager_s *am); +void init_action_reap_command(FAR struct action_manager_s *am, int ret); int init_action_parse(FAR const struct parser_s *parser, bool create, FAR char *buf); int init_action_foreach_event(FAR struct action_manager_s *am, diff --git a/system/nxinit/init.c b/system/nxinit/init.c index 2c2bcb166..8f8be4e29 100644 --- a/system/nxinit/init.c +++ b/system/nxinit/init.c @@ -91,7 +91,7 @@ static void reap_process(FAR struct service_manager_s *sm, if (pid == am->pid_running) { name = am->running->argv[0]; - init_action_reap_command(am); + init_action_reap_command(am, ret); } service = init_service_find_by_pid(sm, pid);