bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
885673616ab8dc038eafdf76efe4184ecffcdc88Timo Sirainen#define SECTION_ERRORMSG "%s (section changed in %s at line %d)"
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainensettings_section_callback_t *null_settings_section_callback = NULL;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenstatic const char *get_bool(const char *value, bool *result)
9e49712b9cddbf47568ea4f3676e59b151489356Timo Sirainen return t_strconcat("Invalid boolean: ", value, NULL);
9e49712b9cddbf47568ea4f3676e59b151489356Timo Sirainenstatic const char *get_uint(const char *value, unsigned int *result)
bd8b391d7d2112e989963980663ef8cb0469b35cTimo Sirainen if (sscanf(value, "%i", &num) != 1 || num < 0)
9e49712b9cddbf47568ea4f3676e59b151489356Timo Sirainen return t_strconcat("Invalid number: ", value, NULL);
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainenparse_setting_from_defs(pool_t pool, const struct setting_def *defs, void *base,
9e49712b9cddbf47568ea4f3676e59b151489356Timo Sirainen void *ptr = STRUCT_MEMBER_P(base, def->offset);
9e49712b9cddbf47568ea4f3676e59b151489356Timo Sirainen /* use %i so we can handle eg. 0600
9e49712b9cddbf47568ea4f3676e59b151489356Timo Sirainen as octal value with umasks */
9e49712b9cddbf47568ea4f3676e59b151489356Timo Sirainen return t_strconcat("Unknown setting: ", key, NULL);
90441432cfe7a5bf7ee07c91c57f4027946ee4f1Timo Sirainenstatic const char *
90441432cfe7a5bf7ee07c91c57f4027946ee4f1Timo Sirainenfix_relative_path(const char *path, struct input_stack *input)
90441432cfe7a5bf7ee07c91c57f4027946ee4f1Timo Sirainen const char *p;
90441432cfe7a5bf7ee07c91c57f4027946ee4f1Timo Sirainen return t_strconcat(t_strdup_until(input->path, p+1), path, NULL);
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainenstatic int settings_add_include(const char *path, struct input_stack **inputp,
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen for (tmp = *inputp; tmp != NULL; tmp = tmp->prev) {
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen *error_r = t_strdup_printf("Recursive include file: %s", path);
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen *error_r = t_strdup_printf("Couldn't open include file %s: %m",
bace943c67e6cd14ce6c994f533d82a3caad5bf1Timo Sirainen new_input->input = i_stream_create_fd_autoclose(&fd, (size_t)-1);
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen i_stream_set_return_partial_line(new_input->input, TRUE);
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainensettings_include(const char *pattern, struct input_stack **inputp,
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen unsigned int i;
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen switch (glob(pattern, GLOB_BRACE, NULL, &globbers)) {
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen *error_r = "glob() failed: Not enough memory";
19557f192d37cd54a1a090a8a26d9d47265e4413Aki Tuomi /* iterate through the different files matching the globbing */
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen if (settings_add_include(globbers.gl_pathv[i], inputp,
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen return settings_add_include(pattern, inputp, ignore_errors, error_r);
9e49712b9cddbf47568ea4f3676e59b151489356Timo Sirainen#define IS_WHITE(c) ((c) == ' ' || (c) == '\t')
803197abb1cc0e81abb668c026c22394bfef820dTimo Sirainenbool settings_read_i(const char *path, const char *section,
803197abb1cc0e81abb668c026c22394bfef820dTimo Sirainen settings_section_callback_t *sect_callback, void *context,
803197abb1cc0e81abb668c026c22394bfef820dTimo Sirainen const char **error_r)
885673616ab8dc038eafdf76efe4184ecffcdc88Timo Sirainen /* pretty horrible code, but v2.0 will have this rewritten anyway.. */
885673616ab8dc038eafdf76efe4184ecffcdc88Timo Sirainen const char *errormsg, *next_section, *name, *last_section_path = NULL;
885673616ab8dc038eafdf76efe4184ecffcdc88Timo Sirainen int fd, last_section_line = 0, skip, sections, root_section;
803197abb1cc0e81abb668c026c22394bfef820dTimo Sirainen "Can't open configuration file %s: %m", path);
885673616ab8dc038eafdf76efe4184ecffcdc88Timo Sirainen sections = 0; root_section = 0; errormsg = NULL;
bace943c67e6cd14ce6c994f533d82a3caad5bf1Timo Sirainen input->input = i_stream_create_fd_autoclose(&fd, (size_t)-1);
885673616ab8dc038eafdf76efe4184ecffcdc88Timo Sirainen i_stream_set_return_partial_line(input->input, TRUE);
885673616ab8dc038eafdf76efe4184ecffcdc88Timo Sirainen while ((line = i_stream_read_next_line(input->input)) != NULL) {
9e49712b9cddbf47568ea4f3676e59b151489356Timo Sirainen /* @UNSAFE: line is modified */
9e49712b9cddbf47568ea4f3676e59b151489356Timo Sirainen /* skip whitespace */
9e49712b9cddbf47568ea4f3676e59b151489356Timo Sirainen /* ignore comments or empty lines */
6cc8fac7fd9b47e179629a61acef0e8758763803Timo Sirainen /* strip away comments. pretty kludgy way really.. */
6cc8fac7fd9b47e179629a61acef0e8758763803Timo Sirainen if (*p == '\0')
6cc8fac7fd9b47e179629a61acef0e8758763803Timo Sirainen } else if (*p == '#') {
25e480bc781fdbcbee1d8b88ccdef163c0c63b0fTimo Sirainen "Ambiguous '#' character in line, treating it as comment. "
25e480bc781fdbcbee1d8b88ccdef163c0c63b0fTimo Sirainen "Add a space before it to remove this warning.",
3f8a5d2a09e90961d1d86dea294be162ccdb64a8Timo Sirainen /* remove whitespace from end of line */
12bbab623d9965d019e6e80d4f41255cd5002c9aTimo Sirainen /* continues in next line */
3f8a5d2a09e90961d1d86dea294be162ccdb64a8Timo Sirainen /* a) key = value
d81433c272dc189ff50ecde109cd0040f21fa8b0Timo Sirainen b) section_type [section_name] {
337e0bdea4c5b1a9e3ac3e915b31a6413f46220cTimo Sirainen while (!IS_WHITE(*line) && *line != '\0' && *line != '=')
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen if (settings_include(fix_relative_path(line, input),
d81433c272dc189ff50ecde109cd0040f21fa8b0Timo Sirainen } else if (strcmp(key, "}") != 0 || *line != '\0') {
d81433c272dc189ff50ecde109cd0040f21fa8b0Timo Sirainen /* b) + errors */
d81433c272dc189ff50ecde109cd0040f21fa8b0Timo Sirainen /* we found the section,
803197abb1cc0e81abb668c026c22394bfef820dTimo Sirainen "Error in configuration file %s line %d: %s",