diff options
Diffstat (limited to 'init')
-rw-r--r-- | init/init.c | 22 | ||||
-rw-r--r-- | init/init.h | 10 | ||||
-rw-r--r-- | init/init_parser.c | 134 | ||||
-rw-r--r-- | init/parser.c | 9 | ||||
-rw-r--r-- | init/readme.txt | 9 |
5 files changed, 128 insertions, 56 deletions
diff --git a/init/init.c b/init/init.c index 2b82937..269c11b 100644 --- a/init/init.c +++ b/init/init.c @@ -540,17 +540,35 @@ static int is_last_command(struct action *act, struct command *cmd) return (list_tail(&act->commands) == &cmd->clist); } + +void build_triggers_string(char *name_str, int length, struct action *cur_action) { + struct listnode *node; + struct trigger *cur_trigger; + + list_for_each(node, &cur_action->triggers) { + cur_trigger = node_to_item(node, struct trigger, nlist); + if (node != cur_action->triggers.next) { + strlcat(name_str, " " , length); + } + strlcat(name_str, cur_trigger->name , length); + } +} + void execute_one_command(void) { int ret, i; char cmd_str[256] = ""; + char name_str[256] = ""; if (!cur_action || !cur_command || is_last_command(cur_action, cur_command)) { cur_action = action_remove_queue_head(); cur_command = NULL; if (!cur_action) return; - INFO("processing action %p (%s)\n", cur_action, cur_action->name); + + build_triggers_string(name_str, sizeof(name_str), cur_action); + + INFO("processing action %p (%s)\n", cur_action, name_str); cur_command = get_first_command(cur_action); } else { cur_command = get_next_command(cur_action, cur_command); @@ -568,7 +586,7 @@ void execute_one_command(void) } } INFO("command '%s' action=%s status=%d (%s:%d)\n", - cmd_str, cur_action ? cur_action->name : "", ret, cur_command->filename, + cmd_str, cur_action ? name_str : "", ret, cur_command->filename, cur_command->line); } } diff --git a/init/init.h b/init/init.h index a7615a3..e03bd53 100644 --- a/init/init.h +++ b/init/init.h @@ -37,6 +37,11 @@ struct command char *args[1]; }; +struct trigger { + struct listnode nlist; + const char *name; +}; + struct action { /* node in list of all actions */ struct listnode alist; @@ -46,12 +51,15 @@ struct action { struct listnode tlist; unsigned hash; - const char *name; + /* list of actions which triggers the commands*/ + struct listnode triggers; struct listnode commands; struct command *current; }; +void build_triggers_string(char *name_str, int length, struct action *cur_action); + struct socketinfo { struct socketinfo *next; const char *name; diff --git a/init/init_parser.c b/init/init_parser.c index 2b4db8e..a124fa2 100644 --- a/init/init_parser.c +++ b/init/init_parser.c @@ -499,77 +499,92 @@ void service_for_each_flags(unsigned matchflags, void action_for_each_trigger(const char *trigger, void (*func)(struct action *act)) { - struct listnode *node; + struct listnode *node, *node2; struct action *act; + struct trigger *cur_trigger; + list_for_each(node, &action_list) { act = node_to_item(node, struct action, alist); - if (!strcmp(act->name, trigger)) { - func(act); + list_for_each(node2, &act->triggers) { + cur_trigger = node_to_item(node2, struct trigger, nlist); + if (!strcmp(cur_trigger->name, trigger)) { + func(act); + } } } } + void queue_property_triggers(const char *name, const char *value) { - struct listnode *node; + struct listnode *node, *node2; struct action *act; + struct trigger *cur_trigger; + bool match; + int name_length; + list_for_each(node, &action_list) { act = node_to_item(node, struct action, alist); - if (!strncmp(act->name, "property:", strlen("property:"))) { - const char *test = act->name + strlen("property:"); - int name_length = strlen(name); - - if (!strncmp(name, test, name_length) && - test[name_length] == '=' && - (!strcmp(test + name_length + 1, value) || - !strcmp(test + name_length + 1, "*"))) { - action_add_queue_tail(act); - } + match = !name; + list_for_each(node2, &act->triggers) { + cur_trigger = node_to_item(node2, struct trigger, nlist); + if (!strncmp(cur_trigger->name, "property:", strlen("property:"))) { + const char *test = cur_trigger->name + strlen("property:"); + if (!match) { + name_length = strlen(name); + if (!strncmp(name, test, name_length) && + test[name_length] == '=' && + (!strcmp(test + name_length + 1, value) || + !strcmp(test + name_length + 1, "*"))) { + match = true; + continue; + } + } else { + const char* equals = strchr(test, '='); + if (equals) { + char prop_name[PROP_NAME_MAX + 1]; + char value[PROP_VALUE_MAX]; + int length = equals - test; + if (length <= PROP_NAME_MAX) { + int ret; + memcpy(prop_name, test, length); + prop_name[length] = 0; + + /* does the property exist, and match the trigger value? */ + ret = property_get(prop_name, value); + if (ret > 0 && (!strcmp(equals + 1, value) || + !strcmp(equals + 1, "*"))) { + continue; + } + } + } + } + } + match = false; + break; + } + if (match) { + action_add_queue_tail(act); } } } void queue_all_property_triggers() { - struct listnode *node; - struct action *act; - list_for_each(node, &action_list) { - act = node_to_item(node, struct action, alist); - if (!strncmp(act->name, "property:", strlen("property:"))) { - /* parse property name and value - syntax is property:<name>=<value> */ - const char* name = act->name + strlen("property:"); - const char* equals = strchr(name, '='); - if (equals) { - char prop_name[PROP_NAME_MAX + 1]; - char value[PROP_VALUE_MAX]; - int length = equals - name; - if (length > PROP_NAME_MAX) { - ERROR("property name too long in trigger %s", act->name); - } else { - int ret; - memcpy(prop_name, name, length); - prop_name[length] = 0; - - /* does the property exist, and match the trigger value? */ - ret = property_get(prop_name, value); - if (ret > 0 && (!strcmp(equals + 1, value) || - !strcmp(equals + 1, "*"))) { - action_add_queue_tail(act); - } - } - } - } - } + queue_property_triggers(NULL, NULL); } void queue_builtin_action(int (*func)(int nargs, char **args), char *name) { struct action *act; struct command *cmd; + struct trigger *cur_trigger; act = calloc(1, sizeof(*act)); - act->name = name; + cur_trigger = calloc(1, sizeof(*cur_trigger)); + cur_trigger->name = name; + list_init(&act->triggers); + list_add_tail(&act->triggers, &cur_trigger->nlist); list_init(&act->commands); list_init(&act->qlist); @@ -611,6 +626,7 @@ int action_queue_empty() static void *parse_service(struct parse_state *state, int nargs, char **args) { struct service *svc; + struct trigger *cur_trigger; if (nargs < 3) { parse_error(state, "services must have a name and a program\n"); return 0; @@ -635,9 +651,12 @@ static void *parse_service(struct parse_state *state, int nargs, char **args) svc->name = args[1]; svc->classname = "default"; memcpy(svc->args, args + 2, sizeof(char*) * nargs); + cur_trigger = calloc(1, sizeof(*cur_trigger)); svc->args[nargs] = 0; svc->nargs = nargs; - svc->onrestart.name = "onrestart"; + list_init(&svc->onrestart.triggers); + cur_trigger->name = "onrestart"; + list_add_tail(&svc->onrestart.triggers, &cur_trigger->nlist); list_init(&svc->onrestart.commands); list_add_tail(&service_list, &svc->slist); return svc; @@ -821,16 +840,29 @@ static void parse_line_service(struct parse_state *state, int nargs, char **args static void *parse_action(struct parse_state *state, int nargs, char **args) { struct action *act; + struct trigger *cur_trigger; + int i; if (nargs < 2) { parse_error(state, "actions must have a trigger\n"); return 0; } - if (nargs > 2) { - parse_error(state, "actions may not have extra parameters\n"); - return 0; - } + act = calloc(1, sizeof(*act)); - act->name = args[1]; + list_init(&act->triggers); + + for (i = 1; i < nargs; i++) { + if (!(i % 2)) { + if (strcmp(args[i], "&&")) { + parse_error(state, "& is the only symbol allowed to concatenate actions\n"); + return 0; + } else + continue; + } + cur_trigger = calloc(1, sizeof(*cur_trigger)); + cur_trigger->name = args[i]; + list_add_tail(&act->triggers, &cur_trigger->nlist); + } + list_init(&act->commands); list_init(&act->qlist); list_add_tail(&action_list, &act->alist); diff --git a/init/parser.c b/init/parser.c index 48e7aec..80bfb09 100644 --- a/init/parser.c +++ b/init/parser.c @@ -15,9 +15,10 @@ void DUMP(void) struct command *cmd; struct listnode *node; struct listnode *node2; + char name_str[256] = ""; struct socketinfo *si; int n; - + list_for_each(node, &service_list) { svc = node_to_item(node, struct service, slist); RAW("service %s\n", svc->name); @@ -34,7 +35,11 @@ void DUMP(void) list_for_each(node, &action_list) { act = node_to_item(node, struct action, alist); - RAW("on %s\n", act->name); + RAW("on "); + build_triggers_string(name_str, sizeof(name_str), act); + RAW("%s", name_str); + RAW("\n"); + list_for_each(node2, &act->commands) { cmd = node_to_item(node2, struct command, clist); RAW(" %p", cmd->func); diff --git a/init/readme.txt b/init/readme.txt index 750d953..0b43fd5 100644 --- a/init/readme.txt +++ b/init/readme.txt @@ -123,6 +123,15 @@ boot Triggers of this form occur when the property <name> is set to the specific value <value>. + One can also test Mutliple properties to execute a group + of commands. For example: + + on property:test.a=1 && property:test.b=1 + setprop test.c 1 + + The above stub sets test.c to 1 only when + both test.a=1 and test.b=1 + Commands -------- |