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) {
225 log_info("[%s:%u] Assignment outside of section. Ignoring.", filename, line);
232 log_error("[%s:%u] Missing '='.", filename, line);
239 return next_assignment(
251 /* Go through the file and parse each line */
253 const char *filename,
255 const char *sections,
256 ConfigItemLookup lookup,
262 char *section = NULL;
265 char *continuation = NULL;
271 f = fopen(filename, "re");
274 log_error("Failed to open configuration file '%s': %s", filename, strerror(-r));
282 char l[LINE_MAX], *p, *c = NULL, *e;
283 bool escaped = false;
285 if (!fgets(l, sizeof(l), f)) {
290 log_error("Failed to read configuration file '%s': %s", filename, strerror(-r));
297 c = strappend(continuation, l);
309 for (e = p; *e; e++) {
322 continuation = strdup(l);
332 r = parse_line(filename,
359 int config_parse_int(
360 const char *filename,
377 if ((r = safe_atoi(rvalue, i)) < 0) {
378 log_error("[%s:%u] Failed to parse numeric value, ingoring: %s", filename, line, rvalue);
385 int config_parse_long(
386 const char *filename,
403 if ((r = safe_atoli(rvalue, i)) < 0) {
404 log_error("[%s:%u] Failed to parse numeric value, ignoring: %s", filename, line, rvalue);
411 int config_parse_uint64(
412 const char *filename,
429 if ((r = safe_atou64(rvalue, u)) < 0) {
430 log_error("[%s:%u] Failed to parse numeric value, ignoring: %s", filename, line, rvalue);
437 int config_parse_unsigned(
438 const char *filename,
455 if ((r = safe_atou(rvalue, u)) < 0) {
456 log_error("[%s:%u] Failed to parse numeric value: %s", filename, line, rvalue);
463 int config_parse_bytes_size(
464 const char *filename,
481 if (parse_bytes(rvalue, &o) < 0 || (off_t) (size_t) o != o) {
482 log_error("[%s:%u] Failed to parse byte value, ignoring: %s", filename, line, rvalue);
491 int config_parse_bytes_off(
492 const char *filename,
508 assert_cc(sizeof(off_t) == sizeof(uint64_t));
510 if (parse_bytes(rvalue, bytes) < 0) {
511 log_error("[%s:%u] Failed to parse bytes value, ignoring: %s", filename, line, rvalue);
518 int config_parse_bool(
519 const char *filename,
536 if ((k = parse_boolean(rvalue)) < 0) {
537 log_error("[%s:%u] Failed to parse boolean value, ignoring: %s", filename, line, rvalue);
545 int config_parse_tristate(
546 const char *filename,
563 /* Tristates are like booleans, but can also take the 'default' value, i.e. "-1" */
565 k = parse_boolean(rvalue);
567 log_error("[%s:%u] Failed to parse boolean value, ignoring: %s", filename, line, rvalue);
575 int config_parse_string(
576 const char *filename,
593 n = cunescape(rvalue);
597 if (!utf8_is_valid(n)) {
598 log_error("[%s:%u] String is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
614 int config_parse_path(
615 const char *filename,
632 if (!utf8_is_valid(rvalue)) {
633 log_error("[%s:%u] Path is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
637 if (!path_is_absolute(rvalue)) {
638 log_error("[%s:%u] Not an absolute path, ignoring: %s", filename, line, rvalue);
646 path_kill_slashes(n);
654 int config_parse_strv(
655 const char *filename,
677 k = strv_length(*sv);
678 FOREACH_WORD_QUOTED(w, l, rvalue, state)
686 for (k = 0; (*sv)[k]; k++)
691 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
692 n[k] = cunescape_length(w, l);
698 if (!utf8_is_valid(n[k])) {
699 log_error("[%s:%u] String is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
721 int config_parse_path_strv(
722 const char *filename,
744 k = strv_length(*sv);
745 FOREACH_WORD_QUOTED(w, l, rvalue, state)
754 for (; (*sv)[k]; k++)
757 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
758 n[k] = strndup(w, l);
764 if (!utf8_is_valid(n[k])) {
765 log_error("[%s:%u] Path is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
770 if (!path_is_absolute(n[k])) {
771 log_error("[%s:%u] Not an absolute path, ignoring: %s", filename, line, rvalue);
776 path_kill_slashes(n[k]);
794 int config_parse_usec(
795 const char *filename,
811 if (parse_usec(rvalue, usec) < 0) {
812 log_error("[%s:%u] Failed to parse time value, ignoring: %s", filename, line, rvalue);
819 int config_parse_mode(
820 const char *filename,
839 l = strtol(rvalue, &x, 8);
840 if (!x || *x || errno) {
841 log_error("[%s:%u] Failed to parse mode value, ignoring: %s", filename, line, rvalue);
845 if (l < 0000 || l > 07777) {
846 log_error("[%s:%u] mode value out of range, ignoring: %s", filename, line, rvalue);