diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
index b21c5aa104..8fb9ecc6dc 100644
--- a/man/systemd.exec.xml
+++ b/man/systemd.exec.xml
@@ -728,7 +728,8 @@ CapabilityBoundingSet=~CAP_B CAP_C
Sets the I/O scheduling class for executed processes. Takes an integer between 0 and 3 or one
of the strings , , or
- . See
+ . If the empty string is assigned to this option, all prior assignments to both
+ IOSchedulingClass= and IOSchedulingPriority= have no effect. See
ioprio_set2 for
details.
@@ -738,7 +739,9 @@ CapabilityBoundingSet=~CAP_B CAP_C
Sets the I/O scheduling priority for executed processes. Takes an integer between 0 (highest
priority) and 7 (lowest priority). The available priorities depend on the selected I/O scheduling class (see
- above). See ioprio_set2 for
+ above). If the empty string is assigned to this option, all prior assignments to both
+ IOSchedulingClass= and IOSchedulingPriority= have no effect.
+ See ioprio_set2 for
details.
diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c
index 95a79f7b53..508f6a26f7 100644
--- a/src/basic/socket-util.c
+++ b/src/basic/socket-util.c
@@ -790,7 +790,7 @@ static const char* const socket_address_bind_ipv6_only_table[_SOCKET_ADDRESS_BIN
DEFINE_STRING_TABLE_LOOKUP(socket_address_bind_ipv6_only, SocketAddressBindIPv6Only);
-SocketAddressBindIPv6Only parse_socket_address_bind_ipv6_only_or_bool(const char *n) {
+SocketAddressBindIPv6Only socket_address_bind_ipv6_only_or_bool_from_string(const char *n) {
int r;
r = parse_boolean(n);
diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h
index c2b6107f49..9cd7f9ec54 100644
--- a/src/basic/socket-util.h
+++ b/src/basic/socket-util.h
@@ -116,7 +116,7 @@ int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret);
const char* socket_address_bind_ipv6_only_to_string(SocketAddressBindIPv6Only b) _const_;
SocketAddressBindIPv6Only socket_address_bind_ipv6_only_from_string(const char *s) _pure_;
-SocketAddressBindIPv6Only parse_socket_address_bind_ipv6_only_or_bool(const char *s);
+SocketAddressBindIPv6Only socket_address_bind_ipv6_only_or_bool_from_string(const char *s);
int netlink_family_to_string_alloc(int b, char **s);
int netlink_family_from_string(const char *s) _pure_;
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
index 977ef22c94..ec1b62fb42 100644
--- a/src/core/dbus-execute.c
+++ b/src/core/dbus-execute.c
@@ -1024,8 +1024,8 @@ static BUS_DEFINE_SET_TRANSIENT_IS_VALID(nice, "i", int32_t, int, "%" PRIi32, ni
static BUS_DEFINE_SET_TRANSIENT_PARSE(std_input, ExecInput, exec_input_from_string);
static BUS_DEFINE_SET_TRANSIENT_PARSE(std_output, ExecOutput, exec_output_from_string);
static BUS_DEFINE_SET_TRANSIENT_PARSE(utmp_mode, ExecUtmpMode, exec_utmp_mode_from_string);
-static BUS_DEFINE_SET_TRANSIENT_PARSE(protect_system, ProtectSystem, parse_protect_system_or_bool);
-static BUS_DEFINE_SET_TRANSIENT_PARSE(protect_home, ProtectHome, parse_protect_home_or_bool);
+static BUS_DEFINE_SET_TRANSIENT_PARSE(protect_system, ProtectSystem, protect_system_or_bool_from_string);
+static BUS_DEFINE_SET_TRANSIENT_PARSE(protect_home, ProtectHome, protect_home_or_bool_from_string);
static BUS_DEFINE_SET_TRANSIENT_PARSE(keyring_mode, ExecKeyringMode, exec_keyring_mode_from_string);
static BUS_DEFINE_SET_TRANSIENT_PARSE(preserve_mode, ExecPreserveMode, exec_preserve_mode_from_string);
static BUS_DEFINE_SET_TRANSIENT_PARSE_PTR(personality, unsigned long, parse_personality);
diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c
index 893e3d3839..88e180a037 100644
--- a/src/core/dbus-socket.c
+++ b/src/core/dbus-socket.c
@@ -142,7 +142,10 @@ static inline bool check_size_t_truncation(uint64_t t) {
return (size_t) t == t;
}
-static inline const char* socket_protocol_to_name_supported(int32_t i) {
+static inline const char* supported_socket_protocol_to_string(int32_t i) {
+ if (i == IPPROTO_IP)
+ return "";
+
if (!IN_SET(i, IPPROTO_UDPLITE, IPPROTO_SCTP))
return NULL;
@@ -152,11 +155,11 @@ static inline const char* socket_protocol_to_name_supported(int32_t i) {
static BUS_DEFINE_SET_TRANSIENT(int, "i", int32_t, int, "%" PRIi32);
static BUS_DEFINE_SET_TRANSIENT(message_queue, "x", int64_t, long, "%" PRIi64);
static BUS_DEFINE_SET_TRANSIENT_IS_VALID(size_t_check_truncation, "t", uint64_t, size_t, "%" PRIu64, check_size_t_truncation);
-static BUS_DEFINE_SET_TRANSIENT_PARSE(bind_ipv6_only, SocketAddressBindIPv6Only, parse_socket_address_bind_ipv6_only_or_bool);
+static BUS_DEFINE_SET_TRANSIENT_PARSE(bind_ipv6_only, SocketAddressBindIPv6Only, socket_address_bind_ipv6_only_or_bool_from_string);
static BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(fdname, fdname_is_valid);
static BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(ifname, ifname_valid);
static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(ip_tos, "i", int32_t, int, "%" PRIi32, ip_tos_to_string_alloc);
-static BUS_DEFINE_SET_TRANSIENT_TO_STRING(socket_protocol, "i", int32_t, int, "%" PRIi32, socket_protocol_to_name_supported);
+static BUS_DEFINE_SET_TRANSIENT_TO_STRING(socket_protocol, "i", int32_t, int, "%" PRIi32, supported_socket_protocol_to_string);
static int bus_socket_set_transient_property(
Socket *s,
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index 3757a651b2..44c9978c54 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -59,11 +59,11 @@ $1.SyslogLevelPrefix, config_parse_bool, 0,
$1.LogLevelMax, config_parse_log_level, 0, offsetof($1, exec_context.log_level_max)
$1.LogExtraFields, config_parse_log_extra_fields, 0, offsetof($1, exec_context)
$1.Capabilities, config_parse_warn_compat, DISABLED_LEGACY, offsetof($1, exec_context)
-$1.SecureBits, config_parse_exec_secure_bits, 0, offsetof($1, exec_context)
+$1.SecureBits, config_parse_exec_secure_bits, 0, offsetof($1, exec_context.secure_bits)
$1.CapabilityBoundingSet, config_parse_capability_set, 0, offsetof($1, exec_context.capability_bounding_set)
$1.AmbientCapabilities, config_parse_capability_set, 0, offsetof($1, exec_context.capability_ambient_set)
$1.TimerSlackNSec, config_parse_nsec, 0, offsetof($1, exec_context.timer_slack_nsec)
-$1.NoNewPrivileges, config_parse_no_new_privileges, 0, offsetof($1, exec_context)
+$1.NoNewPrivileges, config_parse_bool, 0, offsetof($1, exec_context.no_new_privileges)
$1.KeyringMode, config_parse_exec_keyring_mode, 0, offsetof($1, exec_context.keyring_mode)
m4_ifdef(`HAVE_SECCOMP',
`$1.SystemCallFilter, config_parse_syscall_filter, 0, offsetof($1, exec_context)
@@ -114,9 +114,9 @@ $1.ProtectKernelModules, config_parse_bool, 0,
$1.ProtectControlGroups, config_parse_bool, 0, offsetof($1, exec_context.protect_control_groups)
$1.PrivateNetwork, config_parse_bool, 0, offsetof($1, exec_context.private_network)
$1.PrivateUsers, config_parse_bool, 0, offsetof($1, exec_context.private_users)
-$1.ProtectSystem, config_parse_protect_system, 0, offsetof($1, exec_context)
-$1.ProtectHome, config_parse_protect_home, 0, offsetof($1, exec_context)
-$1.MountFlags, config_parse_exec_mount_flags, 0, offsetof($1, exec_context)
+$1.ProtectSystem, config_parse_protect_system, 0, offsetof($1, exec_context.protect_system)
+$1.ProtectHome, config_parse_protect_home, 0, offsetof($1, exec_context.protect_home)
+$1.MountFlags, config_parse_exec_mount_flags, 0, offsetof($1, exec_context.mount_flags)
$1.MountAPIVFS, config_parse_bool, 0, offsetof($1, exec_context.mount_apivfs)
$1.Personality, config_parse_personality, 0, offsetof($1, exec_context.personality)
$1.RuntimeDirectoryPreserve, config_parse_runtime_preserve_mode, 0, offsetof($1, exec_context.runtime_directory_preserve_mode)
@@ -155,8 +155,8 @@ $1.KillSignal, config_parse_signal, 0,
m4_define(`CGROUP_CONTEXT_CONFIG_ITEMS',
`$1.Slice, config_parse_unit_slice, 0, 0
$1.CPUAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.cpu_accounting)
-$1.CPUWeight, config_parse_cpu_weight, 0, offsetof($1, cgroup_context.cpu_weight)
-$1.StartupCPUWeight, config_parse_cpu_weight, 0, offsetof($1, cgroup_context.startup_cpu_weight)
+$1.CPUWeight, config_parse_cg_weight, 0, offsetof($1, cgroup_context.cpu_weight)
+$1.StartupCPUWeight, config_parse_cg_weight, 0, offsetof($1, cgroup_context.startup_cpu_weight)
$1.CPUShares, config_parse_cpu_shares, 0, offsetof($1, cgroup_context.cpu_shares)
$1.StartupCPUShares, config_parse_cpu_shares, 0, offsetof($1, cgroup_context.startup_cpu_shares)
$1.CPUQuota, config_parse_cpu_quota, 0, offsetof($1, cgroup_context)
@@ -169,8 +169,8 @@ $1.MemoryLimit, config_parse_memory_limit, 0,
$1.DeviceAllow, config_parse_device_allow, 0, offsetof($1, cgroup_context)
$1.DevicePolicy, config_parse_device_policy, 0, offsetof($1, cgroup_context.device_policy)
$1.IOAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.io_accounting)
-$1.IOWeight, config_parse_io_weight, 0, offsetof($1, cgroup_context.io_weight)
-$1.StartupIOWeight, config_parse_io_weight, 0, offsetof($1, cgroup_context.startup_io_weight)
+$1.IOWeight, config_parse_cg_weight, 0, offsetof($1, cgroup_context.io_weight)
+$1.StartupIOWeight, config_parse_cg_weight, 0, offsetof($1, cgroup_context.startup_io_weight)
$1.IODeviceWeight, config_parse_io_device_weight, 0, offsetof($1, cgroup_context)
$1.IOReadBandwidthMax, config_parse_io_limit, 0, offsetof($1, cgroup_context)
$1.IOWriteBandwidthMax, config_parse_io_limit, 0, offsetof($1, cgroup_context)
@@ -291,7 +291,7 @@ Service.ExecStopPost, config_parse_exec, SERVICE_EXE
Service.RestartSec, config_parse_sec, 0, offsetof(Service, restart_usec)
Service.TimeoutSec, config_parse_service_timeout, 0, 0
Service.TimeoutStartSec, config_parse_service_timeout, 0, 0
-Service.TimeoutStopSec, config_parse_service_timeout, 0, 0
+Service.TimeoutStopSec, config_parse_sec_fix_0, 0, offsetof(Service, timeout_stop_usec)
Service.RuntimeMaxSec, config_parse_sec, 0, offsetof(Service, runtime_max_usec)
Service.WatchdogSec, config_parse_sec, 0, offsetof(Service, watchdog_usec)
m4_dnl The following five only exist for compatibility, they moved into Unit, see above
@@ -330,8 +330,8 @@ Socket.ListenNetlink, config_parse_socket_listen, SOCKET_SOCK
Socket.ListenSpecial, config_parse_socket_listen, SOCKET_SPECIAL, 0
Socket.ListenMessageQueue, config_parse_socket_listen, SOCKET_MQUEUE, 0
Socket.ListenUSBFunction, config_parse_socket_listen, SOCKET_USB_FUNCTION, 0
-Socket.SocketProtocol, config_parse_socket_protocol, 0, 0
-Socket.BindIPv6Only, config_parse_socket_bind, 0, 0,
+Socket.SocketProtocol, config_parse_socket_protocol, 0, offsetof(Socket, socket_protocol)
+Socket.BindIPv6Only, config_parse_socket_bind, 0, offsetof(Socket, bind_ipv6_only)
Socket.Backlog, config_parse_unsigned, 0, offsetof(Socket, backlog)
Socket.BindToDevice, config_parse_socket_bindtodevice, 0, 0
Socket.ExecStartPre, config_parse_exec, SOCKET_EXEC_START_PRE, offsetof(Socket, exec_command)
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index f16b0d182b..dd4c755894 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -61,7 +61,42 @@
#include "utf8.h"
#include "web-util.h"
+static int supported_socket_protocol_from_string(const char *s) {
+ int r;
+
+ if (isempty(s))
+ return IPPROTO_IP;
+
+ r = socket_protocol_from_name(s);
+ if (r < 0)
+ return -EINVAL;
+ if (!IN_SET(r, IPPROTO_UDPLITE, IPPROTO_SCTP))
+ return -EPROTONOSUPPORT;
+
+ return r;
+}
+
+DEFINE_CONFIG_PARSE(config_parse_socket_protocol, supported_socket_protocol_from_string, "Failed to parse socket protocol");
+DEFINE_CONFIG_PARSE(config_parse_exec_secure_bits, secure_bits_from_string, "Failed to parse secure bits");
DEFINE_CONFIG_PARSE_ENUM(config_parse_collect_mode, collect_mode, CollectMode, "Failed to parse garbage collection mode");
+DEFINE_CONFIG_PARSE_ENUM(config_parse_device_policy, cgroup_device_policy, CGroupDevicePolicy, "Failed to parse device policy");
+DEFINE_CONFIG_PARSE_ENUM(config_parse_emergency_action, emergency_action, EmergencyAction, "Failed to parse failure action specifier");
+DEFINE_CONFIG_PARSE_ENUM(config_parse_exec_keyring_mode, exec_keyring_mode, ExecKeyringMode, "Failed to parse keyring mode");
+DEFINE_CONFIG_PARSE_ENUM(config_parse_exec_utmp_mode, exec_utmp_mode, ExecUtmpMode, "Failed to parse utmp mode");
+DEFINE_CONFIG_PARSE_ENUM(config_parse_job_mode, job_mode, JobMode, "Failed to parse job mode");
+DEFINE_CONFIG_PARSE_ENUM(config_parse_kill_mode, kill_mode, KillMode, "Failed to parse kill mode");
+DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier");
+DEFINE_CONFIG_PARSE_ENUM(config_parse_protect_home, protect_home_or_bool, ProtectHome, "Failed to parse protect home value");
+DEFINE_CONFIG_PARSE_ENUM(config_parse_protect_system, protect_system_or_bool, ProtectSystem, "Failed to parse protect system value");
+DEFINE_CONFIG_PARSE_ENUM(config_parse_runtime_preserve_mode, exec_preserve_mode, ExecPreserveMode, "Failed to parse runtime directory preserve mode");
+DEFINE_CONFIG_PARSE_ENUM(config_parse_service_type, service_type, ServiceType, "Failed to parse service type");
+DEFINE_CONFIG_PARSE_ENUM(config_parse_service_restart, service_restart, ServiceRestart, "Failed to parse service restart specifier");
+DEFINE_CONFIG_PARSE_ENUM(config_parse_socket_bind, socket_address_bind_ipv6_only_or_bool, SocketAddressBindIPv6Only, "Failed to parse bind IPv6 only value");
+DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_ip_tos, ip_tos, int, -1, "Failed to parse IP TOS value");
+DEFINE_CONFIG_PARSE_PTR(config_parse_blockio_weight, cg_blkio_weight_parse, uint64_t, "Invalid block IO weight");
+DEFINE_CONFIG_PARSE_PTR(config_parse_cg_weight, cg_weight_parse, uint64_t, "Invalid weight");
+DEFINE_CONFIG_PARSE_PTR(config_parse_cpu_shares, cg_cpu_shares_parse, uint64_t, "Invalid CPU shares");
+DEFINE_CONFIG_PARSE_PTR(config_parse_exec_mount_flags, mount_propagation_flags_from_string, unsigned long, "Failed to parse mount flag");
int config_parse_unit_deps(
const char *unit,
@@ -404,72 +439,6 @@ int config_parse_socket_listen(const char *unit,
return 0;
}
-int config_parse_socket_protocol(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
- Socket *s;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- s = SOCKET(data);
-
- r = socket_protocol_from_name(rvalue);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Invalid socket protocol '%s', ignoring: %m", rvalue);
- return 0;
- } else if (!IN_SET(r, IPPROTO_UDPLITE, IPPROTO_SCTP)) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Socket protocol not supported, ignoring: %s", rvalue);
- return 0;
- }
-
- s->socket_protocol = r;
-
- return 0;
-}
-
-int config_parse_socket_bind(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- Socket *s;
- SocketAddressBindIPv6Only b;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- s = SOCKET(data);
-
- b = parse_socket_address_bind_ipv6_only_or_bool(rvalue);
- if (b < 0) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse bind IPv6 only value, ignoring: %s", rvalue);
- return 0;
- }
-
- s->bind_ipv6_only = b;
-
- return 0;
-}
-
int config_parse_exec_nice(
const char *unit,
const char *filename,
@@ -490,6 +459,11 @@ int config_parse_exec_nice(
assert(rvalue);
assert(data);
+ if (isempty(rvalue)) {
+ c->nice_set = false;
+ return 0;
+ }
+
r = parse_nice(rvalue, &priority);
if (r < 0) {
if (r == -ERANGE)
@@ -779,9 +753,6 @@ int config_parse_exec(
return 0;
}
-DEFINE_CONFIG_PARSE_ENUM(config_parse_service_type, service_type, ServiceType, "Failed to parse service type");
-DEFINE_CONFIG_PARSE_ENUM(config_parse_service_restart, service_restart, ServiceRestart, "Failed to parse service restart specifier");
-
int config_parse_socket_bindtodevice(
const char* unit,
const char *filename,
@@ -1111,6 +1082,12 @@ int config_parse_exec_io_class(const char *unit,
assert(rvalue);
assert(data);
+ if (isempty(rvalue)) {
+ c->ioprio_set = false;
+ c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 0);
+ return 0;
+ }
+
x = ioprio_class_from_string(rvalue);
if (x < 0) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse IO scheduling class, ignoring: %s", rvalue);
@@ -1142,6 +1119,12 @@ int config_parse_exec_io_priority(const char *unit,
assert(rvalue);
assert(data);
+ if (isempty(rvalue)) {
+ c->ioprio_set = false;
+ c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 0);
+ return 0;
+ }
+
r = ioprio_parse_priority(rvalue, &i);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse IO priority, ignoring: %s", rvalue);
@@ -1173,6 +1156,13 @@ int config_parse_exec_cpu_sched_policy(const char *unit,
assert(rvalue);
assert(data);
+ if (isempty(rvalue)) {
+ c->cpu_sched_set = false;
+ c->cpu_sched_policy = SCHED_OTHER;
+ c->cpu_sched_priority = 0;
+ return 0;
+ }
+
x = sched_policy_from_string(rvalue);
if (x < 0) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse CPU scheduling policy, ignoring: %s", rvalue);
@@ -1277,43 +1267,6 @@ int config_parse_exec_cpu_affinity(const char *unit,
return 0;
}
-int config_parse_exec_secure_bits(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- ExecContext *c = data;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- if (isempty(rvalue)) {
- /* An empty assignment resets the field */
- c->secure_bits = 0;
- return 0;
- }
-
- r = secure_bits_from_string(rvalue);
- if (r < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, r,
- "Failed to parse secure bits, ignoring: %s", rvalue);
- return 0;
- }
-
- c->secure_bits = r;
-
- return 0;
-}
-
int config_parse_capability_set(
const char *unit,
const char *filename,
@@ -1365,71 +1318,6 @@ int config_parse_capability_set(
return 0;
}
-#if HAVE_SYSV_COMPAT
-int config_parse_sysv_priority(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- int *priority = data;
- int i, r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- r = safe_atoi(rvalue, &i);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse SysV start priority, ignoring: %s", rvalue);
- return 0;
- }
- if (i < 0) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid SysV start priority, ignoring: %s", rvalue);
- return 0;
- }
-
- *priority = (int) i;
- return 0;
-}
-#endif
-
-DEFINE_CONFIG_PARSE_ENUM(config_parse_exec_utmp_mode, exec_utmp_mode, ExecUtmpMode, "Failed to parse utmp mode");
-DEFINE_CONFIG_PARSE_ENUM(config_parse_kill_mode, kill_mode, KillMode, "Failed to parse kill mode");
-
-int config_parse_exec_mount_flags(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- ExecContext *c = data;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- r = mount_propagation_flags_from_string(rvalue, &c->mount_flags);
- if (r < 0)
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse mount flag %s, ignoring: %m", rvalue);
-
- return 0;
-}
-
int config_parse_exec_selinux_context(
const char *unit,
const char *filename,
@@ -1956,26 +1844,21 @@ int config_parse_service_timeout(
assert(rvalue);
assert(s);
- /* This is called for three cases: TimeoutSec=, TimeoutStopSec= and TimeoutStartSec=. */
+ /* This is called for two cases: TimeoutSec= and TimeoutStartSec=. */
- r = parse_sec(rvalue, &usec);
+ /* Traditionally, these options accepted 0 to disable the timeouts. However, a timeout of 0 suggests it happens
+ * immediately, hence fix this to become USEC_INFINITY instead. This is in-line with how we internally handle
+ * all other timeouts. */
+ r = parse_sec_fix_0(rvalue, &usec);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s= parameter, ignoring: %s", lvalue, rvalue);
return 0;
}
- /* Traditionally, these options accepted 0 to disable the timeouts. However, a timeout of 0 suggests it happens
- * immediately, hence fix this to become USEC_INFINITY instead. This is in-line with how we internally handle
- * all other timeouts. */
- if (usec <= 0)
- usec = USEC_INFINITY;
+ s->start_timeout_defined = true;
+ s->timeout_start_usec = usec;
- if (!streq(lvalue, "TimeoutStopSec")) {
- s->start_timeout_defined = true;
- s->timeout_start_usec = usec;
- }
-
- if (!streq(lvalue, "TimeoutStartSec"))
+ if (streq(lvalue, "TimeoutSec"))
s->timeout_stop_usec = usec;
return 0;
@@ -2139,6 +2022,12 @@ int config_parse_working_directory(
assert(c);
assert(u);
+ if (isempty(rvalue)) {
+ c->working_directory_home = false;
+ c->working_directory = mfree(c->working_directory);
+ return 0;
+ }
+
if (rvalue[0] == '-') {
missing_ok = true;
rvalue++;
@@ -2514,34 +2403,6 @@ int config_parse_log_extra_fields(
}
}
-int config_parse_ip_tos(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- int *ip_tos = data, x;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- x = ip_tos_from_string(rvalue);
- if (x < 0) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse IP TOS value, ignoring: %s", rvalue);
- return 0;
- }
-
- *ip_tos = x;
- return 0;
-}
-
int config_parse_unit_condition_path(
const char *unit,
const char *filename,
@@ -2703,9 +2564,6 @@ int config_parse_unit_condition_null(
return 0;
}
-DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier");
-DEFINE_CONFIG_PARSE_ENUM(config_parse_emergency_action, emergency_action, EmergencyAction, "Failed to parse failure action specifier");
-
int config_parse_unit_requires_mounts_for(
const char *unit,
const char *filename,
@@ -3152,64 +3010,6 @@ int config_parse_unit_slice(
return 0;
}
-DEFINE_CONFIG_PARSE_ENUM(config_parse_device_policy, cgroup_device_policy, CGroupDevicePolicy, "Failed to parse device policy");
-
-int config_parse_cpu_weight(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- uint64_t *weight = data;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
-
- r = cg_weight_parse(rvalue, weight);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Invalid CPU weight '%s', ignoring: %m", rvalue);
- return 0;
- }
-
- return 0;
-}
-
-int config_parse_cpu_shares(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- uint64_t *shares = data;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
-
- r = cg_cpu_shares_parse(rvalue, shares);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Invalid CPU shares '%s', ignoring: %m", rvalue);
- return 0;
- }
-
- return 0;
-}
-
int config_parse_cpu_quota(
const char *unit,
const char *filename,
@@ -3487,34 +3287,6 @@ int config_parse_device_allow(
return 0;
}
-int config_parse_io_weight(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- uint64_t *weight = data;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
-
- r = cg_weight_parse(rvalue, weight);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Invalid IO weight '%s', ignoring.", rvalue);
- return 0;
- }
-
- return 0;
-}
-
int config_parse_io_device_weight(
const char *unit,
const char *filename,
@@ -3687,34 +3459,6 @@ int config_parse_io_limit(
return 0;
}
-int config_parse_blockio_weight(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- uint64_t *weight = data;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
-
- r = cg_blkio_weight_parse(rvalue, weight);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Invalid block IO weight '%s', ignoring: %m", rvalue);
- return 0;
- }
-
- return 0;
-}
-
int config_parse_blockio_device_weight(
const char *unit,
const char *filename,
@@ -3885,8 +3629,6 @@ int config_parse_blockio_bandwidth(
return 0;
}
-DEFINE_CONFIG_PARSE_ENUM(config_parse_job_mode, job_mode, JobMode, "Failed to parse job mode");
-
int config_parse_job_mode_isolate(
const char *unit,
const char *filename,
@@ -3918,8 +3660,6 @@ int config_parse_job_mode_isolate(
return 0;
}
-DEFINE_CONFIG_PARSE_ENUM(config_parse_runtime_preserve_mode, exec_preserve_mode, ExecPreserveMode, "Failed to parse runtime directory preserve mode");
-
int config_parse_exec_directories(
const char *unit,
const char *filename,
@@ -4369,104 +4109,6 @@ int config_parse_bind_paths(
return 0;
}
-int config_parse_no_new_privileges(
- const char* unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- ExecContext *c = data;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- r = parse_boolean(rvalue);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse boolean value, ignoring: %s", rvalue);
- return 0;
- }
-
- c->no_new_privileges = r;
-
- return 0;
-}
-
-int config_parse_protect_home(
- const char* unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- ExecContext *c = data;
- ProtectHome h;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- /* Our enum shall be a superset of booleans, hence first try
- * to parse as boolean, and then as enum */
-
- h = parse_protect_home_or_bool(rvalue);
- if (h < 0) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse protect home value, ignoring: %s", rvalue);
- return 0;
- }
-
- c->protect_home = h;
-
- return 0;
-}
-
-int config_parse_protect_system(
- const char* unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- ExecContext *c = data;
- ProtectSystem s;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- s = parse_protect_system_or_bool(rvalue);
- if (s < 0) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse protect system value, ignoring: %s", rvalue);
- return 0;
- }
-
- c->protect_system = s;
-
- return 0;
-}
-
-DEFINE_CONFIG_PARSE_ENUM(config_parse_exec_keyring_mode, exec_keyring_mode, ExecKeyringMode, "Failed to parse keyring mode");
-
int config_parse_job_timeout_sec(
const char* unit,
const char *filename,
@@ -4875,9 +4517,7 @@ void unit_dump_config_items(FILE *f) {
const ConfigParserCallback callback;
const char *rvalue;
} table[] = {
-#if !HAVE_SYSV_COMPAT || !HAVE_SECCOMP || !HAVE_PAM || !HAVE_SELINUX || !ENABLE_SMACK || !HAVE_APPARMOR
{ config_parse_warn_compat, "NOTSUPPORTED" },
-#endif
{ config_parse_int, "INTEGER" },
{ config_parse_unsigned, "UNSIGNED" },
{ config_parse_iec_size, "SIZE" },
@@ -4908,9 +4548,6 @@ void unit_dump_config_items(FILE *f) {
{ config_parse_exec, "PATH [ARGUMENT [...]]" },
{ config_parse_service_type, "SERVICETYPE" },
{ config_parse_service_restart, "SERVICERESTART" },
-#if HAVE_SYSV_COMPAT
- { config_parse_sysv_priority, "SYSVPRIORITY" },
-#endif
{ config_parse_kill_mode, "KILLMODE" },
{ config_parse_signal, "SIGNAL" },
{ config_parse_socket_listen, "SOCKET [...]" },
@@ -4946,12 +4583,11 @@ void unit_dump_config_items(FILE *f) {
{ config_parse_restrict_namespaces, "NAMESPACES" },
#endif
{ config_parse_cpu_shares, "SHARES" },
- { config_parse_cpu_weight, "WEIGHT" },
+ { config_parse_cg_weight, "WEIGHT" },
{ config_parse_memory_limit, "LIMIT" },
{ config_parse_device_allow, "DEVICE" },
{ config_parse_device_policy, "POLICY" },
{ config_parse_io_limit, "LIMIT" },
- { config_parse_io_weight, "WEIGHT" },
{ config_parse_io_device_weight, "DEVICEWEIGHT" },
{ config_parse_blockio_bandwidth, "BANDWIDTH" },
{ config_parse_blockio_weight, "WEIGHT" },
diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h
index 4bfe943981..9a3ccd9d26 100644
--- a/src/core/load-fragment.h
+++ b/src/core/load-fragment.h
@@ -44,7 +44,6 @@ CONFIG_PARSER_PROTOTYPE(config_parse_exec_cpu_sched_prio);
CONFIG_PARSER_PROTOTYPE(config_parse_exec_cpu_affinity);
CONFIG_PARSER_PROTOTYPE(config_parse_exec_secure_bits);
CONFIG_PARSER_PROTOTYPE(config_parse_capability_set);
-CONFIG_PARSER_PROTOTYPE(config_parse_sysv_priority);
CONFIG_PARSER_PROTOTYPE(config_parse_kill_signal);
CONFIG_PARSER_PROTOTYPE(config_parse_exec_mount_flags);
CONFIG_PARSER_PROTOTYPE(config_parse_timer);
@@ -68,14 +67,13 @@ CONFIG_PARSER_PROTOTYPE(config_parse_environ);
CONFIG_PARSER_PROTOTYPE(config_parse_pass_environ);
CONFIG_PARSER_PROTOTYPE(config_parse_unset_environ);
CONFIG_PARSER_PROTOTYPE(config_parse_unit_slice);
-CONFIG_PARSER_PROTOTYPE(config_parse_cpu_weight);
+CONFIG_PARSER_PROTOTYPE(config_parse_cg_weight);
CONFIG_PARSER_PROTOTYPE(config_parse_cpu_shares);
CONFIG_PARSER_PROTOTYPE(config_parse_memory_limit);
CONFIG_PARSER_PROTOTYPE(config_parse_tasks_max);
CONFIG_PARSER_PROTOTYPE(config_parse_delegate);
CONFIG_PARSER_PROTOTYPE(config_parse_device_policy);
CONFIG_PARSER_PROTOTYPE(config_parse_device_allow);
-CONFIG_PARSER_PROTOTYPE(config_parse_io_weight);
CONFIG_PARSER_PROTOTYPE(config_parse_io_device_weight);
CONFIG_PARSER_PROTOTYPE(config_parse_io_limit);
CONFIG_PARSER_PROTOTYPE(config_parse_blockio_weight);
@@ -93,7 +91,6 @@ CONFIG_PARSER_PROTOTYPE(config_parse_exec_directories);
CONFIG_PARSER_PROTOTYPE(config_parse_set_status);
CONFIG_PARSER_PROTOTYPE(config_parse_namespace_path_strv);
CONFIG_PARSER_PROTOTYPE(config_parse_temporary_filesystems);
-CONFIG_PARSER_PROTOTYPE(config_parse_no_new_privileges);
CONFIG_PARSER_PROTOTYPE(config_parse_cpu_quota);
CONFIG_PARSER_PROTOTYPE(config_parse_protect_home);
CONFIG_PARSER_PROTOTYPE(config_parse_protect_system);
diff --git a/src/core/namespace.c b/src/core/namespace.c
index 3154cad58a..24da3b8a64 100644
--- a/src/core/namespace.c
+++ b/src/core/namespace.c
@@ -1682,7 +1682,7 @@ static const char *const protect_home_table[_PROTECT_HOME_MAX] = {
DEFINE_STRING_TABLE_LOOKUP(protect_home, ProtectHome);
-ProtectHome parse_protect_home_or_bool(const char *s) {
+ProtectHome protect_home_or_bool_from_string(const char *s) {
int r;
r = parse_boolean(s);
@@ -1703,7 +1703,7 @@ static const char *const protect_system_table[_PROTECT_SYSTEM_MAX] = {
DEFINE_STRING_TABLE_LOOKUP(protect_system, ProtectSystem);
-ProtectSystem parse_protect_system_or_bool(const char *s) {
+ProtectSystem protect_system_or_bool_from_string(const char *s) {
int r;
r = parse_boolean(s);
diff --git a/src/core/namespace.h b/src/core/namespace.h
index d8e4682255..705eb4e13a 100644
--- a/src/core/namespace.h
+++ b/src/core/namespace.h
@@ -97,11 +97,11 @@ int setup_netns(int netns_storage_socket[2]);
const char* protect_home_to_string(ProtectHome p) _const_;
ProtectHome protect_home_from_string(const char *s) _pure_;
-ProtectHome parse_protect_home_or_bool(const char *s);
+ProtectHome protect_home_or_bool_from_string(const char *s);
const char* protect_system_to_string(ProtectSystem p) _const_;
ProtectSystem protect_system_from_string(const char *s) _pure_;
-ProtectSystem parse_protect_system_or_bool(const char *s);
+ProtectSystem protect_system_or_bool_from_string(const char *s);
void bind_mount_free_many(BindMount *b, size_t n);
int bind_mount_add(BindMount **b, size_t *n, const BindMount *item);
diff --git a/src/core/socket.c b/src/core/socket.c
index 45c49eac49..238c942a1a 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -786,27 +786,28 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
"%sKeepAliveTimeSec: %s\n",
prefix, format_timespan(time_string, FORMAT_TIMESPAN_MAX, s->keep_alive_time, USEC_PER_SEC));
- if (s->keep_alive_interval)
+ if (s->keep_alive_interval > 0)
fprintf(f,
"%sKeepAliveIntervalSec: %s\n",
prefix, format_timespan(time_string, FORMAT_TIMESPAN_MAX, s->keep_alive_interval, USEC_PER_SEC));
- if (s->keep_alive_cnt)
+ if (s->keep_alive_cnt > 0)
fprintf(f,
"%sKeepAliveProbes: %u\n",
prefix, s->keep_alive_cnt);
- if (s->defer_accept)
+ if (s->defer_accept > 0)
fprintf(f,
"%sDeferAcceptSec: %s\n",
prefix, format_timespan(time_string, FORMAT_TIMESPAN_MAX, s->defer_accept, USEC_PER_SEC));
LIST_FOREACH(port, p, s->ports) {
- if (p->type == SOCKET_SOCKET) {
+ switch (p->type) {
+ case SOCKET_SOCKET: {
+ _cleanup_free_ char *k = NULL;
const char *t;
int r;
- char *k = NULL;
r = socket_address_print(&p->address, &k);
if (r < 0)
@@ -815,15 +816,20 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
t = k;
fprintf(f, "%s%s: %s\n", prefix, listen_lookup(socket_address_family(&p->address), p->address.type), t);
- free(k);
- } else if (p->type == SOCKET_SPECIAL)
+ break;
+ }
+ case SOCKET_SPECIAL:
fprintf(f, "%sListenSpecial: %s\n", prefix, p->path);
- else if (p->type == SOCKET_USB_FUNCTION)
+ break;
+ case SOCKET_USB_FUNCTION:
fprintf(f, "%sListenUSBFunction: %s\n", prefix, p->path);
- else if (p->type == SOCKET_MQUEUE)
+ break;
+ case SOCKET_MQUEUE:
fprintf(f, "%sListenMessageQueue: %s\n", prefix, p->path);
- else
+ break;
+ default:
fprintf(f, "%sListenFIFO: %s\n", prefix, p->path);
+ }
}
fprintf(f,
@@ -1033,43 +1039,43 @@ static void socket_apply_socket_options(Socket *s, int fd) {
assert(fd >= 0);
if (s->keep_alive) {
- int b = s->keep_alive;
- if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &b, sizeof(b)) < 0)
+ int one = 1;
+ if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(one)) < 0)
log_unit_warning_errno(UNIT(s), errno, "SO_KEEPALIVE failed: %m");
}
- if (s->keep_alive_time) {
+ if (s->keep_alive_time > 0) {
int value = s->keep_alive_time / USEC_PER_SEC;
if (setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &value, sizeof(value)) < 0)
log_unit_warning_errno(UNIT(s), errno, "TCP_KEEPIDLE failed: %m");
}
- if (s->keep_alive_interval) {
+ if (s->keep_alive_interval > 0) {
int value = s->keep_alive_interval / USEC_PER_SEC;
if (setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &value, sizeof(value)) < 0)
log_unit_warning_errno(UNIT(s), errno, "TCP_KEEPINTVL failed: %m");
}
- if (s->keep_alive_cnt) {
+ if (s->keep_alive_cnt > 0) {
int value = s->keep_alive_cnt;
if (setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &value, sizeof(value)) < 0)
log_unit_warning_errno(UNIT(s), errno, "TCP_KEEPCNT failed: %m");
}
- if (s->defer_accept) {
+ if (s->defer_accept > 0) {
int value = s->defer_accept / USEC_PER_SEC;
if (setsockopt(fd, SOL_TCP, TCP_DEFER_ACCEPT, &value, sizeof(value)) < 0)
log_unit_warning_errno(UNIT(s), errno, "TCP_DEFER_ACCEPT failed: %m");
}
if (s->no_delay) {
- int b = s->no_delay;
+ int one = 1;
if (s->socket_protocol == IPPROTO_SCTP) {
- if (setsockopt(fd, SOL_SCTP, SCTP_NODELAY, &b, sizeof(b)) < 0)
+ if (setsockopt(fd, SOL_SCTP, SCTP_NODELAY, &one, sizeof(one)) < 0)
log_unit_warning_errno(UNIT(s), errno, "SCTP_NODELAY failed: %m");
} else {
- if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &b, sizeof(b)) < 0)
+ if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one)) < 0)
log_unit_warning_errno(UNIT(s), errno, "TCP_NODELAY failed: %m");
}
}
@@ -1100,7 +1106,6 @@ static void socket_apply_socket_options(Socket *s, int fd) {
int value = (int) s->receive_buffer;
/* We first try with SO_RCVBUFFORCE, in case we have the perms for that */
-
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &value, sizeof(value)) < 0)
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) < 0)
log_unit_warning_errno(UNIT(s), errno, "SO_RCVBUF failed: %m");
@@ -1190,7 +1195,7 @@ static int fifo_address_create(
return r;
/* Enforce the right access mode for the fifo */
- old_mask = umask(~ socket_mode);
+ old_mask = umask(~socket_mode);
/* Include the original umask in our mask */
(void) umask(~socket_mode | old_mask);
@@ -1294,7 +1299,7 @@ static int mq_address_create(
}
/* Enforce the right access mode for the mq */
- old_mask = umask(~ mq_mode);
+ old_mask = umask(~mq_mode);
/* Include the original umask in our mask */
(void) umask(~mq_mode | old_mask);
diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c
index b74daefa2b..c74c83ba5b 100644
--- a/src/shared/conf-parser.c
+++ b/src/shared/conf-parser.c
@@ -502,34 +502,7 @@ int config_parse_many(
}
#define DEFINE_PARSER(type, vartype, conv_func) \
- int config_parse_##type( \
- const char *unit, \
- const char *filename, \
- unsigned line, \
- const char *section, \
- unsigned section_line, \
- const char *lvalue, \
- int ltype, \
- const char *rvalue, \
- void *data, \
- void *userdata) { \
- \
- vartype *i = data; \
- int r; \
- \
- assert(filename); \
- assert(lvalue); \
- assert(rvalue); \
- assert(data); \
- \
- r = conv_func(rvalue, i); \
- if (r < 0) \
- log_syntax(unit, LOG_ERR, filename, line, r, \
- "Failed to parse %s value, ignoring: %s", \
- #type, rvalue); \
- \
- return 0; \
- }
+ DEFINE_CONFIG_PARSE_PTR(config_parse_##type, conv_func, vartype, "Failed to parse " #type " value")
DEFINE_PARSER(int, int, safe_atoi);
DEFINE_PARSER(long, long, safe_atoli);
diff --git a/src/shared/conf-parser.h b/src/shared/conf-parser.h
index 0b0532d1ab..70d313d4eb 100644
--- a/src/shared/conf-parser.h
+++ b/src/shared/conf-parser.h
@@ -152,7 +152,45 @@ typedef enum Disabled {
DISABLED_EXPERIMENTAL,
} Disabled;
-#define DEFINE_CONFIG_PARSE_ENUM(function,name,type,msg) \
+#define DEFINE_CONFIG_PARSE(function, parser, msg) \
+ CONFIG_PARSER_PROTOTYPE(function) { \
+ int *i = data, r; \
+ \
+ assert(filename); \
+ assert(lvalue); \
+ assert(rvalue); \
+ assert(data); \
+ \
+ r = parser(rvalue); \
+ if (r < 0) { \
+ log_syntax(unit, LOG_ERR, filename, line, r, \
+ msg ", ignoring: %s", rvalue); \
+ return 0; \
+ } \
+ \
+ *i = r; \
+ return 0; \
+ }
+
+#define DEFINE_CONFIG_PARSE_PTR(function, parser, type, msg) \
+ CONFIG_PARSER_PROTOTYPE(function) { \
+ type *i = data; \
+ int r; \
+ \
+ assert(filename); \
+ assert(lvalue); \
+ assert(rvalue); \
+ assert(data); \
+ \
+ r = parser(rvalue, i); \
+ if (r < 0) \
+ log_syntax(unit, LOG_ERR, filename, line, r, \
+ msg ", ignoring: %s", rvalue); \
+ \
+ return 0; \
+ }
+
+#define DEFINE_CONFIG_PARSE_ENUM(function, name, type, msg) \
CONFIG_PARSER_PROTOTYPE(function) { \
type *i = data, x; \
\
@@ -161,8 +199,9 @@ typedef enum Disabled {
assert(rvalue); \
assert(data); \
\
- if ((x = name##_from_string(rvalue)) < 0) { \
- log_syntax(unit, LOG_ERR, filename, line, -x, \
+ x = name##_from_string(rvalue); \
+ if (x < 0) { \
+ log_syntax(unit, LOG_ERR, filename, line, 0, \
msg ", ignoring: %s", rvalue); \
return 0; \
} \
@@ -171,7 +210,32 @@ typedef enum Disabled {
return 0; \
}
-#define DEFINE_CONFIG_PARSE_ENUMV(function,name,type,invalid,msg) \
+#define DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(function, name, type, default_value, msg) \
+ CONFIG_PARSER_PROTOTYPE(function) { \
+ type *i = data, x; \
+ \
+ assert(filename); \
+ assert(lvalue); \
+ assert(rvalue); \
+ assert(data); \
+ \
+ if (isempty(rvalue)) { \
+ *i = default_value; \
+ return 0; \
+ } \
+ \
+ x = name##_from_string(rvalue); \
+ if (x < 0) { \
+ log_syntax(unit, LOG_ERR, filename, line, 0, \
+ msg ", ignoring: %s", rvalue); \
+ return 0; \
+ } \
+ \
+ *i = x; \
+ return 0; \
+ }
+
+#define DEFINE_CONFIG_PARSE_ENUMV(function, name, type, invalid, msg) \
CONFIG_PARSER_PROTOTYPE(function) { \
type **enums = data, x, *ys; \
_cleanup_free_ type *xs = NULL; \
@@ -198,17 +262,17 @@ typedef enum Disabled {
return -ENOMEM; \
\
if ((x = name##_from_string(en)) < 0) { \
- log_syntax(unit, LOG_ERR, filename, line, \
- -x, msg ", ignoring: %s", en); \
+ log_syntax(unit, LOG_ERR, filename, line, 0, \
+ msg ", ignoring: %s", en); \
continue; \
} \
\
for (ys = xs; x != invalid && *ys != invalid; ys++) { \
if (*ys == x) { \
- log_syntax(unit, LOG_ERR, filename, \
- line, -x, \
- "Duplicate entry, ignoring: %s", \
- en); \
+ log_syntax(unit, LOG_NOTICE, filename, \
+ line, 0, \
+ "Duplicate entry, ignoring: %s", \
+ en); \
x = invalid; \
} \
} \