Mercurial > dovecot > core-2.2
changeset 9263:5d0a69504867 HEAD
config handling fixes and improvements. Separated module/service lookups. Added support for per-lip/rip settings.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Mon, 11 May 2009 20:10:30 -0400 |
parents | 7604073a4ccc |
children | 11b6aab8a203 |
files | src/config/Makefile.am src/config/all-settings.h src/config/config-connection.c src/config/config-filter.c src/config/config-filter.h src/config/config-parser.c src/config/config-parser.h src/config/config-request.c src/config/config-request.h src/config/doveconf.c src/imap/main.c src/lda/main.c src/lib-master/master-service-settings.c src/lib-master/master-service-settings.h src/lib-storage/mail-storage-service.c src/lib-storage/mail-storage-service.h src/login-common/login-settings.c src/pop3/main.c |
diffstat | 18 files changed, 458 insertions(+), 74 deletions(-) [+] |
line wrap: on
line diff
--- a/src/config/Makefile.am Mon May 11 20:09:33 2009 -0400 +++ b/src/config/Makefile.am Mon May 11 20:10:30 2009 -0400 @@ -28,6 +28,7 @@ common = \ all-settings.c \ config-connection.c \ + config-filter.c \ config-parser.c \ config-request.c \ sysinfo-get.c @@ -43,6 +44,7 @@ noinst_HEADERS = \ all-settings.h \ config-connection.h \ + config-filter.h \ config-parser.h \ config-request.h \ sysinfo-get.h
--- a/src/config/all-settings.h Mon May 11 20:09:33 2009 -0400 +++ b/src/config/all-settings.h Mon May 11 20:10:30 2009 -0400 @@ -7,6 +7,7 @@ struct setting_parser_context *parser; void *settings; }; +ARRAY_DEFINE_TYPE(config_setting_parsers, struct config_setting_parser_list *); extern struct config_setting_parser_list config_setting_parsers[];
--- a/src/config/config-connection.c Mon May 11 20:09:33 2009 -0400 +++ b/src/config/config-connection.c Mon May 11 20:10:30 2009 -0400 @@ -56,16 +56,34 @@ static void config_connection_request(struct config_connection *conn, const char *const *args) { - const char *service = ""; + struct config_filter filter; + const char *module = ""; /* [<args>] */ + memset(&filter, 0, sizeof(filter)); for (; *args != NULL; args++) { if (strncmp(*args, "service=", 8) == 0) - service = *args + 8; + filter.service = *args + 8; + else if (strncmp(*args, "module=", 7) == 0) + module = *args + 7; + else if (strncmp(*args, "lip=", 4) == 0) { + if (net_addr2ip(*args + 4, &filter.local_net) == 0) { + filter.local_bits = + IPADDR_IS_V4(&filter.local_net) ? + 32 : 128; + } + } else if (strncmp(*args, "rip=", 4) == 0) { + if (net_addr2ip(*args + 4, &filter.remote_net) == 0) { + filter.remote_bits = + IPADDR_IS_V4(&filter.remote_net) ? + 32 : 128; + } + } } o_stream_cork(conn->output); - config_request_handle(service, 0, config_request_output, conn->output); + config_request_handle(&filter, module, 0, config_request_output, + conn->output); o_stream_send_str(conn->output, "\n"); o_stream_uncork(conn->output); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/config/config-filter.c Mon May 11 20:10:30 2009 -0400 @@ -0,0 +1,120 @@ +/* Copyright (C) 2005-2009 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "array.h" +#include "config-filter.h" + +struct config_filter_context { + pool_t pool; + struct config_filter_parser_list *const *parsers; +}; + +bool config_filter_match(const struct config_filter *mask, + const struct config_filter *filter) +{ + if (mask->service != NULL) { + if (filter->service == NULL) + return FALSE; + if (strcasecmp(filter->service, mask->service) != 0) + return FALSE; + } + /* FIXME: it's not comparing full masks */ + if (mask->remote_bits != 0) { + if (filter->remote_bits == 0) + return FALSE; + if (!net_is_in_network(&filter->remote_net, &mask->remote_net, + mask->remote_bits)) + return FALSE; + } + if (mask->local_bits != 0) { + if (filter->local_bits == 0) + return FALSE; + if (!net_is_in_network(&filter->local_net, &mask->local_net, + mask->local_bits)) + return FALSE; + } + return TRUE; +} + +bool config_filters_equal(const struct config_filter *f1, + const struct config_filter *f2) +{ + if (null_strcmp(f1->service, f2->service) != 0) + return FALSE; + + if (f1->remote_bits != f2->remote_bits) + return FALSE; + if (!net_ip_compare(&f1->remote_net, &f2->remote_net)) + return FALSE; + + if (f1->local_bits != f2->local_bits) + return FALSE; + if (!net_ip_compare(&f1->local_net, &f2->local_net)) + return FALSE; + + return TRUE; +} + +struct config_filter_context *config_filter_init(pool_t pool) +{ + struct config_filter_context *ctx; + + ctx = p_new(pool, struct config_filter_context, 1); + ctx->pool = pool; + return ctx; +} + +void config_filter_deinit(struct config_filter_context **_ctx) +{ + struct config_filter_context *ctx = *_ctx; + + *_ctx = NULL; + + pool_unref(&ctx->pool); +} + +void config_filter_add_all(struct config_filter_context *ctx, + struct config_filter_parser_list *const *parsers) +{ + ctx->parsers = parsers; +} + +static int filter_cmp(const struct config_filter *f1, + const struct config_filter *f2) +{ + int ret; + + ret = f2->remote_bits - f1->remote_bits; + if (ret != 0) + return ret; + + ret = f2->local_bits - f1->local_bits; + if (ret != 0) + return ret; + + if (f1->service != NULL) + return -1; + else + return 1; +} + +const struct config_setting_parser_list * +config_filter_match_parsers(struct config_filter_context *ctx, + const struct config_filter *filter) +{ + struct config_filter_parser_list *best = NULL; + 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. */ + for (i = 0; ctx->parsers[i] != NULL; i++) { + if (!config_filter_match(&ctx->parsers[i]->filter, filter)) + continue; + + if (best == NULL || + filter_cmp(&best->filter, &ctx->parsers[i]->filter) > 0) + best = ctx->parsers[i]; + } + return best == NULL ? NULL : best->parser_list; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/config/config-filter.h Mon May 11 20:10:30 2009 -0400 @@ -0,0 +1,35 @@ +#ifndef CONFIG_FILTER_H +#define CONFIG_FILTER_H + +#include "network.h" +#include "all-settings.h" + +struct config_filter { + const char *service; + struct ip_addr local_net, remote_net; + unsigned int local_bits, remote_bits; +}; + +struct config_filter_parser_list { + struct config_filter filter; + struct config_setting_parser_list *parser_list; +}; + +struct config_filter_context *config_filter_init(pool_t pool); +void config_filter_deinit(struct config_filter_context **ctx); + +void config_filter_add_all(struct config_filter_context *ctx, + struct config_filter_parser_list *const *parsers); + +const struct config_setting_parser_list * +config_filter_match_parsers(struct config_filter_context *ctx, + const struct config_filter *filter); + +/* Returns TRUE if filter matches mask. */ +bool config_filter_match(const struct config_filter *mask, + const struct config_filter *filter); +/* Returns TRUE if two filters are fully equal. */ +bool config_filters_equal(const struct config_filter *f1, + const struct config_filter *f2); + +#endif
--- a/src/config/config-parser.c Mon May 11 20:09:33 2009 -0400 +++ b/src/config/config-parser.c Mon May 11 20:10:30 2009 -0400 @@ -7,7 +7,7 @@ #include "strescape.h" #include "istream.h" #include "settings-parser.h" -#include "all-settings.h" +#include "config-filter.h" #include "config-parser.h" #include <unistd.h> @@ -15,6 +15,12 @@ #define IS_WHITE(c) ((c) == ' ' || (c) == '\t') +struct config_filter_stack { + struct config_filter_stack *prev; + struct config_filter filter; + unsigned int pathlen; +}; + struct input_stack { struct input_stack *prev; @@ -23,6 +29,21 @@ unsigned int linenum; }; +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_setting_parsers) cur_parsers; + struct config_filter_stack *cur_filter; + struct input_stack *cur_input; + + struct config_filter_context *filter; +}; + +struct config_filter_context *config_filter; + static const char *info_type_name_find(const struct setting_parser_info *info) { unsigned int i; @@ -62,13 +83,15 @@ } static const char * -config_parse_line(const char *key, const char *line, const char *section_name) +config_parsers_parse_line(struct config_setting_parser_list *parsers, + const char *key, const char *line, + const char *section_name) { struct config_setting_parser_list *l; bool found = FALSE; int ret; - for (l = config_setting_parsers; l->module_name != NULL; l++) { + for (l = parsers; l->module_name != NULL; l++) { ret = settings_parse_line(l->parser, line); if (ret > 0) { found = TRUE; @@ -82,6 +105,21 @@ } static const char * +config_parse_line(struct config_setting_parser_list *const *all_parsers, + const char *key, const char *line, const char *section_name) +{ + const char *ret; + + for (; *all_parsers != NULL; all_parsers++) { + ret = config_parsers_parse_line(*all_parsers, key, line, + section_name); + if (ret != NULL) + return ret; + } + return NULL; +} + +static const char * fix_relative_path(const char *path, struct input_stack *input) { const char *p; @@ -96,14 +134,122 @@ return t_strconcat(t_strdup_until(input->path, p+1), path, NULL); } +static struct config_setting_parser_list * +config_setting_parser_list_dup(pool_t pool, + const struct config_setting_parser_list *src) +{ + struct config_setting_parser_list *dest; + unsigned int i, count; + + for (count = 0; src[count].module_name != NULL; count++) ; + + dest = p_new(pool, struct config_setting_parser_list, count + 1); + for (i = 0; i < count; i++) { + dest[i] = src[i]; + dest[i].parser = settings_parser_dup(src[i].parser, pool); + } + return dest; +} + +static struct config_filter_parser_list * +config_add_new_parser(struct parser_context *ctx) +{ + struct config_filter_parser_list *parser; + struct config_setting_parser_list *const *cur_parsers; + unsigned int count; + + parser = p_new(ctx->pool, struct config_filter_parser_list, 1); + parser->filter = ctx->cur_filter->filter; + + cur_parsers = array_get(&ctx->cur_parsers, &count); + if (count == 0) { + /* first one */ + parser->parser_list = config_setting_parsers; + } else { + /* duplicate the first settings list */ + parser->parser_list = + config_setting_parser_list_dup(ctx->pool, + cur_parsers[0]); + } + + array_append(&ctx->all_parsers, &parser, 1); + return parser; +} + +static void config_add_new_filter(struct parser_context *ctx) +{ + struct config_filter_stack *filter; + + filter = p_new(ctx->pool, struct config_filter_stack, 1); + filter->prev = ctx->cur_filter; + filter->filter = ctx->cur_filter->filter; + ctx->cur_filter = filter; +} + +static struct config_setting_parser_list *const * +config_update_cur_parsers(struct parser_context *ctx) +{ + struct config_filter_parser_list *const *all_parsers; + unsigned int i, count; + bool full_found = FALSE; + + array_clear(&ctx->cur_parsers); + + all_parsers = array_get(&ctx->all_parsers, &count); + for (i = 0; i < count; i++) { + if (!config_filter_match(&ctx->cur_filter->filter, + &all_parsers[i]->filter)) + continue; + + if (config_filters_equal(&all_parsers[i]->filter, + &ctx->cur_filter->filter)) { + array_insert(&ctx->cur_parsers, 0, + &all_parsers[i]->parser_list, 1); + full_found = TRUE; + } else { + array_append(&ctx->cur_parsers, + &all_parsers[i]->parser_list, 1); + } + } + i_assert(full_found); + (void)array_append_space(&ctx->cur_parsers); + return array_idx(&ctx->cur_parsers, 0); +} + +static void +config_filter_parser_list_check(struct parser_context *ctx, + struct config_filter_parser_list *parser) +{ + struct config_setting_parser_list *l = parser->parser_list; + const char *errormsg; + + for (; l->module_name != NULL; l++) { + if (!settings_parser_check(l->parser, ctx->pool, &errormsg)) { + i_fatal("Error in configuration file %s: %s", + ctx->path, errormsg); + } + } +} + +static void +config_all_parsers_check(struct parser_context *ctx) +{ + struct config_filter_parser_list *const *parsers; + unsigned int i, count; + + parsers = array_get(&ctx->all_parsers, &count); + for (i = 0; i < count; i++) + config_filter_parser_list_check(ctx, parsers[i]); +} + void config_parse_file(const char *path) { enum settings_parser_flags parser_flags = SETTINGS_PARSER_FLAG_IGNORE_UNKNOWN_KEYS; - struct input_stack root, *input, *new_input; - ARRAY_DEFINE(pathlen_stack, unsigned int); + struct input_stack root, *new_input; ARRAY_TYPE(const_string) auth_defaults; - struct config_setting_parser_list *l; + struct config_setting_parser_list *l, *const *parsers; + struct parser_context ctx; unsigned int pathlen = 0; unsigned int counter = 0, auth_counter = 0, cur_counter; const char *errormsg, *name; @@ -111,38 +257,46 @@ int fd, ret; string_t *str, *full_line; size_t len; - pool_t pool; - pool = pool_alloconly_create("config file parser", 10240); + memset(&ctx, 0, sizeof(ctx)); + ctx.pool = pool_alloconly_create("config file parser", 10240); + ctx.path = path; fd = open(path, O_RDONLY); if (fd < 0) i_fatal("open(%s) failed: %m", path); - t_array_init(&pathlen_stack, 10); t_array_init(&auth_defaults, 32); for (l = config_setting_parsers; l->module_name != NULL; l++) { i_assert(l->parser == NULL); - l->parser = settings_parser_init(pool, l->root, parser_flags); + l->parser = settings_parser_init(ctx.pool, l->root, parser_flags); } - errormsg = config_parse_line("0", "auth=0", NULL); + t_array_init(&ctx.cur_parsers, 128); + p_array_init(&ctx.all_parsers, ctx.pool, 128); + ctx.cur_filter = p_new(ctx.pool, struct config_filter_stack, 1); + config_add_new_parser(&ctx); + parsers = config_update_cur_parsers(&ctx); + + errormsg = config_parse_line(parsers, "0", "auth=0", NULL); + i_assert(errormsg == NULL); + errormsg = config_parse_line(parsers, "name", "auth/0/name=default", NULL); i_assert(errormsg == NULL); memset(&root, 0, sizeof(root)); root.path = path; - input = &root; + ctx.cur_input = &root; str = t_str_new(256); full_line = t_str_new(512); errormsg = NULL; newfile: - input->input = i_stream_create_fd(fd, (size_t)-1, TRUE); - i_stream_set_return_partial_line(input->input, TRUE); + ctx.cur_input->input = i_stream_create_fd(fd, (size_t)-1, TRUE); + i_stream_set_return_partial_line(ctx.cur_input->input, TRUE); prevfile: - while ((line = i_stream_read_next_line(input->input)) != NULL) { - input->linenum++; + while ((line = i_stream_read_next_line(ctx.cur_input->input)) != NULL) { + ctx.cur_input->linenum++; /* @UNSAFE: line is modified */ @@ -204,8 +358,8 @@ struct input_stack *tmp; const char *path; - path = fix_relative_path(line, input); - for (tmp = input; tmp != NULL; tmp = tmp->prev) { + path = fix_relative_path(line, ctx.cur_input); + for (tmp = ctx.cur_input; tmp != NULL; tmp = tmp->prev) { if (strcmp(tmp->path, path) == 0) break; } @@ -213,9 +367,9 @@ errormsg = "Recursive include"; } else if ((fd = open(path, O_RDONLY)) != -1) { new_input = t_new(struct input_stack, 1); - new_input->prev = input; + new_input->prev = ctx.cur_input; new_input->path = t_strdup(path); - input = new_input; + ctx.cur_input = new_input; goto newfile; } else { /* failed, but ignore failures with include_try. */ @@ -249,10 +403,10 @@ str_truncate(str, 0); str_printfa(str, "auth/0/%s=%s", key + 5, line); - errormsg = config_parse_line(key + 5, str_c(str), NULL); + errormsg = config_parse_line(parsers, key + 5, str_c(str), NULL); array_append(&auth_defaults, &s, 1); } else { - errormsg = config_parse_line(key, str_c(str), NULL); + errormsg = config_parse_line(parsers, key, str_c(str), NULL); } } else if (strcmp(key, "}") != 0 || *line != '\0') { /* b) + errors */ @@ -274,26 +428,46 @@ if (*line != '{') errormsg = "Expecting '='"; + + config_add_new_filter(&ctx); + ctx.cur_filter->pathlen = pathlen; if (strcmp(key, "protocol") == 0) { - array_append(&pathlen_stack, &pathlen, 1); + ctx.cur_filter->filter.service = + p_strdup(ctx.pool, name); + config_add_new_parser(&ctx); + parsers = config_update_cur_parsers(&ctx); + } else if (strcmp(key, "local_ip") == 0) { + if (net_parse_range(name, &ctx.cur_filter->filter.local_net, + &ctx.cur_filter->filter.local_bits) < 0) + errormsg = "Invalid network mask"; + config_add_new_parser(&ctx); + parsers = config_update_cur_parsers(&ctx); + } else if (strcmp(key, "remote_ip") == 0) { + if (net_parse_range(name, &ctx.cur_filter->filter.remote_net, + &ctx.cur_filter->filter.remote_bits) < 0) + errormsg = "Invalid network mask"; + config_add_new_parser(&ctx); + parsers = config_update_cur_parsers(&ctx); } else { - array_append(&pathlen_stack, &pathlen, 1); - str_truncate(str, pathlen); str_append(str, key); pathlen = str_len(str); - if (strcmp(key, "auth") == 0) + if (strcmp(key, "auth") == 0) { cur_counter = auth_counter++; - else + if (cur_counter == 0 && strcmp(name, "default") != 0) + cur_counter = auth_counter++; + } else { cur_counter = counter++; + } str_append_c(str, '='); str_printfa(str, "%u", cur_counter); + if (cur_counter == 0 && strcmp(key, "auth") == 0) { /* already added this */ } else { - errormsg = config_parse_line(key, str_c(str), name); + errormsg = config_parse_line(parsers, key, str_c(str), name); } str_truncate(str, pathlen); @@ -314,43 +488,39 @@ p = strchr(lines[i], '='); str_append(str, lines[i]); - errormsg = config_parse_line(t_strdup_until(lines[i], p), str_c(str), NULL); + errormsg = config_parse_line(parsers, t_strdup_until(lines[i], p), str_c(str), NULL); i_assert(errormsg == NULL); } } } } else { /* c) */ - unsigned int pathlen_count; - const unsigned int *arr; - - arr = array_get(&pathlen_stack, &pathlen_count); - if (pathlen_count == 0) + if (ctx.cur_filter->prev == NULL) errormsg = "Unexpected '}'"; else { - pathlen = arr[pathlen_count - 1]; - array_delete(&pathlen_stack, - pathlen_count - 1, 1); + pathlen = ctx.cur_filter->pathlen; + ctx.cur_filter = ctx.cur_filter->prev; + parsers = config_update_cur_parsers(&ctx); } } if (errormsg != NULL) { i_fatal("Error in configuration file %s line %d: %s", - input->path, input->linenum, errormsg); + ctx.cur_input->path, ctx.cur_input->linenum, + errormsg); break; } str_truncate(full_line, 0); } - i_stream_destroy(&input->input); - input = input->prev; - if (line == NULL && input != NULL) + i_stream_destroy(&ctx.cur_input->input); + ctx.cur_input = ctx.cur_input->prev; + if (line == NULL && ctx.cur_input != NULL) goto prevfile; - for (l = config_setting_parsers; l->module_name != NULL; l++) { - if (!settings_parser_check(l->parser, pool, &errormsg)) { - i_fatal("Error in configuration file %s: %s", - path, errormsg); - } - } + config_all_parsers_check(&ctx); + + (void)array_append_space(&ctx.all_parsers); + config_filter = config_filter_init(ctx.pool); + config_filter_add_all(config_filter, array_idx(&ctx.all_parsers, 0)); }
--- a/src/config/config-parser.h Mon May 11 20:09:33 2009 -0400 +++ b/src/config/config-parser.h Mon May 11 20:10:30 2009 -0400 @@ -1,6 +1,8 @@ #ifndef CONFIG_PARSER_H #define CONFIG_PARSER_H +extern struct config_filter_context *config_filter; + void config_parse_file(const char *path); #endif
--- a/src/config/config-request.c Mon May 11 20:09:33 2009 -0400 +++ b/src/config/config-request.c Mon May 11 20:10:30 2009 -0400 @@ -8,6 +8,7 @@ #include "settings-parser.h" #include "master-service-settings.h" #include "all-settings.h" +#include "config-parser.h" #include "config-request.h" struct settings_export_context { @@ -45,12 +46,12 @@ } static bool -config_setting_parser_is_in_service(struct config_setting_parser_list *list, - const char *service) +config_setting_parser_is_in_service(const struct config_setting_parser_list *list, + const char *module) { struct config_setting_parser_list *l; - if (strcmp(list->module_name, service) == 0) + if (strcmp(list->module_name, module) == 0) return TRUE; if (list->root == &master_service_setting_parser_info) { /* everyone wants master service settings */ @@ -58,7 +59,7 @@ } for (l = config_setting_parsers; l->module_name != NULL; l++) { - if (strcmp(l->module_name, service) != 0) + if (strcmp(l->module_name, module) != 0) continue; /* see if we can find a way to get from the original parser @@ -213,10 +214,11 @@ } } -void config_request_handle(const char *service, enum config_dump_flags flags, +void config_request_handle(const struct config_filter *filter, + const char *module, enum config_dump_flags flags, config_request_callback_t *callback, void *context) { - struct config_setting_parser_list *l; + const struct config_setting_parser_list *l; struct settings_export_context ctx; memset(&ctx, 0, sizeof(ctx)); @@ -229,9 +231,10 @@ ctx.keys = hash_table_create(default_pool, ctx.pool, 0, str_hash, (hash_cmp_callback_t *)strcmp); - for (l = config_setting_parsers; l->module_name != NULL; l++) { - if (*service == '\0' || - config_setting_parser_is_in_service(l, service)) { + l = config_filter_match_parsers(config_filter, filter); + for (; l->module_name != NULL; l++) { + if (*module == '\0' || + config_setting_parser_is_in_service(l, module)) { settings_export(&ctx, l->root, settings_parser_get(l->parser)); }
--- a/src/config/config-request.h Mon May 11 20:09:33 2009 -0400 +++ b/src/config/config-request.h Mon May 11 20:10:30 2009 -0400 @@ -1,6 +1,8 @@ #ifndef CONFIG_REQUEST_H #define CONFIG_REQUEST_H +#include "config-filter.h" + enum config_dump_flags { CONFIG_DUMP_FLAG_DEFAULTS = 0x01 }; @@ -8,7 +10,8 @@ typedef void config_request_callback_t(const char *key, const char *value, bool list, void *context); -void config_request_handle(const char *service, enum config_dump_flags flags, +void config_request_handle(const struct config_filter *filter, + const char *module, enum config_dump_flags flags, config_request_callback_t *callback, void *context); #endif
--- a/src/config/doveconf.c Mon May 11 20:09:33 2009 -0400 +++ b/src/config/doveconf.c Mon May 11 20:10:30 2009 -0400 @@ -65,7 +65,8 @@ } static void config_connection_request_human(struct ostream *output, - const char *service, + const struct config_filter *filter, + const char *module, enum config_dump_flags flags) { static const char *ident_str = " "; @@ -79,7 +80,8 @@ ctx.pool = pool_alloconly_create("config human strings", 10240); i_array_init(&ctx.strings, 256); - config_request_handle(service, flags, config_request_get_strings, &ctx); + config_request_handle(filter, module, flags, + config_request_get_strings, &ctx); strings = array_get_modifiable(&ctx.strings, &count); qsort(strings, count, sizeof(*strings), config_string_cmp); @@ -158,13 +160,15 @@ pool_unref(&ctx.pool); } -static void config_dump_human(const char *service, enum config_dump_flags flags) +static void config_dump_human(const struct config_filter *filter, + const char *module, + enum config_dump_flags flags) { struct ostream *output; output = o_stream_create_fd(STDOUT_FILENO, 0, FALSE); o_stream_cork(output); - config_connection_request_human(output, service, flags); + config_connection_request_human(output, filter, module, flags); o_stream_uncork(output); } @@ -202,25 +206,30 @@ int main(int argc, char *argv[]) { enum config_dump_flags flags = CONFIG_DUMP_FLAG_DEFAULTS; - const char *getopt_str, *config_path, *service_name = ""; + const char *getopt_str, *config_path, *module = ""; + struct config_filter filter; char **exec_args = NULL; int c; + memset(&filter, 0, sizeof(filter)); service = master_service_init("config", MASTER_SERVICE_FLAG_STANDALONE, argc, argv); i_set_failure_prefix("doveconf: "); - getopt_str = t_strconcat("anp:e", master_service_getopt_string(), NULL); + getopt_str = t_strconcat("am:np:e", master_service_getopt_string(), NULL); while ((c = getopt(argc, argv, getopt_str)) > 0) { if (c == 'e') break; switch (c) { case 'a': break; + case 'm': + module = optarg; + break; case 'n': flags &= ~CONFIG_DUMP_FLAG_DEFAULTS; break; case 'p': - service_name = optarg; + filter.service = optarg; break; default: if (!master_service_parse_option(service, c, optarg)) @@ -248,10 +257,10 @@ if (*info != '\0') printf("# %s\n", info); fflush(stdout); - config_dump_human(service_name, flags); + config_dump_human(&filter, module, flags); } else { env_put("DOVECONF_ENV=1"); - config_request_handle(service_name, 0, + config_request_handle(&filter, module, 0, config_request_putenv, NULL); execvp(exec_args[0], exec_args); i_fatal("execvp(%s) failed: %m", exec_args[0]);
--- a/src/imap/main.c Mon May 11 20:09:33 2009 -0400 +++ b/src/imap/main.c Mon May 11 20:10:30 2009 -0400 @@ -186,6 +186,8 @@ } memset(&input, 0, sizeof(input)); + input.module = "imap"; + input.service = "imap"; input.username = getenv("USER"); if (input.username == NULL) { if (IS_STANDALONE())
--- a/src/lda/main.c Mon May 11 20:09:33 2009 -0400 +++ b/src/lda/main.c Mon May 11 20:10:30 2009 -0400 @@ -315,6 +315,8 @@ } memset(&service_input, 0, sizeof(service_input)); + service_input.module = "lda"; + service_input.service = "lda"; service_input.username = user; service_flags |= MAIL_STORAGE_SERVICE_FLAG_DISALLOW_ROOT;
--- a/src/lib-master/master-service-settings.c Mon May 11 20:09:33 2009 -0400 +++ b/src/lib-master/master-service-settings.c Mon May 11 20:10:30 2009 -0400 @@ -124,8 +124,11 @@ string_t *str; str = t_str_new(128); - str_append(str, CONFIG_HANDSHAKE); - str_printfa(str, "REQ\tservice=%s", service->name); + str_append(str, CONFIG_HANDSHAKE"REQ"); + if (input->module != NULL) + str_printfa(str, "\tmodule=%s", input->module); + if (input->service != NULL) + str_printfa(str, "\tservice=%s", input->service); if (input->username != NULL) str_printfa(str, "\tuser=%s", input->username); if (input->local_ip.family != 0) { @@ -269,6 +272,7 @@ memset(&input, 0, sizeof(input)); input.roots = roots; + input.module = service->name; return master_service_settings_read(service, &input, error_r); }
--- a/src/lib-master/master-service-settings.h Mon May 11 20:09:33 2009 -0400 +++ b/src/lib-master/master-service-settings.h Mon May 11 20:10:30 2009 -0400 @@ -20,6 +20,8 @@ const struct dynamic_settings_parser *dyn_parsers; bool preserve_home; + const char *module; + const char *service; const char *username; struct ip_addr local_ip, remote_ip; };
--- a/src/lib-storage/mail-storage-service.c Mon May 11 20:09:33 2009 -0400 +++ b/src/lib-storage/mail-storage-service.c Mon May 11 20:10:30 2009 -0400 @@ -334,6 +334,8 @@ set_input.dyn_parsers = mail_storage_get_dynamic_parsers(); set_input.preserve_home = preserve_home; if (input != NULL) { + set_input.module = input->module; + set_input.service = input->service; set_input.username = input->username; set_input.local_ip = input->local_ip; set_input.remote_ip = input->remote_ip;
--- a/src/lib-storage/mail-storage-service.h Mon May 11 20:09:33 2009 -0400 +++ b/src/lib-storage/mail-storage-service.h Mon May 11 20:10:30 2009 -0400 @@ -17,6 +17,8 @@ }; struct mail_storage_service_input { + const char *module; + const char *service; const char *username; struct ip_addr local_ip, remote_ip; };
--- a/src/login-common/login-settings.c Mon May 11 20:09:33 2009 -0400 +++ b/src/login-common/login-settings.c Mon May 11 20:10:30 2009 -0400 @@ -1,6 +1,6 @@ /* Copyright (c) 2005-2009 Dovecot authors, see the included COPYING file */ -#include "lib.h" +#include "common.h" #include "settings-parser.h" #include "master-service-settings.h" #include "login-settings.h" @@ -178,11 +178,16 @@ &login_setting_parser_info, NULL }; + struct master_service_settings_input input; const char *error; void **sets; - if (master_service_settings_read_simple(service, set_roots, - &error) < 0) + memset(&input, 0, sizeof(input)); + input.roots = set_roots; + input.module = "login"; + input.service = login_protocol; + + if (master_service_settings_read(service, &input, &error) < 0) i_fatal("Error reading configuration: %s", error); sets = master_service_settings_get_others(service);