Add Coccinelle patch for replacing NULL/non-NULL tt_assert().
[tor.git] / src / or / confparse.c
blobabae7e33dc522a28895a8e4dd4f6b28965274d57
2 /* Copyright (c) 2001 Matej Pfajfar.
3 * Copyright (c) 2001-2004, Roger Dingledine.
4 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
5 * Copyright (c) 2007-2017, The Tor Project, Inc. */
6 /* See LICENSE for licensing information */
8 /**
9 * \file confparse.c
11 * \brief Back-end for parsing and generating key-value files, used to
12 * implement the torrc file format and the state file.
14 * This module is used by config.c to parse and encode torrc
15 * configuration files, and by statefile.c to parse and encode the
16 * $DATADIR/state file.
18 * To use this module, its callers provide an instance of
19 * config_format_t to describe the mappings from a set of configuration
20 * options to a number of fields in a C structure. With this mapping,
21 * the functions here can convert back and forth between the C structure
22 * specified, and a linked list of key-value pairs.
25 #include "or.h"
26 #include "confparse.h"
27 #include "routerset.h"
29 static uint64_t config_parse_memunit(const char *s, int *ok);
30 static int config_parse_msec_interval(const char *s, int *ok);
31 static int config_parse_interval(const char *s, int *ok);
32 static void config_reset(const config_format_t *fmt, void *options,
33 const config_var_t *var, int use_defaults);
35 /** Allocate an empty configuration object of a given format type. */
36 void *
37 config_new(const config_format_t *fmt)
39 void *opts = tor_malloc_zero(fmt->size);
40 *(uint32_t*)STRUCT_VAR_P(opts, fmt->magic_offset) = fmt->magic;
41 CONFIG_CHECK(fmt, opts);
42 return opts;
46 * Functions to parse config options
49 /** If <b>option</b> is an official abbreviation for a longer option,
50 * return the longer option. Otherwise return <b>option</b>.
51 * If <b>command_line</b> is set, apply all abbreviations. Otherwise, only
52 * apply abbreviations that work for the config file and the command line.
53 * If <b>warn_obsolete</b> is set, warn about deprecated names. */
54 const char *
55 config_expand_abbrev(const config_format_t *fmt, const char *option,
56 int command_line, int warn_obsolete)
58 int i;
59 if (! fmt->abbrevs)
60 return option;
61 for (i=0; fmt->abbrevs[i].abbreviated; ++i) {
62 /* Abbreviations are case insensitive. */
63 if (!strcasecmp(option,fmt->abbrevs[i].abbreviated) &&
64 (command_line || !fmt->abbrevs[i].commandline_only)) {
65 if (warn_obsolete && fmt->abbrevs[i].warn) {
66 log_warn(LD_CONFIG,
67 "The configuration option '%s' is deprecated; "
68 "use '%s' instead.",
69 fmt->abbrevs[i].abbreviated,
70 fmt->abbrevs[i].full);
72 /* Keep going through the list in case we want to rewrite it more.
73 * (We could imagine recursing here, but I don't want to get the
74 * user into an infinite loop if we craft our list wrong.) */
75 option = fmt->abbrevs[i].full;
78 return option;
81 /** If <b>key</b> is a deprecated configuration option, return the message
82 * explaining why it is deprecated (which may be an empty string). Return NULL
83 * if it is not deprecated. The <b>key</b> field must be fully expanded. */
84 const char *
85 config_find_deprecation(const config_format_t *fmt, const char *key)
87 if (BUG(fmt == NULL) || BUG(key == NULL))
88 return NULL;
89 if (fmt->deprecations == NULL)
90 return NULL;
92 const config_deprecation_t *d;
93 for (d = fmt->deprecations; d->name; ++d) {
94 if (!strcasecmp(d->name, key)) {
95 return d->why_deprecated ? d->why_deprecated : "";
98 return NULL;
101 /** As config_find_option, but return a non-const pointer. */
102 config_var_t *
103 config_find_option_mutable(config_format_t *fmt, const char *key)
105 int i;
106 size_t keylen = strlen(key);
107 if (!keylen)
108 return NULL; /* if they say "--" on the command line, it's not an option */
109 /* First, check for an exact (case-insensitive) match */
110 for (i=0; fmt->vars[i].name; ++i) {
111 if (!strcasecmp(key, fmt->vars[i].name)) {
112 return &fmt->vars[i];
115 /* If none, check for an abbreviated match */
116 for (i=0; fmt->vars[i].name; ++i) {
117 if (!strncasecmp(key, fmt->vars[i].name, keylen)) {
118 log_warn(LD_CONFIG, "The abbreviation '%s' is deprecated. "
119 "Please use '%s' instead",
120 key, fmt->vars[i].name);
121 return &fmt->vars[i];
124 /* Okay, unrecognized option */
125 return NULL;
128 /** If <b>key</b> is a configuration option, return the corresponding const
129 * config_var_t. Otherwise, if <b>key</b> is a non-standard abbreviation,
130 * warn, and return the corresponding const config_var_t. Otherwise return
131 * NULL.
133 const config_var_t *
134 config_find_option(const config_format_t *fmt, const char *key)
136 return config_find_option_mutable((config_format_t*)fmt, key);
139 /** Return the number of option entries in <b>fmt</b>. */
140 static int
141 config_count_options(const config_format_t *fmt)
143 int i;
144 for (i=0; fmt->vars[i].name; ++i)
146 return i;
150 * Functions to assign config options.
153 /** <b>c</b>-\>key is known to be a real key. Update <b>options</b>
154 * with <b>c</b>-\>value and return 0, or return -1 if bad value.
156 * Called from config_assign_line() and option_reset().
158 static int
159 config_assign_value(const config_format_t *fmt, void *options,
160 config_line_t *c, char **msg)
162 int i, ok;
163 const config_var_t *var;
164 void *lvalue;
165 int *csv_int;
166 smartlist_t *csv_str;
168 CONFIG_CHECK(fmt, options);
170 var = config_find_option(fmt, c->key);
171 tor_assert(var);
173 lvalue = STRUCT_VAR_P(options, var->var_offset);
175 switch (var->type) {
177 case CONFIG_TYPE_PORT:
178 if (!strcasecmp(c->value, "auto")) {
179 *(int *)lvalue = CFG_AUTO_PORT;
180 break;
182 /* fall through */
183 case CONFIG_TYPE_INT:
184 case CONFIG_TYPE_UINT:
185 i = (int)tor_parse_long(c->value, 10,
186 var->type==CONFIG_TYPE_INT ? INT_MIN : 0,
187 var->type==CONFIG_TYPE_PORT ? 65535 : INT_MAX,
188 &ok, NULL);
189 if (!ok) {
190 tor_asprintf(msg,
191 "Int keyword '%s %s' is malformed or out of bounds.",
192 c->key, c->value);
193 return -1;
195 *(int *)lvalue = i;
196 break;
198 case CONFIG_TYPE_INTERVAL: {
199 i = config_parse_interval(c->value, &ok);
200 if (!ok) {
201 tor_asprintf(msg,
202 "Interval '%s %s' is malformed or out of bounds.",
203 c->key, c->value);
204 return -1;
206 *(int *)lvalue = i;
207 break;
210 case CONFIG_TYPE_MSEC_INTERVAL: {
211 i = config_parse_msec_interval(c->value, &ok);
212 if (!ok) {
213 tor_asprintf(msg,
214 "Msec interval '%s %s' is malformed or out of bounds.",
215 c->key, c->value);
216 return -1;
218 *(int *)lvalue = i;
219 break;
222 case CONFIG_TYPE_MEMUNIT: {
223 uint64_t u64 = config_parse_memunit(c->value, &ok);
224 if (!ok) {
225 tor_asprintf(msg,
226 "Value '%s %s' is malformed or out of bounds.",
227 c->key, c->value);
228 return -1;
230 *(uint64_t *)lvalue = u64;
231 break;
234 case CONFIG_TYPE_BOOL:
235 i = (int)tor_parse_long(c->value, 10, 0, 1, &ok, NULL);
236 if (!ok) {
237 tor_asprintf(msg,
238 "Boolean '%s %s' expects 0 or 1.",
239 c->key, c->value);
240 return -1;
242 *(int *)lvalue = i;
243 break;
245 case CONFIG_TYPE_AUTOBOOL:
246 if (!strcmp(c->value, "auto"))
247 *(int *)lvalue = -1;
248 else if (!strcmp(c->value, "0"))
249 *(int *)lvalue = 0;
250 else if (!strcmp(c->value, "1"))
251 *(int *)lvalue = 1;
252 else {
253 tor_asprintf(msg, "Boolean '%s %s' expects 0, 1, or 'auto'.",
254 c->key, c->value);
255 return -1;
257 break;
259 case CONFIG_TYPE_STRING:
260 case CONFIG_TYPE_FILENAME:
261 tor_free(*(char **)lvalue);
262 *(char **)lvalue = tor_strdup(c->value);
263 break;
265 case CONFIG_TYPE_DOUBLE:
266 *(double *)lvalue = atof(c->value);
267 break;
269 case CONFIG_TYPE_ISOTIME:
270 if (parse_iso_time(c->value, (time_t *)lvalue)) {
271 tor_asprintf(msg,
272 "Invalid time '%s' for keyword '%s'", c->value, c->key);
273 return -1;
275 break;
277 case CONFIG_TYPE_ROUTERSET:
278 if (*(routerset_t**)lvalue) {
279 routerset_free(*(routerset_t**)lvalue);
281 *(routerset_t**)lvalue = routerset_new();
282 if (routerset_parse(*(routerset_t**)lvalue, c->value, c->key)<0) {
283 tor_asprintf(msg, "Invalid exit list '%s' for option '%s'",
284 c->value, c->key);
285 return -1;
287 break;
289 case CONFIG_TYPE_CSV:
290 if (*(smartlist_t**)lvalue) {
291 SMARTLIST_FOREACH(*(smartlist_t**)lvalue, char *, cp, tor_free(cp));
292 smartlist_clear(*(smartlist_t**)lvalue);
293 } else {
294 *(smartlist_t**)lvalue = smartlist_new();
297 smartlist_split_string(*(smartlist_t**)lvalue, c->value, ",",
298 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
299 break;
301 case CONFIG_TYPE_CSV_INTERVAL:
302 if (*(smartlist_t**)lvalue) {
303 SMARTLIST_FOREACH(*(smartlist_t**)lvalue, int *, cp, tor_free(cp));
304 smartlist_clear(*(smartlist_t**)lvalue);
305 } else {
306 *(smartlist_t**)lvalue = smartlist_new();
308 csv_str = smartlist_new();
309 smartlist_split_string(csv_str, c->value, ",",
310 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
311 SMARTLIST_FOREACH_BEGIN(csv_str, char *, str)
313 i = config_parse_interval(str, &ok);
314 if (!ok) {
315 tor_asprintf(msg,
316 "Interval in '%s %s' is malformed or out of bounds.",
317 c->key, c->value);
318 SMARTLIST_FOREACH(csv_str, char *, cp, tor_free(cp));
319 smartlist_free(csv_str);
320 return -1;
322 csv_int = tor_malloc_zero(sizeof(int));
323 *csv_int = i;
324 smartlist_add(*(smartlist_t**)lvalue, csv_int);
326 SMARTLIST_FOREACH_END(str);
327 SMARTLIST_FOREACH(csv_str, char *, cp, tor_free(cp));
328 smartlist_free(csv_str);
329 break;
331 case CONFIG_TYPE_LINELIST:
332 case CONFIG_TYPE_LINELIST_S:
334 config_line_t *lastval = *(config_line_t**)lvalue;
335 if (lastval && lastval->fragile) {
336 if (c->command != CONFIG_LINE_APPEND) {
337 config_free_lines(lastval);
338 *(config_line_t**)lvalue = NULL;
339 } else {
340 lastval->fragile = 0;
344 config_line_append((config_line_t**)lvalue, c->key, c->value);
346 break;
347 case CONFIG_TYPE_OBSOLETE:
348 log_warn(LD_CONFIG, "Skipping obsolete configuration option '%s'", c->key);
349 break;
350 case CONFIG_TYPE_LINELIST_V:
351 tor_asprintf(msg,
352 "You may not provide a value for virtual option '%s'", c->key);
353 return -1;
354 default:
355 tor_assert(0);
356 break;
358 return 0;
361 /** Mark every linelist in <b>options</b> "fragile", so that fresh assignments
362 * to it will replace old ones. */
363 static void
364 config_mark_lists_fragile(const config_format_t *fmt, void *options)
366 int i;
367 tor_assert(fmt);
368 tor_assert(options);
370 for (i = 0; fmt->vars[i].name; ++i) {
371 const config_var_t *var = &fmt->vars[i];
372 config_line_t *list;
373 if (var->type != CONFIG_TYPE_LINELIST &&
374 var->type != CONFIG_TYPE_LINELIST_V)
375 continue;
377 list = *(config_line_t **)STRUCT_VAR_P(options, var->var_offset);
378 if (list)
379 list->fragile = 1;
383 void
384 warn_deprecated_option(const char *what, const char *why)
386 const char *space = (why && strlen(why)) ? " " : "";
387 log_warn(LD_CONFIG, "The %s option is deprecated, and will most likely "
388 "be removed in a future version of Tor.%s%s (If you think this is "
389 "a mistake, please let us know!)",
390 what, space, why);
393 /** If <b>c</b> is a syntactically valid configuration line, update
394 * <b>options</b> with its value and return 0. Otherwise return -1 for bad
395 * key, -2 for bad value.
397 * If <b>clear_first</b> is set, clear the value first. Then if
398 * <b>use_defaults</b> is set, set the value to the default.
400 * Called from config_assign().
402 static int
403 config_assign_line(const config_format_t *fmt, void *options,
404 config_line_t *c, unsigned flags,
405 bitarray_t *options_seen, char **msg)
407 const unsigned use_defaults = flags & CAL_USE_DEFAULTS;
408 const unsigned clear_first = flags & CAL_CLEAR_FIRST;
409 const unsigned warn_deprecations = flags & CAL_WARN_DEPRECATIONS;
410 const config_var_t *var;
412 CONFIG_CHECK(fmt, options);
414 var = config_find_option(fmt, c->key);
415 if (!var) {
416 if (fmt->extra) {
417 void *lvalue = STRUCT_VAR_P(options, fmt->extra->var_offset);
418 log_info(LD_CONFIG,
419 "Found unrecognized option '%s'; saving it.", c->key);
420 config_line_append((config_line_t**)lvalue, c->key, c->value);
421 return 0;
422 } else {
423 tor_asprintf(msg,
424 "Unknown option '%s'. Failing.", c->key);
425 return -1;
429 /* Put keyword into canonical case. */
430 if (strcmp(var->name, c->key)) {
431 tor_free(c->key);
432 c->key = tor_strdup(var->name);
435 const char *deprecation_msg;
436 if (warn_deprecations &&
437 (deprecation_msg = config_find_deprecation(fmt, var->name))) {
438 warn_deprecated_option(var->name, deprecation_msg);
441 if (!strlen(c->value)) {
442 /* reset or clear it, then return */
443 if (!clear_first) {
444 if ((var->type == CONFIG_TYPE_LINELIST ||
445 var->type == CONFIG_TYPE_LINELIST_S) &&
446 c->command != CONFIG_LINE_CLEAR) {
447 /* We got an empty linelist from the torrc or command line.
448 As a special case, call this an error. Warn and ignore. */
449 log_warn(LD_CONFIG,
450 "Linelist option '%s' has no value. Skipping.", c->key);
451 } else { /* not already cleared */
452 config_reset(fmt, options, var, use_defaults);
455 return 0;
456 } else if (c->command == CONFIG_LINE_CLEAR && !clear_first) {
457 config_reset(fmt, options, var, use_defaults);
460 if (options_seen && (var->type != CONFIG_TYPE_LINELIST &&
461 var->type != CONFIG_TYPE_LINELIST_S)) {
462 /* We're tracking which options we've seen, and this option is not
463 * supposed to occur more than once. */
464 int var_index = (int)(var - fmt->vars);
465 if (bitarray_is_set(options_seen, var_index)) {
466 log_warn(LD_CONFIG, "Option '%s' used more than once; all but the last "
467 "value will be ignored.", var->name);
469 bitarray_set(options_seen, var_index);
472 if (config_assign_value(fmt, options, c, msg) < 0)
473 return -2;
474 return 0;
477 /** Restore the option named <b>key</b> in options to its default value.
478 * Called from config_assign(). */
479 static void
480 config_reset_line(const config_format_t *fmt, void *options,
481 const char *key, int use_defaults)
483 const config_var_t *var;
485 CONFIG_CHECK(fmt, options);
487 var = config_find_option(fmt, key);
488 if (!var)
489 return; /* give error on next pass. */
491 config_reset(fmt, options, var, use_defaults);
494 /** Return true iff value needs to be quoted and escaped to be used in
495 * a configuration file. */
496 static int
497 config_value_needs_escape(const char *value)
499 if (*value == '\"')
500 return 1;
501 while (*value) {
502 switch (*value)
504 case '\r':
505 case '\n':
506 case '#':
507 /* Note: quotes and backspaces need special handling when we are using
508 * quotes, not otherwise, so they don't trigger escaping on their
509 * own. */
510 return 1;
511 default:
512 if (!TOR_ISPRINT(*value))
513 return 1;
515 ++value;
517 return 0;
520 /** Return newly allocated line or lines corresponding to <b>key</b> in the
521 * configuration <b>options</b>. If <b>escape_val</b> is true and a
522 * value needs to be quoted before it's put in a config file, quote and
523 * escape that value. Return NULL if no such key exists. */
524 config_line_t *
525 config_get_assigned_option(const config_format_t *fmt, const void *options,
526 const char *key, int escape_val)
528 const config_var_t *var;
529 const void *value;
530 config_line_t *result;
531 smartlist_t *csv_str;
532 tor_assert(options && key);
534 CONFIG_CHECK(fmt, options);
536 var = config_find_option(fmt, key);
537 if (!var) {
538 log_warn(LD_CONFIG, "Unknown option '%s'. Failing.", key);
539 return NULL;
541 value = STRUCT_VAR_P(options, var->var_offset);
543 result = tor_malloc_zero(sizeof(config_line_t));
544 result->key = tor_strdup(var->name);
545 switch (var->type)
547 case CONFIG_TYPE_STRING:
548 case CONFIG_TYPE_FILENAME:
549 if (*(char**)value) {
550 result->value = tor_strdup(*(char**)value);
551 } else {
552 tor_free(result->key);
553 tor_free(result);
554 return NULL;
556 break;
557 case CONFIG_TYPE_ISOTIME:
558 if (*(time_t*)value) {
559 result->value = tor_malloc(ISO_TIME_LEN+1);
560 format_iso_time(result->value, *(time_t*)value);
561 } else {
562 tor_free(result->key);
563 tor_free(result);
565 escape_val = 0; /* Can't need escape. */
566 break;
567 case CONFIG_TYPE_PORT:
568 if (*(int*)value == CFG_AUTO_PORT) {
569 result->value = tor_strdup("auto");
570 escape_val = 0;
571 break;
573 /* fall through */
574 case CONFIG_TYPE_INTERVAL:
575 case CONFIG_TYPE_MSEC_INTERVAL:
576 case CONFIG_TYPE_UINT:
577 case CONFIG_TYPE_INT:
578 /* This means every or_options_t uint or bool element
579 * needs to be an int. Not, say, a uint16_t or char. */
580 tor_asprintf(&result->value, "%d", *(int*)value);
581 escape_val = 0; /* Can't need escape. */
582 break;
583 case CONFIG_TYPE_MEMUNIT:
584 tor_asprintf(&result->value, U64_FORMAT,
585 U64_PRINTF_ARG(*(uint64_t*)value));
586 escape_val = 0; /* Can't need escape. */
587 break;
588 case CONFIG_TYPE_DOUBLE:
589 tor_asprintf(&result->value, "%f", *(double*)value);
590 escape_val = 0; /* Can't need escape. */
591 break;
593 case CONFIG_TYPE_AUTOBOOL:
594 if (*(int*)value == -1) {
595 result->value = tor_strdup("auto");
596 escape_val = 0;
597 break;
599 /* fall through */
600 case CONFIG_TYPE_BOOL:
601 result->value = tor_strdup(*(int*)value ? "1" : "0");
602 escape_val = 0; /* Can't need escape. */
603 break;
604 case CONFIG_TYPE_ROUTERSET:
605 result->value = routerset_to_string(*(routerset_t**)value);
606 break;
607 case CONFIG_TYPE_CSV:
608 if (*(smartlist_t**)value)
609 result->value =
610 smartlist_join_strings(*(smartlist_t**)value, ",", 0, NULL);
611 else
612 result->value = tor_strdup("");
613 break;
614 case CONFIG_TYPE_CSV_INTERVAL:
615 if (*(smartlist_t**)value) {
616 csv_str = smartlist_new();
617 SMARTLIST_FOREACH_BEGIN(*(smartlist_t**)value, int *, i)
619 smartlist_add_asprintf(csv_str, "%d", *i);
621 SMARTLIST_FOREACH_END(i);
622 result->value = smartlist_join_strings(csv_str, ",", 0, NULL);
623 SMARTLIST_FOREACH(csv_str, char *, cp, tor_free(cp));
624 smartlist_free(csv_str);
625 } else
626 result->value = tor_strdup("");
627 break;
628 case CONFIG_TYPE_OBSOLETE:
629 log_fn(LOG_INFO, LD_CONFIG,
630 "You asked me for the value of an obsolete config option '%s'.",
631 key);
632 tor_free(result->key);
633 tor_free(result);
634 return NULL;
635 case CONFIG_TYPE_LINELIST_S:
636 tor_free(result->key);
637 tor_free(result);
638 result = config_lines_dup_and_filter(*(const config_line_t **)value,
639 key);
640 break;
641 case CONFIG_TYPE_LINELIST:
642 case CONFIG_TYPE_LINELIST_V:
643 tor_free(result->key);
644 tor_free(result);
645 result = config_lines_dup(*(const config_line_t**)value);
646 break;
647 default:
648 tor_free(result->key);
649 tor_free(result);
650 log_warn(LD_BUG,"Unknown type %d for known key '%s'",
651 var->type, key);
652 return NULL;
655 if (escape_val) {
656 config_line_t *line;
657 for (line = result; line; line = line->next) {
658 if (line->value && config_value_needs_escape(line->value)) {
659 char *newval = esc_for_log(line->value);
660 tor_free(line->value);
661 line->value = newval;
666 return result;
668 /** Iterate through the linked list of requested options <b>list</b>.
669 * For each item, convert as appropriate and assign to <b>options</b>.
670 * If an item is unrecognized, set *msg and return -1 immediately,
671 * else return 0 for success.
673 * If <b>clear_first</b>, interpret config options as replacing (not
674 * extending) their previous values. If <b>clear_first</b> is set,
675 * then <b>use_defaults</b> to decide if you set to defaults after
676 * clearing, or make the value 0 or NULL.
678 * Here are the use cases:
679 * 1. A non-empty AllowInvalid line in your torrc. Appends to current
680 * if linelist, replaces current if csv.
681 * 2. An empty AllowInvalid line in your torrc. Should clear it.
682 * 3. "RESETCONF AllowInvalid" sets it to default.
683 * 4. "SETCONF AllowInvalid" makes it NULL.
684 * 5. "SETCONF AllowInvalid=foo" clears it and sets it to "foo".
686 * Use_defaults Clear_first
687 * 0 0 "append"
688 * 1 0 undefined, don't use
689 * 0 1 "set to null first"
690 * 1 1 "set to defaults first"
691 * Return 0 on success, -1 on bad key, -2 on bad value.
693 * As an additional special case, if a LINELIST config option has
694 * no value and clear_first is 0, then warn and ignore it.
698 There are three call cases for config_assign() currently.
700 Case one: Torrc entry
701 options_init_from_torrc() calls config_assign(0, 0)
702 calls config_assign_line(0, 0).
703 if value is empty, calls config_reset(0) and returns.
704 calls config_assign_value(), appends.
706 Case two: setconf
707 options_trial_assign() calls config_assign(0, 1)
708 calls config_reset_line(0)
709 calls config_reset(0)
710 calls option_clear().
711 calls config_assign_line(0, 1).
712 if value is empty, returns.
713 calls config_assign_value(), appends.
715 Case three: resetconf
716 options_trial_assign() calls config_assign(1, 1)
717 calls config_reset_line(1)
718 calls config_reset(1)
719 calls option_clear().
720 calls config_assign_value(default)
721 calls config_assign_line(1, 1).
722 returns.
725 config_assign(const config_format_t *fmt, void *options, config_line_t *list,
726 unsigned config_assign_flags, char **msg)
728 config_line_t *p;
729 bitarray_t *options_seen;
730 const int n_options = config_count_options(fmt);
731 const unsigned clear_first = config_assign_flags & CAL_CLEAR_FIRST;
732 const unsigned use_defaults = config_assign_flags & CAL_USE_DEFAULTS;
734 CONFIG_CHECK(fmt, options);
736 /* pass 1: normalize keys */
737 for (p = list; p; p = p->next) {
738 const char *full = config_expand_abbrev(fmt, p->key, 0, 1);
739 if (strcmp(full,p->key)) {
740 tor_free(p->key);
741 p->key = tor_strdup(full);
745 /* pass 2: if we're reading from a resetting source, clear all
746 * mentioned config options, and maybe set to their defaults. */
747 if (clear_first) {
748 for (p = list; p; p = p->next)
749 config_reset_line(fmt, options, p->key, use_defaults);
752 options_seen = bitarray_init_zero(n_options);
753 /* pass 3: assign. */
754 while (list) {
755 int r;
756 if ((r=config_assign_line(fmt, options, list, config_assign_flags,
757 options_seen, msg))) {
758 bitarray_free(options_seen);
759 return r;
761 list = list->next;
763 bitarray_free(options_seen);
765 /** Now we're done assigning a group of options to the configuration.
766 * Subsequent group assignments should _replace_ linelists, not extend
767 * them. */
768 config_mark_lists_fragile(fmt, options);
770 return 0;
773 /** Reset config option <b>var</b> to 0, 0.0, NULL, or the equivalent.
774 * Called from config_reset() and config_free(). */
775 static void
776 config_clear(const config_format_t *fmt, void *options,
777 const config_var_t *var)
779 void *lvalue = STRUCT_VAR_P(options, var->var_offset);
780 (void)fmt; /* unused */
781 switch (var->type) {
782 case CONFIG_TYPE_STRING:
783 case CONFIG_TYPE_FILENAME:
784 tor_free(*(char**)lvalue);
785 break;
786 case CONFIG_TYPE_DOUBLE:
787 *(double*)lvalue = 0.0;
788 break;
789 case CONFIG_TYPE_ISOTIME:
790 *(time_t*)lvalue = 0;
791 break;
792 case CONFIG_TYPE_INTERVAL:
793 case CONFIG_TYPE_MSEC_INTERVAL:
794 case CONFIG_TYPE_UINT:
795 case CONFIG_TYPE_INT:
796 case CONFIG_TYPE_PORT:
797 case CONFIG_TYPE_BOOL:
798 *(int*)lvalue = 0;
799 break;
800 case CONFIG_TYPE_AUTOBOOL:
801 *(int*)lvalue = -1;
802 break;
803 case CONFIG_TYPE_MEMUNIT:
804 *(uint64_t*)lvalue = 0;
805 break;
806 case CONFIG_TYPE_ROUTERSET:
807 if (*(routerset_t**)lvalue) {
808 routerset_free(*(routerset_t**)lvalue);
809 *(routerset_t**)lvalue = NULL;
811 break;
812 case CONFIG_TYPE_CSV:
813 if (*(smartlist_t**)lvalue) {
814 SMARTLIST_FOREACH(*(smartlist_t **)lvalue, char *, cp, tor_free(cp));
815 smartlist_free(*(smartlist_t **)lvalue);
816 *(smartlist_t **)lvalue = NULL;
818 break;
819 case CONFIG_TYPE_CSV_INTERVAL:
820 if (*(smartlist_t**)lvalue) {
821 SMARTLIST_FOREACH(*(smartlist_t **)lvalue, int *, cp, tor_free(cp));
822 smartlist_free(*(smartlist_t **)lvalue);
823 *(smartlist_t **)lvalue = NULL;
825 break;
826 case CONFIG_TYPE_LINELIST:
827 case CONFIG_TYPE_LINELIST_S:
828 config_free_lines(*(config_line_t **)lvalue);
829 *(config_line_t **)lvalue = NULL;
830 break;
831 case CONFIG_TYPE_LINELIST_V:
832 /* handled by linelist_s. */
833 break;
834 case CONFIG_TYPE_OBSOLETE:
835 break;
839 /** Clear the option indexed by <b>var</b> in <b>options</b>. Then if
840 * <b>use_defaults</b>, set it to its default value.
841 * Called by config_init() and option_reset_line() and option_assign_line(). */
842 static void
843 config_reset(const config_format_t *fmt, void *options,
844 const config_var_t *var, int use_defaults)
846 config_line_t *c;
847 char *msg = NULL;
848 CONFIG_CHECK(fmt, options);
849 config_clear(fmt, options, var); /* clear it first */
850 if (!use_defaults)
851 return; /* all done */
852 if (var->initvalue) {
853 c = tor_malloc_zero(sizeof(config_line_t));
854 c->key = tor_strdup(var->name);
855 c->value = tor_strdup(var->initvalue);
856 if (config_assign_value(fmt, options, c, &msg) < 0) {
857 log_warn(LD_BUG, "Failed to assign default: %s", msg);
858 tor_free(msg); /* if this happens it's a bug */
860 config_free_lines(c);
864 /** Release storage held by <b>options</b>. */
865 void
866 config_free(const config_format_t *fmt, void *options)
868 int i;
870 if (!options)
871 return;
873 tor_assert(fmt);
875 for (i=0; fmt->vars[i].name; ++i)
876 config_clear(fmt, options, &(fmt->vars[i]));
877 if (fmt->extra) {
878 config_line_t **linep = STRUCT_VAR_P(options, fmt->extra->var_offset);
879 config_free_lines(*linep);
880 *linep = NULL;
882 tor_free(options);
885 /** Return true iff the option <b>name</b> has the same value in <b>o1</b>
886 * and <b>o2</b>. Must not be called for LINELIST_S or OBSOLETE options.
889 config_is_same(const config_format_t *fmt,
890 const void *o1, const void *o2,
891 const char *name)
893 config_line_t *c1, *c2;
894 int r = 1;
895 CONFIG_CHECK(fmt, o1);
896 CONFIG_CHECK(fmt, o2);
898 c1 = config_get_assigned_option(fmt, o1, name, 0);
899 c2 = config_get_assigned_option(fmt, o2, name, 0);
900 r = config_lines_eq(c1, c2);
901 config_free_lines(c1);
902 config_free_lines(c2);
903 return r;
906 /** Copy storage held by <b>old</b> into a new or_options_t and return it. */
907 void *
908 config_dup(const config_format_t *fmt, const void *old)
910 void *newopts;
911 int i;
912 config_line_t *line;
914 newopts = config_new(fmt);
915 for (i=0; fmt->vars[i].name; ++i) {
916 if (fmt->vars[i].type == CONFIG_TYPE_LINELIST_S)
917 continue;
918 if (fmt->vars[i].type == CONFIG_TYPE_OBSOLETE)
919 continue;
920 line = config_get_assigned_option(fmt, old, fmt->vars[i].name, 0);
921 if (line) {
922 char *msg = NULL;
923 if (config_assign(fmt, newopts, line, 0, &msg) < 0) {
924 log_err(LD_BUG, "config_get_assigned_option() generated "
925 "something we couldn't config_assign(): %s", msg);
926 tor_free(msg);
927 tor_assert(0);
930 config_free_lines(line);
932 return newopts;
934 /** Set all vars in the configuration object <b>options</b> to their default
935 * values. */
936 void
937 config_init(const config_format_t *fmt, void *options)
939 int i;
940 const config_var_t *var;
941 CONFIG_CHECK(fmt, options);
943 for (i=0; fmt->vars[i].name; ++i) {
944 var = &fmt->vars[i];
945 if (!var->initvalue)
946 continue; /* defaults to NULL or 0 */
947 config_reset(fmt, options, var, 1);
951 /** Allocate and return a new string holding the written-out values of the vars
952 * in 'options'. If 'minimal', do not write out any default-valued vars.
953 * Else, if comment_defaults, write default values as comments.
955 char *
956 config_dump(const config_format_t *fmt, const void *default_options,
957 const void *options, int minimal,
958 int comment_defaults)
960 smartlist_t *elements;
961 const void *defaults = default_options;
962 void *defaults_tmp = NULL;
963 config_line_t *line, *assigned;
964 char *result;
965 int i;
966 char *msg = NULL;
968 if (defaults == NULL) {
969 defaults = defaults_tmp = config_new(fmt);
970 config_init(fmt, defaults_tmp);
973 /* XXX use a 1 here so we don't add a new log line while dumping */
974 if (default_options == NULL) {
975 if (fmt->validate_fn(NULL, defaults_tmp, defaults_tmp, 1, &msg) < 0) {
976 log_err(LD_BUG, "Failed to validate default config: %s", msg);
977 tor_free(msg);
978 tor_assert(0);
982 elements = smartlist_new();
983 for (i=0; fmt->vars[i].name; ++i) {
984 int comment_option = 0;
985 if (fmt->vars[i].type == CONFIG_TYPE_OBSOLETE ||
986 fmt->vars[i].type == CONFIG_TYPE_LINELIST_S)
987 continue;
988 /* Don't save 'hidden' control variables. */
989 if (!strcmpstart(fmt->vars[i].name, "__"))
990 continue;
991 if (minimal && config_is_same(fmt, options, defaults, fmt->vars[i].name))
992 continue;
993 else if (comment_defaults &&
994 config_is_same(fmt, options, defaults, fmt->vars[i].name))
995 comment_option = 1;
997 line = assigned =
998 config_get_assigned_option(fmt, options, fmt->vars[i].name, 1);
1000 for (; line; line = line->next) {
1001 if (!strcmpstart(line->key, "__")) {
1002 /* This check detects "hidden" variables inside LINELIST_V structures.
1004 continue;
1006 smartlist_add_asprintf(elements, "%s%s %s\n",
1007 comment_option ? "# " : "",
1008 line->key, line->value);
1010 config_free_lines(assigned);
1013 if (fmt->extra) {
1014 line = *(config_line_t**)STRUCT_VAR_P(options, fmt->extra->var_offset);
1015 for (; line; line = line->next) {
1016 smartlist_add_asprintf(elements, "%s %s\n", line->key, line->value);
1020 result = smartlist_join_strings(elements, "", 0, NULL);
1021 SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp));
1022 smartlist_free(elements);
1023 if (defaults_tmp)
1024 config_free(fmt, defaults_tmp);
1025 return result;
1028 /** Mapping from a unit name to a multiplier for converting that unit into a
1029 * base unit. Used by config_parse_unit. */
1030 struct unit_table_t {
1031 const char *unit; /**< The name of the unit */
1032 uint64_t multiplier; /**< How many of the base unit appear in this unit */
1035 /** Table to map the names of memory units to the number of bytes they
1036 * contain. */
1037 static struct unit_table_t memory_units[] = {
1038 { "", 1 },
1039 { "b", 1<< 0 },
1040 { "byte", 1<< 0 },
1041 { "bytes", 1<< 0 },
1042 { "kb", 1<<10 },
1043 { "kbyte", 1<<10 },
1044 { "kbytes", 1<<10 },
1045 { "kilobyte", 1<<10 },
1046 { "kilobytes", 1<<10 },
1047 { "kilobits", 1<<7 },
1048 { "kilobit", 1<<7 },
1049 { "kbits", 1<<7 },
1050 { "kbit", 1<<7 },
1051 { "m", 1<<20 },
1052 { "mb", 1<<20 },
1053 { "mbyte", 1<<20 },
1054 { "mbytes", 1<<20 },
1055 { "megabyte", 1<<20 },
1056 { "megabytes", 1<<20 },
1057 { "megabits", 1<<17 },
1058 { "megabit", 1<<17 },
1059 { "mbits", 1<<17 },
1060 { "mbit", 1<<17 },
1061 { "gb", 1<<30 },
1062 { "gbyte", 1<<30 },
1063 { "gbytes", 1<<30 },
1064 { "gigabyte", 1<<30 },
1065 { "gigabytes", 1<<30 },
1066 { "gigabits", 1<<27 },
1067 { "gigabit", 1<<27 },
1068 { "gbits", 1<<27 },
1069 { "gbit", 1<<27 },
1070 { "tb", U64_LITERAL(1)<<40 },
1071 { "tbyte", U64_LITERAL(1)<<40 },
1072 { "tbytes", U64_LITERAL(1)<<40 },
1073 { "terabyte", U64_LITERAL(1)<<40 },
1074 { "terabytes", U64_LITERAL(1)<<40 },
1075 { "terabits", U64_LITERAL(1)<<37 },
1076 { "terabit", U64_LITERAL(1)<<37 },
1077 { "tbits", U64_LITERAL(1)<<37 },
1078 { "tbit", U64_LITERAL(1)<<37 },
1079 { NULL, 0 },
1082 /** Table to map the names of time units to the number of seconds they
1083 * contain. */
1084 static struct unit_table_t time_units[] = {
1085 { "", 1 },
1086 { "second", 1 },
1087 { "seconds", 1 },
1088 { "minute", 60 },
1089 { "minutes", 60 },
1090 { "hour", 60*60 },
1091 { "hours", 60*60 },
1092 { "day", 24*60*60 },
1093 { "days", 24*60*60 },
1094 { "week", 7*24*60*60 },
1095 { "weeks", 7*24*60*60 },
1096 { "month", 2629728, }, /* about 30.437 days */
1097 { "months", 2629728, },
1098 { NULL, 0 },
1101 /** Table to map the names of time units to the number of milliseconds
1102 * they contain. */
1103 static struct unit_table_t time_msec_units[] = {
1104 { "", 1 },
1105 { "msec", 1 },
1106 { "millisecond", 1 },
1107 { "milliseconds", 1 },
1108 { "second", 1000 },
1109 { "seconds", 1000 },
1110 { "minute", 60*1000 },
1111 { "minutes", 60*1000 },
1112 { "hour", 60*60*1000 },
1113 { "hours", 60*60*1000 },
1114 { "day", 24*60*60*1000 },
1115 { "days", 24*60*60*1000 },
1116 { "week", 7*24*60*60*1000 },
1117 { "weeks", 7*24*60*60*1000 },
1118 { NULL, 0 },
1121 /** Parse a string <b>val</b> containing a number, zero or more
1122 * spaces, and an optional unit string. If the unit appears in the
1123 * table <b>u</b>, then multiply the number by the unit multiplier.
1124 * On success, set *<b>ok</b> to 1 and return this product.
1125 * Otherwise, set *<b>ok</b> to 0.
1127 static uint64_t
1128 config_parse_units(const char *val, struct unit_table_t *u, int *ok)
1130 uint64_t v = 0;
1131 double d = 0;
1132 int use_float = 0;
1133 char *cp;
1135 tor_assert(ok);
1137 v = tor_parse_uint64(val, 10, 0, UINT64_MAX, ok, &cp);
1138 if (!*ok || (cp && *cp == '.')) {
1139 d = tor_parse_double(val, 0, (double)UINT64_MAX, ok, &cp);
1140 if (!*ok)
1141 goto done;
1142 use_float = 1;
1145 if (!cp) {
1146 *ok = 1;
1147 v = use_float ? DBL_TO_U64(d) : v;
1148 goto done;
1151 cp = (char*) eat_whitespace(cp);
1153 for ( ;u->unit;++u) {
1154 if (!strcasecmp(u->unit, cp)) {
1155 if (use_float)
1156 v = (uint64_t)(u->multiplier * d);
1157 else
1158 v *= u->multiplier;
1159 *ok = 1;
1160 goto done;
1163 log_warn(LD_CONFIG, "Unknown unit '%s'.", cp);
1164 *ok = 0;
1165 done:
1167 if (*ok)
1168 return v;
1169 else
1170 return 0;
1173 /** Parse a string in the format "number unit", where unit is a unit of
1174 * information (byte, KB, M, etc). On success, set *<b>ok</b> to true
1175 * and return the number of bytes specified. Otherwise, set
1176 * *<b>ok</b> to false and return 0. */
1177 static uint64_t
1178 config_parse_memunit(const char *s, int *ok)
1180 uint64_t u = config_parse_units(s, memory_units, ok);
1181 return u;
1184 /** Parse a string in the format "number unit", where unit is a unit of
1185 * time in milliseconds. On success, set *<b>ok</b> to true and return
1186 * the number of milliseconds in the provided interval. Otherwise, set
1187 * *<b>ok</b> to 0 and return -1. */
1188 static int
1189 config_parse_msec_interval(const char *s, int *ok)
1191 uint64_t r;
1192 r = config_parse_units(s, time_msec_units, ok);
1193 if (r > INT_MAX) {
1194 log_warn(LD_CONFIG, "Msec interval '%s' is too long", s);
1195 *ok = 0;
1196 return -1;
1198 return (int)r;
1201 /** Parse a string in the format "number unit", where unit is a unit of time.
1202 * On success, set *<b>ok</b> to true and return the number of seconds in
1203 * the provided interval. Otherwise, set *<b>ok</b> to 0 and return -1.
1205 static int
1206 config_parse_interval(const char *s, int *ok)
1208 uint64_t r;
1209 r = config_parse_units(s, time_units, ok);
1210 if (r > INT_MAX) {
1211 log_warn(LD_CONFIG, "Interval '%s' is too long", s);
1212 *ok = 0;
1213 return -1;
1215 return (int)r;