]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/conf-parser.c
service: add options RestartPreventExitStatus and SuccessExitStatus
[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
LP
22#include <string.h>
23#include <stdio.h>
24#include <errno.h>
25#include <assert.h>
26#include <stdlib.h>
27
28#include "conf-parser.h"
29#include "util.h"
30#include "macro.h"
57d42a5f 31#include "strv.h"
16354eff 32#include "log.h"
7f110ff9 33#include "utf8.h"
9eb977db 34#include "path-util.h"
96342de6
LN
35#include "set.h"
36#include "exit-status.h"
ed5bcfbe 37
f975e971
LP
38int config_item_table_lookup(
39 void *table,
ed5bcfbe 40 const char *section,
ed5bcfbe 41 const char *lvalue,
f975e971
LP
42 ConfigParserCallback *func,
43 int *ltype,
44 void **data,
ed5bcfbe
LP
45 void *userdata) {
46
f975e971
LP
47 ConfigTableItem *t;
48
49 assert(table);
ed5bcfbe 50 assert(lvalue);
f975e971
LP
51 assert(func);
52 assert(ltype);
53 assert(data);
ed5bcfbe 54
f975e971 55 for (t = table; t->lvalue; t++) {
ed5bcfbe 56
f975e971 57 if (!streq(lvalue, t->lvalue))
ed5bcfbe
LP
58 continue;
59
f975e971 60 if (!streq_ptr(section, t->section))
ed5bcfbe
LP
61 continue;
62
f975e971
LP
63 *func = t->parse;
64 *ltype = t->ltype;
65 *data = t->data;
66 return 1;
67 }
ed5bcfbe 68
f975e971
LP
69 return 0;
70}
10e87ee7 71
f975e971
LP
72int config_item_perf_lookup(
73 void *table,
74 const char *section,
75 const char *lvalue,
76 ConfigParserCallback *func,
77 int *ltype,
78 void **data,
79 void *userdata) {
80
81 ConfigPerfItemLookup lookup = (ConfigPerfItemLookup) table;
82 const ConfigPerfItem *p;
83
84 assert(table);
85 assert(lvalue);
86 assert(func);
87 assert(ltype);
88 assert(data);
89
90 if (!section)
91 p = lookup(lvalue, strlen(lvalue));
92 else {
93 char *key;
94
b7def684 95 key = strjoin(section, ".", lvalue, NULL);
44d91056 96 if (!key)
f975e971
LP
97 return -ENOMEM;
98
99 p = lookup(key, strlen(key));
100 free(key);
ed5bcfbe
LP
101 }
102
f975e971
LP
103 if (!p)
104 return 0;
105
106 *func = p->parse;
107 *ltype = p->ltype;
108 *data = (uint8_t*) userdata + p->offset;
109 return 1;
110}
111
112/* Run the user supplied parser for an assignment */
113static int next_assignment(
114 const char *filename,
115 unsigned line,
116 ConfigItemLookup lookup,
117 void *table,
118 const char *section,
119 const char *lvalue,
120 const char *rvalue,
121 bool relaxed,
122 void *userdata) {
123
124 ConfigParserCallback func = NULL;
125 int ltype = 0;
126 void *data = NULL;
127 int r;
128
129 assert(filename);
130 assert(line > 0);
131 assert(lookup);
132 assert(lvalue);
133 assert(rvalue);
134
135 r = lookup(table, section, lvalue, &func, &ltype, &data, userdata);
136 if (r < 0)
137 return r;
138
d937fbbd
LP
139 if (r > 0) {
140 if (func)
141 return func(filename, line, section, lvalue, ltype, rvalue, data, userdata);
142
143 return 0;
144 }
f975e971 145
46205bb6 146 /* Warn about unknown non-extension fields. */
10e87ee7 147 if (!relaxed && !startswith(lvalue, "X-"))
f975e971 148 log_info("[%s:%u] Unknown lvalue '%s' in section '%s'. Ignoring.", filename, line, lvalue, section);
46205bb6 149
f1857be0 150 return 0;
ed5bcfbe
LP
151}
152
ed5bcfbe 153/* Parse a variable assignment line */
f975e971
LP
154static int parse_line(
155 const char *filename,
156 unsigned line,
157 const char *sections,
158 ConfigItemLookup lookup,
159 void *table,
160 bool relaxed,
161 char **section,
162 char *l,
163 void *userdata) {
164
b2aa81ef 165 char *e;
ed5bcfbe 166
f975e971
LP
167 assert(filename);
168 assert(line > 0);
169 assert(lookup);
170 assert(l);
171
b2aa81ef 172 l = strstrip(l);
ed5bcfbe 173
b2aa81ef 174 if (!*l)
ed5bcfbe 175 return 0;
1ea86b18 176
b2aa81ef 177 if (strchr(COMMENTS, *l))
1ea86b18 178 return 0;
ed5bcfbe 179
b2aa81ef
LP
180 if (startswith(l, ".include ")) {
181 char *fn;
ed5bcfbe
LP
182 int r;
183
f975e971
LP
184 fn = file_in_same_dir(filename, strstrip(l+9));
185 if (!fn)
b2aa81ef 186 return -ENOMEM;
ed5bcfbe 187
f975e971 188 r = config_parse(fn, NULL, sections, lookup, table, relaxed, userdata);
b2aa81ef
LP
189 free(fn);
190
ed5bcfbe
LP
191 return r;
192 }
193
b2aa81ef 194 if (*l == '[') {
ed5bcfbe
LP
195 size_t k;
196 char *n;
197
b2aa81ef 198 k = strlen(l);
ed5bcfbe
LP
199 assert(k > 0);
200
b2aa81ef 201 if (l[k-1] != ']') {
16354eff 202 log_error("[%s:%u] Invalid section header.", filename, line);
ed5bcfbe
LP
203 return -EBADMSG;
204 }
205
f975e971
LP
206 n = strndup(l+1, k-2);
207 if (!n)
ed5bcfbe
LP
208 return -ENOMEM;
209
f975e971 210 if (sections && !nulstr_contains(sections, n)) {
42f4e3c4 211
f975e971
LP
212 if (!relaxed)
213 log_info("[%s:%u] Unknown section '%s'. Ignoring.", filename, line, n);
214
215 free(n);
216 *section = NULL;
217 } else {
218 free(*section);
219 *section = n;
220 }
ed5bcfbe
LP
221
222 return 0;
223 }
224
62f168a0
LP
225 if (sections && !*section) {
226
227 if (!relaxed)
228 log_info("[%s:%u] Assignment outside of section. Ignoring.", filename, line);
229
10e87ee7 230 return 0;
62f168a0 231 }
10e87ee7 232
f975e971
LP
233 e = strchr(l, '=');
234 if (!e) {
16354eff 235 log_error("[%s:%u] Missing '='.", filename, line);
ed5bcfbe
LP
236 return -EBADMSG;
237 }
238
239 *e = 0;
240 e++;
241
f975e971
LP
242 return next_assignment(
243 filename,
244 line,
245 lookup,
246 table,
247 *section,
248 strstrip(l),
249 strstrip(e),
250 relaxed,
251 userdata);
ed5bcfbe
LP
252}
253
254/* Go through the file and parse each line */
f975e971
LP
255int config_parse(
256 const char *filename,
257 FILE *f,
258 const char *sections,
259 ConfigItemLookup lookup,
260 void *table,
261 bool relaxed,
262 void *userdata) {
263
ed5bcfbe
LP
264 unsigned line = 0;
265 char *section = NULL;
ed5bcfbe 266 int r;
63ad1ab4 267 bool ours = false;
3dab2943 268 char *continuation = NULL;
ed5bcfbe
LP
269
270 assert(filename);
f975e971 271 assert(lookup);
ed5bcfbe 272
87f0e418 273 if (!f) {
f975e971
LP
274 f = fopen(filename, "re");
275 if (!f) {
87f0e418
LP
276 r = -errno;
277 log_error("Failed to open configuration file '%s': %s", filename, strerror(-r));
278 goto finish;
279 }
63ad1ab4
LP
280
281 ours = true;
ed5bcfbe
LP
282 }
283
284 while (!feof(f)) {
3dab2943
LP
285 char l[LINE_MAX], *p, *c = NULL, *e;
286 bool escaped = false;
ed5bcfbe
LP
287
288 if (!fgets(l, sizeof(l), f)) {
289 if (feof(f))
290 break;
291
292 r = -errno;
16354eff 293 log_error("Failed to read configuration file '%s': %s", filename, strerror(-r));
ed5bcfbe
LP
294 goto finish;
295 }
296
3dab2943
LP
297 truncate_nl(l);
298
299 if (continuation) {
f975e971
LP
300 c = strappend(continuation, l);
301 if (!c) {
3dab2943
LP
302 r = -ENOMEM;
303 goto finish;
304 }
305
306 free(continuation);
307 continuation = NULL;
308 p = c;
309 } else
310 p = l;
311
312 for (e = p; *e; e++) {
313 if (escaped)
314 escaped = false;
315 else if (*e == '\\')
316 escaped = true;
317 }
318
319 if (escaped) {
320 *(e-1) = ' ';
321
322 if (c)
323 continuation = c;
f975e971
LP
324 else {
325 continuation = strdup(l);
8ea913b2 326 if (!continuation) {
f975e971
LP
327 r = -ENOMEM;
328 goto finish;
329 }
3dab2943
LP
330 }
331
332 continue;
333 }
334
f975e971
LP
335 r = parse_line(filename,
336 ++line,
337 sections,
338 lookup,
339 table,
340 relaxed,
341 &section,
342 p,
343 userdata);
3dab2943
LP
344 free(c);
345
346 if (r < 0)
ed5bcfbe
LP
347 goto finish;
348 }
349
350 r = 0;
351
352finish:
353 free(section);
3dab2943 354 free(continuation);
ed5bcfbe 355
63ad1ab4 356 if (f && ours)
ed5bcfbe
LP
357 fclose(f);
358
359 return r;
360}
361
362int config_parse_int(
363 const char *filename,
364 unsigned line,
365 const char *section,
366 const char *lvalue,
2b583ce6 367 int ltype,
ed5bcfbe
LP
368 const char *rvalue,
369 void *data,
370 void *userdata) {
371
372 int *i = data;
373 int r;
374
375 assert(filename);
376 assert(lvalue);
377 assert(rvalue);
378 assert(data);
379
380 if ((r = safe_atoi(rvalue, i)) < 0) {
f975e971
LP
381 log_error("[%s:%u] Failed to parse numeric value, ingoring: %s", filename, line, rvalue);
382 return 0;
ed5bcfbe
LP
383 }
384
385 return 0;
386}
387
916abb21
LP
388int config_parse_long(
389 const char *filename,
390 unsigned line,
391 const char *section,
392 const char *lvalue,
393 int ltype,
394 const char *rvalue,
395 void *data,
396 void *userdata) {
397
398 long *i = data;
399 int r;
400
401 assert(filename);
402 assert(lvalue);
403 assert(rvalue);
404 assert(data);
405
406 if ((r = safe_atoli(rvalue, i)) < 0) {
f975e971
LP
407 log_error("[%s:%u] Failed to parse numeric value, ignoring: %s", filename, line, rvalue);
408 return 0;
916abb21
LP
409 }
410
411 return 0;
412}
413
ec863ba6
LP
414int config_parse_uint64(
415 const char *filename,
416 unsigned line,
417 const char *section,
418 const char *lvalue,
2b583ce6 419 int ltype,
ec863ba6
LP
420 const char *rvalue,
421 void *data,
422 void *userdata) {
423
424 uint64_t *u = data;
425 int r;
426
427 assert(filename);
428 assert(lvalue);
429 assert(rvalue);
430 assert(data);
431
432 if ((r = safe_atou64(rvalue, u)) < 0) {
f975e971
LP
433 log_error("[%s:%u] Failed to parse numeric value, ignoring: %s", filename, line, rvalue);
434 return 0;
ec863ba6
LP
435 }
436
437 return 0;
438}
439
ed5bcfbe
LP
440int config_parse_unsigned(
441 const char *filename,
442 unsigned line,
443 const char *section,
444 const char *lvalue,
2b583ce6 445 int ltype,
ed5bcfbe
LP
446 const char *rvalue,
447 void *data,
448 void *userdata) {
449
450 unsigned *u = data;
451 int r;
452
453 assert(filename);
454 assert(lvalue);
455 assert(rvalue);
456 assert(data);
457
458 if ((r = safe_atou(rvalue, u)) < 0) {
16354eff 459 log_error("[%s:%u] Failed to parse numeric value: %s", filename, line, rvalue);
ed5bcfbe
LP
460 return r;
461 }
462
463 return 0;
464}
465
9ba1a159 466int config_parse_bytes_size(
ed5bcfbe
LP
467 const char *filename,
468 unsigned line,
469 const char *section,
470 const char *lvalue,
2b583ce6 471 int ltype,
ed5bcfbe
LP
472 const char *rvalue,
473 void *data,
474 void *userdata) {
475
476 size_t *sz = data;
9ba1a159 477 off_t o;
ed5bcfbe
LP
478
479 assert(filename);
480 assert(lvalue);
481 assert(rvalue);
482 assert(data);
483
9ba1a159
LP
484 if (parse_bytes(rvalue, &o) < 0 || (off_t) (size_t) o != o) {
485 log_error("[%s:%u] Failed to parse byte value, ignoring: %s", filename, line, rvalue);
486 return 0;
487 }
488
489 *sz = (size_t) o;
490 return 0;
491}
492
493
494int config_parse_bytes_off(
495 const char *filename,
496 unsigned line,
497 const char *section,
498 const char *lvalue,
499 int ltype,
500 const char *rvalue,
501 void *data,
502 void *userdata) {
503
504 off_t *bytes = data;
505
506 assert(filename);
507 assert(lvalue);
508 assert(rvalue);
509 assert(data);
510
511 assert_cc(sizeof(off_t) == sizeof(uint64_t));
512
513 if (parse_bytes(rvalue, bytes) < 0) {
514 log_error("[%s:%u] Failed to parse bytes value, ignoring: %s", filename, line, rvalue);
f975e971 515 return 0;
ed5bcfbe
LP
516 }
517
ed5bcfbe
LP
518 return 0;
519}
520
521int config_parse_bool(
522 const char *filename,
523 unsigned line,
524 const char *section,
525 const char *lvalue,
2b583ce6 526 int ltype,
ed5bcfbe
LP
527 const char *rvalue,
528 void *data,
529 void *userdata) {
530
531 int k;
532 bool *b = data;
533
534 assert(filename);
535 assert(lvalue);
536 assert(rvalue);
537 assert(data);
538
539 if ((k = parse_boolean(rvalue)) < 0) {
f975e971
LP
540 log_error("[%s:%u] Failed to parse boolean value, ignoring: %s", filename, line, rvalue);
541 return 0;
ed5bcfbe
LP
542 }
543
544 *b = !!k;
545 return 0;
546}
547
8d53b453
LP
548int config_parse_tristate(
549 const char *filename,
550 unsigned line,
551 const char *section,
552 const char *lvalue,
553 int ltype,
554 const char *rvalue,
555 void *data,
556 void *userdata) {
557
558 int k;
559 int *b = data;
560
561 assert(filename);
562 assert(lvalue);
563 assert(rvalue);
564 assert(data);
565
566 /* Tristates are like booleans, but can also take the 'default' value, i.e. "-1" */
567
568 k = parse_boolean(rvalue);
569 if (k < 0) {
570 log_error("[%s:%u] Failed to parse boolean value, ignoring: %s", filename, line, rvalue);
571 return 0;
572 }
573
574 *b = !!k;
575 return 0;
576}
577
ed5bcfbe
LP
578int config_parse_string(
579 const char *filename,
580 unsigned line,
581 const char *section,
582 const char *lvalue,
2b583ce6 583 int ltype,
ed5bcfbe
LP
584 const char *rvalue,
585 void *data,
586 void *userdata) {
587
588 char **s = data;
589 char *n;
590
591 assert(filename);
592 assert(lvalue);
593 assert(rvalue);
594 assert(data);
595
7f110ff9
LP
596 n = cunescape(rvalue);
597 if (!n)
598 return -ENOMEM;
599
600 if (!utf8_is_valid(n)) {
601 log_error("[%s:%u] String is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
602 free(n);
603 return 0;
604 }
ed5bcfbe
LP
605
606 free(*s);
7f110ff9
LP
607 if (*n)
608 *s = n;
609 else {
610 free(n);
611 *s = NULL;
612 }
ed5bcfbe
LP
613
614 return 0;
615}
57d42a5f 616
034c6ed7
LP
617int config_parse_path(
618 const char *filename,
619 unsigned line,
620 const char *section,
621 const char *lvalue,
2b583ce6 622 int ltype,
034c6ed7
LP
623 const char *rvalue,
624 void *data,
625 void *userdata) {
626
627 char **s = data;
628 char *n;
629
630 assert(filename);
631 assert(lvalue);
632 assert(rvalue);
633 assert(data);
634
7f110ff9
LP
635 if (!utf8_is_valid(rvalue)) {
636 log_error("[%s:%u] Path is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
637 return 0;
638 }
639
15ae422b 640 if (!path_is_absolute(rvalue)) {
f975e971
LP
641 log_error("[%s:%u] Not an absolute path, ignoring: %s", filename, line, rvalue);
642 return 0;
034c6ed7
LP
643 }
644
7f110ff9
LP
645 n = strdup(rvalue);
646 if (!n)
034c6ed7
LP
647 return -ENOMEM;
648
01f78473
LP
649 path_kill_slashes(n);
650
034c6ed7
LP
651 free(*s);
652 *s = n;
653
654 return 0;
655}
57d42a5f
LP
656
657int config_parse_strv(
658 const char *filename,
659 unsigned line,
660 const char *section,
661 const char *lvalue,
2b583ce6 662 int ltype,
57d42a5f
LP
663 const char *rvalue,
664 void *data,
665 void *userdata) {
666
667 char*** sv = data;
668 char **n;
669 char *w;
670 unsigned k;
671 size_t l;
672 char *state;
7f110ff9 673 int r;
57d42a5f
LP
674
675 assert(filename);
676 assert(lvalue);
677 assert(rvalue);
678 assert(data);
679
680 k = strv_length(*sv);
034c6ed7 681 FOREACH_WORD_QUOTED(w, l, rvalue, state)
57d42a5f
LP
682 k++;
683
7f110ff9
LP
684 n = new(char*, k+1);
685 if (!n)
57d42a5f
LP
686 return -ENOMEM;
687
3251df7d
LP
688 if (*sv)
689 for (k = 0; (*sv)[k]; k++)
690 n[k] = (*sv)[k];
7418040c
LP
691 else
692 k = 0;
3251df7d 693
7f110ff9
LP
694 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
695 n[k] = cunescape_length(w, l);
696 if (!n[k]) {
697 r = -ENOMEM;
57d42a5f 698 goto fail;
7f110ff9
LP
699 }
700
701 if (!utf8_is_valid(n[k])) {
702 log_error("[%s:%u] String is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
703 free(n[k]);
704 continue;
705 }
706
707 k++;
708 }
57d42a5f
LP
709
710 n[k] = NULL;
711 free(*sv);
712 *sv = n;
713
714 return 0;
715
716fail:
717 for (; k > 0; k--)
718 free(n[k-1]);
034c6ed7 719 free(n);
57d42a5f 720
7f110ff9 721 return r;
57d42a5f 722}
15ae422b
LP
723
724int config_parse_path_strv(
725 const char *filename,
726 unsigned line,
727 const char *section,
728 const char *lvalue,
2b583ce6 729 int ltype,
15ae422b
LP
730 const char *rvalue,
731 void *data,
732 void *userdata) {
733
734 char*** sv = data;
735 char **n;
736 char *w;
737 unsigned k;
738 size_t l;
739 char *state;
740 int r;
741
742 assert(filename);
743 assert(lvalue);
744 assert(rvalue);
745 assert(data);
746
747 k = strv_length(*sv);
748 FOREACH_WORD_QUOTED(w, l, rvalue, state)
749 k++;
750
7f110ff9
LP
751 n = new(char*, k+1);
752 if (!n)
15ae422b
LP
753 return -ENOMEM;
754
755 k = 0;
756 if (*sv)
757 for (; (*sv)[k]; k++)
758 n[k] = (*sv)[k];
759
760 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
7f110ff9
LP
761 n[k] = strndup(w, l);
762 if (!n[k]) {
15ae422b
LP
763 r = -ENOMEM;
764 goto fail;
765 }
766
7f110ff9
LP
767 if (!utf8_is_valid(n[k])) {
768 log_error("[%s:%u] Path is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
769 free(n[k]);
770 continue;
771 }
772
15ae422b 773 if (!path_is_absolute(n[k])) {
f975e971
LP
774 log_error("[%s:%u] Not an absolute path, ignoring: %s", filename, line, rvalue);
775 free(n[k]);
776 continue;
15ae422b
LP
777 }
778
01f78473 779 path_kill_slashes(n[k]);
15ae422b
LP
780 k++;
781 }
782
783 n[k] = NULL;
784 free(*sv);
785 *sv = n;
786
787 return 0;
788
789fail:
15ae422b
LP
790 for (; k > 0; k--)
791 free(n[k-1]);
792 free(n);
793
794 return r;
795}
f975e971
LP
796
797int config_parse_usec(
798 const char *filename,
799 unsigned line,
800 const char *section,
801 const char *lvalue,
802 int ltype,
803 const char *rvalue,
804 void *data,
805 void *userdata) {
806
807 usec_t *usec = data;
808
809 assert(filename);
810 assert(lvalue);
811 assert(rvalue);
812 assert(data);
813
814 if (parse_usec(rvalue, usec) < 0) {
815 log_error("[%s:%u] Failed to parse time value, ignoring: %s", filename, line, rvalue);
d88a251b
LP
816 return 0;
817 }
818
819 return 0;
820}
821
822int config_parse_nsec(
823 const char *filename,
824 unsigned line,
825 const char *section,
826 const char *lvalue,
827 int ltype,
828 const char *rvalue,
829 void *data,
830 void *userdata) {
831
832 nsec_t *nsec = data;
833
834 assert(filename);
835 assert(lvalue);
836 assert(rvalue);
837 assert(data);
838
839 if (parse_nsec(rvalue, nsec) < 0) {
840 log_error("[%s:%u] Failed to parse time value, ignoring: %s", filename, line, rvalue);
f975e971
LP
841 return 0;
842 }
843
844 return 0;
845}
846
847int config_parse_mode(
848 const char *filename,
849 unsigned line,
850 const char *section,
851 const char *lvalue,
852 int ltype,
853 const char *rvalue,
854 void *data,
855 void *userdata) {
856
857 mode_t *m = data;
858 long l;
859 char *x = NULL;
860
861 assert(filename);
862 assert(lvalue);
863 assert(rvalue);
864 assert(data);
865
866 errno = 0;
867 l = strtol(rvalue, &x, 8);
868 if (!x || *x || errno) {
869 log_error("[%s:%u] Failed to parse mode value, ignoring: %s", filename, line, rvalue);
870 return 0;
871 }
872
873 if (l < 0000 || l > 07777) {
874 log_error("[%s:%u] mode value out of range, ignoring: %s", filename, line, rvalue);
875 return 0;
876 }
877
878 *m = (mode_t) l;
879 return 0;
880}
213ba152
LP
881
882int config_parse_facility(
883 const char *filename,
884 unsigned line,
885 const char *section,
886 const char *lvalue,
887 int ltype,
888 const char *rvalue,
889 void *data,
890 void *userdata) {
891
892
893 int *o = data, x;
894
895 assert(filename);
896 assert(lvalue);
897 assert(rvalue);
898 assert(data);
899
900 x = log_facility_unshifted_from_string(rvalue);
901 if (x < 0) {
902 log_error("[%s:%u] Failed to parse log facility, ignoring: %s", filename, line, rvalue);
903 return 0;
904 }
905
906 *o = (x << 3) | LOG_PRI(*o);
907
908 return 0;
909}
910
911int config_parse_level(
912 const char *filename,
913 unsigned line,
914 const char *section,
915 const char *lvalue,
916 int ltype,
917 const char *rvalue,
918 void *data,
919 void *userdata) {
920
921
922 int *o = data, x;
923
924 assert(filename);
925 assert(lvalue);
926 assert(rvalue);
927 assert(data);
928
929 x = log_level_from_string(rvalue);
930 if (x < 0) {
931 log_error("[%s:%u] Failed to parse log level, ignoring: %s", filename, line, rvalue);
932 return 0;
933 }
934
935 *o = (*o & LOG_FACMASK) | x;
936 return 0;
937}
96342de6
LN
938
939int config_parse_set_status(
940 const char *filename,
941 unsigned line,
942 const char *section,
943 const char *lvalue,
944 int ltype,
945 const char *rvalue,
946 void *data,
947 void *userdata) {
948
949 char *w;
950 size_t l;
951 char *state;
952 int r;
953 ExitStatusSet *status_set = data;
954
955 assert(filename);
956 assert(lvalue);
957 assert(rvalue);
958 assert(data);
959
960 FOREACH_WORD(w, l, rvalue, state) {
961 int val;
962 char *temp = strndup(w, l);
963 if (!temp)
964 return log_oom();
965
966 r = safe_atoi(temp, &val);
967 if (r < 0) {
968 val = signal_from_string_try_harder(temp);
969 free(temp);
970 if (val > 0) {
971 if (!status_set->signal) {
972 status_set->signal = set_new(trivial_hash_func, trivial_compare_func);
973 if (!status_set->signal)
974 return log_oom();
975 }
976 r = set_put(status_set->signal, INT_TO_PTR(val));
977 if (r < 0) {
978 log_error("[%s:%u] Unable to store: %s", filename, line, w);
979 return r;
980 }
981 } else {
982 log_error("[%s:%u] Failed to parse value: %s", filename, line, w);
983 return r;
984 }
985 } else {
986 free(temp);
987 if(val < 0 || val > 255)
988 log_warning("[%s:%u] Value %d is outside range 0-255, ignoring", filename, line, val);
989 else {
990 if (!status_set->code) {
991 status_set->code = set_new(trivial_hash_func, trivial_compare_func);
992 if (!status_set->code)
993 return log_oom();
994 }
995 r = set_put(status_set->code, INT_TO_PTR(val));
996 if (r < 0) {
997 log_error("[%s:%u] Unable to store: %s", filename, line, w);
998 return r;
999 }
1000 }
1001 }
1002
1003 }
1004 return 0;
1005}