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 key
= join(section
, ".", lvalue
, NULL
);
95 p
= lookup(key
, strlen(key
));
104 *data
= (uint8_t*) userdata
+ p
->offset
;
108 /* Run the user supplied parser for an assignment */
109 static int next_assignment(
110 const char *filename
,
112 ConfigItemLookup lookup
,
120 ConfigParserCallback func
= NULL
;
131 r
= lookup(table
, section
, lvalue
, &func
, <ype
, &data
, userdata
);
137 return func(filename
, line
, section
, lvalue
, ltype
, rvalue
, data
, userdata
);
142 /* Warn about unknown non-extension fields. */
143 if (!relaxed
&& !startswith(lvalue
, "X-"))
144 log_info("[%s:%u] Unknown lvalue '%s' in section '%s'. Ignoring.", filename
, line
, lvalue
, section
);
149 /* Parse a variable assignment line */
150 static int parse_line(
151 const char *filename
,
153 const char *sections
,
154 ConfigItemLookup lookup
,
173 if (strchr(COMMENTS
, *l
))
176 if (startswith(l
, ".include ")) {
180 fn
= file_in_same_dir(filename
, strstrip(l
+9));
184 r
= config_parse(fn
, NULL
, sections
, lookup
, table
, relaxed
, userdata
);
198 log_error("[%s:%u] Invalid section header.", filename
, line
);
202 n
= strndup(l
+1, k
-2);
206 if (sections
&& !nulstr_contains(sections
, n
)) {
209 log_info("[%s:%u] Unknown section '%s'. Ignoring.", filename
, line
, n
);
221 if (sections
&& !*section
)
226 log_error("[%s:%u] Missing '='.", filename
, line
);
233 return next_assignment(
245 /* Go through the file and parse each line */
247 const char *filename
,
249 const char *sections
,
250 ConfigItemLookup lookup
,
256 char *section
= NULL
;
259 char *continuation
= NULL
;
265 f
= fopen(filename
, "re");
268 log_error("Failed to open configuration file '%s': %s", filename
, strerror(-r
));
276 char l
[LINE_MAX
], *p
, *c
= NULL
, *e
;
277 bool escaped
= false;
279 if (!fgets(l
, sizeof(l
), f
)) {
284 log_error("Failed to read configuration file '%s': %s", filename
, strerror(-r
));
291 c
= strappend(continuation
, l
);
303 for (e
= p
; *e
; e
++) {
316 continuation
= strdup(l
);
326 r
= parse_line(filename
,
353 int config_parse_int(
354 const char *filename
,
371 if ((r
= safe_atoi(rvalue
, i
)) < 0) {
372 log_error("[%s:%u] Failed to parse numeric value, ingoring: %s", filename
, line
, rvalue
);
379 int config_parse_long(
380 const char *filename
,
397 if ((r
= safe_atoli(rvalue
, i
)) < 0) {
398 log_error("[%s:%u] Failed to parse numeric value, ignoring: %s", filename
, line
, rvalue
);
405 int config_parse_uint64(
406 const char *filename
,
423 if ((r
= safe_atou64(rvalue
, u
)) < 0) {
424 log_error("[%s:%u] Failed to parse numeric value, ignoring: %s", filename
, line
, rvalue
);
431 int config_parse_unsigned(
432 const char *filename
,
449 if ((r
= safe_atou(rvalue
, u
)) < 0) {
450 log_error("[%s:%u] Failed to parse numeric value: %s", filename
, line
, rvalue
);
457 int config_parse_size(
458 const char *filename
,
476 if ((r
= safe_atou(rvalue
, &u
)) < 0) {
477 log_error("[%s:%u] Failed to parse numeric value, ignoring: %s", filename
, line
, rvalue
);
485 int config_parse_bool(
486 const char *filename
,
503 if ((k
= parse_boolean(rvalue
)) < 0) {
504 log_error("[%s:%u] Failed to parse boolean value, ignoring: %s", filename
, line
, rvalue
);
512 int config_parse_string(
513 const char *filename
,
531 if (!(n
= strdup(rvalue
)))
542 int config_parse_path(
543 const char *filename
,
560 if (!path_is_absolute(rvalue
)) {
561 log_error("[%s:%u] Not an absolute path, ignoring: %s", filename
, line
, rvalue
);
565 if (!(n
= strdup(rvalue
)))
568 path_kill_slashes(n
);
576 int config_parse_strv(
577 const char *filename
,
598 k
= strv_length(*sv
);
599 FOREACH_WORD_QUOTED(w
, l
, rvalue
, state
)
602 if (!(n
= new(char*, k
+1)))
606 for (k
= 0; (*sv
)[k
]; k
++)
611 FOREACH_WORD_QUOTED(w
, l
, rvalue
, state
)
612 if (!(n
[k
++] = cunescape_length(w
, l
)))
629 int config_parse_path_strv(
630 const char *filename
,
652 k
= strv_length(*sv
);
653 FOREACH_WORD_QUOTED(w
, l
, rvalue
, state
)
656 if (!(n
= new(char*, k
+1)))
661 for (; (*sv
)[k
]; k
++)
664 FOREACH_WORD_QUOTED(w
, l
, rvalue
, state
) {
665 if (!(n
[k
] = cunescape_length(w
, l
))) {
670 if (!path_is_absolute(n
[k
])) {
671 log_error("[%s:%u] Not an absolute path, ignoring: %s", filename
, line
, rvalue
);
676 path_kill_slashes(n
[k
]);
696 int config_parse_usec(
697 const char *filename
,
713 if (parse_usec(rvalue
, usec
) < 0) {
714 log_error("[%s:%u] Failed to parse time value, ignoring: %s", filename
, line
, rvalue
);
721 int config_parse_mode(
722 const char *filename
,
741 l
= strtol(rvalue
, &x
, 8);
742 if (!x
|| *x
|| errno
) {
743 log_error("[%s:%u] Failed to parse mode value, ignoring: %s", filename
, line
, rvalue
);
747 if (l
< 0000 || l
> 07777) {
748 log_error("[%s:%u] mode value out of range, ignoring: %s", filename
, line
, rvalue
);