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