diff --git a/src/or/config.c b/src/or/config.c index 6fbc2dfed6..cf8b07be7f 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -744,16 +744,12 @@ config_find_option(config_format_t *fmt, const char *key) return NULL; } -/** If c is a syntactically valid configuration line, update - * options with its value and return 0. Otherwise return -1 for bad key, - * -2 for bad value. - * - * If 'reset' is set, and we get a line containing no value, restore the - * option to its default value. +/** c-\>key is known to be a real key. Update options + * with c-\>value and return 0, or return -1 if bad value. */ static int -config_assign_line(config_format_t *fmt, - or_options_t *options, config_line_t *c, int reset) +config_assign_value(config_format_t *fmt, or_options_t *options, + config_line_t *c) { int i, ok; config_var_t *var; @@ -762,25 +758,10 @@ config_assign_line(config_format_t *fmt, CHECK(fmt, options); var = config_find_option(fmt, c->key); - if (!var) { - log_fn(LOG_WARN, "Unknown option '%s'. Failing.", c->key); - return -1; - } - /* Put keyword into canonical case. */ - if (strcmp(var->name, c->key)) { - tor_free(c->key); - c->key = tor_strdup(var->name); - } - - if (!strlen(c->value)) { /* reset or clear it, then return */ - if (reset) - option_reset(fmt, options, var); - else - option_clear(fmt, options, var); - return 0; - } + tor_assert(var); lvalue = ((char*)options) + var->var_offset; + switch (var->type) { case CONFIG_TYPE_UINT: @@ -788,7 +769,7 @@ config_assign_line(config_format_t *fmt, if (!ok) { log(LOG_WARN, "Int keyword '%s %s' is malformed or out of bounds.", c->key,c->value); - return -2; + return -1; } *(int *)lvalue = i; break; @@ -796,7 +777,7 @@ config_assign_line(config_format_t *fmt, case CONFIG_TYPE_INTERVAL: { i = config_parse_interval(c->value, &ok); if (!ok) { - return -2; + return -1; } *(int *)lvalue = i; break; @@ -805,7 +786,7 @@ config_assign_line(config_format_t *fmt, case CONFIG_TYPE_MEMUNIT: { uint64_t u64 = config_parse_memunit(c->value, &ok); if (!ok) { - return -2; + return -1; } *(uint64_t *)lvalue = u64; break; @@ -815,7 +796,7 @@ config_assign_line(config_format_t *fmt, i = tor_parse_long(c->value, 10, 0, 1, &ok, NULL); if (!ok) { log(LOG_WARN, "Boolean keyword '%s' expects 0 or 1.", c->key); - return -2; + return -1; } *(int *)lvalue = i; break; @@ -832,7 +813,7 @@ config_assign_line(config_format_t *fmt, case CONFIG_TYPE_ISOTIME: if (parse_iso_time(c->value, (time_t *)lvalue)) { log(LOG_WARN, "Invalid time '%s' for keyword '%s'", c->value, c->key); - return -2; + return -1; } break; @@ -858,7 +839,7 @@ config_assign_line(config_format_t *fmt, break; case CONFIG_TYPE_LINELIST_V: log_fn(LOG_WARN, "Can't provide value for virtual option '%s'", c->key); - return -2; + return -1; default: tor_assert(0); break; @@ -866,6 +847,45 @@ config_assign_line(config_format_t *fmt, return 0; } +/** If c is a syntactically valid configuration line, update + * options with its value and return 0. Otherwise return -1 for bad key, + * -2 for bad value. + * + * If 'reset' is set, and we get a line containing no value, restore the + * option to its default value. + */ +static int +config_assign_line(config_format_t *fmt, or_options_t *options, + config_line_t *c, int reset) +{ + config_var_t *var; + + CHECK(fmt, options); + + var = config_find_option(fmt, c->key); + if (!var) { + log_fn(LOG_WARN, "Unknown option '%s'. Failing.", c->key); + return -1; + } + /* Put keyword into canonical case. */ + if (strcmp(var->name, c->key)) { + tor_free(c->key); + c->key = tor_strdup(var->name); + } + + if (!strlen(c->value)) { /* reset or clear it, then return */ + if (reset) + option_reset(fmt, options, var); + else + option_clear(fmt, options, var); + return 0; + } + + if (config_assign_value(fmt, options, c) < 0) + return -2; + return 0; +} + /** restore the option named key in options to its default value. */ static void config_reset_line(config_format_t *fmt, or_options_t *options, const char *key) @@ -1143,7 +1163,7 @@ option_reset(config_format_t *fmt, or_options_t *options, config_var_t *var) c = tor_malloc_zero(sizeof(config_line_t)); c->key = tor_strdup(var->name); c->value = tor_strdup(var->initvalue); - config_assign_line(fmt, options,c,0); + config_assign_value(fmt, options, c); config_free_lines(c); } } @@ -2275,8 +2295,8 @@ options_init_from_torrc(int argc, char **argv) } /* Go through command-line variables too */ - cl = config_get_commandlines(argc,argv); - retval = config_assign(&options_format, newoptions,cl,0); + cl = config_get_commandlines(argc, argv); + retval = config_assign(&options_format, newoptions, cl, 0); config_free_lines(cl); if (retval < 0) goto err;