1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
28 #include "conf-parser.h"
34 int config_item_table_lookup(
38 ConfigParserCallback *func,
51 for (t = table; t->lvalue; t++) {
53 if (!streq(lvalue, t->lvalue))
56 if (!streq_ptr(section, t->section))
68 int config_item_perf_lookup(
72 ConfigParserCallback *func,
77 ConfigPerfItemLookup lookup = (ConfigPerfItemLookup) table;
78 const ConfigPerfItem *p;
87 p = lookup(lvalue, strlen(lvalue));
91 key = join(section, ".", lvalue, NULL);
95 p = lookup(key, strlen(key));
104 *data = (uint8_t*) userdata + p->offset;
108 /* Run the user supplied parser for an assignment */
109 static int next_assignment(
110 const char *filename,
112 ConfigItemLookup lookup,
120 ConfigParserCallback func = NULL;
131 r = lookup(table, section, lvalue, &func, <ype, &data, userdata);
137 return func(filename, line, section, lvalue, ltype, rvalue, data, userdata);
142 /* Warn about unknown non-extension fields. */
143 if (!relaxed && !startswith(lvalue, "X-"))
144 log_info("[%s:%u] Unknown lvalue '%s' in section '%s'. Ignoring.", filename, line, lvalue, section);
149 /* Parse a variable assignment line */
150 static int parse_line(
151 const char *filename,
153 const char *sections,
154 ConfigItemLookup lookup,
173 if (strchr(COMMENTS, *l))
176 if (startswith(l, ".include ")) {
180 fn = file_in_same_dir(filename, strstrip(l+9));
184 r = config_parse(fn, NULL, sections, lookup, table, relaxed, userdata);
198 log_error("[%s:%u] Invalid section header.", filename, line);
202 n = strndup(l+1, k-2);
206 if (sections && !nulstr_contains(sections, n)) {
209 log_info("[%s:%u] Unknown section '%s'. Ignoring.", filename, line, n);
221 if (sections && !*section)
226 log_error("[%s:%u] Missing '='.", filename, line);
233 return next_assignment(
245 /* Go through the file and parse each line */
247 const char *filename,
249 const char *sections,
250 ConfigItemLookup lookup,
256 char *section = NULL;
259 char *continuation = NULL;
265 f = fopen(filename, "re");
268 log_error("Failed to open configuration file '%s': %s", filename, strerror(-r));
276 char l[LINE_MAX], *p, *c = NULL, *e;
277 bool escaped = false;
279 if (!fgets(l, sizeof(l), f)) {
284 log_error("Failed to read configuration file '%s': %s", filename, strerror(-r));
291 c = strappend(continuation, l);
303 for (e = p; *e; e++) {
316 continuation = strdup(l);
326 r = parse_line(filename,
353 int config_parse_int(
354 const char *filename,
371 if ((r = safe_atoi(rvalue, i)) < 0) {
372 log_error("[%s:%u] Failed to parse numeric value, ingoring: %s", filename, line, rvalue);
379 int config_parse_long(
380 const char *filename,
397 if ((r = safe_atoli(rvalue, i)) < 0) {
398 log_error("[%s:%u] Failed to parse numeric value, ignoring: %s", filename, line, rvalue);
405 int config_parse_uint64(
406 const char *filename,
423 if ((r = safe_atou64(rvalue, u)) < 0) {
424 log_error("[%s:%u] Failed to parse numeric value, ignoring: %s", filename, line, rvalue);
431 int config_parse_unsigned(
432 const char *filename,
449 if ((r = safe_atou(rvalue, u)) < 0) {
450 log_error("[%s:%u] Failed to parse numeric value: %s", filename, line, rvalue);
457 int config_parse_size(
458 const char *filename,
476 if ((r = safe_atou(rvalue, &u)) < 0) {
477 log_error("[%s:%u] Failed to parse numeric value, ignoring: %s", filename, line, rvalue);
485 int config_parse_bool(
486 const char *filename,
503 if ((k = parse_boolean(rvalue)) < 0) {
504 log_error("[%s:%u] Failed to parse boolean value, ignoring: %s", filename, line, rvalue);
512 int config_parse_string(
513 const char *filename,
531 if (!(n = strdup(rvalue)))
542 int config_parse_path(
543 const char *filename,
560 if (!path_is_absolute(rvalue)) {
561 log_error("[%s:%u] Not an absolute path, ignoring: %s", filename, line, rvalue);
565 if (!(n = strdup(rvalue)))
568 path_kill_slashes(n);
576 int config_parse_strv(
577 const char *filename,
598 k = strv_length(*sv);
599 FOREACH_WORD_QUOTED(w, l, rvalue, state)
602 if (!(n = new(char*, k+1)))
606 for (k = 0; (*sv)[k]; k++)
611 FOREACH_WORD_QUOTED(w, l, rvalue, state)
612 if (!(n[k++] = cunescape_length(w, l)))
629 int config_parse_path_strv(
630 const char *filename,
652 k = strv_length(*sv);
653 FOREACH_WORD_QUOTED(w, l, rvalue, state)
656 if (!(n = new(char*, k+1)))
661 for (; (*sv)[k]; k++)
664 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
665 if (!(n[k] = cunescape_length(w, l))) {
670 if (!path_is_absolute(n[k])) {
671 log_error("[%s:%u] Not an absolute path, ignoring: %s", filename, line, rvalue);
676 path_kill_slashes(n[k]);
696 int config_parse_usec(
697 const char *filename,
713 if (parse_usec(rvalue, usec) < 0) {
714 log_error("[%s:%u] Failed to parse time value, ignoring: %s", filename, line, rvalue);
721 int config_parse_mode(
722 const char *filename,
741 l = strtol(rvalue, &x, 8);
742 if (!x || *x || errno) {
743 log_error("[%s:%u] Failed to parse mode value, ignoring: %s", filename, line, rvalue);
747 if (l < 0000 || l > 07777) {
748 log_error("[%s:%u] mode value out of range, ignoring: %s", filename, line, rvalue);