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);
132 return config_parse_string(filename, line, section, lvalue, ltype, k, data, userdata);
135 int config_parse_unit_strv_printf(
136 const char *filename,
146 _cleanup_free_ char *k = NULL;
153 k = unit_full_printf(u, rvalue);
157 return config_parse_strv(filename, line, section, lvalue, ltype, k, data, userdata);
160 int config_parse_unit_path_printf(
161 const char *filename,
171 _cleanup_free_ char *k = NULL;
178 k = unit_full_printf(u, rvalue);
182 return config_parse_path(filename, line, section, lvalue, ltype, k, data, userdata);
185 int config_parse_socket_listen(
186 const char *filename,
195 SocketPort *p, *tail;
205 if (isempty(rvalue)) {
206 /* An empty assignment removes all ports */
207 socket_free_ports(s);
211 p = new0(SocketPort, 1);
215 if (ltype != SOCKET_SOCKET) {
218 p->path = unit_full_printf(UNIT(s), rvalue);
224 path_kill_slashes(p->path);
226 } else if (streq(lvalue, "ListenNetlink")) {
227 _cleanup_free_ char *k = NULL;
230 p->type = SOCKET_SOCKET;
231 k = unit_full_printf(UNIT(s), rvalue);
237 r = socket_address_parse_netlink(&p->address, k);
239 log_error("[%s:%u] Failed to parse address value, ignoring: %s", filename, line, rvalue);
245 _cleanup_free_ char *k = NULL;
248 p->type = SOCKET_SOCKET;
249 k = unit_full_printf(UNIT(s), rvalue);
255 r = socket_address_parse(&p->address, k);
257 log_error("[%s:%u] Failed to parse address value, ignoring: %s", filename, line, rvalue);
262 if (streq(lvalue, "ListenStream"))
263 p->address.type = SOCK_STREAM;
264 else if (streq(lvalue, "ListenDatagram"))
265 p->address.type = SOCK_DGRAM;
267 assert(streq(lvalue, "ListenSequentialPacket"));
268 p->address.type = SOCK_SEQPACKET;
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);
281 LIST_FIND_TAIL(SocketPort, port, s->ports, tail);
282 LIST_INSERT_AFTER(SocketPort, port, s->ports, tail, p);
284 LIST_PREPEND(SocketPort, port, s->ports, p);
289 int config_parse_socket_bind(
290 const char *filename,
300 SocketAddressBindIPv6Only b;
309 b = socket_address_bind_ipv6_only_from_string(rvalue);
313 r = parse_boolean(rvalue);
315 log_error("[%s:%u] Failed to parse bind IPv6 only value, ignoring: %s", filename, line, rvalue);
319 s->bind_ipv6_only = r ? SOCKET_ADDRESS_IPV6_ONLY : SOCKET_ADDRESS_BOTH;
321 s->bind_ipv6_only = b;
326 int config_parse_exec_nice(
327 const char *filename,
336 ExecContext *c = data;
344 if (safe_atoi(rvalue, &priority) < 0) {
345 log_error("[%s:%u] Failed to parse nice priority, ignoring: %s. ", filename, line, rvalue);
349 if (priority < PRIO_MIN || priority >= PRIO_MAX) {
350 log_error("[%s:%u] Nice priority out of range, ignoring: %s", filename, line, rvalue);
360 int config_parse_exec_oom_score_adjust(
361 const char *filename,
370 ExecContext *c = data;
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);
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);
388 c->oom_score_adjust = oa;
389 c->oom_score_adjust_set = true;
394 int config_parse_exec(
395 const char *filename,
404 ExecCommand **e = data, *nce;
416 if (isempty(rvalue)) {
417 /* An empty assignment resets the list */
418 exec_command_free_list(*e);
423 /* We accept an absolute path as first argument, or
424 * alternatively an absolute prefixed with @ to allow
425 * overriding of argv[0]. */
431 bool honour_argv0 = false, ignore = false;
437 rvalue += strspn(rvalue, WHITESPACE);
442 for (i = 0; i < 2; i++) {
443 if (rvalue[0] == '-' && !ignore) {
448 if (rvalue[0] == '@' && !honour_argv0) {
454 if (*rvalue != '/') {
455 log_error("[%s:%u] Executable path is not absolute, ignoring: %s",
456 filename, line, rvalue);
461 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
462 if (strneq(w, ";", MAX(l, 1U)))
468 n = new(char*, k + !honour_argv0);
473 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
474 if (strneq(w, ";", MAX(l, 1U)))
476 else if (strneq(w, "\\;", MAX(l, 1U)))
479 if (honour_argv0 && w == rvalue) {
482 path = strndup(w, l);
488 if (!utf8_is_valid(path)) {
489 log_error("[%s:%u] Path is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
497 c = n[k++] = cunescape_length(w, l);
503 if (!utf8_is_valid(c)) {
504 log_error("[%s:%u] Path is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
514 log_error("[%s:%u] Invalid command line, ignoring: %s", filename, line, rvalue);
527 assert(path_is_absolute(path));
529 nce = new0(ExecCommand, 1);
537 nce->ignore = ignore;
539 path_kill_slashes(nce->path);
541 exec_command_append_list(e, nce);
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");
560 int config_parse_socket_bindtodevice(
561 const char *filename,
578 if (rvalue[0] && !streq(rvalue, "*")) {
585 free(s->bind_to_device);
586 s->bind_to_device = n;
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");
594 int config_parse_exec_io_class(
595 const char *filename,
604 ExecContext *c = data;
612 x = ioprio_class_from_string(rvalue);
614 log_error("[%s:%u] Failed to parse IO scheduling class, ignoring: %s", filename, line, rvalue);
618 c->ioprio = IOPRIO_PRIO_VALUE(x, IOPRIO_PRIO_DATA(c->ioprio));
619 c->ioprio_set = true;
624 int config_parse_exec_io_priority(
625 const char *filename,
634 ExecContext *c = data;
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);
647 c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_PRIO_CLASS(c->ioprio), i);
648 c->ioprio_set = true;
653 int config_parse_exec_cpu_sched_policy(
654 const char *filename,
664 ExecContext *c = data;
672 x = sched_policy_from_string(rvalue);
674 log_error("[%s:%u] Failed to parse CPU scheduling policy, ignoring: %s", filename, line, rvalue);
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;
686 int config_parse_exec_cpu_sched_prio(
687 const char *filename,
696 ExecContext *c = data;
704 if (safe_atoi(rvalue, &i) < 0) {
705 log_error("[%s:%u] Failed to parse CPU scheduling priority, ignoring: %s", filename, line, rvalue);
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);
713 if (i < min || i > max) {
714 log_error("[%s:%u] CPU scheduling priority is out of range, ignoring: %s", filename, line, rvalue);
718 c->cpu_sched_priority = i;
719 c->cpu_sched_set = true;
724 int config_parse_exec_cpu_affinity(
725 const char *filename,
734 ExecContext *c = data;
744 if (isempty(rvalue)) {
745 /* An empty assignment resets the CPU list */
752 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
753 char _cleanup_free_ *t = NULL;
761 r = safe_atou(t, &cpu);
764 c->cpuset = cpu_set_malloc(&c->cpuset_ncpus);
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);
775 CPU_SET_S(cpu, CPU_ALLOC_SIZE(c->cpuset_ncpus), c->cpuset);
781 int config_parse_exec_capabilities(
782 const char *filename,
791 ExecContext *c = data;
799 cap = cap_from_text(rvalue);
804 log_error("[%s:%u] Failed to parse capabilities, ignoring: %s", filename, line, rvalue);
809 cap_free(c->capabilities);
810 c->capabilities = cap;
815 int config_parse_exec_secure_bits(
816 const char *filename,
825 ExecContext *c = data;
835 if (isempty(rvalue)) {
836 /* An empty assignment resets the field */
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;
855 log_error("[%s:%u] Failed to parse secure bits, ignoring: %s",
856 filename, line, rvalue);
864 int config_parse_bounding_set(
865 const char *filename,
874 uint64_t *capability_bounding_set_drop = data;
886 if (isempty(rvalue)) {
887 /* An empty assignment resets */
888 *capability_bounding_set_drop = 0;
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);
1004 r = unit_add_cgroup_from_text(u, ku, true, NULL);
1006 log_error("[%s:%u] Failed to parse cgroup value %s, ignoring: %s",
1007 filename, line, k, rvalue);
1015 #ifdef HAVE_SYSV_COMPAT
1016 int config_parse_sysv_priority(
1017 const char *filename,
1019 const char *section,
1026 int *priority = data;
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);
1039 *priority = (int) i;
1044 int config_parse_fsck_passno(
1045 const char *filename,
1047 const char *section,
1062 if (safe_atoi(rvalue, &i) || i < 0) {
1063 log_error("[%s:%u] Failed to parse fsck pass number, ignoring: %s", filename, line, rvalue);
1071 DEFINE_CONFIG_PARSE_ENUM(config_parse_kill_mode, kill_mode, KillMode, "Failed to parse kill mode");
1073 int config_parse_kill_signal(
1074 const char *filename,
1076 const char *section,
1091 r = signal_from_string_try_harder(rvalue);
1093 log_error("[%s:%u] Failed to parse kill signal, ignoring: %s", filename, line, rvalue);
1101 int config_parse_exec_mount_flags(
1102 const char *filename,
1104 const char *section,
1111 ExecContext *c = data;
1115 unsigned long flags = 0;
1122 FOREACH_WORD_SEPARATOR(w, l, rvalue, ", ", state) {
1123 char _cleanup_free_ *t;
1129 if (streq(t, "shared"))
1131 else if (streq(t, "slave"))
1133 else if (streq(w, "private"))
1134 flags |= MS_PRIVATE;
1136 log_error("[%s:%u] Failed to parse mount flag %s, ignoring: %s",
1137 filename, line, t, rvalue);
1142 c->mount_flags = flags;
1146 int config_parse_timer(
1147 const char *filename,
1149 const char *section,
1160 CalendarSpec *c = NULL;
1168 if (isempty(rvalue)) {
1169 /* Empty assignment resets list */
1170 timer_free_values(t);
1174 b = timer_base_from_string(lvalue);
1176 log_error("[%s:%u] Failed to parse timer base, ignoring: %s", filename, line, lvalue);
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);
1186 id = CLOCK_REALTIME;
1188 if (parse_usec(rvalue, &u) < 0) {
1189 log_error("[%s:%u] Failed to parse timer value, ignoring: %s", filename, line, rvalue);
1193 id = CLOCK_MONOTONIC;
1196 v = new0(TimerValue, 1);
1203 v->calendar_spec = c;
1205 LIST_PREPEND(TimerValue, value, t->values, v);
1210 int config_parse_timer_unit(
1211 const char *filename,
1213 const char *section,
1224 _cleanup_free_ char *p = NULL;
1231 dbus_error_init(&error);
1233 p = unit_name_printf(UNIT(t), rvalue);
1237 if (endswith(p, ".timer")) {
1238 log_error("[%s:%u] Unit cannot be of type timer, ignoring: %s", filename, line, rvalue);
1242 r = manager_load_unit(UNIT(t)->manager, p, NULL, NULL, &u);
1244 log_error("[%s:%u] Failed to load unit %s, ignoring: %s", filename, line, rvalue, bus_error(&error, r));
1245 dbus_error_free(&error);
1249 unit_ref_set(&t->unit, u);
1254 int config_parse_path_spec(
1255 const char *filename,
1257 const char *section,
1274 if (isempty(rvalue)) {
1275 /* Empty assignment clears list */
1280 b = path_type_from_string(lvalue);
1282 log_error("[%s:%u] Failed to parse path type, ignoring: %s", filename, line, lvalue);
1286 k = unit_full_printf(UNIT(p), rvalue);
1290 if (!path_is_absolute(k)) {
1291 log_error("[%s:%u] Path is not absolute, ignoring: %s", filename, line, k);
1296 s = new0(PathSpec, 1);
1302 s->path = path_kill_slashes(k);
1306 LIST_PREPEND(PathSpec, spec, p->specs, s);
1311 int config_parse_path_unit(
1312 const char *filename,
1314 const char *section,
1325 _cleanup_free_ char *p = NULL;
1332 dbus_error_init(&error);
1334 p = unit_name_printf(UNIT(t), rvalue);
1338 if (endswith(p, ".path")) {
1339 log_error("[%s:%u] Unit cannot be of type path, ignoring: %s", filename, line, p);
1343 r = manager_load_unit(UNIT(t)->manager, p, NULL, &error, &u);
1345 log_error("[%s:%u] Failed to load unit %s, ignoring: %s", filename, line, p, bus_error(&error, r));
1346 dbus_error_free(&error);
1350 unit_ref_set(&t->unit, u);
1355 int config_parse_socket_service(
1356 const char *filename,
1358 const char *section,
1369 _cleanup_free_ char *p = NULL;
1376 dbus_error_init(&error);
1378 p = unit_name_printf(UNIT(s), rvalue);
1382 if (!endswith(p, ".service")) {
1383 log_error("[%s:%u] Unit must be of type service, ignoring: %s", filename, line, rvalue);
1387 r = manager_load_unit(UNIT(s)->manager, p, NULL, &error, &x);
1389 log_error("[%s:%u] Failed to load unit %s, ignoring: %s", filename, line, rvalue, bus_error(&error, r));
1390 dbus_error_free(&error);
1394 unit_ref_set(&s->service, x);
1399 int config_parse_service_sockets(
1400 const char *filename,
1402 const char *section,
1419 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
1420 char _cleanup_free_ *t = NULL, *k = NULL;
1426 k = unit_name_printf(UNIT(s), t);
1430 if (!endswith(k, ".socket")) {
1431 log_error("[%s:%u] Unit must be of type socket, ignoring: %s",
1436 r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_WANTS, UNIT_AFTER, k, NULL, true);
1438 log_error("[%s:%u] Failed to add dependency on %s, ignoring: %s",
1439 filename, line, k, strerror(-r));
1441 r = unit_add_dependency_by_name(UNIT(s), UNIT_TRIGGERED_BY, k, NULL, true);
1449 int config_parse_service_timeout(
1450 const char *filename,
1452 const char *section,
1459 Service *s = userdata;
1467 r = config_parse_usec(filename, line, section, lvalue, ltype, rvalue, data, userdata);
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;
1480 int config_parse_unit_env_file(
1481 const char *filename,
1483 const char *section,
1492 _cleanup_free_ char *s = NULL;
1500 if (isempty(rvalue)) {
1501 /* Empty assignment frees the list */
1507 s = unit_full_printf(u, rvalue);
1511 if (!path_is_absolute(s[0] == '-' ? s + 1 : s)) {
1512 log_error("[%s:%u] Path '%s' is not absolute, ignoring.", filename, line, s);
1516 r = strv_extend(env, s);
1523 int config_parse_environ(
1524 const char *filename,
1526 const char *section,
1534 char*** env = data, *w, *state;
1536 _cleanup_free_ char *k = NULL;
1543 if (isempty(rvalue)) {
1544 /* Empty assignment resets the list */
1550 k = unit_full_printf(u, rvalue);
1554 FOREACH_WORD_QUOTED(w, l, k, state) {
1555 _cleanup_free_ char *n;
1558 n = cunescape_length(w, l);
1562 if (!env_assignment_is_valid(n)) {
1563 log_error("[%s:%u] Invalid environment assignment, ignoring: %s", filename, line, rvalue);
1567 x = strv_env_set(*env, n);
1578 int config_parse_ip_tos(
1579 const char *filename,
1581 const char *section,
1588 int *ip_tos = data, x;
1595 x = ip_tos_from_string(rvalue);
1597 log_error("[%s:%u] Failed to parse IP TOS value, ignoring: %s", filename, line, rvalue);
1605 int config_parse_unit_condition_path(
1606 const char *filename,
1608 const char *section,
1615 ConditionType cond = ltype;
1617 bool trigger, negate;
1619 _cleanup_free_ char *p = NULL;
1626 if (isempty(rvalue)) {
1627 /* Empty assignment resets the list */
1628 condition_free_list(u->conditions);
1629 u->conditions = NULL;
1633 trigger = rvalue[0] == '|';
1637 negate = rvalue[0] == '!';
1641 p = unit_full_printf(u, rvalue);
1645 if (!path_is_absolute(p)) {
1646 log_error("[%s:%u] Path in condition not absolute, ignoring: %s", filename, line, p);
1650 c = condition_new(cond, p, trigger, negate);
1654 LIST_PREPEND(Condition, conditions, u->conditions, c);
1658 int config_parse_unit_condition_string(
1659 const char *filename,
1661 const char *section,
1668 ConditionType cond = ltype;
1670 bool trigger, negate;
1672 _cleanup_free_ char *s = NULL;
1679 if (isempty(rvalue)) {
1680 /* Empty assignment resets the list */
1681 condition_free_list(u->conditions);
1682 u->conditions = NULL;
1686 trigger = rvalue[0] == '|';
1690 negate = rvalue[0] == '!';
1694 s = unit_full_printf(u, rvalue);
1698 c = condition_new(cond, s, trigger, negate);
1702 LIST_PREPEND(Condition, conditions, u->conditions, c);
1706 int config_parse_unit_condition_null(
1707 const char *filename,
1709 const char *section,
1718 bool trigger, negate;
1726 if (isempty(rvalue)) {
1727 /* Empty assignment resets the list */
1728 condition_free_list(u->conditions);
1729 u->conditions = NULL;
1733 trigger = rvalue[0] == '|';
1737 negate = rvalue[0] == '!';
1741 b = parse_boolean(rvalue);
1743 log_error("[%s:%u] Failed to parse boolean value in condition, ignoring: %s", filename, line, rvalue);
1750 c = condition_new(CONDITION_NULL, NULL, trigger, negate);
1754 LIST_PREPEND(Condition, conditions, u->conditions, c);
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");
1761 int config_parse_unit_cgroup_attr(
1762 const char *filename,
1764 const char *section,
1772 _cleanup_strv_free_ char **l = NULL;
1780 if (isempty(rvalue)) {
1781 /* Empty assignment clears the list */
1782 cgroup_attribute_free_list(u->cgroup_attributes);
1783 u->cgroup_attributes = NULL;
1787 l = strv_split_quoted(rvalue);
1791 if (strv_length(l) != 2) {
1792 log_error("[%s:%u] Failed to parse cgroup attribute value, ignoring: %s", filename, line, rvalue);
1796 r = unit_add_cgroup_attribute(u, NULL, l[0], l[1], NULL, NULL);
1798 log_error("[%s:%u] Failed to add cgroup attribute value, ignoring: %s", filename, line, rvalue);
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) {
1809 _cleanup_free_ char *t = NULL;
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);
1821 if (asprintf(&t, "%lu", ul) < 0)
1824 r = unit_add_cgroup_attribute(u, "cpu", "cpu.shares", t, NULL, NULL);
1826 log_error("[%s:%u] Failed to add cgroup attribute value, ignoring: %s", filename, line, rvalue);
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) {
1837 _cleanup_free_ char *t = NULL;
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);
1849 if (asprintf(&t, "%llu", (unsigned long long) sz) < 0)
1852 r = unit_add_cgroup_attribute(u,
1854 streq(lvalue, "MemorySoftLimit") ? "memory.soft_limit_in_bytes" : "memory.limit_in_bytes",
1857 log_error("[%s:%u] Failed to add cgroup attribute value, ignoring: %s", filename, line, rvalue);
1864 static int device_map(const char *controller, const char *name, const char *value, char **ret) {
1865 _cleanup_strv_free_ char **l = NULL;
1872 l = strv_split_quoted(value);
1876 assert(strv_length(l) >= 1);
1878 if (streq(l[0], "*")) {
1880 if (asprintf(ret, "a *:*%s%s",
1881 isempty(l[1]) ? "" : " ", strempty(l[1])) < 0)
1886 if (stat(l[0], &st) < 0) {
1887 log_warning("Couldn't stat device %s", l[0]);
1891 if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) {
1892 log_warning("%s is not a device.", l[0]);
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)
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) {
1908 _cleanup_strv_free_ char **l = NULL;
1917 l = strv_split_quoted(rvalue);
1922 if (k < 1 || k > 2) {
1923 log_error("[%s:%u] Failed to parse device value, ignoring: %s", filename, line, rvalue);
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);
1932 if (!isempty(l[1]) && !in_charset(l[1], "rwm")) {
1933 log_error("[%s:%u] Device access string invalid, ignoring: %s", filename, line, rvalue);
1937 r = unit_add_cgroup_attribute(u, "devices",
1938 streq(lvalue, "DeviceAllow") ? "devices.allow" : "devices.deny",
1939 rvalue, device_map, NULL);
1942 log_error("[%s:%u] Failed to add cgroup attribute value, ignoring: %s", filename, line, rvalue);
1949 static int blkio_map(const char *controller, const char *name, const char *value, char **ret) {
1951 _cleanup_strv_free_ char **l = NULL;
1959 l = strv_split_quoted(value);
1963 assert(strv_length(l) == 2);
1965 if (stat(l[0], &st) < 0) {
1966 log_warning("Couldn't stat device %s", l[0]);
1970 if (S_ISBLK(st.st_mode))
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 */
1977 /* If this is a partition, try to get the originating
1979 block_get_whole_disk(d, &d);
1981 log_warning("%s is not a block device and file system block device cannot be determined or is not local.", l[0]);
1985 if (asprintf(ret, "%u:%u %s", major(d), minor(d), l[1]) < 0)
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) {
1995 const char *device = NULL, *weight;
1997 _cleanup_free_ char *t = NULL;
1998 _cleanup_strv_free_ char **l = NULL;
2005 l = strv_split_quoted(rvalue);
2010 if (k < 1 || k > 2) {
2011 log_error("[%s:%u] Failed to parse weight value, ignoring: %s", filename, line, rvalue);
2022 if (device && !path_is_absolute(device)) {
2023 log_error("[%s:%u] Failed to parse block device node value, ignoring: %s", filename, line, rvalue);
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);
2033 r = asprintf(&t, "%s %lu", device, ul);
2035 r = asprintf(&t, "%lu", ul);
2040 r = unit_add_cgroup_attribute(u, "blkio", "blkio.weight_device", t, blkio_map, NULL);
2042 r = unit_add_cgroup_attribute(u, "blkio", "blkio.weight", t, NULL, NULL);
2044 log_error("[%s:%u] Failed to add cgroup attribute value, ignoring: %s", filename, line, rvalue);
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) {
2056 _cleanup_free_ char *t = NULL;
2057 _cleanup_strv_free_ char **l = NULL;
2064 l = strv_split_quoted(rvalue);
2070 log_error("[%s:%u] Failed to parse bandwidth value, ignoring: %s", filename, line, rvalue);
2074 if (!path_is_absolute(l[0])) {
2075 log_error("[%s:%u] Failed to parse block device node value, ignoring: %s", filename, line, rvalue);
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);
2084 r = asprintf(&t, "%s %llu", l[0], (unsigned long long) bytes);
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);
2092 log_error("[%s:%u] Failed to add cgroup attribute value, ignoring: %s", filename, line, rvalue);
2099 int config_parse_unit_requires_mounts_for(
2100 const char *filename,
2102 const char *section,
2118 empty_before = !u->requires_mounts_for;
2120 r = config_parse_path_strv(filename, line, section, lvalue, ltype, rvalue, data, userdata);
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);
2129 int config_parse_documentation(
2130 const char *filename,
2132 const char *section,
2148 if (isempty(rvalue)) {
2149 /* Empty assignment resets the list */
2150 strv_free(u->documentation);
2151 u->documentation = NULL;
2155 r = config_parse_unit_strv_printf(filename, line, section, lvalue, ltype, rvalue, data, userdata);
2159 for (a = b = u->documentation; a && *a; a++) {
2161 if (is_valid_documentation_url(*a))
2164 log_error("[%s:%u] Invalid URL, ignoring: %s", filename, line, *a);
2173 static void syscall_set(uint32_t *p, int nr) {
2174 nr = SYSCALL_TO_INDEX(nr);
2175 p[nr >> 4] |= 1 << (nr & 31);
2178 static void syscall_unset(uint32_t *p, int nr) {
2179 nr = SYSCALL_TO_INDEX(nr);
2180 p[nr >> 4] &= ~(1 << (nr & 31));
2183 int config_parse_syscall_filter(
2184 const char *filename,
2186 const char *section,
2193 ExecContext *c = data;
2195 bool invert = false;
2205 if (isempty(rvalue)) {
2206 /* Empty assignment resets the list */
2207 free(c->syscall_filter);
2208 c->syscall_filter = NULL;
2212 if (rvalue[0] == '~') {
2217 if (!c->syscall_filter) {
2220 n = (syscall_max() + 31) >> 4;
2221 c->syscall_filter = new(uint32_t, n);
2222 if (!c->syscall_filter)
2225 memset(c->syscall_filter, invert ? 0xFF : 0, n * sizeof(uint32_t));
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);
2233 syscall_set(c->syscall_filter, __NR_exit_group);
2234 syscall_set(c->syscall_filter, __NR_exit);
2237 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
2239 char _cleanup_free_ *t = NULL;
2245 id = syscall_from_name(t);
2247 log_error("[%s:%u] Failed to parse syscall, ignoring: %s",
2253 syscall_unset(c->syscall_filter, id);
2255 syscall_set(c->syscall_filter, id);
2258 c->no_new_privileges = true;
2263 #define FOLLOW_MAX 8
2265 static int open_follow(char **filename, FILE **_f, Set *names, char **_final) {
2276 /* This will update the filename pointer if the loaded file is
2277 * reached by a symlink. The old string will be freed. */
2280 char *target, *name;
2282 if (c++ >= FOLLOW_MAX)
2285 path_kill_slashes(*filename);
2287 /* Add the file name we are currently looking at to
2288 * the names of this unit, but only if it is a valid
2290 name = path_get_file_name(*filename);
2292 if (unit_name_is_valid(name, true)) {
2294 id = set_get(names, name);
2300 r = set_put(names, id);
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);
2316 /* Hmm, so this is a symlink. Let's read the name, and follow it manually */
2317 r = readlink_and_make_absolute(*filename, &target);
2325 f = fdopen(fd, "re");
2328 close_nointr_nofail(fd);
2337 static int merge_by_names(Unit **u, Set *names, const char *id) {
2345 /* Let's try to add in all symlink names we found */
2346 while ((k = set_steal_first(names))) {
2348 /* First try to merge in the other name into our
2350 r = unit_merge_by_name(*u, k);
2354 /* Hmm, we couldn't merge the other unit into
2355 * ours? Then let's try it the other way
2358 other = manager_get_unit((*u)->manager, k);
2362 r = unit_merge(other, *u);
2365 return merge_by_names(u, names, NULL);
2373 unit_choose_id(*u, id);
2381 static int load_from_path(Unit *u, const char *path) {
2385 char *filename = NULL, *id = NULL;
2392 symlink_names = set_new(string_hash_func, string_compare_func);
2396 if (path_is_absolute(path)) {
2398 filename = strdup(path);
2404 r = open_follow(&filename, &f, symlink_names, &id);
2416 STRV_FOREACH(p, u->manager->lookup_paths.unit_path) {
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);
2427 if (u->manager->unit_path_cache &&
2428 !set_get(u->manager->unit_path_cache, filename))
2431 r = open_follow(&filename, &f, symlink_names, &id);
2440 /* Empty the symlink names for the next run */
2441 set_clear_free(symlink_names);
2450 /* Hmm, no suitable file found? */
2456 r = merge_by_names(&merged, symlink_names, id);
2461 u->load_state = UNIT_MERGED;
2466 if (fstat(fileno(f), &st) < 0) {
2471 if (null_or_empty(&st))
2472 u->load_state = UNIT_MASKED;
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);
2479 u->load_state = UNIT_LOADED;
2482 free(u->fragment_path);
2483 u->fragment_path = filename;
2486 u->fragment_mtime = timespec_load(&st.st_mtim);
2488 if (u->source_path) {
2489 if (stat(u->source_path, &st) >= 0)
2490 u->source_mtime = timespec_load(&st.st_mtim);
2492 u->source_mtime = 0;
2498 set_free_free(symlink_names);
2507 int unit_load_fragment(Unit *u) {
2513 assert(u->load_state == UNIT_STUB);
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);
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) {
2530 r = load_from_path(u, t);
2534 if (u->load_state != UNIT_STUB)
2538 /* And now, try looking for it under the suggested (originally linked) path */
2539 if (u->load_state == UNIT_STUB && u->fragment_path) {
2541 r = load_from_path(u, u->fragment_path);
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;
2554 /* Look for a template */
2555 if (u->load_state == UNIT_STUB && u->instance) {
2558 k = unit_name_template(u->id);
2562 r = load_from_path(u, k);
2568 if (u->load_state == UNIT_STUB)
2569 SET_FOREACH(t, u->names, i) {
2574 k = unit_name_template(t);
2578 r = load_from_path(u, k);
2584 if (u->load_state != UNIT_STUB)
2592 void unit_dump_config_items(FILE *f) {
2593 static const struct {
2594 const ConfigParserCallback callback;
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" },
2630 { config_parse_warn_compat, "NOTSUPPORTED" },
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" },
2654 const char *prev = NULL;
2659 NULSTR_FOREACH(i, load_fragment_gperf_nulstr) {
2660 const char *rvalue = "OTHER", *lvalue;
2664 const ConfigPerfItem *p;
2666 assert_se(p = load_fragment_gperf_lookup(i, strlen(i)));
2668 dot = strchr(i, '.');
2669 lvalue = dot ? dot + 1 : i;
2673 if (!prev || !strneq(prev, i, prefix_len+1)) {
2677 fprintf(f, "[%.*s]\n", (int) prefix_len, i);
2680 for (j = 0; j < ELEMENTSOF(table); j++)
2681 if (p->parse == table[j].callback) {
2682 rvalue = table[j].rvalue;
2686 fprintf(f, "%s=%s\n", lvalue, rvalue);