From: Timo Sirainen Date: Mon, 13 Apr 2009 17:36:05 +0000 (-0400) Subject: Some cleanups to the config parsing code. X-Git-Tag: 2.0.alpha1~965 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3c00540a27bc1e7636ab2b52c3baae9ed9ec9aa6;p=thirdparty%2Fdovecot%2Fcore.git Some cleanups to the config parsing code. --HG-- branch : HEAD --- diff --git a/src/config/common.h b/src/config/common.h index 2a40691659..afdc06fbcb 100644 --- a/src/config/common.h +++ b/src/config/common.h @@ -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 diff --git a/src/config/config-connection.c b/src/config/config-connection.c index a8c2ebc86f..a2b8a83821 100644 --- a/src/config/config-connection.c +++ b/src/config/config-connection.c @@ -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; + /* [] */ - // 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; } diff --git a/src/config/config-connection.h b/src/config/config-connection.h index c451efd75b..e73fa7f040 100644 --- a/src/config/config-connection.h +++ b/src/config/config-connection.h @@ -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 diff --git a/src/config/config-parser.c b/src/config/config-parser.c index 39c45aa7f8..0afe071cef 100644 --- a/src/config/config-parser.c +++ b/src/config/config-parser.c @@ -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); } diff --git a/src/config/config-parser.h b/src/config/config-parser.h index cf42d95799..d565747347 100644 --- a/src/config/config-parser.h +++ b/src/config/config-parser.h @@ -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 diff --git a/src/config/main.c b/src/config/main.c index 32e863b76f..1fb048ffdc 100644 --- a/src/config/main.c +++ b/src/config/main.c @@ -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" @@ -11,43 +12,42 @@ #include #include -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;