# HG changeset patch # User Timo Sirainen # Date 1264176871 -7200 # Node ID b01b9eff1f1561064c74f55dfe1a84f806373b15 # Parent f1a0f9a6616437ed5a4b1bf6c89fe674f6e520e6 doveconf: Dump config to stdout even when there are errors, just show them afterwards. diff -r f1a0f9a66164 -r b01b9eff1f15 src/config/config-parser.c --- a/src/config/config-parser.c Fri Jan 22 17:46:54 2010 +0200 +++ b/src/config/config-parser.c Fri Jan 22 18:14:31 2010 +0200 @@ -589,22 +589,22 @@ { struct config_filter_context *new_filter; const char *error; + int ret; new_filter = config_filter_init(ctx->pool); (void)array_append_space(&ctx->all_parsers); config_filter_add_all(new_filter, array_idx(&ctx->all_parsers, 0)); - if (config_all_parsers_check(ctx, new_filter, &error) < 0) { + if ((ret = config_all_parsers_check(ctx, new_filter, &error)) < 0) { *error_r = t_strdup_printf("Error in configuration file %s: %s", ctx->path, error); - return -1; } if (config_filter != NULL) config_filter_deinit(&config_filter); config_module_parsers = ctx->root_parsers; config_filter = new_filter; - return 0; + return ret; } int config_parse_file(const char *path, bool expand_files, @@ -735,7 +735,7 @@ "Error in configuration file %s line %d: %s", ctx.cur_input->path, ctx.cur_input->linenum, errormsg); - ret = -1; + ret = -2; break; } str_truncate(full_line, 0); @@ -748,11 +748,7 @@ if (ret == 0) ret = config_parse_finish(&ctx, error_r); - if (ret < 0) { - pool_unref(&ctx.pool); - return -1; - } - return 1; + return ret; } void config_parse_load_modules(void) diff -r f1a0f9a66164 -r b01b9eff1f15 src/config/config-request.c --- a/src/config/config-request.c Fri Jan 22 17:46:54 2010 +0200 +++ b/src/config/config-request.c Fri Jan 22 18:14:31 2010 +0200 @@ -325,9 +325,14 @@ settings_parse_var_skip(parser->parser); if (!settings_parser_check(parser->parser, ctx.pool, &error)) { - i_error("%s", error); - ret = -1; - break; + if ((flags & CONFIG_DUMP_FLAG_CALLBACK_ERRORS) != 0) { + callback(NULL, error, CONFIG_KEY_ERROR, + context); + } else { + i_error("%s", error); + ret = -1; + break; + } } } } diff -r f1a0f9a66164 -r b01b9eff1f15 src/config/config-request.h --- a/src/config/config-request.h Fri Jan 22 17:46:54 2010 +0200 +++ b/src/config/config-request.h Fri Jan 22 18:14:31 2010 +0200 @@ -14,13 +14,17 @@ enum config_dump_flags { CONFIG_DUMP_FLAG_CHECK_SETTINGS = 0x01, - CONFIG_DUMP_FLAG_HIDE_LIST_DEFAULTS = 0x02 + CONFIG_DUMP_FLAG_HIDE_LIST_DEFAULTS = 0x02, + /* Errors are reported using callback and they don't stop handling */ + CONFIG_DUMP_FLAG_CALLBACK_ERRORS = 0x04 }; enum config_key_type { CONFIG_KEY_NORMAL, CONFIG_KEY_LIST, - CONFIG_KEY_UNIQUE_KEY + CONFIG_KEY_UNIQUE_KEY, + /* error message is in value */ + CONFIG_KEY_ERROR }; typedef void config_request_callback_t(const char *key, const char *value, diff -r f1a0f9a66164 -r b01b9eff1f15 src/config/doveconf.c --- a/src/config/doveconf.c Fri Jan 22 17:46:54 2010 +0200 +++ b/src/config/doveconf.c Fri Jan 22 18:14:31 2010 +0200 @@ -25,6 +25,7 @@ struct config_request_get_string_ctx { pool_t pool; ARRAY_TYPE(const_string) strings; + ARRAY_TYPE(const_string) errors; }; #define LIST_KEY_PREFIX "\001" @@ -51,6 +52,10 @@ value = p_strdup_printf(ctx->pool, "%s/"UNIQUE_KEY_SUFFIX"%s=%s", t_strdup_until(key, p), p + 1, value); break; + case CONFIG_KEY_ERROR: + value = p_strdup(ctx->pool, value); + array_append(&ctx->errors, &value, 1); + return; } array_append(&ctx->strings, &value, 1); } @@ -100,10 +105,10 @@ s->str_pos = -1U; } -static void config_connection_request_human(struct ostream *output, - const struct config_filter *filter, - const char *module, - enum config_dump_scope scope) +static int config_connection_request_human(struct ostream *output, + const struct config_filter *filter, + const char *module, + enum config_dump_scope scope) { static const char *indent_str = " "; ARRAY_TYPE(const_string) prefixes_arr; @@ -116,14 +121,17 @@ unsigned int indent = 0, prefix_idx = -1U; string_t *list_prefix; bool unique_key; + int ret = 0; ctx.pool = pool_alloconly_create("config human strings", 10240); i_array_init(&ctx.strings, 256); + i_array_init(&ctx.errors, 256); if (config_request_handle(filter, module, scope, CONFIG_DUMP_FLAG_CHECK_SETTINGS | - CONFIG_DUMP_FLAG_HIDE_LIST_DEFAULTS, + CONFIG_DUMP_FLAG_HIDE_LIST_DEFAULTS | + CONFIG_DUMP_FLAG_CALLBACK_ERRORS, config_request_get_strings, &ctx) < 0) - return; + return -1; array_sort(&ctx.strings, config_string_cmp); strings = array_get(&ctx.strings, &count); @@ -231,21 +239,32 @@ o_stream_send_str(output, "}\n"); } + /* flush output before writing errors */ + o_stream_uncork(output); + array_foreach(&ctx.errors, strings) { + i_error("%s", *strings); + ret = -1; + } + array_free(&ctx.strings); + array_free(&ctx.errors); pool_unref(&ctx.pool); + return ret; } -static void config_dump_human(const struct config_filter *filter, - const char *module, - enum config_dump_scope scope) +static int config_dump_human(const struct config_filter *filter, + const char *module, + enum config_dump_scope scope) { struct ostream *output; + int ret; output = o_stream_create_fd(STDOUT_FILENO, 0, FALSE); o_stream_cork(output); - config_connection_request_human(output, filter, module, scope); + ret = config_connection_request_human(output, filter, module, scope); o_stream_uncork(output); o_stream_unref(&output); + return ret; } static void config_request_putenv(const char *key, const char *value, @@ -309,7 +328,7 @@ struct config_filter filter; const char *error; char **exec_args = NULL; - int c, ret; + int c, ret, ret2; memset(&filter, 0, sizeof(filter)); master_service = master_service_init("config", @@ -358,7 +377,8 @@ i_fatal("%s (copy example configs from "EXAMPLE_CONFIG_DIR"/)", error); } - if (ret <= 0) + + if (ret <= 0 && (exec_args != NULL || ret == -2)) i_fatal("%s", error); if (exec_args == NULL) { @@ -368,7 +388,14 @@ if (*info != '\0') printf("# %s\n", info); fflush(stdout); - config_dump_human(&filter, module, scope); + ret2 = config_dump_human(&filter, module, scope); + + if (ret < 0) { + /* delayed error */ + i_fatal("%s", error); + } + if (ret2 < 0) + i_fatal("Errors in configuration"); } else { env_put("DOVECONF_ENV=1"); if (config_request_handle(&filter, module,