void free_commands(struct run_event_state *state) { free_rule_list(state->rule_list); state->rule_list = NULL; state->command_out_fd = -1; state->command_pid = 0; }
void free_nt_list() { non_terminal_t *temp = non_terminals; while (temp != NULL) { free_rule_list(temp->rules); non_terminal_t *old = temp; temp = temp->next; free(old); } }
char *list_possible_events(struct dump_dir *dd, const char *dump_dir_name, const char *pfx) { struct strbuf *result = strbuf_new(); GList *rule_list = load_rule_list(NULL, CONF_DIR"/report_event.conf", /*recursion_depth:*/ 0); unsigned pfx_len = strlen(pfx); for (;;) { /* Retrieve each cmd, and fetch its EVENT=foo value */ char *event_name = NULL; char *cmd = pop_next_command(&rule_list, &event_name, /* return event_name */ (dd ? &dd : NULL), /* match this dd... */ dump_dir_name, /* ...or if NULL, this dirname */ pfx, pfx_len /* for events with this prefix */ ); if (!cmd) { free_rule_list(rule_list); free(event_name); break; } free(cmd); if (event_name) { /* Append "EVENT\n" - only if it is not there yet */ unsigned e_len = strlen(event_name); char *p = result->buf; while (p && *p) { if (strncmp(p, event_name, e_len) == 0 && p[e_len] == '\n') goto skip; /* This event is already in the result */ p = strchr(p, '\n'); if (p) p++; } strbuf_append_strf(result, "%s\n", event_name); skip: free(event_name); } } return strbuf_free_nobuf(result); }
/* Checks rules in *pp_rule_list, starting from first (remaining) rule, * until it finds a rule with all conditions satisfied. * In this case, it deletes this rule and returns this rule's cmd. * Else (if it didn't find such rule), it returns NULL. * In case of error (dump_dir can't be opened), returns NULL. * * Intended usage: * list = load_rule_list(...); * while ((cmd = pop_next_command(&list, ...)) != NULL) * run(cmd); */ static char* pop_next_command(GList **pp_rule_list, char **pp_event_name, /* reports EVENT value thru this, if not NULL on entry */ struct dump_dir **pp_dd, /* use *pp_dd for access to dump dir, if non-NULL */ const char *dump_dir_name, const char *pfx, unsigned pfx_len ) { char *command = NULL; struct dump_dir *dd = pp_dd ? *pp_dd : NULL; GList *rule_list = *pp_rule_list; while (rule_list) { struct rule *cur_rule = rule_list->data; GList *condition = cur_rule->conditions; while (condition) { const char *cond_str = condition->data; const char *eq_sign = strchr(cond_str, '='); /* Is it "EVENT=foo"? */ if (strncmp(cond_str, "EVENT=", 6) == 0) { if (strncmp(eq_sign + 1, pfx, pfx_len) != 0) goto next_rule; /* prefix doesn't match */ if (pp_event_name) { free(*pp_event_name); *pp_event_name = xstrdup(eq_sign + 1); } } else { /* Read from dump dir and compare */ if (!dd) { /* Without dir to match, we assume match for all conditions */ if (!dump_dir_name) goto next_cond; dd = dd_opendir(dump_dir_name, /*flags:*/ DD_OPEN_READONLY); if (!dd) { free_rule_list(rule_list); *pp_rule_list = NULL; goto ret; /* error (note: dd_opendir logged error msg) */ } } /* Is it "VAR~=REGEX"? */ int regex = (eq_sign > cond_str && eq_sign[-1] == '~'); /* Is it "VAR!=VAL"? */ int inverted = (eq_sign > cond_str && eq_sign[-1] == '!'); char *var_name = xstrndup(cond_str, eq_sign - cond_str - (regex|inverted)); char *real_val = dd_load_text_ext(dd, var_name, DD_FAIL_QUIETLY_ENOENT); free(var_name); int vals_differ = regex ? regcmp_lines(real_val, eq_sign + 1) : strcmp(real_val, eq_sign + 1); free(real_val); if (inverted) vals_differ = !vals_differ; /* Do values match? */ if (vals_differ) /* no */ { //log_debug("var '%s': '%.*s'!='%s', skipping line", // p, // (int)(strchrnul(real_val, '\n') - real_val), real_val, // eq_sign); goto next_rule; } } next_cond: /* We are here if current condition is satisfied */ condition = condition->next; } /* while (condition) */ /* We are here if all conditions are satisfied */ /* IOW, we found rule to run, delete it and return its command */ *pp_rule_list = g_list_remove(*pp_rule_list, cur_rule); list_free_with_free(cur_rule->conditions); command = cur_rule->command; /*free(cur_rule->command); - WRONG! we are returning it! */ free(cur_rule); break; next_rule: rule_list = rule_list->next; } /* while (rule_list) */ ret: if (pp_dd) *pp_dd = dd; else dd_close(dd); return command; }