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