dovecot-2.0: config: Code cleanups.
dovecot at dovecot.org
dovecot at dovecot.org
Mon Aug 31 19:20:46 EEST 2009
details: http://hg.dovecot.org/dovecot-2.0/rev/a0ec16185806
changeset: 9833:a0ec16185806
user: Timo Sirainen <tss at iki.fi>
date: Mon Aug 31 12:20:38 2009 -0400
description:
config: Code cleanups.
diffstat:
1 file changed, 212 insertions(+), 157 deletions(-)
src/config/config-parser.c | 369 +++++++++++++++++++++++++-------------------
diffs (truncated from 497 to 300 lines):
diff -r 3a16bec9c961 -r a0ec16185806 src/config/config-parser.c
--- a/src/config/config-parser.c Mon Aug 31 11:38:42 2009 -0400
+++ b/src/config/config-parser.c Mon Aug 31 12:20:38 2009 -0400
@@ -92,10 +92,10 @@ static void config_add_type(struct setti
i_assert(ret > 0);
}
-static const char *
+static int
config_parsers_parse_line(struct config_setting_parser_list *parsers,
const char *key, const char *line,
- const char *section_name)
+ const char *section_name, const char **error_r)
{
struct config_setting_parser_list *l;
bool found = FALSE;
@@ -107,26 +107,30 @@ config_parsers_parse_line(struct config_
found = TRUE;
if (section_name != NULL)
config_add_type(l->parser, line, section_name);
- } else if (ret < 0)
- return settings_parser_get_error(l->parser);
- }
-
- return found ? NULL : t_strconcat("Unknown setting: ", key, NULL);
-}
-
-static const char *
-config_parse_line(struct config_setting_parser_list *const *all_parsers,
- const char *key, const char *line, const char *section_name)
-{
- const char *ret;
-
+ } else if (ret < 0) {
+ *error_r = settings_parser_get_error(l->parser);
+ return -1;
+ }
+ }
+ if (!found) {
+ *error_r = t_strconcat("Unknown setting: ", key, NULL);
+ return -1;
+ }
+ return 0;
+}
+
+static int
+config_apply_line(struct config_setting_parser_list *const *all_parsers,
+ const char *key, const char *line, const char *section_name,
+ const char **error_r)
+{
for (; *all_parsers != NULL; all_parsers++) {
- ret = config_parsers_parse_line(*all_parsers, key, line,
- section_name);
- if (ret != NULL)
- return ret;
- }
- return NULL;
+ if (config_parsers_parse_line(*all_parsers, key, line,
+ section_name, error_r) < 0)
+ return -1;
+ }
+ *error_r = NULL;
+ return 0;
}
static const char *
@@ -260,7 +264,7 @@ config_all_parsers_check(struct parser_c
return 0;
}
-static void
+static int
str_append_file(string_t *str, const char *key, const char *path,
const char **error_r)
{
@@ -272,7 +276,7 @@ str_append_file(string_t *str, const cha
if (fd == -1) {
*error_r = t_strdup_printf("%s: Can't open file %s: %m",
key, path);
- return;
+ return -1;
}
while ((ret = read(fd, buf, sizeof(buf))) > 0)
str_append_n(str, buf, ret);
@@ -281,6 +285,7 @@ str_append_file(string_t *str, const cha
key, path);
}
(void)close(fd);
+ return ret < 0 ? -1 : 0;
}
static int settings_add_include(struct parser_context *ctx, const char *path,
@@ -354,6 +359,133 @@ settings_include(struct parser_context *
#else
return settings_add_include(ctx, pattern, ignore_errors, error_r);
#endif
+}
+
+enum config_line_type {
+ CONFIG_LINE_TYPE_SKIP,
+ CONFIG_LINE_TYPE_ERROR,
+ CONFIG_LINE_TYPE_KEYVALUE,
+ CONFIG_LINE_TYPE_SECTION_BEGIN,
+ CONFIG_LINE_TYPE_SECTION_END,
+ CONFIG_LINE_TYPE_INCLUDE,
+ CONFIG_LINE_TYPE_INCLUDE_TRY
+};
+
+static enum config_line_type
+config_parse_line(char *line, string_t *full_line, const char **key_r,
+ const char **section_r, const char **value_r)
+{
+ const char *key;
+ unsigned int len;
+ char *p;
+
+ *key_r = NULL;
+ *value_r = NULL;
+ *section_r = NULL;
+
+ /* @UNSAFE: line is modified */
+
+ /* skip whitespace */
+ while (IS_WHITE(*line))
+ line++;
+
+ /* ignore comments or empty lines */
+ if (*line == '#' || *line == '\0')
+ return CONFIG_LINE_TYPE_SKIP;
+
+ /* strip away comments. pretty kludgy way really.. */
+ for (p = line; *p != '\0'; p++) {
+ if (*p == '\'' || *p == '"') {
+ char quote = *p;
+ for (p++; *p != quote && *p != '\0'; p++) {
+ if (*p == '\\' && p[1] != '\0')
+ p++;
+ }
+ if (*p == '\0')
+ break;
+ } else if (*p == '#') {
+ *p = '\0';
+ break;
+ }
+ }
+
+ /* remove whitespace from end of line */
+ len = strlen(line);
+ while (IS_WHITE(line[len-1]))
+ len--;
+ line[len] = '\0';
+
+ if (len > 0 && line[len-1] == '\\') {
+ /* continues in next line */
+ line[len-1] = '\0';
+ str_append(full_line, line);
+ return CONFIG_LINE_TYPE_SKIP;
+ }
+ if (str_len(full_line) > 0) {
+ str_append(full_line, line);
+ line = str_c_modifiable(full_line);
+ }
+
+ /* a) key = value
+ b) section_type [section_name] {
+ c) } */
+ key = line;
+ while (!IS_WHITE(*line) && *line != '\0' && *line != '=')
+ line++;
+ if (IS_WHITE(*line)) {
+ *line++ = '\0';
+ while (IS_WHITE(*line)) line++;
+ }
+ *key_r = key;
+ *value_r = line;
+
+ if (strcmp(key, "!include") == 0)
+ return CONFIG_LINE_TYPE_INCLUDE;
+ if (strcmp(key, "!include_try") == 0)
+ return CONFIG_LINE_TYPE_INCLUDE_TRY;
+
+ if (*line == '=') {
+ /* a) */
+ *line++ = '\0';
+ while (IS_WHITE(*line)) line++;
+
+ len = strlen(line);
+ if (len > 0 &&
+ ((*line == '"' && line[len-1] == '"') ||
+ (*line == '\'' && line[len-1] == '\''))) {
+ line[len-1] = '\0';
+ line = str_unescape(line+1);
+ }
+ *value_r = line;
+ return CONFIG_LINE_TYPE_KEYVALUE;
+ }
+
+ if (strcmp(key, "}") == 0 && *line == '\0')
+ return CONFIG_LINE_TYPE_SECTION_END;
+
+ /* b) + errors */
+ line[-1] = '\0';
+
+ if (*line == '{')
+ *section_r = "";
+ else {
+ /* get section name */
+ *section_r = line;
+ while (!IS_WHITE(*line) && *line != '\0')
+ line++;
+
+ if (*line != '\0') {
+ *line++ = '\0';
+ while (IS_WHITE(*line))
+ line++;
+ }
+ if (*line != '{') {
+ *value_r = "Expecting '='";
+ return CONFIG_LINE_TYPE_ERROR;
+ }
+ *value_r = line;
+ }
+ return CONFIG_LINE_TYPE_SECTION_BEGIN;
}
int config_parse_file(const char *path, bool expand_files,
@@ -367,11 +499,11 @@ int config_parse_file(const char *path,
struct parser_context ctx;
unsigned int pathlen = 0;
unsigned int i, count, counter = 0, auth_counter = 0, cur_counter;
- const char *errormsg, *name;
- char *line, *key, *p;
+ const char *errormsg, *key, *value, *section, *p;
+ string_t *str, *full_line;
+ enum config_line_type type;
+ char *line;
int fd, ret = 0;
- string_t *str, *full_line;
- size_t len;
fd = open(path, O_RDONLY);
if (fd < 0) {
@@ -401,9 +533,9 @@ int config_parse_file(const char *path,
config_add_new_parser(&ctx);
parsers = config_update_cur_parsers(&ctx);
- errormsg = config_parse_line(parsers, "0", "auth=0", NULL);
+ (void)config_apply_line(parsers, "0", "auth=0", NULL, &errormsg);
i_assert(errormsg == NULL);
- errormsg = config_parse_line(parsers, "name", "auth/0/name=default", NULL);
+ (void)config_apply_line(parsers, "name", "auth/0/name=default", NULL, &errormsg);
i_assert(errormsg == NULL);
memset(&root, 0, sizeof(root));
@@ -418,146 +550,61 @@ prevfile:
prevfile:
while ((line = i_stream_read_next_line(ctx.cur_input->input)) != NULL) {
ctx.cur_input->linenum++;
-
- /* @UNSAFE: line is modified */
-
- /* skip whitespace */
- while (IS_WHITE(*line))
- line++;
-
- /* ignore comments or empty lines */
- if (*line == '#' || *line == '\0')
- continue;
-
- /* strip away comments. pretty kludgy way really.. */
- for (p = line; *p != '\0'; p++) {
- if (*p == '\'' || *p == '"') {
- char quote = *p;
- for (p++; *p != quote && *p != '\0'; p++) {
- if (*p == '\\' && p[1] != '\0')
- p++;
- }
- if (*p == '\0')
- break;
- } else if (*p == '#') {
- *p = '\0';
- break;
- }
- }
-
- /* remove whitespace from end of line */
- len = strlen(line);
- while (IS_WHITE(line[len-1]))
- len--;
- line[len] = '\0';
-
- if (len > 0 && line[len-1] == '\\') {
- /* continues in next line */
- line[len-1] = '\0';
- str_append(full_line, line);
- continue;
- }
- if (str_len(full_line) > 0) {
- str_append(full_line, line);
- line = str_c_modifiable(full_line);
More information about the dovecot-cvs
mailing list