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