From: Timo Sirainen Date: Tue, 27 Oct 2009 01:44:10 +0000 (-0400) Subject: doveconf -n/-a: Don't dump default service settings. X-Git-Tag: 2.0.alpha3~99 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d84c270231a617298088f597474a73f4a14921ae;p=thirdparty%2Fdovecot%2Fcore.git doveconf -n/-a: Don't dump default service settings. This code is just getting uglier and uglier.. --HG-- branch : HEAD --- diff --git a/src/config/config-connection.c b/src/config/config-connection.c index 08f0db2192..8d024c64e4 100644 --- a/src/config/config-connection.c +++ b/src/config/config-connection.c @@ -46,7 +46,7 @@ config_connection_next_line(struct config_connection *conn) static void config_request_output(const char *key, const char *value, - bool list ATTR_UNUSED, void *context) + enum config_key_type type ATTR_UNUSED, void *context) { struct ostream *output = context; const char *p; diff --git a/src/config/config-request.c b/src/config/config-request.c index ee92da2f02..b0f56f959b 100644 --- a/src/config/config-request.c +++ b/src/config/config-request.c @@ -71,9 +71,11 @@ config_module_parser_is_in_service(const struct config_module_parser *list, return FALSE; } -static void settings_export(struct settings_export_context *ctx, - const struct setting_parser_info *info, - const void *set, const void *change_set) +static void +settings_export(struct settings_export_context *ctx, + const struct setting_parser_info *info, + bool parent_unique_deflist, + const void *set, const void *change_set) { const struct setting_define *def; const void *value, *default_value, *change_value; @@ -104,6 +106,10 @@ static void settings_export(struct settings_export_context *ctx, hasn't changed, it's the default. even if info->defaults has a different value. */ default_value = value; + } else if (parent_unique_deflist) { + /* value is set explicitly, but we don't know the + default here. assume it's not the default. */ + dump_default = TRUE; } dump = FALSE; @@ -196,7 +202,7 @@ static void settings_export(struct settings_export_context *ctx, break; } hash_table_insert(ctx->keys, key, key); - ctx->callback(key, "0", TRUE, ctx->context); + ctx->callback(key, "0", CONFIG_KEY_LIST, ctx->context); strings = array_get(val, &count); i_assert(count % 2 == 0); @@ -207,8 +213,8 @@ static void settings_export(struct settings_export_context *ctx, SETTINGS_SEPARATOR, SETTINGS_SEPARATOR, strings[i]); - ctx->callback(str, strings[i+1], FALSE, - ctx->context); + ctx->callback(str, strings[i+1], + CONFIG_KEY_NORMAL, ctx->context); } count = 0; break; @@ -218,8 +224,16 @@ static void settings_export(struct settings_export_context *ctx, 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), - SETTING_TYPE_IS_DEFLIST(def->type), + enum config_key_type type; + + if (def->offset == info->type_offset && + parent_unique_deflist) + type = CONFIG_KEY_UNIQUE_KEY; + else if (SETTING_TYPE_IS_DEFLIST(def->type)) + type = CONFIG_KEY_LIST; + else + type = CONFIG_KEY_NORMAL; + ctx->callback(key, str_c(ctx->value), type, ctx->context); hash_table_insert(ctx->keys, key, key); } @@ -231,8 +245,9 @@ static void settings_export(struct settings_export_context *ctx, 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], - change_children[i]); + settings_export(ctx, def->list_info, + def->type == SET_DEFLIST_UNIQUE, + children[i], change_children[i]); str_truncate(ctx->prefix, prefix_len); } @@ -274,7 +289,7 @@ int config_request_handle(const struct config_filter *filter, !config_module_parser_is_in_service(parser, module)) continue; - settings_export(&ctx, parser->root, + settings_export(&ctx, parser->root, FALSE, settings_parser_get(parser->parser), settings_parser_get_changes(parser->parser)); diff --git a/src/config/config-request.h b/src/config/config-request.h index 38a403b73b..0c317628db 100644 --- a/src/config/config-request.h +++ b/src/config/config-request.h @@ -12,8 +12,14 @@ enum config_dump_scope { CONFIG_DUMP_SCOPE_CHANGED }; +enum config_key_type { + CONFIG_KEY_NORMAL, + CONFIG_KEY_LIST, + CONFIG_KEY_UNIQUE_KEY +}; + typedef void config_request_callback_t(const char *key, const char *value, - bool list, void *context); + enum config_key_type type, void *context); int config_request_handle(const struct config_filter *filter, const char *module, enum config_dump_scope scope, diff --git a/src/config/doveconf.c b/src/config/doveconf.c index 8ff44e432e..8fecba8e8a 100644 --- a/src/config/doveconf.c +++ b/src/config/doveconf.c @@ -4,6 +4,7 @@ #include "array.h" #include "env-util.h" #include "ostream.h" +#include "str.h" #include "settings-parser.h" #include "master-service.h" #include "all-settings.h" @@ -15,19 +16,42 @@ #include #include +struct prefix_stack { + unsigned int prefix_idx; + unsigned int str_pos; +}; +ARRAY_DEFINE_TYPE(prefix_stack, struct prefix_stack); + struct config_request_get_string_ctx { pool_t pool; ARRAY_TYPE(const_string) strings; }; +#define LIST_KEY_PREFIX "\001" +#define UNIQUE_KEY_SUFFIX "\xff" + static void config_request_get_strings(const char *key, const char *value, - bool list, void *context) + enum config_key_type type, void *context) { struct config_request_get_string_ctx *ctx = context; + const char *p; - value = p_strdup_printf(ctx->pool, list ? "-%s=%s" : "%s=%s", - key, value); + switch (type) { + case CONFIG_KEY_NORMAL: + value = p_strdup_printf(ctx->pool, "%s=%s", key, value); + break; + case CONFIG_KEY_LIST: + value = p_strdup_printf(ctx->pool, LIST_KEY_PREFIX"%s=%s", + key, value); + break; + case CONFIG_KEY_UNIQUE_KEY: + p = strrchr(key, '/'); + i_assert(p != NULL); + value = p_strdup_printf(ctx->pool, "%s/"UNIQUE_KEY_SUFFIX"%s=%s", + t_strdup_until(key, p), p + 1, value); + break; + } array_append(&ctx->strings, &value, 1); } @@ -46,18 +70,34 @@ static int config_string_cmp(const char *const *p1, const char *const *p2) return -1; if (s2[i] == '=') return 1; + return s1[i] - s2[i]; } -static unsigned int prefix_stack_pop(ARRAY_TYPE(uint) *stack) +static struct prefix_stack prefix_stack_pop(ARRAY_TYPE(prefix_stack) *stack) { - const unsigned int *indexes; - unsigned int idx, count; + const struct prefix_stack *s; + struct prefix_stack sc; + unsigned int count; - indexes = array_get(stack, &count); - idx = count <= 1 ? -1U : indexes[count-2]; + s = array_get(stack, &count); + i_assert(count > 0); + if (count == 1) { + sc.prefix_idx = -1U; + } else { + sc.prefix_idx = s[count-2].prefix_idx; + } + sc.str_pos = s[count-1].str_pos; array_delete(stack, count-1, 1); - return idx; + return sc; +} + +static void prefix_stack_reset_str(ARRAY_TYPE(prefix_stack) *stack) +{ + struct prefix_stack *s; + + array_foreach_modifiable(stack, s) + s->str_pos = -1U; } static void config_connection_request_human(struct ostream *output, @@ -65,14 +105,17 @@ static void config_connection_request_human(struct ostream *output, const char *module, enum config_dump_scope scope) { - static const char *ident_str = " "; + static const char *indent_str = " "; ARRAY_TYPE(const_string) prefixes_arr; - ARRAY_TYPE(uint) prefix_idx_stack; + ARRAY_TYPE(prefix_stack) prefix_stack; + struct prefix_stack prefix; struct config_request_get_string_ctx ctx; const char *const *strings, *const *args, *p, *str, *const *prefixes; const char *key, *key2, *value; unsigned int i, j, count, len, prefix_count, skip_len; unsigned int indent = 0, prefix_idx = -1U; + string_t *list_prefix; + bool unique_key; ctx.pool = pool_alloconly_create("config human strings", 10240); i_array_init(&ctx.strings, 256); @@ -84,7 +127,7 @@ static void config_connection_request_human(struct ostream *output, strings = array_get(&ctx.strings, &count); p_array_init(&prefixes_arr, ctx.pool, 32); - for (i = 0; i < count && strings[i][0] == '-'; i++) T_BEGIN { + for (i = 0; i < count && strings[i][0] == LIST_KEY_PREFIX[0]; i++) T_BEGIN { p = strchr(strings[i], '='); i_assert(p != NULL); for (args = t_strsplit(p + 1, " "); *args != NULL; args++) { @@ -96,22 +139,36 @@ static void config_connection_request_human(struct ostream *output, } T_END; prefixes = array_get(&prefixes_arr, &prefix_count); - p_array_init(&prefix_idx_stack, ctx.pool, 8); + list_prefix = str_new(ctx.pool, 128); + p_array_init(&prefix_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++; + + key = t_strdup_until(strings[i], value++); + unique_key = FALSE; + + p = strrchr(key, '/'); + if (p != NULL && p[1] == UNIQUE_KEY_SUFFIX[0]) { + key = t_strconcat(t_strdup_until(key, p + 1), + p + 2, NULL); + unique_key = TRUE; + } again: 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); + prefix = prefix_stack_pop(&prefix_stack); indent--; - o_stream_send(output, ident_str, indent*2); - o_stream_send_str(output, "}\n"); + if (prefix.str_pos != -1U) + str_truncate(list_prefix, prefix.str_pos); + else { + o_stream_send(output, indent_str, indent*2); + o_stream_send_str(output, "}\n"); + } + prefix_idx = prefix.prefix_idx; } else { /* keep the prefix */ j = prefix_idx + 1; @@ -123,31 +180,52 @@ static void config_connection_request_human(struct ostream *output, if (strncmp(prefixes[j], key, len) == 0) { key2 = key + (prefix_idx == -1U ? 0 : strlen(prefixes[prefix_idx])); - o_stream_send(output, ident_str, indent*2); - o_stream_send_str(output, t_strcut(key2, '/')); - o_stream_send_str(output, " {\n"); - indent++; + prefix.str_pos = !unique_key ? -1U : + str_len(list_prefix); prefix_idx = j; - array_append(&prefix_idx_stack, &prefix_idx, 1); - goto again; + prefix.prefix_idx = prefix_idx; + array_append(&prefix_stack, &prefix, 1); + + str_append_n(list_prefix, indent_str, indent*2); + p = strchr(key2, '/'); + if (p != NULL) + str_append_n(list_prefix, key2, p - key2); + else + str_append(list_prefix, key2); + if (unique_key) + str_printfa(list_prefix, " %s", value); + str_append(list_prefix, " {\n"); + indent++; + + if (unique_key) + goto end; + else + goto again; } } + o_stream_send(output, str_data(list_prefix), str_len(list_prefix)); + str_truncate(list_prefix, 0); + prefix_stack_reset_str(&prefix_stack); + skip_len = prefix_idx == -1U ? 0 : strlen(prefixes[prefix_idx]); i_assert(skip_len == 0 || strncmp(prefixes[prefix_idx], strings[i], skip_len) == 0); - o_stream_send(output, ident_str, indent*2); + o_stream_send(output, indent_str, indent*2); key = strings[i] + skip_len; + if (unique_key) key++; 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); + end: ; } T_END; while (prefix_idx != -1U) { - prefix_idx = prefix_stack_pop(&prefix_idx_stack); + prefix = prefix_stack_pop(&prefix_stack); + prefix_idx = prefix.prefix_idx; indent--; - o_stream_send(output, ident_str, indent*2); + o_stream_send(output, indent_str, indent*2); o_stream_send_str(output, "}\n"); } @@ -169,7 +247,7 @@ static void config_dump_human(const struct config_filter *filter, } static void config_request_putenv(const char *key, const char *value, - bool list ATTR_UNUSED, + enum config_key_type type ATTR_UNUSED, void *context ATTR_UNUSED) { T_BEGIN {