index = pevent_get_input_buf_ptr();
len = input ? strlen(input) : 0;
- error = malloc_or_die(MAX_ERR_STR_SIZE + (len*2) + 3);
+ error = malloc(MAX_ERR_STR_SIZE + (len*2) + 3);
+ if (error == NULL) {
+ /*
+ * Maybe it's due to len is too long.
+ * Retry without the input buffer part.
+ */
+ len = 0;
+
+ error = malloc(MAX_ERR_STR_SIZE);
+ if (error == NULL) {
+ /* no memory */
+ *error_str = NULL;
+ return;
+ }
+ }
if (len) {
strcpy(error, input);
(strcmp(token, "=") == 0 || strcmp(token, "!") == 0) &&
pevent_peek_char() == '~') {
/* append it */
- *tok = malloc_or_die(3);
+ *tok = malloc(3);
+ if (*tok == NULL) {
+ free_token(token);
+ return EVENT_ERROR;
+ }
sprintf(*tok, "%c%c", *token, '~');
free_token(token);
/* Now remove the '~' from the buffer */
if (filter_type)
return filter_type;
- filter->event_filters = realloc(filter->event_filters,
- sizeof(*filter->event_filters) *
- (filter->filters + 1));
- if (!filter->event_filters)
- die("Could not allocate filter");
+ filter_type = realloc(filter->event_filters,
+ sizeof(*filter->event_filters) *
+ (filter->filters + 1));
+ if (!filter_type)
+ return NULL;
+
+ filter->event_filters = filter_type;
for (i = 0; i < filter->filters; i++) {
if (filter->event_filters[i].event_id > id)
{
struct event_filter *filter;
- filter = malloc_or_die(sizeof(*filter));
+ filter = malloc(sizeof(*filter));
+ if (filter == NULL)
+ return NULL;
+
memset(filter, 0, sizeof(*filter));
filter->pevent = pevent;
pevent_ref(pevent);
static struct filter_arg *allocate_arg(void)
{
- struct filter_arg *arg;
-
- arg = malloc_or_die(sizeof(*arg));
- memset(arg, 0, sizeof(*arg));
-
- return arg;
+ return calloc(1, sizeof(struct filter_arg));
}
static void free_arg(struct filter_arg *arg)
free(arg);
}
-static void add_event(struct event_list **events,
+static int add_event(struct event_list **events,
struct event_format *event)
{
struct event_list *list;
- list = malloc_or_die(sizeof(*list));
+ list = malloc(sizeof(*list));
+ if (list == NULL)
+ return -1;
+
list->next = *events;
*events = list;
list->event = event;
+ return 0;
}
static int event_match(struct event_format *event,
!regexec(ereg, event->name, 0, NULL, 0);
}
-static int
+static enum pevent_errno
find_event(struct pevent *pevent, struct event_list **events,
char *sys_name, char *event_name)
{
regex_t ereg;
regex_t sreg;
int match = 0;
+ int fail = 0;
char *reg;
int ret;
int i;
sys_name = NULL;
}
- reg = malloc_or_die(strlen(event_name) + 3);
+ reg = malloc(strlen(event_name) + 3);
+ if (reg == NULL)
+ return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+
sprintf(reg, "^%s$", event_name);
ret = regcomp(&ereg, reg, REG_ICASE|REG_NOSUB);
free(reg);
if (ret)
- return -1;
+ return PEVENT_ERRNO__INVALID_EVENT_NAME;
if (sys_name) {
- reg = malloc_or_die(strlen(sys_name) + 3);
+ reg = malloc(strlen(sys_name) + 3);
+ if (reg == NULL) {
+ regfree(&ereg);
+ return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+ }
+
sprintf(reg, "^%s$", sys_name);
ret = regcomp(&sreg, reg, REG_ICASE|REG_NOSUB);
free(reg);
if (ret) {
regfree(&ereg);
- return -1;
+ return PEVENT_ERRNO__INVALID_EVENT_NAME;
}
}
event = pevent->events[i];
if (event_match(event, sys_name ? &sreg : NULL, &ereg)) {
match = 1;
- add_event(events, event);
+ if (add_event(events, event) < 0) {
+ fail = 1;
+ break;
+ }
}
}
regfree(&sreg);
if (!match)
- return -1;
+ return PEVENT_ERRNO__EVENT_NOT_FOUND;
+ if (fail)
+ return PEVENT_ERRNO__MEM_ALLOC_FAILED;
return 0;
}
struct filter_arg *arg;
arg = allocate_arg();
+ if (arg == NULL) {
+ show_error(error_str, "failed to allocate filter arg");
+ return NULL;
+ }
switch (type) {
arg->value.type =
type == EVENT_DQUOTE ? FILTER_STRING : FILTER_CHAR;
arg->value.str = strdup(token);
- if (!arg->value.str)
- die("malloc string");
+ if (!arg->value.str) {
+ free_arg(arg);
+ show_error(error_str, "failed to allocate string filter arg");
+ return NULL;
+ }
break;
case EVENT_ITEM:
/* if it is a number, then convert it */
struct filter_arg *arg;
arg = allocate_arg();
+ if (!arg)
+ return NULL;
+
arg->type = FILTER_ARG_OP;
arg->op.type = btype;
struct filter_arg *arg;
arg = allocate_arg();
+ if (!arg)
+ return NULL;
+
arg->type = FILTER_ARG_EXP;
arg->op.type = etype;
struct filter_arg *arg;
arg = allocate_arg();
+ if (!arg)
+ return NULL;
+
/* Use NUM and change if necessary */
arg->type = FILTER_ARG_NUM;
arg->op.type = etype;
return arg;
}
-static int add_right(struct filter_arg *op, struct filter_arg *arg,
- char **error_str)
+static enum pevent_errno
+add_right(struct filter_arg *op, struct filter_arg *arg, char **error_str)
{
struct filter_arg *left;
char *str;
case FILTER_ARG_FIELD:
break;
default:
- show_error(error_str,
- "Illegal rvalue");
- return -1;
+ show_error(error_str, "Illegal rvalue");
+ return PEVENT_ERRNO__ILLEGAL_RVALUE;
}
/*
if (left->type != FILTER_ARG_FIELD) {
show_error(error_str,
"Illegal lvalue for string comparison");
- return -1;
+ return PEVENT_ERRNO__ILLEGAL_LVALUE;
}
/* Make sure this is a valid string compare */
show_error(error_str,
"RegEx '%s' did not compute",
str);
- return -1;
+ return PEVENT_ERRNO__INVALID_REGEX;
}
break;
default:
show_error(error_str,
"Illegal comparison for string");
- return -1;
+ return PEVENT_ERRNO__ILLEGAL_STRING_CMP;
}
op->type = FILTER_ARG_STR;
op->str.type = op_type;
op->str.field = left->field.field;
op->str.val = strdup(str);
- if (!op->str.val)
- die("malloc string");
+ if (!op->str.val) {
+ show_error(error_str, "Failed to allocate string filter");
+ return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+ }
/*
* Need a buffer to copy data for tests
*/
- op->str.buffer = malloc_or_die(op->str.field->size + 1);
+ op->str.buffer = malloc(op->str.field->size + 1);
+ if (!op->str.buffer) {
+ show_error(error_str, "Failed to allocate string filter");
+ return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+ }
/* Null terminate this buffer */
op->str.buffer[op->str.field->size] = 0;
case FILTER_CMP_NOT_REGEX:
show_error(error_str,
"Op not allowed with integers");
- return -1;
+ return PEVENT_ERRNO__ILLEGAL_INTEGER_CMP;
default:
break;
return 0;
out_fail:
- show_error(error_str,
- "Syntax error");
- return -1;
+ show_error(error_str, "Syntax error");
+ return PEVENT_ERRNO__SYNTAX_ERROR;
}
static struct filter_arg *
return arg;
}
-static int add_left(struct filter_arg *op, struct filter_arg *arg)
+static enum pevent_errno add_left(struct filter_arg *op, struct filter_arg *arg)
{
switch (op->type) {
case FILTER_ARG_EXP:
/* left arg of compares must be a field */
if (arg->type != FILTER_ARG_FIELD &&
arg->type != FILTER_ARG_BOOLEAN)
- return -1;
+ return PEVENT_ERRNO__INVALID_ARG_TYPE;
op->num.left = arg;
break;
default:
- return -1;
+ return PEVENT_ERRNO__INVALID_ARG_TYPE;
}
return 0;
}
FILTER_VAL_TRUE,
};
-void reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child,
- struct filter_arg *arg)
+static enum pevent_errno
+reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child,
+ struct filter_arg *arg, char **error_str)
{
struct filter_arg *other_child;
struct filter_arg **ptr;
if (parent->type != FILTER_ARG_OP &&
- arg->type != FILTER_ARG_OP)
- die("can not reparent other than OP");
+ arg->type != FILTER_ARG_OP) {
+ show_error(error_str, "can not reparent other than OP");
+ return PEVENT_ERRNO__REPARENT_NOT_OP;
+ }
/* Get the sibling */
if (old_child->op.right == arg) {
} else if (old_child->op.left == arg) {
ptr = &old_child->op.left;
other_child = old_child->op.right;
- } else
- die("Error in reparent op, find other child");
+ } else {
+ show_error(error_str, "Error in reparent op, find other child");
+ return PEVENT_ERRNO__REPARENT_FAILED;
+ }
/* Detach arg from old_child */
*ptr = NULL;
*parent = *arg;
/* Free arg without recussion */
free(arg);
- return;
+ return 0;
}
if (parent->op.right == old_child)
ptr = &parent->op.right;
else if (parent->op.left == old_child)
ptr = &parent->op.left;
- else
- die("Error in reparent op");
+ else {
+ show_error(error_str, "Error in reparent op");
+ return PEVENT_ERRNO__REPARENT_FAILED;
+ }
+
*ptr = arg;
free_arg(old_child);
+ return 0;
}
-enum filter_vals test_arg(struct filter_arg *parent, struct filter_arg *arg)
+/* Returns either filter_vals (success) or pevent_errno (failfure) */
+static int test_arg(struct filter_arg *parent, struct filter_arg *arg,
+ char **error_str)
{
- enum filter_vals lval, rval;
+ int lval, rval;
switch (arg->type) {
return FILTER_VAL_NORM;
case FILTER_ARG_EXP:
- lval = test_arg(arg, arg->exp.left);
+ lval = test_arg(arg, arg->exp.left, error_str);
if (lval != FILTER_VAL_NORM)
return lval;
- rval = test_arg(arg, arg->exp.right);
+ rval = test_arg(arg, arg->exp.right, error_str);
if (rval != FILTER_VAL_NORM)
return rval;
return FILTER_VAL_NORM;
case FILTER_ARG_NUM:
- lval = test_arg(arg, arg->num.left);
+ lval = test_arg(arg, arg->num.left, error_str);
if (lval != FILTER_VAL_NORM)
return lval;
- rval = test_arg(arg, arg->num.right);
+ rval = test_arg(arg, arg->num.right, error_str);
if (rval != FILTER_VAL_NORM)
return rval;
return FILTER_VAL_NORM;
case FILTER_ARG_OP:
if (arg->op.type != FILTER_OP_NOT) {
- lval = test_arg(arg, arg->op.left);
+ lval = test_arg(arg, arg->op.left, error_str);
switch (lval) {
case FILTER_VAL_NORM:
break;
case FILTER_VAL_TRUE:
if (arg->op.type == FILTER_OP_OR)
return FILTER_VAL_TRUE;
- rval = test_arg(arg, arg->op.right);
+ rval = test_arg(arg, arg->op.right, error_str);
if (rval != FILTER_VAL_NORM)
return rval;
- reparent_op_arg(parent, arg, arg->op.right);
- return FILTER_VAL_NORM;
+ return reparent_op_arg(parent, arg, arg->op.right,
+ error_str);
case FILTER_VAL_FALSE:
if (arg->op.type == FILTER_OP_AND)
return FILTER_VAL_FALSE;
- rval = test_arg(arg, arg->op.right);
+ rval = test_arg(arg, arg->op.right, error_str);
if (rval != FILTER_VAL_NORM)
return rval;
- reparent_op_arg(parent, arg, arg->op.right);
- return FILTER_VAL_NORM;
+ return reparent_op_arg(parent, arg, arg->op.right,
+ error_str);
+
+ default:
+ return lval;
}
}
- rval = test_arg(arg, arg->op.right);
+ rval = test_arg(arg, arg->op.right, error_str);
switch (rval) {
case FILTER_VAL_NORM:
+ default:
break;
+
case FILTER_VAL_TRUE:
if (arg->op.type == FILTER_OP_OR)
return FILTER_VAL_TRUE;
if (arg->op.type == FILTER_OP_NOT)
return FILTER_VAL_FALSE;
- reparent_op_arg(parent, arg, arg->op.left);
- return FILTER_VAL_NORM;
+ return reparent_op_arg(parent, arg, arg->op.left,
+ error_str);
case FILTER_VAL_FALSE:
if (arg->op.type == FILTER_OP_AND)
if (arg->op.type == FILTER_OP_NOT)
return FILTER_VAL_TRUE;
- reparent_op_arg(parent, arg, arg->op.left);
- return FILTER_VAL_NORM;
+ return reparent_op_arg(parent, arg, arg->op.left,
+ error_str);
}
- return FILTER_VAL_NORM;
+ return rval;
default:
- die("bad arg in filter tree");
+ show_error(error_str, "bad arg in filter tree");
+ return PEVENT_ERRNO__BAD_FILTER_ARG;
}
return FILTER_VAL_NORM;
}
/* Remove any unknown event fields */
-static struct filter_arg *collapse_tree(struct filter_arg *arg)
+static struct filter_arg *collapse_tree(struct filter_arg *arg, char **error_str)
{
enum filter_vals ret;
- ret = test_arg(arg, arg);
+ ret = test_arg(arg, arg, error_str);
switch (ret) {
case FILTER_VAL_NORM:
- return arg;
+ break;
case FILTER_VAL_TRUE:
case FILTER_VAL_FALSE:
free_arg(arg);
arg = allocate_arg();
- arg->type = FILTER_ARG_BOOLEAN;
- arg->boolean.value = ret == FILTER_VAL_TRUE;
+ if (arg) {
+ arg->type = FILTER_ARG_BOOLEAN;
+ arg->boolean.value = ret == FILTER_VAL_TRUE;
+ } else {
+ show_error(error_str, "Failed to allocate filter arg");
+ }
+ break;
+
+ default:
+ /* test_arg() already set the error_str */
+ free_arg(arg);
+ arg = NULL;
+ break;
}
return arg;
switch (op_type) {
case OP_BOOL:
arg = create_arg_op(btype);
+ if (arg == NULL)
+ goto fail_alloc;
if (current_op)
ret = add_left(arg, current_op);
else
case OP_NOT:
arg = create_arg_op(btype);
+ if (arg == NULL)
+ goto fail_alloc;
if (current_op)
ret = add_right(current_op, arg, error_str);
if (ret < 0)
arg = create_arg_exp(etype);
else
arg = create_arg_cmp(ctype);
+ if (arg == NULL)
+ goto fail_alloc;
if (current_op)
ret = add_right(current_op, arg, error_str);
break;
case EVENT_NONE:
break;
+ case EVENT_ERROR:
+ goto fail_alloc;
default:
goto fail_print;
}
if (!current_op)
current_op = current_exp;
- current_op = collapse_tree(current_op);
+ current_op = collapse_tree(current_op, error_str);
+ if (current_op == NULL)
+ goto fail;
*parg = current_op;
return 0;
+ fail_alloc:
+ show_error(error_str, "failed to allocate filter arg");
+ goto fail;
fail_print:
show_error(error_str, "Syntax error");
fail:
/* If parg is NULL, then make it into FALSE */
if (!*parg) {
*parg = allocate_arg();
+ if (*parg == NULL) {
+ show_error(error_str, "failed to allocate filter arg");
+ return -1;
+ }
(*parg)->type = FILTER_ARG_BOOLEAN;
(*parg)->boolean.value = FILTER_FALSE;
}
} else {
/* just add a TRUE arg */
arg = allocate_arg();
+ if (arg == NULL) {
+ show_error(error_str, "failed to allocate filter arg");
+ return -1;
+ }
arg->type = FILTER_ARG_BOOLEAN;
arg->boolean.value = FILTER_TRUE;
}
filter_type = add_filter_type(filter, event->id);
+ if (filter_type == NULL) {
+ show_error(error_str, "failed to add a new filter: %s",
+ filter_str ? filter_str : "true");
+ return -1;
+ }
+
if (filter_type->filter)
free_arg(filter_type->filter);
filter_type->filter = arg;
else
len = strlen(filter_str);
- this_event = malloc_or_die(len + 1);
+ this_event = malloc(len + 1);
+ if (this_event == NULL) {
+ show_error(error_str, "Memory allocation failure");
+ /* This can only happen when events is NULL, but still */
+ free_events(events);
+ return -1;
+ }
memcpy(this_event, filter_str, len);
this_event[len] = 0;
/* Find this event */
ret = find_event(pevent, &events, strim(sys_name), strim(event_name));
if (ret < 0) {
- if (event_name)
+ if (ret == PEVENT_ERRNO__MEM_ALLOC_FAILED)
+ show_error(error_str,
+ "Memory allocation failure");
+ else if (event_name)
show_error(error_str,
"No event found under '%s.%s'",
sys_name, event_name);
if (strcmp(str, "TRUE") == 0 || strcmp(str, "FALSE") == 0) {
/* Add trivial event */
arg = allocate_arg();
+ if (arg == NULL)
+ return -1;
+
arg->type = FILTER_ARG_BOOLEAN;
if (strcmp(str, "TRUE") == 0)
arg->boolean.value = 1;
arg->boolean.value = 0;
filter_type = add_filter_type(filter, event->id);
+ if (filter_type == NULL)
+ return -1;
+
filter_type->filter = arg;
free(str);
* @type: remove only true, false, or both
*
* Removes filters that only contain a TRUE or FALES boolean arg.
+ *
+ * Returns 0 on success and -1 if there was a problem.
*/
-void pevent_filter_clear_trivial(struct event_filter *filter,
+int pevent_filter_clear_trivial(struct event_filter *filter,
enum filter_trivial_type type)
{
struct filter_type *filter_type;
int i;
if (!filter->filters)
- return;
+ return 0;
/*
* Two steps, first get all ids with trivial filters.
* then remove those ids.
*/
for (i = 0; i < filter->filters; i++) {
+ int *new_ids;
+
filter_type = &filter->event_filters[i];
if (filter_type->filter->type != FILTER_ARG_BOOLEAN)
continue;
break;
}
- ids = realloc(ids, sizeof(*ids) * (count + 1));
- if (!ids)
- die("Can't allocate ids");
+ new_ids = realloc(ids, sizeof(*ids) * (count + 1));
+ if (!new_ids) {
+ free(ids);
+ return -1;
+ }
+
+ ids = new_ids;
ids[count++] = filter_type->event_id;
}
if (!count)
- return;
+ return 0;
for (i = 0; i < count; i++)
pevent_filter_remove_event(filter, ids[i]);
free(ids);
+ return 0;
}
/**