]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
config: $setting as value returns the setting's current value.
authorTimo Sirainen <tss@iki.fi>
Sat, 13 Feb 2010 06:07:31 +0000 (08:07 +0200)
committerTimo Sirainen <tss@iki.fi>
Sat, 13 Feb 2010 06:07:31 +0000 (08:07 +0200)
--HG--
branch : HEAD

src/config/config-parser.c
src/config/config-parser.h
src/config/config-request.c
src/config/config-request.h
src/lib-settings/settings-parser.c
src/lib-settings/settings-parser.h

index 58e0cd2222d270cad41a2f8584ef287499896e88..05d4141f750b2186f5de15e640eea37cc304f202 100644 (file)
@@ -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 <stdlib.h>
@@ -53,6 +54,7 @@ struct parser_context {
        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 @@ enum config_line_type {
        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 @@ config_parse_line(struct parser_context *ctx, char *line, string_t *full_line,
                        *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 @@ static int config_parse_finish(struct parser_context *ctx, const char **error_r)
        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 @@ int config_parse_file(const char *path, bool expand_files,
        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 @@ prevfile:
                        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:
index e84a5ebef43d76d5b84636eae646482e82a46773..47b9ee5fdcd9cb0465442dc529da0bb9feb0028d 100644 (file)
@@ -13,7 +13,7 @@ ARRAY_DEFINE_TYPE(config_module_parsers, struct config_module_parser *);
 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);
index 8b53e1f34804c5e785a21984acff5ea0134c234f..75875227dc80545850f52a6fff7b1daffb9aaa43 100644 (file)
@@ -71,6 +71,91 @@ config_module_parser_is_in_service(const struct config_module_parser *list,
        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 @@ settings_export(struct settings_export_context *ctx,
                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;
index f7bcad1e899710e9995013ee23cca932efdca434..bbc97b266a68fce95d1f36283ae682887d52b218 100644 (file)
@@ -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 @@ enum config_key_type {
 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,
index f1ca733fa8da5f35480b3b21932bac20817c9842..4f4f96cc5b466c65d0f8538e4e536edeb7f270ea 100644 (file)
@@ -692,6 +692,22 @@ bool settings_parse_is_valid_key(struct setting_parser_context *ctx,
        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;
index 7369ba402a0c6af09446ea4298312d2c9ffabc5a..217487428ebc689d89207455e0d388ee9c147c5d 100644 (file)
@@ -124,6 +124,10 @@ settings_parse_get_prev_info(struct setting_parser_context *ctx);
 /* 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. */