chiark / gitweb /
Move x-systemd-device.timeout handling from core to fstab-generator
[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 #include <sys/types.h>
37 #include <grp.h>
38
39 #ifdef HAVE_SECCOMP
40 #include <seccomp.h>
41 #endif
42
43 #include "sd-messages.h"
44 #include "unit.h"
45 #include "strv.h"
46 #include "conf-parser.h"
47 #include "load-fragment.h"
48 #include "log.h"
49 #include "ioprio.h"
50 #include "securebits.h"
51 #include "missing.h"
52 #include "unit-name.h"
53 #include "unit-printf.h"
54 #include "utf8.h"
55 #include "path-util.h"
56 #include "env-util.h"
57 #include "cgroup.h"
58 #include "bus-util.h"
59 #include "bus-error.h"
60 #include "errno-list.h"
61 #include "af-list.h"
62
63 #ifdef HAVE_SECCOMP
64 #include "seccomp-util.h"
65 #endif
66
67 #if !defined(HAVE_SYSV_COMPAT) || !defined(HAVE_SECCOMP) || !defined(HAVE_PAM) || !defined(HAVE_SELINUX) || !defined(HAVE_SMACK) || !defined(HAVE_APPARMOR)
68 int config_parse_warn_compat(
69                 const char *unit,
70                 const char *filename,
71                 unsigned line,
72                 const char *section,
73                 unsigned section_line,
74                 const char *lvalue,
75                 int ltype,
76                 const char *rvalue,
77                 void *data,
78                 void *userdata) {
79
80         log_syntax(unit, LOG_DEBUG, filename, line, EINVAL,
81                    "Support for option %s= has been disabled at compile time and is ignored",
82                    lvalue);
83         return 0;
84 }
85 #endif
86
87 int config_parse_unit_deps(const char* unit,
88                            const char *filename,
89                            unsigned line,
90                            const char *section,
91                            unsigned section_line,
92                            const char *lvalue,
93                            int ltype,
94                            const char *rvalue,
95                            void *data,
96                            void *userdata) {
97
98         UnitDependency d = ltype;
99         Unit *u = userdata;
100         char *w, *state;
101         size_t l;
102
103         assert(filename);
104         assert(lvalue);
105         assert(rvalue);
106
107         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
108                 _cleanup_free_ char *t = NULL, *k = NULL;
109                 int r;
110
111                 t = strndup(w, l);
112                 if (!t)
113                         return log_oom();
114
115                 r = unit_name_printf(u, t, &k);
116                 if (r < 0) {
117                         log_syntax(unit, LOG_ERR, filename, line, -r,
118                                    "Failed to resolve specifiers, ignoring: %s", strerror(-r));
119                         continue;
120                 }
121
122                 r = unit_add_dependency_by_name(u, d, k, NULL, true);
123                 if (r < 0)
124                         log_syntax(unit, LOG_ERR, filename, line, -r,
125                                    "Failed to add dependency on %s, ignoring: %s", k, strerror(-r));
126         }
127
128         return 0;
129 }
130
131 int config_parse_unit_string_printf(const char *unit,
132                                     const char *filename,
133                                     unsigned line,
134                                     const char *section,
135                                     unsigned section_line,
136                                     const char *lvalue,
137                                     int ltype,
138                                     const char *rvalue,
139                                     void *data,
140                                     void *userdata) {
141
142         Unit *u = userdata;
143         _cleanup_free_ char *k = NULL;
144         int r;
145
146         assert(filename);
147         assert(lvalue);
148         assert(rvalue);
149         assert(u);
150
151         r = unit_full_printf(u, rvalue, &k);
152         if (r < 0)
153                 log_syntax(unit, LOG_ERR, filename, line, -r,
154                            "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
155
156         return config_parse_string(unit, filename, line, section, section_line, lvalue, ltype,
157                                    k ? k : rvalue, data, userdata);
158 }
159
160 int config_parse_unit_strv_printf(const char *unit,
161                                   const char *filename,
162                                   unsigned line,
163                                   const char *section,
164                                   unsigned section_line,
165                                   const char *lvalue,
166                                   int ltype,
167                                   const char *rvalue,
168                                   void *data,
169                                   void *userdata) {
170
171         Unit *u = userdata;
172         _cleanup_free_ char *k = NULL;
173         int r;
174
175         assert(filename);
176         assert(lvalue);
177         assert(rvalue);
178         assert(u);
179
180         r = unit_full_printf(u, rvalue, &k);
181         if (r < 0)
182                 log_syntax(unit, LOG_ERR, filename, line, -r,
183                            "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
184
185         return config_parse_strv(unit, filename, line, section, section_line, lvalue, ltype,
186                                  k ? k : rvalue, data, userdata);
187 }
188
189 int config_parse_unit_path_printf(const char *unit,
190                                   const char *filename,
191                                   unsigned line,
192                                   const char *section,
193                                   unsigned section_line,
194                                   const char *lvalue,
195                                   int ltype,
196                                   const char *rvalue,
197                                   void *data,
198                                   void *userdata) {
199
200         _cleanup_free_ char *k = NULL;
201         Unit *u = userdata;
202         int r;
203
204         assert(filename);
205         assert(lvalue);
206         assert(rvalue);
207         assert(u);
208
209         r = unit_full_printf(u, rvalue, &k);
210         if (r < 0) {
211                 log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
212                 return 0;
213         }
214
215         return config_parse_path(unit, filename, line, section, section_line, lvalue, ltype, k, data, userdata);
216 }
217
218 int config_parse_unit_path_strv_printf(
219                 const char *unit,
220                 const char *filename,
221                 unsigned line,
222                 const char *section,
223                 unsigned section_line,
224                 const char *lvalue,
225                 int ltype,
226                 const char *rvalue,
227                 void *data,
228                 void *userdata) {
229
230         char *w, *state, ***x = data;
231         Unit *u = userdata;
232         size_t l;
233         int r;
234
235         assert(filename);
236         assert(lvalue);
237         assert(rvalue);
238         assert(u);
239
240         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
241                 _cleanup_free_ char *k = NULL;
242                 char t[l+1];
243
244                 memcpy(t, w, l);
245                 t[l] = 0;
246
247                 r = unit_full_printf(u, t, &k);
248                 if (r < 0) {
249                         log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve unit specifiers on %s, ignoring: %s", t, strerror(-r));
250                         return 0;
251                 }
252
253                 if (!utf8_is_valid(k)) {
254                         log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue);
255                         return 0;
256                 }
257
258                 if (!path_is_absolute(k)) {
259                         log_syntax(unit, LOG_ERR, filename, line, -r, "Symlink path %s is not absolute, ignoring: %s", k, strerror(-r));
260                         return 0;
261                 }
262
263                 path_kill_slashes(k);
264
265                 r = strv_push(x, k);
266                 if (r < 0)
267                         return log_oom();
268
269                 k = NULL;
270         }
271
272         return 0;
273 }
274
275 int config_parse_socket_listen(const char *unit,
276                                const char *filename,
277                                unsigned line,
278                                const char *section,
279                                unsigned section_line,
280                                const char *lvalue,
281                                int ltype,
282                                const char *rvalue,
283                                void *data,
284                                void *userdata) {
285
286         SocketPort *p, *tail;
287         Socket *s;
288         int r;
289
290         assert(filename);
291         assert(lvalue);
292         assert(rvalue);
293         assert(data);
294
295         s = SOCKET(data);
296
297         if (isempty(rvalue)) {
298                 /* An empty assignment removes all ports */
299                 socket_free_ports(s);
300                 return 0;
301         }
302
303         p = new0(SocketPort, 1);
304         if (!p)
305                 return log_oom();
306
307         if (ltype != SOCKET_SOCKET) {
308
309                 p->type = ltype;
310                 r = unit_full_printf(UNIT(s), rvalue, &p->path);
311                 if (r < 0) {
312                         p->path = strdup(rvalue);
313                         if (!p->path) {
314                                 free(p);
315                                 return log_oom();
316                         } else
317                                 log_syntax(unit, LOG_ERR, filename, line, -r,
318                                            "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
319                 }
320
321                 path_kill_slashes(p->path);
322
323         } else if (streq(lvalue, "ListenNetlink")) {
324                 _cleanup_free_ char  *k = NULL;
325
326                 p->type = SOCKET_SOCKET;
327                 r = unit_full_printf(UNIT(s), rvalue, &k);
328                 if (r < 0)
329                         log_syntax(unit, LOG_ERR, filename, line, -r,
330                                    "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
331
332                 r = socket_address_parse_netlink(&p->address, k ? k : rvalue);
333                 if (r < 0) {
334                         log_syntax(unit, LOG_ERR, filename, line, -r,
335                                    "Failed to parse address value, ignoring: %s", rvalue);
336                         free(p);
337                         return 0;
338                 }
339
340         } else {
341                 _cleanup_free_ char *k = NULL;
342
343                 p->type = SOCKET_SOCKET;
344                 r = unit_full_printf(UNIT(s), rvalue, &k);
345                 if (r < 0)
346                         log_syntax(unit, LOG_ERR, filename, line, -r,
347                                    "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
348
349                 r = socket_address_parse(&p->address, k ? k : rvalue);
350                 if (r < 0) {
351                         log_syntax(unit, LOG_ERR, filename, line, -r,
352                                    "Failed to parse address value, ignoring: %s", rvalue);
353                         free(p);
354                         return 0;
355                 }
356
357                 if (streq(lvalue, "ListenStream"))
358                         p->address.type = SOCK_STREAM;
359                 else if (streq(lvalue, "ListenDatagram"))
360                         p->address.type = SOCK_DGRAM;
361                 else {
362                         assert(streq(lvalue, "ListenSequentialPacket"));
363                         p->address.type = SOCK_SEQPACKET;
364                 }
365
366                 if (socket_address_family(&p->address) != AF_LOCAL && p->address.type == SOCK_SEQPACKET) {
367                         log_syntax(unit, LOG_ERR, filename, line, ENOTSUP,
368                                    "Address family not supported, ignoring: %s", rvalue);
369                         free(p);
370                         return 0;
371                 }
372         }
373
374         p->fd = -1;
375         p->socket = s;
376
377         if (s->ports) {
378                 LIST_FIND_TAIL(port, s->ports, tail);
379                 LIST_INSERT_AFTER(port, s->ports, tail, p);
380         } else
381                 LIST_PREPEND(port, s->ports, p);
382
383         return 0;
384 }
385
386 int config_parse_socket_bind(const char *unit,
387                              const char *filename,
388                              unsigned line,
389                              const char *section,
390                              unsigned section_line,
391                              const char *lvalue,
392                              int ltype,
393                              const char *rvalue,
394                              void *data,
395                              void *userdata) {
396
397         Socket *s;
398         SocketAddressBindIPv6Only b;
399
400         assert(filename);
401         assert(lvalue);
402         assert(rvalue);
403         assert(data);
404
405         s = SOCKET(data);
406
407         b = socket_address_bind_ipv6_only_from_string(rvalue);
408         if (b < 0) {
409                 int r;
410
411                 r = parse_boolean(rvalue);
412                 if (r < 0) {
413                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
414                                    "Failed to parse bind IPv6 only value, ignoring: %s", rvalue);
415                         return 0;
416                 }
417
418                 s->bind_ipv6_only = r ? SOCKET_ADDRESS_IPV6_ONLY : SOCKET_ADDRESS_BOTH;
419         } else
420                 s->bind_ipv6_only = b;
421
422         return 0;
423 }
424
425 int config_parse_exec_nice(const char *unit,
426                            const char *filename,
427                            unsigned line,
428                            const char *section,
429                            unsigned section_line,
430                            const char *lvalue,
431                            int ltype,
432                            const char *rvalue,
433                            void *data,
434                            void *userdata) {
435
436         ExecContext *c = data;
437         int priority, r;
438
439         assert(filename);
440         assert(lvalue);
441         assert(rvalue);
442         assert(data);
443
444         r = safe_atoi(rvalue, &priority);
445         if (r < 0) {
446                 log_syntax(unit, LOG_ERR, filename, line, -r,
447                            "Failed to parse nice priority, ignoring: %s. ", rvalue);
448                 return 0;
449         }
450
451         if (priority < PRIO_MIN || priority >= PRIO_MAX) {
452                 log_syntax(unit, LOG_ERR, filename, line, ERANGE,
453                            "Nice priority out of range, ignoring: %s", rvalue);
454                 return 0;
455         }
456
457         c->nice = priority;
458         c->nice_set = true;
459
460         return 0;
461 }
462
463 int config_parse_exec_oom_score_adjust(const char* unit,
464                                        const char *filename,
465                                        unsigned line,
466                                        const char *section,
467                                        unsigned section_line,
468                                        const char *lvalue,
469                                        int ltype,
470                                        const char *rvalue,
471                                        void *data,
472                                        void *userdata) {
473
474         ExecContext *c = data;
475         int oa, r;
476
477         assert(filename);
478         assert(lvalue);
479         assert(rvalue);
480         assert(data);
481
482         r = safe_atoi(rvalue, &oa);
483         if (r < 0) {
484                 log_syntax(unit, LOG_ERR, filename, line, -r,
485                            "Failed to parse the OOM score adjust value, ignoring: %s", rvalue);
486                 return 0;
487         }
488
489         if (oa < OOM_SCORE_ADJ_MIN || oa > OOM_SCORE_ADJ_MAX) {
490                 log_syntax(unit, LOG_ERR, filename, line, ERANGE,
491                            "OOM score adjust value out of range, ignoring: %s", rvalue);
492                 return 0;
493         }
494
495         c->oom_score_adjust = oa;
496         c->oom_score_adjust_set = true;
497
498         return 0;
499 }
500
501 int config_parse_exec(const char *unit,
502                       const char *filename,
503                       unsigned line,
504                       const char *section,
505                       unsigned section_line,
506                       const char *lvalue,
507                       int ltype,
508                       const char *rvalue,
509                       void *data,
510                       void *userdata) {
511
512         ExecCommand **e = data, *nce;
513         char *path, **n;
514         unsigned k;
515         int r;
516
517         assert(filename);
518         assert(lvalue);
519         assert(rvalue);
520         assert(e);
521
522         e += ltype;
523
524         if (isempty(rvalue)) {
525                 /* An empty assignment resets the list */
526                 exec_command_free_list(*e);
527                 *e = NULL;
528                 return 0;
529         }
530
531         /* We accept an absolute path as first argument, or
532          * alternatively an absolute prefixed with @ to allow
533          * overriding of argv[0]. */
534         for (;;) {
535                 int i;
536                 char *w;
537                 size_t l;
538                 char *state;
539                 bool honour_argv0 = false, ignore = false;
540
541                 path = NULL;
542                 nce = NULL;
543                 n = NULL;
544
545                 rvalue += strspn(rvalue, WHITESPACE);
546
547                 if (rvalue[0] == 0)
548                         break;
549
550                 for (i = 0; i < 2; i++) {
551                         if (rvalue[0] == '-' && !ignore) {
552                                 ignore = true;
553                                 rvalue ++;
554                         }
555
556                         if (rvalue[0] == '@' && !honour_argv0) {
557                                 honour_argv0 = true;
558                                 rvalue ++;
559                         }
560                 }
561
562                 if (*rvalue != '/') {
563                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
564                                    "Executable path is not absolute, ignoring: %s", rvalue);
565                         return 0;
566                 }
567
568                 k = 0;
569                 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
570                         if (strneq(w, ";", MAX(l, 1U)))
571                                 break;
572
573                         k++;
574                 }
575
576                 n = new(char*, k + !honour_argv0);
577                 if (!n)
578                         return log_oom();
579
580                 k = 0;
581                 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
582                         if (strneq(w, ";", MAX(l, 1U)))
583                                 break;
584                         else if (strneq(w, "\\;", MAX(l, 1U)))
585                                 w ++;
586
587                         if (honour_argv0 && w == rvalue) {
588                                 assert(!path);
589
590                                 path = strndup(w, l);
591                                 if (!path) {
592                                         r = log_oom();
593                                         goto fail;
594                                 }
595
596                                 if (!utf8_is_valid(path)) {
597                                         log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue);
598                                         r = 0;
599                                         goto fail;
600                                 }
601
602                         } else {
603                                 char *c;
604
605                                 c = n[k++] = cunescape_length(w, l);
606                                 if (!c) {
607                                         r = log_oom();
608                                         goto fail;
609                                 }
610
611                                 if (!utf8_is_valid(c)) {
612                                         log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue);
613                                         r = 0;
614                                         goto fail;
615                                 }
616                         }
617                 }
618
619                 n[k] = NULL;
620
621                 if (!n[0]) {
622                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
623                                    "Invalid command line, ignoring: %s", rvalue);
624                         r = 0;
625                         goto fail;
626                 }
627
628                 if (!path) {
629                         path = strdup(n[0]);
630                         if (!path) {
631                                 r = log_oom();
632                                 goto fail;
633                         }
634                 }
635
636                 assert(path_is_absolute(path));
637
638                 nce = new0(ExecCommand, 1);
639                 if (!nce) {
640                         r = log_oom();
641                         goto fail;
642                 }
643
644                 nce->argv = n;
645                 nce->path = path;
646                 nce->ignore = ignore;
647
648                 path_kill_slashes(nce->path);
649
650                 exec_command_append_list(e, nce);
651
652                 rvalue = state;
653         }
654
655         return 0;
656
657 fail:
658         n[k] = NULL;
659         strv_free(n);
660         free(path);
661         free(nce);
662
663         return r;
664 }
665
666 DEFINE_CONFIG_PARSE_ENUM(config_parse_service_type, service_type, ServiceType, "Failed to parse service type");
667 DEFINE_CONFIG_PARSE_ENUM(config_parse_service_restart, service_restart, ServiceRestart, "Failed to parse service restart specifier");
668
669 int config_parse_socket_bindtodevice(const char* unit,
670                                      const char *filename,
671                                      unsigned line,
672                                      const char *section,
673                                      unsigned section_line,
674                                      const char *lvalue,
675                                      int ltype,
676                                      const char *rvalue,
677                                      void *data,
678                                      void *userdata) {
679
680         Socket *s = data;
681         char *n;
682
683         assert(filename);
684         assert(lvalue);
685         assert(rvalue);
686         assert(data);
687
688         if (rvalue[0] && !streq(rvalue, "*")) {
689                 n = strdup(rvalue);
690                 if (!n)
691                         return log_oom();
692         } else
693                 n = NULL;
694
695         free(s->bind_to_device);
696         s->bind_to_device = n;
697
698         return 0;
699 }
700
701 DEFINE_CONFIG_PARSE_ENUM(config_parse_output, exec_output, ExecOutput, "Failed to parse output specifier");
702 DEFINE_CONFIG_PARSE_ENUM(config_parse_input, exec_input, ExecInput, "Failed to parse input specifier");
703
704 int config_parse_exec_io_class(const char *unit,
705                                const char *filename,
706                                unsigned line,
707                                const char *section,
708                                unsigned section_line,
709                                const char *lvalue,
710                                int ltype,
711                                const char *rvalue,
712                                void *data,
713                                void *userdata) {
714
715         ExecContext *c = data;
716         int x;
717
718         assert(filename);
719         assert(lvalue);
720         assert(rvalue);
721         assert(data);
722
723         x = ioprio_class_from_string(rvalue);
724         if (x < 0) {
725                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
726                            "Failed to parse IO scheduling class, ignoring: %s", rvalue);
727                 return 0;
728         }
729
730         c->ioprio = IOPRIO_PRIO_VALUE(x, IOPRIO_PRIO_DATA(c->ioprio));
731         c->ioprio_set = true;
732
733         return 0;
734 }
735
736 int config_parse_exec_io_priority(const char *unit,
737                                   const char *filename,
738                                   unsigned line,
739                                   const char *section,
740                                   unsigned section_line,
741                                   const char *lvalue,
742                                   int ltype,
743                                   const char *rvalue,
744                                   void *data,
745                                   void *userdata) {
746
747         ExecContext *c = data;
748         int i, r;
749
750         assert(filename);
751         assert(lvalue);
752         assert(rvalue);
753         assert(data);
754
755         r = safe_atoi(rvalue, &i);
756         if (r < 0 || i < 0 || i >= IOPRIO_BE_NR) {
757                 log_syntax(unit, LOG_ERR, filename, line, -r,
758                            "Failed to parse IO priority, ignoring: %s", rvalue);
759                 return 0;
760         }
761
762         c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_PRIO_CLASS(c->ioprio), i);
763         c->ioprio_set = true;
764
765         return 0;
766 }
767
768 int config_parse_exec_cpu_sched_policy(const char *unit,
769                                        const char *filename,
770                                        unsigned line,
771                                        const char *section,
772                                        unsigned section_line,
773                                        const char *lvalue,
774                                        int ltype,
775                                        const char *rvalue,
776                                        void *data,
777                                        void *userdata) {
778
779
780         ExecContext *c = data;
781         int x;
782
783         assert(filename);
784         assert(lvalue);
785         assert(rvalue);
786         assert(data);
787
788         x = sched_policy_from_string(rvalue);
789         if (x < 0) {
790                 log_syntax(unit, LOG_ERR, filename, line, -x,
791                            "Failed to parse CPU scheduling policy, ignoring: %s", rvalue);
792                 return 0;
793         }
794
795         c->cpu_sched_policy = x;
796         /* Moving to or from real-time policy? We need to adjust the priority */
797         c->cpu_sched_priority = CLAMP(c->cpu_sched_priority, sched_get_priority_min(x), sched_get_priority_max(x));
798         c->cpu_sched_set = true;
799
800         return 0;
801 }
802
803 int config_parse_exec_cpu_sched_prio(const char *unit,
804                                      const char *filename,
805                                      unsigned line,
806                                      const char *section,
807                                      unsigned section_line,
808                                      const char *lvalue,
809                                      int ltype,
810                                      const char *rvalue,
811                                      void *data,
812                                      void *userdata) {
813
814         ExecContext *c = data;
815         int i, min, max, r;
816
817         assert(filename);
818         assert(lvalue);
819         assert(rvalue);
820         assert(data);
821
822         r = safe_atoi(rvalue, &i);
823         if (r < 0) {
824                 log_syntax(unit, LOG_ERR, filename, line, -r,
825                            "Failed to parse CPU scheduling policy, ignoring: %s", rvalue);
826                 return 0;
827         }
828
829         /* On Linux RR/FIFO range from 1 to 99 and OTHER/BATCH may only be 0 */
830         min = sched_get_priority_min(c->cpu_sched_policy);
831         max = sched_get_priority_max(c->cpu_sched_policy);
832
833         if (i < min || i > max) {
834                 log_syntax(unit, LOG_ERR, filename, line, ERANGE,
835                            "CPU scheduling priority is out of range, ignoring: %s", rvalue);
836                 return 0;
837         }
838
839         c->cpu_sched_priority = i;
840         c->cpu_sched_set = true;
841
842         return 0;
843 }
844
845 int config_parse_exec_cpu_affinity(const char *unit,
846                                    const char *filename,
847                                    unsigned line,
848                                    const char *section,
849                                    unsigned section_line,
850                                    const char *lvalue,
851                                    int ltype,
852                                    const char *rvalue,
853                                    void *data,
854                                    void *userdata) {
855
856         ExecContext *c = data;
857         char *w;
858         size_t l;
859         char *state;
860
861         assert(filename);
862         assert(lvalue);
863         assert(rvalue);
864         assert(data);
865
866         if (isempty(rvalue)) {
867                 /* An empty assignment resets the CPU list */
868                 if (c->cpuset)
869                         CPU_FREE(c->cpuset);
870                 c->cpuset = NULL;
871                 return 0;
872         }
873
874         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
875                 _cleanup_free_ char *t = NULL;
876                 int r;
877                 unsigned cpu;
878
879                 t = strndup(w, l);
880                 if (!t)
881                         return log_oom();
882
883                 r = safe_atou(t, &cpu);
884
885                 if (!c->cpuset) {
886                         c->cpuset = cpu_set_malloc(&c->cpuset_ncpus);
887                         if (!c->cpuset)
888                                 return log_oom();
889                 }
890
891                 if (r < 0 || cpu >= c->cpuset_ncpus) {
892                         log_syntax(unit, LOG_ERR, filename, line, ERANGE,
893                                    "Failed to parse CPU affinity '%s', ignoring: %s", t, rvalue);
894                         return 0;
895                 }
896
897                 CPU_SET_S(cpu, CPU_ALLOC_SIZE(c->cpuset_ncpus), c->cpuset);
898         }
899
900         return 0;
901 }
902
903 int config_parse_exec_capabilities(const char *unit,
904                                    const char *filename,
905                                    unsigned line,
906                                    const char *section,
907                                    unsigned section_line,
908                                    const char *lvalue,
909                                    int ltype,
910                                    const char *rvalue,
911                                    void *data,
912                                    void *userdata) {
913
914         ExecContext *c = data;
915         cap_t cap;
916
917         assert(filename);
918         assert(lvalue);
919         assert(rvalue);
920         assert(data);
921
922         cap = cap_from_text(rvalue);
923         if (!cap) {
924                 log_syntax(unit, LOG_ERR, filename, line, errno,
925                            "Failed to parse capabilities, ignoring: %s", rvalue);
926                 return 0;
927         }
928
929         if (c->capabilities)
930                 cap_free(c->capabilities);
931         c->capabilities = cap;
932
933         return 0;
934 }
935
936 int config_parse_exec_secure_bits(const char *unit,
937                                   const char *filename,
938                                   unsigned line,
939                                   const char *section,
940                                   unsigned section_line,
941                                   const char *lvalue,
942                                   int ltype,
943                                   const char *rvalue,
944                                   void *data,
945                                   void *userdata) {
946
947         ExecContext *c = data;
948         char *w;
949         size_t l;
950         char *state;
951
952         assert(filename);
953         assert(lvalue);
954         assert(rvalue);
955         assert(data);
956
957         if (isempty(rvalue)) {
958                 /* An empty assignment resets the field */
959                 c->secure_bits = 0;
960                 return 0;
961         }
962
963         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
964                 if (first_word(w, "keep-caps"))
965                         c->secure_bits |= 1<<SECURE_KEEP_CAPS;
966                 else if (first_word(w, "keep-caps-locked"))
967                         c->secure_bits |= 1<<SECURE_KEEP_CAPS_LOCKED;
968                 else if (first_word(w, "no-setuid-fixup"))
969                         c->secure_bits |= 1<<SECURE_NO_SETUID_FIXUP;
970                 else if (first_word(w, "no-setuid-fixup-locked"))
971                         c->secure_bits |= 1<<SECURE_NO_SETUID_FIXUP_LOCKED;
972                 else if (first_word(w, "noroot"))
973                         c->secure_bits |= 1<<SECURE_NOROOT;
974                 else if (first_word(w, "noroot-locked"))
975                         c->secure_bits |= 1<<SECURE_NOROOT_LOCKED;
976                 else {
977                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
978                                    "Failed to parse secure bits, ignoring: %s", rvalue);
979                         return 0;
980                 }
981         }
982
983         return 0;
984 }
985
986 int config_parse_bounding_set(const char *unit,
987                               const char *filename,
988                               unsigned line,
989                               const char *section,
990                               unsigned section_line,
991                               const char *lvalue,
992                               int ltype,
993                               const char *rvalue,
994                               void *data,
995                               void *userdata) {
996
997         uint64_t *capability_bounding_set_drop = data;
998         char *w;
999         size_t l;
1000         char *state;
1001         bool invert = false;
1002         uint64_t sum = 0;
1003
1004         assert(filename);
1005         assert(lvalue);
1006         assert(rvalue);
1007         assert(data);
1008
1009         if (rvalue[0] == '~') {
1010                 invert = true;
1011                 rvalue++;
1012         }
1013
1014         /* Note that we store this inverted internally, since the
1015          * kernel wants it like this. But we actually expose it
1016          * non-inverted everywhere to have a fully normalized
1017          * interface. */
1018
1019         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
1020                 _cleanup_free_ char *t = NULL;
1021                 int r;
1022                 cap_value_t cap;
1023
1024                 t = strndup(w, l);
1025                 if (!t)
1026                         return log_oom();
1027
1028                 r = cap_from_name(t, &cap);
1029                 if (r < 0) {
1030                         log_syntax(unit, LOG_ERR, filename, line, errno,
1031                                    "Failed to parse capability in bounding set, ignoring: %s", t);
1032                         continue;
1033                 }
1034
1035                 sum |= ((uint64_t) 1ULL) << (uint64_t) cap;
1036         }
1037
1038         if (invert)
1039                 *capability_bounding_set_drop |= sum;
1040         else
1041                 *capability_bounding_set_drop |= ~sum;
1042
1043         return 0;
1044 }
1045
1046 int config_parse_limit(const char *unit,
1047                        const char *filename,
1048                        unsigned line,
1049                        const char *section,
1050                        unsigned section_line,
1051                        const char *lvalue,
1052                        int ltype,
1053                        const char *rvalue,
1054                        void *data,
1055                        void *userdata) {
1056
1057         struct rlimit **rl = data;
1058         unsigned long long u;
1059
1060         assert(filename);
1061         assert(lvalue);
1062         assert(rvalue);
1063         assert(data);
1064
1065         rl += ltype;
1066
1067         if (streq(rvalue, "infinity"))
1068                 u = (unsigned long long) RLIM_INFINITY;
1069         else {
1070                 int r;
1071
1072                 r = safe_atollu(rvalue, &u);
1073                 if (r < 0) {
1074                         log_syntax(unit, LOG_ERR, filename, line, -r,
1075                                    "Failed to parse resource value, ignoring: %s", rvalue);
1076                         return 0;
1077                 }
1078         }
1079
1080         if (!*rl) {
1081                 *rl = new(struct rlimit, 1);
1082                 if (!*rl)
1083                         return log_oom();
1084         }
1085
1086         (*rl)->rlim_cur = (*rl)->rlim_max = (rlim_t) u;
1087         return 0;
1088 }
1089
1090 #ifdef HAVE_SYSV_COMPAT
1091 int config_parse_sysv_priority(const char *unit,
1092                                const char *filename,
1093                                unsigned line,
1094                                const char *section,
1095                                unsigned section_line,
1096                                const char *lvalue,
1097                                int ltype,
1098                                const char *rvalue,
1099                                void *data,
1100                                void *userdata) {
1101
1102         int *priority = data;
1103         int i, r;
1104
1105         assert(filename);
1106         assert(lvalue);
1107         assert(rvalue);
1108         assert(data);
1109
1110         r = safe_atoi(rvalue, &i);
1111         if (r < 0 || i < 0) {
1112                 log_syntax(unit, LOG_ERR, filename, line, -r,
1113                            "Failed to parse SysV start priority, ignoring: %s", rvalue);
1114                 return 0;
1115         }
1116
1117         *priority = (int) i;
1118         return 0;
1119 }
1120 #endif
1121
1122 DEFINE_CONFIG_PARSE_ENUM(config_parse_kill_mode, kill_mode, KillMode, "Failed to parse kill mode");
1123
1124 int config_parse_kill_signal(const char *unit,
1125                              const char *filename,
1126                              unsigned line,
1127                              const char *section,
1128                              unsigned section_line,
1129                              const char *lvalue,
1130                              int ltype,
1131                              const char *rvalue,
1132                              void *data,
1133                              void *userdata) {
1134
1135         int *sig = data;
1136         int r;
1137
1138         assert(filename);
1139         assert(lvalue);
1140         assert(rvalue);
1141         assert(sig);
1142
1143         r = signal_from_string_try_harder(rvalue);
1144         if (r <= 0) {
1145                 log_syntax(unit, LOG_ERR, filename, line, -r,
1146                            "Failed to parse kill signal, ignoring: %s", rvalue);
1147                 return 0;
1148         }
1149
1150         *sig = r;
1151         return 0;
1152 }
1153
1154 int config_parse_exec_mount_flags(const char *unit,
1155                                   const char *filename,
1156                                   unsigned line,
1157                                   const char *section,
1158                                   unsigned section_line,
1159                                   const char *lvalue,
1160                                   int ltype,
1161                                   const char *rvalue,
1162                                   void *data,
1163                                   void *userdata) {
1164
1165         ExecContext *c = data;
1166         char *w;
1167         size_t l;
1168         char *state;
1169         unsigned long flags = 0;
1170
1171         assert(filename);
1172         assert(lvalue);
1173         assert(rvalue);
1174         assert(data);
1175
1176         FOREACH_WORD_SEPARATOR(w, l, rvalue, ", ", state) {
1177                 _cleanup_free_ char *t;
1178
1179                 t = strndup(w, l);
1180                 if (!t)
1181                         return log_oom();
1182
1183                 if (streq(t, "shared"))
1184                         flags = MS_SHARED;
1185                 else if (streq(t, "slave"))
1186                         flags = MS_SLAVE;
1187                 else if (streq(w, "private"))
1188                         flags = MS_PRIVATE;
1189                 else {
1190                         log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse mount flag %s, ignoring: %s", t, rvalue);
1191                         return 0;
1192                 }
1193         }
1194
1195         c->mount_flags = flags;
1196         return 0;
1197 }
1198
1199 int config_parse_exec_selinux_context(
1200                 const char *unit,
1201                 const char *filename,
1202                 unsigned line,
1203                 const char *section,
1204                 unsigned section_line,
1205                 const char *lvalue,
1206                 int ltype,
1207                 const char *rvalue,
1208                 void *data,
1209                 void *userdata) {
1210
1211         ExecContext *c = data;
1212         Unit *u = userdata;
1213         bool ignore;
1214         char *k;
1215         int r;
1216
1217         assert(filename);
1218         assert(lvalue);
1219         assert(rvalue);
1220         assert(data);
1221
1222         if (isempty(rvalue)) {
1223                 free(c->selinux_context);
1224                 c->selinux_context = NULL;
1225                 c->selinux_context_ignore = false;
1226                 return 0;
1227         }
1228
1229         if (rvalue[0] == '-') {
1230                 ignore = true;
1231                 rvalue++;
1232         } else
1233                 ignore = false;
1234
1235         r = unit_name_printf(u, rvalue, &k);
1236         if (r < 0) {
1237                 log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve specifiers, ignoring: %s", strerror(-r));
1238                 return 0;
1239         }
1240
1241         free(c->selinux_context);
1242         c->selinux_context = k;
1243         c->selinux_context_ignore = ignore;
1244
1245         return 0;
1246 }
1247
1248 int config_parse_exec_apparmor_profile(
1249                 const char *unit,
1250                 const char *filename,
1251                 unsigned line,
1252                 const char *section,
1253                 unsigned section_line,
1254                 const char *lvalue,
1255                 int ltype,
1256                 const char *rvalue,
1257                 void *data,
1258                 void *userdata) {
1259
1260         ExecContext *c = data;
1261         Unit *u = userdata;
1262         bool ignore;
1263         char *k;
1264         int r;
1265
1266         assert(filename);
1267         assert(lvalue);
1268         assert(rvalue);
1269         assert(data);
1270
1271         if (isempty(rvalue)) {
1272                 free(c->apparmor_profile);
1273                 c->apparmor_profile = NULL;
1274                 c->apparmor_profile_ignore = false;
1275                 return 0;
1276         }
1277
1278         if (rvalue[0] == '-') {
1279                 ignore = true;
1280                 rvalue++;
1281         } else
1282                 ignore = false;
1283
1284         r = unit_name_printf(u, rvalue, &k);
1285         if (r < 0) {
1286                 log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve specifiers, ignoring: %s", strerror(-r));
1287                 return 0;
1288         }
1289
1290         free(c->apparmor_profile);
1291         c->apparmor_profile = k;
1292         c->apparmor_profile_ignore = ignore;
1293
1294         return 0;
1295 }
1296
1297 int config_parse_timer(const char *unit,
1298                        const char *filename,
1299                        unsigned line,
1300                        const char *section,
1301                        unsigned section_line,
1302                        const char *lvalue,
1303                        int ltype,
1304                        const char *rvalue,
1305                        void *data,
1306                        void *userdata) {
1307
1308         Timer *t = data;
1309         usec_t u = 0;
1310         TimerValue *v;
1311         TimerBase b;
1312         CalendarSpec *c = NULL;
1313
1314         assert(filename);
1315         assert(lvalue);
1316         assert(rvalue);
1317         assert(data);
1318
1319         if (isempty(rvalue)) {
1320                 /* Empty assignment resets list */
1321                 timer_free_values(t);
1322                 return 0;
1323         }
1324
1325         b = timer_base_from_string(lvalue);
1326         if (b < 0) {
1327                 log_syntax(unit, LOG_ERR, filename, line, -b,
1328                            "Failed to parse timer base, ignoring: %s", lvalue);
1329                 return 0;
1330         }
1331
1332         if (b == TIMER_CALENDAR) {
1333                 if (calendar_spec_from_string(rvalue, &c) < 0) {
1334                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1335                                    "Failed to parse calendar specification, ignoring: %s",
1336                                    rvalue);
1337                         return 0;
1338                 }
1339         } else {
1340                 if (parse_sec(rvalue, &u) < 0) {
1341                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1342                                    "Failed to parse timer value, ignoring: %s",
1343                                    rvalue);
1344                         return 0;
1345                 }
1346         }
1347
1348         v = new0(TimerValue, 1);
1349         if (!v)
1350                 return log_oom();
1351
1352         v->base = b;
1353         v->value = u;
1354         v->calendar_spec = c;
1355
1356         LIST_PREPEND(value, t->values, v);
1357
1358         return 0;
1359 }
1360
1361 int config_parse_trigger_unit(
1362                 const char *unit,
1363                 const char *filename,
1364                 unsigned line,
1365                 const char *section,
1366                 unsigned section_line,
1367                 const char *lvalue,
1368                 int ltype,
1369                 const char *rvalue,
1370                 void *data,
1371                 void *userdata) {
1372
1373         _cleanup_free_ char *p = NULL;
1374         Unit *u = data;
1375         UnitType type;
1376         int r;
1377
1378         assert(filename);
1379         assert(lvalue);
1380         assert(rvalue);
1381         assert(data);
1382
1383         if (!set_isempty(u->dependencies[UNIT_TRIGGERS])) {
1384                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1385                            "Multiple units to trigger specified, ignoring: %s", rvalue);
1386                 return 0;
1387         }
1388
1389         r = unit_name_printf(u, rvalue, &p);
1390         if (r < 0)
1391                 log_syntax(unit, LOG_ERR, filename, line, -r,
1392                            "Failed to resolve specifiers, ignoring: %s", strerror(-r));
1393
1394         type = unit_name_to_type(p ?: rvalue);
1395         if (type < 0) {
1396                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1397                            "Unit type not valid, ignoring: %s", rvalue);
1398                 return 0;
1399         }
1400
1401         if (type == u->type) {
1402                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1403                            "Trigger cannot be of same type, ignoring: %s", rvalue);
1404                 return 0;
1405         }
1406
1407         r = unit_add_two_dependencies_by_name(u, UNIT_BEFORE, UNIT_TRIGGERS, p ?: rvalue, NULL, true);
1408         if (r < 0) {
1409                 log_syntax(unit, LOG_ERR, filename, line, -r,
1410                            "Failed to add trigger on %s, ignoring: %s", p ?: rvalue, strerror(-r));
1411                 return 0;
1412         }
1413
1414         return 0;
1415 }
1416
1417 int config_parse_path_spec(const char *unit,
1418                            const char *filename,
1419                            unsigned line,
1420                            const char *section,
1421                            unsigned section_line,
1422                            const char *lvalue,
1423                            int ltype,
1424                            const char *rvalue,
1425                            void *data,
1426                            void *userdata) {
1427
1428         Path *p = data;
1429         PathSpec *s;
1430         PathType b;
1431         _cleanup_free_ char *k = NULL;
1432         int r;
1433
1434         assert(filename);
1435         assert(lvalue);
1436         assert(rvalue);
1437         assert(data);
1438
1439         if (isempty(rvalue)) {
1440                 /* Empty assignment clears list */
1441                 path_free_specs(p);
1442                 return 0;
1443         }
1444
1445         b = path_type_from_string(lvalue);
1446         if (b < 0) {
1447                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1448                            "Failed to parse path type, ignoring: %s", lvalue);
1449                 return 0;
1450         }
1451
1452         r = unit_full_printf(UNIT(p), rvalue, &k);
1453         if (r < 0) {
1454                 k = strdup(rvalue);
1455                 if (!k)
1456                         return log_oom();
1457                 else
1458                         log_syntax(unit, LOG_ERR, filename, line, -r,
1459                                    "Failed to resolve unit specifiers on %s. Ignoring.",
1460                                    rvalue);
1461         }
1462
1463         if (!path_is_absolute(k)) {
1464                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1465                            "Path is not absolute, ignoring: %s", k);
1466                 return 0;
1467         }
1468
1469         s = new0(PathSpec, 1);
1470         if (!s)
1471                 return log_oom();
1472
1473         s->unit = UNIT(p);
1474         s->path = path_kill_slashes(k);
1475         k = NULL;
1476         s->type = b;
1477         s->inotify_fd = -1;
1478
1479         LIST_PREPEND(spec, p->specs, s);
1480
1481         return 0;
1482 }
1483
1484 int config_parse_socket_service(const char *unit,
1485                                 const char *filename,
1486                                 unsigned line,
1487                                 const char *section,
1488                                 unsigned section_line,
1489                                 const char *lvalue,
1490                                 int ltype,
1491                                 const char *rvalue,
1492                                 void *data,
1493                                 void *userdata) {
1494
1495         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1496         Socket *s = data;
1497         int r;
1498         Unit *x;
1499         _cleanup_free_ char *p = NULL;
1500
1501         assert(filename);
1502         assert(lvalue);
1503         assert(rvalue);
1504         assert(data);
1505
1506         r = unit_name_printf(UNIT(s), rvalue, &p);
1507         if (r < 0) {
1508                 log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve specifiers, ignoring: %s", rvalue);
1509                 return 0;
1510         }
1511
1512         if (!endswith(p, ".service")) {
1513                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Unit must be of type service, ignoring: %s", rvalue);
1514                 return 0;
1515         }
1516
1517         r = manager_load_unit(UNIT(s)->manager, p, NULL, &error, &x);
1518         if (r < 0) {
1519                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load unit %s, ignoring: %s", rvalue, bus_error_message(&error, r));
1520                 return 0;
1521         }
1522
1523         unit_ref_set(&s->service, x);
1524
1525         return 0;
1526 }
1527
1528 int config_parse_service_sockets(const char *unit,
1529                                  const char *filename,
1530                                  unsigned line,
1531                                  const char *section,
1532                                  unsigned section_line,
1533                                  const char *lvalue,
1534                                  int ltype,
1535                                  const char *rvalue,
1536                                  void *data,
1537                                  void *userdata) {
1538
1539         Service *s = data;
1540         int r;
1541         char *state, *w;
1542         size_t l;
1543
1544         assert(filename);
1545         assert(lvalue);
1546         assert(rvalue);
1547         assert(data);
1548
1549         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
1550                 _cleanup_free_ char *t = NULL, *k = NULL;
1551
1552                 t = strndup(w, l);
1553                 if (!t)
1554                         return log_oom();
1555
1556                 r = unit_name_printf(UNIT(s), t, &k);
1557                 if (r < 0)
1558                         log_syntax(unit, LOG_ERR, filename, line, -r,
1559                                    "Failed to resolve specifiers, ignoring: %s", strerror(-r));
1560
1561                 if (!endswith(k ?: t, ".socket")) {
1562                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1563                                    "Unit must be of type socket, ignoring: %s", k ?: t);
1564                         continue;
1565                 }
1566
1567                 r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_WANTS, UNIT_AFTER, k ?: t, NULL, true);
1568                 if (r < 0)
1569                         log_syntax(unit, LOG_ERR, filename, line, -r,
1570                                    "Failed to add dependency on %s, ignoring: %s",
1571                                    k ?: t, strerror(-r));
1572
1573                 r = unit_add_dependency_by_name(UNIT(s), UNIT_TRIGGERED_BY, k ?: t, NULL, true);
1574                 if (r < 0)
1575                         return r;
1576         }
1577
1578         return 0;
1579 }
1580
1581 int config_parse_service_timeout(const char *unit,
1582                                  const char *filename,
1583                                  unsigned line,
1584                                  const char *section,
1585                                  unsigned section_line,
1586                                  const char *lvalue,
1587                                  int ltype,
1588                                  const char *rvalue,
1589                                  void *data,
1590                                  void *userdata) {
1591
1592         Service *s = userdata;
1593         int r;
1594
1595         assert(filename);
1596         assert(lvalue);
1597         assert(rvalue);
1598         assert(s);
1599
1600         r = config_parse_sec(unit, filename, line, section, section_line, lvalue, ltype,
1601                              rvalue, data, userdata);
1602         if (r < 0)
1603                 return r;
1604
1605         if (streq(lvalue, "TimeoutSec")) {
1606                 s->start_timeout_defined = true;
1607                 s->timeout_stop_usec = s->timeout_start_usec;
1608         } else if (streq(lvalue, "TimeoutStartSec"))
1609                 s->start_timeout_defined = true;
1610
1611         return 0;
1612 }
1613
1614 int config_parse_busname_service(
1615                 const char *unit,
1616                 const char *filename,
1617                 unsigned line,
1618                 const char *section,
1619                 unsigned section_line,
1620                 const char *lvalue,
1621                 int ltype,
1622                 const char *rvalue,
1623                 void *data,
1624                 void *userdata) {
1625
1626         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1627         BusName *n = data;
1628         int r;
1629         Unit *x;
1630         _cleanup_free_ char *p = NULL;
1631
1632         assert(filename);
1633         assert(lvalue);
1634         assert(rvalue);
1635         assert(data);
1636
1637         r = unit_name_printf(UNIT(n), rvalue, &p);
1638         if (r < 0) {
1639                 log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve specifiers, ignoring: %s", rvalue);
1640                 return 0;
1641         }
1642
1643         if (!endswith(p, ".service")) {
1644                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Unit must be of type service, ignoring: %s", rvalue);
1645                 return 0;
1646         }
1647
1648         r = manager_load_unit(UNIT(n)->manager, p, NULL, &error, &x);
1649         if (r < 0) {
1650                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load unit %s, ignoring: %s", rvalue, bus_error_message(&error, r));
1651                 return 0;
1652         }
1653
1654         unit_ref_set(&n->service, x);
1655
1656         return 0;
1657 }
1658
1659 DEFINE_CONFIG_PARSE_ENUM(config_parse_bus_policy_world, busname_policy_access, BusNamePolicyAccess, "Failed to parse bus name policy access");
1660
1661 int config_parse_bus_policy(
1662                 const char *unit,
1663                 const char *filename,
1664                 unsigned line,
1665                 const char *section,
1666                 unsigned section_line,
1667                 const char *lvalue,
1668                 int ltype,
1669                 const char *rvalue,
1670                 void *data,
1671                 void *userdata) {
1672
1673         _cleanup_free_ BusNamePolicy *p = NULL;
1674         _cleanup_free_ char *id_str = NULL;
1675         BusName *busname = data;
1676         char *access_str;
1677
1678         assert(filename);
1679         assert(lvalue);
1680         assert(rvalue);
1681         assert(data);
1682
1683         p = new0(BusNamePolicy, 1);
1684         if (!p)
1685                 return log_oom();
1686
1687         if (streq(lvalue, "AllowUser"))
1688                 p->type = BUSNAME_POLICY_TYPE_USER;
1689         else if (streq(lvalue, "AllowGroup"))
1690                 p->type = BUSNAME_POLICY_TYPE_GROUP;
1691         else
1692                 assert_not_reached("Unknown lvalue");
1693
1694         id_str = strdup(rvalue);
1695         if (!id_str)
1696                 return log_oom();
1697
1698         access_str = strpbrk(id_str, WHITESPACE);
1699         if (!access_str) {
1700                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Invalid busname policy value '%s'", rvalue);
1701                 return 0;
1702         }
1703
1704         *access_str = '\0';
1705         access_str++;
1706         access_str += strspn(access_str, WHITESPACE);
1707
1708         p->access = busname_policy_access_from_string(access_str);
1709         if (p->access < 0) {
1710                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Invalid busname policy access type '%s'", access_str);
1711                 return 0;
1712         }
1713
1714         p->name = id_str;
1715         id_str = NULL;
1716
1717         LIST_PREPEND(policy, busname->policy, p);
1718         p = NULL;
1719
1720         return 0;
1721 }
1722
1723 int config_parse_unit_env_file(const char *unit,
1724                                const char *filename,
1725                                unsigned line,
1726                                const char *section,
1727                                unsigned section_line,
1728                                const char *lvalue,
1729                                int ltype,
1730                                const char *rvalue,
1731                                void *data,
1732                                void *userdata) {
1733
1734         char ***env = data;
1735         Unit *u = userdata;
1736         _cleanup_free_ char *n = NULL;
1737         const char *s;
1738         int r;
1739
1740         assert(filename);
1741         assert(lvalue);
1742         assert(rvalue);
1743         assert(data);
1744
1745         if (isempty(rvalue)) {
1746                 /* Empty assignment frees the list */
1747                 strv_free(*env);
1748                 *env = NULL;
1749                 return 0;
1750         }
1751
1752         r = unit_full_printf(u, rvalue, &n);
1753         if (r < 0)
1754                 log_syntax(unit, LOG_ERR, filename, line, r,
1755                            "Failed to resolve specifiers, ignoring: %s", rvalue);
1756
1757         s = n ?: rvalue;
1758         if (!path_is_absolute(s[0] == '-' ? s + 1 : s)) {
1759                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1760                            "Path '%s' is not absolute, ignoring.", s);
1761                 return 0;
1762         }
1763
1764         r = strv_extend(env, s);
1765         if (r < 0)
1766                 return log_oom();
1767
1768         return 0;
1769 }
1770
1771 int config_parse_environ(const char *unit,
1772                          const char *filename,
1773                          unsigned line,
1774                          const char *section,
1775                          unsigned section_line,
1776                          const char *lvalue,
1777                          int ltype,
1778                          const char *rvalue,
1779                          void *data,
1780                          void *userdata) {
1781
1782         Unit *u = userdata;
1783         char*** env = data, *w, *state;
1784         size_t l;
1785         _cleanup_free_ char *k = NULL;
1786         int r;
1787
1788         assert(filename);
1789         assert(lvalue);
1790         assert(rvalue);
1791         assert(data);
1792
1793         if (isempty(rvalue)) {
1794                 /* Empty assignment resets the list */
1795                 strv_free(*env);
1796                 *env = NULL;
1797                 return 0;
1798         }
1799
1800         if (u) {
1801                 r = unit_full_printf(u, rvalue, &k);
1802                 if (r < 0)
1803                         log_syntax(unit, LOG_ERR, filename, line, -r,
1804                                    "Failed to resolve specifiers, ignoring: %s", rvalue);
1805         }
1806
1807         if (!k)
1808                 k = strdup(rvalue);
1809         if (!k)
1810                 return log_oom();
1811
1812         FOREACH_WORD_QUOTED(w, l, k, state) {
1813                 _cleanup_free_ char *n;
1814                 char **x;
1815
1816                 n = cunescape_length(w, l);
1817                 if (!n)
1818                         return log_oom();
1819
1820                 if (!env_assignment_is_valid(n)) {
1821                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1822                                    "Invalid environment assignment, ignoring: %s", rvalue);
1823                         continue;
1824                 }
1825
1826                 x = strv_env_set(*env, n);
1827                 if (!x)
1828                         return log_oom();
1829
1830                 strv_free(*env);
1831                 *env = x;
1832         }
1833
1834         return 0;
1835 }
1836
1837 int config_parse_ip_tos(const char *unit,
1838                         const char *filename,
1839                         unsigned line,
1840                         const char *section,
1841                         unsigned section_line,
1842                         const char *lvalue,
1843                         int ltype,
1844                         const char *rvalue,
1845                         void *data,
1846                         void *userdata) {
1847
1848         int *ip_tos = data, x;
1849
1850         assert(filename);
1851         assert(lvalue);
1852         assert(rvalue);
1853         assert(data);
1854
1855         x = ip_tos_from_string(rvalue);
1856         if (x < 0) {
1857                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1858                            "Failed to parse IP TOS value, ignoring: %s", rvalue);
1859                 return 0;
1860         }
1861
1862         *ip_tos = x;
1863         return 0;
1864 }
1865
1866 int config_parse_unit_condition_path(const char *unit,
1867                                      const char *filename,
1868                                      unsigned line,
1869                                      const char *section,
1870                                      unsigned section_line,
1871                                      const char *lvalue,
1872                                      int ltype,
1873                                      const char *rvalue,
1874                                      void *data,
1875                                      void *userdata) {
1876
1877         ConditionType cond = ltype;
1878         Unit *u = data;
1879         bool trigger, negate;
1880         Condition *c;
1881         _cleanup_free_ char *p = NULL;
1882         int r;
1883
1884         assert(filename);
1885         assert(lvalue);
1886         assert(rvalue);
1887         assert(data);
1888
1889         if (isempty(rvalue)) {
1890                 /* Empty assignment resets the list */
1891                 condition_free_list(u->conditions);
1892                 u->conditions = NULL;
1893                 return 0;
1894         }
1895
1896         trigger = rvalue[0] == '|';
1897         if (trigger)
1898                 rvalue++;
1899
1900         negate = rvalue[0] == '!';
1901         if (negate)
1902                 rvalue++;
1903
1904         r = unit_full_printf(u, rvalue, &p);
1905         if (r < 0)
1906                 log_syntax(unit, LOG_ERR, filename, line, -r,
1907                            "Failed to resolve specifiers, ignoring: %s", rvalue);
1908         if (!p) {
1909                 p = strdup(rvalue);
1910                 if (!p)
1911                         return log_oom();
1912         }
1913
1914         if (!path_is_absolute(p)) {
1915                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1916                            "Path in condition not absolute, ignoring: %s", p);
1917                 return 0;
1918         }
1919
1920         c = condition_new(cond, p, trigger, negate);
1921         if (!c)
1922                 return log_oom();
1923
1924         LIST_PREPEND(conditions, u->conditions, c);
1925         return 0;
1926 }
1927
1928 int config_parse_unit_condition_string(const char *unit,
1929                                        const char *filename,
1930                                        unsigned line,
1931                                        const char *section,
1932                                        unsigned section_line,
1933                                        const char *lvalue,
1934                                        int ltype,
1935                                        const char *rvalue,
1936                                        void *data,
1937                                        void *userdata) {
1938
1939         ConditionType cond = ltype;
1940         Unit *u = data;
1941         bool trigger, negate;
1942         Condition *c;
1943         _cleanup_free_ char *s = NULL;
1944         int r;
1945
1946         assert(filename);
1947         assert(lvalue);
1948         assert(rvalue);
1949         assert(data);
1950
1951         if (isempty(rvalue)) {
1952                 /* Empty assignment resets the list */
1953                 condition_free_list(u->conditions);
1954                 u->conditions = NULL;
1955                 return 0;
1956         }
1957
1958         trigger = rvalue[0] == '|';
1959         if (trigger)
1960                 rvalue++;
1961
1962         negate = rvalue[0] == '!';
1963         if (negate)
1964                 rvalue++;
1965
1966         r = unit_full_printf(u, rvalue, &s);
1967         if (r < 0)
1968                 log_syntax(unit, LOG_ERR, filename, line, -r,
1969                            "Failed to resolve specifiers, ignoring: %s", rvalue);
1970         if (!s) {
1971                 s = strdup(rvalue);
1972                 if (!s)
1973                         return log_oom();
1974         }
1975
1976         c = condition_new(cond, s, trigger, negate);
1977         if (!c)
1978                 return log_oom();
1979
1980         LIST_PREPEND(conditions, u->conditions, c);
1981         return 0;
1982 }
1983
1984 int config_parse_unit_condition_null(const char *unit,
1985                                      const char *filename,
1986                                      unsigned line,
1987                                      const char *section,
1988                                      unsigned section_line,
1989                                      const char *lvalue,
1990                                      int ltype,
1991                                      const char *rvalue,
1992                                      void *data,
1993                                      void *userdata) {
1994
1995         Unit *u = data;
1996         Condition *c;
1997         bool trigger, negate;
1998         int b;
1999
2000         assert(filename);
2001         assert(lvalue);
2002         assert(rvalue);
2003         assert(data);
2004
2005         if (isempty(rvalue)) {
2006                 /* Empty assignment resets the list */
2007                 condition_free_list(u->conditions);
2008                 u->conditions = NULL;
2009                 return 0;
2010         }
2011
2012         trigger = rvalue[0] == '|';
2013         if (trigger)
2014                 rvalue++;
2015
2016         negate = rvalue[0] == '!';
2017         if (negate)
2018                 rvalue++;
2019
2020         b = parse_boolean(rvalue);
2021         if (b < 0) {
2022                 log_syntax(unit, LOG_ERR, filename, line, -b,
2023                            "Failed to parse boolean value in condition, ignoring: %s",
2024                            rvalue);
2025                 return 0;
2026         }
2027
2028         if (!b)
2029                 negate = !negate;
2030
2031         c = condition_new(CONDITION_NULL, NULL, trigger, negate);
2032         if (!c)
2033                 return log_oom();
2034
2035         LIST_PREPEND(conditions, u->conditions, c);
2036         return 0;
2037 }
2038
2039 DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier");
2040 DEFINE_CONFIG_PARSE_ENUM(config_parse_failure_action, failure_action, FailureAction, "Failed to parse failure action specifier");
2041
2042 int config_parse_unit_requires_mounts_for(
2043                 const char *unit,
2044                 const char *filename,
2045                 unsigned line,
2046                 const char *section,
2047                 unsigned section_line,
2048                 const char *lvalue,
2049                 int ltype,
2050                 const char *rvalue,
2051                 void *data,
2052                 void *userdata) {
2053
2054         Unit *u = userdata;
2055         char *state;
2056         size_t l;
2057         char *w;
2058
2059         assert(filename);
2060         assert(lvalue);
2061         assert(rvalue);
2062         assert(data);
2063
2064         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
2065                 int r;
2066                 _cleanup_free_ char *n;
2067
2068                 n = strndup(w, l);
2069                 if (!n)
2070                         return log_oom();
2071
2072                 if (!utf8_is_valid(n)) {
2073                         log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue);
2074                         continue;
2075                 }
2076
2077                 r = unit_require_mounts_for(u, n);
2078                 if (r < 0) {
2079                         log_syntax(unit, LOG_ERR, filename, line, r,
2080                                    "Failed to add required mount for, ignoring: %s", rvalue);
2081                         continue;
2082                 }
2083         }
2084
2085         return 0;
2086 }
2087
2088 int config_parse_documentation(const char *unit,
2089                                const char *filename,
2090                                unsigned line,
2091                                const char *section,
2092                                unsigned section_line,
2093                                const char *lvalue,
2094                                int ltype,
2095                                const char *rvalue,
2096                                void *data,
2097                                void *userdata) {
2098
2099         Unit *u = userdata;
2100         int r;
2101         char **a, **b;
2102
2103         assert(filename);
2104         assert(lvalue);
2105         assert(rvalue);
2106         assert(u);
2107
2108         if (isempty(rvalue)) {
2109                 /* Empty assignment resets the list */
2110                 strv_free(u->documentation);
2111                 u->documentation = NULL;
2112                 return 0;
2113         }
2114
2115         r = config_parse_unit_strv_printf(unit, filename, line, section, section_line, lvalue, ltype,
2116                                           rvalue, data, userdata);
2117         if (r < 0)
2118                 return r;
2119
2120         for (a = b = u->documentation; a && *a; a++) {
2121
2122                 if (is_valid_documentation_url(*a))
2123                         *(b++) = *a;
2124                 else {
2125                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2126                                    "Invalid URL, ignoring: %s", *a);
2127                         free(*a);
2128                 }
2129         }
2130         if (b)
2131                 *b = NULL;
2132
2133         return r;
2134 }
2135
2136 #ifdef HAVE_SECCOMP
2137 int config_parse_syscall_filter(
2138                 const char *unit,
2139                 const char *filename,
2140                 unsigned line,
2141                 const char *section,
2142                 unsigned section_line,
2143                 const char *lvalue,
2144                 int ltype,
2145                 const char *rvalue,
2146                 void *data,
2147                 void *userdata) {
2148
2149         static const char default_syscalls[] =
2150                 "execve\0"
2151                 "exit\0"
2152                 "exit_group\0"
2153                 "rt_sigreturn\0"
2154                 "sigreturn\0";
2155
2156         ExecContext *c = data;
2157         Unit *u = userdata;
2158         bool invert = false;
2159         char *w, *state;
2160         size_t l;
2161         int r;
2162
2163         assert(filename);
2164         assert(lvalue);
2165         assert(rvalue);
2166         assert(u);
2167
2168         if (isempty(rvalue)) {
2169                 /* Empty assignment resets the list */
2170                 set_free(c->syscall_filter);
2171                 c->syscall_filter = NULL;
2172                 c->syscall_whitelist = false;
2173                 return 0;
2174         }
2175
2176         if (rvalue[0] == '~') {
2177                 invert = true;
2178                 rvalue++;
2179         }
2180
2181         if (!c->syscall_filter) {
2182                 c->syscall_filter = set_new(trivial_hash_func, trivial_compare_func);
2183                 if (!c->syscall_filter)
2184                         return log_oom();
2185
2186                 if (invert)
2187                         /* Allow everything but the ones listed */
2188                         c->syscall_whitelist = false;
2189                 else {
2190                         const char *i;
2191
2192                         /* Allow nothing but the ones listed */
2193                         c->syscall_whitelist = true;
2194
2195                         /* Accept default syscalls if we are on a whitelist */
2196                         NULSTR_FOREACH(i, default_syscalls)  {
2197                                 int id;
2198
2199                                 id = seccomp_syscall_resolve_name(i);
2200                                 if (id < 0)
2201                                         continue;
2202
2203                                 r = set_put(c->syscall_filter, INT_TO_PTR(id + 1));
2204                                 if (r == -EEXIST)
2205                                         continue;
2206                                 if (r < 0)
2207                                         return log_oom();
2208                         }
2209                 }
2210         }
2211
2212         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
2213                 _cleanup_free_ char *t = NULL;
2214                 int id;
2215
2216                 t = strndup(w, l);
2217                 if (!t)
2218                         return log_oom();
2219
2220                 id = seccomp_syscall_resolve_name(t);
2221                 if (id < 0)  {
2222                         log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse system call, ignoring: %s", t);
2223                         continue;
2224                 }
2225
2226                 /* If we previously wanted to forbid a syscall and now
2227                  * we want to allow it, then remove it from the list
2228                  */
2229                 if (!invert == c->syscall_whitelist)  {
2230                         r = set_put(c->syscall_filter, INT_TO_PTR(id + 1));
2231                         if (r == -EEXIST)
2232                                 continue;
2233                         if (r < 0)
2234                                 return log_oom();
2235                 } else
2236                         set_remove(c->syscall_filter, INT_TO_PTR(id + 1));
2237         }
2238
2239         /* Turn on NNP, but only if it wasn't configured explicitly
2240          * before, and only if we are in user mode. */
2241         if (!c->no_new_privileges_set && u->manager->running_as == SYSTEMD_USER)
2242                 c->no_new_privileges = true;
2243
2244         return 0;
2245 }
2246
2247 int config_parse_syscall_archs(
2248                 const char *unit,
2249                 const char *filename,
2250                 unsigned line,
2251                 const char *section,
2252                 unsigned section_line,
2253                 const char *lvalue,
2254                 int ltype,
2255                 const char *rvalue,
2256                 void *data,
2257                 void *userdata) {
2258
2259         Set **archs = data;
2260         char *w, *state;
2261         size_t l;
2262         int r;
2263
2264         if (isempty(rvalue)) {
2265                 set_free(*archs);
2266                 *archs = NULL;
2267                 return 0;
2268         }
2269
2270         r = set_ensure_allocated(archs, trivial_hash_func, trivial_compare_func);
2271         if (r < 0)
2272                 return log_oom();
2273
2274         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
2275                 _cleanup_free_ char *t = NULL;
2276                 uint32_t a;
2277
2278                 t = strndup(w, l);
2279                 if (!t)
2280                         return log_oom();
2281
2282                 r = seccomp_arch_from_string(t, &a);
2283                 if (r < 0) {
2284                         log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse system call architecture, ignoring: %s", t);
2285                         continue;
2286                 }
2287
2288                 r = set_put(*archs, UINT32_TO_PTR(a + 1));
2289                 if (r == -EEXIST)
2290                         continue;
2291                 if (r < 0)
2292                         return log_oom();
2293         }
2294
2295         return 0;
2296 }
2297
2298 int config_parse_syscall_errno(
2299                 const char *unit,
2300                 const char *filename,
2301                 unsigned line,
2302                 const char *section,
2303                 unsigned section_line,
2304                 const char *lvalue,
2305                 int ltype,
2306                 const char *rvalue,
2307                 void *data,
2308                 void *userdata) {
2309
2310         ExecContext *c = data;
2311         int e;
2312
2313         assert(filename);
2314         assert(lvalue);
2315         assert(rvalue);
2316
2317         if (isempty(rvalue)) {
2318                 /* Empty assignment resets to KILL */
2319                 c->syscall_errno = 0;
2320                 return 0;
2321         }
2322
2323         e = errno_from_name(rvalue);
2324         if (e < 0) {
2325                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse error number, ignoring: %s", rvalue);
2326                 return 0;
2327         }
2328
2329         c->syscall_errno = e;
2330         return 0;
2331 }
2332
2333 int config_parse_address_families(
2334                 const char *unit,
2335                 const char *filename,
2336                 unsigned line,
2337                 const char *section,
2338                 unsigned section_line,
2339                 const char *lvalue,
2340                 int ltype,
2341                 const char *rvalue,
2342                 void *data,
2343                 void *userdata) {
2344
2345         ExecContext *c = data;
2346         Unit *u = userdata;
2347         bool invert = false;
2348         char *w, *state;
2349         size_t l;
2350         int r;
2351
2352         assert(filename);
2353         assert(lvalue);
2354         assert(rvalue);
2355         assert(u);
2356
2357         if (isempty(rvalue)) {
2358                 /* Empty assignment resets the list */
2359                 set_free(c->address_families);
2360                 c->address_families = NULL;
2361                 c->address_families_whitelist = false;
2362                 return 0;
2363         }
2364
2365         if (rvalue[0] == '~') {
2366                 invert = true;
2367                 rvalue++;
2368         }
2369
2370         if (!c->address_families) {
2371                 c->address_families = set_new(trivial_hash_func, trivial_compare_func);
2372                 if (!c->address_families)
2373                         return log_oom();
2374
2375                 c->address_families_whitelist = !invert;
2376         }
2377
2378         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
2379                 _cleanup_free_ char *t = NULL;
2380                 int af;
2381
2382                 t = strndup(w, l);
2383                 if (!t)
2384                         return log_oom();
2385
2386                 af = af_from_name(t);
2387                 if (af <= 0)  {
2388                         log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse address family, ignoring: %s", t);
2389                         continue;
2390                 }
2391
2392                 /* If we previously wanted to forbid an address family and now
2393                  * we want to allow it, then remove it from the list
2394                  */
2395                 if (!invert == c->address_families_whitelist)  {
2396                         r = set_put(c->address_families, INT_TO_PTR(af));
2397                         if (r == -EEXIST)
2398                                 continue;
2399                         if (r < 0)
2400                                 return log_oom();
2401                 } else
2402                         set_remove(c->address_families, INT_TO_PTR(af));
2403         }
2404
2405         return 0;
2406 }
2407 #endif
2408
2409 int config_parse_unit_slice(
2410                 const char *unit,
2411                 const char *filename,
2412                 unsigned line,
2413                 const char *section,
2414                 unsigned section_line,
2415                 const char *lvalue,
2416                 int ltype,
2417                 const char *rvalue,
2418                 void *data,
2419                 void *userdata) {
2420
2421         _cleanup_free_ char *k = NULL;
2422         Unit *u = userdata, *slice;
2423         int r;
2424
2425         assert(filename);
2426         assert(lvalue);
2427         assert(rvalue);
2428         assert(u);
2429
2430         r = unit_name_printf(u, rvalue, &k);
2431         if (r < 0)
2432                 log_syntax(unit, LOG_ERR, filename, line, -r,
2433                            "Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
2434         if (!k) {
2435                 k = strdup(rvalue);
2436                 if (!k)
2437                         return log_oom();
2438         }
2439
2440         r = manager_load_unit(u->manager, k, NULL, NULL, &slice);
2441         if (r < 0) {
2442                 log_syntax(unit, LOG_ERR, filename, line, -r,
2443                            "Failed to load slice unit %s. Ignoring.", k);
2444                 return 0;
2445         }
2446
2447         if (slice->type != UNIT_SLICE) {
2448                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2449                            "Slice unit %s is not a slice. Ignoring.", k);
2450                 return 0;
2451         }
2452
2453         unit_ref_set(&u->slice, slice);
2454         return 0;
2455 }
2456
2457 DEFINE_CONFIG_PARSE_ENUM(config_parse_device_policy, cgroup_device_policy, CGroupDevicePolicy, "Failed to parse device policy");
2458
2459 int config_parse_cpu_shares(
2460                 const char *unit,
2461                 const char *filename,
2462                 unsigned line,
2463                 const char *section,
2464                 unsigned section_line,
2465                 const char *lvalue,
2466                 int ltype,
2467                 const char *rvalue,
2468                 void *data,
2469                 void *userdata) {
2470
2471         unsigned long *shares = data, lu;
2472         int r;
2473
2474         assert(filename);
2475         assert(lvalue);
2476         assert(rvalue);
2477
2478         if (isempty(rvalue)) {
2479                 *shares = (unsigned long) -1;
2480                 return 0;
2481         }
2482
2483         r = safe_atolu(rvalue, &lu);
2484         if (r < 0 || lu <= 0) {
2485                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "CPU shares '%s' invalid. Ignoring.", rvalue);
2486                 return 0;
2487         }
2488
2489         *shares = lu;
2490         return 0;
2491 }
2492
2493 int config_parse_cpu_quota(
2494                 const char *unit,
2495                 const char *filename,
2496                 unsigned line,
2497                 const char *section,
2498                 unsigned section_line,
2499                 const char *lvalue,
2500                 int ltype,
2501                 const char *rvalue,
2502                 void *data,
2503                 void *userdata) {
2504
2505         CGroupContext *c = data;
2506         double percent;
2507
2508         assert(filename);
2509         assert(lvalue);
2510         assert(rvalue);
2511
2512         if (isempty(rvalue)) {
2513                 c->cpu_quota_per_sec_usec = (usec_t) -1;
2514                 return 0;
2515         }
2516
2517         if (!endswith(rvalue, "%")) {
2518
2519                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "CPU quota '%s' not ending in '%%'. Ignoring.", rvalue);
2520                 return 0;
2521         }
2522
2523         if (sscanf(rvalue, "%lf%%", &percent) != 1 || percent <= 0) {
2524                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "CPU quota '%s' invalid. Ignoring.", rvalue);
2525                 return 0;
2526         }
2527
2528         c->cpu_quota_per_sec_usec = (usec_t) (percent * USEC_PER_SEC / 100);
2529
2530         return 0;
2531 }
2532
2533 int config_parse_memory_limit(
2534                 const char *unit,
2535                 const char *filename,
2536                 unsigned line,
2537                 const char *section,
2538                 unsigned section_line,
2539                 const char *lvalue,
2540                 int ltype,
2541                 const char *rvalue,
2542                 void *data,
2543                 void *userdata) {
2544
2545         CGroupContext *c = data;
2546         off_t bytes;
2547         int r;
2548
2549         if (isempty(rvalue)) {
2550                 c->memory_limit = (uint64_t) -1;
2551                 return 0;
2552         }
2553
2554         assert_cc(sizeof(uint64_t) == sizeof(off_t));
2555
2556         r = parse_size(rvalue, 1024, &bytes);
2557         if (r < 0) {
2558                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Memory limit '%s' invalid. Ignoring.", rvalue);
2559                 return 0;
2560         }
2561
2562         c->memory_limit = (uint64_t) bytes;
2563         return 0;
2564 }
2565
2566 int config_parse_device_allow(
2567                 const char *unit,
2568                 const char *filename,
2569                 unsigned line,
2570                 const char *section,
2571                 unsigned section_line,
2572                 const char *lvalue,
2573                 int ltype,
2574                 const char *rvalue,
2575                 void *data,
2576                 void *userdata) {
2577
2578         _cleanup_free_ char *path = NULL;
2579         CGroupContext *c = data;
2580         CGroupDeviceAllow *a;
2581         const char *m;
2582         size_t n;
2583
2584         if (isempty(rvalue)) {
2585                 while (c->device_allow)
2586                         cgroup_context_free_device_allow(c, c->device_allow);
2587
2588                 return 0;
2589         }
2590
2591         n = strcspn(rvalue, WHITESPACE);
2592         path = strndup(rvalue, n);
2593         if (!path)
2594                 return log_oom();
2595
2596         if (!startswith(path, "/dev/") &&
2597             !startswith(path, "block-") &&
2598             !startswith(path, "char-")) {
2599                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Invalid device node path '%s'. Ignoring.", path);
2600                 return 0;
2601         }
2602
2603         m = rvalue + n + strspn(rvalue + n, WHITESPACE);
2604         if (isempty(m))
2605                 m = "rwm";
2606
2607         if (!in_charset(m, "rwm")) {
2608                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Invalid device rights '%s'. Ignoring.", m);
2609                 return 0;
2610         }
2611
2612         a = new0(CGroupDeviceAllow, 1);
2613         if (!a)
2614                 return log_oom();
2615
2616         a->path = path;
2617         path = NULL;
2618         a->r = !!strchr(m, 'r');
2619         a->w = !!strchr(m, 'w');
2620         a->m = !!strchr(m, 'm');
2621
2622         LIST_PREPEND(device_allow, c->device_allow, a);
2623         return 0;
2624 }
2625
2626 int config_parse_blockio_weight(
2627                 const char *unit,
2628                 const char *filename,
2629                 unsigned line,
2630                 const char *section,
2631                 unsigned section_line,
2632                 const char *lvalue,
2633                 int ltype,
2634                 const char *rvalue,
2635                 void *data,
2636                 void *userdata) {
2637
2638         unsigned long *weight = data, lu;
2639         int r;
2640
2641         assert(filename);
2642         assert(lvalue);
2643         assert(rvalue);
2644
2645         if (isempty(rvalue)) {
2646                 *weight = (unsigned long) -1;
2647                 return 0;
2648         }
2649
2650         r = safe_atolu(rvalue, &lu);
2651         if (r < 0 || lu < 10 || lu > 1000) {
2652                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Block IO weight '%s' invalid. Ignoring.", rvalue);
2653                 return 0;
2654         }
2655
2656         *weight = lu;
2657         return 0;
2658 }
2659
2660 int config_parse_blockio_device_weight(
2661                 const char *unit,
2662                 const char *filename,
2663                 unsigned line,
2664                 const char *section,
2665                 unsigned section_line,
2666                 const char *lvalue,
2667                 int ltype,
2668                 const char *rvalue,
2669                 void *data,
2670                 void *userdata) {
2671
2672         _cleanup_free_ char *path = NULL;
2673         CGroupBlockIODeviceWeight *w;
2674         CGroupContext *c = data;
2675         unsigned long lu;
2676         const char *weight;
2677         size_t n;
2678         int r;
2679
2680         assert(filename);
2681         assert(lvalue);
2682         assert(rvalue);
2683
2684         if (isempty(rvalue)) {
2685                 while (c->blockio_device_weights)
2686                         cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
2687
2688                 return 0;
2689         }
2690
2691         n = strcspn(rvalue, WHITESPACE);
2692         weight = rvalue + n;
2693         if (!*weight) {
2694                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Expected block device and device weight. Ignoring.");
2695                 return 0;
2696         }
2697
2698         path = strndup(rvalue, n);
2699         if (!path)
2700                 return log_oom();
2701
2702         if (!path_startswith(path, "/dev")) {
2703                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Invalid device node path '%s'. Ignoring.", path);
2704                 return 0;
2705         }
2706
2707         weight += strspn(weight, WHITESPACE);
2708         r = safe_atolu(weight, &lu);
2709         if (r < 0 || lu < 10 || lu > 1000) {
2710                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Block IO weight '%s' invalid. Ignoring.", rvalue);
2711                 return 0;
2712         }
2713
2714         w = new0(CGroupBlockIODeviceWeight, 1);
2715         if (!w)
2716                 return log_oom();
2717
2718         w->path = path;
2719         path = NULL;
2720
2721         w->weight = lu;
2722
2723         LIST_PREPEND(device_weights, c->blockio_device_weights, w);
2724         return 0;
2725 }
2726
2727 int config_parse_blockio_bandwidth(
2728                 const char *unit,
2729                 const char *filename,
2730                 unsigned line,
2731                 const char *section,
2732                 unsigned section_line,
2733                 const char *lvalue,
2734                 int ltype,
2735                 const char *rvalue,
2736                 void *data,
2737                 void *userdata) {
2738
2739         _cleanup_free_ char *path = NULL;
2740         CGroupBlockIODeviceBandwidth *b;
2741         CGroupContext *c = data;
2742         const char *bandwidth;
2743         off_t bytes;
2744         bool read;
2745         size_t n;
2746         int r;
2747
2748         assert(filename);
2749         assert(lvalue);
2750         assert(rvalue);
2751
2752         read = streq("BlockIOReadBandwidth", lvalue);
2753
2754         if (isempty(rvalue)) {
2755                 CGroupBlockIODeviceBandwidth *next;
2756
2757                 LIST_FOREACH_SAFE (device_bandwidths, b, next, c->blockio_device_bandwidths)
2758                         if (b->read == read)
2759                                 cgroup_context_free_blockio_device_bandwidth(c, b);
2760
2761                 return 0;
2762         }
2763
2764         n = strcspn(rvalue, WHITESPACE);
2765         bandwidth = rvalue + n;
2766         bandwidth += strspn(bandwidth, WHITESPACE);
2767
2768         if (!*bandwidth) {
2769                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2770                            "Expected space separated pair of device node and bandwidth. Ignoring.");
2771                 return 0;
2772         }
2773
2774         path = strndup(rvalue, n);
2775         if (!path)
2776                 return log_oom();
2777
2778         if (!path_startswith(path, "/dev")) {
2779                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2780                            "Invalid device node path '%s'. Ignoring.", path);
2781                 return 0;
2782         }
2783
2784         r = parse_size(bandwidth, 1000, &bytes);
2785         if (r < 0 || bytes <= 0) {
2786                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Block IO Bandwidth '%s' invalid. Ignoring.", rvalue);
2787                 return 0;
2788         }
2789
2790         b = new0(CGroupBlockIODeviceBandwidth, 1);
2791         if (!b)
2792                 return log_oom();
2793
2794         b->path = path;
2795         path = NULL;
2796         b->bandwidth = (uint64_t) bytes;
2797         b->read = read;
2798
2799         LIST_PREPEND(device_bandwidths, c->blockio_device_bandwidths, b);
2800
2801         return 0;
2802 }
2803
2804 DEFINE_CONFIG_PARSE_ENUM(config_parse_job_mode, job_mode, JobMode, "Failed to parse job mode");
2805
2806 int config_parse_job_mode_isolate(
2807                 const char *unit,
2808                 const char *filename,
2809                 unsigned line,
2810                 const char *section,
2811                 unsigned section_line,
2812                 const char *lvalue,
2813                 int ltype,
2814                 const char *rvalue,
2815                 void *data,
2816                 void *userdata) {
2817
2818         JobMode *m = data;
2819         int r;
2820
2821         assert(filename);
2822         assert(lvalue);
2823         assert(rvalue);
2824
2825         r = parse_boolean(rvalue);
2826         if (r < 0) {
2827                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse boolean, ignoring: %s", rvalue);
2828                 return 0;
2829         }
2830
2831         *m = r ? JOB_ISOLATE : JOB_REPLACE;
2832         return 0;
2833 }
2834
2835 int config_parse_personality(
2836                 const char *unit,
2837                 const char *filename,
2838                 unsigned line,
2839                 const char *section,
2840                 unsigned section_line,
2841                 const char *lvalue,
2842                 int ltype,
2843                 const char *rvalue,
2844                 void *data,
2845                 void *userdata) {
2846
2847         unsigned long *personality = data, p;
2848
2849         assert(filename);
2850         assert(lvalue);
2851         assert(rvalue);
2852         assert(personality);
2853
2854         p = personality_from_string(rvalue);
2855         if (p == 0xffffffffUL) {
2856                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2857                            "Failed to parse personality, ignoring: %s", rvalue);
2858                 return 0;
2859         }
2860
2861         *personality = p;
2862         return 0;
2863 }
2864
2865 int config_parse_runtime_directory(
2866                 const char *unit,
2867                 const char *filename,
2868                 unsigned line,
2869                 const char *section,
2870                 unsigned section_line,
2871                 const char *lvalue,
2872                 int ltype,
2873                 const char *rvalue,
2874                 void *data,
2875                 void *userdata) {
2876
2877         char***rt = data, *w, *state;
2878         size_t l;
2879         int r;
2880
2881         assert(filename);
2882         assert(lvalue);
2883         assert(rvalue);
2884         assert(data);
2885
2886         if (isempty(rvalue)) {
2887                 /* Empty assignment resets the list */
2888                 strv_free(*rt);
2889                 *rt = NULL;
2890                 return 0;
2891         }
2892
2893         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
2894                 _cleanup_free_ char *n;
2895
2896                 n = strndup(w, l);
2897                 if (!n)
2898                         return log_oom();
2899
2900                 if (!filename_is_safe(n)) {
2901                         log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Runtime directory is not valid, ignoring assignment: %s", rvalue);
2902                         continue;
2903                 }
2904
2905                 r = strv_push(rt, n);
2906                 if (r < 0)
2907                         return log_oom();
2908
2909                 n = NULL;
2910         }
2911
2912         return 0;
2913 }
2914
2915 int config_parse_set_status(
2916                 const char *unit,
2917                 const char *filename,
2918                 unsigned line,
2919                 const char *section,
2920                 unsigned section_line,
2921                 const char *lvalue,
2922                 int ltype,
2923                 const char *rvalue,
2924                 void *data,
2925                 void *userdata) {
2926
2927         char *w;
2928         size_t l;
2929         char *state;
2930         int r;
2931         ExitStatusSet *status_set = data;
2932
2933         assert(filename);
2934         assert(lvalue);
2935         assert(rvalue);
2936         assert(data);
2937
2938         if (isempty(rvalue)) {
2939                 /* Empty assignment resets the list */
2940
2941                 set_free(status_set->signal);
2942                 set_free(status_set->code);
2943
2944                 status_set->signal = status_set->code = NULL;
2945                 return 0;
2946         }
2947
2948         FOREACH_WORD(w, l, rvalue, state) {
2949                 _cleanup_free_ char *temp;
2950                 int val;
2951
2952                 temp = strndup(w, l);
2953                 if (!temp)
2954                         return log_oom();
2955
2956                 r = safe_atoi(temp, &val);
2957                 if (r < 0) {
2958                         val = signal_from_string_try_harder(temp);
2959
2960                         if (val > 0) {
2961                                 r = set_ensure_allocated(&status_set->signal, trivial_hash_func, trivial_compare_func);
2962                                 if (r < 0)
2963                                         return log_oom();
2964
2965                                 r = set_put(status_set->signal, INT_TO_PTR(val));
2966                                 if (r < 0) {
2967                                         log_syntax(unit, LOG_ERR, filename, line, -r, "Unable to store: %s", w);
2968                                         return r;
2969                                 }
2970                         } else {
2971                                 log_syntax(unit, LOG_ERR, filename, line, -val, "Failed to parse value, ignoring: %s", w);
2972                                 return 0;
2973                         }
2974                 } else {
2975                         if (val < 0 || val > 255)
2976                                 log_syntax(unit, LOG_ERR, filename, line, ERANGE, "Value %d is outside range 0-255, ignoring", val);
2977                         else {
2978                                 r = set_ensure_allocated(&status_set->code, trivial_hash_func, trivial_compare_func);
2979                                 if (r < 0)
2980                                         return log_oom();
2981
2982                                 r = set_put(status_set->code, INT_TO_PTR(val));
2983                                 if (r < 0) {
2984                                         log_syntax(unit, LOG_ERR, filename, line, -r, "Unable to store: %s", w);
2985                                         return r;
2986                                 }
2987                         }
2988                 }
2989         }
2990
2991         return 0;
2992 }
2993
2994 int config_parse_namespace_path_strv(
2995                 const char *unit,
2996                 const char *filename,
2997                 unsigned line,
2998                 const char *section,
2999                 unsigned section_line,
3000                 const char *lvalue,
3001                 int ltype,
3002                 const char *rvalue,
3003                 void *data,
3004                 void *userdata) {
3005
3006         char*** sv = data, *w, *state;
3007         size_t l;
3008         int r;
3009
3010         assert(filename);
3011         assert(lvalue);
3012         assert(rvalue);
3013         assert(data);
3014
3015         if (isempty(rvalue)) {
3016                 /* Empty assignment resets the list */
3017                 strv_free(*sv);
3018                 *sv = NULL;
3019                 return 0;
3020         }
3021
3022         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
3023                 _cleanup_free_ char *n;
3024                 int offset;
3025
3026                 n = strndup(w, l);
3027                 if (!n)
3028                         return log_oom();
3029
3030                 if (!utf8_is_valid(n)) {
3031                         log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue);
3032                         continue;
3033                 }
3034
3035                 offset = n[0] == '-';
3036                 if (!path_is_absolute(n + offset)) {
3037                         log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Not an absolute path, ignoring: %s", rvalue);
3038                         continue;
3039                 }
3040
3041                 path_kill_slashes(n);
3042
3043                 r = strv_push(sv, n);
3044                 if (r < 0)
3045                         return log_oom();
3046
3047                 n = NULL;
3048         }
3049
3050         return 0;
3051 }
3052
3053 int config_parse_no_new_privileges(
3054                 const char* unit,
3055                 const char *filename,
3056                 unsigned line,
3057                 const char *section,
3058                 unsigned section_line,
3059                 const char *lvalue,
3060                 int ltype,
3061                 const char *rvalue,
3062                 void *data,
3063                 void *userdata) {
3064
3065         ExecContext *c = data;
3066         int k;
3067
3068         assert(filename);
3069         assert(lvalue);
3070         assert(rvalue);
3071         assert(data);
3072
3073         k = parse_boolean(rvalue);
3074         if (k < 0) {
3075                 log_syntax(unit, LOG_ERR, filename, line, -k, "Failed to parse boolean value, ignoring: %s", rvalue);
3076                 return 0;
3077         }
3078
3079         c->no_new_privileges = !!k;
3080         c->no_new_privileges_set = true;
3081
3082         return 0;
3083 }
3084
3085 int config_parse_protect_home(
3086                 const char* unit,
3087                 const char *filename,
3088                 unsigned line,
3089                 const char *section,
3090                 unsigned section_line,
3091                 const char *lvalue,
3092                 int ltype,
3093                 const char *rvalue,
3094                 void *data,
3095                 void *userdata) {
3096
3097         ExecContext *c = data;
3098         int k;
3099
3100         assert(filename);
3101         assert(lvalue);
3102         assert(rvalue);
3103         assert(data);
3104
3105         /* Our enum shall be a superset of booleans, hence first try
3106          * to parse as as boolean, and then as enum */
3107
3108         k = parse_boolean(rvalue);
3109         if (k > 0)
3110                 c->protect_home = PROTECT_HOME_YES;
3111         else if (k == 0)
3112                 c->protect_home = PROTECT_HOME_NO;
3113         else {
3114                 ProtectHome h;
3115
3116                 h = protect_home_from_string(rvalue);
3117                 if (h < 0){
3118                         log_syntax(unit, LOG_ERR, filename, line, -h, "Failed to parse protect home value, ignoring: %s", rvalue);
3119                         return 0;
3120                 }
3121
3122                 c->protect_home = h;
3123         }
3124
3125         return 0;
3126 }
3127
3128 int config_parse_protect_system(
3129                 const char* unit,
3130                 const char *filename,
3131                 unsigned line,
3132                 const char *section,
3133                 unsigned section_line,
3134                 const char *lvalue,
3135                 int ltype,
3136                 const char *rvalue,
3137                 void *data,
3138                 void *userdata) {
3139
3140         ExecContext *c = data;
3141         int k;
3142
3143         assert(filename);
3144         assert(lvalue);
3145         assert(rvalue);
3146         assert(data);
3147
3148         /* Our enum shall be a superset of booleans, hence first try
3149          * to parse as as boolean, and then as enum */
3150
3151         k = parse_boolean(rvalue);
3152         if (k > 0)
3153                 c->protect_system = PROTECT_SYSTEM_YES;
3154         else if (k == 0)
3155                 c->protect_system = PROTECT_SYSTEM_NO;
3156         else {
3157                 ProtectSystem s;
3158
3159                 s = protect_system_from_string(rvalue);
3160                 if (s < 0){
3161                         log_syntax(unit, LOG_ERR, filename, line, -s, "Failed to parse protect system value, ignoring: %s", rvalue);
3162                         return 0;
3163                 }
3164
3165                 c->protect_system = s;
3166         }
3167
3168         return 0;
3169 }
3170
3171 #define FOLLOW_MAX 8
3172
3173 static int open_follow(char **filename, FILE **_f, Set *names, char **_final) {
3174         unsigned c = 0;
3175         int fd, r;
3176         FILE *f;
3177         char *id = NULL;
3178
3179         assert(filename);
3180         assert(*filename);
3181         assert(_f);
3182         assert(names);
3183
3184         /* This will update the filename pointer if the loaded file is
3185          * reached by a symlink. The old string will be freed. */
3186
3187         for (;;) {
3188                 char *target, *name;
3189
3190                 if (c++ >= FOLLOW_MAX)
3191                         return -ELOOP;
3192
3193                 path_kill_slashes(*filename);
3194
3195                 /* Add the file name we are currently looking at to
3196                  * the names of this unit, but only if it is a valid
3197                  * unit name. */
3198                 name = basename(*filename);
3199
3200                 if (unit_name_is_valid(name, TEMPLATE_VALID)) {
3201
3202                         id = set_get(names, name);
3203                         if (!id) {
3204                                 id = strdup(name);
3205                                 if (!id)
3206                                         return -ENOMEM;
3207
3208                                 r = set_consume(names, id);
3209                                 if (r < 0)
3210                                         return r;
3211                         }
3212                 }
3213
3214                 /* Try to open the file name, but don't if its a symlink */
3215                 fd = open(*filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
3216                 if (fd >= 0)
3217                         break;
3218
3219                 if (errno != ELOOP)
3220                         return -errno;
3221
3222                 /* Hmm, so this is a symlink. Let's read the name, and follow it manually */
3223                 r = readlink_and_make_absolute(*filename, &target);
3224                 if (r < 0)
3225                         return r;
3226
3227                 free(*filename);
3228                 *filename = target;
3229         }
3230
3231         f = fdopen(fd, "re");
3232         if (!f) {
3233                 r = -errno;
3234                 safe_close(fd);
3235                 return r;
3236         }
3237
3238         *_f = f;
3239         *_final = id;
3240         return 0;
3241 }
3242
3243 static int merge_by_names(Unit **u, Set *names, const char *id) {
3244         char *k;
3245         int r;
3246
3247         assert(u);
3248         assert(*u);
3249         assert(names);
3250
3251         /* Let's try to add in all symlink names we found */
3252         while ((k = set_steal_first(names))) {
3253
3254                 /* First try to merge in the other name into our
3255                  * unit */
3256                 r = unit_merge_by_name(*u, k);
3257                 if (r < 0) {
3258                         Unit *other;
3259
3260                         /* Hmm, we couldn't merge the other unit into
3261                          * ours? Then let's try it the other way
3262                          * round */
3263
3264                         other = manager_get_unit((*u)->manager, k);
3265                         free(k);
3266
3267                         if (other) {
3268                                 r = unit_merge(other, *u);
3269                                 if (r >= 0) {
3270                                         *u = other;
3271                                         return merge_by_names(u, names, NULL);
3272                                 }
3273                         }
3274
3275                         return r;
3276                 }
3277
3278                 if (id == k)
3279                         unit_choose_id(*u, id);
3280
3281                 free(k);
3282         }
3283
3284         return 0;
3285 }
3286
3287 static int load_from_path(Unit *u, const char *path) {
3288         int r;
3289         _cleanup_set_free_free_ Set *symlink_names = NULL;
3290         _cleanup_fclose_ FILE *f = NULL;
3291         _cleanup_free_ char *filename = NULL;
3292         char *id = NULL;
3293         Unit *merged;
3294         struct stat st;
3295
3296         assert(u);
3297         assert(path);
3298
3299         symlink_names = set_new(string_hash_func, string_compare_func);
3300         if (!symlink_names)
3301                 return -ENOMEM;
3302
3303         if (path_is_absolute(path)) {
3304
3305                 filename = strdup(path);
3306                 if (!filename)
3307                         return -ENOMEM;
3308
3309                 r = open_follow(&filename, &f, symlink_names, &id);
3310                 if (r < 0) {
3311                         free(filename);
3312                         filename = NULL;
3313
3314                         if (r != -ENOENT)
3315                                 return r;
3316                 }
3317
3318         } else  {
3319                 char **p;
3320
3321                 STRV_FOREACH(p, u->manager->lookup_paths.unit_path) {
3322
3323                         /* Instead of opening the path right away, we manually
3324                          * follow all symlinks and add their name to our unit
3325                          * name set while doing so */
3326                         filename = path_make_absolute(path, *p);
3327                         if (!filename)
3328                                 return -ENOMEM;
3329
3330                         if (u->manager->unit_path_cache &&
3331                             !set_get(u->manager->unit_path_cache, filename))
3332                                 r = -ENOENT;
3333                         else
3334                                 r = open_follow(&filename, &f, symlink_names, &id);
3335
3336                         if (r < 0) {
3337                                 free(filename);
3338                                 filename = NULL;
3339
3340                                 if (r != -ENOENT)
3341                                         return r;
3342
3343                                 /* Empty the symlink names for the next run */
3344                                 set_clear_free(symlink_names);
3345                                 continue;
3346                         }
3347
3348                         break;
3349                 }
3350         }
3351
3352         if (!filename)
3353                 /* Hmm, no suitable file found? */
3354                 return 0;
3355
3356         merged = u;
3357         r = merge_by_names(&merged, symlink_names, id);
3358         if (r < 0)
3359                 return r;
3360
3361         if (merged != u) {
3362                 u->load_state = UNIT_MERGED;
3363                 return 0;
3364         }
3365
3366         if (fstat(fileno(f), &st) < 0)
3367                 return -errno;
3368
3369         if (null_or_empty(&st))
3370                 u->load_state = UNIT_MASKED;
3371         else {
3372                 u->load_state = UNIT_LOADED;
3373
3374                 /* Now, parse the file contents */
3375                 r = config_parse(u->id, filename, f, UNIT_VTABLE(u)->sections,
3376                                  config_item_perf_lookup,
3377                                  (void*) load_fragment_gperf_lookup, false, true, u);
3378                 if (r < 0)
3379                         return r;
3380         }
3381
3382         free(u->fragment_path);
3383         u->fragment_path = filename;
3384         filename = NULL;
3385
3386         u->fragment_mtime = timespec_load(&st.st_mtim);
3387
3388         if (u->source_path) {
3389                 if (stat(u->source_path, &st) >= 0)
3390                         u->source_mtime = timespec_load(&st.st_mtim);
3391                 else
3392                         u->source_mtime = 0;
3393         }
3394
3395         return 0;
3396 }
3397
3398 int unit_load_fragment(Unit *u) {
3399         int r;
3400         Iterator i;
3401         const char *t;
3402
3403         assert(u);
3404         assert(u->load_state == UNIT_STUB);
3405         assert(u->id);
3406
3407         /* First, try to find the unit under its id. We always look
3408          * for unit files in the default directories, to make it easy
3409          * to override things by placing things in /etc/systemd/system */
3410         r = load_from_path(u, u->id);
3411         if (r < 0)
3412                 return r;
3413
3414         /* Try to find an alias we can load this with */
3415         if (u->load_state == UNIT_STUB)
3416                 SET_FOREACH(t, u->names, i) {
3417
3418                         if (t == u->id)
3419                                 continue;
3420
3421                         r = load_from_path(u, t);
3422                         if (r < 0)
3423                                 return r;
3424
3425                         if (u->load_state != UNIT_STUB)
3426                                 break;
3427                 }
3428
3429         /* And now, try looking for it under the suggested (originally linked) path */
3430         if (u->load_state == UNIT_STUB && u->fragment_path) {
3431
3432                 r = load_from_path(u, u->fragment_path);
3433                 if (r < 0)
3434                         return r;
3435
3436                 if (u->load_state == UNIT_STUB) {
3437                         /* Hmm, this didn't work? Then let's get rid
3438                          * of the fragment path stored for us, so that
3439                          * we don't point to an invalid location. */
3440                         free(u->fragment_path);
3441                         u->fragment_path = NULL;
3442                 }
3443         }
3444
3445         /* Look for a template */
3446         if (u->load_state == UNIT_STUB && u->instance) {
3447                 _cleanup_free_ char *k;
3448
3449                 k = unit_name_template(u->id);
3450                 if (!k)
3451                         return -ENOMEM;
3452
3453                 r = load_from_path(u, k);
3454                 if (r < 0)
3455                         return r;
3456
3457                 if (u->load_state == UNIT_STUB)
3458                         SET_FOREACH(t, u->names, i) {
3459                                 _cleanup_free_ char *z = NULL;
3460
3461                                 if (t == u->id)
3462                                         continue;
3463
3464                                 z = unit_name_template(t);
3465                                 if (!z)
3466                                         return -ENOMEM;
3467
3468                                 r = load_from_path(u, z);
3469                                 if (r < 0)
3470                                         return r;
3471
3472                                 if (u->load_state != UNIT_STUB)
3473                                         break;
3474                         }
3475         }
3476
3477         return 0;
3478 }
3479
3480 void unit_dump_config_items(FILE *f) {
3481         static const struct {
3482                 const ConfigParserCallback callback;
3483                 const char *rvalue;
3484         } table[] = {
3485 #if !defined(HAVE_SYSV_COMPAT) || !defined(HAVE_SECCOMP) || !defined(HAVE_PAM) || !defined(HAVE_SELINUX) || !defined(HAVE_SMACK) || !defined(HAVE_APPARMOR)
3486                 { config_parse_warn_compat,           "NOTSUPPORTED" },
3487 #endif
3488                 { config_parse_int,                   "INTEGER" },
3489                 { config_parse_unsigned,              "UNSIGNED" },
3490                 { config_parse_iec_size,              "SIZE" },
3491                 { config_parse_iec_off,               "SIZE" },
3492                 { config_parse_si_size,               "SIZE" },
3493                 { config_parse_bool,                  "BOOLEAN" },
3494                 { config_parse_string,                "STRING" },
3495                 { config_parse_path,                  "PATH" },
3496                 { config_parse_unit_path_printf,      "PATH" },
3497                 { config_parse_strv,                  "STRING [...]" },
3498                 { config_parse_exec_nice,             "NICE" },
3499                 { config_parse_exec_oom_score_adjust, "OOMSCOREADJUST" },
3500                 { config_parse_exec_io_class,         "IOCLASS" },
3501                 { config_parse_exec_io_priority,      "IOPRIORITY" },
3502                 { config_parse_exec_cpu_sched_policy, "CPUSCHEDPOLICY" },
3503                 { config_parse_exec_cpu_sched_prio,   "CPUSCHEDPRIO" },
3504                 { config_parse_exec_cpu_affinity,     "CPUAFFINITY" },
3505                 { config_parse_mode,                  "MODE" },
3506                 { config_parse_unit_env_file,         "FILE" },
3507                 { config_parse_output,                "OUTPUT" },
3508                 { config_parse_input,                 "INPUT" },
3509                 { config_parse_log_facility,          "FACILITY" },
3510                 { config_parse_log_level,             "LEVEL" },
3511                 { config_parse_exec_capabilities,     "CAPABILITIES" },
3512                 { config_parse_exec_secure_bits,      "SECUREBITS" },
3513                 { config_parse_bounding_set,          "BOUNDINGSET" },
3514                 { config_parse_limit,                 "LIMIT" },
3515                 { config_parse_unit_deps,             "UNIT [...]" },
3516                 { config_parse_exec,                  "PATH [ARGUMENT [...]]" },
3517                 { config_parse_service_type,          "SERVICETYPE" },
3518                 { config_parse_service_restart,       "SERVICERESTART" },
3519 #ifdef HAVE_SYSV_COMPAT
3520                 { config_parse_sysv_priority,         "SYSVPRIORITY" },
3521 #endif
3522                 { config_parse_kill_mode,             "KILLMODE" },
3523                 { config_parse_kill_signal,           "SIGNAL" },
3524                 { config_parse_socket_listen,         "SOCKET [...]" },
3525                 { config_parse_socket_bind,           "SOCKETBIND" },
3526                 { config_parse_socket_bindtodevice,   "NETWORKINTERFACE" },
3527                 { config_parse_sec,                   "SECONDS" },
3528                 { config_parse_nsec,                  "NANOSECONDS" },
3529                 { config_parse_namespace_path_strv,   "PATH [...]" },
3530                 { config_parse_unit_requires_mounts_for, "PATH [...]" },
3531                 { config_parse_exec_mount_flags,      "MOUNTFLAG [...]" },
3532                 { config_parse_unit_string_printf,    "STRING" },
3533                 { config_parse_trigger_unit,          "UNIT" },
3534                 { config_parse_timer,                 "TIMER" },
3535                 { config_parse_path_spec,             "PATH" },
3536                 { config_parse_notify_access,         "ACCESS" },
3537                 { config_parse_ip_tos,                "TOS" },
3538                 { config_parse_unit_condition_path,   "CONDITION" },
3539                 { config_parse_unit_condition_string, "CONDITION" },
3540                 { config_parse_unit_condition_null,   "CONDITION" },
3541                 { config_parse_unit_slice,            "SLICE" },
3542                 { config_parse_documentation,         "URL" },
3543                 { config_parse_service_timeout,       "SECONDS" },
3544                 { config_parse_failure_action,        "ACTION" },
3545                 { config_parse_set_status,            "STATUS" },
3546                 { config_parse_service_sockets,       "SOCKETS" },
3547                 { config_parse_environ,               "ENVIRON" },
3548 #ifdef HAVE_SECCOMP
3549                 { config_parse_syscall_filter,        "SYSCALLS" },
3550                 { config_parse_syscall_archs,         "ARCHS" },
3551                 { config_parse_syscall_errno,         "ERRNO" },
3552                 { config_parse_address_families,      "FAMILIES" },
3553 #endif
3554                 { config_parse_cpu_shares,            "SHARES" },
3555                 { config_parse_memory_limit,          "LIMIT" },
3556                 { config_parse_device_allow,          "DEVICE" },
3557                 { config_parse_device_policy,         "POLICY" },
3558                 { config_parse_blockio_bandwidth,     "BANDWIDTH" },
3559                 { config_parse_blockio_weight,        "WEIGHT" },
3560                 { config_parse_blockio_device_weight, "DEVICEWEIGHT" },
3561                 { config_parse_long,                  "LONG" },
3562                 { config_parse_socket_service,        "SERVICE" },
3563 #ifdef HAVE_SELINUX
3564                 { config_parse_exec_selinux_context,  "LABEL" },
3565 #endif
3566                 { config_parse_job_mode,              "MODE" },
3567                 { config_parse_job_mode_isolate,      "BOOLEAN" },
3568                 { config_parse_personality,           "PERSONALITY" },
3569         };
3570
3571         const char *prev = NULL;
3572         const char *i;
3573
3574         assert(f);
3575
3576         NULSTR_FOREACH(i, load_fragment_gperf_nulstr) {
3577                 const char *rvalue = "OTHER", *lvalue;
3578                 unsigned j;
3579                 size_t prefix_len;
3580                 const char *dot;
3581                 const ConfigPerfItem *p;
3582
3583                 assert_se(p = load_fragment_gperf_lookup(i, strlen(i)));
3584
3585                 dot = strchr(i, '.');
3586                 lvalue = dot ? dot + 1 : i;
3587                 prefix_len = dot-i;
3588
3589                 if (dot)
3590                         if (!prev || !strneq(prev, i, prefix_len+1)) {
3591                                 if (prev)
3592                                         fputc('\n', f);
3593
3594                                 fprintf(f, "[%.*s]\n", (int) prefix_len, i);
3595                         }
3596
3597                 for (j = 0; j < ELEMENTSOF(table); j++)
3598                         if (p->parse == table[j].callback) {
3599                                 rvalue = table[j].rvalue;
3600                                 break;
3601                         }
3602
3603                 fprintf(f, "%s=%s\n", lvalue, rvalue);
3604                 prev = i;
3605         }
3606 }