]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
doveconf: Dump config to stdout even when there are errors, just show them afterwards.
authorTimo Sirainen <tss@iki.fi>
Fri, 22 Jan 2010 16:14:31 +0000 (18:14 +0200)
committerTimo Sirainen <tss@iki.fi>
Fri, 22 Jan 2010 16:14:31 +0000 (18:14 +0200)
--HG--
branch : HEAD

src/config/config-parser.c
src/config/config-request.c
src/config/config-request.h
src/config/doveconf.c

index 6d075237ff1a86f5dc022b503129ddeaf548b896..3747f8a4b5c2fa4fc90e84d9273e4eab31425383 100644 (file)
@@ -589,22 +589,22 @@ static int config_parse_finish(struct parser_context *ctx, const char **error_r)
 {
        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 @@ prevfile:
                                "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 @@ prevfile:
 
        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)
index 34407e9ea8ddada839bcae0ef0180b1493eaf8d8..d5c18349bff1965f683bca5df73a6d51f865dd62 100644 (file)
@@ -325,9 +325,14 @@ int config_request_handle(const struct config_filter *filter,
                        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;
+                               }
                        }
                }
        }
index 3cad6b7bfb046dad8631028636421b490d20bb78..f7bcad1e899710e9995013ee23cca932efdca434 100644 (file)
@@ -14,13 +14,17 @@ enum config_dump_scope {
 
 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,
index b9b09576e217a5d3ab7fb22ef150510cbcdef95f..0b9c99b8d5b91a9ec4a6db870337d95a4ae29f90 100644 (file)
@@ -25,6 +25,7 @@ ARRAY_DEFINE_TYPE(prefix_stack, struct prefix_stack);
 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 @@ config_request_get_strings(const char *key, const char *value,
                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 @@ static void prefix_stack_reset_str(ARRAY_TYPE(prefix_stack) *stack)
                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 @@ static void config_connection_request_human(struct ostream *output,
        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 @@ static void config_connection_request_human(struct ostream *output,
                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 @@ int main(int argc, char *argv[])
        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 @@ int main(int argc, char *argv[])
                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 @@ int main(int argc, char *argv[])
                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,