]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Some cleanups to the config parsing code.
authorTimo Sirainen <tss@iki.fi>
Mon, 13 Apr 2009 17:36:05 +0000 (13:36 -0400)
committerTimo Sirainen <tss@iki.fi>
Mon, 13 Apr 2009 17:36:05 +0000 (13:36 -0400)
--HG--
branch : HEAD

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/main.c

index 2a40691659bb3221221924fe78f32cb9ed2d496e..afdc06fbcbf4860571f30ccb0a6dd99a06fc55f1 100644 (file)
@@ -4,6 +4,6 @@
 #include "lib.h"
 
 extern struct master_service *service;
-extern string_t *config_string;
+extern ARRAY_TYPE(const_string) config_strings;
 
 #endif
index a8c2ebc86f64f4c2826e8372c0c71a5498c9c75e..a2b8a83821a445b49e1711b85aad52c96acae0c0 100644 (file)
@@ -1,6 +1,7 @@
 /* Copyright (C) 2005-2009 Dovecot authors, see the included COPYING file */
 
 #include "common.h"
+#include "array.h"
 #include "str.h"
 #include "ioloop.h"
 #include "network.h"
@@ -41,13 +42,24 @@ config_connection_next_line(struct config_connection *conn)
 }
 
 static void config_connection_request(struct config_connection *conn,
-                                     const char *const *args)
+                                     const char *const *args,
+                                     enum config_dump_flags flags)
 {
+       const char *const *strings;
+       unsigned int i, count;
+       string_t *str;
+
        /* <process> [<args>] */
-       // FIXME
-       o_stream_send(conn->output, str_data(config_string),
-                     str_len(config_string));
-       o_stream_flush(conn->output);
+       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));
+       }
+       o_stream_send_str(conn->output, "\n");
+       o_stream_uncork(conn->output);
 }
 
 static void config_connection_input(void *context)
@@ -86,7 +98,7 @@ static void config_connection_input(void *context)
                if (args[0] == NULL)
                        continue;
                if (strcmp(args[0], "REQ") == 0)
-                       config_connection_request(conn, args + 1);
+                       config_connection_request(conn, args + 1, 0);
        }
        t_pop();
 }
@@ -113,32 +125,25 @@ void config_connection_destroy(struct config_connection *conn)
        i_free(conn);
 }
 
-void config_connection_dump_request(int fd, const char *service)
+void config_connection_dump_request(int fd, const char *service,
+                                   enum config_dump_flags flags)
 {
        struct config_connection *conn;
        const char *args[2] = { service, NULL };
 
        conn = config_connection_create(fd);
-        config_connection_request(conn, args);
+        config_connection_request(conn, args, flags);
        config_connection_destroy(conn);
 }
 
 void config_connection_putenv(void)
 {
-       const char *env, *p, *key, *value;
-
-       env = str_c(config_string);
-       for (; *env != '\0'; env = p + 1) {
-               p = strchr(env, '\n');
-               if (env == p || p == NULL)
-                       break;
-
-               T_BEGIN {
-                       value = strchr(env, '=');
-                       i_assert(value != NULL && value < p);
-                       key = t_str_ucase(t_strdup_until(env, value));
-                       value = t_strdup_until(value, p);
-                       env_put(t_strconcat(key, value, NULL));
-               } T_END;
-       }
+       const char *const *strings;
+       unsigned int i, count;
+
+       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;
 }
index c451efd75b23eac6481038c787caa38faadfab31..e73fa7f0408865b12f3f9c17077a4131a5b837ac 100644 (file)
@@ -1,10 +1,16 @@
 #ifndef __CONFIG_CONNECTION_H
 #define __CONFIG_CONNECTION_H
 
+enum config_dump_flags {
+       CONFIG_DUMP_FLAG_HUMAN          = 0x01,
+       CONFIG_DUMP_FLAG_DEFAULTS       = 0x02
+};
+
 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);
+void config_connection_dump_request(int fd, const char *service,
+                                   enum config_dump_flags flags);
 void config_connection_putenv(void);
 
 #endif
index 39c45aa7f8f52169a24f6626ef953a12f288551d..0afe071cef1c6fb5c33859bb049d8806fdba507e 100644 (file)
@@ -52,11 +52,11 @@ config_parse_line(pool_t pool, const char *key, const char *line,
 }
 
 struct settings_export_context {
-       string_t *dest;
+       pool_t pool;
+       ARRAY_TYPE(const_string) *dest;
        string_t *value;
        string_t *prefix;
        struct hash_table *keys;
-       pool_t pool;
        bool export_defaults;
 };
 
