chiark / gitweb /
42c181de4da6efbef91ad6f3463af6752a0f43e6
[elogind.git] / src / core / load-fragment.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 Lennart Poettering
7   Copyright 2012 Holger Hans Peter Freyther
8
9   systemd is free software; you can redistribute it and/or modify it
10   under the terms of the GNU Lesser General Public License as published by
11   the Free Software Foundation; either version 2.1 of the License, or
12   (at your option) any later version.
13
14   systemd is distributed in the hope that it will be useful, but
15   WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   Lesser General Public License for more details.
18
19   You should have received a copy of the GNU Lesser General Public License
20   along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 ***/
22
23 #include <linux/oom.h>
24 #include <assert.h>
25 #include <errno.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <sched.h>
30 #include <sys/prctl.h>
31 #include <sys/mount.h>
32 #include <linux/fs.h>
33 #include <sys/stat.h>
34 #include <sys/time.h>
35 #include <sys/resource.h>
36
37 #include "unit.h"
38 #include "strv.h"
39 #include "conf-parser.h"
40 #include "load-fragment.h"
41 #include "log.h"
42 #include "ioprio.h"
43 #include "securebits.h"
44 #include "missing.h"
45 #include "unit-name.h"
46 #include "unit-printf.h"
47 #include "bus-errors.h"
48 #include "utf8.h"
49 #include "path-util.h"
50 #include "syscall-list.h"
51 #include "env-util.h"
52
53 #ifndef HAVE_SYSV_COMPAT
54 int config_parse_warn_compat(
55                 const char *filename,
56                 unsigned line,
57                 const char *section,
58                 const char *lvalue,
59                 int ltype,
60                 const char *rvalue,
61                 void *data,
62                 void *userdata) {
63
64         log_debug("[%s:%u] Support for option %s= has been disabled at compile time and is ignored", filename, line, lvalue);
65         return 0;
66 }
67 #endif
68
69 int config_parse_unit_deps(
70                 const char *filename,
71                 unsigned line,
72                 const char *section,
73                 const char *lvalue,
74                 int ltype,
75                 const char *rvalue,
76                 void *data,
77                 void *userdata) {
78
79         UnitDependency d = ltype;
80         Unit *u = userdata;
81         char *w;
82         size_t l;
83         char *state;
84
85         assert(filename);
86         assert(lvalue);
87         assert(rvalue);
88
89         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
90                 char _cleanup_free_ *t = NULL, *k = NULL;
91                 int r;
92
93                 t = strndup(w, l);
94                 if (!t)
95                         return log_oom();
96
97                 k = unit_name_printf(u, t);
98                 if (!k)
99                         return log_oom();
100
101                 r = unit_add_dependency_by_name(u, d, k, NULL, true);
102                 if (r < 0)
103                         log_error("[%s:%u] Failed to add dependency on %s, ignoring: %s",
104                                   filename, line, k, strerror(-r));
105         }
106
107         return 0;
108 }
109
110 int config_parse_unit_string_printf(
111                 const char *filename,
112                 unsigned line,
113                 const char *section,
114                 const char *lvalue,
115                 int ltype,
116                 const char *rvalue,
117                 void *data,
118                 void *userdata) {
119
120         Unit *u = userdata;
121         _cleanup_free_ char *k = NULL;
122
123         assert(filename);
124         assert(lvalue);
125         assert(rvalue);
126         assert(u);
127
128         k = unit_full_printf(u, rvalue);
129         if (!k)
130                 log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.",
131                           filename, line, rvalue);
132
133         return config_parse_string(filename, line, section, lvalue, ltype, k ? k : rvalue, data, userdata);
134 }
135
136 int config_parse_unit_strv_printf(
137                 const char *filename,
138                 unsigned line,
139                 const char *section,
140                 const char *lvalue,
141                 int ltype,
142                 const char *rvalue,
143                 void *data,
144                 void *userdata) {
145
146         Unit *u = userdata;
147         _cleanup_free_ char *k = NULL;
148
149         assert(filename);
150         assert(lvalue);
151         assert(rvalue);
152         assert(u);
153
154         k = unit_full_printf(u, rvalue);
155         if (!k)
156                 log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.",
157                           filename, line, rvalue);
158
159         return config_parse_strv(filename, line, section, lvalue, ltype, k ? k : rvalue, data, userdata);
160 }
161
162 int config_parse_unit_path_printf(
163                 const char *filename,
164                 unsigned line,
165                 const char *section,
166                 const char *lvalue,
167                 int ltype,
168                 const char *rvalue,
169                 void *data,
170                 void *userdata) {
171
172         Unit *u = userdata;
173         _cleanup_free_ char *k = NULL;
174
175         assert(filename);
176         assert(lvalue);
177         assert(rvalue);
178         assert(u);
179
180         k = unit_full_printf(u, rvalue);
181         if (!k)
182                 log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.",
183                           filename, line, rvalue);
184
185         return config_parse_path(filename, line, section, lvalue, ltype, k ? k : rvalue, data, userdata);
186 }
187
188 int config_parse_socket_listen(
189                 const char *filename,
190                 unsigned line,
191                 const char *section,
192                 const char *lvalue,
193                 int ltype,
194                 const char *rvalue,
195                 void *data,
196                 void *userdata) {
197
198         SocketPort *p, *tail;
199         Socket *s;
200
201         assert(filename);
202         assert(lvalue);
203         assert(rvalue);
204         assert(data);
205
206         s = SOCKET(data);
207
208         if (isempty(rvalue)) {
209                 /* An empty assignment removes all ports */
210                 socket_free_ports(s);
211                 return 0;
212         }
213
214         p = new0(SocketPort, 1);
215         if (!p)
216                 return log_oom();
217
218         if (ltype != SOCKET_SOCKET) {
219
220                 p->type = ltype;
221                 p->path = unit_full_printf(UNIT(s), rvalue);
222                 if (!p->path) {
223                         p->path = strdup(rvalue);
224                         if (!p->path) {
225                                 free(p);
226                                 return log_oom();
227                         } else
228                                 log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.",
229                                           filename, line, rvalue);
230                 }
231
232                 path_kill_slashes(p->path);
233
234         } else if (streq(lvalue, "ListenNetlink")) {
235                 _cleanup_free_ char  *k = NULL;
236                 int r;
237
238                 p->type = SOCKET_SOCKET;
239                 k = unit_full_printf(UNIT(s), rvalue);
240                 if (!k)
241                         log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.",
242                                   filename, line, rvalue);
243
244                 r = socket_address_parse_netlink(&p->address, k ? k : rvalue);
245                 if (r < 0) {
246                         log_error("[%s:%u] Failed to parse address value, ignoring: %s", filename, line, rvalue);
247                         free(p);
248                         return 0;
249                 }
250
251         } else {
252                 _cleanup_free_ char *k = NULL;
253                 int r;
254
255                 p->type = SOCKET_SOCKET;
256                 k = unit_full_printf(UNIT(s), rvalue);
257                 if (!k)
258                         log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.",
259                                   filename, line, rvalue);
260
261                 r = socket_address_parse(&p->address, k ? k : rvalue);
262                 if (r < 0) {
263                         log_error("[%s:%u] Failed to parse address value, ignoring: %s", filename, line, rvalue);
264                         free(p);
265                         return 0;
266                 }
267
268                 if (streq(lvalue, "ListenStream"))
269                         p->address.type = SOCK_STREAM;
270                 else if (streq(lvalue, "ListenDatagram"))
271                         p->address.type = SOCK_DGRAM;
272                 else {
273                         assert(streq(lvalue, "ListenSequentialPacket"));
274                         p->address.type = SOCK_SEQPACKET;
275                 }
276
277                 if (socket_address_family(&p->address) != AF_LOCAL && p->address.type == SOCK_SEQPACKET) {
278                         log_error("[%s:%u] Address family not supported, ignoring: %s", filename, line, rvalue);
279                         free(p);
280                         return 0;
281                 }
282         }
283
284         p->fd = -1;
285
286         if (s->ports) {
287                 LIST_FIND_TAIL(SocketPort, port, s->ports, tail);
288                 LIST_INSERT_AFTER(SocketPort, port, s->ports, tail, p);
289         } else
290                 LIST_PREPEND(SocketPort, port, s->ports, p);
291
292         return 0;
293 }
294
295 int config_parse_socket_bind(
296                 const char *filename,
297                 unsigned line,
298                 const char *section,
299                 const char *lvalue,
300                 int ltype,
301                 const char *rvalue,
302                 void *data,
303                 void *userdata) {
304
305         Socket *s;
306         SocketAddressBindIPv6Only b;
307
308         assert(filename);
309         assert(lvalue);
310         assert(rvalue);
311         assert(data);
312
313         s = SOCKET(data);
314
315         b = socket_address_bind_ipv6_only_from_string(rvalue);
316         if (b < 0) {
317                 int r;
318
319                 r = parse_boolean(rvalue);
320                 if (r < 0) {
321                         log_error("[%s:%u] Failed to parse bind IPv6 only value, ignoring: %s", filename, line, rvalue);
322                         return 0;
323                 }
324
325                 s->bind_ipv6_only = r ? SOCKET_ADDRESS_IPV6_ONLY : SOCKET_ADDRESS_BOTH;
326         } else
327                 s->bind_ipv6_only = b;
328
329         return 0;
330 }
331
332 int config_parse_exec_nice(
333                 const char *filename,
334                 unsigned line,
335                 const char *section,
336                 const char *lvalue,
337                 int ltype,
338                 const char *rvalue,
339                 void *data,
340                 void *userdata) {
341
342         ExecContext *c = data;
343         int priority;
344
345         assert(filename);
346         assert(lvalue);
347         assert(rvalue);
348         assert(data);
349
350         if (safe_atoi(rvalue, &priority) < 0) {
351                 log_error("[%s:%u] Failed to parse nice priority, ignoring: %s. ", filename, line, rvalue);
352                 return 0;
353         }
354
355         if (priority < PRIO_MIN || priority >= PRIO_MAX) {
356                 log_error("[%s:%u] Nice priority out of range, ignoring: %s", filename, line, rvalue);
357                 return 0;
358         }
359
360         c->nice = priority;
361         c->nice_set = true;
362
363         return 0;
364 }
365
366 int config_parse_exec_oom_score_adjust(
367                 const char *filename,
368                 unsigned line,
369                 const char *section,
370                 const char *lvalue,
371                 int ltype,
372                 const char *rvalue,
373                 void *data,
374                 void *userdata) {
375
376         ExecContext *c = data;
377         int oa;
378
379         assert(filename);
380         assert(lvalue);
381         assert(rvalue);
382         assert(data);
383
384         if (safe_atoi(rvalue, &oa) < 0) {
385                 log_error("[%s:%u] Failed to parse the OOM score adjust value, ignoring: %s", filename, line, rvalue);
386                 return 0;
387         }
388
389         if (oa < OOM_SCORE_ADJ_MIN || oa > OOM_SCORE_ADJ_MAX) {
390                 log_error("[%s:%u] OOM score adjust value out of range, ignoring: %s", filename, line, rvalue);
391                 return 0;
392         }
393
394         c->oom_score_adjust = oa;
395         c->oom_score_adjust_set = true;
396
397         return 0;
398 }
399
400 int config_parse_exec(
401                 const char *filename,
402                 unsigned line,
403                 const char *section,
404                 const char *lvalue,
405                 int ltype,
406                 const char *rvalue,
407                 void *data,
408                 void *userdata) {
409
410         ExecCommand **e = data, *nce;
411         char *path, **n;
412         unsigned k;
413         int r;
414
415         assert(filename);
416         assert(lvalue);
417         assert(rvalue);
418         assert(e);
419
420         e += ltype;
421
422         if (isempty(rvalue)) {
423                 /* An empty assignment resets the list */
424                 exec_command_free_list(*e);
425                 *e = NULL;
426                 return 0;
427         }
428
429         /* We accept an absolute path as first argument, or
430          * alternatively an absolute prefixed with @ to allow
431          * overriding of argv[0]. */
432         for (;;) {
433                 int i;
434                 char *w;
435                 size_t l;
436                 char *state;
437                 bool honour_argv0 = false, ignore = false;
438
439                 path = NULL;
440                 nce = NULL;
441                 n = NULL;
442
443                 rvalue += strspn(rvalue, WHITESPACE);
444
445                 if (rvalue[0] == 0)
446                         break;
447
448                 for (i = 0; i < 2; i++) {
449                         if (rvalue[0] == '-' && !ignore) {
450                                 ignore = true;
451                                 rvalue ++;
452                         }
453
454                         if (rvalue[0] == '@' && !honour_argv0) {
455                                 honour_argv0 = true;
456                                 rvalue ++;
457                         }
458                 }
459
460                 if (*rvalue != '/') {
461                         log_error("[%s:%u] Executable path is not absolute, ignoring: %s",
462                                   filename, line, rvalue);
463                         return 0;
464                 }
465
466                 k = 0;
467                 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
468                         if (strneq(w, ";", MAX(l, 1U)))
469                                 break;
470
471                         k++;
472                 }
473
474                 n = new(char*, k + !honour_argv0);
475                 if (!n)
476                         return log_oom();
477
478                 k = 0;
479                 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
480                         if (strneq(w, ";", MAX(l, 1U)))
481                                 break;
482                         else if (strneq(w, "\\;", MAX(l, 1U)))
483                                 w ++;
484
485                         if (honour_argv0 && w == rvalue) {
486                                 assert(!path);
487
488                                 path = strndup(w, l);
489                                 if (!path) {
490                                         r = log_oom();
491                                         goto fail;
492                                 }
493
494                                 if (!utf8_is_valid(path)) {
495                                         log_error("[%s:%u] Path is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
496                                         r = 0;
497                                         goto fail;
498                                 }
499
500                         } else {
501                                 char *c;
502
503                                 c = n[k++] = cunescape_length(w, l);
504                                 if (!c) {
505                                         r = log_oom();
506                                         goto fail;
507                                 }
508
509                                 if (!utf8_is_valid(c)) {
510                                         log_error("[%s:%u] Path is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
511                                         r = 0;
512                                         goto fail;
513                                 }
514                         }
515                 }
516
517                 n[k] = NULL;
518
519                 if (!n[0]) {
520                         log_error("[%s:%u] Invalid command line, ignoring: %s", filename, line, rvalue);
521                         r = 0;
522                         goto fail;
523                 }
524
525                 if (!path) {
526                         path = strdup(n[0]);
527                         if (!path) {
528                                 r = log_oom();
529                                 goto fail;
530                         }
531                 }
532
533                 assert(path_is_absolute(path));
534
535                 nce = new0(ExecCommand, 1);
536                 if (!nce) {
537                         r = log_oom();
538                         goto fail;
539                 }
540
541                 nce->argv = n;
542                 nce->path = path;
543                 nce->ignore = ignore;
544
545                 path_kill_slashes(nce->path);
546
547                 exec_command_append_list(e, nce);
548
549                 rvalue = state;
550         }
551
552         return 0;
553
554 fail:
555         n[k] = NULL;
556         strv_free(n);
557         free(path);
558         free(nce);
559
560         return r;
561 }
562
563 DEFINE_CONFIG_PARSE_ENUM(config_parse_service_type, service_type, ServiceType, "Failed to parse service type");
564 DEFINE_CONFIG_PARSE_ENUM(config_parse_service_restart, service_restart, ServiceRestart, "Failed to parse service restart specifier");
565
566 int config_parse_socket_bindtodevice(
567                 const char *filename,
568                 unsigned line,
569                 const char *section,
570                 const char *lvalue,
571                 int ltype,
572                 const char *rvalue,
573                 void *data,
574                 void *userdata) {
575
576         Socket *s = data;
577         char *n;
578
579         assert(filename);
580         assert(lvalue);
581         assert(rvalue);
582         assert(data);
583
584         if (rvalue[0] && !streq(rvalue, "*")) {
585                 n = strdup(rvalue);
586                 if (!n)
587                         return log_oom();
588         } else
589                 n = NULL;
590
591         free(s->bind_to_device);
592         s->bind_to_device = n;
593
594         return 0;
595 }
596
597 DEFINE_CONFIG_PARSE_ENUM(config_parse_output, exec_output, ExecOutput, "Failed to parse output specifier");
598 DEFINE_CONFIG_PARSE_ENUM(config_parse_input, exec_input, ExecInput, "Failed to parse input specifier");
599
600 int config_parse_exec_io_class(
601                 const char *filename,
602                 unsigned line,
603                 const char *section,
604                 const char *lvalue,
605                 int ltype,
606                 const char *rvalue,
607                 void *data,
608                 void *userdata) {
609
610         ExecContext *c = data;
611         int x;
612
613         assert(filename);
614         assert(lvalue);
615         assert(rvalue);
616         assert(data);
617
618         x = ioprio_class_from_string(rvalue);
619         if (x < 0) {
620                 log_error("[%s:%u] Failed to parse IO scheduling class, ignoring: %s", filename, line, rvalue);
621                 return 0;
622         }
623
624         c->ioprio = IOPRIO_PRIO_VALUE(x, IOPRIO_PRIO_DATA(c->ioprio));
625         c->ioprio_set = true;
626
627         return 0;
628 }
629
630 int config_parse_exec_io_priority(
631                 const char *filename,
632                 unsigned line,
633                 const char *section,
634                 const char *lvalue,
635                 int ltype,
636                 const char *rvalue,
637                 void *data,
638                 void *userdata) {
639
640         ExecContext *c = data;
641         int i;
642
643         assert(filename);
644         assert(lvalue);
645         assert(rvalue);
646         assert(data);
647
648         if (safe_atoi(rvalue, &i) < 0 || i < 0 || i >= IOPRIO_BE_NR) {
649                 log_error("[%s:%u] Failed to parse io priority, ignoring: %s", filename, line, rvalue);
650                 return 0;
651         }
652
653         c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_PRIO_CLASS(c->ioprio), i);
654         c->ioprio_set = true;
655
656         return 0;
657 }
658
659 int config_parse_exec_cpu_sched_policy(
660                 const char *filename,
661                 unsigned line,
662                 const char *section,
663                 const char *lvalue,
664                 int ltype,
665                 const char *rvalue,
666                 void *data,
667                 void *userdata) {
668
669
670         ExecContext *c = data;
671         int x;
672
673         assert(filename);
674         assert(lvalue);
675         assert(rvalue);
676         assert(data);
677
678         x = sched_policy_from_string(rvalue);
679         if (x < 0) {
680                 log_error("[%s:%u] Failed to parse CPU scheduling policy, ignoring: %s", filename, line, rvalue);
681                 return 0;
682         }
683
684         c->cpu_sched_policy = x;
685         /* Moving to or from real-time policy? We need to adjust the priority */
686         c->cpu_sched_priority = CLAMP(c->cpu_sched_priority, sched_get_priority_min(x), sched_get_priority_max(x));
687         c->cpu_sched_set = true;
688
689         return 0;
690 }
691
692 int config_parse_exec_cpu_sched_prio(
693                 const char *filename,
694                 unsigned line,
695                 const char *section,
696                 const char *lvalue,
697                 int ltype,
698                 const char *rvalue,
699                 void *data,
700                 void *userdata) {
701
702         ExecContext *c = data;
703         int i, min, max;
704
705         assert(filename);
706         assert(lvalue);
707         assert(rvalue);
708         assert(data);
709
710         if (safe_atoi(rvalue, &i) < 0) {
711                 log_error("[%s:%u] Failed to parse CPU scheduling priority, ignoring: %s", filename, line, rvalue);
712                 return 0;
713         }
714
715         /* On Linux RR/FIFO range from 1 to 99 and OTHER/BATCH may only be 0 */
716         min = sched_get_priority_min(c->cpu_sched_policy);
717         max = sched_get_priority_max(c->cpu_sched_policy);
718
719         if (i < min || i > max) {
720                 log_error("[%s:%u] CPU scheduling priority is out of range, ignoring: %s", filename, line, rvalue);
721                 return 0;
722         }
723
724         c->cpu_sched_priority = i;
725         c->cpu_sched_set = true;
726
727         return 0;
728 }
729
730 int config_parse_exec_cpu_affinity(
731                 const char *filename,
732                 unsigned line,
733                 const char *section,
734                 const char *lvalue,
735                 int ltype,
736                 const char *rvalue,
737                 void *data,
738                 void *userdata) {
739
740         ExecContext *c = data;
741         char *w;
742         size_t l;
743         char *state;
744
745         assert(filename);
746         assert(lvalue);
747         assert(rvalue);
748         assert(data);
749
750         if (isempty(rvalue)) {
751                 /* An empty assignment resets the CPU list */
752                 if (c->cpuset)
753                         CPU_FREE(c->cpuset);
754                 c->cpuset = NULL;
755                 return 0;
756         }
757
758         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
759                 char _cleanup_free_ *t = NULL;
760                 int r;
761                 unsigned cpu;
762
763                 t = strndup(w, l);
764                 if (!t)
765                         return log_oom();
766
767                 r = safe_atou(t, &cpu);
768
769                 if (!c->cpuset) {
770                         c->cpuset = cpu_set_malloc(&c->cpuset_ncpus);
771                         if (!c->cpuset)
772                                 return log_oom();
773                 }
774
775                 if (r < 0 || cpu >= c->cpuset_ncpus) {
776                         log_error("[%s:%u] Failed to parse CPU affinity %s, ignoring: %s",
777                                   filename, line, t, rvalue);
778                         return 0;
779                 }
780
781                 CPU_SET_S(cpu, CPU_ALLOC_SIZE(c->cpuset_ncpus), c->cpuset);
782         }
783
784         return 0;
785 }
786
787 int config_parse_exec_capabilities(
788                 const char *filename,
789                 unsigned line,
790                 const char *section,
791                 const char *lvalue,
792                 int ltype,
793                 const char *rvalue,
794                 void *data,
795                 void *userdata) {
796
797         ExecContext *c = data;
798         cap_t cap;
799
800         assert(filename);
801         assert(lvalue);
802         assert(rvalue);
803         assert(data);
804
805         cap = cap_from_text(rvalue);
806         if (!cap) {
807                 if (errno == ENOMEM)
808                         return log_oom();
809
810                 log_error("[%s:%u] Failed to parse capabilities, ignoring: %s", filename, line, rvalue);
811                 return 0;
812         }
813
814         if (c->capabilities)
815                 cap_free(c->capabilities);
816         c->capabilities = cap;
817
818         return 0;
819 }
820
821 int config_parse_exec_secure_bits(
822                 const char *filename,
823                 unsigned line,
824                 const char *section,
825                 const char *lvalue,
826                 int ltype,
827                 const char *rvalue,
828                 void *data,
829                 void *userdata) {
830
831         ExecContext *c = data;
832         char *w;
833         size_t l;
834         char *state;
835
836         assert(filename);
837         assert(lvalue);
838         assert(rvalue);
839         assert(data);
840
841         if (isempty(rvalue)) {
842                 /* An empty assignment resets the field */
843                 c->secure_bits = 0;
844                 return 0;
845         }
846
847         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
848                 if (first_word(w, "keep-caps"))
849                         c->secure_bits |= 1<<SECURE_KEEP_CAPS;
850                 else if (first_word(w, "keep-caps-locked"))
851                         c->secure_bits |= 1<<SECURE_KEEP_CAPS_LOCKED;
852                 else if (first_word(w, "no-setuid-fixup"))
853                         c->secure_bits |= 1<<SECURE_NO_SETUID_FIXUP;
854                 else if (first_word(w, "no-setuid-fixup-locked"))
855                         c->secure_bits |= 1<<SECURE_NO_SETUID_FIXUP_LOCKED;
856                 else if (first_word(w, "noroot"))
857                         c->secure_bits |= 1<<SECURE_NOROOT;
858                 else if (first_word(w, "noroot-locked"))
859                         c->secure_bits |= 1<<SECURE_NOROOT_LOCKED;
860                 else {
861                         log_error("[%s:%u] Failed to parse secure bits, ignoring: %s",
862                                   filename, line, rvalue);
863                         return 0;
864                 }
865         }
866
867         return 0;
868 }
869
870 int config_parse_bounding_set(
871                 const char *filename,
872                 unsigned line,
873                 const char *section,
874                 const char *lvalue,
875                 int ltype,
876                 const char *rvalue,
877                 void *data,
878                 void *userdata) {
879
880         uint64_t *capability_bounding_set_drop = data;
881         char *w;
882         size_t l;
883         char *state;
884         bool invert = false;
885         uint64_t sum = 0;
886
887         assert(filename);
888         assert(lvalue);
889         assert(rvalue);
890         assert(data);
891
892         if (rvalue[0] == '~') {
893                 invert = true;
894                 rvalue++;
895         }
896
897         /* Note that we store this inverted internally, since the
898          * kernel wants it like this. But we actually expose it
899          * non-inverted everywhere to have a fully normalized
900          * interface. */
901
902         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
903                 char _cleanup_free_ *t = NULL;
904                 int r;
905                 cap_value_t cap;
906
907                 t = strndup(w, l);
908                 if (!t)
909                         return log_oom();
910
911                 r = cap_from_name(t, &cap);
912                 if (r < 0) {
913                         log_error("[%s:%u] Failed to parse capability in bounding set, ignoring: %s",
914                                   filename, line, t);
915                         continue;
916                 }
917
918                 sum |= ((uint64_t) 1ULL) << (uint64_t) cap;
919         }
920
921         if (invert)
922                 *capability_bounding_set_drop |= sum;
923         else
924                 *capability_bounding_set_drop |= ~sum;
925
926         return 0;
927 }
928
929 int config_parse_limit(
930                 const char *filename,
931                 unsigned line,
932                 const char *section,
933                 const char *lvalue,
934                 int ltype,
935                 const char *rvalue,
936                 void *data,
937                 void *userdata) {
938
939         struct rlimit **rl = data;
940         unsigned long long u;
941
942         assert(filename);
943         assert(lvalue);
944         assert(rvalue);
945         assert(data);
946
947         rl += ltype;
948
949         if (streq(rvalue, "infinity"))
950                 u = (unsigned long long) RLIM_INFINITY;
951         else if (safe_atollu(rvalue, &u) < 0) {
952                 log_error("[%s:%u] Failed to parse resource value, ignoring: %s", filename, line, rvalue);
953                 return 0;
954         }
955
956         if (!*rl) {
957                 *rl = new(struct rlimit, 1);
958                 if (!*rl)
959                         return log_oom();
960         }
961
962         (*rl)->rlim_cur = (*rl)->rlim_max = (rlim_t) u;
963         return 0;
964 }
965
966 int config_parse_unit_cgroup(
967                 const char *filename,
968                 unsigned line,
969                 const char *section,
970                 const char *lvalue,
971                 int ltype,
972                 const char *rvalue,
973                 void *data,
974                 void *userdata) {
975
976         Unit *u = userdata;
977         char *w;
978         size_t l;
979         char *state;
980
981         if (isempty(rvalue)) {
982                 /* An empty assignment resets the list */
983                 cgroup_bonding_free_list(u->cgroup_bondings, false);
984                 u->cgroup_bondings = NULL;
985                 return 0;
986         }
987
988         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
989                 char _cleanup_free_ *t = NULL, *k = NULL, *ku = NULL;
990                 int r;
991
992                 t = strndup(w, l);
993                 if (!t)
994                         return log_oom();
995
996                 k = unit_full_printf(u, t);
997                 if (!k)
998                         log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.",
999                                   filename, line, t);
1000
1001                 ku = cunescape(k ? k : t);
1002                 if (!ku)
1003                         return log_oom();
1004
1005                 r = unit_add_cgroup_from_text(u, ku, true, NULL);
1006                 if (r < 0) {
1007                         log_error("[%s:%u] Failed to parse cgroup value %s, ignoring: %s",
1008                                   filename, line, k, rvalue);
1009                         return 0;
1010                 }
1011         }
1012
1013         return 0;
1014 }
1015
1016 #ifdef HAVE_SYSV_COMPAT
1017 int config_parse_sysv_priority(
1018                 const char *filename,
1019                 unsigned line,
1020                 const char *section,
1021                 const char *lvalue,
1022                 int ltype,
1023                 const char *rvalue,
1024                 void *data,
1025                 void *userdata) {
1026
1027         int *priority = data;
1028         int i;
1029
1030         assert(filename);
1031         assert(lvalue);
1032         assert(rvalue);
1033         assert(data);
1034
1035         if (safe_atoi(rvalue, &i) < 0 || i < 0) {
1036                 log_error("[%s:%u] Failed to parse SysV start priority, ignoring: %s", filename, line, rvalue);
1037                 return 0;
1038         }
1039
1040         *priority = (int) i;
1041         return 0;
1042 }
1043 #endif
1044
1045 int config_parse_fsck_passno(
1046                 const char *filename,
1047                 unsigned line,
1048                 const char *section,
1049                 const char *lvalue,
1050                 int ltype,
1051                 const char *rvalue,
1052                 void *data,
1053                 void *userdata) {
1054
1055         int *passno = data;
1056         int i;
1057
1058         assert(filename);
1059         assert(lvalue);
1060         assert(rvalue);
1061         assert(data);
1062
1063         if (safe_atoi(rvalue, &i) || i < 0) {
1064                 log_error("[%s:%u] Failed to parse fsck pass number, ignoring: %s", filename, line, rvalue);
1065                 return 0;
1066         }
1067
1068         *passno = (int) i;
1069         return 0;
1070 }
1071
1072 DEFINE_CONFIG_PARSE_ENUM(config_parse_kill_mode, kill_mode, KillMode, "Failed to parse kill mode");
1073
1074 int config_parse_kill_signal(
1075                 const char *filename,
1076                 unsigned line,
1077                 const char *section,
1078                 const char *lvalue,
1079                 int ltype,
1080                 const char *rvalue,
1081                 void *data,
1082                 void *userdata) {
1083
1084         int *sig = data;
1085         int r;
1086
1087         assert(filename);
1088         assert(lvalue);
1089         assert(rvalue);
1090         assert(sig);
1091
1092         r = signal_from_string_try_harder(rvalue);
1093         if (r <= 0) {
1094                 log_error("[%s:%u] Failed to parse kill signal, ignoring: %s", filename, line, rvalue);
1095                 return 0;
1096         }
1097
1098         *sig = r;
1099         return 0;
1100 }
1101
1102 int config_parse_exec_mount_flags(
1103                 const char *filename,
1104                 unsigned line,
1105                 const char *section,
1106                 const char *lvalue,
1107                 int ltype,
1108                 const char *rvalue,
1109                 void *data,
1110                 void *userdata) {
1111
1112         ExecContext *c = data;
1113         char *w;
1114         size_t l;
1115         char *state;
1116         unsigned long flags = 0;
1117
1118         assert(filename);
1119         assert(lvalue);
1120         assert(rvalue);
1121         assert(data);
1122
1123         FOREACH_WORD_SEPARATOR(w, l, rvalue, ", ", state) {
1124                 char _cleanup_free_ *t;
1125
1126                 t = strndup(w, l);
1127                 if (!t)
1128                         return log_oom();
1129
1130                 if (streq(t, "shared"))
1131                         flags |= MS_SHARED;
1132                 else if (streq(t, "slave"))
1133                         flags |= MS_SLAVE;
1134                 else if (streq(w, "private"))
1135                         flags |= MS_PRIVATE;
1136                 else {
1137                         log_error("[%s:%u] Failed to parse mount flag %s, ignoring: %s",
1138                                   filename, line, t, rvalue);
1139                         return 0;
1140                 }
1141         }
1142
1143         c->mount_flags = flags;
1144         return 0;
1145 }
1146
1147 int config_parse_timer(
1148                 const char *filename,
1149                 unsigned line,
1150                 const char *section,
1151                 const char *lvalue,
1152                 int ltype,
1153                 const char *rvalue,
1154                 void *data,
1155                 void *userdata) {
1156
1157         Timer *t = data;
1158         usec_t u = 0;
1159         TimerValue *v;
1160         TimerBase b;
1161         CalendarSpec *c = NULL;
1162         clockid_t id;
1163
1164         assert(filename);
1165         assert(lvalue);
1166         assert(rvalue);
1167         assert(data);
1168
1169         if (isempty(rvalue)) {
1170                 /* Empty assignment resets list */
1171                 timer_free_values(t);
1172                 return 0;
1173         }
1174
1175         b = timer_base_from_string(lvalue);
1176         if (b < 0) {
1177                 log_error("[%s:%u] Failed to parse timer base, ignoring: %s", filename, line, lvalue);
1178                 return 0;
1179         }
1180
1181         if (b == TIMER_CALENDAR) {
1182                 if (calendar_spec_from_string(rvalue, &c) < 0) {
1183                         log_error("[%s:%u] Failed to parse calendar specification, ignoring: %s", filename, line, rvalue);
1184                         return 0;
1185                 }
1186
1187                 id = CLOCK_REALTIME;
1188         } else {
1189                 if (parse_sec(rvalue, &u) < 0) {
1190                         log_error("[%s:%u] Failed to parse timer value, ignoring: %s", filename, line, rvalue);
1191                         return 0;
1192                 }
1193
1194                 id = CLOCK_MONOTONIC;
1195         }
1196
1197         v = new0(TimerValue, 1);
1198         if (!v)
1199                 return log_oom();
1200
1201         v->base = b;
1202         v->clock_id = id;
1203         v->value = u;
1204         v->calendar_spec = c;
1205
1206         LIST_PREPEND(TimerValue, value, t->values, v);
1207
1208         return 0;
1209 }
1210
1211 int config_parse_timer_unit(
1212                 const char *filename,
1213                 unsigned line,
1214                 const char *section,
1215                 const char *lvalue,
1216                 int ltype,
1217                 const char *rvalue,
1218                 void *data,
1219                 void *userdata) {
1220
1221         Timer *t = data;
1222         int r;
1223         DBusError error;
1224         Unit *u;
1225         _cleanup_free_ char *p = NULL;
1226
1227         assert(filename);
1228         assert(lvalue);
1229         assert(rvalue);
1230         assert(data);
1231
1232         dbus_error_init(&error);
1233
1234         p = unit_name_printf(UNIT(t), rvalue);
1235         if (!p)
1236                 return log_oom();
1237
1238         if (endswith(p, ".timer")) {
1239                 log_error("[%s:%u] Unit cannot be of type timer, ignoring: %s", filename, line, rvalue);
1240                 return 0;
1241         }
1242
1243         r = manager_load_unit(UNIT(t)->manager, p, NULL, NULL, &u);
1244         if (r < 0) {
1245                 log_error("[%s:%u] Failed to load unit %s, ignoring: %s", filename, line, rvalue, bus_error(&error, r));
1246                 dbus_error_free(&error);
1247                 return 0;
1248         }
1249
1250         unit_ref_set(&t->unit, u);
1251
1252         return 0;
1253 }
1254
1255 int config_parse_path_spec(
1256                 const char *filename,
1257                 unsigned line,
1258                 const char *section,
1259                 const char *lvalue,
1260                 int ltype,
1261                 const char *rvalue,
1262                 void *data,
1263                 void *userdata) {
1264
1265         Path *p = data;
1266         PathSpec *s;
1267         PathType b;
1268         char *k;
1269
1270         assert(filename);
1271         assert(lvalue);
1272         assert(rvalue);
1273         assert(data);
1274
1275         if (isempty(rvalue)) {
1276                 /* Empty assignment clears list */
1277                 path_free_specs(p);
1278                 return 0;
1279         }
1280
1281         b = path_type_from_string(lvalue);
1282         if (b < 0) {
1283                 log_error("[%s:%u] Failed to parse path type, ignoring: %s", filename, line, lvalue);
1284                 return 0;
1285         }
1286
1287         k = unit_full_printf(UNIT(p), rvalue);
1288         if (!k) {
1289                 k = strdup(rvalue);
1290                 if (!k)
1291                         return log_oom();
1292                 else
1293                         log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.",
1294                                   filename, line, rvalue);
1295         }
1296
1297         if (!path_is_absolute(k)) {
1298                 log_error("[%s:%u] Path is not absolute, ignoring: %s", filename, line, k);
1299                 free(k);
1300                 return 0;
1301         }
1302
1303         s = new0(PathSpec, 1);
1304         if (!s) {
1305                 free(k);
1306                 return log_oom();
1307         }
1308
1309         s->path = path_kill_slashes(k);
1310         s->type = b;
1311         s->inotify_fd = -1;
1312
1313         LIST_PREPEND(PathSpec, spec, p->specs, s);
1314
1315         return 0;
1316 }
1317
1318 int config_parse_path_unit(
1319                 const char *filename,
1320                 unsigned line,
1321                 const char *section,
1322                 const char *lvalue,
1323                 int ltype,
1324                 const char *rvalue,
1325                 void *data,
1326                 void *userdata) {
1327
1328         Path *t = data;
1329         int r;
1330         DBusError error;
1331         Unit *u;
1332         _cleanup_free_ char *p = NULL;
1333
1334         assert(filename);
1335         assert(lvalue);
1336         assert(rvalue);
1337         assert(data);
1338
1339         dbus_error_init(&error);
1340
1341         p = unit_name_printf(UNIT(t), rvalue);
1342         if (!p)
1343                 return log_oom();
1344
1345         if (endswith(p, ".path")) {
1346                 log_error("[%s:%u] Unit cannot be of type path, ignoring: %s", filename, line, p);
1347                 return 0;
1348         }
1349
1350         r = manager_load_unit(UNIT(t)->manager, p, NULL, &error, &u);
1351         if (r < 0) {
1352                 log_error("[%s:%u] Failed to load unit %s, ignoring: %s", filename, line, p, bus_error(&error, r));
1353                 dbus_error_free(&error);
1354                 return 0;
1355         }
1356
1357         unit_ref_set(&t->unit, u);
1358
1359         return 0;
1360 }
1361
1362 int config_parse_socket_service(
1363                 const char *filename,
1364                 unsigned line,
1365                 const char *section,
1366                 const char *lvalue,
1367                 int ltype,
1368                 const char *rvalue,
1369                 void *data,
1370                 void *userdata) {
1371
1372         Socket *s = data;
1373         int r;
1374         DBusError error;
1375         Unit *x;
1376         _cleanup_free_ char *p = NULL;
1377
1378         assert(filename);
1379         assert(lvalue);
1380         assert(rvalue);
1381         assert(data);
1382
1383         dbus_error_init(&error);
1384
1385         p = unit_name_printf(UNIT(s), rvalue);
1386         if (!p)
1387                 return log_oom();
1388
1389         if (!endswith(p, ".service")) {
1390                 log_error("[%s:%u] Unit must be of type service, ignoring: %s", filename, line, rvalue);
1391                 return 0;
1392         }
1393
1394         r = manager_load_unit(UNIT(s)->manager, p, NULL, &error, &x);
1395         if (r < 0) {
1396                 log_error("[%s:%u] Failed to load unit %s, ignoring: %s", filename, line, rvalue, bus_error(&error, r));
1397                 dbus_error_free(&error);
1398                 return 0;
1399         }
1400
1401         unit_ref_set(&s->service, x);
1402
1403         return 0;
1404 }
1405
1406 int config_parse_service_sockets(
1407                 const char *filename,
1408                 unsigned line,
1409                 const char *section,
1410                 const char *lvalue,
1411                 int ltype,
1412                 const char *rvalue,
1413                 void *data,
1414                 void *userdata) {
1415
1416         Service *s = data;
1417         int r;
1418         char *state, *w;
1419         size_t l;
1420
1421         assert(filename);
1422         assert(lvalue);
1423         assert(rvalue);
1424         assert(data);
1425
1426         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
1427                 char _cleanup_free_ *t = NULL, *k = NULL;
1428
1429                 t = strndup(w, l);
1430                 if (!t)
1431                         return log_oom();
1432
1433                 k = unit_name_printf(UNIT(s), t);
1434                 if (!k)
1435                         return log_oom();
1436
1437                 if (!endswith(k, ".socket")) {
1438                         log_error("[%s:%u] Unit must be of type socket, ignoring: %s",
1439                                   filename, line, k);
1440                         continue;
1441                 }
1442
1443                 r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_WANTS, UNIT_AFTER, k, NULL, true);
1444                 if (r < 0)
1445                         log_error("[%s:%u] Failed to add dependency on %s, ignoring: %s",
1446                                   filename, line, k, strerror(-r));
1447
1448                 r = unit_add_dependency_by_name(UNIT(s), UNIT_TRIGGERED_BY, k, NULL, true);
1449                 if (r < 0)
1450                         return r;
1451         }
1452
1453         return 0;
1454 }
1455
1456 int config_parse_service_timeout(
1457                 const char *filename,
1458                 unsigned line,
1459                 const char *section,
1460                 const char *lvalue,
1461                 int ltype,
1462                 const char *rvalue,
1463                 void *data,
1464                 void *userdata) {
1465
1466         Service *s = userdata;
1467         int r;
1468
1469         assert(filename);
1470         assert(lvalue);
1471         assert(rvalue);
1472         assert(s);
1473
1474         r = config_parse_sec(filename, line, section, lvalue, ltype, rvalue, data, userdata);
1475         if (r < 0)
1476                 return r;
1477
1478         if (streq(lvalue, "TimeoutSec")) {
1479                 s->start_timeout_defined = true;
1480                 s->timeout_stop_usec = s->timeout_start_usec;
1481         } else if (streq(lvalue, "TimeoutStartSec"))
1482                 s->start_timeout_defined = true;
1483
1484         return 0;
1485 }
1486
1487 int config_parse_unit_env_file(
1488                 const char *filename,
1489                 unsigned line,
1490                 const char *section,
1491                 const char *lvalue,
1492                 int ltype,
1493                 const char *rvalue,
1494                 void *data,
1495                 void *userdata) {
1496
1497         char ***env = data;
1498         Unit *u = userdata;
1499         _cleanup_free_ char *s = NULL;
1500         int r;
1501
1502         assert(filename);
1503         assert(lvalue);
1504         assert(rvalue);
1505         assert(data);
1506
1507         if (isempty(rvalue)) {
1508                 /* Empty assignment frees the list */
1509                 strv_free(*env);
1510                 *env = NULL;
1511                 return 0;
1512         }
1513
1514         s = unit_full_printf(u, rvalue);
1515         if (!s)
1516                 return log_oom();
1517
1518         if (!path_is_absolute(s[0] == '-' ? s + 1 : s)) {
1519                 log_error("[%s:%u] Path '%s' is not absolute, ignoring.", filename, line, s);
1520                 return 0;
1521         }
1522
1523         r = strv_extend(env, s);
1524         if (r < 0)
1525                 return log_oom();
1526
1527         return 0;
1528 }
1529
1530 int config_parse_environ(
1531                 const char *filename,
1532                 unsigned line,
1533                 const char *section,
1534                 const char *lvalue,
1535                 int ltype,
1536                 const char *rvalue,
1537                 void *data,
1538                 void *userdata) {
1539
1540         Unit *u = userdata;
1541         char*** env = data, *w, *state;
1542         size_t l;
1543         _cleanup_free_ char *k = NULL;
1544
1545         assert(filename);
1546         assert(lvalue);
1547         assert(rvalue);
1548         assert(u);
1549
1550         if (isempty(rvalue)) {
1551                 /* Empty assignment resets the list */
1552                 strv_free(*env);
1553                 *env = NULL;
1554                 return 0;
1555         }
1556
1557         k = unit_full_printf(u, rvalue);
1558         if (!k)
1559                 return log_oom();
1560
1561         FOREACH_WORD_QUOTED(w, l, k, state) {
1562                 _cleanup_free_ char *n;
1563                 char **x;
1564
1565                 n = cunescape_length(w, l);
1566                 if (!n)
1567                         return log_oom();
1568
1569                 if (!env_assignment_is_valid(n)) {
1570                         log_error("[%s:%u] Invalid environment assignment, ignoring: %s", filename, line, rvalue);
1571                         continue;
1572                 }
1573
1574                 x = strv_env_set(*env, n);
1575                 if (!x)
1576                         return log_oom();
1577
1578                 strv_free(*env);
1579                 *env = x;
1580         }
1581
1582         return 0;
1583 }
1584
1585 int config_parse_ip_tos(
1586                 const char *filename,
1587                 unsigned line,
1588                 const char *section,
1589                 const char *lvalue,
1590                 int ltype,
1591                 const char *rvalue,
1592                 void *data,
1593                 void *userdata) {
1594
1595         int *ip_tos = data, x;
1596
1597         assert(filename);
1598         assert(lvalue);
1599         assert(rvalue);
1600         assert(data);
1601
1602         x = ip_tos_from_string(rvalue);
1603         if (x < 0) {
1604                 log_error("[%s:%u] Failed to parse IP TOS value, ignoring: %s", filename, line, rvalue);
1605                 return 0;
1606         }
1607
1608         *ip_tos = x;
1609         return 0;
1610 }
1611
1612 int config_parse_unit_condition_path(
1613                 const char *filename,
1614                 unsigned line,
1615                 const char *section,
1616                 const char *lvalue,
1617                 int ltype,
1618                 const char *rvalue,
1619                 void *data,
1620                 void *userdata) {
1621
1622         ConditionType cond = ltype;
1623         Unit *u = data;
1624         bool trigger, negate;
1625         Condition *c;
1626         _cleanup_free_ char *p = NULL;
1627
1628         assert(filename);
1629         assert(lvalue);
1630         assert(rvalue);
1631         assert(data);
1632
1633         if (isempty(rvalue)) {
1634                 /* Empty assignment resets the list */
1635                 condition_free_list(u->conditions);
1636                 u->conditions = NULL;
1637                 return 0;
1638         }
1639
1640         trigger = rvalue[0] == '|';
1641         if (trigger)
1642                 rvalue++;
1643
1644         negate = rvalue[0] == '!';
1645         if (negate)
1646                 rvalue++;
1647
1648         p = unit_full_printf(u, rvalue);
1649         if (!p)
1650                 return log_oom();
1651
1652         if (!path_is_absolute(p)) {
1653                 log_error("[%s:%u] Path in condition not absolute, ignoring: %s", filename, line, p);
1654                 return 0;
1655         }
1656
1657         c = condition_new(cond, p, trigger, negate);
1658         if (!c)
1659                 return log_oom();
1660
1661         LIST_PREPEND(Condition, conditions, u->conditions, c);
1662         return 0;
1663 }
1664
1665 int config_parse_unit_condition_string(
1666                 const char *filename,
1667                 unsigned line,
1668                 const char *section,
1669                 const char *lvalue,
1670                 int ltype,
1671                 const char *rvalue,
1672                 void *data,
1673                 void *userdata) {
1674
1675         ConditionType cond = ltype;
1676         Unit *u = data;
1677         bool trigger, negate;
1678         Condition *c;
1679         _cleanup_free_ char *s = NULL;
1680
1681         assert(filename);
1682         assert(lvalue);
1683         assert(rvalue);
1684         assert(data);
1685
1686         if (isempty(rvalue)) {
1687                 /* Empty assignment resets the list */
1688                 condition_free_list(u->conditions);
1689                 u->conditions = NULL;
1690                 return 0;
1691         }
1692
1693         trigger = rvalue[0] == '|';
1694         if (trigger)
1695                 rvalue++;
1696
1697         negate = rvalue[0] == '!';
1698         if (negate)
1699                 rvalue++;
1700
1701         s = unit_full_printf(u, rvalue);
1702         if (!s)
1703                 return log_oom();
1704
1705         c = condition_new(cond, s, trigger, negate);
1706         if (!c)
1707                 return log_oom();
1708
1709         LIST_PREPEND(Condition, conditions, u->conditions, c);
1710         return 0;
1711 }
1712
1713 int config_parse_unit_condition_null(
1714                 const char *filename,
1715                 unsigned line,
1716                 const char *section,
1717                 const char *lvalue,
1718                 int ltype,
1719                 const char *rvalue,
1720                 void *data,
1721                 void *userdata) {
1722
1723         Unit *u = data;
1724         Condition *c;
1725         bool trigger, negate;
1726         int b;
1727
1728         assert(filename);
1729         assert(lvalue);
1730         assert(rvalue);
1731         assert(data);
1732
1733         if (isempty(rvalue)) {
1734                 /* Empty assignment resets the list */
1735                 condition_free_list(u->conditions);
1736                 u->conditions = NULL;
1737                 return 0;
1738         }
1739
1740         trigger = rvalue[0] == '|';
1741         if (trigger)
1742                 rvalue++;
1743
1744         negate = rvalue[0] == '!';
1745         if (negate)
1746                 rvalue++;
1747
1748         b = parse_boolean(rvalue);
1749         if (b < 0) {
1750                 log_error("[%s:%u] Failed to parse boolean value in condition, ignoring: %s", filename, line, rvalue);
1751                 return 0;
1752         }
1753
1754         if (!b)
1755                 negate = !negate;
1756
1757         c = condition_new(CONDITION_NULL, NULL, trigger, negate);
1758         if (!c)
1759                 return log_oom();
1760
1761         LIST_PREPEND(Condition, conditions, u->conditions, c);
1762         return 0;
1763 }
1764
1765 DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier");
1766 DEFINE_CONFIG_PARSE_ENUM(config_parse_start_limit_action, start_limit_action, StartLimitAction, "Failed to parse start limit action specifier");
1767
1768 int config_parse_unit_cgroup_attr(
1769                 const char *filename,
1770                 unsigned line,
1771                 const char *section,
1772                 const char *lvalue,
1773                 int ltype,
1774                 const char *rvalue,
1775                 void *data,
1776                 void *userdata) {
1777
1778         Unit *u = data;
1779         size_t a, b;
1780         _cleanup_free_ char *n = NULL, *v = NULL;
1781         const CGroupSemantics *s;
1782         int r;
1783
1784         assert(filename);
1785         assert(lvalue);
1786         assert(rvalue);
1787         assert(data);
1788
1789         if (isempty(rvalue)) {
1790                 /* Empty assignment clears the list */
1791                 cgroup_attribute_free_list(u->cgroup_attributes);
1792                 u->cgroup_attributes = NULL;
1793                 return 0;
1794         }
1795
1796         a = strcspn(rvalue, WHITESPACE);
1797         b = strspn(rvalue + a, WHITESPACE);
1798         if (a <= 0 || b <= 0) {
1799                 log_error("[%s:%u] Failed to parse cgroup attribute value, ignoring: %s", filename, line, rvalue);
1800                 return 0;
1801         }
1802
1803         n = strndup(rvalue, a);
1804         if (!n)
1805                 return log_oom();
1806
1807         r = cgroup_semantics_find(NULL, n, rvalue + a + b, &v, &s);
1808         if (r < 0) {
1809                 log_error("[%s:%u] Failed to parse cgroup attribute value, ignoring: %s", filename, line, rvalue);
1810                 return 0;
1811         }
1812
1813         r = unit_add_cgroup_attribute(u, s, NULL, n, v ? v : rvalue + a + b, NULL);
1814         if (r < 0) {
1815                 log_error("[%s:%u] Failed to add cgroup attribute value, ignoring: %s", filename, line, rvalue);
1816                 return 0;
1817         }
1818
1819         return 0;
1820 }
1821
1822 int config_parse_unit_cgroup_attr_pretty(
1823                 const char *filename,
1824                 unsigned line,
1825                 const char *section,
1826                 const char *lvalue,
1827                 int ltype,
1828                 const char *rvalue,
1829                 void *data,
1830                 void *userdata) {
1831
1832         Unit *u = data;
1833         _cleanup_free_ char *v = NULL;
1834         const CGroupSemantics *s;
1835         int r;
1836
1837         assert(filename);
1838         assert(lvalue);
1839         assert(rvalue);
1840         assert(data);
1841
1842         r = cgroup_semantics_find(NULL, lvalue, rvalue, &v, &s);
1843         if (r < 0) {
1844                 log_error("[%s:%u] Failed to parse cgroup attribute value, ignoring: %s", filename, line, rvalue);
1845                 return 0;
1846         } else if (r == 0) {
1847                 log_error("[%s:%u] Unknown or unsupported cgroup attribute %s, ignoring: %s", filename, line, lvalue, rvalue);
1848                 return 0;
1849         }
1850
1851         r = unit_add_cgroup_attribute(u, s, NULL, NULL, v, NULL);
1852         if (r < 0) {
1853                 log_error("[%s:%u] Failed to add cgroup attribute value, ignoring: %s", filename, line, rvalue);
1854                 return 0;
1855         }
1856
1857         return 0;
1858 }
1859
1860 int config_parse_unit_requires_mounts_for(
1861                 const char *filename,
1862                 unsigned line,
1863                 const char *section,
1864                 const char *lvalue,
1865                 int ltype,
1866                 const char *rvalue,
1867                 void *data,
1868                 void *userdata) {
1869
1870         Unit *u = userdata;
1871         int r;
1872         bool empty_before;
1873
1874         assert(filename);
1875         assert(lvalue);
1876         assert(rvalue);
1877         assert(data);
1878
1879         empty_before = !u->requires_mounts_for;
1880
1881         r = config_parse_path_strv(filename, line, section, lvalue, ltype, rvalue, data, userdata);
1882
1883         /* Make it easy to find units with requires_mounts set */
1884         if (empty_before && u->requires_mounts_for)
1885                 LIST_PREPEND(Unit, has_requires_mounts_for, u->manager->has_requires_mounts_for, u);
1886
1887         return r;
1888 }
1889
1890 int config_parse_documentation(
1891                 const char *filename,
1892                 unsigned line,
1893                 const char *section,
1894                 const char *lvalue,
1895                 int ltype,
1896                 const char *rvalue,
1897                 void *data,
1898                 void *userdata) {
1899
1900         Unit *u = userdata;
1901         int r;
1902         char **a, **b;
1903
1904         assert(filename);
1905         assert(lvalue);
1906         assert(rvalue);
1907         assert(u);
1908
1909         if (isempty(rvalue)) {
1910                 /* Empty assignment resets the list */
1911                 strv_free(u->documentation);
1912                 u->documentation = NULL;
1913                 return 0;
1914         }
1915
1916         r = config_parse_unit_strv_printf(filename, line, section, lvalue, ltype, rvalue, data, userdata);
1917         if (r < 0)
1918                 return r;
1919
1920         for (a = b = u->documentation; a && *a; a++) {
1921
1922                 if (is_valid_documentation_url(*a))
1923                         *(b++) = *a;
1924                 else {
1925                         log_error("[%s:%u] Invalid URL, ignoring: %s", filename, line, *a);
1926                         free(*a);
1927                 }
1928         }
1929         *b = NULL;
1930
1931         return r;
1932 }
1933
1934 static void syscall_set(uint32_t *p, int nr) {
1935         nr = SYSCALL_TO_INDEX(nr);
1936         p[nr >> 4] |= 1 << (nr & 31);
1937 }
1938
1939 static void syscall_unset(uint32_t *p, int nr) {
1940         nr = SYSCALL_TO_INDEX(nr);
1941         p[nr >> 4] &= ~(1 << (nr & 31));
1942 }
1943
1944 int config_parse_syscall_filter(
1945                 const char *filename,
1946                 unsigned line,
1947                 const char *section,
1948                 const char *lvalue,
1949                 int ltype,
1950                 const char *rvalue,
1951                 void *data,
1952                 void *userdata) {
1953
1954         ExecContext *c = data;
1955         Unit *u = userdata;
1956         bool invert = false;
1957         char *w;
1958         size_t l;
1959         char *state;
1960
1961         assert(filename);
1962         assert(lvalue);
1963         assert(rvalue);
1964         assert(u);
1965
1966         if (isempty(rvalue)) {
1967                 /* Empty assignment resets the list */
1968                 free(c->syscall_filter);
1969                 c->syscall_filter = NULL;
1970                 return 0;
1971         }
1972
1973         if (rvalue[0] == '~') {
1974                 invert = true;
1975                 rvalue++;
1976         }
1977
1978         if (!c->syscall_filter) {
1979                 size_t n;
1980
1981                 n = (syscall_max() + 31) >> 4;
1982                 c->syscall_filter = new(uint32_t, n);
1983                 if (!c->syscall_filter)
1984                         return log_oom();
1985
1986                 memset(c->syscall_filter, invert ? 0xFF : 0, n * sizeof(uint32_t));
1987
1988                 /* Add these by default */
1989                 syscall_set(c->syscall_filter, __NR_execve);
1990                 syscall_set(c->syscall_filter, __NR_rt_sigreturn);
1991 #ifdef __NR_sigreturn
1992                 syscall_set(c->syscall_filter, __NR_sigreturn);
1993 #endif
1994                 syscall_set(c->syscall_filter, __NR_exit_group);
1995                 syscall_set(c->syscall_filter, __NR_exit);
1996         }
1997
1998         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
1999                 int id;
2000                 char _cleanup_free_ *t = NULL;
2001
2002                 t = strndup(w, l);
2003                 if (!t)
2004                         return log_oom();
2005
2006                 id = syscall_from_name(t);
2007                 if (id < 0)  {
2008                         log_error("[%s:%u] Failed to parse syscall, ignoring: %s",
2009                                   filename, line, t);
2010                         continue;
2011                 }
2012
2013                 if (invert)
2014                         syscall_unset(c->syscall_filter, id);
2015                 else
2016                         syscall_set(c->syscall_filter, id);
2017         }
2018
2019         c->no_new_privileges = true;
2020
2021         return 0;
2022 }
2023
2024 #define FOLLOW_MAX 8
2025
2026 static int open_follow(char **filename, FILE **_f, Set *names, char **_final) {
2027         unsigned c = 0;
2028         int fd, r;
2029         FILE *f;
2030         char *id = NULL;
2031
2032         assert(filename);
2033         assert(*filename);
2034         assert(_f);
2035         assert(names);
2036
2037         /* This will update the filename pointer if the loaded file is
2038          * reached by a symlink. The old string will be freed. */
2039
2040         for (;;) {
2041                 char *target, *name;
2042
2043                 if (c++ >= FOLLOW_MAX)
2044                         return -ELOOP;
2045
2046                 path_kill_slashes(*filename);
2047
2048                 /* Add the file name we are currently looking at to
2049                  * the names of this unit, but only if it is a valid
2050                  * unit name. */
2051                 name = path_get_file_name(*filename);
2052
2053                 if (unit_name_is_valid(name, true)) {
2054
2055                         id = set_get(names, name);
2056                         if (!id) {
2057                                 id = strdup(name);
2058                                 if (!id)
2059                                         return -ENOMEM;
2060
2061                                 r = set_put(names, id);
2062                                 if (r < 0) {
2063                                         free(id);
2064                                         return r;
2065                                 }
2066                         }
2067                 }
2068
2069                 /* Try to open the file name, but don't if its a symlink */
2070                 fd = open(*filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
2071                 if (fd >= 0)
2072                         break;
2073
2074                 if (errno != ELOOP)
2075                         return -errno;
2076
2077                 /* Hmm, so this is a symlink. Let's read the name, and follow it manually */
2078                 r = readlink_and_make_absolute(*filename, &target);
2079                 if (r < 0)
2080                         return r;
2081
2082                 free(*filename);
2083                 *filename = target;
2084         }
2085
2086         f = fdopen(fd, "re");
2087         if (!f) {
2088                 r = -errno;
2089                 close_nointr_nofail(fd);
2090                 return r;
2091         }
2092
2093         *_f = f;
2094         *_final = id;
2095         return 0;
2096 }
2097
2098 static int merge_by_names(Unit **u, Set *names, const char *id) {
2099         char *k;
2100         int r;
2101
2102         assert(u);
2103         assert(*u);
2104         assert(names);
2105
2106         /* Let's try to add in all symlink names we found */
2107         while ((k = set_steal_first(names))) {
2108
2109                 /* First try to merge in the other name into our
2110                  * unit */
2111                 r = unit_merge_by_name(*u, k);
2112                 if (r < 0) {
2113                         Unit *other;
2114
2115                         /* Hmm, we couldn't merge the other unit into
2116                          * ours? Then let's try it the other way
2117                          * round */
2118
2119                         other = manager_get_unit((*u)->manager, k);
2120                         free(k);
2121
2122                         if (other) {
2123                                 r = unit_merge(other, *u);
2124                                 if (r >= 0) {
2125                                         *u = other;
2126                                         return merge_by_names(u, names, NULL);
2127                                 }
2128                         }
2129
2130                         return r;
2131                 }
2132
2133                 if (id == k)
2134                         unit_choose_id(*u, id);
2135
2136                 free(k);
2137         }
2138
2139         return 0;
2140 }
2141
2142 static int load_from_path(Unit *u, const char *path) {
2143         int r;
2144         Set *symlink_names;
2145         FILE *f = NULL;
2146         char *filename = NULL, *id = NULL;
2147         Unit *merged;
2148         struct stat st;
2149
2150         assert(u);
2151         assert(path);
2152
2153         symlink_names = set_new(string_hash_func, string_compare_func);
2154         if (!symlink_names)
2155                 return -ENOMEM;
2156
2157         if (path_is_absolute(path)) {
2158
2159                 filename = strdup(path);
2160                 if (!filename) {
2161                         r = -ENOMEM;
2162                         goto finish;
2163                 }
2164
2165                 r = open_follow(&filename, &f, symlink_names, &id);
2166                 if (r < 0) {
2167                         free(filename);
2168                         filename = NULL;
2169
2170                         if (r != -ENOENT)
2171                                 goto finish;
2172                 }
2173
2174         } else  {
2175                 char **p;
2176
2177                 STRV_FOREACH(p, u->manager->lookup_paths.unit_path) {
2178
2179                         /* Instead of opening the path right away, we manually
2180                          * follow all symlinks and add their name to our unit
2181                          * name set while doing so */
2182                         filename = path_make_absolute(path, *p);
2183                         if (!filename) {
2184                                 r = -ENOMEM;
2185                                 goto finish;
2186                         }
2187
2188                         if (u->manager->unit_path_cache &&
2189                             !set_get(u->manager->unit_path_cache, filename))
2190                                 r = -ENOENT;
2191                         else
2192                                 r = open_follow(&filename, &f, symlink_names, &id);
2193
2194                         if (r < 0) {
2195                                 free(filename);
2196                                 filename = NULL;
2197
2198                                 if (r != -ENOENT)
2199                                         goto finish;
2200
2201                                 /* Empty the symlink names for the next run */
2202                                 set_clear_free(symlink_names);
2203                                 continue;
2204                         }
2205
2206                         break;
2207                 }
2208         }
2209
2210         if (!filename) {
2211                 /* Hmm, no suitable file found? */
2212                 r = 0;
2213                 goto finish;
2214         }
2215
2216         merged = u;
2217         r = merge_by_names(&merged, symlink_names, id);
2218         if (r < 0)
2219                 goto finish;
2220
2221         if (merged != u) {
2222                 u->load_state = UNIT_MERGED;
2223                 r = 0;
2224                 goto finish;
2225         }
2226
2227         if (fstat(fileno(f), &st) < 0) {
2228                 r = -errno;
2229                 goto finish;
2230         }
2231
2232         if (null_or_empty(&st))
2233                 u->load_state = UNIT_MASKED;
2234         else {
2235                 /* Now, parse the file contents */
2236                 r = config_parse(filename, f, UNIT_VTABLE(u)->sections, config_item_perf_lookup, (void*) load_fragment_gperf_lookup, false, u);
2237                 if (r < 0)
2238                         goto finish;
2239
2240                 u->load_state = UNIT_LOADED;
2241         }
2242
2243         free(u->fragment_path);
2244         u->fragment_path = filename;
2245         filename = NULL;
2246
2247         u->fragment_mtime = timespec_load(&st.st_mtim);
2248
2249         if (u->source_path) {
2250                 if (stat(u->source_path, &st) >= 0)
2251                         u->source_mtime = timespec_load(&st.st_mtim);
2252                 else
2253                         u->source_mtime = 0;
2254         }
2255
2256         r = 0;
2257
2258 finish:
2259         set_free_free(symlink_names);
2260         free(filename);
2261
2262         if (f)
2263                 fclose(f);
2264
2265         return r;
2266 }
2267
2268 int unit_load_fragment(Unit *u) {
2269         int r;
2270         Iterator i;
2271         const char *t;
2272
2273         assert(u);
2274         assert(u->load_state == UNIT_STUB);
2275         assert(u->id);
2276
2277         /* First, try to find the unit under its id. We always look
2278          * for unit files in the default directories, to make it easy
2279          * to override things by placing things in /etc/systemd/system */
2280         r = load_from_path(u, u->id);
2281         if (r < 0)
2282                 return r;
2283
2284         /* Try to find an alias we can load this with */
2285         if (u->load_state == UNIT_STUB)
2286                 SET_FOREACH(t, u->names, i) {
2287
2288                         if (t == u->id)
2289                                 continue;
2290
2291                         r = load_from_path(u, t);
2292                         if (r < 0)
2293                                 return r;
2294
2295                         if (u->load_state != UNIT_STUB)
2296                                 break;
2297                 }
2298
2299         /* And now, try looking for it under the suggested (originally linked) path */
2300         if (u->load_state == UNIT_STUB && u->fragment_path) {
2301
2302                 r = load_from_path(u, u->fragment_path);
2303                 if (r < 0)
2304                         return r;
2305
2306                 if (u->load_state == UNIT_STUB) {
2307                         /* Hmm, this didn't work? Then let's get rid
2308                          * of the fragment path stored for us, so that
2309                          * we don't point to an invalid location. */
2310                         free(u->fragment_path);
2311                         u->fragment_path = NULL;
2312                 }
2313         }
2314
2315         /* Look for a template */
2316         if (u->load_state == UNIT_STUB && u->instance) {
2317                 char *k;
2318
2319                 k = unit_name_template(u->id);
2320                 if (!k)
2321                         return -ENOMEM;
2322
2323                 r = load_from_path(u, k);
2324                 free(k);
2325
2326                 if (r < 0)
2327                         return r;
2328
2329                 if (u->load_state == UNIT_STUB)
2330                         SET_FOREACH(t, u->names, i) {
2331
2332                                 if (t == u->id)
2333                                         continue;
2334
2335                                 k = unit_name_template(t);
2336                                 if (!k)
2337                                         return -ENOMEM;
2338
2339                                 r = load_from_path(u, k);
2340                                 free(k);
2341
2342                                 if (r < 0)
2343                                         return r;
2344
2345                                 if (u->load_state != UNIT_STUB)
2346                                         break;
2347                         }
2348         }
2349
2350         return 0;
2351 }
2352
2353 void unit_dump_config_items(FILE *f) {
2354         static const struct {
2355                 const ConfigParserCallback callback;
2356                 const char *rvalue;
2357         } table[] = {
2358                 { config_parse_int,                   "INTEGER" },
2359                 { config_parse_unsigned,              "UNSIGNED" },
2360                 { config_parse_bytes_size,            "SIZE" },
2361                 { config_parse_bool,                  "BOOLEAN" },
2362                 { config_parse_string,                "STRING" },
2363                 { config_parse_path,                  "PATH" },
2364                 { config_parse_unit_path_printf,      "PATH" },
2365                 { config_parse_strv,                  "STRING [...]" },
2366                 { config_parse_exec_nice,             "NICE" },
2367                 { config_parse_exec_oom_score_adjust, "OOMSCOREADJUST" },
2368                 { config_parse_exec_io_class,         "IOCLASS" },
2369                 { config_parse_exec_io_priority,      "IOPRIORITY" },
2370                 { config_parse_exec_cpu_sched_policy, "CPUSCHEDPOLICY" },
2371                 { config_parse_exec_cpu_sched_prio,   "CPUSCHEDPRIO" },
2372                 { config_parse_exec_cpu_affinity,     "CPUAFFINITY" },
2373                 { config_parse_mode,                  "MODE" },
2374                 { config_parse_unit_env_file,         "FILE" },
2375                 { config_parse_output,                "OUTPUT" },
2376                 { config_parse_input,                 "INPUT" },
2377                 { config_parse_facility,              "FACILITY" },
2378                 { config_parse_level,                 "LEVEL" },
2379                 { config_parse_exec_capabilities,     "CAPABILITIES" },
2380                 { config_parse_exec_secure_bits,      "SECUREBITS" },
2381                 { config_parse_bounding_set,          "BOUNDINGSET" },
2382                 { config_parse_limit,                 "LIMIT" },
2383                 { config_parse_unit_cgroup,           "CGROUP [...]" },
2384                 { config_parse_unit_deps,             "UNIT [...]" },
2385                 { config_parse_exec,                  "PATH [ARGUMENT [...]]" },
2386                 { config_parse_service_type,          "SERVICETYPE" },
2387                 { config_parse_service_restart,       "SERVICERESTART" },
2388 #ifdef HAVE_SYSV_COMPAT
2389                 { config_parse_sysv_priority,         "SYSVPRIORITY" },
2390 #else
2391                 { config_parse_warn_compat,           "NOTSUPPORTED" },
2392 #endif
2393                 { config_parse_kill_mode,             "KILLMODE" },
2394                 { config_parse_kill_signal,           "SIGNAL" },
2395                 { config_parse_socket_listen,         "SOCKET [...]" },
2396                 { config_parse_socket_bind,           "SOCKETBIND" },
2397                 { config_parse_socket_bindtodevice,   "NETWORKINTERFACE" },
2398                 { config_parse_sec,                   "SECONDS" },
2399                 { config_parse_nsec,                  "NANOSECONDS" },
2400                 { config_parse_path_strv,             "PATH [...]" },
2401                 { config_parse_unit_requires_mounts_for, "PATH [...]" },
2402                 { config_parse_exec_mount_flags,      "MOUNTFLAG [...]" },
2403                 { config_parse_unit_string_printf,    "STRING" },
2404                 { config_parse_timer,                 "TIMER" },
2405                 { config_parse_timer_unit,            "NAME" },
2406                 { config_parse_path_spec,             "PATH" },
2407                 { config_parse_path_unit,             "UNIT" },
2408                 { config_parse_notify_access,         "ACCESS" },
2409                 { config_parse_ip_tos,                "TOS" },
2410                 { config_parse_unit_condition_path,   "CONDITION" },
2411                 { config_parse_unit_condition_string, "CONDITION" },
2412                 { config_parse_unit_condition_null,   "CONDITION" },
2413         };
2414
2415         const char *prev = NULL;
2416         const char *i;
2417
2418         assert(f);
2419
2420         NULSTR_FOREACH(i, load_fragment_gperf_nulstr) {
2421                 const char *rvalue = "OTHER", *lvalue;
2422                 unsigned j;
2423                 size_t prefix_len;
2424                 const char *dot;
2425                 const ConfigPerfItem *p;
2426
2427                 assert_se(p = load_fragment_gperf_lookup(i, strlen(i)));
2428
2429                 dot = strchr(i, '.');
2430                 lvalue = dot ? dot + 1 : i;
2431                 prefix_len = dot-i;
2432
2433                 if (dot)
2434                         if (!prev || !strneq(prev, i, prefix_len+1)) {
2435                                 if (prev)
2436                                         fputc('\n', f);
2437
2438                                 fprintf(f, "[%.*s]\n", (int) prefix_len, i);
2439                         }
2440
2441                 for (j = 0; j < ELEMENTSOF(table); j++)
2442                         if (p->parse == table[j].callback) {
2443                                 rvalue = table[j].rvalue;
2444                                 break;
2445                         }
2446
2447                 fprintf(f, "%s=%s\n", lvalue, rvalue);
2448                 prev = i;
2449         }
2450 }