Mercurial > dovecot > core-2.2
changeset 9179:f8460b27db00 HEAD
doveconf: With -p only protocol-specific settings are returned. -n and -a return human-readable output.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 30 Apr 2009 15:02:44 -0400 |
parents | 13bbdd7b15b8 |
children | ea0b68301004 |
files | src/config/Makefile.am src/config/common.h src/config/config-connection.c src/config/config-connection.h src/config/config-parser.c src/config/config-parser.h src/config/config-request.c src/config/config-request.h src/config/main.c src/config/settings-get.pl src/imap/imap-settings.c src/lib-lda/lda-settings.c src/lib-settings/settings-parser.h src/pop3/pop3-settings.c |
diffstat | 14 files changed, 481 insertions(+), 261 deletions(-) [+] |
line wrap: on
line diff
--- a/src/config/Makefile.am Thu Apr 30 14:48:54 2009 -0400 +++ b/src/config/Makefile.am Thu Apr 30 15:02:44 2009 -0400 @@ -22,11 +22,11 @@ all-settings.c \ config-connection.c \ config-parser.c \ + config-request.c \ main.c noinst_HEADERS = \ all-settings.h \ - common.h \ config-connection.h \ config-parser.h
--- a/src/config/common.h Thu Apr 30 14:48:54 2009 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -#ifndef COMMON_H -#define COMMON_H - -#include "lib.h" - -extern ARRAY_TYPE(const_string) config_strings; - -#endif
--- a/src/config/config-connection.c Thu Apr 30 14:48:54 2009 -0400 +++ b/src/config/config-connection.c Thu Apr 30 15:02:44 2009 -0400 @@ -1,19 +1,18 @@ /* Copyright (C) 2005-2009 Dovecot authors, see the included COPYING file */ -#include "common.h" +#include "lib.h" #include "array.h" -#include "str.h" #include "llist.h" #include "ioloop.h" #include "network.h" #include "istream.h" #include "ostream.h" #include "env-util.h" +#include "config-request.h" #include "config-connection.h" #include <stdlib.h> #include <unistd.h> -#include <fcntl.h> #define MAX_INBUF_SIZE 1024 @@ -46,24 +45,176 @@ return t_strsplit(line, "\t"); } +static void +config_request_output(const char *key, const char *value, + bool list ATTR_UNUSED, void *context) +{ + struct ostream *output = context; + + o_stream_send_str(output, key); + o_stream_send_str(output, "="); + o_stream_send_str(output, value); + o_stream_send_str(output, "\n"); +} + +struct config_request_get_string_ctx { + pool_t pool; + ARRAY_TYPE(const_string) strings; +}; + +static void +config_request_get_strings(const char *key, const char *value, + bool list, void *context) +{ + struct config_request_get_string_ctx *ctx = context; + + value = p_strdup_printf(ctx->pool, list ? "-%s=%s" : "%s=%s", + key, value); + array_append(&ctx->strings, &value, 1); +} + +static int config_string_cmp(const void *p1, const void *p2) +{ + const char *s1 = *(const char *const *)p1; + const char *s2 = *(const char *const *)p2; + unsigned int i = 0; + + while (s1[i] == s2[i]) { + if (s1[i] == '\0' || s1[i] == '=') + return 0; + i++; + } + + if (s1[i] == '=') + return -1; + if (s2[i] == '=') + return 1; + return s1[i] - s2[i]; +} + +static unsigned int prefix_stack_pop(ARRAY_TYPE(uint) *stack) +{ + const unsigned int *indexes; + unsigned int idx, count; + + indexes = array_get(stack, &count); + idx = count <= 1 ? -1U : indexes[count-2]; + array_delete(stack, count-1, 1); + return idx; +} + +static void config_connection_request_human(struct ostream *output, + const char *service, + enum config_dump_flags flags) +{ + static const char *ident_str = " "; + ARRAY_TYPE(const_string) prefixes_arr; + ARRAY_TYPE(uint) prefix_idx_stack; + struct config_request_get_string_ctx ctx; + const char **strings, *const *args, *p, *str, *const *prefixes; + const char *key, *value; + unsigned int i, j, count, len, prefix_count, skip_len; + unsigned int indent = 0, prefix_idx = -1U; + + 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); + + strings = array_get_modifiable(&ctx.strings, &count); + qsort(strings, count, sizeof(*strings), config_string_cmp); + + p_array_init(&prefixes_arr, ctx.pool, 32); + for (i = 0; i < count && strings[i][0] == '-'; i++) T_BEGIN { + p = strchr(strings[i], '='); + i_assert(p != NULL); + for (args = t_strsplit(p + 1, " "); *args != NULL; args++) { + str = p_strdup_printf(ctx.pool, "%s/%s/", + t_strcut(strings[i]+1, '='), + *args); + array_append(&prefixes_arr, &str, 1); + } + } T_END; + prefixes = array_get(&prefixes_arr, &prefix_count); + + p_array_init(&prefix_idx_stack, ctx.pool, 8); + for (; i < count; i++) T_BEGIN { + value = strchr(strings[i], '='); + i_assert(value != NULL); + key = t_strdup_until(strings[i], value); + value++; + + j = 0; + while (prefix_idx != -1U) { + len = strlen(prefixes[prefix_idx]); + if (strncmp(prefixes[prefix_idx], key, len) != 0) { + prefix_idx = prefix_stack_pop(&prefix_idx_stack); + indent--; + o_stream_send(output, ident_str, indent*2); + o_stream_send_str(output, "}\n"); + } else if (strchr(key + len, '/') == NULL) { + /* keep the prefix */ + j = prefix_count; + break; + } else { + /* subprefix */ + break; + } + } + for (; j < prefix_count; j++) { + len = strlen(prefixes[j]); + if (strncmp(prefixes[j], key, len) == 0 && + strchr(key + len, '/') == NULL) { + key += prefix_idx == -1U ? 0 : + strlen(prefixes[prefix_idx]); + o_stream_send(output, ident_str, indent*2); + o_stream_send_str(output, t_strcut(key, '/')); + o_stream_send_str(output, " {\n"); + indent++; + prefix_idx = j; + array_append(&prefix_idx_stack, &prefix_idx, 1); + break; + } + } + skip_len = prefix_idx == -1U ? 0 : strlen(prefixes[prefix_idx]); + i_assert(strncmp(prefixes[prefix_idx], strings[i], skip_len) == 0); + o_stream_send(output, ident_str, indent*2); + key = strings[i] + skip_len; + value = strchr(key, '='); + o_stream_send(output, key, value-key); + o_stream_send_str(output, " = "); + o_stream_send_str(output, value+1); + o_stream_send(output, "\n", 1); + } T_END; + + while (prefix_idx != -1U) { + prefix_idx = prefix_stack_pop(&prefix_idx_stack); + indent--; + o_stream_send(output, ident_str, indent*2); + o_stream_send_str(output, "}\n"); + } + + array_free(&ctx.strings); + pool_unref(&ctx.pool); +} + static void config_connection_request(struct config_connection *conn, const char *const *args, enum config_dump_flags flags) { - const char *const *strings; - unsigned int i, count; - string_t *str; + const char *service = ""; + + /* [<service> [<args>]] */ + if (args[0] != NULL) + service = args[0]; - /* <process> [<args>] */ - str = t_str_new(256); - strings = array_get(&config_strings, &count); o_stream_cork(conn->output); - for (i = 0; i < count; i += 2) { - str_truncate(str, 0); - str_printfa(str, "%s=%s\n", strings[i], strings[i+1]); - o_stream_send(conn->output, str_data(str), str_len(str)); + if ((flags & CONFIG_DUMP_FLAG_HUMAN) == 0) { + config_request_handle(service, flags, config_request_output, + conn->output); + o_stream_send_str(conn->output, "\n"); + } else { + config_connection_request_human(conn->output, service, flags); } - o_stream_send_str(conn->output, "\n"); o_stream_uncork(conn->output); } @@ -138,20 +289,22 @@ const char *args[2] = { service, NULL }; conn = config_connection_create(fd); - config_connection_request(conn, args, flags); + config_connection_request(conn, args, flags); config_connection_destroy(conn); } -void config_connection_putenv(void) +static void config_request_putenv(const char *key, const char *value, + bool list ATTR_UNUSED, + void *context ATTR_UNUSED) { - const char *const *strings; - unsigned int i, count; + T_BEGIN { + env_put(t_strconcat(t_str_ucase(key), "=", value, NULL)); + } T_END; +} - strings = array_get(&config_strings, &count); - for (i = 0; i < count; i += 2) T_BEGIN { - env_put(t_strconcat(t_str_ucase(strings[i]), "=", - strings[i+1], NULL)); - } T_END; +void config_connection_putenv(const char *service) +{ + config_request_handle(service, 0, config_request_putenv, NULL); } void config_connections_destroy_all(void)
--- a/src/config/config-connection.h Thu Apr 30 14:48:54 2009 -0400 +++ b/src/config/config-connection.h Thu Apr 30 15:02:44 2009 -0400 @@ -1,17 +1,14 @@ #ifndef CONFIG_CONNECTION_H #define CONFIG_CONNECTION_H -enum config_dump_flags { - CONFIG_DUMP_FLAG_HUMAN = 0x01, - CONFIG_DUMP_FLAG_DEFAULTS = 0x02 -}; +enum config_dump_flags; struct config_connection *config_connection_create(int fd); void config_connection_destroy(struct config_connection *conn); void config_connection_dump_request(int fd, const char *service, enum config_dump_flags flags); -void config_connection_putenv(void); +void config_connection_putenv(const char *service); void config_connections_destroy_all(void);
--- a/src/config/config-parser.c Thu Apr 30 14:48:54 2009 -0400 +++ b/src/config/config-parser.c Thu Apr 30 15:02:44 2009 -0400 @@ -24,22 +24,15 @@ }; static const char * -config_parse_line(pool_t pool, const char *key, const char *line, +config_parse_line(const char *key, const char *line, const struct setting_parser_info **info_r) { - enum settings_parser_flags parser_flags = - SETTINGS_PARSER_FLAG_IGNORE_UNKNOWN_KEYS; struct config_setting_parser_list *l; bool found = FALSE; int ret; *info_r = NULL; for (l = config_setting_parsers; l->module_name != NULL; l++) { - if (l->parser == NULL) { - l->parser = settings_parser_init(pool, l->root, - parser_flags); - } - ret = settings_parse_line(l->parser, line); if (ret > 0) { found = TRUE; @@ -51,189 +44,6 @@ return found ? NULL : t_strconcat("Unknown setting: ", key, NULL); } -struct settings_export_context { - pool_t pool; - ARRAY_TYPE(const_string) *dest; - string_t *value; - string_t *prefix; - struct hash_table *keys; - bool export_defaults; -}; - -static void settings_export(struct settings_export_context *ctx, - const struct setting_parser_info *info, - const void *set) -{ - const struct setting_define *def; - const void *value, *default_value; - void *const *children = NULL; - unsigned int i, count, prefix_len; - const char *str; - char *key; - - for (def = info->defines; def->key != NULL; def++) { - value = CONST_PTR_OFFSET(set, def->offset); - default_value = info->defaults == NULL ? NULL : - CONST_PTR_OFFSET(info->defaults, def->offset); - - count = 0; - str_truncate(ctx->value, 0); - switch (def->type) { - case SET_INTERNAL: - break; - case SET_BOOL: { - const bool *val = value, *dval = default_value; - if (ctx->export_defaults || - dval == NULL || *val != *dval) { - str_append(ctx->value, - *val ? "yes" : "no"); - } - break; - } - case SET_UINT: { - const unsigned int *val = value, *dval = default_value; - if (ctx->export_defaults || - dval == NULL || *val != *dval) - str_printfa(ctx->value, "%u", *val); - break; - } - case SET_STR_VARS: { - const char *const *val = value, *sval; - const char *const *_dval = default_value; - const char *dval = _dval == NULL ? NULL : *_dval; - - i_assert(*val == NULL || - **val == SETTING_STRVAR_UNEXPANDED[0]); - - sval = *val == NULL ? NULL : (*val + 1); - if ((ctx->export_defaults || - null_strcmp(sval, dval) != 0) && sval != NULL) - str_append(ctx->value, sval); - break; - } - case SET_STR: { - const char *const *val = value; - const char *const *_dval = default_value; - const char *dval = _dval == NULL ? NULL : *_dval; - - if ((ctx->export_defaults || - null_strcmp(*val, dval) != 0) && *val != NULL) - str_append(ctx->value, *val); - break; - } - case SET_ENUM: { - const char *const *val = value; - const char *const *_dval = default_value; - const char *dval = _dval == NULL ? NULL : *_dval; - unsigned int len = strlen(*val); - - if (ctx->export_defaults || - strncmp(*val, dval, len) != 0 || - ((*val)[len] != ':' && (*val)[len] != '\0')) - str_append(ctx->value, *val); - break; - } - case SET_DEFLIST: { - const ARRAY_TYPE(void_array) *val = value; - - if (!array_is_created(val)) - break; - - children = array_get(val, &count); - for (i = 0; i < count; i++) { - if (i > 0) - str_append_c(ctx->value, ' '); - str_printfa(ctx->value, "%u", i); - } - break; - } - case SET_STRLIST: { - const ARRAY_TYPE(const_string) *val = value; - const char *const *strings; - - if (!array_is_created(val)) - break; - - key = p_strconcat(ctx->pool, str_c(ctx->prefix), - def->key, NULL); - - if (hash_table_lookup(ctx->keys, key) != NULL) { - /* already added all of these */ - break; - } - hash_table_insert(ctx->keys, key, key); - - str = key; - array_append(ctx->dest, &str, 1); - str = "0"; - array_append(ctx->dest, &str, 1); - - strings = array_get(val, &count); - i_assert(count % 2 == 0); - for (i = 0; i < count; i += 2) { - str = p_strdup_printf(ctx->pool, "%s%s%c0%c%s", - str_c(ctx->prefix), - def->key, - SETTINGS_SEPARATOR, - SETTINGS_SEPARATOR, - strings[i]); - array_append(ctx->dest, &str, 1); - str = p_strdup(ctx->pool, strings[i+1]); - array_append(ctx->dest, &str, 1); - } - count = 0; - break; - } - } - if (str_len(ctx->value) > 0) { - key = p_strconcat(ctx->pool, str_c(ctx->prefix), - def->key, NULL); - if (hash_table_lookup(ctx->keys, key) == NULL) { - str = key; - array_append(ctx->dest, &str, 1); - str = p_strdup(ctx->pool, str_c(ctx->value)); - array_append(ctx->dest, &str, 1); - hash_table_insert(ctx->keys, key, key); - } - } - - prefix_len = str_len(ctx->prefix); - for (i = 0; i < count; i++) { - str_append(ctx->prefix, def->key); - str_append_c(ctx->prefix, SETTINGS_SEPARATOR); - str_printfa(ctx->prefix, "%u", i); - str_append_c(ctx->prefix, SETTINGS_SEPARATOR); - settings_export(ctx, def->list_info, children[i]); - - str_truncate(ctx->prefix, prefix_len); - } - } -} - -static void config_export(pool_t pool, ARRAY_TYPE(const_string) *dest) -{ - struct config_setting_parser_list *l; - struct settings_export_context ctx; - const void *set; - - memset(&ctx, 0, sizeof(ctx)); - ctx.pool = pool; - ctx.dest = dest; - ctx.export_defaults = FALSE; - ctx.value = t_str_new(256); - ctx.prefix = t_str_new(64); - 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 (l->parser != NULL) { - set = settings_parser_get(l->parser); - settings_export(&ctx, l->root, set); - } - } - hash_table_destroy(&ctx.keys); -} - static const char *info_type_name_find(const struct setting_parser_info *info) { unsigned int i; @@ -261,9 +71,10 @@ return t_strconcat(t_strdup_until(input->path, p+1), path, NULL); } -void config_parse_file(pool_t dest_pool, ARRAY_TYPE(const_string) *dest, - const char *path, const char *service) +void config_parse_file(const char *path, const char *service) { + 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); ARRAY_TYPE(const_string) auth_defaults; @@ -287,7 +98,12 @@ t_array_init(&pathlen_stack, 10); t_array_init(&auth_defaults, 32); - errormsg = config_parse_line(pool, "0", "auth=0", &info); + 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); + } + + errormsg = config_parse_line("0", "auth=0", &info); i_assert(errormsg == NULL); memset(&root, 0, sizeof(root)); @@ -411,10 +227,10 @@ str_truncate(str, 0); str_printfa(str, "auth/0/%s=%s", key + 5, line); - errormsg = config_parse_line(pool, key + 5, str_c(str), &info); + errormsg = config_parse_line(key + 5, str_c(str), &info); array_append(&auth_defaults, &s, 1); } else { - errormsg = config_parse_line(pool, key, str_c(str), &info); + errormsg = config_parse_line(key, str_c(str), &info); } } else if (strcmp(key, "}") != 0 || *line != '\0') { /* b) + errors */ @@ -458,7 +274,7 @@ if (cur_counter == 0 && strcmp(key, "auth") == 0) { /* already added this */ } else { - errormsg = config_parse_line(pool, key, + errormsg = config_parse_line(key, str_c(str), &info); } @@ -473,7 +289,7 @@ str_append(str, type_name); str_append_c(str, '='); str_append(str, name); - errormsg = config_parse_line(pool, type_name, + errormsg = config_parse_line(type_name, str_c(str), &info); str_truncate(str, pathlen); @@ -491,7 +307,7 @@ p = strchr(lines[i], '='); str_append(str, lines[i]); - errormsg = config_parse_line(pool, t_strdup_until(lines[i], p), str_c(str), &info); + errormsg = config_parse_line(t_strdup_until(lines[i], p), str_c(str), &info); i_assert(errormsg == NULL); } } @@ -528,14 +344,9 @@ goto prevfile; for (l = config_setting_parsers; l->module_name != NULL; l++) { - if (l->parser == NULL) - continue; - if (!settings_parser_check(l->parser, pool, &errormsg)) { i_fatal("Error in configuration file %s: %s", path, errormsg); } } - - config_export(dest_pool, dest); }
--- a/src/config/config-parser.h Thu Apr 30 14:48:54 2009 -0400 +++ b/src/config/config-parser.h Thu Apr 30 15:02:44 2009 -0400 @@ -1,7 +1,6 @@ #ifndef CONFIG_PARSER_H #define CONFIG_PARSER_H -void config_parse_file(pool_t dest_pool, ARRAY_TYPE(const_string) *dest, - const char *path, const char *service); +void config_parse_file(const char *path, const char *service); #endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/config/config-request.c Thu Apr 30 15:02:44 2009 -0400 @@ -0,0 +1,236 @@ +/* Copyright (C) 2005-2009 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "array.h" +#include "str.h" +#include "hash.h" +#include "ostream.h" +#include "settings-parser.h" +#include "all-settings.h" +#include "config-request.h" + +struct settings_export_context { + pool_t pool; + string_t *value; + string_t *prefix; + struct hash_table *keys; + bool export_defaults; + + config_request_callback_t *callback; + void *context; +}; + +static bool parsers_are_connected(struct setting_parser_info *root, + struct setting_parser_info *info) +{ + struct setting_parser_info *const *dep, *p; + + /* we're trying to find info or its parents from root's dependencies. */ + + for (p = info; p != NULL; p = p->parent) { + if (p == root) + return TRUE; + } + + if (root->dependencies != NULL) { + for (dep = root->dependencies; *dep != NULL; dep++) { + for (p = info; p != NULL; p = p->parent) { + if (p == *dep) + return TRUE; + } + } + } + return FALSE; +} + +static bool +config_setting_parser_is_in_service(struct config_setting_parser_list *list, + const char *service) +{ + struct config_setting_parser_list *l; + + if (strcmp(list->module_name, service) == 0) + return TRUE; + + for (l = config_setting_parsers; l->module_name != NULL; l++) { + if (strcmp(l->module_name, service) != 0) + continue; + + /* see if we can find a way to get from the original parser + to this parser */ + if (parsers_are_connected(l->root, list->root)) + return TRUE; + } + return FALSE; +} + +static void settings_export(struct settings_export_context *ctx, + const struct setting_parser_info *info, + const void *set) +{ + const struct setting_define *def; + const void *value, *default_value; + void *const *children = NULL; + unsigned int i, count, prefix_len; + const char *str; + char *key; + + for (def = info->defines; def->key != NULL; def++) { + value = CONST_PTR_OFFSET(set, def->offset); + default_value = info->defaults == NULL ? NULL : + CONST_PTR_OFFSET(info->defaults, def->offset); + + count = 0; + str_truncate(ctx->value, 0); + switch (def->type) { + case SET_INTERNAL: + break; + case SET_BOOL: { + const bool *val = value, *dval = default_value; + if (ctx->export_defaults || + dval == NULL || *val != *dval) { + str_append(ctx->value, + *val ? "yes" : "no"); + } + break; + } + case SET_UINT: { + const unsigned int *val = value, *dval = default_value; + if (ctx->export_defaults || + dval == NULL || *val != *dval) + str_printfa(ctx->value, "%u", *val); + break; + } + case SET_STR_VARS: { + const char *const *val = value, *sval; + const char *const *_dval = default_value; + const char *dval = _dval == NULL ? NULL : *_dval; + + i_assert(*val == NULL || + **val == SETTING_STRVAR_UNEXPANDED[0]); + + sval = *val == NULL ? NULL : (*val + 1); + if ((ctx->export_defaults || + null_strcmp(sval, dval) != 0) && sval != NULL) + str_append(ctx->value, sval); + break; + } + case SET_STR: { + const char *const *val = value; + const char *const *_dval = default_value; + const char *dval = _dval == NULL ? NULL : *_dval; + + if ((ctx->export_defaults || + null_strcmp(*val, dval) != 0) && *val != NULL) + str_append(ctx->value, *val); + break; + } + case SET_ENUM: { + const char *const *val = value; + const char *const *_dval = default_value; + const char *dval = _dval == NULL ? NULL : *_dval; + unsigned int len = strlen(*val); + + if (ctx->export_defaults || + strncmp(*val, dval, len) != 0 || + ((*val)[len] != ':' && (*val)[len] != '\0')) + str_append(ctx->value, *val); + break; + } + case SET_DEFLIST: { + const ARRAY_TYPE(void_array) *val = value; + + if (!array_is_created(val)) + break; + + children = array_get(val, &count); + for (i = 0; i < count; i++) { + if (i > 0) + str_append_c(ctx->value, ' '); + str_printfa(ctx->value, "%u", i); + } + break; + } + case SET_STRLIST: { + const ARRAY_TYPE(const_string) *val = value; + const char *const *strings; + + if (!array_is_created(val)) + break; + + key = p_strconcat(ctx->pool, str_c(ctx->prefix), + def->key, NULL); + + if (hash_table_lookup(ctx->keys, key) != NULL) { + /* already added all of these */ + break; + } + hash_table_insert(ctx->keys, key, key); + ctx->callback(key, "0", TRUE, ctx->context); + + strings = array_get(val, &count); + i_assert(count % 2 == 0); + for (i = 0; i < count; i += 2) { + str = p_strdup_printf(ctx->pool, "%s%s%c0%c%s", + str_c(ctx->prefix), + def->key, + SETTINGS_SEPARATOR, + SETTINGS_SEPARATOR, + strings[i]); + ctx->callback(str, strings[i+1], FALSE, + ctx->context); + } + count = 0; + break; + } + } + if (str_len(ctx->value) > 0) { + key = p_strconcat(ctx->pool, str_c(ctx->prefix), + def->key, NULL); + if (hash_table_lookup(ctx->keys, key) == NULL) { + ctx->callback(key, str_c(ctx->value), + def->type == SET_DEFLIST, + ctx->context); + hash_table_insert(ctx->keys, key, key); + } + } + + prefix_len = str_len(ctx->prefix); + for (i = 0; i < count; i++) { + str_append(ctx->prefix, def->key); + str_append_c(ctx->prefix, SETTINGS_SEPARATOR); + str_printfa(ctx->prefix, "%u", i); + str_append_c(ctx->prefix, SETTINGS_SEPARATOR); + settings_export(ctx, def->list_info, children[i]); + + str_truncate(ctx->prefix, prefix_len); + } + } +} + +void config_request_handle(const char *service, enum config_dump_flags flags, + config_request_callback_t *callback, void *context) +{ + struct config_setting_parser_list *l; + struct settings_export_context ctx; + + memset(&ctx, 0, sizeof(ctx)); + ctx.pool = pool_alloconly_create("config request", 10240); + ctx.callback = callback; + ctx.context = context; + ctx.export_defaults = (flags & CONFIG_DUMP_FLAG_DEFAULTS) != 0; + ctx.value = t_str_new(256); + ctx.prefix = t_str_new(64); + 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)) { + settings_export(&ctx, l->root, + settings_parser_get(l->parser)); + } + } + hash_table_destroy(&ctx.keys); + pool_unref(&ctx.pool); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/config/config-request.h Thu Apr 30 15:02:44 2009 -0400 @@ -0,0 +1,15 @@ +#ifndef CONFIG_REQUEST_H +#define CONFIG_REQUEST_H + +enum config_dump_flags { + CONFIG_DUMP_FLAG_HUMAN = 0x01, + CONFIG_DUMP_FLAG_DEFAULTS = 0x02 +}; + +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, + config_request_callback_t *callback, void *context); + +#endif
--- a/src/config/main.c Thu Apr 30 14:48:54 2009 -0400 +++ b/src/config/main.c Thu Apr 30 15:02:44 2009 -0400 @@ -1,26 +1,21 @@ /* Copyright (C) 2005-2009 Dovecot authors, see the included COPYING file */ -#include "common.h" +#include "lib.h" #include "array.h" #include "env-util.h" #include "master-service.h" #include "config-connection.h" #include "config-parser.h" +#include "config-request.h" #include <stdlib.h> #include <unistd.h> -ARRAY_TYPE(const_string) config_strings; - static struct master_service *service; -static pool_t config_pool; static void main_init(const char *service_name) { - config_pool = pool_alloconly_create("config parser", 10240); - p_array_init(&config_strings, config_pool, 256); - config_parse_file(config_pool, &config_strings, - master_service_get_config_path(service), + config_parse_file(master_service_get_config_path(service), service_name); } @@ -67,16 +62,16 @@ if (master_service_get_socket_count(service) > 0) master_service_run(service, client_connected); - else if (exec_args == NULL) - config_connection_dump_request(STDOUT_FILENO, "master", flags); - else { - config_connection_putenv(); + else if (exec_args == NULL) { + config_connection_dump_request(STDOUT_FILENO, + service_name, flags); + } else { + config_connection_putenv(service_name); env_put("DOVECONF_ENV=1"); execvp(exec_args[0], exec_args); i_fatal("execvp(%s) failed: %m", exec_args[0]); } config_connections_destroy_all(); - pool_unref(&config_pool); master_service_deinit(&service); return 0; }
--- a/src/config/settings-get.pl Thu Apr 30 14:48:54 2009 -0400 +++ b/src/config/settings-get.pl Thu Apr 30 15:02:44 2009 -0400 @@ -31,7 +31,8 @@ $state++; } elsif (/^(static )?struct setting_parser_info (.*) = {/) { $state++; - $parsers{$2} = 1; + my $name = $2; + $parsers{$name} = 1 if ($name !~ /\*/); } elsif (/^extern struct setting_parser_info (.*);/) { $externs .= "extern struct setting_parser_info $1;\n"; } elsif (/\/\* <settings checks> \*\//) {
--- a/src/imap/imap-settings.c Thu Apr 30 14:48:54 2009 -0400 +++ b/src/imap/imap-settings.c Thu Apr 30 15:02:44 2009 -0400 @@ -49,6 +49,11 @@ MEMBER(imap_id_log) "" }; +static struct setting_parser_info *imap_setting_dependencies[] = { + &mail_user_setting_parser_info, + NULL +}; + struct setting_parser_info imap_setting_parser_info = { MEMBER(defines) imap_setting_defines, MEMBER(defaults) &imap_default_settings, @@ -59,5 +64,6 @@ MEMBER(parent_offset) (size_t)-1, MEMBER(type_offset) (size_t)-1, MEMBER(struct_size) sizeof(struct imap_settings), - MEMBER(check_func) NULL + MEMBER(check_func) NULL, + MEMBER(dependencies) imap_setting_dependencies };
--- a/src/lib-lda/lda-settings.c Thu Apr 30 14:48:54 2009 -0400 +++ b/src/lib-lda/lda-settings.c Thu Apr 30 15:02:44 2009 -0400 @@ -2,6 +2,7 @@ #include "lib.h" #include "settings-parser.h" +#include "mail-storage-settings.h" #include "lda-settings.h" #include <stddef.h> @@ -42,6 +43,11 @@ MEMBER(lda_mailbox_autosubscribe) FALSE }; +static struct setting_parser_info *lda_setting_dependencies[] = { + &mail_user_setting_parser_info, + NULL +}; + struct setting_parser_info lda_setting_parser_info = { MEMBER(defines) lda_setting_defines, MEMBER(defaults) &lda_default_settings, @@ -53,10 +59,11 @@ MEMBER(type_offset) (size_t)-1, MEMBER(struct_size) sizeof(struct lda_settings), #ifdef CONFIG_BINARY - MEMBER(check_func) NULL + MEMBER(check_func) NULL, #else - MEMBER(check_func) lda_settings_check + MEMBER(check_func) lda_settings_check, #endif + MEMBER(dependencies) lda_setting_dependencies }; static bool lda_settings_check(void *_set, pool_t pool ATTR_UNUSED,
--- a/src/lib-settings/settings-parser.h Thu Apr 30 14:48:54 2009 -0400 +++ b/src/lib-settings/settings-parser.h Thu Apr 30 15:02:44 2009 -0400 @@ -58,6 +58,8 @@ size_t type_offset; size_t struct_size; bool (*check_func)(void *set, pool_t pool, const char **error_r); + struct setting_parser_info *const *dependencies; + }; ARRAY_DEFINE_TYPE(setting_parser_info, struct setting_parser_info);
--- a/src/pop3/pop3-settings.c Thu Apr 30 14:48:54 2009 -0400 +++ b/src/pop3/pop3-settings.c Thu Apr 30 15:02:44 2009 -0400 @@ -44,6 +44,11 @@ MEMBER(pop3_logout_format) "top=%t/%p, retr=%r/%b, del=%d/%m, size=%s" }; +static struct setting_parser_info *pop3_setting_dependencies[] = { + &mail_user_setting_parser_info, + NULL +}; + struct setting_parser_info pop3_setting_parser_info = { MEMBER(defines) pop3_setting_defines, MEMBER(defaults) &pop3_default_settings, @@ -54,5 +59,6 @@ MEMBER(parent_offset) (size_t)-1, MEMBER(type_offset) (size_t)-1, MEMBER(struct_size) sizeof(struct pop3_settings), - MEMBER(check_func) NULL + MEMBER(check_func) NULL, + MEMBER(dependencies) pop3_setting_dependencies };