chiark / gitweb /
core: convert PID 1 to libsystemd-bus
[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 "sd-messages.h"
38 #include "unit.h"
39 #include "strv.h"
40 #include "conf-parser.h"
41 #include "load-fragment.h"
42 #include "log.h"
43 #include "ioprio.h"
44 #include "securebits.h"
45 #include "missing.h"
46 #include "unit-name.h"
47 #include "unit-printf.h"
48 #include "utf8.h"
49 #include "path-util.h"
50 #include "syscall-list.h"
51 #include "env-util.h"
52 #include "cgroup.h"
53 #include "bus-util.h"
54 #include "bus-error.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 DEFINE_CONFIG_PARSE_ENUM(config_parse_kill_mode, kill_mode, KillMode, "Failed to parse kill mode");
1037
1038 int config_parse_kill_signal(const char *unit,
1039                              const char *filename,
1040                              unsigned line,
1041                              const char *section,
1042                              const char *lvalue,
1043                              int ltype,
1044                              const char *rvalue,
1045                              void *data,
1046                              void *userdata) {
1047
1048         int *sig = data;
1049         int r;
1050
1051         assert(filename);
1052         assert(lvalue);
1053         assert(rvalue);
1054         assert(sig);
1055
1056         r = signal_from_string_try_harder(rvalue);
1057         if (r <= 0) {
1058                 log_syntax(unit, LOG_ERR, filename, line, -r,
1059                            "Failed to parse kill signal, ignoring: %s", rvalue);
1060                 return 0;
1061         }
1062
1063         *sig = r;
1064         return 0;
1065 }
1066
1067 int config_parse_exec_mount_flags(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         ExecContext *c = data;
1078         char *w;
1079         size_t l;
1080         char *state;
1081         unsigned long flags = 0;
1082
1083         assert(filename);
1084         assert(lvalue);
1085         assert(rvalue);
1086         assert(data);
1087
1088         FOREACH_WORD_SEPARATOR(w, l, rvalue, ", ", state) {
1089                 _cleanup_free_ char *t;
1090
1091                 t = strndup(w, l);
1092                 if (!t)
1093                         return log_oom();
1094
1095                 if (streq(t, "shared"))
1096                         flags |= MS_SHARED;
1097                 else if (streq(t, "slave"))
1098                         flags |= MS_SLAVE;
1099                 else if (streq(w, "private"))
1100                         flags |= MS_PRIVATE;
1101                 else {
1102                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1103                                    "Failed to parse mount flag %s, ignoring: %s",
1104                                    t, rvalue);
1105                         return 0;
1106                 }
1107         }
1108
1109         c->mount_flags = flags;
1110         return 0;
1111 }
1112
1113 int config_parse_timer(const char *unit,
1114                        const char *filename,
1115                        unsigned line,
1116                        const char *section,
1117                        const char *lvalue,
1118                        int ltype,
1119                        const char *rvalue,
1120                        void *data,
1121                        void *userdata) {
1122
1123         Timer *t = data;
1124         usec_t u = 0;
1125         TimerValue *v;
1126         TimerBase b;
1127         CalendarSpec *c = NULL;
1128         clockid_t id;
1129
1130         assert(filename);
1131         assert(lvalue);
1132         assert(rvalue);
1133         assert(data);
1134
1135         if (isempty(rvalue)) {
1136                 /* Empty assignment resets list */
1137                 timer_free_values(t);
1138                 return 0;
1139         }
1140
1141         b = timer_base_from_string(lvalue);
1142         if (b < 0) {
1143                 log_syntax(unit, LOG_ERR, filename, line, -b,
1144                            "Failed to parse timer base, ignoring: %s", lvalue);
1145                 return 0;
1146         }
1147
1148         if (b == TIMER_CALENDAR) {
1149                 if (calendar_spec_from_string(rvalue, &c) < 0) {
1150                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1151                                    "Failed to parse calendar specification, ignoring: %s",
1152                                    rvalue);
1153                         return 0;
1154                 }
1155
1156                 id = CLOCK_REALTIME;
1157         } else {
1158                 if (parse_sec(rvalue, &u) < 0) {
1159                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1160                                    "Failed to parse timer value, ignoring: %s",
1161                                    rvalue);
1162                         return 0;
1163                 }
1164
1165                 id = CLOCK_MONOTONIC;
1166         }
1167
1168         v = new0(TimerValue, 1);
1169         if (!v)
1170                 return log_oom();
1171
1172         v->base = b;
1173         v->clock_id = id;
1174         v->value = u;
1175         v->calendar_spec = c;
1176
1177         LIST_PREPEND(value, t->values, v);
1178
1179         return 0;
1180 }
1181
1182 int config_parse_trigger_unit(
1183                 const char *unit,
1184                 const char *filename,
1185                 unsigned line,
1186                 const char *section,
1187                 const char *lvalue,
1188                 int ltype,
1189                 const char *rvalue,
1190                 void *data,
1191                 void *userdata) {
1192
1193         _cleanup_free_ char *p = NULL;
1194         Unit *u = data;
1195         UnitType type;
1196         int r;
1197
1198         assert(filename);
1199         assert(lvalue);
1200         assert(rvalue);
1201         assert(data);
1202
1203         if (!set_isempty(u->dependencies[UNIT_TRIGGERS])) {
1204                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1205                            "Multiple units to trigger specified, ignoring: %s", rvalue);
1206                 return 0;
1207         }
1208
1209         r = unit_name_printf(u, rvalue, &p);
1210         if (r < 0)
1211                 log_syntax(unit, LOG_ERR, filename, line, -r,
1212                            "Failed to resolve specifiers, ignoring: %s", strerror(-r));
1213
1214         type = unit_name_to_type(p ?: rvalue);
1215         if (type < 0) {
1216                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1217                            "Unit type not valid, ignoring: %s", rvalue);
1218                 return 0;
1219         }
1220
1221         if (type == u->type) {
1222                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1223                            "Trigger cannot be of same type, ignoring: %s", rvalue);
1224                 return 0;
1225         }
1226
1227         r = unit_add_two_dependencies_by_name(u, UNIT_BEFORE, UNIT_TRIGGERS, p ?: rvalue, NULL, true);
1228         if (r < 0) {
1229                 log_syntax(unit, LOG_ERR, filename, line, -r,
1230                            "Failed to add trigger on %s, ignoring: %s", p ?: rvalue, strerror(-r));
1231                 return 0;
1232         }
1233
1234         return 0;
1235 }
1236
1237 int config_parse_path_spec(const char *unit,
1238                            const char *filename,
1239                            unsigned line,
1240                            const char *section,
1241                            const char *lvalue,
1242                            int ltype,
1243                            const char *rvalue,
1244                            void *data,
1245                            void *userdata) {
1246
1247         Path *p = data;
1248         PathSpec *s;
1249         PathType b;
1250         _cleanup_free_ char *k = NULL;
1251         int r;
1252
1253         assert(filename);
1254         assert(lvalue);
1255         assert(rvalue);
1256         assert(data);
1257
1258         if (isempty(rvalue)) {
1259                 /* Empty assignment clears list */
1260                 path_free_specs(p);
1261                 return 0;
1262         }
1263
1264         b = path_type_from_string(lvalue);
1265         if (b < 0) {
1266                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1267                            "Failed to parse path type, ignoring: %s", lvalue);
1268                 return 0;
1269         }
1270
1271         r = unit_full_printf(UNIT(p), rvalue, &k);
1272         if (r < 0) {
1273                 k = strdup(rvalue);
1274                 if (!k)
1275                         return log_oom();
1276                 else
1277                         log_syntax(unit, LOG_ERR, filename, line, -r,
1278                                    "Failed to resolve unit specifiers on %s. Ignoring.",
1279                                    rvalue);
1280         }
1281
1282         if (!path_is_absolute(k)) {
1283                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1284                            "Path is not absolute, ignoring: %s", k);
1285                 return 0;
1286         }
1287
1288         s = new0(PathSpec, 1);
1289         if (!s)
1290                 return log_oom();
1291
1292         s->unit = UNIT(p);
1293         s->path = path_kill_slashes(k);
1294         k = NULL;
1295         s->type = b;
1296         s->inotify_fd = -1;
1297
1298         LIST_PREPEND(spec, p->specs, s);
1299
1300         return 0;
1301 }
1302
1303 int config_parse_socket_service(const char *unit,
1304                                 const char *filename,
1305                                 unsigned line,
1306                                 const char *section,
1307                                 const char *lvalue,
1308                                 int ltype,
1309                                 const char *rvalue,
1310                                 void *data,
1311                                 void *userdata) {
1312
1313         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1314         Socket *s = data;
1315         int r;
1316         Unit *x;
1317         _cleanup_free_ char *p = NULL;
1318
1319         assert(filename);
1320         assert(lvalue);
1321         assert(rvalue);
1322         assert(data);
1323
1324         r = unit_name_printf(UNIT(s), rvalue, &p);
1325         if (r < 0)
1326                 log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve specifiers, ignoring: %s", rvalue);
1327
1328         if (!endswith(p ?: rvalue, ".service")) {
1329                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Unit must be of type service, ignoring: %s", rvalue);
1330                 return 0;
1331         }
1332
1333         r = manager_load_unit(UNIT(s)->manager, p ?: rvalue, NULL, &error, &x);
1334         if (r < 0) {
1335                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load unit %s, ignoring: %s", rvalue, bus_error_message(&error, r));
1336                 return 0;
1337         }
1338
1339         unit_ref_set(&s->service, x);
1340
1341         return 0;
1342 }
1343
1344 int config_parse_service_sockets(const char *unit,
1345                                  const char *filename,
1346                                  unsigned line,
1347                                  const char *section,
1348                                  const char *lvalue,
1349                                  int ltype,
1350                                  const char *rvalue,
1351                                  void *data,
1352                                  void *userdata) {
1353
1354         Service *s = data;
1355         int r;
1356         char *state, *w;
1357         size_t l;
1358
1359         assert(filename);
1360         assert(lvalue);
1361         assert(rvalue);
1362         assert(data);
1363
1364         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
1365                 _cleanup_free_ char *t = NULL, *k = NULL;
1366
1367                 t = strndup(w, l);
1368                 if (!t)
1369                         return log_oom();
1370
1371                 r = unit_name_printf(UNIT(s), t, &k);
1372                 if (r < 0)
1373                         log_syntax(unit, LOG_ERR, filename, line, -r,
1374                                    "Failed to resolve specifiers, ignoring: %s", strerror(-r));
1375
1376                 if (!endswith(k ?: t, ".socket")) {
1377                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1378                                    "Unit must be of type socket, ignoring: %s", k ?: t);
1379                         continue;
1380                 }
1381
1382                 r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_WANTS, UNIT_AFTER, k ?: t, NULL, true);
1383                 if (r < 0)
1384                         log_syntax(unit, LOG_ERR, filename, line, -r,
1385                                    "Failed to add dependency on %s, ignoring: %s",
1386                                    k ?: t, strerror(-r));
1387
1388                 r = unit_add_dependency_by_name(UNIT(s), UNIT_TRIGGERED_BY, k ?: t, NULL, true);
1389                 if (r < 0)
1390                         return r;
1391         }
1392
1393         return 0;
1394 }
1395
1396 int config_parse_service_timeout(const char *unit,
1397                                  const char *filename,
1398                                  unsigned line,
1399                                  const char *section,
1400                                  const char *lvalue,
1401                                  int ltype,
1402                                  const char *rvalue,
1403                                  void *data,
1404                                  void *userdata) {
1405
1406         Service *s = userdata;
1407         int r;
1408
1409         assert(filename);
1410         assert(lvalue);
1411         assert(rvalue);
1412         assert(s);
1413
1414         r = config_parse_sec(unit, filename, line, section, lvalue, ltype,
1415                              rvalue, data, userdata);
1416         if (r < 0)
1417                 return r;
1418
1419         if (streq(lvalue, "TimeoutSec")) {
1420                 s->start_timeout_defined = true;
1421                 s->timeout_stop_usec = s->timeout_start_usec;
1422         } else if (streq(lvalue, "TimeoutStartSec"))
1423                 s->start_timeout_defined = true;
1424
1425         return 0;
1426 }
1427
1428 int config_parse_unit_env_file(const char *unit,
1429                                const char *filename,
1430                                unsigned line,
1431                                const char *section,
1432                                const char *lvalue,
1433                                int ltype,
1434                                const char *rvalue,
1435                                void *data,
1436                                void *userdata) {
1437
1438         char ***env = data;
1439         Unit *u = userdata;
1440         _cleanup_free_ char *n = NULL;
1441         const char *s;
1442         int r;
1443
1444         assert(filename);
1445         assert(lvalue);
1446         assert(rvalue);
1447         assert(data);
1448
1449         if (isempty(rvalue)) {
1450                 /* Empty assignment frees the list */
1451                 strv_free(*env);
1452                 *env = NULL;
1453                 return 0;
1454         }
1455
1456         r = unit_full_printf(u, rvalue, &n);
1457         if (r < 0)
1458                 log_syntax(unit, LOG_ERR, filename, line, r,
1459                            "Failed to resolve specifiers, ignoring: %s", rvalue);
1460
1461         s = n ?: rvalue;
1462         if (!path_is_absolute(s[0] == '-' ? s + 1 : s)) {
1463                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1464                            "Path '%s' is not absolute, ignoring.", s);
1465                 return 0;
1466         }
1467
1468         r = strv_extend(env, s);
1469         if (r < 0)
1470                 return log_oom();
1471
1472         return 0;
1473 }
1474
1475 int config_parse_environ(const char *unit,
1476                          const char *filename,
1477                          unsigned line,
1478                          const char *section,
1479                          const char *lvalue,
1480                          int ltype,
1481                          const char *rvalue,
1482                          void *data,
1483                          void *userdata) {
1484
1485         Unit *u = userdata;
1486         char*** env = data, *w, *state;
1487         size_t l;
1488         _cleanup_free_ char *k = NULL;
1489         int r;
1490
1491         assert(filename);
1492         assert(lvalue);
1493         assert(rvalue);
1494         assert(data);
1495
1496         if (isempty(rvalue)) {
1497                 /* Empty assignment resets the list */
1498                 strv_free(*env);
1499                 *env = NULL;
1500                 return 0;
1501         }
1502
1503         if (u) {
1504                 r = unit_full_printf(u, rvalue, &k);
1505                 if (r < 0)
1506                         log_syntax(unit, LOG_ERR, filename, line, -r,
1507                                    "Failed to resolve specifiers, ignoring: %s", rvalue);
1508         }
1509
1510         if (!k)
1511                 k = strdup(rvalue);
1512         if (!k)
1513                 return log_oom();
1514
1515         FOREACH_WORD_QUOTED(w, l, k, state) {
1516                 _cleanup_free_ char *n;
1517                 char **x;
1518
1519                 n = cunescape_length(w, l);
1520                 if (!n)
1521                         return log_oom();
1522
1523                 if (!env_assignment_is_valid(n)) {
1524                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1525                                    "Invalid environment assignment, ignoring: %s", rvalue);
1526                         continue;
1527                 }
1528
1529                 x = strv_env_set(*env, n);
1530                 if (!x)
1531                         return log_oom();
1532
1533                 strv_free(*env);
1534                 *env = x;
1535         }
1536
1537         return 0;
1538 }
1539
1540 int config_parse_ip_tos(const char *unit,
1541                         const char *filename,
1542                         unsigned line,
1543                         const char *section,
1544                         const char *lvalue,
1545                         int ltype,
1546                         const char *rvalue,
1547                         void *data,
1548                         void *userdata) {
1549
1550         int *ip_tos = data, x;
1551
1552         assert(filename);
1553         assert(lvalue);
1554         assert(rvalue);
1555         assert(data);
1556
1557         x = ip_tos_from_string(rvalue);
1558         if (x < 0) {
1559                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1560                            "Failed to parse IP TOS value, ignoring: %s", rvalue);
1561                 return 0;
1562         }
1563
1564         *ip_tos = x;
1565         return 0;
1566 }
1567
1568 int config_parse_unit_condition_path(const char *unit,
1569                                      const char *filename,
1570                                      unsigned line,
1571                                      const char *section,
1572                                      const char *lvalue,
1573                                      int ltype,
1574                                      const char *rvalue,
1575                                      void *data,
1576                                      void *userdata) {
1577
1578         ConditionType cond = ltype;
1579         Unit *u = data;
1580         bool trigger, negate;
1581         Condition *c;
1582         _cleanup_free_ char *p = NULL;
1583         int r;
1584
1585         assert(filename);
1586         assert(lvalue);
1587         assert(rvalue);
1588         assert(data);
1589
1590         if (isempty(rvalue)) {
1591                 /* Empty assignment resets the list */
1592                 condition_free_list(u->conditions);
1593                 u->conditions = NULL;
1594                 return 0;
1595         }
1596
1597         trigger = rvalue[0] == '|';
1598         if (trigger)
1599                 rvalue++;
1600
1601         negate = rvalue[0] == '!';
1602         if (negate)
1603                 rvalue++;
1604
1605         r = unit_full_printf(u, rvalue, &p);
1606         if (r < 0)
1607                 log_syntax(unit, LOG_ERR, filename, line, -r,
1608                            "Failed to resolve specifiers, ignoring: %s", rvalue);
1609         if (!p) {
1610                 p = strdup(rvalue);
1611                 if (!p)
1612                         return log_oom();
1613         }
1614
1615         if (!path_is_absolute(p)) {
1616                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1617                            "Path in condition not absolute, ignoring: %s", p);
1618                 return 0;
1619         }
1620
1621         c = condition_new(cond, p, trigger, negate);
1622         if (!c)
1623                 return log_oom();
1624
1625         LIST_PREPEND(conditions, u->conditions, c);
1626         return 0;
1627 }
1628
1629 int config_parse_unit_condition_string(const char *unit,
1630                                        const char *filename,
1631                                        unsigned line,
1632                                        const char *section,
1633                                        const char *lvalue,
1634                                        int ltype,
1635                                        const char *rvalue,
1636                                        void *data,
1637                                        void *userdata) {
1638
1639         ConditionType cond = ltype;
1640         Unit *u = data;
1641         bool trigger, negate;
1642         Condition *c;
1643         _cleanup_free_ char *s = NULL;
1644         int r;
1645
1646         assert(filename);
1647         assert(lvalue);
1648         assert(rvalue);
1649         assert(data);
1650
1651         if (isempty(rvalue)) {
1652                 /* Empty assignment resets the list */
1653                 condition_free_list(u->conditions);
1654                 u->conditions = NULL;
1655                 return 0;
1656         }
1657
1658         trigger = rvalue[0] == '|';
1659         if (trigger)
1660                 rvalue++;
1661
1662         negate = rvalue[0] == '!';
1663         if (negate)
1664                 rvalue++;
1665
1666         r = unit_full_printf(u, rvalue, &s);
1667         if (r < 0)
1668                 log_syntax(unit, LOG_ERR, filename, line, -r,
1669                            "Failed to resolve specifiers, ignoring: %s", rvalue);
1670         if (!s) {
1671                 s = strdup(rvalue);
1672                 if (!s)
1673                         return log_oom();
1674         }
1675
1676         c = condition_new(cond, s, trigger, negate);
1677         if (!c)
1678                 return log_oom();
1679
1680         LIST_PREPEND(conditions, u->conditions, c);
1681         return 0;
1682 }
1683
1684 int config_parse_unit_condition_null(const char *unit,
1685                                      const char *filename,
1686                                      unsigned line,
1687                                      const char *section,
1688                                      const char *lvalue,
1689                                      int ltype,
1690                                      const char *rvalue,
1691                                      void *data,
1692                                      void *userdata) {
1693
1694         Unit *u = data;
1695         Condition *c;
1696         bool trigger, negate;
1697         int b;
1698
1699         assert(filename);
1700         assert(lvalue);
1701         assert(rvalue);
1702         assert(data);
1703
1704         if (isempty(rvalue)) {
1705                 /* Empty assignment resets the list */
1706                 condition_free_list(u->conditions);
1707                 u->conditions = NULL;
1708                 return 0;
1709         }
1710
1711         trigger = rvalue[0] == '|';
1712         if (trigger)
1713                 rvalue++;
1714
1715         negate = rvalue[0] == '!';
1716         if (negate)
1717                 rvalue++;
1718
1719         b = parse_boolean(rvalue);
1720         if (b < 0) {
1721                 log_syntax(unit, LOG_ERR, filename, line, -b,
1722                            "Failed to parse boolean value in condition, ignoring: %s",
1723                            rvalue);
1724                 return 0;
1725         }
1726
1727         if (!b)
1728                 negate = !negate;
1729
1730         c = condition_new(CONDITION_NULL, NULL, trigger, negate);
1731         if (!c)
1732                 return log_oom();
1733
1734         LIST_PREPEND(conditions, u->conditions, c);
1735         return 0;
1736 }
1737
1738 DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier");
1739 DEFINE_CONFIG_PARSE_ENUM(config_parse_start_limit_action, start_limit_action, StartLimitAction, "Failed to parse start limit action specifier");
1740
1741 int config_parse_unit_requires_mounts_for(
1742                 const char *unit,
1743                 const char *filename,
1744                 unsigned line,
1745                 const char *section,
1746                 const char *lvalue,
1747                 int ltype,
1748                 const char *rvalue,
1749                 void *data,
1750                 void *userdata) {
1751
1752         Unit *u = userdata;
1753         char *state;
1754         size_t l;
1755         char *w;
1756
1757         assert(filename);
1758         assert(lvalue);
1759         assert(rvalue);
1760         assert(data);
1761
1762         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
1763                 int r;
1764                 _cleanup_free_ char *n;
1765
1766                 n = strndup(w, l);
1767                 if (!n)
1768                         return log_oom();
1769
1770                 if (!utf8_is_valid(n)) {
1771                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1772                                    "Path is not UTF-8 clean, ignoring assignment: %s", rvalue);
1773                         continue;
1774                 }
1775
1776                 r = unit_require_mounts_for(u, n);
1777                 if (r < 0) {
1778                         log_syntax(unit, LOG_ERR, filename, line, r,
1779                                    "Failed to add required mount for, ignoring: %s", rvalue);
1780                         continue;
1781                 }
1782         }
1783
1784         return 0;
1785 }
1786
1787 int config_parse_documentation(const char *unit,
1788                                const char *filename,
1789                                unsigned line,
1790                                const char *section,
1791                                const char *lvalue,
1792                                int ltype,
1793                                const char *rvalue,
1794                                void *data,
1795                                void *userdata) {
1796
1797         Unit *u = userdata;
1798         int r;
1799         char **a, **b;
1800
1801         assert(filename);
1802         assert(lvalue);
1803         assert(rvalue);
1804         assert(u);
1805
1806         if (isempty(rvalue)) {
1807                 /* Empty assignment resets the list */
1808                 strv_free(u->documentation);
1809                 u->documentation = NULL;
1810                 return 0;
1811         }
1812
1813         r = config_parse_unit_strv_printf(unit, filename, line, section, lvalue, ltype,
1814                                           rvalue, data, userdata);
1815         if (r < 0)
1816                 return r;
1817
1818         for (a = b = u->documentation; a && *a; a++) {
1819
1820                 if (is_valid_documentation_url(*a))
1821                         *(b++) = *a;
1822                 else {
1823                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1824                                    "Invalid URL, ignoring: %s", *a);
1825                         free(*a);
1826                 }
1827         }
1828         if (b)
1829                 *b = NULL;
1830
1831         return r;
1832 }
1833
1834 static void syscall_set(uint32_t *p, int nr) {
1835         nr = SYSCALL_TO_INDEX(nr);
1836         p[nr >> 4] |= 1 << (nr & 31);
1837 }
1838
1839 static void syscall_unset(uint32_t *p, int nr) {
1840         nr = SYSCALL_TO_INDEX(nr);
1841         p[nr >> 4] &= ~(1 << (nr & 31));
1842 }
1843
1844 int config_parse_syscall_filter(const char *unit,
1845                                 const char *filename,
1846                                 unsigned line,
1847                                 const char *section,
1848                                 const char *lvalue,
1849                                 int ltype,
1850                                 const char *rvalue,
1851                                 void *data,
1852                                 void *userdata) {
1853
1854         ExecContext *c = data;
1855         Unit *u = userdata;
1856         bool invert = false;
1857         char *w;
1858         size_t l;
1859         char *state;
1860
1861         assert(filename);
1862         assert(lvalue);
1863         assert(rvalue);
1864         assert(u);
1865
1866         if (isempty(rvalue)) {
1867                 /* Empty assignment resets the list */
1868                 free(c->syscall_filter);
1869                 c->syscall_filter = NULL;
1870                 return 0;
1871         }
1872
1873         if (rvalue[0] == '~') {
1874                 invert = true;
1875                 rvalue++;
1876         }
1877
1878         if (!c->syscall_filter) {
1879                 size_t n;
1880
1881                 n = (syscall_max() + 31) >> 4;
1882                 c->syscall_filter = new(uint32_t, n);
1883                 if (!c->syscall_filter)
1884                         return log_oom();
1885
1886                 memset(c->syscall_filter, invert ? 0xFF : 0, n * sizeof(uint32_t));
1887
1888                 /* Add these by default */
1889                 syscall_set(c->syscall_filter, __NR_execve);
1890                 syscall_set(c->syscall_filter, __NR_rt_sigreturn);
1891 #ifdef __NR_sigreturn
1892                 syscall_set(c->syscall_filter, __NR_sigreturn);
1893 #endif
1894                 syscall_set(c->syscall_filter, __NR_exit_group);
1895                 syscall_set(c->syscall_filter, __NR_exit);
1896         }
1897
1898         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
1899                 int id;
1900                 _cleanup_free_ char *t = NULL;
1901
1902                 t = strndup(w, l);
1903                 if (!t)
1904                         return log_oom();
1905
1906                 id = syscall_from_name(t);
1907                 if (id < 0)  {
1908                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1909                                    "Failed to parse syscall, ignoring: %s", t);
1910                         continue;
1911                 }
1912
1913                 if (invert)
1914                         syscall_unset(c->syscall_filter, id);
1915                 else
1916                         syscall_set(c->syscall_filter, id);
1917         }
1918
1919         c->no_new_privileges = true;
1920
1921         return 0;
1922 }
1923
1924 int config_parse_unit_slice(
1925                 const char *unit,
1926                 const char *filename,
1927                 unsigned line,
1928                 const char *section,
1929                 const char *lvalue,
1930                 int ltype,
1931                 const char *rvalue,
1932                 void *data,
1933                 void *userdata) {
1934
1935         _cleanup_free_ char *k = NULL;
1936         Unit *u = userdata, *slice;
1937         int r;
1938
1939         assert(filename);
1940         assert(lvalue);
1941         assert(rvalue);
1942         assert(u);
1943
1944         r = unit_name_printf(u, rvalue, &k);
1945         if (r < 0)
1946                 log_syntax(unit, LOG_ERR, filename, line, -r,
1947                            "Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
1948         if (!k) {
1949                 k = strdup(rvalue);
1950                 if (!k)
1951                         return log_oom();
1952         }
1953
1954         r = manager_load_unit(u->manager, k, NULL, NULL, &slice);
1955         if (r < 0) {
1956                 log_syntax(unit, LOG_ERR, filename, line, -r,
1957                            "Failed to load slice unit %s. Ignoring.", k);
1958                 return 0;
1959         }
1960
1961         if (slice->type != UNIT_SLICE) {
1962                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1963                            "Slice unit %s is not a slice. Ignoring.", k);
1964                 return 0;
1965         }
1966
1967         unit_ref_set(&u->slice, slice);
1968         return 0;
1969 }
1970
1971 DEFINE_CONFIG_PARSE_ENUM(config_parse_device_policy, cgroup_device_policy, CGroupDevicePolicy, "Failed to parse device policy");
1972
1973 int config_parse_cpu_shares(
1974                 const char *unit,
1975                 const char *filename,
1976                 unsigned line,
1977                 const char *section,
1978                 const char *lvalue,
1979                 int ltype,
1980                 const char *rvalue,
1981                 void *data,
1982                 void *userdata) {
1983
1984         CGroupContext *c = data;
1985         unsigned long lu;
1986         int r;
1987
1988         assert(filename);
1989         assert(lvalue);
1990         assert(rvalue);
1991
1992         if (isempty(rvalue)) {
1993                 c->cpu_shares = 1024;
1994                 return 0;
1995         }
1996
1997         r = safe_atolu(rvalue, &lu);
1998         if (r < 0 || lu <= 0) {
1999                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2000                            "CPU shares '%s' invalid. Ignoring.", rvalue);
2001                 return 0;
2002         }
2003
2004         c->cpu_shares = lu;
2005         return 0;
2006 }
2007
2008 int config_parse_memory_limit(
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         off_t bytes;
2021         int r;
2022
2023         if (isempty(rvalue)) {
2024                 c->memory_limit = (uint64_t) -1;
2025                 return 0;
2026         }
2027
2028         assert_cc(sizeof(uint64_t) == sizeof(off_t));
2029
2030         r = parse_bytes(rvalue, &bytes);
2031         if (r < 0) {
2032                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2033                            "Memory limit '%s' invalid. Ignoring.", rvalue);
2034                 return 0;
2035         }
2036
2037         c->memory_limit = (uint64_t) bytes;
2038         return 0;
2039 }
2040
2041 int config_parse_device_allow(
2042                 const char *unit,
2043                 const char *filename,
2044                 unsigned line,
2045                 const char *section,
2046                 const char *lvalue,
2047                 int ltype,
2048                 const char *rvalue,
2049                 void *data,
2050                 void *userdata) {
2051
2052         _cleanup_free_ char *path = NULL;
2053         CGroupContext *c = data;
2054         CGroupDeviceAllow *a;
2055         const char *m;
2056         size_t n;
2057
2058         if (isempty(rvalue)) {
2059                 while (c->device_allow)
2060                         cgroup_context_free_device_allow(c, c->device_allow);
2061
2062                 return 0;
2063         }
2064
2065         n = strcspn(rvalue, WHITESPACE);
2066         path = strndup(rvalue, n);
2067         if (!path)
2068                 return log_oom();
2069
2070         if (!path_startswith(path, "/dev")) {
2071                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2072                            "Invalid device node path '%s'. Ignoring.", path);
2073                 return 0;
2074         }
2075
2076         m = rvalue + n + strspn(rvalue + n, WHITESPACE);
2077         if (isempty(m))
2078                 m = "rwm";
2079
2080         if (!in_charset(m, "rwm")) {
2081                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2082                            "Invalid device rights '%s'. Ignoring.", m);
2083                 return 0;
2084         }
2085
2086         a = new0(CGroupDeviceAllow, 1);
2087         if (!a)
2088                 return log_oom();
2089
2090         a->path = path;
2091         path = NULL;
2092         a->r = !!strchr(m, 'r');
2093         a->w = !!strchr(m, 'w');
2094         a->m = !!strchr(m, 'm');
2095
2096         LIST_PREPEND(device_allow, c->device_allow, a);
2097         return 0;
2098 }
2099
2100 int config_parse_blockio_weight(
2101                 const char *unit,
2102                 const char *filename,
2103                 unsigned line,
2104                 const char *section,
2105                 const char *lvalue,
2106                 int ltype,
2107                 const char *rvalue,
2108                 void *data,
2109                 void *userdata) {
2110
2111         CGroupContext *c = data;
2112         unsigned long lu;
2113         int r;
2114
2115         assert(filename);
2116         assert(lvalue);
2117         assert(rvalue);
2118
2119         if (isempty(rvalue)) {
2120                 c->blockio_weight = 1000;
2121                 return 0;
2122         }
2123
2124         r = safe_atolu(rvalue, &lu);
2125         if (r < 0 || lu < 10 || lu > 1000) {
2126                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2127                            "Block IO weight '%s' invalid. Ignoring.", rvalue);
2128                 return 0;
2129         }
2130
2131         c->blockio_weight = lu;
2132
2133         return 0;
2134 }
2135
2136 int config_parse_blockio_device_weight(
2137                 const char *unit,
2138                 const char *filename,
2139                 unsigned line,
2140                 const char *section,
2141                 const char *lvalue,
2142                 int ltype,
2143                 const char *rvalue,
2144                 void *data,
2145                 void *userdata) {
2146
2147         _cleanup_free_ char *path = NULL;
2148         CGroupBlockIODeviceWeight *w;
2149         CGroupContext *c = data;
2150         unsigned long lu;
2151         const char *weight;
2152         size_t n;
2153         int r;
2154
2155         assert(filename);
2156         assert(lvalue);
2157         assert(rvalue);
2158
2159         if (isempty(rvalue)) {
2160                 while (c->blockio_device_weights)
2161                         cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
2162
2163                 return 0;
2164         }
2165
2166         n = strcspn(rvalue, WHITESPACE);
2167         weight = rvalue + n;
2168         if (!*weight) {
2169                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2170                            "Expected block device and device weight. Ignoring.");
2171                 return 0;
2172         }
2173
2174         path = strndup(rvalue, n);
2175         if (!path)
2176                 return log_oom();
2177
2178         if (!path_startswith(path, "/dev")) {
2179                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2180                            "Invalid device node path '%s'. Ignoring.", path);
2181                 return 0;
2182         }
2183
2184         weight += strspn(weight, WHITESPACE);
2185         r = safe_atolu(weight, &lu);
2186         if (r < 0 || lu < 10 || lu > 1000) {
2187                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2188                            "Block IO weight '%s' invalid. Ignoring.", rvalue);
2189                 return 0;
2190         }
2191
2192
2193         w = new0(CGroupBlockIODeviceWeight, 1);
2194         if (!w)
2195                 return log_oom();
2196
2197         w->path = path;
2198         path = NULL;
2199
2200         w->weight = lu;
2201
2202         LIST_PREPEND(device_weights, c->blockio_device_weights, w);
2203         return 0;
2204 }
2205
2206 int config_parse_blockio_bandwidth(
2207                 const char *unit,
2208                 const char *filename,
2209                 unsigned line,
2210                 const char *section,
2211                 const char *lvalue,
2212                 int ltype,
2213                 const char *rvalue,
2214                 void *data,
2215                 void *userdata) {
2216
2217         _cleanup_free_ char *path = NULL;
2218         CGroupBlockIODeviceBandwidth *b;
2219         CGroupContext *c = data;
2220         const char *bandwidth;
2221         off_t bytes;
2222         bool read;
2223         size_t n;
2224         int r;
2225
2226         assert(filename);
2227         assert(lvalue);
2228         assert(rvalue);
2229
2230         read = streq("BlockIOReadBandwidth", lvalue);
2231
2232         if (isempty(rvalue)) {
2233                 CGroupBlockIODeviceBandwidth *next;
2234
2235                 LIST_FOREACH_SAFE (device_bandwidths, b, next, c->blockio_device_bandwidths)
2236                         if (b->read == read)
2237                                 cgroup_context_free_blockio_device_bandwidth(c, b);
2238
2239                 return 0;
2240         }
2241
2242         n = strcspn(rvalue, WHITESPACE);
2243         bandwidth = rvalue + n;
2244         bandwidth += strspn(bandwidth, WHITESPACE);
2245
2246         if (!*bandwidth) {
2247                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2248                            "Expected space separated pair of device node and bandwidth. Ignoring.");
2249                 return 0;
2250         }
2251
2252         path = strndup(rvalue, n);
2253         if (!path)
2254                 return log_oom();
2255
2256         if (!path_startswith(path, "/dev")) {
2257                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2258                            "Invalid device node path '%s'. Ignoring.", path);
2259                 return 0;
2260         }
2261
2262         r = parse_bytes(bandwidth, &bytes);
2263         if (r < 0 || bytes <= 0) {
2264                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2265                            "Block IO Bandwidth '%s' invalid. Ignoring.", rvalue);
2266                 return 0;
2267         }
2268
2269         b = new0(CGroupBlockIODeviceBandwidth, 1);
2270         if (!b)
2271                 return log_oom();
2272
2273         b->path = path;
2274         path = NULL;
2275         b->bandwidth = (uint64_t) bytes;
2276         b->read = read;
2277
2278         LIST_PREPEND(device_bandwidths, c->blockio_device_bandwidths, b);
2279
2280         return 0;
2281 }
2282
2283 #define FOLLOW_MAX 8
2284
2285 static int open_follow(char **filename, FILE **_f, Set *names, char **_final) {
2286         unsigned c = 0;
2287         int fd, r;
2288         FILE *f;
2289         char *id = NULL;
2290
2291         assert(filename);
2292         assert(*filename);
2293         assert(_f);
2294         assert(names);
2295
2296         /* This will update the filename pointer if the loaded file is
2297          * reached by a symlink. The old string will be freed. */
2298
2299         for (;;) {
2300                 char *target, *name;
2301
2302                 if (c++ >= FOLLOW_MAX)
2303                         return -ELOOP;
2304
2305                 path_kill_slashes(*filename);
2306
2307                 /* Add the file name we are currently looking at to
2308                  * the names of this unit, but only if it is a valid
2309                  * unit name. */
2310                 name = path_get_file_name(*filename);
2311
2312                 if (unit_name_is_valid(name, true)) {
2313
2314                         id = set_get(names, name);
2315                         if (!id) {
2316                                 id = strdup(name);
2317                                 if (!id)
2318                                         return -ENOMEM;
2319
2320                                 r = set_consume(names, id);
2321                                 if (r < 0)
2322                                         return r;
2323                         }
2324                 }
2325
2326                 /* Try to open the file name, but don't if its a symlink */
2327                 fd = open(*filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
2328                 if (fd >= 0)
2329                         break;
2330
2331                 if (errno != ELOOP)
2332                         return -errno;
2333
2334                 /* Hmm, so this is a symlink. Let's read the name, and follow it manually */
2335                 r = readlink_and_make_absolute(*filename, &target);
2336                 if (r < 0)
2337                         return r;
2338
2339                 free(*filename);
2340                 *filename = target;
2341         }
2342
2343         f = fdopen(fd, "re");
2344         if (!f) {
2345                 r = -errno;
2346                 close_nointr_nofail(fd);
2347                 return r;
2348         }
2349
2350         *_f = f;
2351         *_final = id;
2352         return 0;
2353 }
2354
2355 static int merge_by_names(Unit **u, Set *names, const char *id) {
2356         char *k;
2357         int r;
2358
2359         assert(u);
2360         assert(*u);
2361         assert(names);
2362
2363         /* Let's try to add in all symlink names we found */
2364         while ((k = set_steal_first(names))) {
2365
2366                 /* First try to merge in the other name into our
2367                  * unit */
2368                 r = unit_merge_by_name(*u, k);
2369                 if (r < 0) {
2370                         Unit *other;
2371
2372                         /* Hmm, we couldn't merge the other unit into
2373                          * ours? Then let's try it the other way
2374                          * round */
2375
2376                         other = manager_get_unit((*u)->manager, k);
2377                         free(k);
2378
2379                         if (other) {
2380                                 r = unit_merge(other, *u);
2381                                 if (r >= 0) {
2382                                         *u = other;
2383                                         return merge_by_names(u, names, NULL);
2384                                 }
2385                         }
2386
2387                         return r;
2388                 }
2389
2390                 if (id == k)
2391                         unit_choose_id(*u, id);
2392
2393                 free(k);
2394         }
2395
2396         return 0;
2397 }
2398
2399 static int load_from_path(Unit *u, const char *path) {
2400         int r;
2401         _cleanup_set_free_free_ Set *symlink_names = NULL;
2402         _cleanup_fclose_ FILE *f = NULL;
2403         _cleanup_free_ char *filename = NULL;
2404         char *id = NULL;
2405         Unit *merged;
2406         struct stat st;
2407
2408         assert(u);
2409         assert(path);
2410
2411         symlink_names = set_new(string_hash_func, string_compare_func);
2412         if (!symlink_names)
2413                 return -ENOMEM;
2414
2415         if (path_is_absolute(path)) {
2416
2417                 filename = strdup(path);
2418                 if (!filename)
2419                         return -ENOMEM;
2420
2421                 r = open_follow(&filename, &f, symlink_names, &id);
2422                 if (r < 0) {
2423                         free(filename);
2424                         filename = NULL;
2425
2426                         if (r != -ENOENT)
2427                                 return r;
2428                 }
2429
2430         } else  {
2431                 char **p;
2432
2433                 STRV_FOREACH(p, u->manager->lookup_paths.unit_path) {
2434
2435                         /* Instead of opening the path right away, we manually
2436                          * follow all symlinks and add their name to our unit
2437                          * name set while doing so */
2438                         filename = path_make_absolute(path, *p);
2439                         if (!filename)
2440                                 return -ENOMEM;
2441
2442                         if (u->manager->unit_path_cache &&
2443                             !set_get(u->manager->unit_path_cache, filename))
2444                                 r = -ENOENT;
2445                         else
2446                                 r = open_follow(&filename, &f, symlink_names, &id);
2447
2448                         if (r < 0) {
2449                                 free(filename);
2450                                 filename = NULL;
2451
2452                                 if (r != -ENOENT)
2453                                         return r;
2454
2455                                 /* Empty the symlink names for the next run */
2456                                 set_clear_free(symlink_names);
2457                                 continue;
2458                         }
2459
2460                         break;
2461                 }
2462         }
2463
2464         if (!filename)
2465                 /* Hmm, no suitable file found? */
2466                 return 0;
2467
2468         merged = u;
2469         r = merge_by_names(&merged, symlink_names, id);
2470         if (r < 0)
2471                 return r;
2472
2473         if (merged != u) {
2474                 u->load_state = UNIT_MERGED;
2475                 return 0;
2476         }
2477
2478         if (fstat(fileno(f), &st) < 0)
2479                 return -errno;
2480
2481         if (null_or_empty(&st))
2482                 u->load_state = UNIT_MASKED;
2483         else {
2484                 u->load_state = UNIT_LOADED;
2485
2486                 /* Now, parse the file contents */
2487                 r = config_parse(u->id, filename, f, UNIT_VTABLE(u)->sections,
2488                                  config_item_perf_lookup,
2489                                  (void*) load_fragment_gperf_lookup, false, true, u);
2490                 if (r < 0)
2491                         return r;
2492         }
2493
2494         free(u->fragment_path);
2495         u->fragment_path = filename;
2496         filename = NULL;
2497
2498         u->fragment_mtime = timespec_load(&st.st_mtim);
2499
2500         if (u->source_path) {
2501                 if (stat(u->source_path, &st) >= 0)
2502                         u->source_mtime = timespec_load(&st.st_mtim);
2503                 else
2504                         u->source_mtime = 0;
2505         }
2506
2507         return 0;
2508 }
2509
2510 int unit_load_fragment(Unit *u) {
2511         int r;
2512         Iterator i;
2513         const char *t;
2514
2515         assert(u);
2516         assert(u->load_state == UNIT_STUB);
2517         assert(u->id);
2518
2519         /* First, try to find the unit under its id. We always look
2520          * for unit files in the default directories, to make it easy
2521          * to override things by placing things in /etc/systemd/system */
2522         r = load_from_path(u, u->id);
2523         if (r < 0)
2524                 return r;
2525
2526         /* Try to find an alias we can load this with */
2527         if (u->load_state == UNIT_STUB)
2528                 SET_FOREACH(t, u->names, i) {
2529
2530                         if (t == u->id)
2531                                 continue;
2532
2533                         r = load_from_path(u, t);
2534                         if (r < 0)
2535                                 return r;
2536
2537                         if (u->load_state != UNIT_STUB)
2538                                 break;
2539                 }
2540
2541         /* And now, try looking for it under the suggested (originally linked) path */
2542         if (u->load_state == UNIT_STUB && u->fragment_path) {
2543
2544                 r = load_from_path(u, u->fragment_path);
2545                 if (r < 0)
2546                         return r;
2547
2548                 if (u->load_state == UNIT_STUB) {
2549                         /* Hmm, this didn't work? Then let's get rid
2550                          * of the fragment path stored for us, so that
2551                          * we don't point to an invalid location. */
2552                         free(u->fragment_path);
2553                         u->fragment_path = NULL;
2554                 }
2555         }
2556
2557         /* Look for a template */
2558         if (u->load_state == UNIT_STUB && u->instance) {
2559                 char *k;
2560
2561                 k = unit_name_template(u->id);
2562                 if (!k)
2563                         return -ENOMEM;
2564
2565                 r = load_from_path(u, k);
2566                 free(k);
2567
2568                 if (r < 0)
2569                         return r;
2570
2571                 if (u->load_state == UNIT_STUB)
2572                         SET_FOREACH(t, u->names, i) {
2573
2574                                 if (t == u->id)
2575                                         continue;
2576
2577                                 k = unit_name_template(t);
2578                                 if (!k)
2579                                         return -ENOMEM;
2580
2581                                 r = load_from_path(u, k);
2582                                 free(k);
2583
2584                                 if (r < 0)
2585                                         return r;
2586
2587                                 if (u->load_state != UNIT_STUB)
2588                                         break;
2589                         }
2590         }
2591
2592         return 0;
2593 }
2594
2595 void unit_dump_config_items(FILE *f) {
2596         static const struct {
2597                 const ConfigParserCallback callback;
2598                 const char *rvalue;
2599         } table[] = {
2600                 { config_parse_int,                   "INTEGER" },
2601                 { config_parse_unsigned,              "UNSIGNED" },
2602                 { config_parse_bytes_size,            "SIZE" },
2603                 { config_parse_bool,                  "BOOLEAN" },
2604                 { config_parse_string,                "STRING" },
2605                 { config_parse_path,                  "PATH" },
2606                 { config_parse_unit_path_printf,      "PATH" },
2607                 { config_parse_strv,                  "STRING [...]" },
2608                 { config_parse_exec_nice,             "NICE" },
2609                 { config_parse_exec_oom_score_adjust, "OOMSCOREADJUST" },
2610                 { config_parse_exec_io_class,         "IOCLASS" },
2611                 { config_parse_exec_io_priority,      "IOPRIORITY" },
2612                 { config_parse_exec_cpu_sched_policy, "CPUSCHEDPOLICY" },
2613                 { config_parse_exec_cpu_sched_prio,   "CPUSCHEDPRIO" },
2614                 { config_parse_exec_cpu_affinity,     "CPUAFFINITY" },
2615                 { config_parse_mode,                  "MODE" },
2616                 { config_parse_unit_env_file,         "FILE" },
2617                 { config_parse_output,                "OUTPUT" },
2618                 { config_parse_input,                 "INPUT" },
2619                 { config_parse_facility,              "FACILITY" },
2620                 { config_parse_level,                 "LEVEL" },
2621                 { config_parse_exec_capabilities,     "CAPABILITIES" },
2622                 { config_parse_exec_secure_bits,      "SECUREBITS" },
2623                 { config_parse_bounding_set,          "BOUNDINGSET" },
2624                 { config_parse_limit,                 "LIMIT" },
2625                 { config_parse_unit_deps,             "UNIT [...]" },
2626                 { config_parse_exec,                  "PATH [ARGUMENT [...]]" },
2627                 { config_parse_service_type,          "SERVICETYPE" },
2628                 { config_parse_service_restart,       "SERVICERESTART" },
2629 #ifdef HAVE_SYSV_COMPAT
2630                 { config_parse_sysv_priority,         "SYSVPRIORITY" },
2631 #else
2632                 { config_parse_warn_compat,           "NOTSUPPORTED" },
2633 #endif
2634                 { config_parse_kill_mode,             "KILLMODE" },
2635                 { config_parse_kill_signal,           "SIGNAL" },
2636                 { config_parse_socket_listen,         "SOCKET [...]" },
2637                 { config_parse_socket_bind,           "SOCKETBIND" },
2638                 { config_parse_socket_bindtodevice,   "NETWORKINTERFACE" },
2639                 { config_parse_sec,                   "SECONDS" },
2640                 { config_parse_nsec,                  "NANOSECONDS" },
2641                 { config_parse_path_strv,             "PATH [...]" },
2642                 { config_parse_unit_requires_mounts_for, "PATH [...]" },
2643                 { config_parse_exec_mount_flags,      "MOUNTFLAG [...]" },
2644                 { config_parse_unit_string_printf,    "STRING" },
2645                 { config_parse_trigger_unit,          "UNIT" },
2646                 { config_parse_timer,                 "TIMER" },
2647                 { config_parse_path_spec,             "PATH" },
2648                 { config_parse_notify_access,         "ACCESS" },
2649                 { config_parse_ip_tos,                "TOS" },
2650                 { config_parse_unit_condition_path,   "CONDITION" },
2651                 { config_parse_unit_condition_string, "CONDITION" },
2652                 { config_parse_unit_condition_null,   "CONDITION" },
2653                 { config_parse_unit_slice,            "SLICE" },
2654                 { config_parse_documentation,         "URL" },
2655                 { config_parse_service_timeout,       "SECONDS" },
2656                 { config_parse_start_limit_action,    "ACTION" },
2657                 { config_parse_set_status,            "STATUS" },
2658                 { config_parse_service_sockets,       "SOCKETS" },
2659                 { config_parse_environ,               "ENVIRON" },
2660                 { config_parse_syscall_filter,        "SYSCALL" },
2661                 { config_parse_cpu_shares,            "SHARES" },
2662                 { config_parse_memory_limit,          "LIMIT" },
2663                 { config_parse_device_allow,          "DEVICE" },
2664                 { config_parse_device_policy,         "POLICY" },
2665                 { config_parse_blockio_bandwidth,     "BANDWIDTH" },
2666                 { config_parse_blockio_weight,        "WEIGHT" },
2667                 { config_parse_blockio_device_weight, "DEVICEWEIGHT" },
2668                 { config_parse_long,                  "LONG" },
2669                 { config_parse_socket_service,        "SERVICE" },
2670         };
2671
2672         const char *prev = NULL;
2673         const char *i;
2674
2675         assert(f);
2676
2677         NULSTR_FOREACH(i, load_fragment_gperf_nulstr) {
2678                 const char *rvalue = "OTHER", *lvalue;
2679                 unsigned j;
2680                 size_t prefix_len;
2681                 const char *dot;
2682                 const ConfigPerfItem *p;
2683
2684                 assert_se(p = load_fragment_gperf_lookup(i, strlen(i)));
2685
2686                 dot = strchr(i, '.');
2687                 lvalue = dot ? dot + 1 : i;
2688                 prefix_len = dot-i;
2689
2690                 if (dot)
2691                         if (!prev || !strneq(prev, i, prefix_len+1)) {
2692                                 if (prev)
2693                                         fputc('\n', f);
2694
2695                                 fprintf(f, "[%.*s]\n", (int) prefix_len, i);
2696                         }
2697
2698                 for (j = 0; j < ELEMENTSOF(table); j++)
2699                         if (p->parse == table[j].callback) {
2700                                 rvalue = table[j].rvalue;
2701                                 break;
2702                         }
2703
2704                 fprintf(f, "%s=%s\n", lvalue, rvalue);
2705                 prev = i;
2706         }
2707 }