Loading init/init.c +20 −2 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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); } } Loading init/init.h +9 −1 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading init/init_parser.c +83 −51 Original line number Diff line number Diff line Loading @@ -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)) { 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); 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, "*"))) { action_add_queue_tail(act); } } } match = true; continue; } 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, '='); } else { const char* equals = strchr(test, '='); 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 length = equals - test; if (length <= PROP_NAME_MAX) { int ret; memcpy(prop_name, name, length); 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, "*"))) { action_add_queue_tail(act); continue; } } } } } match = false; break; } if (match) { action_add_queue_tail(act); } } } void queue_all_property_triggers() { 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); Loading Loading @@ -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; Loading @@ -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; Loading Loading @@ -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"); act = calloc(1, sizeof(*act)); 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; } act = calloc(1, sizeof(*act)); act->name = args[1]; 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); Loading init/parser.c +7 −2 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ void DUMP(void) struct command *cmd; struct listnode *node; struct listnode *node2; char name_str[256] = ""; struct socketinfo *si; int n; Loading @@ -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); Loading init/readme.txt +9 −0 Original line number Diff line number Diff line Loading @@ -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 -------- Loading Loading
init/init.c +20 −2 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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); } } Loading
init/init.h +9 −1 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading
init/init_parser.c +83 −51 Original line number Diff line number Diff line Loading @@ -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)) { 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); 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, "*"))) { action_add_queue_tail(act); } } } match = true; continue; } 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, '='); } else { const char* equals = strchr(test, '='); 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 length = equals - test; if (length <= PROP_NAME_MAX) { int ret; memcpy(prop_name, name, length); 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, "*"))) { action_add_queue_tail(act); continue; } } } } } match = false; break; } if (match) { action_add_queue_tail(act); } } } void queue_all_property_triggers() { 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); Loading Loading @@ -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; Loading @@ -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; Loading Loading @@ -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"); act = calloc(1, sizeof(*act)); 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; } act = calloc(1, sizeof(*act)); act->name = args[1]; 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); Loading
init/parser.c +7 −2 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ void DUMP(void) struct command *cmd; struct listnode *node; struct listnode *node2; char name_str[256] = ""; struct socketinfo *si; int n; Loading @@ -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); Loading
init/readme.txt +9 −0 Original line number Diff line number Diff line Loading @@ -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 -------- Loading