static int rules_parse(JsonNode *root) { int have_error = 0, match = 0, x = 0; unsigned int i = 0; struct JsonNode *jrules = NULL; char *rule = NULL; double active = 1.0; if(root->tag == JSON_OBJECT) { jrules = json_first_child(root); while(jrules) { i++; if(jrules->tag == JSON_OBJECT) { if(json_find_string(jrules, "rule", &rule) != 0) { logprintf(LOG_ERR, "config rule #%d \"%s\", missing \"rule\"", i, jrules->key); have_error = 1; break; } else { active = 1.0; json_find_number(jrules, "active", &active); struct rules_t *tmp = rules; match = 0; while(tmp) { if(strcmp(tmp->name, jrules->key) == 0) { match = 1; break; } tmp = tmp->next; } if(match == 1) { logprintf(LOG_ERR, "config rule #%d \"%s\" already exists", i, jrules->key); have_error = 1; break; } for(x=0;x<strlen(jrules->key);x++) { if(!isalnum(jrules->key[x]) && jrules->key[x] != '-' && jrules->key[x] != '_') { logprintf(LOG_ERR, "config rule #%d \"%s\", not alphanumeric", i, jrules->key); have_error = 1; break; } } struct rules_t *node = MALLOC(sizeof(struct rules_t)); if(node == NULL) { fprintf(stderr, "out of memory\n"); exit(EXIT_FAILURE); } node->next = NULL; node->values = NULL; node->nrdevices = 0; node->status = 0; node->devices = NULL; node->actions = NULL; node->nr = i; if((node->name = MALLOC(strlen(jrules->key)+1)) == NULL) { fprintf(stderr, "out of memory\n"); exit(EXIT_FAILURE); } strcpy(node->name, jrules->key); clock_gettime(CLOCK_MONOTONIC, &node->timestamp.first); if(event_parse_rule(rule, node, 0, 1) == -1) { have_error = 1; } clock_gettime(CLOCK_MONOTONIC, &node->timestamp.second); logprintf(LOG_INFO, "rule #%d %s was parsed in %.6f seconds", node->nr, node->name, ((double)node->timestamp.second.tv_sec + 1.0e-9*node->timestamp.second.tv_nsec) - ((double)node->timestamp.first.tv_sec + 1.0e-9*node->timestamp.first.tv_nsec)); node->status = 0; if((node->rule = MALLOC(strlen(rule)+1)) == NULL) { fprintf(stderr, "out of memory\n"); exit(EXIT_FAILURE); } strcpy(node->rule, rule); node->active = (unsigned short)active; tmp = rules; if(tmp) { while(tmp->next != NULL) { tmp = tmp->next; } tmp->next = node; } else { node->next = rules; rules = node; } /* * In case of an error, we do want to * save a pointer to our faulty rule * so it can be properly garbage collected. */ if(have_error == 1) { break; } } } jrules = jrules->next; } } else { logprintf(LOG_ERR, "config rules should be placed in an object"); have_error = 1; } return have_error; }
static int rules_parse(JsonNode *root) { int have_error = 0, match = 0; unsigned int i = 0; struct JsonNode *jrules = NULL; char *rule = NULL; double active = 1.0; if(root->tag == JSON_OBJECT) { jrules = json_first_child(root); while(jrules) { i++; if(jrules->tag == JSON_OBJECT) { if(json_find_string(jrules, "rule", &rule) != 0) { logprintf(LOG_ERR, "config rules #%d \"%s\", missing \"rule\"", i, jrules->key); have_error = 1; break; } else { active = 1.0; json_find_number(jrules, "active", &active); struct rules_t *tmp = rules; match = 0; while(tmp) { if(strcmp(tmp->name, jrules->key) == 0) { match = 1; break; } tmp = tmp->next; } if(match == 1) { logprintf(LOG_ERR, "config rules #%d \"%s\" already exists", i, jrules->key); have_error = 1; break; } struct rules_t *node = MALLOC(sizeof(struct rules_t)); if(node == NULL) { logprintf(LOG_ERR, "out of memory"); exit(EXIT_FAILURE); } node->next = NULL; node->values = NULL; node->nrdevices = 0; node->status = 0; node->devices = NULL; node->action = NULL; node->arguments = NULL; if(event_parse_rule(rule, node, 0, i, 1) == -1) { for(i=0;i<node->nrdevices;i++) { FREE(node->devices[i]); } if(node->devices != NULL) { FREE(node->devices); } FREE(node); have_error = 1; break; } node->status = 0; node->rule = MALLOC(strlen(rule)+1); if(node->rule == NULL) { logprintf(LOG_ERR, "out of memory"); exit(EXIT_FAILURE); } strcpy(node->rule, rule); node->name = MALLOC(strlen(jrules->key)+1); if(node->name == NULL) { logprintf(LOG_ERR, "out of memory"); exit(EXIT_FAILURE); } strcpy(node->name, jrules->key); node->active = (unsigned short)active; tmp = rules; if(tmp) { while(tmp->next != NULL) { tmp = tmp->next; } tmp->next = node; } else { node->next = rules; rules = node; } } } jrules = jrules->next; } } else { logprintf(LOG_ERR, "config rules should be placed in an object"); have_error = 1; } return have_error; }
void *events_loop(void *param) { logprintf(LOG_STACK, "%s(...)", __FUNCTION__); pthread_mutexattr_init(&events_attr); pthread_mutexattr_settype(&events_attr, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&events_lock, &events_attr); pthread_cond_init(&events_signal, NULL); struct JsonNode *jdevices = NULL, *jchilds = NULL; struct rules_t *tmp_rules = NULL; char *str = NULL; unsigned short match = 0; unsigned int i = 0; pthread_mutex_lock(&events_lock); while(loop) { if(eventsqueue_number > 0) { pthread_mutex_lock(&events_lock); logprintf(LOG_STACK, "%s::unlocked", __FUNCTION__); running = 1; jdevices = json_find_member(eventsqueue->jconfig, "devices"); tmp_rules = rules_get(); while(tmp_rules) { if(tmp_rules->active == 1) { match = 0; if((str = MALLOC(strlen(tmp_rules->rule)+1)) == NULL) { logprintf(LOG_ERR, "out of memory"); exit(EXIT_FAILURE); } strcpy(str, tmp_rules->rule); /* Only run those events that affect the updates devices */ if(jdevices != NULL) { jchilds = json_first_child(jdevices); while(jchilds) { for(i=0;i<tmp_rules->nrdevices;i++) { if(jchilds->tag == JSON_STRING && strcmp(jchilds->string_, tmp_rules->devices[i]) == 0) { match = 1; break; } } if(match == 1) { break; } jchilds = jchilds->next; } } if(match == 1 && tmp_rules->status == 0) { if(event_parse_rule(str, tmp_rules, 0, 1, 0) == 0) { if(tmp_rules->status) { logprintf(LOG_INFO, "executed rule: %s", tmp_rules->name); } } tmp_rules->status = 0; } FREE(str); } tmp_rules = tmp_rules->next; } struct eventsqueue_t *tmp = eventsqueue; json_delete(tmp->jconfig); eventsqueue = eventsqueue->next; FREE(tmp); eventsqueue_number--; running = 0; pthread_mutex_unlock(&events_lock); } else { pthread_cond_wait(&events_signal, &events_lock); } } return (void *)NULL; }