dovecot-2.0: config: Several fixes. Now per-ip settings work pro...
dovecot at dovecot.org
dovecot at dovecot.org
Thu Sep 3 23:36:52 EEST 2009
details: http://hg.dovecot.org/dovecot-2.0/rev/f9ca1a1ebcf8
changeset: 9859:f9ca1a1ebcf8
user: Timo Sirainen <tss at iki.fi>
date: Thu Sep 03 16:36:38 2009 -0400
description:
config: Several fixes. Now per-ip settings work properly.
doveconf parameters were also changed. Now it's possible to ask
configuration for a specified filter.
diffstat:
7 files changed, 320 insertions(+), 210 deletions(-)
src/config/config-connection.c | 7
src/config/config-filter.c | 129 ++++++++++++++---
src/config/config-filter.h | 14 +
src/config/config-parser.c | 288 +++++++++++++++++++---------------------
src/config/config-request.c | 43 ++++-
src/config/config-request.h | 7
src/config/doveconf.c | 42 ++++-
diffs (truncated from 812 to 300 lines):
diff -r 2e502c0e23e7 -r f9ca1a1ebcf8 src/config/config-connection.c
--- a/src/config/config-connection.c Thu Sep 03 16:35:19 2009 -0400
+++ b/src/config/config-connection.c Thu Sep 03 16:36:38 2009 -0400
@@ -102,8 +102,11 @@ static int config_connection_request(str
}
o_stream_cork(conn->output);
- config_request_handle(&filter, module, 0, config_request_output,
- conn->output);
+ if (config_request_handle(&filter, module, CONFIG_DUMP_SCOPE_SET, FALSE,
+ config_request_output, conn->output) < 0) {
+ config_connection_destroy(conn);
+ return -1;
+ }
o_stream_send_str(conn->output, "\n");
o_stream_uncork(conn->output);
return 0;
diff -r 2e502c0e23e7 -r f9ca1a1ebcf8 src/config/config-filter.c
--- a/src/config/config-filter.c Thu Sep 03 16:35:19 2009 -0400
+++ b/src/config/config-filter.c Thu Sep 03 16:36:38 2009 -0400
@@ -2,12 +2,13 @@
#include "lib.h"
#include "array.h"
+#include "settings-parser.h"
#include "config-parser.h"
#include "config-filter.h"
struct config_filter_context {
pool_t pool;
- struct config_filter_parser_list *const *parsers;
+ struct config_filter_parser *const *parsers;
};
bool config_filter_match(const struct config_filter *mask,
@@ -75,47 +76,123 @@ void config_filter_deinit(struct config_
}
void config_filter_add_all(struct config_filter_context *ctx,
- struct config_filter_parser_list *const *parsers)
+ struct config_filter_parser *const *parsers)
{
ctx->parsers = parsers;
}
-static int filter_cmp(const struct config_filter *f1,
- const struct config_filter *f2)
+static int
+config_filter_parser_cmp(struct config_filter_parser *const *p1,
+ struct config_filter_parser *const *p2)
{
- int ret;
+ const struct config_filter *f1 = &(*p1)->filter, *f2 = &(*p2)->filter;
- ret = f2->remote_bits - f1->remote_bits;
- if (ret != 0)
- return ret;
+ /* remote_ip and local_ips are first, although it doesn't really
+ matter which one comes first */
+ if (f1->local_bits > f2->local_bits)
+ return -1;
+ if (f1->local_bits < f2->local_bits)
+ return 1;
- ret = f2->local_bits - f1->local_bits;
- if (ret != 0)
- return ret;
+ if (f1->remote_bits > f2->remote_bits)
+ return -1;
+ if (f1->remote_bits < f2->remote_bits)
+ return 1;
- if (f1->service != NULL)
+ if (f1->service != NULL && f2->service == NULL)
return -1;
- else
+ if (f1->service == NULL && f2->service != NULL)
return 1;
+ return 0;
}
-const struct config_filter_parser_list *
-config_filter_find(struct config_filter_context *ctx,
- const struct config_filter *filter)
+static struct config_filter_parser *const *
+config_filter_find_all(struct config_filter_context *ctx,
+ const struct config_filter *filter)
{
- struct config_filter_parser_list *best = NULL;
+ ARRAY_TYPE(config_filter_parsers) matches;
unsigned int i;
- /* find the filter that best matches what we have.
- FIXME: this can't really work. we'd want to merge changes from
- different matches.. requires something larger after all. */
+ t_array_init(&matches, 8);
for (i = 0; ctx->parsers[i] != NULL; i++) {
- if (!config_filter_match(&ctx->parsers[i]->filter, filter))
- continue;
+ if (config_filter_match(&ctx->parsers[i]->filter, filter))
+ array_append(&matches, &ctx->parsers[i], 1);
+ }
+ array_sort(&matches, config_filter_parser_cmp);
+ (void)array_append_space(&matches);
+ return array_idx(&matches, 0);
+}
- if (best == NULL ||
- filter_cmp(&best->filter, &ctx->parsers[i]->filter) > 0)
- best = ctx->parsers[i];
+static bool
+config_filter_is_superset(const struct config_filter *sup,
+ const struct config_filter *filter)
+{
+ /* assume that both of the filters match the same subset, so we don't
+ need to compare IPs and service name. */
+ if (sup->local_bits < filter->local_bits)
+ return FALSE;
+ if (sup->remote_bits < filter->remote_bits)
+ return FALSE;
+ if (sup->service != NULL && filter->service == NULL)
+ return FALSE;
+ return TRUE;
+}
+
+static int
+config_module_parser_apply_changes(struct config_module_parser *dest,
+ const struct config_filter_parser *src,
+ pool_t pool, const char **error_r)
+{
+ unsigned int i;
+
+ for (i = 0; dest[i].module_name != NULL; i++) {
+ if (settings_parser_apply_changes(dest[i].parser,
+ src->parsers[i].parser, pool,
+ error_r) < 0) {
+ *error_r = t_strdup_printf("Conflict in setting %s",
+ *error_r);
+ return -1;
+ }
}
- return best;
+ return 0;
}
+
+int config_filter_get_parsers(struct config_filter_context *ctx, pool_t pool,
+ const struct config_filter *filter,
+ const struct config_module_parser **parsers_r,
+ const char **error_r)
+{
+ struct config_filter_parser *const *src;
+ struct config_module_parser *dest;
+ const char *error, **error_p;
+ unsigned int i, count;
+
+ src = config_filter_find_all(ctx, filter);
+
+ /* all of them should have the same number of parsers.
+ duplicate our initial parsers from the first match */
+ for (count = 0; src[0]->parsers[count].module_name != NULL; count++) ;
+ dest = p_new(pool, struct config_module_parser, count + 1);
+ for (i = 0; i < count; i++) {
+ dest[i] = src[0]->parsers[i];
+ dest[i].parser =
+ settings_parser_dup(src[0]->parsers[i].parser, pool);
+ }
+
+ /* apply the changes from rest of the matches */
+ for (i = 1; src[i] != NULL; i++) {
+ if (config_filter_is_superset(&src[i-1]->filter,
+ &src[i]->filter))
+ error_p = NULL;
+ else
+ error_p = &error;
+
+ if (config_module_parser_apply_changes(dest, src[i], pool,
+ error_p) < 0) {
+ *error_r = error;
+ return -1;
+ }
+ }
+ *parsers_r = dest;
+ return 0;
+}
diff -r 2e502c0e23e7 -r f9ca1a1ebcf8 src/config/config-filter.h
--- a/src/config/config-filter.h Thu Sep 03 16:35:19 2009 -0400
+++ b/src/config/config-filter.h Thu Sep 03 16:36:38 2009 -0400
@@ -9,23 +9,25 @@ struct config_filter {
unsigned int local_bits, remote_bits;
};
-struct config_filter_parser_list {
+struct config_filter_parser {
struct config_filter filter;
/* NULL-terminated array of parsers */
struct config_module_parser *parsers;
};
+ARRAY_DEFINE_TYPE(config_filter_parsers, struct config_filter_parser *);
struct config_filter_context *config_filter_init(pool_t pool);
void config_filter_deinit(struct config_filter_context **ctx);
/* Replace filter's parsers with given parser list. */
void config_filter_add_all(struct config_filter_context *ctx,
- struct config_filter_parser_list *const *parsers);
+ struct config_filter_parser *const *parsers);
-/* Find the filter that best matches what we have. */
-const struct config_filter_parser_list *
-config_filter_find(struct config_filter_context *ctx,
- const struct config_filter *filter);
+/* Build new parsers from all existing ones matching the given filter. */
+int config_filter_get_parsers(struct config_filter_context *ctx, pool_t pool,
+ const struct config_filter *filter,
+ const struct config_module_parser **parsers_r,
+ const char **error_r);
/* Returns TRUE if filter matches mask. */
bool config_filter_match(const struct config_filter *mask,
diff -r 2e502c0e23e7 -r f9ca1a1ebcf8 src/config/config-parser.c
--- a/src/config/config-parser.c Thu Sep 03 16:35:19 2009 -0400
+++ b/src/config/config-parser.c Thu Sep 03 16:36:38 2009 -0400
@@ -23,9 +23,12 @@
#define IS_WHITE(c) ((c) == ' ' || (c) == '\t')
-struct config_filter_stack {
- struct config_filter_stack *prev;
+struct config_section_stack {
+ struct config_section_stack *prev;
+
struct config_filter filter;
+ /* module_name=NULL-terminated list of parsers */
+ struct config_module_parser *parsers;
unsigned int pathlen;
};
@@ -41,15 +44,17 @@ struct parser_context {
pool_t pool;
const char *path;
- ARRAY_DEFINE(all_parsers, struct config_filter_parser_list *);
- /* parsers matching cur_filter */
- ARRAY_TYPE(config_module_parsers) cur_parsers;
+ ARRAY_DEFINE(all_parsers, struct config_filter_parser *);
struct config_module_parser *root_parsers;
- struct config_filter_stack *cur_filter;
+ struct config_section_stack *cur_section;
struct input_stack *cur_input;
struct config_filter_context *filter;
};
+
+static const enum settings_parser_flags settings_parser_flags =
+ SETTINGS_PARSER_FLAG_IGNORE_UNKNOWN_KEYS |
+ SETTINGS_PARSER_FLAG_TRACK_CHANGES;
struct config_module_parser *config_module_parsers;
struct config_filter_context *config_filter;
@@ -93,15 +98,15 @@ static void config_add_type(struct setti
}
static int
-config_parsers_parse_line(struct config_module_parser *parsers,
- const char *key, const char *line,
- const char *section_name, const char **error_r)
+config_apply_line(struct parser_context *ctx, const char *key,
+ const char *line, const char *section_name,
+ const char **error_r)
{
struct config_module_parser *l;
bool found = FALSE;
int ret;
- for (l = parsers; l->module_name != NULL; l++) {
+ for (l = ctx->cur_section->parsers; l->module_name != NULL; l++) {
ret = settings_parse_line(l->parser, line);
if (ret > 0) {
found = TRUE;
@@ -116,23 +121,6 @@ config_parsers_parse_line(struct config_
*error_r = t_strconcat("Unknown setting: ", key, NULL);
return -1;
}
- return 0;
-}
-
-static int
-config_apply_line(struct parser_context *ctx, const char *key,
- const char *line, const char *section_name,
- const char **error_r)
-{
- struct config_module_parser *const *parsers;
- unsigned int i, count;
-
- parsers = array_get(&ctx->cur_parsers, &count);
- for (i = 0; i < count; i++) {
- if (config_parsers_parse_line(parsers[i], key, line,
- section_name, error_r) < 0)
- return -1;
- }
More information about the dovecot-cvs
mailing list