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"
34 #include "path-util.h"
36 int config_item_table_lookup(
40 ConfigParserCallback *func,
53 for (t = table; t->lvalue; t++) {
55 if (!streq(lvalue, t->lvalue))
58 if (!streq_ptr(section, t->section))
70 int config_item_perf_lookup(
74 ConfigParserCallback *func,
79 ConfigPerfItemLookup lookup = (ConfigPerfItemLookup) table;
80 const ConfigPerfItem *p;
89 p = lookup(lvalue, strlen(lvalue));
93 key = join(section, ".", lvalue, NULL);
97 p = lookup(key, strlen(key));
106 *data = (uint8_t*) userdata + p->offset;
110 /* Run the user supplied parser for an assignment */
111 static int next_assignment(
112 const char *filename,
114 ConfigItemLookup lookup,
122 ConfigParserCallback func = NULL;
133 r = lookup(table, section, lvalue, &func, <ype, &data, userdata);
139 return func(filename, line, section, lvalue, ltype, rvalue, data, userdata);
144 /* Warn about unknown non-extension fields. */
145 if (!relaxed && !startswith(lvalue, "X-"))
146 log_info("[%s:%u] Unknown lvalue '%s' in section '%s'. Ignoring.", filename, line, lvalue, section);
151 /* Parse a variable assignment line */
152 static int parse_line(
153 const char *filename,
155 const char *sections,
156 ConfigItemLookup lookup,
175 if (strchr(COMMENTS, *l))
178 if (startswith(l, ".include ")) {
182 fn = file_in_same_dir(filename, strstrip(l+9));
186 r = config_parse(fn, NULL, sections, lookup, table, relaxed, userdata);
200 log_error("[%s:%u] Invalid section header.", filename, line);
204 n = strndup(l+1, k-2);
208 if (sections && !nulstr_contains(sections, n)) {
211 log_info("[%s:%u] Unknown section '%s'. Ignoring.", filename, line, n);
223 if (sections && !*section) {
226 log_info("[%s:%u] Assignment outside of section. Ignoring.", filename, line);
233 log_error("[%s:%u] Missing '='.", filename, line);
240 return next_assignment(
252 /* Go through the file and parse each line */
254 const char *filename,
256 const char *sections,
257 ConfigItemLookup lookup,
263 char *section = NULL;
266 char *continuation = NULL;
272 f = fopen(filename, "re");
275 log_error("Failed to open configuration file '%s': %s", filename, strerror(-r));
283 char l[LINE_MAX], *p, *c = NULL, *e;
284 bool escaped = false;
286 if (!fgets(l, sizeof(l), f)) {
291 log_error("Failed to read configuration file '%s': %s", filename, strerror(-r));
298 c = strappend(continuation, l);
310 for (e = p; *e; e++) {
323 continuation = strdup(l);
333 r = parse_line(filename,
360 int config_parse_int(
361 const char *filename,
378 if ((r = safe_atoi(rvalue, i)) < 0) {
379 log_error("[%s:%u] Failed to parse numeric value, ingoring: %s", filename, line, rvalue);
386 int config_parse_long(
387 const char *filename,
404 if ((r = safe_atoli(rvalue, i)) < 0) {
405 log_error("[%s:%u] Failed to parse numeric value, ignoring: %s", filename, line, rvalue);
412 int config_parse_uint64(
413 const char *filename,
430 if ((r = safe_atou64(rvalue, u)) < 0) {
431 log_error("[%s:%u] Failed to parse numeric value, ignoring: %s", filename, line, rvalue);
438 int config_parse_unsigned(
439 const char *filename,
456 if ((r = safe_atou(rvalue, u)) < 0) {
457 log_error("[%s:%u] Failed to parse numeric value: %s", filename, line, rvalue);
464 int config_parse_bytes_size(
465 const char *filename,
482 if (parse_bytes(rvalue, &o) < 0 || (off_t) (size_t) o != o) {
483 log_error("[%s:%u] Failed to parse byte value, ignoring: %s", filename, line, rvalue);
492 int config_parse_bytes_off(
493 const char *filename,
509 assert_cc(sizeof(off_t) == sizeof(uint64_t));
511 if (parse_bytes(rvalue, bytes) < 0) {
512 log_error("[%s:%u] Failed to parse bytes value, ignoring: %s", filename, line, rvalue);
519 int config_parse_bool(
520 const char *filename,
537 if ((k = parse_boolean(rvalue)) < 0) {
538 log_error("[%s:%u] Failed to parse boolean value, ignoring: %s", filename, line, rvalue);
546 int config_parse_tristate(
547 const char *filename,
564 /* Tristates are like booleans, but can also take the 'default' value, i.e. "-1" */
566 k = parse_boolean(rvalue);
568 log_error("[%s:%u] Failed to parse boolean value, ignoring: %s", filename, line, rvalue);
576 int config_parse_string(
577 const char *filename,
594 n = cunescape(rvalue);
598 if (!utf8_is_valid(n)) {
599 log_error("[%s:%u] String is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
615 int config_parse_path(
616 const char *filename,
633 if (!utf8_is_valid(rvalue)) {
634 log_error("[%s:%u] Path is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
638 if (!path_is_absolute(rvalue)) {
639 log_error("[%s:%u] Not an absolute path, ignoring: %s", filename, line, rvalue);
647 path_kill_slashes(n);
655 int config_parse_strv(
656 const char *filename,
678 k = strv_length(*sv);
679 FOREACH_WORD_QUOTED(w, l, rvalue, state)
687 for (k = 0; (*sv)[k]; k++)
692 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
693 n[k] = cunescape_length(w, l);
699 if (!utf8_is_valid(n[k])) {
700 log_error("[%s:%u] String is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
722 int config_parse_path_strv(
723 const char *filename,
745 k = strv_length(*sv);
746 FOREACH_WORD_QUOTED(w, l, rvalue, state)
755 for (; (*sv)[k]; k++)
758 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
759 n[k] = strndup(w, l);
765 if (!utf8_is_valid(n[k])) {
766 log_error("[%s:%u] Path is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
771 if (!path_is_absolute(n[k])) {
772 log_error("[%s:%u] Not an absolute path, ignoring: %s", filename, line, rvalue);
777 path_kill_slashes(n[k]);
795 int config_parse_usec(
796 const char *filename,
812 if (parse_usec(rvalue, usec) < 0) {
813 log_error("[%s:%u] Failed to parse time value, ignoring: %s", filename, line, rvalue);
820 int config_parse_nsec(
821 const char *filename,
837 if (parse_nsec(rvalue, nsec) < 0) {
838 log_error("[%s:%u] Failed to parse time value, ignoring: %s", filename, line, rvalue);
845 int config_parse_mode(
846 const char *filename,
865 l = strtol(rvalue, &x, 8);
866 if (!x || *x || errno) {
867 log_error("[%s:%u] Failed to parse mode value, ignoring: %s", filename, line, rvalue);
871 if (l < 0000 || l > 07777) {
872 log_error("[%s:%u] mode value out of range, ignoring: %s", filename, line, rvalue);
880 int config_parse_facility(
881 const char *filename,
898 x = log_facility_unshifted_from_string(rvalue);
900 log_error("[%s:%u] Failed to parse log facility, ignoring: %s", filename, line, rvalue);
904 *o = (x << 3) | LOG_PRI(*o);
909 int config_parse_level(
910 const char *filename,
927 x = log_level_from_string(rvalue);
929 log_error("[%s:%u] Failed to parse log level, ignoring: %s", filename, line, rvalue);
933 *o = (*o & LOG_FACMASK) | x;