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 Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser 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);