#include "settings-parser.h"
#include "master-service.h"
#include "config-request.h"
+#include "config-parser.h"
#include "config-connection.h"
#include <stdlib.h>
o_stream_send_str(output, "\n");
}
-static void config_connection_request(struct config_connection *conn,
- const char *const *args)
+static int config_connection_request(struct config_connection *conn,
+ const char *const *args)
{
struct config_filter filter;
- const char *module = "";
+ const char *path, *error, *module = "";
/* [<args>] */
memset(&filter, 0, sizeof(filter));
}
}
+ if (strcmp(module, "master") == 0) {
+ /* master reads configuration only when reloading settings */
+ path = master_service_get_config_path(master_service);
+ if (config_parse_file(path, TRUE, &error) < 0) {
+ o_stream_send_str(conn->output,
+ t_strconcat("ERROR ", error, "\n", NULL));
+ config_connection_destroy(conn);
+ return -1;
+ }
+ }
+
o_stream_cork(conn->output);
config_request_handle(&filter, module, 0, config_request_output,
conn->output);
o_stream_send_str(conn->output, "\n");
o_stream_uncork(conn->output);
+ return 0;
}
static void config_connection_input(void *context)
while ((args = config_connection_next_line(conn)) != NULL) {
if (args[0] == NULL)
continue;
- if (strcmp(args[0], "REQ") == 0)
- config_connection_request(conn, args + 1);
+ if (strcmp(args[0], "REQ") == 0) {
+ if (config_connection_request(conn, args + 1) < 0)
+ break;
+ }
}
}
#include "strescape.h"
#include "istream.h"
#include "settings-parser.h"
+#include "all-settings.h"
#include "config-filter.h"
#include "config-parser.h"
ARRAY_DEFINE(all_parsers, struct config_filter_parser_list *);
/* parsers matching cur_filter */
ARRAY_TYPE(config_setting_parsers) cur_parsers;
+ struct config_setting_parser_list *root_parsers;
struct config_filter_stack *cur_filter;
struct input_stack *cur_input;
struct config_filter_context *filter;
};
+struct config_setting_parser_list *config_setting_parsers;
struct config_filter_context *config_filter;
static const char *info_type_name_find(const struct setting_parser_info *info)
cur_parsers = array_get(&ctx->cur_parsers, &count);
if (count == 0) {
/* first one */
- parser->parser_list = config_setting_parsers;
+ parser->parser_list = ctx->root_parsers;
} else {
/* duplicate the first settings list */
parser->parser_list =
return array_idx(&ctx->cur_parsers, 0);
}
-static void
+static int
config_filter_parser_list_check(struct parser_context *ctx,
- struct config_filter_parser_list *parser)
+ struct config_filter_parser_list *parser,
+ const char **error_r)
{
struct config_setting_parser_list *l = parser->parser_list;
const char *errormsg;
for (; l->module_name != NULL; l++) {
if (!settings_parser_check(l->parser, ctx->pool, &errormsg)) {
- i_fatal("Error in configuration file %s: %s",
+ *error_r = t_strdup_printf(
+ "Error in configuration file %s: %s",
ctx->path, errormsg);
+ return -1;
}
}
+ return 0;
}
-static void
-config_all_parsers_check(struct parser_context *ctx)
+static int
+config_all_parsers_check(struct parser_context *ctx, const char **error_r)
{
struct config_filter_parser_list *const *parsers;
unsigned int i, count;
parsers = array_get(&ctx->all_parsers, &count);
- for (i = 0; i < count; i++)
- config_filter_parser_list_check(ctx, parsers[i]);
+ for (i = 0; i < count; i++) {
+ if (config_filter_parser_list_check(ctx, parsers[i],
+ error_r) < 0)
+ return -1;
+ }
+ return 0;
}
static void
#endif
}
-void config_parse_file(const char *path, bool expand_files)
+int config_parse_file(const char *path, bool expand_files,
+ const char **error_r)
{
enum settings_parser_flags parser_flags =
SETTINGS_PARSER_FLAG_IGNORE_UNKNOWN_KEYS;
struct input_stack root;
ARRAY_TYPE(const_string) auth_defaults;
- struct config_setting_parser_list *l, *const *parsers;
+ struct config_setting_parser_list *const *parsers;
struct parser_context ctx;
unsigned int pathlen = 0;
- unsigned int counter = 0, auth_counter = 0, cur_counter;
+ unsigned int i, count, counter = 0, auth_counter = 0, cur_counter;
const char *errormsg, *name;
char *line, *key, *p;
- int fd, ret;
+ int fd, ret = 0;
string_t *str, *full_line;
size_t len;
+ fd = open(path, O_RDONLY);
+ if (fd < 0) {
+ *error_r = t_strdup_printf("open(%s) failed: %m", path);
+ return -1;
+ }
+
memset(&ctx, 0, sizeof(ctx));
ctx.pool = pool_alloconly_create("config file parser", 1024*64);
ctx.path = path;
- fd = open(path, O_RDONLY);
- if (fd < 0)
- i_fatal("open(%s) failed: %m", path);
-
- t_array_init(&auth_defaults, 32);
-
- for (l = config_setting_parsers; l->module_name != NULL; l++) {
- i_assert(l->parser == NULL);
- l->parser = settings_parser_init(ctx.pool, l->root, parser_flags);
+ for (count = 0; all_roots[count].module_name != NULL; count++) ;
+ ctx.root_parsers =
+ p_new(ctx.pool, struct config_setting_parser_list, count+1);
+ for (i = 0; i < count; i++) {
+ ctx.root_parsers[i].module_name = all_roots[i].module_name;
+ ctx.root_parsers[i].root = all_roots[i].root;
+ ctx.root_parsers[i].parser =
+ settings_parser_init(ctx.pool, all_roots[i].root,
+ parser_flags);
}
+ t_array_init(&auth_defaults, 32);
t_array_init(&ctx.cur_parsers, 128);
p_array_init(&ctx.all_parsers, ctx.pool, 128);
ctx.cur_filter = p_new(ctx.pool, struct config_filter_stack, 1);
while (IS_WHITE(*line)) line++;
}
- ret = 1;
if (strcmp(key, "!include_try") == 0 ||
strcmp(key, "!include") == 0) {
if (settings_include(&ctx, fix_relative_path(line, ctx.cur_input),
}
if (errormsg != NULL) {
- i_fatal("Error in configuration file %s line %d: %s",
+ *error_r = t_strdup_printf(
+ "Error in configuration file %s line %d: %s",
ctx.cur_input->path, ctx.cur_input->linenum,
errormsg);
+ ret = -1;
break;
}
str_truncate(full_line, 0);
if (line == NULL && ctx.cur_input != NULL)
goto prevfile;
- config_all_parsers_check(&ctx);
+ if (ret == 0) {
+ if (config_all_parsers_check(&ctx, error_r) < 0)
+ ret = -1;
+ }
+ if (ret < 0) {
+ pool_unref(&ctx.pool);
+ return -1;
+ }
+
+ if (config_filter != NULL)
+ config_filter_deinit(&config_filter);
+ config_setting_parsers = ctx.root_parsers;
(void)array_append_space(&ctx.all_parsers);
config_filter = config_filter_init(ctx.pool);
config_filter_add_all(config_filter, array_idx(&ctx.all_parsers, 0));
+ return 0;
}