chiark / gitweb /
build-sys: drop -Wunsafe-loop-optimizations
[elogind.git] / load-fragment.c
1 /*-*- Mode: C; c-basic-offset: 8 -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 2 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <linux/oom.h>
23 #include <assert.h>
24 #include <errno.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28 #include <sched.h>
29 #include <sys/prctl.h>
30
31 #include "unit.h"
32 #include "strv.h"
33 #include "conf-parser.h"
34 #include "load-fragment.h"
35 #include "log.h"
36 #include "ioprio.h"
37 #include "securebits.h"
38 #include "missing.h"
39
40 static int config_parse_deps(
41                 const char *filename,
42                 unsigned line,
43                 const char *section,
44                 const char *lvalue,
45                 const char *rvalue,
46                 void *data,
47                 void *userdata) {
48
49         UnitDependency d = PTR_TO_UINT(data);
50         Unit *u = userdata;
51         char *w;
52         size_t l;
53         char *state;
54
55         assert(filename);
56         assert(lvalue);
57         assert(rvalue);
58
59         FOREACH_WORD(w, l, rvalue, state) {
60                 char *t;
61                 int r;
62
63                 if (!(t = strndup(w, l)))
64                         return -ENOMEM;
65
66                 r = unit_add_dependency_by_name(u, d, t);
67                 free(t);
68
69                 if (r < 0)
70                         return r;
71         }
72
73         return 0;
74 }
75
76 static int config_parse_names(
77                 const char *filename,
78                 unsigned line,
79                 const char *section,
80                 const char *lvalue,
81                 const char *rvalue,
82                 void *data,
83                 void *userdata) {
84
85         Unit *u = userdata;
86         char *w;
87         size_t l;
88         char *state;
89
90         assert(filename);
91         assert(lvalue);
92         assert(rvalue);
93         assert(data);
94
95         FOREACH_WORD(w, l, rvalue, state) {
96                 char *t;
97                 int r;
98
99                 if (!(t = strndup(w, l)))
100                         return -ENOMEM;
101
102                 r = unit_merge_by_name(u, t);
103                 free(t);
104
105                 if (r < 0)
106                         return r;
107         }
108
109         return 0;
110 }
111
112 static int config_parse_listen(
113                 const char *filename,
114                 unsigned line,
115                 const char *section,
116                 const char *lvalue,
117                 const char *rvalue,
118                 void *data,
119                 void *userdata) {
120
121         int r;
122         SocketPort *p;
123         Socket *s;
124
125         assert(filename);
126         assert(lvalue);
127         assert(rvalue);
128         assert(data);
129
130         s = (Socket*) data;
131
132         if (!(p = new0(SocketPort, 1)))
133                 return -ENOMEM;
134
135         if (streq(lvalue, "ListenFIFO")) {
136                 p->type = SOCKET_FIFO;
137
138                 if (!(p->path = strdup(rvalue))) {
139                         free(p);
140                         return -ENOMEM;
141                 }
142         } else {
143                 p->type = SOCKET_SOCKET;
144
145                 if ((r = socket_address_parse(&p->address, rvalue)) < 0) {
146                         log_error("[%s:%u] Failed to parse address value: %s", filename, line, rvalue);
147                         free(p);
148                         return r;
149                 }
150
151                 if (streq(lvalue, "ListenStream"))
152                         p->address.type = SOCK_STREAM;
153                 else if (streq(lvalue, "ListenDatagram"))
154                         p->address.type = SOCK_DGRAM;
155                 else {
156                         assert(streq(lvalue, "ListenSequentialPacket"));
157                         p->address.type = SOCK_SEQPACKET;
158                 }
159
160                 if (socket_address_family(&p->address) != AF_LOCAL && p->address.type == SOCK_SEQPACKET) {
161                         free(p);
162                         return -EPROTONOSUPPORT;
163                 }
164         }
165
166         p->fd = -1;
167         LIST_PREPEND(SocketPort, port, s->ports, p);
168
169         return 0;
170 }
171
172 static int config_parse_socket_bind(
173                 const char *filename,
174                 unsigned line,
175                 const char *section,
176                 const char *lvalue,
177                 const char *rvalue,
178                 void *data,
179                 void *userdata) {
180
181         int r;
182         Socket *s;
183
184         assert(filename);
185         assert(lvalue);
186         assert(rvalue);
187         assert(data);
188
189         s = (Socket*) data;
190
191         if ((r = parse_boolean(rvalue)) < 0) {
192                 log_error("[%s:%u] Failed to parse bind IPv6 only value: %s", filename, line, rvalue);
193                 return r;
194         }
195
196         s->bind_ipv6_only = r ? SOCKET_ADDRESS_IPV6_ONLY : SOCKET_ADDRESS_BOTH;
197
198         return 0;
199 }
200
201 static int config_parse_nice(
202                 const char *filename,
203                 unsigned line,
204                 const char *section,
205                 const char *lvalue,
206                 const char *rvalue,
207                 void *data,
208                 void *userdata) {
209
210         ExecContext *c = data;
211         int priority, r;
212
213         assert(filename);
214         assert(lvalue);
215         assert(rvalue);
216         assert(data);
217
218         if ((r = safe_atoi(rvalue, &priority)) < 0) {
219                 log_error("[%s:%u] Failed to parse nice priority: %s", filename, line, rvalue);
220                 return r;
221         }
222
223         if (priority < PRIO_MIN || priority >= PRIO_MAX) {
224                 log_error("[%s:%u] Nice priority out of range: %s", filename, line, rvalue);
225                 return -ERANGE;
226         }
227
228         c->nice = priority;
229         c->nice_set = false;
230
231         return 0;
232 }
233
234 static int config_parse_oom_adjust(
235                 const char *filename,
236                 unsigned line,
237                 const char *section,
238                 const char *lvalue,
239                 const char *rvalue,
240                 void *data,
241                 void *userdata) {
242
243         ExecContext *c = data;
244         int oa, r;
245
246         assert(filename);
247         assert(lvalue);
248         assert(rvalue);
249         assert(data);
250
251         if ((r = safe_atoi(rvalue, &oa)) < 0) {
252                 log_error("[%s:%u] Failed to parse OOM adjust value: %s", filename, line, rvalue);
253                 return r;
254         }
255
256         if (oa < OOM_DISABLE || oa > OOM_ADJUST_MAX) {
257                 log_error("[%s:%u] OOM adjust value out of range: %s", filename, line, rvalue);
258                 return -ERANGE;
259         }
260
261         c->oom_adjust = oa;
262         c->oom_adjust_set = true;
263
264         return 0;
265 }
266
267 static int config_parse_mode(
268                 const char *filename,
269                 unsigned line,
270                 const char *section,
271                 const char *lvalue,
272                 const char *rvalue,
273                 void *data,
274                 void *userdata) {
275
276         mode_t *m = data;
277         long l;
278         char *x = NULL;
279
280         assert(filename);
281         assert(lvalue);
282         assert(rvalue);
283         assert(data);
284
285         errno = 0;
286         l = strtol(rvalue, &x, 8);
287         if (!x || *x || errno) {
288                 log_error("[%s:%u] Failed to parse mode value: %s", filename, line, rvalue);
289                 return errno ? -errno : -EINVAL;
290         }
291
292         if (l < 0000 || l > 07777) {
293                 log_error("[%s:%u] mode value out of range: %s", filename, line, rvalue);
294                 return -ERANGE;
295         }
296
297         *m = (mode_t) l;
298         return 0;
299 }
300
301 static int config_parse_exec(
302                 const char *filename,
303                 unsigned line,
304                 const char *section,
305                 const char *lvalue,
306                 const char *rvalue,
307                 void *data,
308                 void *userdata) {
309
310         ExecCommand **e = data, *nce = NULL;
311         char **n;
312         char *w;
313         unsigned k;
314         size_t l;
315         char *state;
316
317         assert(filename);
318         assert(lvalue);
319         assert(rvalue);
320         assert(data);
321
322         k = 0;
323         FOREACH_WORD_QUOTED(w, l, rvalue, state)
324                 k++;
325
326         if (!(n = new(char*, k+1)))
327                 return -ENOMEM;
328
329         k = 0;
330         FOREACH_WORD_QUOTED(w, l, rvalue, state)
331                 if (!(n[k++] = strndup(w, l)))
332                         goto fail;
333
334         n[k] = NULL;
335
336         if (!n[0] || !path_is_absolute(n[0])) {
337                 log_error("[%s:%u] Invalid executable path in command line: %s", filename, line, rvalue);
338                 strv_free(n);
339                 return -EINVAL;
340         }
341
342         if (!(nce = new0(ExecCommand, 1)))
343                 goto fail;
344
345         nce->argv = n;
346         if (!(nce->path = strdup(n[0])))
347                 goto fail;
348
349         exec_command_append_list(e, nce);
350
351         return 0;
352
353 fail:
354         for (; k > 0; k--)
355                 free(n[k-1]);
356         free(n);
357
358         free(nce);
359
360         return -ENOMEM;
361 }
362
363 static int config_parse_usec(
364                 const char *filename,
365                 unsigned line,
366                 const char *section,
367                 const char *lvalue,
368                 const char *rvalue,
369                 void *data,
370                 void *userdata) {
371
372         usec_t *usec = data;
373         unsigned long long u;
374         int r;
375
376         assert(filename);
377         assert(lvalue);
378         assert(rvalue);
379         assert(data);
380
381         if ((r = safe_atollu(rvalue, &u)) < 0) {
382                 log_error("[%s:%u] Failed to parse time value: %s", filename, line, rvalue);
383                 return r;
384         }
385
386         /* We actually assume the user configures seconds. Later on we
387          * might choose to support suffixes for time values, to
388          * configure bigger or smaller units */
389
390         *usec = u * USEC_PER_SEC;
391
392         return 0;
393 }
394
395 static int config_parse_service_type(
396                 const char *filename,
397                 unsigned line,
398                 const char *section,
399                 const char *lvalue,
400                 const char *rvalue,
401                 void *data,
402                 void *userdata) {
403
404         Service *s = data;
405         ServiceType x;
406
407         assert(filename);
408         assert(lvalue);
409         assert(rvalue);
410         assert(data);
411
412         if ((x = service_type_from_string(rvalue)) < 0) {
413                 log_error("[%s:%u] Failed to parse service type: %s", filename, line, rvalue);
414                 return -EBADMSG;
415         }
416
417         s->type = x;
418
419         return 0;
420 }
421
422 static int config_parse_service_restart(
423                 const char *filename,
424                 unsigned line,
425                 const char *section,
426                 const char *lvalue,
427                 const char *rvalue,
428                 void *data,
429                 void *userdata) {
430
431         Service *s = data;
432         ServiceRestart x;
433
434         assert(filename);
435         assert(lvalue);
436         assert(rvalue);
437         assert(data);
438
439         if ((x = service_restart_from_string(rvalue)) < 0) {
440                 log_error("[%s:%u] Failed to parse service restart specifier: %s", filename, line, rvalue);
441                 return -EBADMSG;
442         }
443
444         s->restart = x;
445
446         return 0;
447 }
448
449 static int config_parse_bindtodevice(
450                 const char *filename,
451                 unsigned line,
452                 const char *section,
453                 const char *lvalue,
454                 const char *rvalue,
455                 void *data,
456                 void *userdata) {
457
458         Socket *s = data;
459         char *n;
460
461         assert(filename);
462         assert(lvalue);
463         assert(rvalue);
464         assert(data);
465
466         if (rvalue[0] && !streq(rvalue, "*")) {
467                 if (!(n = strdup(rvalue)))
468                         return -ENOMEM;
469         } else
470                 n = NULL;
471
472         free(s->bind_to_device);
473         s->bind_to_device = n;
474
475         return 0;
476 }
477
478 static int config_parse_output(
479                 const char *filename,
480                 unsigned line,
481                 const char *section,
482                 const char *lvalue,
483                 const char *rvalue,
484                 void *data,
485                 void *userdata) {
486
487         ExecOutput *o = data, x;
488
489         assert(filename);
490         assert(lvalue);
491         assert(rvalue);
492         assert(data);
493
494         if ((x = exec_output_from_string(rvalue)) < 0) {
495                 log_error("[%s:%u] Failed to parse output specifier: %s", filename, line, rvalue);
496                 return -EBADMSG;
497         }
498
499         *o = x;
500
501         return 0;
502 }
503
504 static int config_parse_input(
505                 const char *filename,
506                 unsigned line,
507                 const char *section,
508                 const char *lvalue,
509                 const char *rvalue,
510                 void *data,
511                 void *userdata) {
512
513         ExecInput *i = data, x;
514
515         assert(filename);
516         assert(lvalue);
517         assert(rvalue);
518         assert(data);
519
520         if ((x = exec_input_from_string(rvalue)) < 0) {
521                 log_error("[%s:%u] Failed to parse input specifier: %s", filename, line, rvalue);
522                 return -EBADMSG;
523         }
524
525         *i = x;
526
527         return 0;
528 }
529
530 static int config_parse_facility(
531                 const char *filename,
532                 unsigned line,
533                 const char *section,
534                 const char *lvalue,
535                 const char *rvalue,
536                 void *data,
537                 void *userdata) {
538
539
540         int *o = data, x;
541
542         assert(filename);
543         assert(lvalue);
544         assert(rvalue);
545         assert(data);
546
547         if ((x = log_facility_from_string(rvalue)) < 0)
548
549                 /* Second try, let's see if this is a number. */
550                 if (safe_atoi(rvalue, &x) < 0 || !log_facility_to_string(x)) {
551                         log_error("[%s:%u] Failed to parse log facility: %s", filename, line, rvalue);
552                         return -EBADMSG;
553                 }
554
555         *o = LOG_MAKEPRI(x, LOG_PRI(*o));
556
557         return 0;
558 }
559
560 static int config_parse_level(
561                 const char *filename,
562                 unsigned line,
563                 const char *section,
564                 const char *lvalue,
565                 const char *rvalue,
566                 void *data,
567                 void *userdata) {
568
569
570         int *o = data, x;
571
572         assert(filename);
573         assert(lvalue);
574         assert(rvalue);
575         assert(data);
576
577         if ((x = log_level_from_string(rvalue)) < 0)
578
579                 /* Second try, let's see if this is a number. */
580                 if (safe_atoi(rvalue, &x) < 0 || !log_level_to_string(x)) {
581                         log_error("[%s:%u] Failed to parse log level: %s", filename, line, rvalue);
582                         return -EBADMSG;
583                 }
584
585         *o = LOG_MAKEPRI(LOG_FAC(*o), x);
586         return 0;
587 }
588
589 static int config_parse_io_class(
590                 const char *filename,
591                 unsigned line,
592                 const char *section,
593                 const char *lvalue,
594                 const char *rvalue,
595                 void *data,
596                 void *userdata) {
597
598         ExecContext *c = data;
599         int x;
600
601         assert(filename);
602         assert(lvalue);
603         assert(rvalue);
604         assert(data);
605
606         if ((x = ioprio_class_from_string(rvalue)) < 0)
607
608                 /* Second try, let's see if this is a number. */
609                 if (safe_atoi(rvalue, &x) < 0 || !ioprio_class_to_string(x)) {
610                         log_error("[%s:%u] Failed to parse IO scheduling class: %s", filename, line, rvalue);
611                         return -EBADMSG;
612                 }
613
614         c->ioprio = IOPRIO_PRIO_VALUE(x, IOPRIO_PRIO_DATA(c->ioprio));
615         c->ioprio_set = true;
616
617         return 0;
618 }
619
620 static int config_parse_io_priority(
621                 const char *filename,
622                 unsigned line,
623                 const char *section,
624                 const char *lvalue,
625                 const char *rvalue,
626                 void *data,
627                 void *userdata) {
628
629         ExecContext *c = data;
630         int i;
631
632         assert(filename);
633         assert(lvalue);
634         assert(rvalue);
635         assert(data);
636
637         if (safe_atoi(rvalue, &i) < 0 || i < 0 || i >= IOPRIO_BE_NR) {
638                 log_error("[%s:%u] Failed to parse io priority: %s", filename, line, rvalue);
639                 return -EBADMSG;
640         }
641
642         c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_PRIO_CLASS(c->ioprio), i);
643         c->ioprio_set = true;
644
645         return 0;
646 }
647
648 static int config_parse_cpu_sched_policy(
649                 const char *filename,
650                 unsigned line,
651                 const char *section,
652                 const char *lvalue,
653                 const char *rvalue,
654                 void *data,
655                 void *userdata) {
656
657
658         ExecContext *c = data;
659         int x;
660
661         assert(filename);
662         assert(lvalue);
663         assert(rvalue);
664         assert(data);
665
666         if ((x = sched_policy_from_string(rvalue)) < 0)
667
668                 /* Second try, let's see if this is a number. */
669                 if (safe_atoi(rvalue, &x) < 0 || !sched_policy_to_string(x)) {
670                         log_error("[%s:%u] Failed to parse CPU scheduling policy: %s", filename, line, rvalue);
671                         return -EBADMSG;
672                 }
673
674         c->cpu_sched_policy = x;
675         c->cpu_sched_set = true;
676
677         return 0;
678 }
679
680 static int config_parse_cpu_sched_prio(
681                 const char *filename,
682                 unsigned line,
683                 const char *section,
684                 const char *lvalue,
685                 const char *rvalue,
686                 void *data,
687                 void *userdata) {
688
689         ExecContext *c = data;
690         int i;
691
692         assert(filename);
693         assert(lvalue);
694         assert(rvalue);
695         assert(data);
696
697         /* On Linux RR/FIFO have the same range */
698         if (safe_atoi(rvalue, &i) < 0 || i < sched_get_priority_min(SCHED_RR) || i > sched_get_priority_max(SCHED_RR)) {
699                 log_error("[%s:%u] Failed to parse CPU scheduling priority: %s", filename, line, rvalue);
700                 return -EBADMSG;
701         }
702
703         c->cpu_sched_priority = i;
704         c->cpu_sched_set = true;
705
706         return 0;
707 }
708
709 static int config_parse_cpu_affinity(
710                 const char *filename,
711                 unsigned line,
712                 const char *section,
713                 const char *lvalue,
714                 const char *rvalue,
715                 void *data,
716                 void *userdata) {
717
718         ExecContext *c = data;
719         char *w;
720         size_t l;
721         char *state;
722
723         assert(filename);
724         assert(lvalue);
725         assert(rvalue);
726         assert(data);
727
728         FOREACH_WORD(w, l, rvalue, state) {
729                 char *t;
730                 int r;
731                 unsigned cpu;
732
733                 if (!(t = strndup(w, l)))
734                         return -ENOMEM;
735
736                 r = safe_atou(t, &cpu);
737                 free(t);
738
739                 if (r < 0 || cpu >= CPU_SETSIZE) {
740                         log_error("[%s:%u] Failed to parse CPU affinity: %s", filename, line, rvalue);
741                         return -EBADMSG;
742                 }
743
744                 CPU_SET(cpu, &c->cpu_affinity);
745         }
746
747         c->cpu_affinity_set = true;
748
749         return 0;
750 }
751
752 static int config_parse_capabilities(
753                 const char *filename,
754                 unsigned line,
755                 const char *section,
756                 const char *lvalue,
757                 const char *rvalue,
758                 void *data,
759                 void *userdata) {
760
761         ExecContext *c = data;
762         cap_t cap;
763
764         assert(filename);
765         assert(lvalue);
766         assert(rvalue);
767         assert(data);
768
769         if (!(cap = cap_from_text(rvalue))) {
770                 if (errno == ENOMEM)
771                         return -ENOMEM;
772
773                 log_error("[%s:%u] Failed to parse capabilities: %s", filename, line, rvalue);
774                 return -EBADMSG;
775         }
776
777         if (c->capabilities)
778                 cap_free(c->capabilities);
779         c->capabilities = cap;
780
781         return 0;
782 }
783
784 static int config_parse_secure_bits(
785                 const char *filename,
786                 unsigned line,
787                 const char *section,
788                 const char *lvalue,
789                 const char *rvalue,
790                 void *data,
791                 void *userdata) {
792
793         ExecContext *c = data;
794         char *w;
795         size_t l;
796         char *state;
797
798         assert(filename);
799         assert(lvalue);
800         assert(rvalue);
801         assert(data);
802
803         FOREACH_WORD(w, l, rvalue, state) {
804                 if (first_word(w, "keep-caps"))
805                         c->secure_bits |= SECURE_KEEP_CAPS;
806                 else if (first_word(w, "keep-caps-locked"))
807                         c->secure_bits |= SECURE_KEEP_CAPS_LOCKED;
808                 else if (first_word(w, "no-setuid-fixup"))
809                         c->secure_bits |= SECURE_NO_SETUID_FIXUP;
810                 else if (first_word(w, "no-setuid-fixup-locked"))
811                         c->secure_bits |= SECURE_NO_SETUID_FIXUP_LOCKED;
812                 else if (first_word(w, "noroot"))
813                         c->secure_bits |= SECURE_NOROOT;
814                 else if (first_word(w, "noroot-locked"))
815                         c->secure_bits |= SECURE_NOROOT_LOCKED;
816                 else {
817                         log_error("[%s:%u] Failed to parse secure bits: %s", filename, line, rvalue);
818                         return -EBADMSG;
819                 }
820         }
821
822         return 0;
823 }
824
825 static int config_parse_bounding_set(
826                 const char *filename,
827                 unsigned line,
828                 const char *section,
829                 const char *lvalue,
830                 const char *rvalue,
831                 void *data,
832                 void *userdata) {
833
834         ExecContext *c = data;
835         char *w;
836         size_t l;
837         char *state;
838
839         assert(filename);
840         assert(lvalue);
841         assert(rvalue);
842         assert(data);
843
844         FOREACH_WORD(w, l, rvalue, state) {
845                 char *t;
846                 int r;
847                 cap_value_t cap;
848
849                 if (!(t = strndup(w, l)))
850                         return -ENOMEM;
851
852                 r = cap_from_name(t, &cap);
853                 free(t);
854
855                 if (r < 0) {
856                         log_error("[%s:%u] Failed to parse capability bounding set: %s", filename, line, rvalue);
857                         return -EBADMSG;
858                 }
859
860                 c->capability_bounding_set_drop |= 1 << cap;
861         }
862
863         return 0;
864 }
865
866 static int config_parse_timer_slack_ns(
867                 const char *filename,
868                 unsigned line,
869                 const char *section,
870                 const char *lvalue,
871                 const char *rvalue,
872                 void *data,
873                 void *userdata) {
874
875         ExecContext *c = data;
876         unsigned long u;
877         int r;
878
879         assert(filename);
880         assert(lvalue);
881         assert(rvalue);
882         assert(data);
883
884         if ((r = safe_atolu(rvalue, &u)) < 0) {
885                 log_error("[%s:%u] Failed to parse time slack value: %s", filename, line, rvalue);
886                 return r;
887         }
888
889         c->timer_slack_ns = u;
890
891         return 0;
892 }
893
894 static int config_parse_limit(
895                 const char *filename,
896                 unsigned line,
897                 const char *section,
898                 const char *lvalue,
899                 const char *rvalue,
900                 void *data,
901                 void *userdata) {
902
903         struct rlimit **rl = data;
904         unsigned long long u;
905         int r;
906
907         assert(filename);
908         assert(lvalue);
909         assert(rvalue);
910         assert(data);
911
912         if ((r = safe_atollu(rvalue, &u)) < 0) {
913                 log_error("[%s:%u] Failed to parse resource value: %s", filename, line, rvalue);
914                 return r;
915         }
916
917         if (!*rl)
918                 if (!(*rl = new(struct rlimit, 1)))
919                         return -ENOMEM;
920
921         (*rl)->rlim_cur = (*rl)->rlim_max = (rlim_t) u;
922         return 0;
923 }
924
925 static int config_parse_cgroup(
926                 const char *filename,
927                 unsigned line,
928                 const char *section,
929                 const char *lvalue,
930                 const char *rvalue,
931                 void *data,
932                 void *userdata) {
933
934         Unit *u = userdata;
935         char *w;
936         size_t l;
937         char *state;
938
939         FOREACH_WORD(w, l, rvalue, state) {
940                 char *t;
941                 int r;
942
943                 if (!(t = strndup(w, l)))
944                         return -ENOMEM;
945
946                 r = unit_add_cgroup_from_text(u, t);
947                 free(t);
948
949                 if (r < 0)
950                         return r;
951         }
952
953         return 0;
954 }
955
956 static int config_parse_sysv_priority(
957                 const char *filename,
958                 unsigned line,
959                 const char *section,
960                 const char *lvalue,
961                 const char *rvalue,
962                 void *data,
963                 void *userdata) {
964
965         int *priority = data;
966         int r, i;
967
968         assert(filename);
969         assert(lvalue);
970         assert(rvalue);
971         assert(data);
972
973         if ((r = safe_atoi(rvalue, &i)) < 0 || i < 0) {
974                 log_error("[%s:%u] Failed to parse SysV start priority: %s", filename, line, rvalue);
975                 return r;
976         }
977
978         *priority = (int) i;
979         return 0;
980 }
981
982 #define FOLLOW_MAX 8
983
984 static int open_follow(char **filename, FILE **_f, Set *names, char **_id) {
985         unsigned c = 0;
986         int fd, r;
987         FILE *f;
988         char *id = NULL;
989
990         assert(filename);
991         assert(*filename);
992         assert(_f);
993         assert(names);
994
995         /* This will update the filename pointer if the loaded file is
996          * reached by a symlink. The old string will be freed. */
997
998         for (;;) {
999                 char *target, *k, *name;
1000
1001                 if (c++ >= FOLLOW_MAX)
1002                         return -ELOOP;
1003
1004                 path_kill_slashes(*filename);
1005
1006                 /* Add the file name we are currently looking at to
1007                  * the names of this unit */
1008                 name = file_name_from_path(*filename);
1009                 if (!(id = set_get(names, name))) {
1010
1011                         if (!(id = strdup(name)))
1012                                 return -ENOMEM;
1013
1014                         if ((r = set_put(names, id)) < 0) {
1015                                 free(id);
1016                                 return r;
1017                         }
1018                 }
1019
1020                 /* Try to open the file name, but don't if its a symlink */
1021                 if ((fd = open(*filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW)) >= 0)
1022                         break;
1023
1024                 if (errno != ELOOP)
1025                         return -errno;
1026
1027                 /* Hmm, so this is a symlink. Let's read the name, and follow it manually */
1028                 if ((r = readlink_malloc(*filename, &target)) < 0)
1029                         return r;
1030
1031                 k = file_in_same_dir(*filename, target);
1032                 free(target);
1033
1034                 if (!k)
1035                         return -ENOMEM;
1036
1037                 free(*filename);
1038                 *filename = k;
1039         }
1040
1041         if (!(f = fdopen(fd, "r"))) {
1042                 r = -errno;
1043                 assert(close_nointr(fd) == 0);
1044                 return r;
1045         }
1046
1047         *_f = f;
1048         *_id = id;
1049         return 0;
1050 }
1051
1052 static int merge_by_names(Unit **u, Set *names, const char *id) {
1053         char *k;
1054         int r;
1055
1056         assert(u);
1057         assert(*u);
1058         assert(names);
1059
1060         /* Let's try to add in all symlink names we found */
1061         while ((k = set_steal_first(names))) {
1062
1063                 /* First try to merge in the other name into our
1064                  * unit */
1065                 if ((r = unit_merge_by_name(*u, k)) < 0) {
1066                         Unit *other;
1067
1068                         /* Hmm, we couldn't merge the other unit into
1069                          * ours? Then let's try it the other way
1070                          * round */
1071
1072                         other = manager_get_unit((*u)->meta.manager, k);
1073                         free(k);
1074
1075                         if (other)
1076                                 if ((r = unit_merge(other, *u)) >= 0) {
1077                                         *u = other;
1078                                         return merge_by_names(u, names, NULL);
1079                                 }
1080
1081                         return r;
1082                 }
1083
1084                 if (id == k)
1085                         unit_choose_id(*u, id);
1086
1087                 free(k);
1088         }
1089
1090         return 0;
1091 }
1092
1093 static int load_from_path(Unit *u, const char *path, UnitLoadState *new_state) {
1094
1095         static const char* const section_table[_UNIT_TYPE_MAX] = {
1096                 [UNIT_SERVICE]   = "Service",
1097                 [UNIT_TIMER]     = "Timer",
1098                 [UNIT_SOCKET]    = "Socket",
1099                 [UNIT_TARGET]    = "Target",
1100                 [UNIT_DEVICE]    = "Device",
1101                 [UNIT_MOUNT]     = "Mount",
1102                 [UNIT_AUTOMOUNT] = "Automount",
1103                 [UNIT_SNAPSHOT]  = "Snapshot"
1104         };
1105
1106 #define EXEC_CONTEXT_CONFIG_ITEMS(context, section) \
1107                 { "WorkingDirectory",       config_parse_path,            &(context).working_directory,                    section   }, \
1108                 { "RootDirectory",          config_parse_path,            &(context).root_directory,                       section   }, \
1109                 { "User",                   config_parse_string,          &(context).user,                                 section   }, \
1110                 { "Group",                  config_parse_string,          &(context).group,                                section   }, \
1111                 { "SupplementaryGroups",    config_parse_strv,            &(context).supplementary_groups,                 section   }, \
1112                 { "Nice",                   config_parse_nice,            &(context),                                      section   }, \
1113                 { "OOMAdjust",              config_parse_oom_adjust,      &(context),                                      section   }, \
1114                 { "IOSchedulingClass",      config_parse_io_class,        &(context),                                      section   }, \
1115                 { "IOSchedulingPriority",   config_parse_io_priority,     &(context),                                      section   }, \
1116                 { "CPUSchedulingPolicy",    config_parse_cpu_sched_policy,&(context),                                      section   }, \
1117                 { "CPUSchedulingPriority",  config_parse_cpu_sched_prio,  &(context),                                      section   }, \
1118                 { "CPUSchedulingResetOnFork", config_parse_bool,          &(context).cpu_sched_reset_on_fork,              section   }, \
1119                 { "CPUAffinity",            config_parse_cpu_affinity,    &(context),                                      section   }, \
1120                 { "UMask",                  config_parse_mode,            &(context).umask,                                section   }, \
1121                 { "Environment",            config_parse_strv,            &(context).environment,                          section   }, \
1122                 { "Output",                 config_parse_output,          &(context).output,                               section   }, \
1123                 { "Input",                  config_parse_input,           &(context).input,                                section   }, \
1124                 { "SyslogIdentifier",       config_parse_string,          &(context).syslog_identifier,                    section   }, \
1125                 { "SyslogFacility",         config_parse_facility,        &(context).syslog_priority,                      section   }, \
1126                 { "SyslogLevel",            config_parse_level,           &(context).syslog_priority,                      section   }, \
1127                 { "Capabilities",           config_parse_capabilities,    &(context),                                      section   }, \
1128                 { "SecureBits",             config_parse_secure_bits,     &(context),                                      section   }, \
1129                 { "CapabilityBoundingSetDrop", config_parse_bounding_set, &(context),                                      section   }, \
1130                 { "TimerSlackNS",           config_parse_timer_slack_ns,  &(context),                                      section   }, \
1131                 { "LimitCPU",               config_parse_limit,           &(context).rlimit[RLIMIT_CPU],                   section   }, \
1132                 { "LimitFSIZE",             config_parse_limit,           &(context).rlimit[RLIMIT_FSIZE],                 section   }, \
1133                 { "LimitDATA",              config_parse_limit,           &(context).rlimit[RLIMIT_DATA],                  section   }, \
1134                 { "LimitSTACK",             config_parse_limit,           &(context).rlimit[RLIMIT_STACK],                 section   }, \
1135                 { "LimitCORE",              config_parse_limit,           &(context).rlimit[RLIMIT_CORE],                  section   }, \
1136                 { "LimitRSS",               config_parse_limit,           &(context).rlimit[RLIMIT_RSS],                   section   }, \
1137                 { "LimitNOFILE",            config_parse_limit,           &(context).rlimit[RLIMIT_NOFILE],                section   }, \
1138                 { "LimitAS",                config_parse_limit,           &(context).rlimit[RLIMIT_AS],                    section   }, \
1139                 { "LimitNPROC",             config_parse_limit,           &(context).rlimit[RLIMIT_NPROC],                 section   }, \
1140                 { "LimitMEMLOCK",           config_parse_limit,           &(context).rlimit[RLIMIT_MEMLOCK],               section   }, \
1141                 { "LimitLOCKS",             config_parse_limit,           &(context).rlimit[RLIMIT_LOCKS],                 section   }, \
1142                 { "LimitSIGPENDING",        config_parse_limit,           &(context).rlimit[RLIMIT_SIGPENDING],            section   }, \
1143                 { "LimitMSGQUEUE",          config_parse_limit,           &(context).rlimit[RLIMIT_MSGQUEUE],              section   }, \
1144                 { "LimitNICE",              config_parse_limit,           &(context).rlimit[RLIMIT_NICE],                  section   }, \
1145                 { "LimitRTPRIO",            config_parse_limit,           &(context).rlimit[RLIMIT_RTPRIO],                section   }, \
1146                 { "LimitRTTIME",            config_parse_limit,           &(context).rlimit[RLIMIT_RTTIME],                section   }, \
1147                 { "NonBlocking",            config_parse_bool,            &(context).non_blocking,                         section   }, \
1148                 { "ControlGroup",           config_parse_cgroup,          u,                                               section   }  \
1149
1150         const ConfigItem items[] = {
1151                 { "Names",                  config_parse_names,           u,                                               "Meta"    },
1152                 { "Description",            config_parse_string,          &u->meta.description,                            "Meta"    },
1153                 { "Requires",               config_parse_deps,            UINT_TO_PTR(UNIT_REQUIRES),                      "Meta"    },
1154                 { "SoftRequires",           config_parse_deps,            UINT_TO_PTR(UNIT_SOFT_REQUIRES),                 "Meta"    },
1155                 { "Wants",                  config_parse_deps,            UINT_TO_PTR(UNIT_WANTS),                         "Meta"    },
1156                 { "Requisite",              config_parse_deps,            UINT_TO_PTR(UNIT_REQUISITE),                     "Meta"    },
1157                 { "SoftRequisite",          config_parse_deps,            UINT_TO_PTR(UNIT_SOFT_REQUISITE),                "Meta"    },
1158                 { "Conflicts",              config_parse_deps,            UINT_TO_PTR(UNIT_CONFLICTS),                     "Meta"    },
1159                 { "Before",                 config_parse_deps,            UINT_TO_PTR(UNIT_BEFORE),                        "Meta"    },
1160                 { "After",                  config_parse_deps,            UINT_TO_PTR(UNIT_AFTER),                         "Meta"    },
1161                 { "RecursiveStop",          config_parse_bool,            &u->meta.recursive_stop,                         "Meta"    },
1162                 { "StopWhenUnneeded",       config_parse_bool,            &u->meta.stop_when_unneeded,                     "Meta"    },
1163
1164                 { "PIDFile",                config_parse_path,            &u->service.pid_file,                            "Service" },
1165                 { "ExecStartPre",           config_parse_exec,            u->service.exec_command+SERVICE_EXEC_START_PRE,  "Service" },
1166                 { "ExecStart",              config_parse_exec,            u->service.exec_command+SERVICE_EXEC_START,      "Service" },
1167                 { "ExecStartPost",          config_parse_exec,            u->service.exec_command+SERVICE_EXEC_START_POST, "Service" },
1168                 { "ExecReload",             config_parse_exec,            u->service.exec_command+SERVICE_EXEC_RELOAD,     "Service" },
1169                 { "ExecStop",               config_parse_exec,            u->service.exec_command+SERVICE_EXEC_STOP,       "Service" },
1170                 { "ExecStopPost",           config_parse_exec,            u->service.exec_command+SERVICE_EXEC_STOP_POST,  "Service" },
1171                 { "RestartSec",             config_parse_usec,            &u->service.restart_usec,                        "Service" },
1172                 { "TimeoutSec",             config_parse_usec,            &u->service.timeout_usec,                        "Service" },
1173                 { "Type",                   config_parse_service_type,    &u->service,                                     "Service" },
1174                 { "Restart",                config_parse_service_restart, &u->service,                                     "Service" },
1175                 { "PermissionsStartOnly",   config_parse_bool,            &u->service.permissions_start_only,              "Service" },
1176                 { "RootDirectoryStartOnly", config_parse_bool,            &u->service.root_directory_start_only,           "Service" },
1177                 { "ValidNoProcess",         config_parse_bool,            &u->service.valid_no_process,                    "Service" },
1178                 { "SysVStartPriority",      config_parse_sysv_priority,   &u->service.sysv_start_priority,                 "Service" },
1179                 EXEC_CONTEXT_CONFIG_ITEMS(u->service.exec_context, "Service"),
1180
1181                 { "ListenStream",           config_parse_listen,          &u->socket,                                      "Socket"  },
1182                 { "ListenDatagram",         config_parse_listen,          &u->socket,                                      "Socket"  },
1183                 { "ListenSequentialPacket", config_parse_listen,          &u->socket,                                      "Socket"  },
1184                 { "ListenFIFO",             config_parse_listen,          &u->socket,                                      "Socket"  },
1185                 { "BindIPv6Only",           config_parse_socket_bind,     &u->socket,                                      "Socket"  },
1186                 { "Backlog",                config_parse_unsigned,        &u->socket.backlog,                              "Socket"  },
1187                 { "BindToDevice",           config_parse_bindtodevice,    &u->socket,                                      "Socket"  },
1188                 { "ExecStartPre",           config_parse_exec,            u->socket.exec_command+SOCKET_EXEC_START_PRE,    "Socket"  },
1189                 { "ExecStartPost",          config_parse_exec,            u->socket.exec_command+SOCKET_EXEC_START_POST,   "Socket"  },
1190                 { "ExecStopPre",            config_parse_exec,            u->socket.exec_command+SOCKET_EXEC_STOP_PRE,     "Socket"  },
1191                 { "ExecStopPost",           config_parse_exec,            u->socket.exec_command+SOCKET_EXEC_STOP_POST,    "Socket"  },
1192                 { "DirectoryMode",          config_parse_mode,            &u->socket.directory_mode,                       "Socket"  },
1193                 { "SocketMode",             config_parse_mode,            &u->socket.socket_mode,                          "Socket"  },
1194                 EXEC_CONTEXT_CONFIG_ITEMS(u->socket.exec_context, "Socket"),
1195
1196                 EXEC_CONTEXT_CONFIG_ITEMS(u->automount.exec_context, "Automount"),
1197
1198                 { NULL, NULL, NULL, NULL }
1199         };
1200
1201 #undef EXEC_CONTEXT_CONFIG_ITEMS
1202
1203         const char *sections[3];
1204         char *k;
1205         int r;
1206         Set *symlink_names;
1207         FILE *f = NULL;
1208         char *filename = NULL, *id = NULL;
1209         Unit *merged;
1210
1211         assert(u);
1212         assert(new_state);
1213
1214         sections[0] = "Meta";
1215         sections[1] = section_table[u->meta.type];
1216         sections[2] = NULL;
1217
1218         if (!(symlink_names = set_new(string_hash_func, string_compare_func)))
1219                 return -ENOMEM;
1220
1221         if (path_is_absolute(path)) {
1222
1223                 if (!(filename = strdup(path))) {
1224                         r = -ENOMEM;
1225                         goto finish;
1226                 }
1227
1228                 if ((r = open_follow(&filename, &f, symlink_names, &id)) < 0) {
1229                         free(filename);
1230                         filename = NULL;
1231
1232                         if (r != -ENOENT)
1233                                 goto finish;
1234                 }
1235
1236         } else  {
1237                 char **p;
1238
1239                 STRV_FOREACH(p, u->meta.manager->unit_path) {
1240
1241                         /* Instead of opening the path right away, we manually
1242                          * follow all symlinks and add their name to our unit
1243                          * name set while doing so */
1244                         if (!(filename = path_make_absolute(path, *p))) {
1245                                 r = -ENOMEM;
1246                                 goto finish;
1247                         }
1248
1249                         if ((r = open_follow(&filename, &f, symlink_names, &id)) < 0) {
1250                                 char *sn;
1251
1252                                 free(filename);
1253                                 filename = NULL;
1254
1255                                 if (r != -ENOENT)
1256                                         goto finish;
1257
1258                                 /* Empty the symlink names for the next run */
1259                                 while ((sn = set_steal_first(symlink_names)))
1260                                         free(sn);
1261
1262                                 continue;
1263                         }
1264
1265                         break;
1266                 }
1267         }
1268
1269         if (!filename) {
1270                 r = 0;
1271                 goto finish;
1272         }
1273
1274         merged = u;
1275         if ((r = merge_by_names(&merged, symlink_names, id)) < 0)
1276                 goto finish;
1277
1278         if (merged != u) {
1279                 *new_state = UNIT_MERGED;
1280                 r = 0;
1281                 goto finish;
1282         }
1283
1284         /* Now, parse the file contents */
1285         if ((r = config_parse(filename, f, sections, items, u)) < 0)
1286                 goto finish;
1287
1288         free(u->meta.fragment_path);
1289         u->meta.fragment_path = filename;
1290         filename = NULL;
1291
1292         *new_state = UNIT_LOADED;
1293         r = 0;
1294
1295 finish:
1296         while ((k = set_steal_first(symlink_names)))
1297                 free(k);
1298
1299         set_free(symlink_names);
1300         free(filename);
1301
1302         if (f)
1303                 fclose(f);
1304
1305         return r;
1306 }
1307
1308 int unit_load_fragment(Unit *u, UnitLoadState *new_state) {
1309         int r;
1310
1311         assert(u);
1312         assert(new_state);
1313         assert(*new_state == UNIT_STUB);
1314
1315         if (u->meta.fragment_path) {
1316
1317                 if ((r = load_from_path(u, u->meta.fragment_path, new_state)) < 0)
1318                         return r;
1319
1320         } else {
1321                 Iterator i;
1322                 const char *t;
1323
1324                 /* Try to find the unit under its id */
1325                 if ((t = unit_id(u)))
1326                         if ((r = load_from_path(u, t, new_state)) < 0)
1327                                 return r;
1328
1329                 /* Try to find an alias we can load this with */
1330                 if (*new_state == UNIT_STUB)
1331                         SET_FOREACH(t, u->meta.names, i) {
1332
1333                                 if (unit_id(u) == t)
1334                                         continue;
1335
1336                                 if ((r = load_from_path(u, t, new_state)) < 0)
1337                                         return r;
1338
1339                                 if (*new_state != UNIT_STUB)
1340                                         break;
1341                         }
1342         }
1343
1344         return 0;
1345 }