chiark / gitweb /
unit: distuingish mandatory from triggering conditions
authorLennart Poettering <lennart@poettering.net>
Tue, 8 Mar 2011 02:04:47 +0000 (03:04 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 8 Mar 2011 02:04:47 +0000 (03:04 +0100)
TODO
man/systemd.unit.xml
src/condition.c
src/condition.h
src/load-fragment.c
units/systemd-sysctl.service.in

diff --git a/TODO b/TODO
index 0a2f7619f606f3bb07749af23d1a0b151fac6e3a..cad97746ef4afa559c70df0c90717b25c8efe9fc 100644 (file)
--- a/TODO
+++ b/TODO
@@ -14,8 +14,6 @@ F15:
 
 * hook emergency.target into local-fs.target in some way as OnFailure with isolate
 
-* introduce simple way to do mandatory conditions (make current conditions mandatory, and introduce =| as non-mandatory conditions)
-
 * mount /dev/.run and /var/run as bind mounts
 
 * Make use of UnknownInterface, UnknownObject
index fa8821afe5a7c94b19578666511841f88dd4ec45..54903fb52fca93eb43e4ac0cb75e0c3df99c1284 100644 (file)
                                 environment and optionally test
                                 whether it is a specific
                                 implementation. Takes either boolean
-                                value to check if being executed in any
-                                virtual environment or one of the
+                                value to check if being executed in
+                                any virtual environment or one of the
                                 <varname>qemu</varname>,
                                 <varname>kvm</varname>,
                                 <varname>vmware</varname>,
                                 will always fail, otherwise
                                 succeed. If multiple conditions are
                                 specified the unit will be executed if
-                                at least one of them applies (i.e. a
-                                logical OR is
-                                applied).</para></listitem>
+                                all of them apply (i.e. a logical AND
+                                is applied). Condition checks can be
+                                prefixed with a pipe symbol (|) in
+                                which case a condition becomes a
+                                triggering condition. If at least one
+                                triggering condition is defined for a
+                                unit then the unit will be executed if
+                                at least one of the triggering
+                                conditions apply and all of the
+                                non-triggering conditions. If you
+                                prefix an argument with the pipe
+                                symbol and an exclamation mark the
+                                pipe symbol must be passed first, the
+                                exclamation second.</para></listitem>
                         </varlistentry>
                 </variablelist>
 
index 630350ed365ea818b4ac0806bfb3cb8940322746..1d6cf12ad4b71c46086d5791cd45d5bebd4d4de0 100644 (file)
 #include "util.h"
 #include "condition.h"
 
-Condition* condition_new(ConditionType type, const char *parameter, bool negate) {
+Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate) {
         Condition *c;
 
         c = new0(Condition, 1);
         c->type = type;
+        c->trigger = trigger;
         c->negate = negate;
 
         if (parameter)
@@ -153,17 +154,28 @@ bool condition_test(Condition *c) {
 
 bool condition_test_list(Condition *first) {
         Condition *c;
+        int triggered = -1;
 
         /* If the condition list is empty, then it is true */
         if (!first)
                 return true;
 
-        /* Otherwise, if any of the conditions apply we return true */
-        LIST_FOREACH(conditions, c, first)
-                if (condition_test(c))
-                        return true;
+        /* Otherwise, if all of the non-trigger conditions apply and
+         * if any of the trigger conditions apply (unless there are
+         * none) we return true */
+        LIST_FOREACH(conditions, c, first) {
+                bool b;
+
+                b = condition_test(c);
+
+                if (!c->trigger && !b)
+                        return false;
+
+                if (c->trigger && triggered <= 0)
+                        triggered = b;
+        }
 
-        return false;
+        return triggered != 0;
 }
 
 void condition_dump(Condition *c, FILE *f, const char *prefix) {
@@ -174,9 +186,10 @@ void condition_dump(Condition *c, FILE *f, const char *prefix) {
                 prefix = "";
 
         fprintf(f,
-                "%s%s: %s%s\n",
+                "%s%s: %s%s%s\n",
                 prefix,
                 condition_type_to_string(c->type),
+                c->trigger ? "|" : "",
                 c->negate ? "!" : "",
                 c->parameter);
 }
index f4903d76d98ce5a36e37b7114a7b0e89215c748e..0ce713bc16f14bf498ee799c48e8d5ecea238562 100644 (file)
@@ -39,12 +39,14 @@ typedef enum ConditionType {
 typedef struct Condition {
         ConditionType type;
         char *parameter;
-        bool negate;
+
+        bool trigger:1;
+        bool negate:1;
 
         LIST_FIELDS(struct Condition, conditions);
 } Condition;
 
-Condition* condition_new(ConditionType type, const char *parameter, bool negate);
+Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate);
 void condition_free(Condition *c);
 void condition_free_list(Condition *c);
 
index bd7529ff950461f59e184c02b822437a4e3cce38..334bc713be8f691bcb65ba7ebf93d2ef31e5aab5 100644 (file)
@@ -1397,7 +1397,7 @@ static int config_parse_condition_path(
                 void *userdata) {
 
         Unit *u = data;
-        bool negate;
+        bool trigger, negate;
         Condition *c;
 
         assert(filename);
@@ -1405,6 +1405,9 @@ static int config_parse_condition_path(
         assert(rvalue);
         assert(data);
 
+        if ((trigger = rvalue[0] == '|'))
+                rvalue++;
+
         if ((negate = rvalue[0] == '!'))
                 rvalue++;
 
@@ -1414,7 +1417,7 @@ static int config_parse_condition_path(
         }
 
         if (!(c = condition_new(streq(lvalue, "ConditionPathExists") ? CONDITION_PATH_EXISTS : CONDITION_DIRECTORY_NOT_EMPTY,
-                                rvalue, negate)))
+                                rvalue, trigger, negate)))
                 return -ENOMEM;
 
         LIST_PREPEND(Condition, conditions, u->meta.conditions, c);
@@ -1431,7 +1434,7 @@ static int config_parse_condition_kernel(
                 void *userdata) {
 
         Unit *u = data;
-        bool negate;
+        bool trigger, negate;
         Condition *c;
 
         assert(filename);
@@ -1439,10 +1442,13 @@ static int config_parse_condition_kernel(
         assert(rvalue);
         assert(data);
 
+        if ((trigger = rvalue[0] == '|'))
+                rvalue++;
+
         if ((negate = rvalue[0] == '!'))
                 rvalue++;
 
-        if (!(c = condition_new(CONDITION_KERNEL_COMMAND_LINE, rvalue, negate)))
+        if (!(c = condition_new(CONDITION_KERNEL_COMMAND_LINE, rvalue, trigger, negate)))
                 return -ENOMEM;
 
         LIST_PREPEND(Condition, conditions, u->meta.conditions, c);
@@ -1459,7 +1465,7 @@ static int config_parse_condition_virt(
                 void *userdata) {
 
         Unit *u = data;
-        bool negate;
+        bool trigger, negate;
         Condition *c;
 
         assert(filename);
@@ -1467,10 +1473,13 @@ static int config_parse_condition_virt(
         assert(rvalue);
         assert(data);
 
+        if ((trigger = rvalue[0] == '|'))
+                rvalue++;
+
         if ((negate = rvalue[0] == '!'))
                 rvalue++;
 
-        if (!(c = condition_new(CONDITION_VIRTUALIZATION, rvalue, negate)))
+        if (!(c = condition_new(CONDITION_VIRTUALIZATION, rvalue, trigger, negate)))
                 return -ENOMEM;
 
         LIST_PREPEND(Condition, conditions, u->meta.conditions, c);
@@ -1488,7 +1497,7 @@ static int config_parse_condition_null(
 
         Unit *u = data;
         Condition *c;
-        bool negate;
+        bool trigger, negate;
         int b;
 
         assert(filename);
@@ -1496,6 +1505,9 @@ static int config_parse_condition_null(
         assert(rvalue);
         assert(data);
 
+        if ((trigger = rvalue[0] == '|'))
+                rvalue++;
+
         if ((negate = rvalue[0] == '!'))
                 rvalue++;
 
@@ -1507,7 +1519,7 @@ static int config_parse_condition_null(
         if (!b)
                 negate = !negate;
 
-        if (!(c = condition_new(CONDITION_NULL, NULL, negate)))
+        if (!(c = condition_new(CONDITION_NULL, NULL, trigger, negate)))
                 return -ENOMEM;
 
         LIST_PREPEND(Condition, conditions, u->meta.conditions, c);
index ada447885fe72f2cf94f4f9adc3f666b23157bee..ea78230d7c0d04a123ec792840dad65985db1484 100644 (file)
@@ -11,8 +11,8 @@ DefaultDependencies=no
 Conflicts=shutdown.target
 After=systemd-readahead-collect.service systemd-readahead-replay.service
 Before=sysinit.target shutdown.target
-ConditionPathExists=/etc/sysctl.conf
-ConditionDirectoryNotEmpty=/etc/sysctl.d
+ConditionPathExists=|/etc/sysctl.conf
+ConditionDirectoryNotEmpty=|/etc/sysctl.d
 
 [Service]
 Type=oneshot