all-settings.c \
config-connection.c \
config-parser.c \
+ config-request.c \
main.c
noinst_HEADERS = \
all-settings.h \
- common.h \
config-connection.h \
config-parser.h
+++ /dev/null
-#ifndef COMMON_H
-#define COMMON_H
-
-#include "lib.h"
-
-extern ARRAY_TYPE(const_string) config_strings;
-
-#endif
/* Copyright (C) 2005-2009 Dovecot authors, see the included COPYING file */
-#include "common.h"
+#include "lib.h"
#include "array.h"
-#include "str.h"
#include "llist.h"
#include "ioloop.h"
#include "network.h"
#include "istream.h"
#include "ostream.h"
#include "env-util.h"
+#include "config-request.h"
#include "config-connection.h"
#include <stdlib.h>
#include <unistd.h>
-#include <fcntl.h>
#define MAX_INBUF_SIZE 1024
return t_strsplit(line, "\t");
}
+static void
+config_request_output(const char *key, const char *value,
+ bool list ATTR_UNUSED, void *context)
+{
+ struct ostream *output = context;
+
+ o_stream_send_str(output, key);
+ o_stream_send_str(output, "=");
+ o_stream_send_str(output, value);
+ o_stream_send_str(output, "\n");
+}
+
+struct config_request_get_string_ctx {
+ pool_t pool;
+ ARRAY_TYPE(const_string) strings;
+};
+
+static void
+config_request_get_strings(const char *key, const char *value,
+ bool list, void *context)
+{
+ struct config_request_get_string_ctx *ctx = context;
+
+ value = p_strdup_printf(ctx->pool, list ? "-%s=%s" : "%s=%s",
+ key, value);
+ array_append(&ctx->strings, &value, 1);
+}
+
+static int config_string_cmp(const void *p1, const void *p2)
+{
+ const char *s1 = *(const char *const *)p1;
+ const char *s2 = *(const char *const *)p2;
+ unsigned int i = 0;
+
+ while (s1[i] == s2[i]) {
+ if (s1[i] == '\0' || s1[i] == '=')
+ return 0;
+ i++;
+ }
+
+ if (s1[i] == '=')
+ return -1;
+ if (s2[i] == '=')
+ return 1;
+ return s1[i] - s2[i];
+}
+
+static unsigned int prefix_stack_pop(ARRAY_TYPE(uint) *stack)
+{
+ const unsigned int *indexes;
+ unsigned int idx, count;
+
+ indexes = array_get(stack, &count);
+ idx = count <= 1 ? -1U : indexes[count-2];
+ array_delete(stack, count-1, 1);
+ return idx;
+}
+
+static void config_connection_request_human(struct ostream *output,
+ const char *service,
+ enum config_dump_flags flags)
+{
+ static const char *ident_str = " ";
+ ARRAY_TYPE(const_string) prefixes_arr;
+ ARRAY_TYPE(uint) prefix_idx_stack;
+ struct config_request_get_string_ctx ctx;
+ const char **strings, *const *args, *p, *str, *const *prefixes;
+ const char *key, *value;
+ unsigned int i, j, count, len, prefix_count, skip_len;
+ unsigned int indent = 0, prefix_idx = -1U;
+
+ ctx.pool = pool_alloconly_create("config human strings", 10240);
+ i_array_init(&ctx.strings, 256);
+ config_request_handle(service, flags, config_request_get_strings, &ctx);
+
+ strings = array_get_modifiable(&ctx.strings, &count);
+ qsort(strings, count, sizeof(*strings), config_string_cmp);
+
+ p_array_init(&prefixes_arr, ctx.pool, 32);
+ for (i = 0; i < count && strings[i][0] == '-'; i++) T_BEGIN {
+ p = strchr(strings[i], '=');
+ i_assert(p != NULL);
+ for (args = t_strsplit(p + 1, " "); *args != NULL; args++) {
+ str = p_strdup_printf(ctx.pool, "%s/%s/",
+ t_strcut(strings[i]+1, '='),
+ *args);
+ array_append(&prefixes_arr, &str, 1);
+ }
+ } T_END;
+ prefixes = array_get(&prefixes_arr, &prefix_count);
+
+ p_array_init(&prefix_idx_stack, ctx.pool, 8);
+ for (; i < count; i++) T_BEGIN {
+ value = strchr(strings[i], '=');
+ i_assert(value != NULL);
+ key = t_strdup_until(strings[i], value);
+ value++;
+
+ j = 0;
+ while (prefix_idx != -1U) {
+ len = strlen(prefixes[prefix_idx]);
+ if (strncmp(prefixes[prefix_idx], key, len) != 0) {
+ prefix_idx = prefix_stack_pop(&prefix_idx_stack);
+ indent--;
+ o_stream_send(output, ident_str, indent*2);
+ o_stream_send_str(output, "}\n");
+ } else if (strchr(key + len, '/') == NULL) {
+ /* keep the prefix */
+ j = prefix_count;
+ break;
+ } else {
+ /* subprefix */
+ break;
+ }
+ }
+ for (; j < prefix_count; j++) {
+ len = strlen(prefixes[j]);
+ if (strncmp(prefixes[j], key, len) == 0 &&
+ strchr(key + len, '/') == NULL) {
+ key += prefix_idx == -1U ? 0 :
+ strlen(prefixes[prefix_idx]);
+ o_stream_send(output, ident_str, indent*2);
+ o_stream_send_str(output, t_strcut(key, '/'));
+ o_stream_send_str(output, " {\n");
+ indent++;
+ prefix_idx = j;
+ array_append(&prefix_idx_stack, &prefix_idx, 1);
+ break;
+ }
+ }
+ skip_len = prefix_idx == -1U ? 0 : strlen(prefixes[prefix_idx]);
+ i_assert(strncmp(prefixes[prefix_idx], strings[i], skip_len) == 0);
+ o_stream_send(output, ident_str, indent*2);
+ key = strings[i] + skip_len;
+ value = strchr(key, '=');
+ o_stream_send(output, key, value-key);
+ o_stream_send_str(output, " = ");
+ o_stream_send_str(output, value+1);
+ o_stream_send(output, "\n", 1);
+ } T_END;
+
+ while (prefix_idx != -1U) {
+ prefix_idx = prefix_stack_pop(&prefix_idx_stack);
+ indent--;
+ o_stream_send(output, ident_str, indent*2);
+ o_stream_send_str(output, "}\n");
+ }
+
+ array_free(&ctx.strings);
+ pool_unref(&ctx.pool);
+}
+
static void config_connection_request(struct config_connection *conn,
const char *const *args,
enum config_dump_flags flags)
{
- const char *const *strings;
- unsigned int i, count;
- string_t *str;
+ const char *service = "";
+
+ /* [<service> [<args>]] */
+ if (args[0] != NULL)
+ service = args[0];
- /* <process> [<args>] */
- 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));
+ if ((flags & CONFIG_DUMP_FLAG_HUMAN) == 0) {
+ config_request_handle(service, flags, config_request_output,
+ conn->output);
+ o_stream_send_str(conn->output, "\n");
+ } else {
+ config_connection_request_human(conn->output, service, flags);
}
- o_stream_send_str(conn->output, "\n");
o_stream_uncork(conn->output);
}
const char *args[2] = { service, NULL };
conn = config_connection_create(fd);
- config_connection_request(conn, args, flags);
+ config_connection_request(conn, args, flags);
config_connection_destroy(conn);
}
-void config_connection_putenv(void)
+static void config_request_putenv(const char *key, const char *value,
+ bool list ATTR_UNUSED,
+ void *context ATTR_UNUSED)
{
- 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_BEGIN {
+ env_put(t_strconcat(t_str_ucase(key), "=", value, NULL));
} T_END;
}
+void config_connection_putenv(const char *service)
+{
+ config_request_handle(service, 0, config_request_putenv, NULL);
+}
+
void config_connections_destroy_all(void)
{
while (config_connections != NULL)
#ifndef CONFIG_CONNECTION_H
#define CONFIG_CONNECTION_H
-enum config_dump_flags {
- CONFIG_DUMP_FLAG_HUMAN = 0x01,
- CONFIG_DUMP_FLAG_DEFAULTS = 0x02
-};
+enum config_dump_flags;
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,
enum config_dump_flags flags);
-void config_connection_putenv(void);
+void config_connection_putenv(const char *service);
void config_connections_destroy_all(void);
};
static const char *
-config_parse_line(pool_t pool, const char *key, const char *line,
+config_parse_line(const char *key, const char *line,
const struct setting_parser_info **info_r)
{
- enum settings_parser_flags parser_flags =
- SETTINGS_PARSER_FLAG_IGNORE_UNKNOWN_KEYS;
struct config_setting_parser_list *l;
bool found = FALSE;
int ret;
*info_r = NULL;
for (l = config_setting_parsers; l->module_name != NULL; l++) {
- if (l->parser == NULL) {
- l->parser = settings_parser_init(pool, l->root,
- parser_flags);
- }
-
ret = settings_parse_line(l->parser, line);
if (ret > 0) {
found = TRUE;
return found ? NULL : t_strconcat("Unknown setting: ", key, NULL);
}
-struct settings_export_context {
- pool_t pool;
- ARRAY_TYPE(const_string) *dest;
- string_t *value;
- string_t *prefix;
- struct hash_table *keys;
- bool export_defaults;
-};
-
-static void settings_export(struct settings_export_context *ctx,
- const struct setting_parser_info *info,
- const void *set)
-{
- const struct setting_define *def;
- 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++) {
- value = CONST_PTR_OFFSET(set, def->offset);
- default_value = info->defaults == NULL ? NULL :
- CONST_PTR_OFFSET(info->defaults, def->offset);
-
- count = 0;
- str_truncate(ctx->value, 0);
- switch (def->type) {
- case SET_INTERNAL:
- break;
- case SET_BOOL: {
- const bool *val = value, *dval = default_value;
- if (ctx->export_defaults ||
- dval == NULL || *val != *dval) {
- str_append(ctx->value,
- *val ? "yes" : "no");
- }
- break;
- }
- case SET_UINT: {
- const unsigned int *val = value, *dval = default_value;
- if (ctx->export_defaults ||
- dval == NULL || *val != *dval)
- str_printfa(ctx->value, "%u", *val);
- 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 ((ctx->export_defaults ||
- null_strcmp(sval, dval) != 0) && sval != NULL)
- str_append(ctx->value, sval);
- break;
- }
- case SET_STR: {
- const char *const *val = value;
- const char *const *_dval = default_value;
- const char *dval = _dval == NULL ? NULL : *_dval;
-
- if ((ctx->export_defaults ||
- null_strcmp(*val, dval) != 0) && *val != NULL)
- str_append(ctx->value, *val);
- 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 (ctx->export_defaults ||
- strncmp(*val, dval, len) != 0 ||
- ((*val)[len] != ':' && (*val)[len] != '\0'))
- str_append(ctx->value, *val);
- break;
- }
- case SET_DEFLIST: {
- const ARRAY_TYPE(void_array) *val = value;
-
- if (!array_is_created(val))
- break;
-
- children = array_get(val, &count);
- for (i = 0; i < count; i++) {
- if (i > 0)
- str_append_c(ctx->value, ' ');
- str_printfa(ctx->value, "%u", i);
- }
- break;
- }
- case SET_STRLIST: {
- const ARRAY_TYPE(const_string) *val = value;
- const char *const *strings;
-
- if (!array_is_created(val))
- break;
-
- key = p_strconcat(ctx->pool, str_c(ctx->prefix),
- def->key, NULL);
-
- if (hash_table_lookup(ctx->keys, key) != NULL) {
- /* already added all of these */
- break;
- }
- 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 = 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) {
- 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);
- }
- }
-
- prefix_len = str_len(ctx->prefix);
- for (i = 0; i < count; i++) {
- str_append(ctx->prefix, def->key);
- str_append_c(ctx->prefix, SETTINGS_SEPARATOR);
- str_printfa(ctx->prefix, "%u", i);
- str_append_c(ctx->prefix, SETTINGS_SEPARATOR);
- settings_export(ctx, def->list_info, children[i]);
-
- str_truncate(ctx->prefix, prefix_len);
- }
- }
-}
-
-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.keys = hash_table_create(default_pool, ctx.pool, 0,
- str_hash, (hash_cmp_callback_t *)strcmp);
-
- for (l = config_setting_parsers; l->module_name != NULL; l++) {
- if (l->parser != NULL) {
- set = settings_parser_get(l->parser);
- settings_export(&ctx, l->root, set);
- }
- }
- hash_table_destroy(&ctx.keys);
-}
-
static const char *info_type_name_find(const struct setting_parser_info *info)
{
unsigned int i;
return t_strconcat(t_strdup_until(input->path, p+1), path, NULL);
}
-void config_parse_file(pool_t dest_pool, ARRAY_TYPE(const_string) *dest,
- const char *path, const char *service)
+void config_parse_file(const char *path, const char *service)
{
+ enum settings_parser_flags parser_flags =
+ SETTINGS_PARSER_FLAG_IGNORE_UNKNOWN_KEYS;
struct input_stack root, *input, *new_input;
ARRAY_DEFINE(pathlen_stack, unsigned int);
ARRAY_TYPE(const_string) auth_defaults;
t_array_init(&pathlen_stack, 10);
t_array_init(&auth_defaults, 32);
- errormsg = config_parse_line(pool, "0", "auth=0", &info);
+ for (l = config_setting_parsers; l->module_name != NULL; l++) {
+ i_assert(l->parser == NULL);
+ l->parser = settings_parser_init(pool, l->root, parser_flags);
+ }
+
+ errormsg = config_parse_line("0", "auth=0", &info);
i_assert(errormsg == NULL);
memset(&root, 0, sizeof(root));
str_truncate(str, 0);
str_printfa(str, "auth/0/%s=%s", key + 5, line);
- errormsg = config_parse_line(pool, key + 5, str_c(str), &info);
+ errormsg = config_parse_line(key + 5, str_c(str), &info);
array_append(&auth_defaults, &s, 1);
} else {
- errormsg = config_parse_line(pool, key, str_c(str), &info);
+ errormsg = config_parse_line(key, str_c(str), &info);
}
} else if (strcmp(key, "}") != 0 || *line != '\0') {
/* b) + errors */
if (cur_counter == 0 && strcmp(key, "auth") == 0) {
/* already added this */
} else {
- errormsg = config_parse_line(pool, key,
+ errormsg = config_parse_line(key,
str_c(str), &info);
}
str_append(str, type_name);
str_append_c(str, '=');
str_append(str, name);
- errormsg = config_parse_line(pool, type_name,
+ errormsg = config_parse_line(type_name,
str_c(str), &info);
str_truncate(str, pathlen);
p = strchr(lines[i], '=');
str_append(str, lines[i]);
- errormsg = config_parse_line(pool, t_strdup_until(lines[i], p), str_c(str), &info);
+ errormsg = config_parse_line(t_strdup_until(lines[i], p), str_c(str), &info);
i_assert(errormsg == NULL);
}
}
goto prevfile;
for (l = config_setting_parsers; l->module_name != NULL; l++) {
- if (l->parser == NULL)
- continue;
-
if (!settings_parser_check(l->parser, pool, &errormsg)) {
i_fatal("Error in configuration file %s: %s",
path, errormsg);
}
}
-
- config_export(dest_pool, dest);
}
#ifndef CONFIG_PARSER_H
#define CONFIG_PARSER_H
-void config_parse_file(pool_t dest_pool, ARRAY_TYPE(const_string) *dest,
- const char *path, const char *service);
+void config_parse_file(const char *path, const char *service);
#endif
--- /dev/null
+/* Copyright (C) 2005-2009 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "array.h"
+#include "str.h"
+#include "hash.h"
+#include "ostream.h"
+#include "settings-parser.h"
+#include "all-settings.h"
+#include "config-request.h"
+
+struct settings_export_context {
+ pool_t pool;
+ string_t *value;
+ string_t *prefix;
+ struct hash_table *keys;
+ bool export_defaults;
+
+ config_request_callback_t *callback;
+ void *context;
+};
+
+static bool parsers_are_connected(struct setting_parser_info *root,
+ struct setting_parser_info *info)
+{
+ struct setting_parser_info *const *dep, *p;
+
+ /* we're trying to find info or its parents from root's dependencies. */
+
+ for (p = info; p != NULL; p = p->parent) {
+ if (p == root)
+ return TRUE;
+ }
+
+ if (root->dependencies != NULL) {
+ for (dep = root->dependencies; *dep != NULL; dep++) {
+ for (p = info; p != NULL; p = p->parent) {
+ if (p == *dep)
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+static bool
+config_setting_parser_is_in_service(struct config_setting_parser_list *list,
+ const char *service)
+{
+ struct config_setting_parser_list *l;
+
+ if (strcmp(list->module_name, service) == 0)
+ return TRUE;
+
+ for (l = config_setting_parsers; l->module_name != NULL; l++) {
+ if (strcmp(l->module_name, service) != 0)
+ continue;
+
+ /* see if we can find a way to get from the original parser
+ to this parser */
+ if (parsers_are_connected(l->root, list->root))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void settings_export(struct settings_export_context *ctx,
+ const struct setting_parser_info *info,
+ const void *set)
+{
+ const struct setting_define *def;
+ 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++) {
+ value = CONST_PTR_OFFSET(set, def->offset);
+ default_value = info->defaults == NULL ? NULL :
+ CONST_PTR_OFFSET(info->defaults, def->offset);
+
+ count = 0;
+ str_truncate(ctx->value, 0);
+ switch (def->type) {
+ case SET_INTERNAL:
+ break;
+ case SET_BOOL: {
+ const bool *val = value, *dval = default_value;
+ if (ctx->export_defaults ||
+ dval == NULL || *val != *dval) {
+ str_append(ctx->value,
+ *val ? "yes" : "no");
+ }
+ break;
+ }
+ case SET_UINT: {
+ const unsigned int *val = value, *dval = default_value;
+ if (ctx->export_defaults ||
+ dval == NULL || *val != *dval)
+ str_printfa(ctx->value, "%u", *val);
+ 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 ((ctx->export_defaults ||
+ null_strcmp(sval, dval) != 0) && sval != NULL)
+ str_append(ctx->value, sval);
+ break;
+ }
+ case SET_STR: {
+ const char *const *val = value;
+ const char *const *_dval = default_value;
+ const char *dval = _dval == NULL ? NULL : *_dval;
+
+ if ((ctx->export_defaults ||
+ null_strcmp(*val, dval) != 0) && *val != NULL)
+ str_append(ctx->value, *val);
+ 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 (ctx->export_defaults ||
+ strncmp(*val, dval, len) != 0 ||
+ ((*val)[len] != ':' && (*val)[len] != '\0'))
+ str_append(ctx->value, *val);
+ break;
+ }
+ case SET_DEFLIST: {
+ const ARRAY_TYPE(void_array) *val = value;
+
+ if (!array_is_created(val))
+ break;
+
+ children = array_get(val, &count);
+ for (i = 0; i < count; i++) {
+ if (i > 0)
+ str_append_c(ctx->value, ' ');
+ str_printfa(ctx->value, "%u", i);
+ }
+ break;
+ }
+ case SET_STRLIST: {
+ const ARRAY_TYPE(const_string) *val = value;
+ const char *const *strings;
+
+ if (!array_is_created(val))
+ break;
+
+ key = p_strconcat(ctx->pool, str_c(ctx->prefix),
+ def->key, NULL);
+
+ if (hash_table_lookup(ctx->keys, key) != NULL) {
+ /* already added all of these */
+ break;
+ }
+ hash_table_insert(ctx->keys, key, key);
+ ctx->callback(key, "0", TRUE, ctx->context);
+
+ strings = array_get(val, &count);
+ i_assert(count % 2 == 0);
+ for (i = 0; i < count; i += 2) {
+ str = p_strdup_printf(ctx->pool, "%s%s%c0%c%s",
+ str_c(ctx->prefix),
+ def->key,
+ SETTINGS_SEPARATOR,
+ SETTINGS_SEPARATOR,
+ strings[i]);
+ ctx->callback(str, strings[i+1], FALSE,
+ ctx->context);
+ }
+ count = 0;
+ break;
+ }
+ }
+ if (str_len(ctx->value) > 0) {
+ key = p_strconcat(ctx->pool, str_c(ctx->prefix),
+ def->key, NULL);
+ if (hash_table_lookup(ctx->keys, key) == NULL) {
+ ctx->callback(key, str_c(ctx->value),
+ def->type == SET_DEFLIST,
+ ctx->context);
+ hash_table_insert(ctx->keys, key, key);
+ }
+ }
+
+ prefix_len = str_len(ctx->prefix);
+ for (i = 0; i < count; i++) {
+ str_append(ctx->prefix, def->key);
+ str_append_c(ctx->prefix, SETTINGS_SEPARATOR);
+ str_printfa(ctx->prefix, "%u", i);
+ str_append_c(ctx->prefix, SETTINGS_SEPARATOR);
+ settings_export(ctx, def->list_info, children[i]);
+
+ str_truncate(ctx->prefix, prefix_len);
+ }
+ }
+}
+
+void config_request_handle(const char *service, enum config_dump_flags flags,
+ config_request_callback_t *callback, void *context)
+{
+ struct config_setting_parser_list *l;
+ struct settings_export_context ctx;
+
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.pool = pool_alloconly_create("config request", 10240);
+ ctx.callback = callback;
+ ctx.context = context;
+ ctx.export_defaults = (flags & CONFIG_DUMP_FLAG_DEFAULTS) != 0;
+ ctx.value = t_str_new(256);
+ ctx.prefix = t_str_new(64);
+ ctx.keys = hash_table_create(default_pool, ctx.pool, 0,
+ str_hash, (hash_cmp_callback_t *)strcmp);
+
+ for (l = config_setting_parsers; l->module_name != NULL; l++) {
+ if (*service == '\0' ||
+ config_setting_parser_is_in_service(l, service)) {
+ settings_export(&ctx, l->root,
+ settings_parser_get(l->parser));
+ }
+ }
+ hash_table_destroy(&ctx.keys);
+ pool_unref(&ctx.pool);
+}
--- /dev/null
+#ifndef CONFIG_REQUEST_H
+#define CONFIG_REQUEST_H
+
+enum config_dump_flags {
+ CONFIG_DUMP_FLAG_HUMAN = 0x01,
+ CONFIG_DUMP_FLAG_DEFAULTS = 0x02
+};
+
+typedef void config_request_callback_t(const char *key, const char *value,
+ bool list, void *context);
+
+void config_request_handle(const char *service, enum config_dump_flags flags,
+ config_request_callback_t *callback, void *context);
+
+#endif
/* Copyright (C) 2005-2009 Dovecot authors, see the included COPYING file */
-#include "common.h"
+#include "lib.h"
#include "array.h"
#include "env-util.h"
#include "master-service.h"
#include "config-connection.h"
#include "config-parser.h"
+#include "config-request.h"
#include <stdlib.h>
#include <unistd.h>
-ARRAY_TYPE(const_string) config_strings;
-
static struct master_service *service;
-static pool_t config_pool;
static void main_init(const char *service_name)
{
- config_pool = pool_alloconly_create("config parser", 10240);
- p_array_init(&config_strings, config_pool, 256);
- config_parse_file(config_pool, &config_strings,
- master_service_get_config_path(service),
+ config_parse_file(master_service_get_config_path(service),
service_name);
}
if (master_service_get_socket_count(service) > 0)
master_service_run(service, client_connected);
- else if (exec_args == NULL)
- config_connection_dump_request(STDOUT_FILENO, "master", flags);
- else {
- config_connection_putenv();
+ else if (exec_args == NULL) {
+ config_connection_dump_request(STDOUT_FILENO,
+ service_name, flags);
+ } else {
+ config_connection_putenv(service_name);
env_put("DOVECONF_ENV=1");
execvp(exec_args[0], exec_args);
i_fatal("execvp(%s) failed: %m", exec_args[0]);
}
config_connections_destroy_all();
- pool_unref(&config_pool);
master_service_deinit(&service);
return 0;
}
$state++;
} elsif (/^(static )?struct setting_parser_info (.*) = {/) {
$state++;
- $parsers{$2} = 1;
+ my $name = $2;
+ $parsers{$name} = 1 if ($name !~ /\*/);
} elsif (/^extern struct setting_parser_info (.*);/) {
$externs .= "extern struct setting_parser_info $1;\n";
} elsif (/\/\* <settings checks> \*\//) {
MEMBER(imap_id_log) ""
};
+static struct setting_parser_info *imap_setting_dependencies[] = {
+ &mail_user_setting_parser_info,
+ NULL
+};
+
struct setting_parser_info imap_setting_parser_info = {
MEMBER(defines) imap_setting_defines,
MEMBER(defaults) &imap_default_settings,
MEMBER(parent_offset) (size_t)-1,
MEMBER(type_offset) (size_t)-1,
MEMBER(struct_size) sizeof(struct imap_settings),
- MEMBER(check_func) NULL
+ MEMBER(check_func) NULL,
+ MEMBER(dependencies) imap_setting_dependencies
};
#include "lib.h"
#include "settings-parser.h"
+#include "mail-storage-settings.h"
#include "lda-settings.h"
#include <stddef.h>
MEMBER(lda_mailbox_autosubscribe) FALSE
};
+static struct setting_parser_info *lda_setting_dependencies[] = {
+ &mail_user_setting_parser_info,
+ NULL
+};
+
struct setting_parser_info lda_setting_parser_info = {
MEMBER(defines) lda_setting_defines,
MEMBER(defaults) &lda_default_settings,
MEMBER(type_offset) (size_t)-1,
MEMBER(struct_size) sizeof(struct lda_settings),
#ifdef CONFIG_BINARY
- MEMBER(check_func) NULL
+ MEMBER(check_func) NULL,
#else
- MEMBER(check_func) lda_settings_check
+ MEMBER(check_func) lda_settings_check,
#endif
+ MEMBER(dependencies) lda_setting_dependencies
};
static bool lda_settings_check(void *_set, pool_t pool ATTR_UNUSED,
size_t type_offset;
size_t struct_size;
bool (*check_func)(void *set, pool_t pool, const char **error_r);
+ struct setting_parser_info *const *dependencies;
+
};
ARRAY_DEFINE_TYPE(setting_parser_info, struct setting_parser_info);
MEMBER(pop3_logout_format) "top=%t/%p, retr=%r/%b, del=%d/%m, size=%s"
};
+static struct setting_parser_info *pop3_setting_dependencies[] = {
+ &mail_user_setting_parser_info,
+ NULL
+};
+
struct setting_parser_info pop3_setting_parser_info = {
MEMBER(defines) pop3_setting_defines,
MEMBER(defaults) &pop3_default_settings,
MEMBER(parent_offset) (size_t)-1,
MEMBER(type_offset) (size_t)-1,
MEMBER(struct_size) sizeof(struct pop3_settings),
- MEMBER(check_func) NULL
+ MEMBER(check_func) NULL,
+ MEMBER(dependencies) pop3_setting_dependencies
};