@@ -68,6 +68,7 @@ static void settings_export(struct settings_export_context *ctx,
        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++) {
@@ -148,57 +149,50 @@ static void settings_export(struct settings_export_context *ctx,
                }
                case SET_STRLIST: {
                        const ARRAY_TYPE(const_string) *val = value;
-                       unsigned int pos = str_len(ctx->dest);
                        const char *const *strings;
 
                        if (!array_is_created(val))
                                break;
 
-                       str_append_str(ctx->dest, ctx->prefix);
-                       str_append(ctx->dest, def->key);
-                       str_append(ctx->dest, "=0\n");
+                       key = p_strconcat(ctx->pool, str_c(ctx->prefix),
+                                         def->key, NULL);
 
-                       if (hash_table_lookup(ctx->keys,
-                                             str_c(ctx->dest) + pos) != NULL) {
+                       if (hash_table_lookup(ctx->keys, key) != NULL) {
                                /* already added all of these */
-                               str_truncate(ctx->dest, pos);
                                break;
                        }
-                       key = p_strdup(ctx->pool, str_c(ctx->dest) + pos);
                        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_append_str(ctx->dest, ctx->prefix);
-                               str_append(ctx->dest, def->key);
-                               str_append_c(ctx->dest, SETTINGS_SEPARATOR);
-                               str_append_c(ctx->dest, '0');
-                               str_append_c(ctx->dest, SETTINGS_SEPARATOR);
-                               str_append(ctx->dest, strings[i+0]);
-                               str_append_c(ctx->dest, '=');
-                               str_append(ctx->dest, strings[i+1]);
-                               str_append_c(ctx->dest, '\n');
+                               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) {
-                       unsigned int pos = str_len(ctx->dest);
-                       str_append_str(ctx->dest, ctx->prefix);
-                       str_append(ctx->dest, def->key);
-
-                       if (hash_table_lookup(ctx->keys,
-                                             str_c(ctx->dest) + pos) != NULL) {
-                               /* already exists */
-                               str_truncate(ctx->dest, pos);
-                       } else {
-                               str_append_c(ctx->dest, '=');
-                               str_append_str(ctx->dest, ctx->value);
-                               str_append_c(ctx->dest, '\n');
-                               key = p_strconcat(ctx->pool, str_c(ctx->prefix),
-                                                 def->key, NULL);
+                       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);
                        }
                }
@@ -216,18 +210,18 @@ static void settings_export(struct settings_export_context *ctx,
        }
 }
 
-static void config_export(string_t *dest)
+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.pool = pool_alloconly_create("config keys", 10240);
        ctx.keys = hash_table_create(default_pool, ctx.pool, 0,
                                     str_hash, (hash_cmp_callback_t *)strcmp);
 
@@ -238,7 +232,6 @@ static void config_export(string_t *dest)
                }
        }
        hash_table_destroy(&ctx.keys);
-       pool_unref(&ctx.pool);
 }
 
 static const char *info_type_name_find(const struct setting_parser_info *info)
@@ -253,7 +246,8 @@ static const char *info_type_name_find(const struct setting_parser_info *info)
        return NULL;
 }
 
-void config_parse_file(string_t *dest, const char *path, const char *service)
+void config_parse_file(pool_t dest_pool, ARRAY_TYPE(const_string) *dest,
+                      const char *path, const char *service)
 {
        struct input_stack root, *input, *new_input;
        ARRAY_DEFINE(pathlen_stack, unsigned int);
@@ -268,7 +262,6 @@ void config_parse_file(string_t *dest, const char *path, const char *service)
        string_t *str, *full_line;
        size_t len;
        pool_t pool;
-       bool asis;
 
        pool = pool_alloconly_create("config file parser", 10240);
 
@@ -288,7 +281,7 @@ void config_parse_file(string_t *dest, const char *path, const char *service)
 
        str = t_str_new(256);
        full_line = t_str_new(512);
-       errormsg = NULL; ignore = 0; asis = FALSE;
+       errormsg = NULL; ignore = 0;
 newfile:
        input->input = i_stream_create_fd(fd, (size_t)-1, TRUE);
        i_stream_set_return_partial_line(input->input, TRUE);
@@ -403,10 +396,6 @@ prevfile:
                                str_printfa(str, "auth/0/%s=%s", key + 5, line);
                                errormsg = config_parse_line(pool, key + 5, str_c(str), &info);
                                array_append(&auth_defaults, &s, 1);
-                       } else if (asis) {
-                               /* don't do any parsing, just add it */
-                               str_append(dest, str_c(str));
-                               str_append_c(dest, '\n');
                        } else {
                                errormsg = config_parse_line(pool, key, str_c(str), &info);
                        }
