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