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"
35 int config_item_table_lookup(
39 ConfigParserCallback *func,
52 for (t = table; t->lvalue; t++) {
54 if (!streq(lvalue, t->lvalue))
57 if (!streq_ptr(section, t->section))
69 int config_item_perf_lookup(
73 ConfigParserCallback *func,
78 ConfigPerfItemLookup lookup = (ConfigPerfItemLookup) table;
79 const ConfigPerfItem *p;
88 p = lookup(lvalue, strlen(lvalue));
92 key = join(section, ".", lvalue, NULL);
96 p = lookup(key, strlen(key));
105 *data = (uint8_t*) userdata + p->offset;
109 /* Run the user supplied parser for an assignment */
110 static int next_assignment(
111 const char *filename,
113 ConfigItemLookup lookup,
121 ConfigParserCallback func = NULL;
132 r = lookup(table, section, lvalue, &func, <ype, &data, userdata);
138 return func(filename, line, section, lvalue, ltype, rvalue, data, userdata);
143 /* Warn about unknown non-extension fields. */
144 if (!relaxed && !startswith(lvalue, "X-"))
145 log_info("[%s:%u] Unknown lvalue '%s' in section '%s'. Ignoring.", filename, line, lvalue, section);
150 /* Parse a variable assignment line */
151 static int parse_line(
152 const char *filename,
154 const char *sections,
155 ConfigItemLookup lookup,
174 if (strchr(COMMENTS, *l))
177 if (startswith(l, ".include ")) {
181 fn = file_in_same_dir(filename, strstrip(l+9));
185 r = config_parse(fn, NULL, sections, lookup, table, relaxed, userdata);
199 log_error("[%s:%u] Invalid section header.", filename, line);
203 n = strndup(l+1, k-2);
207 if (sections && !nulstr_contains(sections, n)) {
210 log_info("[%s:%u] Unknown section '%s'. Ignoring.", filename, line, n);
222 if (sections && !*section)
227 log_error("[%s:%u] Missing '='.", filename, line);
234 return next_assignment(
246 /* Go through the file and parse each line */
248 const char *filename,
250 const char *sections,
251 ConfigItemLookup lookup,
257 char *section = NULL;
260 char *continuation = NULL;
266 f = fopen(filename, "re");
269 log_error("Failed to open configuration file '%s': %s", filename, strerror(-r));
277 char l[LINE_MAX], *p, *c = NULL, *e;
278 bool escaped = false;
280 if (!fgets(l, sizeof(l), f)) {
285 log_error("Failed to read configuration file '%s': %s", filename, strerror(-r));
292 c = strappend(continuation, l);
304 for (e = p; *e; e++) {
317 continuation = strdup(l);
327 r = parse_line(filename,
354 int config_parse_int(
355 const char *filename,
372 if ((r = safe_atoi(rvalue, i)) < 0) {
373 log_error("[%s:%u] Failed to parse numeric value, ingoring: %s", filename, line, rvalue);
380 int config_parse_long(
381 const char *filename,
398 if ((r = safe_atoli(rvalue, i)) < 0) {
399 log_error("[%s:%u] Failed to parse numeric value, ignoring: %s", filename, line, rvalue);
406 int config_parse_uint64(
407 const char *filename,
424 if ((r = safe_atou64(rvalue, u)) < 0) {
425 log_error("[%s:%u] Failed to parse numeric value, ignoring: %s", filename, line, rvalue);
432 int config_parse_unsigned(
433 const char *filename,
450 if ((r = safe_atou(rvalue, u)) < 0) {
451 log_error("[%s:%u] Failed to parse numeric value: %s", filename, line, rvalue);
458 int config_parse_bytes_size(
459 const char *filename,
476 if (parse_bytes(rvalue, &o) < 0 || (off_t) (size_t) o != o) {
477 log_error("[%s:%u] Failed to parse byte value, ignoring: %s", filename, line, rvalue);
486 int config_parse_bytes_off(
487 const char *filename,
503 assert_cc(sizeof(off_t) == sizeof(uint64_t));
505 if (parse_bytes(rvalue, bytes) < 0) {
506 log_error("[%s:%u] Failed to parse bytes value, ignoring: %s", filename, line, rvalue);
513 int config_parse_bool(
514 const char *filename,
531 if ((k = parse_boolean(rvalue)) < 0) {
532 log_error("[%s:%u] Failed to parse boolean value, ignoring: %s", filename, line, rvalue);
540 int config_parse_tristate(
541 const char *filename,
558 /* Tristates are like booleans, but can also take the 'default' value, i.e. "-1" */
560 k = parse_boolean(rvalue);
562 log_error("[%s:%u] Failed to parse boolean value, ignoring: %s", filename, line, rvalue);
570 int config_parse_string(
571 const char *filename,
588 n = cunescape(rvalue);
592 if (!utf8_is_valid(n)) {
593 log_error("[%s:%u] String is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
609 int config_parse_path(
610 const char *filename,
627 if (!utf8_is_valid(rvalue)) {
628 log_error("[%s:%u] Path is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
632 if (!path_is_absolute(rvalue)) {
633 log_error("[%s:%u] Not an absolute path, ignoring: %s", filename, line, rvalue);
641 path_kill_slashes(n);
649 int config_parse_strv(
650 const char *filename,
672 k = strv_length(*sv);
673 FOREACH_WORD_QUOTED(w, l, rvalue, state)
681 for (k = 0; (*sv)[k]; k++)
686 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
687 n[k] = cunescape_length(w, l);
693 if (!utf8_is_valid(n[k])) {
694 log_error("[%s:%u] String is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
716 int config_parse_path_strv(
717 const char *filename,
739 k = strv_length(*sv);
740 FOREACH_WORD_QUOTED(w, l, rvalue, state)
749 for (; (*sv)[k]; k++)
752 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
753 n[k] = strndup(w, l);
759 if (!utf8_is_valid(n[k])) {
760 log_error("[%s:%u] Path is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
765 if (!path_is_absolute(n[k])) {
766 log_error("[%s:%u] Not an absolute path, ignoring: %s", filename, line, rvalue);
771 path_kill_slashes(n[k]);
789 int config_parse_usec(
790 const char *filename,
806 if (parse_usec(rvalue, usec) < 0) {
807 log_error("[%s:%u] Failed to parse time value, ignoring: %s", filename, line, rvalue);
814 int config_parse_mode(
815 const char *filename,
834 l = strtol(rvalue, &x, 8);
835 if (!x || *x || errno) {
836 log_error("[%s:%u] Failed to parse mode value, ignoring: %s", filename, line, rvalue);
840 if (l < 0000 || l > 07777) {
841 log_error("[%s:%u] mode value out of range, ignoring: %s", filename, line, rvalue);