1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
7 Copyright 2012 Holger Hans Peter Freyther
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.
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.
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/>.
23 #include <linux/oom.h>
30 #include <sys/prctl.h>
31 #include <sys/mount.h>
35 #include <sys/resource.h>
39 #include "conf-parser.h"
40 #include "load-fragment.h"
43 #include "securebits.h"
45 #include "unit-name.h"
46 #include "unit-printf.h"
47 #include "bus-errors.h"
49 #include "path-util.h"
50 #include "syscall-list.h"
53 #ifndef HAVE_SYSV_COMPAT
54 int config_parse_warn_compat(
64 log_debug("[%s:%u] Support for option %s= has been disabled at compile time and is ignored", filename, line, lvalue);
69 int config_parse_unit_deps(
79 UnitDependency d = ltype;
89 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
90 char _cleanup_free_ *t = NULL, *k = NULL;
97 k = unit_name_printf(u, t);
101 r = unit_add_dependency_by_name(u, d, k, NULL, true);
103 log_error("[%s:%u] Failed to add dependency on %s, ignoring: %s",
104 filename, line, k, strerror(-r));
110 int config_parse_unit_string_printf(
111 const char *filename,
121 _cleanup_free_ char *k = NULL;
128 k = unit_full_printf(u, rvalue);
130 log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.",
131 filename, line, rvalue);
133 return config_parse_string(filename, line, section, lvalue, ltype, k ? k : rvalue, data, userdata);
136 int config_parse_unit_strv_printf(
137 const char *filename,
147 _cleanup_free_ char *k = NULL;
154 k = unit_full_printf(u, rvalue);
156 log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.",
157 filename, line, rvalue);
159 return config_parse_strv(filename, line, section, lvalue, ltype, k ? k : rvalue, data, userdata);
162 int config_parse_unit_path_printf(
163 const char *filename,
173 _cleanup_free_ char *k = NULL;
180 k = unit_full_printf(u, rvalue);
182 log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.",
183 filename, line, rvalue);
185 return config_parse_path(filename, line, section, lvalue, ltype, k ? k : rvalue, data, userdata);
188 int config_parse_socket_listen(
189 const char *filename,
198 SocketPort *p, *tail;
208 if (isempty(rvalue)) {
209 /* An empty assignment removes all ports */
210 socket_free_ports(s);
214 p = new0(SocketPort, 1);
218 if (ltype != SOCKET_SOCKET) {
221 p->path = unit_full_printf(UNIT(s), rvalue);
223 p->path = strdup(rvalue);
228 log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.",
229 filename, line, rvalue);
232 path_kill_slashes(p->path);
234 } else if (streq(lvalue, "ListenNetlink")) {
235 _cleanup_free_ char *k = NULL;
238 p->type = SOCKET_SOCKET;
239 k = unit_full_printf(UNIT(s), rvalue);
241 log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.",
242 filename, line, rvalue);
244 r = socket_address_parse_netlink(&p->address, k ? k : rvalue);
246 log_error("[%s:%u] Failed to parse address value, ignoring: %s", filename, line, rvalue);
252 _cleanup_free_ char *k = NULL;
255 p->type = SOCKET_SOCKET;
256 k = unit_full_printf(UNIT(s), rvalue);
258 log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.",
259 filename, line, rvalue);
261 r = socket_address_parse(&p->address, k ? k : rvalue);
263 log_error("[%s:%u] Failed to parse address value, ignoring: %s", filename, line, rvalue);
268 if (streq(lvalue, "ListenStream"))
269 p->address.type = SOCK_STREAM;
270 else if (streq(lvalue, "ListenDatagram"))
271 p->address.type = SOCK_DGRAM;
273 assert(streq(lvalue, "ListenSequentialPacket"));
274 p->address.type = SOCK_SEQPACKET;
277 if (socket_address_family(&p->address) != AF_LOCAL && p->address.type == SOCK_SEQPACKET) {
278 log_error("[%s:%u] Address family not supported, ignoring: %s", filename, line, rvalue);
287 LIST_FIND_TAIL(SocketPort, port, s->ports, tail);
288 LIST_INSERT_AFTER(SocketPort, port, s->ports, tail, p);
290 LIST_PREPEND(SocketPort, port, s->ports, p);
295 int config_parse_socket_bind(
296 const char *filename,
306 SocketAddressBindIPv6Only b;
315 b = socket_address_bind_ipv6_only_from_string(rvalue);
319 r = parse_boolean(rvalue);
321 log_error("[%s:%u] Failed to parse bind IPv6 only value, ignoring: %s", filename, line, rvalue);
325 s->bind_ipv6_only = r ? SOCKET_ADDRESS_IPV6_ONLY : SOCKET_ADDRESS_BOTH;
327 s->bind_ipv6_only = b;
332 int config_parse_exec_nice(
333 const char *filename,
342 ExecContext *c = data;
350 if (safe_atoi(rvalue, &priority) < 0) {
351 log_error("[%s:%u] Failed to parse nice priority, ignoring: %s. ", filename, line, rvalue);
355 if (priority < PRIO_MIN || priority >= PRIO_MAX) {
356 log_error("[%s:%u] Nice priority out of range, ignoring: %s", filename, line, rvalue);
366 int config_parse_exec_oom_score_adjust(
367 const char *filename,
376 ExecContext *c = data;
384 if (safe_atoi(rvalue, &oa) < 0) {
385 log_error("[%s:%u] Failed to parse the OOM score adjust value, ignoring: %s", filename, line, rvalue);
389 if (oa < OOM_SCORE_ADJ_MIN || oa > OOM_SCORE_ADJ_MAX) {
390 log_error("[%s:%u] OOM score adjust value out of range, ignoring: %s", filename, line, rvalue);
394 c->oom_score_adjust = oa;
395 c->oom_score_adjust_set = true;
400 int config_parse_exec(
401 const char *filename,
410 ExecCommand **e = data, *nce;
422 if (isempty(rvalue)) {
423 /* An empty assignment resets the list */
424 exec_command_free_list(*e);
429 /* We accept an absolute path as first argument, or
430 * alternatively an absolute prefixed with @ to allow
431 * overriding of argv[0]. */
437 bool honour_argv0 = false, ignore = false;
443 rvalue += strspn(rvalue, WHITESPACE);
448 for (i = 0; i < 2; i++) {
449 if (rvalue[0] == '-' && !ignore) {
454 if (rvalue[0] == '@' && !honour_argv0) {
460 if (*rvalue != '/') {
461 log_error("[%s:%u] Executable path is not absolute, ignoring: %s",
462 filename, line, rvalue);
467 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
468 if (strneq(w, ";", MAX(l, 1U)))
474 n = new(char*, k + !honour_argv0);
479 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
480 if (strneq(w, ";", MAX(l, 1U)))
482 else if (strneq(w, "\\;", MAX(l, 1U)))
485 if (honour_argv0 && w == rvalue) {
488 path = strndup(w, l);
494 if (!utf8_is_valid(path)) {
495 log_error("[%s:%u] Path is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
503 c = n[k++] = cunescape_length(w, l);
509 if (!utf8_is_valid(c)) {
510 log_error("[%s:%u] Path is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
520 log_error("[%s:%u] Invalid command line, ignoring: %s", filename, line, rvalue);
533 assert(path_is_absolute(path));
535 nce = new0(ExecCommand, 1);
543 nce->ignore = ignore;
545 path_kill_slashes(nce->path);
547 exec_command_append_list(e, nce);
563 DEFINE_CONFIG_PARSE_ENUM(config_parse_service_type, service_type, ServiceType, "Failed to parse service type");
564 DEFINE_CONFIG_PARSE_ENUM(config_parse_service_restart, service_restart, ServiceRestart, "Failed to parse service restart specifier");
566 int config_parse_socket_bindtodevice(
567 const char *filename,
584 if (rvalue[0] && !streq(rvalue, "*")) {
591 free(s->bind_to_device);
592 s->bind_to_device = n;
597 DEFINE_CONFIG_PARSE_ENUM(config_parse_output, exec_output, ExecOutput, "Failed to parse output specifier");
598 DEFINE_CONFIG_PARSE_ENUM(config_parse_input, exec_input, ExecInput, "Failed to parse input specifier");
600 int config_parse_exec_io_class(
601 const char *filename,
610 ExecContext *c = data;
618 x = ioprio_class_from_string(rvalue);
620 log_error("[%s:%u] Failed to parse IO scheduling class, ignoring: %s", filename, line, rvalue);
624 c->ioprio = IOPRIO_PRIO_VALUE(x, IOPRIO_PRIO_DATA(c->ioprio));
625 c->ioprio_set = true;
630 int config_parse_exec_io_priority(
631 const char *filename,
640 ExecContext *c = data;
648 if (safe_atoi(rvalue, &i) < 0 || i < 0 || i >= IOPRIO_BE_NR) {
649 log_error("[%s:%u] Failed to parse io priority, ignoring: %s", filename, line, rvalue);
653 c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_PRIO_CLASS(c->ioprio), i);
654 c->ioprio_set = true;
659 int config_parse_exec_cpu_sched_policy(
660 const char *filename,
670 ExecContext *c = data;
678 x = sched_policy_from_string(rvalue);
680 log_error("[%s:%u] Failed to parse CPU scheduling policy, ignoring: %s", filename, line, rvalue);
684 c->cpu_sched_policy = x;
685 /* Moving to or from real-time policy? We need to adjust the priority */
686 c->cpu_sched_priority = CLAMP(c->cpu_sched_priority, sched_get_priority_min(x), sched_get_priority_max(x));
687 c->cpu_sched_set = true;
692 int config_parse_exec_cpu_sched_prio(
693 const char *filename,
702 ExecContext *c = data;
710 if (safe_atoi(rvalue, &i) < 0) {
711 log_error("[%s:%u] Failed to parse CPU scheduling priority, ignoring: %s", filename, line, rvalue);
715 /* On Linux RR/FIFO range from 1 to 99 and OTHER/BATCH may only be 0 */
716 min = sched_get_priority_min(c->cpu_sched_policy);
717 max = sched_get_priority_max(c->cpu_sched_policy);
719 if (i < min || i > max) {
720 log_error("[%s:%u] CPU scheduling priority is out of range, ignoring: %s", filename, line, rvalue);
724 c->cpu_sched_priority = i;
725 c->cpu_sched_set = true;
730 int config_parse_exec_cpu_affinity(
731 const char *filename,
740 ExecContext *c = data;
750 if (isempty(rvalue)) {
751 /* An empty assignment resets the CPU list */
758 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
759 char _cleanup_free_ *t = NULL;
767 r = safe_atou(t, &cpu);
770 c->cpuset = cpu_set_malloc(&c->cpuset_ncpus);
775 if (r < 0 || cpu >= c->cpuset_ncpus) {
776 log_error("[%s:%u] Failed to parse CPU affinity %s, ignoring: %s",
777 filename, line, t, rvalue);
781 CPU_SET_S(cpu, CPU_ALLOC_SIZE(c->cpuset_ncpus), c->cpuset);
787 int config_parse_exec_capabilities(
788 const char *filename,
797 ExecContext *c = data;
805 cap = cap_from_text(rvalue);
810 log_error("[%s:%u] Failed to parse capabilities, ignoring: %s", filename, line, rvalue);
815 cap_free(c->capabilities);
816 c->capabilities = cap;
821 int config_parse_exec_secure_bits(
822 const char *filename,
831 ExecContext *c = data;
841 if (isempty(rvalue)) {
842 /* An empty assignment resets the field */
847 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
848 if (first_word(w, "keep-caps"))
849 c->secure_bits |= SECURE_KEEP_CAPS;
850 else if (first_word(w, "keep-caps-locked"))
851 c->secure_bits |= SECURE_KEEP_CAPS_LOCKED;
852 else if (first_word(w, "no-setuid-fixup"))
853 c->secure_bits |= SECURE_NO_SETUID_FIXUP;
854 else if (first_word(w, "no-setuid-fixup-locked"))
855 c->secure_bits |= SECURE_NO_SETUID_FIXUP_LOCKED;
856 else if (first_word(w, "noroot"))
857 c->secure_bits |= SECURE_NOROOT;
858 else if (first_word(w, "noroot-locked"))
859 c->secure_bits |= SECURE_NOROOT_LOCKED;
861 log_error("[%s:%u] Failed to parse secure bits, ignoring: %s",
862 filename, line, rvalue);
870 int config_parse_bounding_set(
871 const char *filename,
880 uint64_t *capability_bounding_set_drop = data;
892 if (rvalue[0] == '~') {
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
902 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
903 char _cleanup_free_ *t = NULL;
911 r = cap_from_name(t, &cap);
913 log_error("[%s:%u] Failed to parse capability in bounding set, ignoring: %s",
918 sum |= ((uint64_t) 1ULL) << (uint64_t) cap;
922 *capability_bounding_set_drop |= sum;
924 *capability_bounding_set_drop |= ~sum;
929 int config_parse_limit(
930 const char *filename,
939 struct rlimit **rl = data;
940 unsigned long long u;
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);
957 *rl = new(struct rlimit, 1);
962 (*rl)->rlim_cur = (*rl)->rlim_max = (rlim_t) u;
966 int config_parse_unit_cgroup(
967 const char *filename,
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;
988 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
989 char _cleanup_free_ *t = NULL, *k = NULL, *ku = NULL;
996 k = unit_full_printf(u, t);
998 log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.",
1001 ku = cunescape(k ? k : t);
1005 r = unit_add_cgroup_from_text(u, ku, true, NULL);
1007 log_error("[%s:%u] Failed to parse cgroup value %s, ignoring: %s",
1008 filename, line, k, rvalue);
1016 #ifdef HAVE_SYSV_COMPAT
1017 int config_parse_sysv_priority(
1018 const char *filename,
1020 const char *section,
1027 int *priority = data;
1035 if (safe_atoi(rvalue, &i) < 0 || i < 0) {
1036 log_error("[%s:%u] Failed to parse SysV start priority, ignoring: %s", filename, line, rvalue);
1040 *priority = (int) i;
1045 int config_parse_fsck_passno(
1046 const char *filename,
1048 const char *section,
1063 if (safe_atoi(rvalue, &i) || i < 0) {
1064 log_error("[%s:%u] Failed to parse fsck pass number, ignoring: %s", filename, line, rvalue);
1072 DEFINE_CONFIG_PARSE_ENUM(config_parse_kill_mode, kill_mode, KillMode, "Failed to parse kill mode");
1074 int config_parse_kill_signal(
1075 const char *filename,
1077 const char *section,
1092 r = signal_from_string_try_harder(rvalue);
1094 log_error("[%s:%u] Failed to parse kill signal, ignoring: %s", filename, line, rvalue);
1102 int config_parse_exec_mount_flags(
1103 const char *filename,
1105 const char *section,
1112 ExecContext *c = data;
1116 unsigned long flags = 0;
1123 FOREACH_WORD_SEPARATOR(w, l, rvalue, ", ", state) {
1124 char _cleanup_free_ *t;
1130 if (streq(t, "shared"))
1132 else if (streq(t, "slave"))
1134 else if (streq(w, "private"))
1135 flags |= MS_PRIVATE;
1137 log_error("[%s:%u] Failed to parse mount flag %s, ignoring: %s",
1138 filename, line, t, rvalue);
1143 c->mount_flags = flags;
1147 int config_parse_timer(
1148 const char *filename,
1150 const char *section,
1161 CalendarSpec *c = NULL;
1169 if (isempty(rvalue)) {
1170 /* Empty assignment resets list */
1171 timer_free_values(t);
1175 b = timer_base_from_string(lvalue);
1177 log_error("[%s:%u] Failed to parse timer base, ignoring: %s", filename, line, lvalue);
1181 if (b == TIMER_CALENDAR) {
1182 if (calendar_spec_from_string(rvalue, &c) < 0) {
1183 log_error("[%s:%u] Failed to parse calendar specification, ignoring: %s", filename, line, rvalue);
1187 id = CLOCK_REALTIME;
1189 if (parse_usec(rvalue, &u) < 0) {
1190 log_error("[%s:%u] Failed to parse timer value, ignoring: %s", filename, line, rvalue);
1194 id = CLOCK_MONOTONIC;
1197 v = new0(TimerValue, 1);
1204 v->calendar_spec = c;
1206 LIST_PREPEND(TimerValue, value, t->values, v);
1211 int config_parse_timer_unit(
1212 const char *filename,
1214 const char *section,
1225 _cleanup_free_ char *p = NULL;
1232 dbus_error_init(&error);
1234 p = unit_name_printf(UNIT(t), rvalue);
1238 if (endswith(p, ".timer")) {
1239 log_error("[%s:%u] Unit cannot be of type timer, ignoring: %s", filename, line, rvalue);
1243 r = manager_load_unit(UNIT(t)->manager, p, NULL, NULL, &u);
1245 log_error("[%s:%u] Failed to load unit %s, ignoring: %s", filename, line, rvalue, bus_error(&error, r));
1246 dbus_error_free(&error);
1250 unit_ref_set(&t->unit, u);
1255 int config_parse_path_spec(
1256 const char *filename,
1258 const char *section,
1275 if (isempty(rvalue)) {
1276 /* Empty assignment clears list */
1281 b = path_type_from_string(lvalue);
1283 log_error("[%s:%u] Failed to parse path type, ignoring: %s", filename, line, lvalue);
1287 k = unit_full_printf(UNIT(p), rvalue);
1293 log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.",
1294 filename, line, rvalue);
1297 if (!path_is_absolute(k)) {
1298 log_error("[%s:%u] Path is not absolute, ignoring: %s", filename, line, k);
1303 s = new0(PathSpec, 1);
1309 s->path = path_kill_slashes(k);
1313 LIST_PREPEND(PathSpec, spec, p->specs, s);
1318 int config_parse_path_unit(
1319 const char *filename,
1321 const char *section,
1332 _cleanup_free_ char *p = NULL;
1339 dbus_error_init(&error);
1341 p = unit_name_printf(UNIT(t), rvalue);
1345 if (endswith(p, ".path")) {
1346 log_error("[%s:%u] Unit cannot be of type path, ignoring: %s", filename, line, p);
1350 r = manager_load_unit(UNIT(t)->manager, p, NULL, &error, &u);
1352 log_error("[%s:%u] Failed to load unit %s, ignoring: %s", filename, line, p, bus_error(&error, r));
1353 dbus_error_free(&error);
1357 unit_ref_set(&t->unit, u);
1362 int config_parse_socket_service(
1363 const char *filename,
1365 const char *section,
1376 _cleanup_free_ char *p = NULL;
1383 dbus_error_init(&error);
1385 p = unit_name_printf(UNIT(s), rvalue);
1389 if (!endswith(p, ".service")) {
1390 log_error("[%s:%u] Unit must be of type service, ignoring: %s", filename, line, rvalue);
1394 r = manager_load_unit(UNIT(s)->manager, p, NULL, &error, &x);
1396 log_error("[%s:%u] Failed to load unit %s, ignoring: %s", filename, line, rvalue, bus_error(&error, r));
1397 dbus_error_free(&error);
1401 unit_ref_set(&s->service, x);
1406 int config_parse_service_sockets(
1407 const char *filename,
1409 const char *section,
1426 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
1427 char _cleanup_free_ *t = NULL, *k = NULL;
1433 k = unit_name_printf(UNIT(s), t);
1437 if (!endswith(k, ".socket")) {
1438 log_error("[%s:%u] Unit must be of type socket, ignoring: %s",
1443 r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_WANTS, UNIT_AFTER, k, NULL, true);
1445 log_error("[%s:%u] Failed to add dependency on %s, ignoring: %s",
1446 filename, line, k, strerror(-r));
1448 r = unit_add_dependency_by_name(UNIT(s), UNIT_TRIGGERED_BY, k, NULL, true);
1456 int config_parse_service_timeout(
1457 const char *filename,
1459 const char *section,
1466 Service *s = userdata;
1474 r = config_parse_usec(filename, line, section, lvalue, ltype, rvalue, data, userdata);
1478 if (streq(lvalue, "TimeoutSec")) {
1479 s->start_timeout_defined = true;
1480 s->timeout_stop_usec = s->timeout_start_usec;
1481 } else if (streq(lvalue, "TimeoutStartSec"))
1482 s->start_timeout_defined = true;
1487 int config_parse_unit_env_file(
1488 const char *filename,
1490 const char *section,
1499 _cleanup_free_ char *s = NULL;
1507 if (isempty(rvalue)) {
1508 /* Empty assignment frees the list */
1514 s = unit_full_printf(u, rvalue);
1518 if (!path_is_absolute(s[0] == '-' ? s + 1 : s)) {
1519 log_error("[%s:%u] Path '%s' is not absolute, ignoring.", filename, line, s);
1523 r = strv_extend(env, s);
1530 int config_parse_environ(
1531 const char *filename,
1533 const char *section,
1541 char*** env = data, *w, *state;
1543 _cleanup_free_ char *k = NULL;
1550 if (isempty(rvalue)) {
1551 /* Empty assignment resets the list */
1557 k = unit_full_printf(u, rvalue);
1561 FOREACH_WORD_QUOTED(w, l, k, state) {
1562 _cleanup_free_ char *n;
1565 n = cunescape_length(w, l);
1569 if (!env_assignment_is_valid(n)) {
1570 log_error("[%s:%u] Invalid environment assignment, ignoring: %s", filename, line, rvalue);
1574 x = strv_env_set(*env, n);
1585 int config_parse_ip_tos(
1586 const char *filename,
1588 const char *section,
1595 int *ip_tos = data, x;
1602 x = ip_tos_from_string(rvalue);
1604 log_error("[%s:%u] Failed to parse IP TOS value, ignoring: %s", filename, line, rvalue);
1612 int config_parse_unit_condition_path(
1613 const char *filename,
1615 const char *section,
1622 ConditionType cond = ltype;
1624 bool trigger, negate;
1626 _cleanup_free_ char *p = NULL;
1633 if (isempty(rvalue)) {
1634 /* Empty assignment resets the list */
1635 condition_free_list(u->conditions);
1636 u->conditions = NULL;
1640 trigger = rvalue[0] == '|';
1644 negate = rvalue[0] == '!';
1648 p = unit_full_printf(u, rvalue);
1652 if (!path_is_absolute(p)) {
1653 log_error("[%s:%u] Path in condition not absolute, ignoring: %s", filename, line, p);
1657 c = condition_new(cond, p, trigger, negate);
1661 LIST_PREPEND(Condition, conditions, u->conditions, c);
1665 int config_parse_unit_condition_string(
1666 const char *filename,
1668 const char *section,
1675 ConditionType cond = ltype;
1677 bool trigger, negate;
1679 _cleanup_free_ char *s = NULL;
1686 if (isempty(rvalue)) {
1687 /* Empty assignment resets the list */
1688 condition_free_list(u->conditions);
1689 u->conditions = NULL;
1693 trigger = rvalue[0] == '|';
1697 negate = rvalue[0] == '!';
1701 s = unit_full_printf(u, rvalue);
1705 c = condition_new(cond, s, trigger, negate);
1709 LIST_PREPEND(Condition, conditions, u->conditions, c);
1713 int config_parse_unit_condition_null(
1714 const char *filename,
1716 const char *section,
1725 bool trigger, negate;
1733 if (isempty(rvalue)) {
1734 /* Empty assignment resets the list */
1735 condition_free_list(u->conditions);
1736 u->conditions = NULL;
1740 trigger = rvalue[0] == '|';
1744 negate = rvalue[0] == '!';
1748 b = parse_boolean(rvalue);
1750 log_error("[%s:%u] Failed to parse boolean value in condition, ignoring: %s", filename, line, rvalue);
1757 c = condition_new(CONDITION_NULL, NULL, trigger, negate);
1761 LIST_PREPEND(Condition, conditions, u->conditions, c);
1765 DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier");
1766 DEFINE_CONFIG_PARSE_ENUM(config_parse_start_limit_action, start_limit_action, StartLimitAction, "Failed to parse start limit action specifier");
1768 int config_parse_unit_cgroup_attr(
1769 const char *filename,
1771 const char *section,
1780 _cleanup_free_ char *n = NULL, *v = NULL;
1781 const CGroupSemantics *s;
1789 if (isempty(rvalue)) {
1790 /* Empty assignment clears the list */
1791 cgroup_attribute_free_list(u->cgroup_attributes);
1792 u->cgroup_attributes = NULL;
1796 a = strcspn(rvalue, WHITESPACE);
1797 b = strspn(rvalue + a, WHITESPACE);
1798 if (a <= 0 || b <= 0) {
1799 log_error("[%s:%u] Failed to parse cgroup attribute value, ignoring: %s", filename, line, rvalue);
1803 n = strndup(rvalue, a);
1807 r = cgroup_semantics_find(NULL, n, rvalue + a + b, &v, &s);
1809 log_error("[%s:%u] Failed to parse cgroup attribute value, ignoring: %s", filename, line, rvalue);
1813 r = unit_add_cgroup_attribute(u, s, NULL, n, v ? v : rvalue + a + b, NULL);
1815 log_error("[%s:%u] Failed to add cgroup attribute value, ignoring: %s", filename, line, rvalue);
1822 int config_parse_unit_cgroup_attr_pretty(
1823 const char *filename,
1825 const char *section,
1833 _cleanup_free_ char *v = NULL;
1834 const CGroupSemantics *s;
1842 r = cgroup_semantics_find(NULL, lvalue, rvalue, &v, &s);
1844 log_error("[%s:%u] Failed to parse cgroup attribute value, ignoring: %s", filename, line, rvalue);
1846 } else if (r == 0) {
1847 log_error("[%s:%u] Unknown or unsupported cgroup attribute %s, ignoring: %s", filename, line, lvalue, rvalue);
1851 r = unit_add_cgroup_attribute(u, s, NULL, NULL, v, NULL);
1853 log_error("[%s:%u] Failed to add cgroup attribute value, ignoring: %s", filename, line, rvalue);
1860 int config_parse_unit_requires_mounts_for(
1861 const char *filename,
1863 const char *section,
1879 empty_before = !u->requires_mounts_for;
1881 r = config_parse_path_strv(filename, line, section, lvalue, ltype, rvalue, data, userdata);
1883 /* Make it easy to find units with requires_mounts set */
1884 if (empty_before && u->requires_mounts_for)
1885 LIST_PREPEND(Unit, has_requires_mounts_for, u->manager->has_requires_mounts_for, u);
1890 int config_parse_documentation(
1891 const char *filename,
1893 const char *section,
1909 if (isempty(rvalue)) {
1910 /* Empty assignment resets the list */
1911 strv_free(u->documentation);
1912 u->documentation = NULL;
1916 r = config_parse_unit_strv_printf(filename, line, section, lvalue, ltype, rvalue, data, userdata);
1920 for (a = b = u->documentation; a && *a; a++) {
1922 if (is_valid_documentation_url(*a))
1925 log_error("[%s:%u] Invalid URL, ignoring: %s", filename, line, *a);
1934 static void syscall_set(uint32_t *p, int nr) {
1935 nr = SYSCALL_TO_INDEX(nr);
1936 p[nr >> 4] |= 1 << (nr & 31);
1939 static void syscall_unset(uint32_t *p, int nr) {
1940 nr = SYSCALL_TO_INDEX(nr);
1941 p[nr >> 4] &= ~(1 << (nr & 31));
1944 int config_parse_syscall_filter(
1945 const char *filename,
1947 const char *section,
1954 ExecContext *c = data;
1956 bool invert = false;
1966 if (isempty(rvalue)) {
1967 /* Empty assignment resets the list */
1968 free(c->syscall_filter);
1969 c->syscall_filter = NULL;
1973 if (rvalue[0] == '~') {
1978 if (!c->syscall_filter) {
1981 n = (syscall_max() + 31) >> 4;
1982 c->syscall_filter = new(uint32_t, n);
1983 if (!c->syscall_filter)
1986 memset(c->syscall_filter, invert ? 0xFF : 0, n * sizeof(uint32_t));
1988 /* Add these by default */
1989 syscall_set(c->syscall_filter, __NR_execve);
1990 syscall_set(c->syscall_filter, __NR_rt_sigreturn);
1991 #ifdef __NR_sigreturn
1992 syscall_set(c->syscall_filter, __NR_sigreturn);
1994 syscall_set(c->syscall_filter, __NR_exit_group);
1995 syscall_set(c->syscall_filter, __NR_exit);
1998 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
2000 char _cleanup_free_ *t = NULL;
2006 id = syscall_from_name(t);
2008 log_error("[%s:%u] Failed to parse syscall, ignoring: %s",
2014 syscall_unset(c->syscall_filter, id);
2016 syscall_set(c->syscall_filter, id);
2019 c->no_new_privileges = true;
2024 #define FOLLOW_MAX 8
2026 static int open_follow(char **filename, FILE **_f, Set *names, char **_final) {
2037 /* This will update the filename pointer if the loaded file is
2038 * reached by a symlink. The old string will be freed. */
2041 char *target, *name;
2043 if (c++ >= FOLLOW_MAX)
2046 path_kill_slashes(*filename);
2048 /* Add the file name we are currently looking at to
2049 * the names of this unit, but only if it is a valid
2051 name = path_get_file_name(*filename);
2053 if (unit_name_is_valid(name, true)) {
2055 id = set_get(names, name);
2061 r = set_put(names, id);
2069 /* Try to open the file name, but don't if its a symlink */
2070 fd = open(*filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
2077 /* Hmm, so this is a symlink. Let's read the name, and follow it manually */
2078 r = readlink_and_make_absolute(*filename, &target);
2086 f = fdopen(fd, "re");
2089 close_nointr_nofail(fd);
2098 static int merge_by_names(Unit **u, Set *names, const char *id) {
2106 /* Let's try to add in all symlink names we found */
2107 while ((k = set_steal_first(names))) {
2109 /* First try to merge in the other name into our
2111 r = unit_merge_by_name(*u, k);
2115 /* Hmm, we couldn't merge the other unit into
2116 * ours? Then let's try it the other way
2119 other = manager_get_unit((*u)->manager, k);
2123 r = unit_merge(other, *u);
2126 return merge_by_names(u, names, NULL);
2134 unit_choose_id(*u, id);
2142 static int load_from_path(Unit *u, const char *path) {
2146 char *filename = NULL, *id = NULL;
2153 symlink_names = set_new(string_hash_func, string_compare_func);
2157 if (path_is_absolute(path)) {
2159 filename = strdup(path);
2165 r = open_follow(&filename, &f, symlink_names, &id);
2177 STRV_FOREACH(p, u->manager->lookup_paths.unit_path) {
2179 /* Instead of opening the path right away, we manually
2180 * follow all symlinks and add their name to our unit
2181 * name set while doing so */
2182 filename = path_make_absolute(path, *p);
2188 if (u->manager->unit_path_cache &&
2189 !set_get(u->manager->unit_path_cache, filename))
2192 r = open_follow(&filename, &f, symlink_names, &id);
2201 /* Empty the symlink names for the next run */
2202 set_clear_free(symlink_names);
2211 /* Hmm, no suitable file found? */
2217 r = merge_by_names(&merged, symlink_names, id);
2222 u->load_state = UNIT_MERGED;
2227 if (fstat(fileno(f), &st) < 0) {
2232 if (null_or_empty(&st))
2233 u->load_state = UNIT_MASKED;
2235 /* Now, parse the file contents */
2236 r = config_parse(filename, f, UNIT_VTABLE(u)->sections, config_item_perf_lookup, (void*) load_fragment_gperf_lookup, false, u);
2240 u->load_state = UNIT_LOADED;
2243 free(u->fragment_path);
2244 u->fragment_path = filename;
2247 u->fragment_mtime = timespec_load(&st.st_mtim);
2249 if (u->source_path) {
2250 if (stat(u->source_path, &st) >= 0)
2251 u->source_mtime = timespec_load(&st.st_mtim);
2253 u->source_mtime = 0;
2259 set_free_free(symlink_names);
2268 int unit_load_fragment(Unit *u) {
2274 assert(u->load_state == UNIT_STUB);
2277 /* First, try to find the unit under its id. We always look
2278 * for unit files in the default directories, to make it easy
2279 * to override things by placing things in /etc/systemd/system */
2280 r = load_from_path(u, u->id);
2284 /* Try to find an alias we can load this with */
2285 if (u->load_state == UNIT_STUB)
2286 SET_FOREACH(t, u->names, i) {
2291 r = load_from_path(u, t);
2295 if (u->load_state != UNIT_STUB)
2299 /* And now, try looking for it under the suggested (originally linked) path */
2300 if (u->load_state == UNIT_STUB && u->fragment_path) {
2302 r = load_from_path(u, u->fragment_path);
2306 if (u->load_state == UNIT_STUB) {
2307 /* Hmm, this didn't work? Then let's get rid
2308 * of the fragment path stored for us, so that
2309 * we don't point to an invalid location. */
2310 free(u->fragment_path);
2311 u->fragment_path = NULL;
2315 /* Look for a template */
2316 if (u->load_state == UNIT_STUB && u->instance) {
2319 k = unit_name_template(u->id);
2323 r = load_from_path(u, k);
2329 if (u->load_state == UNIT_STUB)
2330 SET_FOREACH(t, u->names, i) {
2335 k = unit_name_template(t);
2339 r = load_from_path(u, k);
2345 if (u->load_state != UNIT_STUB)
2353 void unit_dump_config_items(FILE *f) {
2354 static const struct {
2355 const ConfigParserCallback callback;
2358 { config_parse_int, "INTEGER" },
2359 { config_parse_unsigned, "UNSIGNED" },
2360 { config_parse_bytes_size, "SIZE" },
2361 { config_parse_bool, "BOOLEAN" },
2362 { config_parse_string, "STRING" },
2363 { config_parse_path, "PATH" },
2364 { config_parse_unit_path_printf, "PATH" },
2365 { config_parse_strv, "STRING [...]" },
2366 { config_parse_exec_nice, "NICE" },
2367 { config_parse_exec_oom_score_adjust, "OOMSCOREADJUST" },
2368 { config_parse_exec_io_class, "IOCLASS" },
2369 { config_parse_exec_io_priority, "IOPRIORITY" },
2370 { config_parse_exec_cpu_sched_policy, "CPUSCHEDPOLICY" },
2371 { config_parse_exec_cpu_sched_prio, "CPUSCHEDPRIO" },
2372 { config_parse_exec_cpu_affinity, "CPUAFFINITY" },
2373 { config_parse_mode, "MODE" },
2374 { config_parse_unit_env_file, "FILE" },
2375 { config_parse_output, "OUTPUT" },
2376 { config_parse_input, "INPUT" },
2377 { config_parse_facility, "FACILITY" },
2378 { config_parse_level, "LEVEL" },
2379 { config_parse_exec_capabilities, "CAPABILITIES" },
2380 { config_parse_exec_secure_bits, "SECUREBITS" },
2381 { config_parse_bounding_set, "BOUNDINGSET" },
2382 { config_parse_limit, "LIMIT" },
2383 { config_parse_unit_cgroup, "CGROUP [...]" },
2384 { config_parse_unit_deps, "UNIT [...]" },
2385 { config_parse_exec, "PATH [ARGUMENT [...]]" },
2386 { config_parse_service_type, "SERVICETYPE" },
2387 { config_parse_service_restart, "SERVICERESTART" },
2388 #ifdef HAVE_SYSV_COMPAT
2389 { config_parse_sysv_priority, "SYSVPRIORITY" },
2391 { config_parse_warn_compat, "NOTSUPPORTED" },
2393 { config_parse_kill_mode, "KILLMODE" },
2394 { config_parse_kill_signal, "SIGNAL" },
2395 { config_parse_socket_listen, "SOCKET [...]" },
2396 { config_parse_socket_bind, "SOCKETBIND" },
2397 { config_parse_socket_bindtodevice, "NETWORKINTERFACE" },
2398 { config_parse_usec, "SECONDS" },
2399 { config_parse_nsec, "NANOSECONDS" },
2400 { config_parse_path_strv, "PATH [...]" },
2401 { config_parse_unit_requires_mounts_for, "PATH [...]" },
2402 { config_parse_exec_mount_flags, "MOUNTFLAG [...]" },
2403 { config_parse_unit_string_printf, "STRING" },
2404 { config_parse_timer, "TIMER" },
2405 { config_parse_timer_unit, "NAME" },
2406 { config_parse_path_spec, "PATH" },
2407 { config_parse_path_unit, "UNIT" },
2408 { config_parse_notify_access, "ACCESS" },
2409 { config_parse_ip_tos, "TOS" },
2410 { config_parse_unit_condition_path, "CONDITION" },
2411 { config_parse_unit_condition_string, "CONDITION" },
2412 { config_parse_unit_condition_null, "CONDITION" },
2415 const char *prev = NULL;
2420 NULSTR_FOREACH(i, load_fragment_gperf_nulstr) {
2421 const char *rvalue = "OTHER", *lvalue;
2425 const ConfigPerfItem *p;
2427 assert_se(p = load_fragment_gperf_lookup(i, strlen(i)));
2429 dot = strchr(i, '.');
2430 lvalue = dot ? dot + 1 : i;
2434 if (!prev || !strneq(prev, i, prefix_len+1)) {
2438 fprintf(f, "[%.*s]\n", (int) prefix_len, i);
2441 for (j = 0; j < ELEMENTSOF(table); j++)
2442 if (p->parse == table[j].callback) {
2443 rvalue = table[j].rvalue;
2447 fprintf(f, "%s=%s\n", lvalue, rvalue);