From 54108c71df643b35a5684e9bce4551543f63ddc4 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Fri, 8 Mar 2013 23:49:24 +0100 Subject: fix hotplug --- hotplug-rule.c | 519 --------------------------------------------------------- 1 file changed, 519 deletions(-) delete mode 100644 hotplug-rule.c (limited to 'hotplug-rule.c') diff --git a/hotplug-rule.c b/hotplug-rule.c deleted file mode 100644 index 1f3189d..0000000 --- a/hotplug-rule.c +++ /dev/null @@ -1,519 +0,0 @@ -#include - -#include -#include - -#include -#include -#include - -#include "hotplug.h" - -static struct blob_buf b; - -static int rule_process_expr(struct blob_attr *cur, struct blob_attr *msg); -static int rule_process_cmd(struct blob_attr *cur, struct blob_attr *msg); - -static char *__msg_find_var(struct blob_attr *msg, const char *name) -{ - struct blob_attr *cur; - int rem; - - blob_for_each_attr(cur, msg, rem) { - if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING) - continue; - - if (strcmp(blobmsg_name(cur), name) != 0) - continue; - - return blobmsg_data(cur); - } - - return NULL; -} - -static char *msg_find_var(struct blob_attr *msg, const char *name) -{ - char *str; - - if (!strcmp(name, "DEVICENAME") || !strcmp(name, "DEVNAME")) { - str = __msg_find_var(msg, "DEVPATH"); - if (!str) - return NULL; - - return basename(str); - } - - return __msg_find_var(msg, name); -} - -static void -rule_get_tuple(struct blob_attr *cur, struct blob_attr **tb, int t1, int t2) -{ - static struct blobmsg_policy expr_tuple[3] = { - { .type = BLOBMSG_TYPE_STRING }, - {}, - {}, - }; - - expr_tuple[1].type = t1; - expr_tuple[2].type = t2; - blobmsg_parse_array(expr_tuple, 3, tb, blobmsg_data(cur), blobmsg_data_len(cur)); -} - -static int handle_if(struct blob_attr *expr, struct blob_attr *msg) -{ - struct blob_attr *tb[4]; - int ret; - - static const struct blobmsg_policy if_tuple[4] = { - { .type = BLOBMSG_TYPE_STRING }, - { .type = BLOBMSG_TYPE_ARRAY }, - { .type = BLOBMSG_TYPE_ARRAY }, - { .type = BLOBMSG_TYPE_ARRAY }, - }; - - blobmsg_parse_array(if_tuple, 4, tb, blobmsg_data(expr), blobmsg_data_len(expr)); - - if (!tb[1] || !tb[2]) - return 0; - - ret = rule_process_expr(tb[1], msg); - if (ret < 0) - return 0; - - if (ret) - return rule_process_cmd(tb[2], msg); - - if (!tb[3]) - return 0; - - return rule_process_cmd(tb[3], msg); -} - -static int handle_case(struct blob_attr *expr, struct blob_attr *msg) -{ - struct blob_attr *tb[3], *cur; - const char *var; - int rem; - - rule_get_tuple(expr, tb, BLOBMSG_TYPE_STRING, BLOBMSG_TYPE_TABLE); - if (!tb[1] || !tb[2]) - return 0; - - var = msg_find_var(msg, blobmsg_data(tb[1])); - if (!var) - return 0; - - blobmsg_for_each_attr(cur, tb[2], rem) { - if (!strcmp(var, blobmsg_name(cur))) - return rule_process_cmd(cur, msg); - } - - return 0; -} - -static int handle_return(struct blob_attr *expr, struct blob_attr *msg) -{ - return -2; -} - -static int handle_include(struct blob_attr *expr, struct blob_attr *msg) -{ - struct blob_attr *tb[3]; - struct rule_file *r; - - rule_get_tuple(expr, tb, BLOBMSG_TYPE_STRING, 0); - if (!tb[1]) - return 0; - - r = rule_file_get(blobmsg_data(tb[1])); - if (!r) - return 0; - - return rule_process_cmd(r->data, msg); -} - -static const struct rule_handler cmd[] = { - { "if", handle_if }, - { "case", handle_case }, - { "return", handle_return }, - { "include", handle_include }, -}; - -static int eq_regex_cmp(const char *str, const char *pattern, bool regex) -{ - regex_t reg; - int ret; - - if (!regex) - return !strcmp(str, pattern); - - if (regcomp(®, pattern, REG_EXTENDED | REG_NOSUB)) - return 0; - - ret = !regexec(®, str, 0, NULL, 0); - regfree(®); - - return ret; -} - -static int expr_eq_regex(struct blob_attr *expr, struct blob_attr *msg, bool regex) -{ - struct blob_attr *tb[3], *cur; - const char *var; - int rem; - - rule_get_tuple(expr, tb, BLOBMSG_TYPE_STRING, 0); - if (!tb[1] || !tb[2]) - return -1; - - var = msg_find_var(msg, blobmsg_data(tb[1])); - if (!var) - return 0; - - switch(blobmsg_type(tb[2])) { - case BLOBMSG_TYPE_STRING: - return eq_regex_cmp(var, blobmsg_data(tb[2]), regex); - case BLOBMSG_TYPE_ARRAY: - blobmsg_for_each_attr(cur, tb[2], rem) { - if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING) { - rule_error(cur, "Unexpected element type"); - return -1; - } - - if (eq_regex_cmp(var, blobmsg_data(cur), regex)) - return 1; - } - return 0; - default: - rule_error(tb[2], "Unexpected element type"); - return -1; - } -} - -static int handle_expr_eq(struct blob_attr *expr, struct blob_attr *msg) -{ - return expr_eq_regex(expr, msg, false); -} - -static int handle_expr_regex(struct blob_attr *expr, struct blob_attr *msg) -{ - return expr_eq_regex(expr, msg, true); -} - -static int handle_expr_has(struct blob_attr *expr, struct blob_attr *msg) -{ - struct blob_attr *tb[3], *cur; - int rem; - - rule_get_tuple(expr, tb, 0, 0); - if (!tb[1]) - return -1; - - switch(blobmsg_type(tb[1])) { - case BLOBMSG_TYPE_STRING: - return !!msg_find_var(msg, blobmsg_data(tb[1])); - case BLOBMSG_TYPE_ARRAY: - blobmsg_for_each_attr(cur, tb[1], rem) { - if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING) { - rule_error(cur, "Unexpected element type"); - return -1; - } - - if (msg_find_var(msg, blobmsg_data(cur))) - return 1; - } - return 0; - default: - rule_error(tb[1], "Unexpected element type"); - return -1; - } -} - -static int expr_and_or(struct blob_attr *expr, struct blob_attr *msg, bool and) -{ - struct blob_attr *cur; - int ret, rem; - int i = 0; - - blobmsg_for_each_attr(cur, expr, rem) { - if (i++ < 1) - continue; - - ret = rule_process_expr(cur, msg); - if (ret < 0) - return ret; - - if (ret != and) - return ret; - } - - return and; -} - -static int handle_expr_and(struct blob_attr *expr, struct blob_attr *msg) -{ - return expr_and_or(expr, msg, 1); -} - -static int handle_expr_or(struct blob_attr *expr, struct blob_attr *msg) -{ - return expr_and_or(expr, msg, 0); -} - -static int handle_expr_not(struct blob_attr *expr, struct blob_attr *msg) -{ - struct blob_attr *tb[3]; - - rule_get_tuple(expr, tb, BLOBMSG_TYPE_ARRAY, 0); - if (!tb[1]) - return -1; - - return rule_process_expr(tb[1], msg); -} - -static const struct rule_handler expr[] = { - { "eq", handle_expr_eq }, - { "regex", handle_expr_regex }, - { "has", handle_expr_has }, - { "and", handle_expr_and }, - { "or", handle_expr_or }, - { "not", handle_expr_not }, -}; - -static int -__rule_process_type(struct blob_attr *cur, struct blob_attr *msg, - const struct rule_handler *h, int n, bool *found) -{ - const char *name = blobmsg_data(blobmsg_data(cur)); - int i; - - for (i = 0; i < n; i++) { - if (strcmp(name, h[i].name) != 0) - continue; - - *found = true; - return h[i].handler(cur, msg); - } - - *found = false; - return -1; -} - -static int rule_process_expr(struct blob_attr *cur, struct blob_attr *msg) -{ - bool found; - int ret; - - if (blobmsg_type(cur) != BLOBMSG_TYPE_ARRAY || - blobmsg_type(blobmsg_data(cur)) != BLOBMSG_TYPE_STRING) { - rule_error(cur, "Unexpected element type"); - return -1; - } - - ret = __rule_process_type(cur, msg, expr, ARRAY_SIZE(expr), &found); - if (!found) - rule_error(cur, "Unknown expression type"); - - return ret; -} - -static void cmd_add_string(const char *pattern, struct blob_attr *msg) -{ - char *dest, *next, *str; - int len = 0; - bool var = false; - - dest = blobmsg_alloc_string_buffer(&b, NULL, 1); - str = alloca(strlen(pattern) + 1); - strcpy(str, pattern); - next = str; - - while (*str) { - const char *cur; - int cur_len = 0; - - next = strchr(str, '%'); - if (!next) - next = str + strlen(str); - - if (var) { - if (next > str) { - *next = 0; - cur = msg_find_var(msg, str); - if (cur) - cur_len = strlen(cur); - } else { - cur = str - 1; - cur_len = 1; - } - } else { - cur = str; - cur_len = next - str; - } - - if (cur_len) { - dest = blobmsg_realloc_string_buffer(&b, cur_len + 1); - memcpy(dest + len, cur, cur_len); - len += cur_len; - } - - var = !var; - str = next + 1; - } - - dest[len] = 0; - blobmsg_add_string_buffer(&b); -} - -static int cmd_process_strings(struct blob_attr *attr, struct blob_attr *msg) -{ - struct blob_attr *cur; - int args = -1; - int rem; - void *c; - - blob_buf_init(&b, 0); - c = blobmsg_open_array(&b, NULL); - blobmsg_for_each_attr(cur, attr, rem) { - if (args++ < 0) - continue; - - if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING) { - rule_error(attr, "Invalid argument in command"); - return -1; - } - - cmd_add_string(blobmsg_data(cur), msg); - } - - blobmsg_close_array(&b, c); - - return 0; -} - -static int __rule_process_cmd(struct blob_attr *cur, struct blob_attr *msg) -{ - const char *name; - bool found; - int ret; - - if (blobmsg_type(cur) != BLOBMSG_TYPE_ARRAY || - blobmsg_type(blobmsg_data(cur)) != BLOBMSG_TYPE_STRING) { - rule_error(cur, "Unexpected element type"); - return -1; - } - - ret = __rule_process_type(cur, msg, cmd, ARRAY_SIZE(cmd), &found); - if (found) - return ret; - - name = blobmsg_data(blobmsg_data(cur)); - ret = cmd_process_strings(cur, msg); - if (ret) - return ret; - - rule_handle_command(name, blob_data(b.head)); - - return 0; -} - -static int rule_process_cmd(struct blob_attr *block, struct blob_attr *msg) -{ - struct blob_attr *cur; - int rem; - int ret; - int i = 0; - - if (blobmsg_type(block) != BLOBMSG_TYPE_ARRAY) { - rule_error(block, "Unexpected element type"); - return -1; - } - - blobmsg_for_each_attr(cur, block, rem) { - switch(blobmsg_type(cur)) { - case BLOBMSG_TYPE_STRING: - if (!i) - return __rule_process_cmd(block, msg); - default: - ret = rule_process_cmd(cur, msg); - if (ret < -1) - return ret; - break; - } - i++; - } - - return 0; -} - -void rule_process_msg(struct rule_file *f, struct blob_attr *msg) -{ - rule_process_cmd(f->data, msg); -} - -static struct rule_file * -rule_file_load(const char *filename) -{ - struct rule_file *r; - struct stat st; - - json_object *obj = NULL; - - blob_buf_init(&b, 0); - - if (stat(filename, &st)) - return NULL; - - obj = json_object_from_file((char *) filename); - if (is_error(obj)) - return NULL; - - if (!json_object_is_type(obj, json_type_array)) { - json_object_put(obj); - return NULL; - } - - blobmsg_add_json_element(&b, filename, obj); - json_object_put(obj); - - r = calloc(1, sizeof(*r) + blob_len(b.head)); - memcpy(r->data, blob_data(b.head), blob_len(b.head)); - r->avl.key = blobmsg_name(r->data); - - return r; -} - -static struct avl_tree rule_files; - -struct rule_file * -rule_file_get(const char *filename) -{ - struct rule_file *r; - - if (!rule_files.comp) - avl_init(&rule_files, avl_strcmp, false, NULL); - - r = avl_find_element(&rule_files, filename, r, avl); - if (r) - return r; - - r = rule_file_load(filename); - if (!r) - return NULL; - - avl_insert(&rule_files, &r->avl); - return r; -} - -void -rule_file_free_all(void) -{ - struct rule_file *r, *next; - - avl_remove_all_elements(&rule_files, r, avl, next) - free(r); - - blob_buf_free(&b); -} -- cgit v1.2.3