config-parser.c revision ebded144e74a668973ec9ba6e7e169d4e6dc766c
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi/* Copyright (C) 2005-2009 Dovecot authors, see the included COPYING file */
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi unsigned int pathlen;
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi const char *path;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi unsigned int linenum;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi const char *path;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi ARRAY_DEFINE(all_parsers, struct config_filter_parser_list *);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi /* parsers matching cur_filter */
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomistatic const char *info_type_name_find(const struct setting_parser_info *info)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi unsigned int i;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi i_panic("setting parser: Invalid type_offset value");
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomistatic void config_add_type(struct setting_parser_context *parser,
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi const char *p;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomistatic const char *
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomiconfig_parsers_parse_line(struct config_setting_parser_list *parsers,
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi } else if (ret < 0)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi return found ? NULL : t_strconcat("Unknown setting: ", key, NULL);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomistatic const char *
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomiconfig_parse_line(struct config_setting_parser_list *const *all_parsers,
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi const char *key, const char *line, const char *section_name)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi const char *ret;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi ret = config_parsers_parse_line(*all_parsers, key, line,
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomistatic const char *
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomifix_relative_path(const char *path, struct input_stack *input)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi const char *p;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi return t_strconcat(t_strdup_until(input->path, p+1), path, NULL);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi unsigned int i, count;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi for (count = 0; src[count].module_name != NULL; count++) ;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi dest = p_new(pool, struct config_setting_parser_list, count + 1);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi for (i = 0; i < count; i++) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi dest[i].parser = settings_parser_dup(src[i].parser, pool);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi struct config_setting_parser_list *const *cur_parsers;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi unsigned int count;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi parser = p_new(ctx->pool, struct config_filter_parser_list, 1);
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi cur_parsers = array_get(&ctx->cur_parsers, &count);
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi /* first one */
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi /* duplicate the first settings list */
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomistatic void config_add_new_filter(struct parser_context *ctx)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi filter = p_new(ctx->pool, struct config_filter_stack, 1);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomistatic struct config_setting_parser_list *const *
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomiconfig_update_cur_parsers(struct parser_context *ctx)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi struct config_filter_parser_list *const *all_parsers;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi unsigned int i, count;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi all_parsers = array_get(&ctx->all_parsers, &count);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi for (i = 0; i < count; i++) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (!config_filter_match(&ctx->cur_filter->filter,
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomiconfig_filter_parser_list_check(struct parser_context *ctx,
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi struct config_setting_parser_list *l = parser->parser_list;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (!settings_parser_check(l->parser, ctx->pool, &errormsg)) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomiconfig_all_parsers_check(struct parser_context *ctx)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi unsigned int i, count;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi for (i = 0; i < count; i++)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomistr_append_file(string_t *str, const char *key, const char *path,
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi const char **error_r)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi *error_r = t_strdup_printf("%s: Can't open file %s: %m",
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi *error_r = t_strdup_printf("%s: read(%s) failed: %m",
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomivoid config_parse_file(const char *path, bool expand_files)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi struct config_setting_parser_list *l, *const *parsers;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi unsigned int pathlen = 0;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi unsigned int counter = 0, auth_counter = 0, cur_counter;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi ctx.pool = pool_alloconly_create("config file parser", 1024*64);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi for (l = config_setting_parsers; l->module_name != NULL; l++) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi l->parser = settings_parser_init(ctx.pool, l->root, parser_flags);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi ctx.cur_filter = p_new(ctx.pool, struct config_filter_stack, 1);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi errormsg = config_parse_line(parsers, "0", "auth=0", NULL);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi errormsg = config_parse_line(parsers, "name", "auth/0/name=default", NULL);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi ctx.cur_input->input = i_stream_create_fd(fd, (size_t)-1, TRUE);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi i_stream_set_return_partial_line(ctx.cur_input->input, TRUE);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi while ((line = i_stream_read_next_line(ctx.cur_input->input)) != NULL) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi /* @UNSAFE: line is modified */
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi /* skip whitespace */
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi /* ignore comments or empty lines */
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi /* strip away comments. pretty kludgy way really.. */
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (*p == '\0')
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi } else if (*p == '#') {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi /* remove whitespace from end of line */
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi /* continues in next line */
03c6532fe7aa3ddae23c99ff6bec78d8dd2e8165Aki Tuomi /* a) key = value
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi b) section_type [section_name] {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi while (!IS_WHITE(*line) && *line != '\0' && *line != '=')
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi const char *path;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi for (tmp = ctx.cur_input; tmp != NULL; tmp = tmp->prev) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi /* failed, but ignore failures with include_try. */
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi /* file reading failed */
03c6532fe7aa3ddae23c99ff6bec78d8dd2e8165Aki Tuomi } else if (pathlen == 0 &&
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi /* verify that the setting is valid,
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi but delay actually adding it */
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi errormsg = config_parse_line(parsers, key + 5, str_c(str), NULL);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi errormsg = config_parse_line(parsers, key, str_c(str), NULL);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi } else if (strcmp(key, "}") != 0 || *line != '\0') {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi /* b) + errors */
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (net_parse_range(name, &ctx.cur_filter->filter.local_net,
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (net_parse_range(name, &ctx.cur_filter->filter.remote_net,
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (cur_counter == 0 && strcmp(name, "default") != 0)
03c6532fe7aa3ddae23c99ff6bec78d8dd2e8165Aki Tuomi if (cur_counter == 0 && strcmp(key, "auth") == 0) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi /* already added this */
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi errormsg = config_parse_line(parsers, key, str_c(str), name);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (strcmp(key, "auth") == 0 && errormsg == NULL) {
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi /* add auth default settings */
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi const char *const *lines;
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi unsigned int i, count;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi for (i = 0; i < count; i++) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi errormsg = config_parse_line(parsers, t_strdup_until(lines[i], p), str_c(str), NULL);
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi i_fatal("Error in configuration file %s line %d: %s",