]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/conf-parser.c
util-lib: split out syslog-related calls into syslog-util.[ch]
[thirdparty/systemd.git] / src / shared / conf-parser.c
CommitLineData
d6c9574f 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
ed5bcfbe 2
a7334b09
LP
3/***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
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
a7334b09
LP
11 (at your option) any later version.
12
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
5430f7f2 16 Lesser General Public License for more details.
a7334b09 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
a7334b09
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
ed5bcfbe 22#include <errno.h>
07630cea 23#include <stdio.h>
ed5bcfbe 24#include <stdlib.h>
07630cea 25#include <string.h>
ed5bcfbe 26
f757855e 27#include "sd-messages.h"
07630cea 28
e8461023 29#include "conf-files.h"
6bedfcbb
LP
30#include "conf-parser.h"
31#include "fd-util.h"
f4f15635 32#include "fs-util.h"
16354eff 33#include "log.h"
07630cea 34#include "macro.h"
6bedfcbb 35#include "parse-util.h"
9eb977db 36#include "path-util.h"
f757855e 37#include "signal-util.h"
07630cea
LP
38#include "string-util.h"
39#include "strv.h"
40#include "utf8.h"
41#include "util.h"
7ccbd1ae 42#include "syslog-util.h"
e8e581bf 43
f975e971 44int config_item_table_lookup(
e9f3d2d5 45 const void *table,
ed5bcfbe 46 const char *section,
ed5bcfbe 47 const char *lvalue,
f975e971
LP
48 ConfigParserCallback *func,
49 int *ltype,
50 void **data,
ed5bcfbe
LP
51 void *userdata) {
52
e9f3d2d5 53 const ConfigTableItem *t;
f975e971
LP
54
55 assert(table);
ed5bcfbe 56 assert(lvalue);
f975e971
LP
57 assert(func);
58 assert(ltype);
59 assert(data);
ed5bcfbe 60
f975e971 61 for (t = table; t->lvalue; t++) {
ed5bcfbe 62
f975e971 63 if (!streq(lvalue, t->lvalue))
ed5bcfbe
LP
64 continue;
65
f975e971 66 if (!streq_ptr(section, t->section))
ed5bcfbe
LP
67 continue;
68
f975e971
LP
69 *func = t->parse;
70 *ltype = t->ltype;
71 *data = t->data;
72 return 1;
73 }
ed5bcfbe 74
f975e971
LP
75 return 0;
76}
10e87ee7 77
f975e971 78int config_item_perf_lookup(
e9f3d2d5 79 const void *table,
f975e971
LP
80 const char *section,
81 const char *lvalue,
82 ConfigParserCallback *func,
83 int *ltype,
84 void **data,
85 void *userdata) {
86
87 ConfigPerfItemLookup lookup = (ConfigPerfItemLookup) table;
88 const ConfigPerfItem *p;
89
90 assert(table);
91 assert(lvalue);
92 assert(func);
93 assert(ltype);
94 assert(data);
95
96 if (!section)
97 p = lookup(lvalue, strlen(lvalue));
98 else {
99 char *key;
100
b7def684 101 key = strjoin(section, ".", lvalue, NULL);
44d91056 102 if (!key)
f975e971
LP
103 return -ENOMEM;
104
105 p = lookup(key, strlen(key));
106 free(key);
ed5bcfbe
LP
107 }
108
f975e971
LP
109 if (!p)
110 return 0;
111
112 *func = p->parse;
113 *ltype = p->ltype;
114 *data = (uint8_t*) userdata + p->offset;
115 return 1;
116}
117
118/* Run the user supplied parser for an assignment */
e8e581bf
ZJS
119static int next_assignment(const char *unit,
120 const char *filename,
121 unsigned line,
122 ConfigItemLookup lookup,
e9f3d2d5 123 const void *table,
e8e581bf 124 const char *section,
71a61510 125 unsigned section_line,
e8e581bf
ZJS
126 const char *lvalue,
127 const char *rvalue,
128 bool relaxed,
129 void *userdata) {
f975e971
LP
130
131 ConfigParserCallback func = NULL;
132 int ltype = 0;
133 void *data = NULL;
134 int r;
135
136 assert(filename);
137 assert(line > 0);
138 assert(lookup);
139 assert(lvalue);
140 assert(rvalue);
141
142 r = lookup(table, section, lvalue, &func, &ltype, &data, userdata);
143 if (r < 0)
144 return r;
145
d937fbbd
LP
146 if (r > 0) {
147 if (func)
71a61510
TG
148 return func(unit, filename, line, section, section_line,
149 lvalue, ltype, rvalue, data, userdata);
d937fbbd
LP
150
151 return 0;
152 }
f975e971 153
46205bb6 154 /* Warn about unknown non-extension fields. */
10e87ee7 155 if (!relaxed && !startswith(lvalue, "X-"))
12ca818f 156 log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown lvalue '%s' in section '%s'", lvalue, section);
46205bb6 157
f1857be0 158 return 0;
ed5bcfbe
LP
159}
160
ed5bcfbe 161/* Parse a variable assignment line */
e8e581bf
ZJS
162static int parse_line(const char* unit,
163 const char *filename,
164 unsigned line,
165 const char *sections,
166 ConfigItemLookup lookup,
e9f3d2d5 167 const void *table,
e8e581bf 168 bool relaxed,
db5c0122 169 bool allow_include,
e8e581bf 170 char **section,
71a61510 171 unsigned *section_line,
342aea19 172 bool *section_ignored,
e8e581bf
ZJS
173 char *l,
174 void *userdata) {
f975e971 175
b2aa81ef 176 char *e;
ed5bcfbe 177
f975e971
LP
178 assert(filename);
179 assert(line > 0);
180 assert(lookup);
181 assert(l);
182
b2aa81ef 183 l = strstrip(l);
ed5bcfbe 184
b2aa81ef 185 if (!*l)
ed5bcfbe 186 return 0;
1ea86b18 187
d3b6d0c2 188 if (strchr(COMMENTS "\n", *l))
1ea86b18 189 return 0;
ed5bcfbe 190
b2aa81ef 191 if (startswith(l, ".include ")) {
db5c0122
LP
192 _cleanup_free_ char *fn = NULL;
193
b8e7a47b
LP
194 /* .includes are a bad idea, we only support them here
195 * for historical reasons. They create cyclic include
196 * problems and make it difficult to detect
197 * configuration file changes with an easy
198 * stat(). Better approaches, such as .d/ drop-in
199 * snippets exist.
200 *
201 * Support for them should be eventually removed. */
202
db5c0122 203 if (!allow_include) {
12ca818f 204 log_syntax(unit, LOG_ERR, filename, line, 0, ".include not allowed here. Ignoring.");
db5c0122
LP
205 return 0;
206 }
ed5bcfbe 207
f975e971
LP
208 fn = file_in_same_dir(filename, strstrip(l+9));
209 if (!fn)
b2aa81ef 210 return -ENOMEM;
ed5bcfbe 211
36f822c4 212 return config_parse(unit, fn, NULL, sections, lookup, table, relaxed, false, false, userdata);
ed5bcfbe
LP
213 }
214
b2aa81ef 215 if (*l == '[') {
ed5bcfbe
LP
216 size_t k;
217 char *n;
218
b2aa81ef 219 k = strlen(l);
ed5bcfbe
LP
220 assert(k > 0);
221
b2aa81ef 222 if (l[k-1] != ']') {
12ca818f 223 log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid section header '%s'", l);
ed5bcfbe
LP
224 return -EBADMSG;
225 }
226
f975e971
LP
227 n = strndup(l+1, k-2);
228 if (!n)
ed5bcfbe
LP
229 return -ENOMEM;
230
f975e971 231 if (sections && !nulstr_contains(sections, n)) {
42f4e3c4 232
342aea19 233 if (!relaxed && !startswith(n, "X-"))
12ca818f 234 log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown section '%s'. Ignoring.", n);
f975e971
LP
235
236 free(n);
a1e58e8e 237 *section = mfree(*section);
71a61510 238 *section_line = 0;
342aea19 239 *section_ignored = true;
f975e971
LP
240 } else {
241 free(*section);
242 *section = n;
71a61510 243 *section_line = line;
342aea19 244 *section_ignored = false;
f975e971 245 }
ed5bcfbe
LP
246
247 return 0;
248 }
249
62f168a0
LP
250 if (sections && !*section) {
251
342aea19 252 if (!relaxed && !*section_ignored)
12ca818f 253 log_syntax(unit, LOG_WARNING, filename, line, 0, "Assignment outside of section. Ignoring.");
62f168a0 254
10e87ee7 255 return 0;
62f168a0 256 }
10e87ee7 257
f975e971
LP
258 e = strchr(l, '=');
259 if (!e) {
12ca818f
LP
260 log_syntax(unit, LOG_WARNING, filename, line, 0, "Missing '='.");
261 return -EINVAL;
ed5bcfbe
LP
262 }
263
264 *e = 0;
265 e++;
266
e8e581bf
ZJS
267 return next_assignment(unit,
268 filename,
269 line,
270 lookup,
271 table,
272 *section,
71a61510 273 *section_line,
e8e581bf
ZJS
274 strstrip(l),
275 strstrip(e),
276 relaxed,
277 userdata);
ed5bcfbe
LP
278}
279
280/* Go through the file and parse each line */
e8e581bf
ZJS
281int config_parse(const char *unit,
282 const char *filename,
283 FILE *f,
284 const char *sections,
285 ConfigItemLookup lookup,
e9f3d2d5 286 const void *table,
e8e581bf 287 bool relaxed,
db5c0122 288 bool allow_include,
36f822c4 289 bool warn,
e8e581bf 290 void *userdata) {
f975e971 291
7fd1b19b
HH
292 _cleanup_free_ char *section = NULL, *continuation = NULL;
293 _cleanup_fclose_ FILE *ours = NULL;
71a61510 294 unsigned line = 0, section_line = 0;
342aea19 295 bool section_ignored = false;
ed5bcfbe
LP
296 int r;
297
298 assert(filename);
f975e971 299 assert(lookup);
ed5bcfbe 300
87f0e418 301 if (!f) {
245802dd 302 f = ours = fopen(filename, "re");
f975e971 303 if (!f) {
36f822c4
ZJS
304 /* Only log on request, except for ENOENT,
305 * since we return 0 to the caller. */
306 if (warn || errno == ENOENT)
307 log_full(errno == ENOENT ? LOG_DEBUG : LOG_ERR,
308 "Failed to open configuration file '%s': %m", filename);
9f43a07f 309 return errno == ENOENT ? 0 : -errno;
87f0e418 310 }
ed5bcfbe
LP
311 }
312
fdb9161c
LP
313 fd_warn_permissions(filename, fileno(f));
314
ed5bcfbe 315 while (!feof(f)) {
3dab2943
LP
316 char l[LINE_MAX], *p, *c = NULL, *e;
317 bool escaped = false;
ed5bcfbe
LP
318
319 if (!fgets(l, sizeof(l), f)) {
320 if (feof(f))
321 break;
322
56f64d95 323 log_error_errno(errno, "Failed to read configuration file '%s': %m", filename);
245802dd 324 return -errno;
ed5bcfbe
LP
325 }
326
3dab2943
LP
327 truncate_nl(l);
328
329 if (continuation) {
f975e971 330 c = strappend(continuation, l);
36f822c4
ZJS
331 if (!c) {
332 if (warn)
333 log_oom();
245802dd 334 return -ENOMEM;
36f822c4 335 }
3dab2943 336
97b11eed 337 continuation = mfree(continuation);
3dab2943
LP
338 p = c;
339 } else
340 p = l;
341
342 for (e = p; *e; e++) {
343 if (escaped)
344 escaped = false;
345 else if (*e == '\\')
346 escaped = true;
347 }
348
349 if (escaped) {
350 *(e-1) = ' ';
351
352 if (c)
353 continuation = c;
f975e971
LP
354 else {
355 continuation = strdup(l);
36f822c4
ZJS
356 if (!continuation) {
357 if (warn)
358 log_oom();
245802dd 359 return -ENOMEM;
36f822c4 360 }
3dab2943
LP
361 }
362
363 continue;
364 }
365
e8e581bf
ZJS
366 r = parse_line(unit,
367 filename,
368 ++line,
369 sections,
370 lookup,
371 table,
372 relaxed,
db5c0122 373 allow_include,
e8e581bf 374 &section,
71a61510 375 &section_line,
342aea19 376 &section_ignored,
e8e581bf
ZJS
377 p,
378 userdata);
3dab2943
LP
379 free(c);
380
36f822c4
ZJS
381 if (r < 0) {
382 if (warn)
c33b3297
MS
383 log_warning_errno(r, "Failed to parse file '%s': %m",
384 filename);
245802dd 385 return r;
36f822c4 386 }
ed5bcfbe
LP
387 }
388
245802dd 389 return 0;
ed5bcfbe
LP
390}
391
e8461023
JT
392/* Parse each config file in the specified directories. */
393int config_parse_many(const char *conf_file,
394 const char *conf_file_dirs,
395 const char *sections,
396 ConfigItemLookup lookup,
397 const void *table,
398 bool relaxed,
399 void *userdata) {
400 _cleanup_strv_free_ char **files = NULL;
401 char **fn;
402 int r;
403
404 r = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs);
405 if (r < 0)
406 return r;
407
408 if (conf_file) {
409 r = config_parse(NULL, conf_file, NULL, sections, lookup, table, relaxed, false, true, userdata);
410 if (r < 0)
411 return r;
412 }
413
414 STRV_FOREACH(fn, files) {
415 r = config_parse(NULL, *fn, NULL, sections, lookup, table, relaxed, false, true, userdata);
416 if (r < 0)
417 return r;
418 }
419
420 return 0;
421}
422
eb3491d9 423#define DEFINE_PARSER(type, vartype, conv_func) \
94d75d64
LP
424 int config_parse_##type( \
425 const char *unit, \
426 const char *filename, \
427 unsigned line, \
428 const char *section, \
429 unsigned section_line, \
430 const char *lvalue, \
431 int ltype, \
432 const char *rvalue, \
433 void *data, \
434 void *userdata) { \
eb3491d9
ZJS
435 \
436 vartype *i = data; \
437 int r; \
438 \
439 assert(filename); \
440 assert(lvalue); \
441 assert(rvalue); \
442 assert(data); \
443 \
444 r = conv_func(rvalue, i); \
445 if (r < 0) \
12ca818f 446 log_syntax(unit, LOG_ERR, filename, line, r, \
e8e581bf 447 "Failed to parse %s value, ignoring: %s", \
98d75800 448 #type, rvalue); \
eb3491d9
ZJS
449 \
450 return 0; \
94d75d64
LP
451 } \
452 struct __useless_struct_to_allow_trailing_semicolon__
453
454DEFINE_PARSER(int, int, safe_atoi);
455DEFINE_PARSER(long, long, safe_atoli);
456DEFINE_PARSER(uint32, uint32_t, safe_atou32);
457DEFINE_PARSER(uint64, uint64_t, safe_atou64);
458DEFINE_PARSER(unsigned, unsigned, safe_atou);
459DEFINE_PARSER(double, double, safe_atod);
460DEFINE_PARSER(nsec, nsec_t, parse_nsec);
461DEFINE_PARSER(sec, usec_t, parse_sec);
462DEFINE_PARSER(mode, mode_t, parse_mode);
ed5bcfbe 463
5556b5fe 464int config_parse_iec_size(const char* unit,
e8e581bf
ZJS
465 const char *filename,
466 unsigned line,
467 const char *section,
71a61510 468 unsigned section_line,
e8e581bf
ZJS
469 const char *lvalue,
470 int ltype,
471 const char *rvalue,
472 void *data,
473 void *userdata) {
ed5bcfbe
LP
474
475 size_t *sz = data;
59f448cf 476 uint64_t v;
e8e581bf 477 int r;
ed5bcfbe
LP
478
479 assert(filename);
480 assert(lvalue);
481 assert(rvalue);
482 assert(data);
483
59f448cf
LP
484 r = parse_size(rvalue, 1024, &v);
485 if (r < 0 || (uint64_t) (size_t) v != v) {
12ca818f 486 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse size value, ignoring: %s", rvalue);
9ba1a159
LP
487 return 0;
488 }
489
59f448cf 490 *sz = (size_t) v;
9ba1a159
LP
491 return 0;
492}
493
5556b5fe
LP
494int config_parse_si_size(const char* unit,
495 const char *filename,
496 unsigned line,
497 const char *section,
498 unsigned section_line,
499 const char *lvalue,
500 int ltype,
501 const char *rvalue,
502 void *data,
503 void *userdata) {
504
505 size_t *sz = data;
59f448cf 506 uint64_t v;
5556b5fe
LP
507 int r;
508
509 assert(filename);
510 assert(lvalue);
511 assert(rvalue);
512 assert(data);
513
59f448cf
LP
514 r = parse_size(rvalue, 1000, &v);
515 if (r < 0 || (uint64_t) (size_t) v != v) {
12ca818f 516 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse size value, ignoring: %s", rvalue);
5556b5fe
LP
517 return 0;
518 }
519
59f448cf 520 *sz = (size_t) v;
5556b5fe
LP
521 return 0;
522}
9ba1a159 523
59f448cf 524int config_parse_iec_uint64(const char* unit,
e8e581bf
ZJS
525 const char *filename,
526 unsigned line,
527 const char *section,
71a61510 528 unsigned section_line,
e8e581bf
ZJS
529 const char *lvalue,
530 int ltype,
531 const char *rvalue,
532 void *data,
533 void *userdata) {
9ba1a159 534
59f448cf 535 uint64_t *bytes = data;
e8e581bf 536 int r;
9ba1a159
LP
537
538 assert(filename);
539 assert(lvalue);
540 assert(rvalue);
541 assert(data);
542
5556b5fe 543 r = parse_size(rvalue, 1024, bytes);
e8e581bf 544 if (r < 0)
59f448cf 545 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse size value, ignoring: %s", rvalue);
ed5bcfbe 546
ed5bcfbe
LP
547 return 0;
548}
549
e8e581bf
ZJS
550int config_parse_bool(const char* unit,
551 const char *filename,
552 unsigned line,
553 const char *section,
71a61510 554 unsigned section_line,
e8e581bf
ZJS
555 const char *lvalue,
556 int ltype,
557 const char *rvalue,
558 void *data,
559 void *userdata) {
ed5bcfbe
LP
560
561 int k;
562 bool *b = data;
563
564 assert(filename);
565 assert(lvalue);
566 assert(rvalue);
567 assert(data);
568
e8e581bf
ZJS
569 k = parse_boolean(rvalue);
570 if (k < 0) {
12ca818f 571 log_syntax(unit, LOG_ERR, filename, line, k, "Failed to parse boolean value, ignoring: %s", rvalue);
f975e971 572 return 0;
ed5bcfbe
LP
573 }
574
575 *b = !!k;
576 return 0;
577}
578
f757855e
LP
579int config_parse_tristate(
580 const char* unit,
581 const char *filename,
582 unsigned line,
583 const char *section,
584 unsigned section_line,
585 const char *lvalue,
586 int ltype,
587 const char *rvalue,
588 void *data,
589 void *userdata) {
590
591 int k, *t = data;
592
593 assert(filename);
594 assert(lvalue);
595 assert(rvalue);
596 assert(data);
597
598 /* A tristate is pretty much a boolean, except that it can
599 * also take the special value -1, indicating "uninitialized",
600 * much like NULL is for a pointer type. */
601
602 k = parse_boolean(rvalue);
603 if (k < 0) {
604 log_syntax(unit, LOG_ERR, filename, line, k, "Failed to parse boolean value, ignoring: %s", rvalue);
605 return 0;
606 }
607
608 *t = !!k;
609 return 0;
610}
611
8f2665a4
LP
612int config_parse_string(
613 const char *unit,
614 const char *filename,
615 unsigned line,
616 const char *section,
617 unsigned section_line,
618 const char *lvalue,
619 int ltype,
620 const char *rvalue,
621 void *data,
622 void *userdata) {
623
624 char **s = data, *n;
ed5bcfbe
LP
625
626 assert(filename);
627 assert(lvalue);
628 assert(rvalue);
629 assert(data);
630
8f2665a4 631 if (!utf8_is_valid(rvalue)) {
0e05ee04 632 log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue);
7f110ff9
LP
633 return 0;
634 }
ed5bcfbe 635
8f2665a4
LP
636 if (isempty(rvalue))
637 n = NULL;
7f110ff9 638 else {
8f2665a4
LP
639 n = strdup(rvalue);
640 if (!n)
641 return log_oom();
7f110ff9 642 }
ed5bcfbe 643
8f2665a4
LP
644 free(*s);
645 *s = n;
646
ed5bcfbe
LP
647 return 0;
648}
57d42a5f 649
8f2665a4
LP
650int config_parse_path(
651 const char *unit,
652 const char *filename,
653 unsigned line,
654 const char *section,
655 unsigned section_line,
656 const char *lvalue,
657 int ltype,
658 const char *rvalue,
659 void *data,
660 void *userdata) {
034c6ed7 661
3b436292 662 char **s = data, *n;
034c6ed7
LP
663
664 assert(filename);
665 assert(lvalue);
666 assert(rvalue);
667 assert(data);
668
7f110ff9 669 if (!utf8_is_valid(rvalue)) {
0e05ee04 670 log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue);
7f110ff9
LP
671 return 0;
672 }
673
3b436292 674 if (!path_is_absolute(rvalue)) {
12ca818f 675 log_syntax(unit, LOG_ERR, filename, line, 0, "Not an absolute path, ignoring: %s", rvalue);
f975e971 676 return 0;
034c6ed7
LP
677 }
678
7f110ff9
LP
679 n = strdup(rvalue);
680 if (!n)
74051b9b 681 return log_oom();
034c6ed7 682
01f78473
LP
683 path_kill_slashes(n);
684
034c6ed7
LP
685 free(*s);
686 *s = n;
687
688 return 0;
689}
57d42a5f 690
e8e581bf
ZJS
691int config_parse_strv(const char *unit,
692 const char *filename,
693 unsigned line,
694 const char *section,
71a61510 695 unsigned section_line,
e8e581bf
ZJS
696 const char *lvalue,
697 int ltype,
698 const char *rvalue,
699 void *data,
700 void *userdata) {
57d42a5f 701
a2a5291b
ZJS
702 char ***sv = data;
703 const char *word, *state;
57d42a5f 704 size_t l;
7f110ff9 705 int r;
57d42a5f
LP
706
707 assert(filename);
708 assert(lvalue);
709 assert(rvalue);
710 assert(data);
711
74051b9b 712 if (isempty(rvalue)) {
4589f5bb
LP
713 char **empty;
714
715 /* Empty assignment resets the list. As a special rule
716 * we actually fill in a real empty array here rather
717 * than NULL, since some code wants to know if
718 * something was set at all... */
719 empty = strv_new(NULL, NULL);
720 if (!empty)
721 return log_oom();
722
74051b9b 723 strv_free(*sv);
4589f5bb 724 *sv = empty;
853b8397 725 return 0;
74051b9b
LP
726 }
727
a2a5291b 728 FOREACH_WORD_QUOTED(word, l, rvalue, state) {
6e18964d 729 char *n;
7f110ff9 730
a2a5291b 731 n = strndup(word, l);
853b8397
LP
732 if (!n)
733 return log_oom();
734
735 if (!utf8_is_valid(n)) {
0e05ee04 736 log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue);
9e602778 737 free(n);
7f110ff9
LP
738 continue;
739 }
740
6e18964d 741 r = strv_consume(sv, n);
853b8397
LP
742 if (r < 0)
743 return log_oom();
7f110ff9 744 }
b2fadec6 745 if (!isempty(state))
12ca818f 746 log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring.");
57d42a5f 747
57d42a5f 748 return 0;
57d42a5f 749}
15ae422b 750
ca37242e
LP
751int config_parse_log_facility(
752 const char *unit,
753 const char *filename,
754 unsigned line,
755 const char *section,
756 unsigned section_line,
757 const char *lvalue,
758 int ltype,
759 const char *rvalue,
760 void *data,
761 void *userdata) {
213ba152
LP
762
763
764 int *o = data, x;
765
766 assert(filename);
767 assert(lvalue);
768 assert(rvalue);
769 assert(data);
770
771 x = log_facility_unshifted_from_string(rvalue);
772 if (x < 0) {
12ca818f 773 log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse log facility, ignoring: %s", rvalue);
213ba152
LP
774 return 0;
775 }
776
777 *o = (x << 3) | LOG_PRI(*o);
778
779 return 0;
780}
781
ca37242e
LP
782int config_parse_log_level(
783 const char *unit,
784 const char *filename,
785 unsigned line,
786 const char *section,
787 unsigned section_line,
788 const char *lvalue,
789 int ltype,
790 const char *rvalue,
791 void *data,
792 void *userdata) {
213ba152
LP
793
794
795 int *o = data, x;
796
797 assert(filename);
798 assert(lvalue);
799 assert(rvalue);
800 assert(data);
801
802 x = log_level_from_string(rvalue);
803 if (x < 0) {
12ca818f 804 log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse log level, ignoring: %s", rvalue);
213ba152
LP
805 return 0;
806 }
807
808 *o = (*o & LOG_FACMASK) | x;
809 return 0;
810}
f757855e
LP
811
812int config_parse_signal(
813 const char *unit,
814 const char *filename,
815 unsigned line,
816 const char *section,
817 unsigned section_line,
818 const char *lvalue,
819 int ltype,
820 const char *rvalue,
821 void *data,
822 void *userdata) {
823
824 int *sig = data, r;
825
826 assert(filename);
827 assert(lvalue);
828 assert(rvalue);
829 assert(sig);
830
831 r = signal_from_string_try_harder(rvalue);
832 if (r <= 0) {
12ca818f 833 log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse signal name, ignoring: %s", rvalue);
f757855e
LP
834 return 0;
835 }
836
837 *sig = r;
838 return 0;
839}
840
841int config_parse_personality(
842 const char *unit,
843 const char *filename,
844 unsigned line,
845 const char *section,
846 unsigned section_line,
847 const char *lvalue,
848 int ltype,
849 const char *rvalue,
850 void *data,
851 void *userdata) {
852
853 unsigned long *personality = data, p;
854
855 assert(filename);
856 assert(lvalue);
857 assert(rvalue);
858 assert(personality);
859
860 p = personality_from_string(rvalue);
861 if (p == PERSONALITY_INVALID) {
12ca818f 862 log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse personality, ignoring: %s", rvalue);
f757855e
LP
863 return 0;
864 }
865
866 *personality = p;
867 return 0;
868}