From 929bb1ca2452a5bc7410896fd4e5eea44901a0b7 Mon Sep 17 00:00:00 2001 From: Florent Bruneau Date: Sat, 13 Sep 2008 09:39:53 +0200 Subject: [PATCH] foreach() semantic for arrays, improves configuration post-processing. Signed-off-by: Florent Bruneau --- common/array.h | 4 ++++ postlicyd/config.c | 39 ++++++++++++++++++++++++++++++++++++--- postlicyd/filter.c | 31 +++++++++++++++++++++++++++++-- postlicyd/filter.h | 32 ++++++++++++++++++++++++++++++-- 4 files changed, 99 insertions(+), 7 deletions(-) diff --git a/common/array.h b/common/array.h index e4cf094..ed12b5b 100644 --- a/common/array.h +++ b/common/array.h @@ -109,6 +109,10 @@ #define array_elt(array, n) (array).data[(n)] #define array_ptr(array, n) (array).data + (n) +#define foreach(var, array) \ + for (int __Ai = 0 ; __Ai < (array).len ; ++__Ai) { \ + var = array_ptr(array, __Ai); + #define array_foreach(array, action) \ for (int __Ai = 0 ; __Ai < (array).len ; ++__Ai) { \ action(array_ptr(array, __Ai)); \ diff --git a/postlicyd/config.c b/postlicyd/config.c index 2d818f2..871a71f 100644 --- a/postlicyd/config.c +++ b/postlicyd/config.c @@ -59,6 +59,28 @@ void config_delete(config_t **config) } } + +static bool config_second_pass(config_t *config) +{ + bool ok = true; + if (config->filters.len > 0) { +# define QSORT_TYPE filter_t +# define QSORT_BASE config->filters.data +# define QSORT_NELT config->filters.len +# define QSORT_LT(a,b) strcmp(a->name, b->name) < 0 +# include "qsort.c" + } + + foreach (filter_t *filter, config->filters) { + if (!filter_update_references(filter, &config->filters)) { + ok = false; + break; + } + }} + + return ok; +} + config_t *config_read(const char *file) { config_t *config; @@ -77,6 +99,7 @@ config_t *config_read(const char *file) } config = config_new(); + filter_init(&filter); linep = p = map.map; #define READ_ERROR(Fmt, ...) \ @@ -209,12 +232,15 @@ read_section: read_param_value: READ_BLANK(goto badeof); READ_STRING("parameter value", value, value_len, ;); - /* TODO: Insert parameter in the configuration. - */ + { + filter_params_t param; + param.name = strdup(key); + param.value = strdup(value); + array_add(config->params, param); + } goto read_section; read_filter: - filter_init(&filter); filter_set_name(&filter, key, key_len); READ_BLANK(goto badeof); while (*p != '}') { @@ -249,15 +275,22 @@ read_filter: READ_ERROR("invalid filter %s", filter.name); } array_add(config->filters, filter); + filter_init(&filter); goto read_section; ok: + if (!config_second_pass(config)) { + goto error; + } + file_map_close(&map); return config; badeof: syslog(LOG_ERR, "Unexpected end of file"); error: + filter_wipe(&filter); config_delete(&config); + file_map_close(&map); return NULL; } diff --git a/postlicyd/filter.c b/postlicyd/filter.c index 5c4f93e..da78992 100644 --- a/postlicyd/filter.c +++ b/postlicyd/filter.c @@ -53,13 +53,38 @@ void filter_register(const char *type, filter_constructor_t constructor, bool filter_build(filter_t *filter) { + bool ret = true; if (filter->type == FTK_UNKNOWN || filter->name == NULL) { return false; } + if (filter->hooks.len > 0) { +# define QSORT_TYPE filter_hook_t +# define QSORT_BASE filter->hooks.data +# define QSORT_NELT filter->hooks.len +# define QSORT_LT(a,b) strcmp(a->name, b->name) < 0 +# include "qsort.c" + } filter_constructor_t constructor = constructors[filter->type]; if (constructor) { - return constructor(filter); + ret = constructor(filter); } + array_deep_wipe(filter->params, filter_params_wipe); + return ret; +} + +bool filter_update_references(filter_t *filter, A(filter_t) *filter_list) +{ + foreach (filter_hook_t *hook, filter->hooks) { + if (!hook->postfix) { + hook->filter_id = filter_find_with_name(filter_list, hook->value); + if (hook->filter_id == -1) { + syslog(LOG_ERR, "invalid filter name %s for hook %s", + hook->value, hook->name); + return false; + } + p_delete(&hook->value); + } + }} return true; } @@ -107,7 +132,9 @@ bool filter_add_hook(filter_t *filter, const char *name, ssize_t name_len, { filter_hook_t hook; hook.name = strdup(name); - hook.value = strdup(value); + hook.postfix = (strncmp(value, "postfix:", 8) == 0); + hook.value = strdup(hook.postfix ? value + 8 : value); + hook.filter_id = -1; array_add(filter->hooks, hook); return true; } diff --git a/postlicyd/filter.h b/postlicyd/filter.h index a08ec45..db8e457 100644 --- a/postlicyd/filter.h +++ b/postlicyd/filter.h @@ -46,6 +46,9 @@ typedef filter_token filter_type_t; typedef struct filter_hook_t { char *name; char *value; + + bool postfix; + int filter_id; } filter_hook_t; ARRAY(filter_hook_t) @@ -60,12 +63,13 @@ typedef struct filter_t { filter_type_t type; A(filter_hook_t) hooks; - A(filter_params_t) params; void *data; + + A(filter_params_t) params; } filter_t; ARRAY(filter_t) -#define FILTER_INIT { NULL, FTK_UNKNOWN, ARRAY_INIT, ARRAY_INIT, NULL } +#define FILTER_INIT { NULL, FTK_UNKNOWN, ARRAY_INIT, NULL, ARRAY_INIT } typedef const char *filter_result_t; typedef filter_result_t (*filter_runner_t)(const filter_t *filter, @@ -101,6 +105,30 @@ bool filter_add_hook(filter_t *filter, const char *name, ssize_t name_len, __attribute__((nonnull(1))) bool filter_build(filter_t *filter); +__attribute__((nonnull(1,2))) +static inline int filter_find_with_name(A(filter_t) *array, const char *name) +{ + int start = 0; + int end = array->len; + + while (start < end) { + int mid = (start + end) / 2; + int cmp = strcmp(name, array_elt(*array, mid).name); + + if (cmp == 0) { + return mid; + } else if (cmp < 0) { + end = mid; + } else { + start = mid + 1; + } + } + return -1; +} + +__attribute__((nonnull(1,2))) +bool filter_update_references(filter_t *filter, A(filter_t) *array); + __attribute__((nonnull(1))) static inline void filter_hook_wipe(filter_hook_t *hook) { -- 2.20.1