This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git
commit 99dd131a725e15cb833048181c6218b12e38b385 Author: wangjianyu3 <[email protected]> AuthorDate: Fri Sep 12 11:48:39 2025 +0800 system/nxinit: Add support for action triggers Previously only supported event trigger, now added support for action triggers (property setting). Steps to enable action triggers: - Define all init_property_*() interfaces declared in this file. - Data structures or functions that will likely be used: - struct action_trigger_s - init_action_for_every() Example ``` on boot setprop key_test setprop key_test value_test /* property changed and matched */ trigger event_test on event_test && property:key_test=value_test echo "on event_test, property changed!" on property:key_test=value_test echo "property changed!" ``` Signed-off-by: wangjianyu3 <[email protected]> --- system/nxinit/Kconfig | 16 ++-- system/nxinit/action.c | 218 ++++++++++++++++++++++++++++++++++++++----------- system/nxinit/action.h | 26 ++++-- system/nxinit/init.c | 1 - 4 files changed, 200 insertions(+), 61 deletions(-) diff --git a/system/nxinit/Kconfig b/system/nxinit/Kconfig index e159e90b7..f30335677 100644 --- a/system/nxinit/Kconfig +++ b/system/nxinit/Kconfig @@ -53,7 +53,7 @@ config SYSTEM_NXINIT_ACTION_CMD_ARGS_MAX Maximum number of command arguments. Form: ``` - on <trigger> + on <event> [&& <event>]* <command> <command> <command> @@ -67,16 +67,18 @@ config SYSTEM_NXINIT_ACTION_WARN_SLOW ---help--- Warning if command took more than `SYSTEM_NXINIT_ACTION_WARN_SLOW` ms. -config SYSTEM_NXINIT_ACTION_MANAGER_EVENT_MAX - int "Max number of action manager events" - default 32 +config SYSTEM_NXINIT_ACTION_EVENTS_MAX + int "Max number of events" + default 1 + range 1 64 ---help--- - Maximum number of action manager events. + Maximum number of event and action events. + See action.h: ``` - struct action_manager_s + struct action_s { ... - FAR char *events[CONFIG_SYSTEM_NXINIT_ACTION_MANAGER_EVENT_MAX]; + struct action_event_s events[CONFIG_SYSTEM_NXINIT_ACTION_EVENTS_MAX]; ... }; ``` diff --git a/system/nxinit/action.c b/system/nxinit/action.c index 0975682b7..b4bf03274 100644 --- a/system/nxinit/action.c +++ b/system/nxinit/action.c @@ -32,21 +32,32 @@ #include <sys/types.h> #include <sys/param.h> #include <unistd.h> +#include <fnmatch.h> #include <nuttx/clock.h> #include "action.h" #include "builtin.h" #include "init.h" +#include "property.h" /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ -/* Maximum number of parameters for the action trigger. - * Format: `on <trigger>` - */ +#define ACTION_SECTION_PROP_PREFIX "property:" +#define ACTION_SECTION_AND_PREFIX "&&" -#define ACTION_ARGUMENTS_MAX 2 +#define ACTION_PROP_KEY_DEFAULT "default" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct event_arg_s +{ + FAR const char *key; + FAR const char *value; +}; /**************************************************************************** * Private Function Prototypes @@ -66,9 +77,21 @@ static void init_dump_action(FAR struct action_s *action); static void init_dump_action(FAR struct action_s *action) { FAR struct action_cmd_s *cmd; + size_t i; init_debug("Action %p", action); - init_debug(" event trigger: '%s'", action->event ? action->event : ""); + for (i = 0; i < nitems(action->events); i++) + { + if (!action->events[i].key) + { + continue; + } + + init_debug(" %s%s%s", action->events[i].key, + action->events[i].invert ? "!=" : "==", + action->events[i].value); + } + list_for_every_entry(&action->cmds, cmd, struct action_cmd_s, node) { init_dump_args(cmd->argc, cmd->argv); @@ -94,8 +117,8 @@ static void add_ready(FAR struct action_manager_s *am, { if (ready == a) { - init_debug("Action %p(%s) already on the queue", a, - a->event ? a->event : ""); + init_debug("Event %p(%s:%s) already on the queue", a, + a->events[0].key, a->events[0].value); init_dump_action(a); return; } @@ -104,71 +127,150 @@ static void add_ready(FAR struct action_manager_s *am, list_add_tail(&am->ready_actions, &a->ready_node); } -static void update_ready(FAR struct action_manager_s *am) +static int parse_event(FAR char *buf, FAR struct action_event_s *events, + size_t count) { + FAR char *value; + FAR char *key; size_t i; - /* Actions with event trigger */ + value = strchr(buf, '='); + if (!value || !*(value + 1)) + { + return -EINVAL; + } + + *(value++) = '\0'; + key = strchr(buf, ':'); + if (!key || !*(key + 1)) + { + return -EINVAL; + } - for (i = 0; i < nitems(am->events); i++) + *(key++) = '\0'; + for (i = 0; i < count; i++) { - if (!am->events[i]) + if (events[i].key) { continue; } - am->current = list_prepare_entry(am->current, &am->actions, - struct action_s, node); - list_for_every_entry_continue(am->current, &am->actions, - struct action_s, node) + if (key[strlen(key) - 1] == '!') { - if (am->current->event && !strcmp(am->current->event, - am->events[i])) + events[i].invert = true; + key[strlen(key) - 1] = '\0'; /* Skip '!' */ + } + else + { + events[i].invert = false; + } + + events[i].key = strdup(key); + events[i].value = strdup(value); + + if (events[i].key && events[i].value) + { + init_debug("Added action event key:%s value:%s", events[i].key, + events[i].value); + return 0; + } + + for (; i >= 0; i--) + { + if (events[i].key) + { + free((FAR void *)events[i].key); + events[i].key = NULL; + } + + if (events[i].value) { - add_ready(am, am->current); - return; + free(events[i].value); } } - init_debug("Remove event [%zu] '%s'", i, am->events[i]); - am->current = NULL; - free(am->events[i]); - am->events[i] = NULL; + return -errno; + } + + init_err("Dropped action event key:%s value:%s", key, value); + return -ENOBUFS; +} + +static int event_callback(FAR struct action_manager_s *am, + FAR struct action_s *a, + FAR struct action_event_s *event, + FAR void *argument) +{ + struct event_arg_s *arg = argument; + + if (strcmp(arg->key, event->key)) + { + return 0; } + + if (event->invert != fnmatch(event->value, arg->value, 0)) + { + event->pending = false; + } + else if (!event->pending) + { + event->pending = true; + init_debug("Trigger %s%s%s", event->key, + event->invert ? "!=" : "==", + event->value); + } + + return event->pending; } /**************************************************************************** * Public Functions ****************************************************************************/ -int init_action_add_event(FAR struct action_manager_s *am, - FAR const char *event) +int init_action_foreach_event(FAR struct action_manager_s *am, + init_action_event_cb cb, + FAR void *arg) { - int ret = -ENOBUFS; + FAR struct action_s *a; size_t i; + int ret = 0; - for (i = 0; i < nitems(am->events); i++) + list_for_every_entry(&am->actions, a, struct action_s, node) { - if (am->events[i]) + for (i = 0; i < nitems(a->events) && a->events[i].key; i++) { - continue; - } - - am->events[i] = strdup(event); - if (am->events[i]) - { - init_debug("Add event [%zu] '%s'", i, am->events[i]); - return 0; + ret = cb(am, a, &a->events[i], arg); + if (ret < 0) + { + break; + } + else if (ret > 0) + { + add_ready(am, a); + } } - - ret = -errno; - break; } - init_warn("Drop event '%s' %d", event, ret); return ret; } +void init_action_trigger_event(FAR struct action_manager_s *am, + FAR const char *key, + FAR const char *value) +{ + struct event_arg_s arg; + + arg.key = key; + arg.value = value; + init_action_foreach_event(am, event_callback, &arg); +} + +int init_action_add_event(FAR struct action_manager_s *am, + FAR const char *event) +{ + return init_property_set(am->prop, ACTION_PROP_KEY_DEFAULT, event); +} + /**************************************************************************** * Name: init_action_run_command * @@ -195,7 +297,6 @@ int init_action_run_command(FAR struct action_manager_s *am) return INT_MAX; } - update_ready(am); if (list_is_empty(&am->ready_actions)) { return INT_MAX; @@ -271,7 +372,7 @@ int init_action_parse(FAR const struct parser_s *parser, bool create, FAR char *buf) { FAR struct action_manager_s *am = parser->priv; - FAR char *argv[ACTION_ARGUMENTS_MAX]; + FAR char *argv[2 * CONFIG_SYSTEM_NXINIT_ACTION_EVENTS_MAX]; FAR struct action_cmd_s *cmd; FAR struct action_s *a; int ret; @@ -294,12 +395,35 @@ int init_action_parse(FAR const struct parser_s *parser, list_initialize(&a->cmds); - a->event = strdup(argv[--ret]); - if (a->event == NULL) + while (--ret > 0) { - init_err("Event trigger"); - free(a); - return -errno; + if (!strncmp(argv[ret], ACTION_SECTION_PROP_PREFIX, + strlen(ACTION_SECTION_PROP_PREFIX))) + { + ret = parse_event(argv[ret], a->events, + nitems(a->events)); + if (ret < 0) + { + free(a); + return ret; + } + } + else if (strncmp(argv[ret], ACTION_SECTION_AND_PREFIX, + strlen(ACTION_SECTION_AND_PREFIX))) + { + char tmp[CONFIG_SYSTEM_NXINIT_RC_LINE_MAX]; + + sprintf(tmp, ":%s=%s", ACTION_PROP_KEY_DEFAULT, argv[ret]); + ret = parse_event(tmp, a->events, + nitems(a->events)); + if (ret < 0) + { + free(a); + return ret; + } + + break; + } } list_add_tail(&am->actions, &a->node); diff --git a/system/nxinit/action.h b/system/nxinit/action.h index f05bff1aa..19252f3d0 100644 --- a/system/nxinit/action.h +++ b/system/nxinit/action.h @@ -44,15 +44,19 @@ struct action_cmd_s FAR char *argv[CONFIG_SYSTEM_NXINIT_ACTION_CMD_ARGS_MAX]; }; +struct action_event_s +{ + FAR const char *key; + FAR char *value; + bool invert; + bool pending; +}; + struct action_s { struct list_node node; /* Action list node */ struct list_node ready_node; /* Ready list node */ - - /* Event trigger */ - - FAR const char *event; - + struct action_event_s events[CONFIG_SYSTEM_NXINIT_ACTION_EVENTS_MAX]; struct list_node cmds; /* Command header, struct action_cmd_s */ }; @@ -61,7 +65,6 @@ struct action_manager_s struct list_node actions; /* Action header, struct action_s */ struct list_node ready_actions; /* Ready header, struct action_s */ - FAR char *events[CONFIG_SYSTEM_NXINIT_ACTION_MANAGER_EVENT_MAX]; FAR struct action_s *current; FAR struct action_cmd_s *running; @@ -75,6 +78,11 @@ struct action_manager_s FAR struct init_poller_s *prop; }; +typedef CODE int (*init_action_event_cb)(FAR struct action_manager_s *, + FAR struct action_s *, + FAR struct action_event_s *, + FAR void *arg); + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ @@ -85,6 +93,12 @@ int init_action_run_command(FAR struct action_manager_s *am); void init_action_reap_command(FAR struct action_manager_s *am); 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, + init_action_event_cb cb, + FAR void *arg); +void init_action_trigger_event(FAR struct action_manager_s *am, + FAR const char *key, + FAR const char *value); #ifdef CONFIG_SYSTEM_NXINIT_DEBUG void init_dump_actions(FAR struct list_node *head); #else diff --git a/system/nxinit/init.c b/system/nxinit/init.c index 0f5c03ab4..bd8164a46 100644 --- a/system/nxinit/init.c +++ b/system/nxinit/init.c @@ -125,7 +125,6 @@ int main(int argc, FAR char *argv[]) { .actions = LIST_INITIAL_VALUE(am.actions), .ready_actions = LIST_INITIAL_VALUE(am.ready_actions), - .events = { 0 }, .current = NULL, .running = NULL, .pid_running = -1,
