diff options
-rw-r--r-- | man/systemd.unit.xml | 27 | ||||
-rw-r--r-- | src/condition.c | 15 | ||||
-rw-r--r-- | src/condition.h | 1 | ||||
-rw-r--r-- | src/load-fragment.c | 41 |
4 files changed, 69 insertions, 15 deletions
diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml index 4e1d9f3070..39862cf7c8 100644 --- a/man/systemd.unit.xml +++ b/man/systemd.unit.xml @@ -574,6 +574,7 @@ <varlistentry> <term><varname>ConditionPathExists=</varname></term> <term><varname>ConditionKernelCommandLine=</varname></term> + <term><varname>ConditionNull=</varname></term> <listitem><para>Before starting a unit verify that the specified condition is @@ -602,15 +603,23 @@ must either be a single word, or an assignment (i.e. two words, seperated by the equality sign). In the former - case the kernel command line is search - for the word appearing as is, or as - left hand side of an assignment. In - the latter case the exact assignment - is looked for with right and left hand - side matching. If multiple conditions - are specified the unit will be - executed iff at least one of them - applies (i.e. a logical OR is + case the kernel command line is + searched for the word appearing as is, + or as left hand side of an + assignment. In the latter case the + exact assignment is looked for with + right and left hand side + matching. Finally, + <varname>ConditionNull=</varname> may + be used to add a constant condition + check value to the unit. It takes a + boolean argument. If set to + <varname>false</varname> the condition + will always fail, otherwise + succeed. If multiple conditions are + specified the unit will be executed + iff at least one of them applies + (i.e. a logical OR is applied).</para></listitem> </varlistentry> </variablelist> diff --git a/src/condition.c b/src/condition.c index 1e69b610ff..4bbd4dbafa 100644 --- a/src/condition.c +++ b/src/condition.c @@ -34,10 +34,11 @@ Condition* condition_new(ConditionType type, const char *parameter, bool negate) c->type = type; c->negate = negate; - if (!(c->parameter = strdup(parameter))) { - free(c); - return NULL; - } + if (parameter) + if (!(c->parameter = strdup(parameter))) { + free(c); + return NULL; + } return c; } @@ -108,6 +109,9 @@ bool condition_test(Condition *c) { case CONDITION_KERNEL_COMMAND_LINE: return !!test_kernel_command_line(c->parameter) == !c->negate; + case CONDITION_NULL: + return !c->negate; + default: assert_not_reached("Invalid condition type."); } @@ -152,7 +156,8 @@ void condition_dump_list(Condition *first, FILE *f, const char *prefix) { static const char* const condition_type_table[_CONDITION_TYPE_MAX] = { [CONDITION_KERNEL_COMMAND_LINE] = "ConditionKernelCommandLine", - [CONDITION_PATH_EXISTS] = "ConditionPathExists" + [CONDITION_PATH_EXISTS] = "ConditionPathExists", + [CONDITION_NULL] = "ConditionNull" }; DEFINE_STRING_TABLE_LOOKUP(condition_type, ConditionType); diff --git a/src/condition.h b/src/condition.h index 4e0d63cd51..b9d3f34aef 100644 --- a/src/condition.h +++ b/src/condition.h @@ -29,6 +29,7 @@ typedef enum ConditionType { CONDITION_PATH_EXISTS, CONDITION_KERNEL_COMMAND_LINE, + CONDITION_NULL, _CONDITION_TYPE_MAX, _CONDITION_TYPE_INVALID = -1 } ConditionType; diff --git a/src/load-fragment.c b/src/load-fragment.c index 4f94c6409e..424e6c37bb 100644 --- a/src/load-fragment.c +++ b/src/load-fragment.c @@ -1444,7 +1444,7 @@ static int config_parse_condition_path( rvalue++; if (!path_is_absolute(rvalue)) { - log_error("[%s:%u] Path in condition not absolute: %s", filename, line, rvalue); + log_error("[%s:%u] Path in condition not absolute, ignoring: %s", filename, line, rvalue); return 0; } @@ -1483,6 +1483,43 @@ static int config_parse_condition_kernel( return 0; } +static int config_parse_condition_null( + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + const char *rvalue, + void *data, + void *userdata) { + + Unit *u = data; + Condition *c; + bool negate; + int b; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if ((negate = rvalue[0] == '!')) + rvalue++; + + if ((b = parse_boolean(rvalue)) < 0) { + log_error("[%s:%u] Failed to parse boolean value in condition, ignoring: %s", filename, line, rvalue); + return 0; + } + + if (!b) + negate = !negate; + + if (!(c = condition_new(CONDITION_NULL, NULL, negate))) + return -ENOMEM; + + LIST_PREPEND(Condition, conditions, u->meta.conditions, c); + return 0; +} + static DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier"); #define FOLLOW_MAX 8 @@ -1656,6 +1693,7 @@ static void dump_items(FILE *f, const ConfigItem *items) { { config_parse_ip_tos, "TOS" }, { config_parse_condition_path, "CONDITION" }, { config_parse_condition_kernel, "CONDITION" }, + { config_parse_condition_null, "CONDITION" }, }; assert(f); @@ -1778,6 +1816,7 @@ static int load_from_path(Unit *u, const char *path) { { "JobTimeoutSec", config_parse_usec, &u->meta.job_timeout, "Unit" }, { "ConditionPathExists", config_parse_condition_path, u, "Unit" }, { "ConditionKernelCommandLine", config_parse_condition_kernel, u, "Unit" }, + { "ConditionNull", config_parse_condition_null, u, "Unit" }, { "PIDFile", config_parse_path, &u->service.pid_file, "Service" }, { "ExecStartPre", config_parse_exec, u->service.exec_command+SERVICE_EXEC_START_PRE, "Service" }, |