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 if (asprintf(&key, "%s.%s", section, lvalue) < 0)
94 p = lookup(key, strlen(key));
103 *data = (uint8_t*) userdata + p->offset;
107 /* Run the user supplied parser for an assignment */
108 static int next_assignment(
109 const char *filename,
111 ConfigItemLookup lookup,
119 ConfigParserCallback func = NULL;
130 r = lookup(table, section, lvalue, &func, <ype, &data, userdata);
136 return func(filename, line, section, lvalue, ltype, rvalue, data, userdata);
141 /* Warn about unknown non-extension fields. */
142 if (!relaxed && !startswith(lvalue, "X-"))
143 log_info("[%s:%u] Unknown lvalue '%s' in section '%s'. Ignoring.", filename, line, lvalue, section);
148 /* Parse a variable assignment line */
149 static int parse_line(
150 const char *filename,
152 const char *sections,
153 ConfigItemLookup lookup,
172 if (strchr(COMMENTS, *l))
175 if (startswith(l, ".include ")) {
179 fn = file_in_same_dir(filename, strstrip(l+9));
183 r = config_parse(fn, NULL, sections, lookup, table, relaxed, userdata);
197 log_error("[%s:%u] Invalid section header.", filename, line);
201 n = strndup(l+1, k-2);
205 if (sections && !nulstr_contains(sections, n)) {
208 log_info("[%s:%u] Unknown section '%s'. Ignoring.", filename, line, n);
220 if (sections && !*section)
225 log_error("[%s:%u] Missing '='.", filename, line);
232 return next_assignment(
244 /* Go through the file and parse each line */
246 const char *filename,
248 const char *sections,
249 ConfigItemLookup lookup,
255 char *section = NULL;
258 char *continuation = NULL;
264 f = fopen(filename, "re");
267 log_error("Failed to open configuration file '%s': %s", filename, strerror(-r));
275 char l[LINE_MAX], *p, *c = NULL, *e;
276 bool escaped = false;
278 if (!fgets(l, sizeof(l), f)) {
283 log_error("Failed to read configuration file '%s': %s", filename, strerror(-r));
290 c = strappend(continuation, l);
302 for (e = p; *e; e++) {
315 continuation = strdup(l);
325 r = parse_line(filename,
352 int config_parse_int(
353 const char *filename,
370 if ((r = safe_atoi(rvalue, i)) < 0) {
371 log_error("[%s:%u] Failed to parse numeric value, ingoring: %s", filename, line, rvalue);
378 int config_parse_long(
379 const char *filename,
396 if ((r = safe_atoli(rvalue, i)) < 0) {
397 log_error("[%s:%u] Failed to parse numeric value, ignoring: %s", filename, line, rvalue);
404 int config_parse_uint64(
405 const char *filename,
422 if ((r = safe_atou64(rvalue, u)) < 0) {
423 log_error("[%s:%u] Failed to parse numeric value, ignoring: %s", filename, line, rvalue);
430 int config_parse_unsigned(
431 const char *filename,
448 if ((r = safe_atou(rvalue, u)) < 0) {
449 log_error("[%s:%u] Failed to parse numeric value: %s", filename, line, rvalue);
456 int config_parse_size(
457 const char *filename,
475 if ((r = safe_atou(rvalue, &u)) < 0) {
476 log_error("[%s:%u] Failed to parse numeric value, ignoring: %s", filename, line, rvalue);
484 int config_parse_bool(
485 const char *filename,
502 if ((k = parse_boolean(rvalue)) < 0) {
503 log_error("[%s:%u] Failed to parse boolean value, ignoring: %s", filename, line, rvalue);
511 int config_parse_string(
512 const char *filename,
530 if (!(n = strdup(rvalue)))
541 int config_parse_path(
542 const char *filename,
559 if (!path_is_absolute(rvalue)) {
560 log_error("[%s:%u] Not an absolute path, ignoring: %s", filename, line, rvalue);
564 if (!(n = strdup(rvalue)))
567 path_kill_slashes(n);
575 int config_parse_strv(
576 const char *filename,
597 k = strv_length(*sv);
598 FOREACH_WORD_QUOTED(w, l, rvalue, state)
601 if (!(n = new(char*, k+1)))
605 for (k = 0; (*sv)[k]; k++)
610 FOREACH_WORD_QUOTED(w, l, rvalue, state)
611 if (!(n[k++] = cunescape_length(w, l)))
628 int config_parse_path_strv(
629 const char *filename,
651 k = strv_length(*sv);
652 FOREACH_WORD_QUOTED(w, l, rvalue, state)
655 if (!(n = new(char*, k+1)))
660 for (; (*sv)[k]; k++)
663 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
664 if (!(n[k] = cunescape_length(w, l))) {
669 if (!path_is_absolute(n[k])) {
670 log_error("[%s:%u] Not an absolute path, ignoring: %s", filename, line, rvalue);
675 path_kill_slashes(n[k]);
695 int config_parse_usec(
696 const char *filename,
712 if (parse_usec(rvalue, usec) < 0) {
713 log_error("[%s:%u] Failed to parse time value, ignoring: %s", filename, line, rvalue);
720 int config_parse_mode(
721 const char *filename,
740 l = strtol(rvalue, &x, 8);
741 if (!x || *x || errno) {
742 log_error("[%s:%u] Failed to parse mode value, ignoring: %s", filename, line, rvalue);
746 if (l < 0000 || l > 07777) {
747 log_error("[%s:%u] mode value out of range, ignoring: %s", filename, line, rvalue);