@@ -497,7 +486,6 @@ prevfile:
 
                        if (ignore > 0)
                                ignore--;
-                       asis = FALSE;
 
                        arr = array_get(&pathlen_stack, &pathlen_count);
                        if (pathlen_count == 0)
@@ -532,5 +520,5 @@ prevfile:
                }
        }
 
-       config_export(dest);
+       config_export(dest_pool, dest);
 }
index cf42d9579970906a8c9a1cbb8d1b1097e4158c44..d5657473477b5e18e113942e9571a06b523be4b0 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef __CONFIG_PARSER_H
 #define __CONFIG_PARSER_H
 
-void config_parse_file(string_t *dest, const char *path, const char *service);
+void config_parse_file(pool_t dest_pool, ARRAY_TYPE(const_string) *dest,
+                      const char *path, const char *service);
 
 #endif
index 32e863b76ff7147c5bd7fadcae3195b239c53ddc..1fb048ffdcd082a2cee103fd1cb2018a4446d7f6 100644 (file)
@@ -3,6 +3,7 @@
 #include "common.h"
 #include "lib-signals.h"
 #include "ioloop.h"
+#include "array.h"
 #include "env-util.h"
 #include "str.h"
 #include "config-connection.h"
 #include <stdlib.h>
 #include <unistd.h>
 
-string_t *config_string;
-pool_t parsers_pool;
+ARRAY_TYPE(const_string) config_strings;
 
 static const char *config_path = SYSCONFDIR "/" PACKAGE ".conf";
+static pool_t config_pool;
 
 static void main_init(const char *service)
 {
        if (getenv("LOG_TO_MASTER") != NULL)
                i_set_failure_internal();
 
-       config_string = str_new(default_pool, 10240);
-       config_parse_file(config_string, config_path, service);
-       str_append_c(config_string, '\n');
+       config_pool = pool_alloconly_create("config parser", 10240);
+       p_array_init(&config_strings, config_pool, 256);
+       config_parse_file(config_pool, &config_strings, config_path, service);
 }
 
 int main(int argc, char *argv[])
 {
+       enum config_dump_flags flags = 0;
        struct ioloop *ioloop;
        const char *service = "";
        char **exec_args = NULL;
-       bool dump_nondefaults = FALSE, human_readable = FALSE;
        int i;
 
        lib_init();
 
        for (i = 1; i < argc; i++) {
                if (strcmp(argv[i], "-a") == 0) {
-                       /* FIXME: make it work */
-                       human_readable = TRUE;
+                       flags |= CONFIG_DUMP_FLAG_HUMAN |
+                               CONFIG_DUMP_FLAG_DEFAULTS;
                } else if (strcmp(argv[i], "-c") == 0) {
                        /* config file */
                        i++;
                        if (i == argc) i_fatal("Missing config file argument");
                        config_path = argv[i];
                } else if (strcmp(argv[i], "-n") == 0) {
-                       dump_nondefaults = TRUE;
-                       human_readable = TRUE;
+                       flags |= CONFIG_DUMP_FLAG_HUMAN;
                } else if (strcmp(argv[i], "-s") == 0) {
                        /* service */
                        i++;
@@ -67,13 +67,14 @@ int main(int argc, char *argv[])
        main_init(service);
        ioloop = io_loop_create();
        if (exec_args == NULL)
-               config_connection_dump_request(STDOUT_FILENO, "master");
+               config_connection_dump_request(STDOUT_FILENO, "master", flags);
        else {
                config_connection_putenv();
                env_put("DOVECONF_ENV=1");
                execvp(exec_args[0], exec_args);
                i_fatal("execvp(%s) failed: %m", exec_args[0]);
        }
+       pool_unref(&config_pool);
        io_loop_destroy(&ioloop);
        lib_deinit();
         return 0;