# HG changeset patch # User Timo Sirainen # Date 1266041251 -7200 # Node ID c26002b81f57e7aedd3e49fd569abbe2e1b2a821 # Parent 951a90e95ebec900f54fcf8e1a0cab452f936723 config: $setting as value returns the setting's current value. diff -r 951a90e95ebe -r c26002b81f57 src/config/config-parser.c --- a/src/config/config-parser.c Sat Feb 13 07:25:56 2010 +0200 +++ b/src/config/config-parser.c Sat Feb 13 08:07:31 2010 +0200 @@ -11,6 +11,7 @@ #include "service-settings.h" #include "all-settings.h" #include "config-filter.h" +#include "config-request.h" #include "config-parser.h" #include @@ -53,6 +54,7 @@ struct input_stack *cur_input; struct config_filter_context *filter; + unsigned int expand_values:1; }; static const enum settings_parser_flags settings_parser_flags = @@ -445,6 +447,7 @@ CONFIG_LINE_TYPE_ERROR, CONFIG_LINE_TYPE_KEYVALUE, CONFIG_LINE_TYPE_KEYFILE, + CONFIG_LINE_TYPE_KEYVARIABLE, CONFIG_LINE_TYPE_SECTION_BEGIN, CONFIG_LINE_TYPE_SECTION_END, CONFIG_LINE_TYPE_INCLUDE, @@ -542,6 +545,10 @@ *value_r = line + 1; return CONFIG_LINE_TYPE_KEYFILE; } + if (*line == '$') { + *value_r = line + 1; + return CONFIG_LINE_TYPE_KEYVARIABLE; + } len = strlen(line); if (len > 0 && @@ -607,7 +614,71 @@ return ret; } -int config_parse_file(const char *path, bool expand_files, +static const void * +config_get_value(struct parser_context *ctx, const char *key, + enum setting_type *type_r) +{ + struct config_module_parser *l; + const void *value; + + for (l = ctx->cur_section->parsers; l->root != NULL; l++) { + value = settings_parse_get_value(l->parser, key, type_r); + if (value != NULL) + return value; + } + return NULL; +} + +static int config_write_value(struct parser_context *ctx, + string_t *str, enum config_line_type type, + const char *key, const char *value, + const char **errormsg_r) +{ + const void *var_value; + enum setting_type var_type; + bool dump; + + switch (type) { + case CONFIG_LINE_TYPE_KEYVALUE: + str_append(str, value); + break; + case CONFIG_LINE_TYPE_KEYFILE: + if (!ctx->expand_values) { + str_append_c(str, '<'); + str_append(str, value); + } else { + if (str_append_file(str, key, value, errormsg_r) < 0) { + /* file reading failed */ + return -1; + } + } + break; + case CONFIG_LINE_TYPE_KEYVARIABLE: + if (!ctx->expand_values) { + str_append_c(str, '$'); + str_append(str, value); + } else { + var_value = config_get_value(ctx, value, &var_type); + if (var_value == NULL) { + *errormsg_r = t_strconcat("Unknown variable: $", + value, NULL); + return -1; + } + if (!config_export_type(str, var_value, NULL, + var_type, TRUE, &dump)) { + *errormsg_r = t_strconcat("Invalid variable: $", + value, NULL); + return -1; + } + } + break; + default: + i_unreached(); + } + return 0; +} + +int config_parse_file(const char *path, bool expand_values, const char **error_r) { struct input_stack root; @@ -643,6 +714,7 @@ memset(&root, 0, sizeof(root)); root.path = path; ctx.cur_input = &root; + ctx.expand_values = expand_values; p_array_init(&ctx.all_parsers, ctx.pool, 128); ctx.cur_section = p_new(ctx.pool, struct config_section_stack, 1); @@ -666,19 +738,13 @@ break; case CONFIG_LINE_TYPE_KEYVALUE: case CONFIG_LINE_TYPE_KEYFILE: + case CONFIG_LINE_TYPE_KEYVARIABLE: str_truncate(str, pathlen); str_append(str, key); str_append_c(str, '='); - if (type != CONFIG_LINE_TYPE_KEYFILE) - str_append(str, value); - else if (!expand_files) { - str_append_c(str, '<'); - str_append(str, value); - } else if (str_append_file(str, key, value, &errormsg) < 0) { - /* file reading failed */ + if (config_write_value(&ctx, str, type, key, value, &errormsg) < 0) break; - } (void)config_apply_line(&ctx, key, str_c(str), NULL, &errormsg); break; case CONFIG_LINE_TYPE_SECTION_BEGIN: diff -r 951a90e95ebe -r c26002b81f57 src/config/config-parser.h --- a/src/config/config-parser.h Sat Feb 13 07:25:56 2010 +0200 +++ b/src/config/config-parser.h Sat Feb 13 08:07:31 2010 +0200 @@ -13,7 +13,7 @@ extern struct config_module_parser *config_module_parsers; extern struct config_filter_context *config_filter; -int config_parse_file(const char *path, bool expand_files, +int config_parse_file(const char *path, bool expand_values, const char **error_r); void config_parse_load_modules(void); diff -r 951a90e95ebe -r c26002b81f57 src/config/config-request.c --- a/src/config/config-request.c Sat Feb 13 07:25:56 2010 +0200 +++ b/src/config/config-request.c Sat Feb 13 08:07:31 2010 +0200 @@ -71,6 +71,91 @@ return FALSE; } +bool config_export_type(string_t *str, const void *value, + const void *default_value, + enum setting_type type, bool dump_default, + bool *dump_r) +{ + switch (type) { + case SET_BOOL: { + const bool *val = value, *dval = default_value; + + if (dump_default || dval == NULL || *val != *dval) + str_append(str, *val ? "yes" : "no"); + break; + } + case SET_SIZE: { + const uoff_t *val = value, *dval = default_value; + + if (dump_default || dval == NULL || *val != *dval) + str_printfa(str, "%llu", (unsigned long long)*val); + break; + } + case SET_UINT: + case SET_UINT_OCT: + case SET_TIME: { + const unsigned int *val = value, *dval = default_value; + + if (dump_default || dval == NULL || *val != *dval) { + switch (type) { + case SET_UINT_OCT: + str_printfa(str, "0%o", *val); + break; + case SET_TIME: + str_printfa(str, "%u s", *val); + break; + default: + str_printfa(str, "%u", *val); + break; + } + } + break; + } + case SET_STR_VARS: { + const char *const *val = value, *sval; + const char *const *_dval = default_value; + const char *dval = _dval == NULL ? NULL : *_dval; + + i_assert(*val == NULL || + **val == SETTING_STRVAR_UNEXPANDED[0]); + + sval = *val == NULL ? NULL : (*val + 1); + if ((dump_default || null_strcmp(sval, dval) != 0) && + sval != NULL) { + str_append(str, sval); + *dump_r = TRUE; + } + break; + } + case SET_STR: { + const char *const *val = value; + const char *const *_dval = default_value; + const char *dval = _dval == NULL ? NULL : *_dval; + + if ((dump_default || null_strcmp(*val, dval) != 0) && + *val != NULL) { + str_append(str, *val); + *dump_r = TRUE; + } + break; + } + case SET_ENUM: { + const char *const *val = value; + const char *const *_dval = default_value; + const char *dval = _dval == NULL ? NULL : *_dval; + unsigned int len = strlen(*val); + + if (dump_default || strncmp(*val, dval, len) != 0 || + ((*val)[len] != ':' && (*val)[len] != '\0')) + str_append(str, *val); + break; + } + default: + return FALSE; + } + return TRUE; +} + static void settings_export(struct settings_export_context *ctx, const struct setting_parser_info *info, @@ -120,80 +205,19 @@ count = 0; str_truncate(ctx->value, 0); switch (def->type) { - case SET_BOOL: { - const bool *val = value, *dval = default_value; - if (dump_default || dval == NULL || *val != *dval) { - str_append(ctx->value, - *val ? "yes" : "no"); - } - break; - } - case SET_SIZE: { - const uoff_t *val = value, *dval = default_value; - if (dump_default || dval == NULL || *val != *dval) { - str_printfa(ctx->value, "%llu", - (unsigned long long)*val); - } - break; - } + case SET_BOOL: + case SET_SIZE: case SET_UINT: case SET_UINT_OCT: - case SET_TIME: { - const unsigned int *val = value, *dval = default_value; - if (dump_default || dval == NULL || *val != *dval) { - switch (def->type) { - case SET_UINT_OCT: - str_printfa(ctx->value, "0%o", *val); - break; - case SET_TIME: - str_printfa(ctx->value, "%u s", *val); - break; - default: - str_printfa(ctx->value, "%u", *val); - break; - } - } + case SET_TIME: + case SET_STR_VARS: + case SET_STR: + case SET_ENUM: + if (!config_export_type(ctx->value, value, + default_value, def->type, + dump_default, &dump)) + i_unreached(); break; - } - case SET_STR_VARS: { - const char *const *val = value, *sval; - const char *const *_dval = default_value; - const char *dval = _dval == NULL ? NULL : *_dval; - - i_assert(*val == NULL || - **val == SETTING_STRVAR_UNEXPANDED[0]); - - sval = *val == NULL ? NULL : (*val + 1); - if ((dump_default || null_strcmp(sval, dval) != 0) && - sval != NULL) { - str_append(ctx->value, sval); - dump = TRUE; - } - break; - } - case SET_STR: { - const char *const *val = value; - const char *const *_dval = default_value; - const char *dval = _dval == NULL ? NULL : *_dval; - - if ((dump_default || null_strcmp(*val, dval) != 0) && - *val != NULL) { - str_append(ctx->value, *val); - dump = TRUE; - } - break; - } - case SET_ENUM: { - const char *const *val = value; - const char *const *_dval = default_value; - const char *dval = _dval == NULL ? NULL : *_dval; - unsigned int len = strlen(*val); - - if (dump_default || strncmp(*val, dval, len) != 0 || - ((*val)[len] != ':' && (*val)[len] != '\0')) - str_append(ctx->value, *val); - break; - } case SET_DEFLIST: case SET_DEFLIST_UNIQUE: { const ARRAY_TYPE(void_array) *val = value; diff -r 951a90e95ebe -r c26002b81f57 src/config/config-request.h --- a/src/config/config-request.h Sat Feb 13 07:25:56 2010 +0200 +++ b/src/config/config-request.h Sat Feb 13 08:07:31 2010 +0200 @@ -3,6 +3,8 @@ #include "config-filter.h" +enum setting_type; + enum config_dump_scope { /* Dump all settings */ CONFIG_DUMP_SCOPE_ALL, @@ -30,6 +32,10 @@ typedef void config_request_callback_t(const char *key, const char *value, enum config_key_type type, void *context); +bool config_export_type(string_t *str, const void *value, + const void *default_value, + enum setting_type type, bool dump_default, + bool *dump_r); int config_request_handle(const struct config_filter *filter, const char *module, enum config_dump_scope scope, enum config_dump_flags flags, diff -r 951a90e95ebe -r c26002b81f57 src/lib-settings/settings-parser.c --- a/src/lib-settings/settings-parser.c Sat Feb 13 07:25:56 2010 +0200 +++ b/src/lib-settings/settings-parser.c Sat Feb 13 08:07:31 2010 +0200 @@ -692,6 +692,22 @@ return settings_find_key(ctx, key, &def, &link); } +const void * +settings_parse_get_value(struct setting_parser_context *ctx, + const char *key, enum setting_type *type_r) +{ + const struct setting_define *def; + struct setting_link *link; + + if (!settings_find_key(ctx, key, &def, &link)) + return NULL; + if (link->set_struct == NULL) + return NULL; + + *type_r = def->type; + return STRUCT_MEMBER_P(link->set_struct, def->offset); +} + int settings_parse_line(struct setting_parser_context *ctx, const char *line) { const char *key, *value; diff -r 951a90e95ebe -r c26002b81f57 src/lib-settings/settings-parser.h --- a/src/lib-settings/settings-parser.h Sat Feb 13 07:25:56 2010 +0200 +++ b/src/lib-settings/settings-parser.h Sat Feb 13 08:07:31 2010 +0200 @@ -124,6 +124,10 @@ /* Returns TRUE if the given key is a valid setting. */ bool settings_parse_is_valid_key(struct setting_parser_context *ctx, const char *key); +/* Returns pointer to value for a key, or NULL if not found. */ +const void * +settings_parse_get_value(struct setting_parser_context *ctx, + const char *key, enum setting_type *type_r); /* Parse a single line. Returns 1 if OK, 0 if key is unknown, -1 if error. */ int settings_parse_line(struct setting_parser_context *ctx, const char *line); /* Parse data already read in input stream. */