mirror of
https://github.com/apache/nuttx-apps.git
synced 2026-08-27 20:30:41 +00:00
system/nxinit: support compound command execution
Example in init.rc: echo "start" && hello && echo "done" ls /missing || echo "not found" echo "A" && echo "B" || echo "fallback" Signed-off-by: fangpeina <fangpeina@xiaomi.com>
This commit is contained in:
parent
19bab7621d
commit
4cb0068732
3 changed files with 108 additions and 24 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue