summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO2
-rw-r--r--src/core/condition.c8
-rw-r--r--src/core/condition.h6
-rw-r--r--src/core/dbus-unit.c177
-rw-r--r--src/core/dbus-unit.h1
-rw-r--r--src/core/unit.c3
-rw-r--r--src/systemctl/systemctl.c62
7 files changed, 180 insertions, 79 deletions
diff --git a/TODO b/TODO
index 4b75539f0a..753d1ccdb1 100644
--- a/TODO
+++ b/TODO
@@ -532,8 +532,6 @@ Features:
when done. That means clients don't get a successful method reply,
but much rather a disconnect on success.
-* remember which condition failed for services, not just the fact that something failed
-
* use opterr = 0 for all getopt tools
* properly handle loop back mounts via fstab, especially regards to fsck/passno
diff --git a/src/core/condition.c b/src/core/condition.c
index 2fbc5ad0e6..6c387450af 100644
--- a/src/core/condition.c
+++ b/src/core/condition.c
@@ -250,7 +250,7 @@ static bool test_ac_power(const char *parameter) {
return (on_ac_power() != 0) == !!r;
}
-bool condition_test(Condition *c) {
+static bool condition_test(Condition *c) {
assert(c);
switch(c->type) {
@@ -358,6 +358,7 @@ bool condition_test_list(const char *unit, Condition *first) {
c->parameter,
b ? "succeeded" : "failed",
unit);
+ c->state = b ? 1 : -1;
if (!c->trigger && !b)
return false;
@@ -377,12 +378,13 @@ void condition_dump(Condition *c, FILE *f, const char *prefix) {
prefix = "";
fprintf(f,
- "%s\t%s: %s%s%s\n",
+ "%s\t%s: %s%s%s %s\n",
prefix,
condition_type_to_string(c->type),
c->trigger ? "|" : "",
c->negate ? "!" : "",
- c->parameter);
+ c->parameter,
+ c->state < 0 ? "failed" : c->state > 0 ? "succeeded" : "untested");
}
void condition_dump_list(Condition *first, FILE *f, const char *prefix) {
diff --git a/src/core/condition.h b/src/core/condition.h
index 2ad77876e4..1813b735a5 100644
--- a/src/core/condition.h
+++ b/src/core/condition.h
@@ -48,11 +48,14 @@ typedef enum ConditionType {
typedef struct Condition {
ConditionType type;
- char *parameter;
bool trigger:1;
bool negate:1;
+ char *parameter;
+
+ int state;
+
LIST_FIELDS(struct Condition, conditions);
} Condition;
@@ -60,7 +63,6 @@ Condition* condition_new(ConditionType type, const char *parameter, bool trigger
void condition_free(Condition *c);
void condition_free_list(Condition *c);
-bool condition_test(Condition *c);
bool condition_test_list(const char *unit, Condition *c);
void condition_dump(Condition *c, FILE *f, const char *prefix);
diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
index ba4d42652e..4cd3a13fd2 100644
--- a/src/core/dbus-unit.c
+++ b/src/core/dbus-unit.c
@@ -311,6 +311,58 @@ static int bus_unit_append_need_daemon_reload(DBusMessageIter *i, const char *pr
return 0;
}
+static int bus_property_append_condition(DBusMessageIter *i, const char *property, void *data) {
+ Condition **cp = data;
+ Condition *c;
+ const char *name, *param;
+ dbus_bool_t trigger, negate;
+ dbus_int32_t state;
+ DBusMessageIter sub;
+
+ assert(i);
+ assert(property);
+ assert(cp);
+
+ c = *cp;
+ assert(c);
+
+ name = condition_type_to_string(c->type);
+ param = c->parameter;
+ trigger = c->trigger;
+ negate = c->negate;
+ state = c->state;
+
+ if (!dbus_message_iter_open_container(i, DBUS_TYPE_STRUCT, NULL, &sub) ||
+ !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &name) ||
+ !dbus_message_iter_append_basic(&sub, DBUS_TYPE_BOOLEAN, &trigger) ||
+ !dbus_message_iter_append_basic(&sub, DBUS_TYPE_BOOLEAN, &negate) ||
+ !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &param) ||
+ !dbus_message_iter_append_basic(&sub, DBUS_TYPE_INT32, &state) ||
+ !dbus_message_iter_close_container(i, &sub))
+ return -ENOMEM;
+
+ return 0;
+}
+
+static int bus_property_append_condition_list(DBusMessageIter *i, const char *property, void *data) {
+ Condition **first = data, *c;
+ DBusMessageIter sub;
+
+ assert(i);
+ assert(data);
+
+ if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sbbsi)", &sub))
+ return -ENOMEM;
+
+ LIST_FOREACH(conditions, c, *first)
+ bus_property_append_condition(&sub, property, &c);
+
+ if (!dbus_message_iter_close_container(i, &sub))
+ return -ENOMEM;
+
+ return 0;
+}
+
static int bus_unit_append_load_error(DBusMessageIter *i, const char *property, void *data) {
Unit *u = data;
const char *name, *message;
@@ -975,68 +1027,69 @@ int bus_unit_set_properties(
}
const BusProperty bus_unit_properties[] = {
- { "Id", bus_property_append_string, "s", offsetof(Unit, id), true },
- { "Names", bus_unit_append_names, "as", 0 },
- { "Following", bus_unit_append_following, "s", 0 },
- { "Requires", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUIRES]), true },
- { "RequiresOverridable", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUIRES_OVERRIDABLE]), true },
- { "Requisite", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUISITE]), true },
- { "RequisiteOverridable", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUISITE_OVERRIDABLE]), true },
- { "Wants", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_WANTS]), true },
- { "BindsTo", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_BINDS_TO]), true },
- { "PartOf", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_PART_OF]), true },
- { "RequiredBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUIRED_BY]), true },
- { "RequiredByOverridable",bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUIRED_BY_OVERRIDABLE]), true },
- { "WantedBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_WANTED_BY]), true },
- { "BoundBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_BOUND_BY]), true },
- { "ConsistsOf", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_CONSISTS_OF]), true },
- { "Conflicts", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_CONFLICTS]), true },
- { "ConflictedBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_CONFLICTED_BY]), true },
- { "Before", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_BEFORE]), true },
- { "After", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_AFTER]), true },
- { "OnFailure", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_ON_FAILURE]), true },
- { "Triggers", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_TRIGGERS]), true },
- { "TriggeredBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_TRIGGERED_BY]), true },
- { "PropagatesReloadTo", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_PROPAGATES_RELOAD_TO]), true },
- { "ReloadPropagatedFrom", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_RELOAD_PROPAGATED_FROM]), true },
- { "RequiresMountsFor", bus_property_append_strv, "as", offsetof(Unit, requires_mounts_for), true },
- { "Documentation", bus_property_append_strv, "as", offsetof(Unit, documentation), true },
- { "Description", bus_unit_append_description, "s", 0 },
- { "LoadState", bus_unit_append_load_state, "s", offsetof(Unit, load_state) },
- { "ActiveState", bus_unit_append_active_state, "s", 0 },
- { "SubState", bus_unit_append_sub_state, "s", 0 },
- { "FragmentPath", bus_property_append_string, "s", offsetof(Unit, fragment_path), true },
- { "SourcePath", bus_property_append_string, "s", offsetof(Unit, source_path), true },
- { "DropInPaths", bus_property_append_strv, "as", offsetof(Unit, dropin_paths), true },
- { "UnitFileState", bus_unit_append_file_state, "s", 0 },
- { "InactiveExitTimestamp",bus_property_append_usec, "t", offsetof(Unit, inactive_exit_timestamp.realtime) },
- { "InactiveExitTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, inactive_exit_timestamp.monotonic) },
- { "ActiveEnterTimestamp", bus_property_append_usec, "t", offsetof(Unit, active_enter_timestamp.realtime) },
- { "ActiveEnterTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, active_enter_timestamp.monotonic) },
- { "ActiveExitTimestamp", bus_property_append_usec, "t", offsetof(Unit, active_exit_timestamp.realtime) },
- { "ActiveExitTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, active_exit_timestamp.monotonic) },
- { "InactiveEnterTimestamp", bus_property_append_usec, "t", offsetof(Unit, inactive_enter_timestamp.realtime) },
- { "InactiveEnterTimestampMonotonic",bus_property_append_usec, "t", offsetof(Unit, inactive_enter_timestamp.monotonic) },
- { "CanStart", bus_unit_append_can_start, "b", 0 },
- { "CanStop", bus_unit_append_can_stop, "b", 0 },
- { "CanReload", bus_unit_append_can_reload, "b", 0 },
- { "CanIsolate", bus_unit_append_can_isolate, "b", 0 },
- { "Job", bus_unit_append_job, "(uo)", 0 },
- { "StopWhenUnneeded", bus_property_append_bool, "b", offsetof(Unit, stop_when_unneeded) },
- { "RefuseManualStart", bus_property_append_bool, "b", offsetof(Unit, refuse_manual_start) },
- { "RefuseManualStop", bus_property_append_bool, "b", offsetof(Unit, refuse_manual_stop) },
- { "AllowIsolate", bus_property_append_bool, "b", offsetof(Unit, allow_isolate) },
- { "DefaultDependencies", bus_property_append_bool, "b", offsetof(Unit, default_dependencies) },
- { "OnFailureIsolate", bus_property_append_bool, "b", offsetof(Unit, on_failure_isolate) },
- { "IgnoreOnIsolate", bus_property_append_bool, "b", offsetof(Unit, ignore_on_isolate) },
- { "IgnoreOnSnapshot", bus_property_append_bool, "b", offsetof(Unit, ignore_on_snapshot) },
- { "NeedDaemonReload", bus_unit_append_need_daemon_reload, "b", 0 },
- { "JobTimeoutUSec", bus_property_append_usec, "t", offsetof(Unit, job_timeout) },
- { "ConditionTimestamp", bus_property_append_usec, "t", offsetof(Unit, condition_timestamp.realtime) },
- { "ConditionTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, condition_timestamp.monotonic) },
- { "ConditionResult", bus_property_append_bool, "b", offsetof(Unit, condition_result) },
- { "LoadError", bus_unit_append_load_error, "(ss)", 0 },
- { "Transient", bus_property_append_bool, "b", offsetof(Unit, transient) },
+ { "Id", bus_property_append_string, "s", offsetof(Unit, id), true },
+ { "Names", bus_unit_append_names, "as", 0 },
+ { "Following", bus_unit_append_following, "s", 0 },
+ { "Requires", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUIRES]), true },
+ { "RequiresOverridable", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUIRES_OVERRIDABLE]), true },
+ { "Requisite", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUISITE]), true },
+ { "RequisiteOverridable", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUISITE_OVERRIDABLE]), true },
+ { "Wants", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_WANTS]), true },
+ { "BindsTo", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_BINDS_TO]), true },
+ { "PartOf", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_PART_OF]), true },
+ { "RequiredBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUIRED_BY]), true },
+ { "RequiredByOverridable", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUIRED_BY_OVERRIDABLE]), true },
+ { "WantedBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_WANTED_BY]), true },
+ { "BoundBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_BOUND_BY]), true },
+ { "ConsistsOf", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_CONSISTS_OF]), true },
+ { "Conflicts", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_CONFLICTS]), true },
+ { "ConflictedBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_CONFLICTED_BY]), true },
+ { "Before", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_BEFORE]), true },
+ { "After", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_AFTER]), true },
+ { "OnFailure", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_ON_FAILURE]), true },
+ { "Triggers", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_TRIGGERS]), true },
+ { "TriggeredBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_TRIGGERED_BY]), true },
+ { "PropagatesReloadTo", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_PROPAGATES_RELOAD_TO]), true },
+ { "ReloadPropagatedFrom", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_RELOAD_PROPAGATED_FROM]), true },
+ { "RequiresMountsFor", bus_property_append_strv, "as", offsetof(Unit, requires_mounts_for), true },
+ { "Documentation", bus_property_append_strv, "as", offsetof(Unit, documentation), true },
+ { "Description", bus_unit_append_description, "s", 0 },
+ { "LoadState", bus_unit_append_load_state, "s", offsetof(Unit, load_state) },
+ { "ActiveState", bus_unit_append_active_state, "s", 0 },
+ { "SubState", bus_unit_append_sub_state, "s", 0 },
+ { "FragmentPath", bus_property_append_string, "s", offsetof(Unit, fragment_path), true },
+ { "SourcePath", bus_property_append_string, "s", offsetof(Unit, source_path), true },
+ { "DropInPaths", bus_property_append_strv, "as", offsetof(Unit, dropin_paths), true },
+ { "UnitFileState", bus_unit_append_file_state, "s", 0 },
+ { "InactiveExitTimestamp", bus_property_append_usec, "t", offsetof(Unit, inactive_exit_timestamp.realtime) },
+ { "InactiveExitTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, inactive_exit_timestamp.monotonic) },
+ { "ActiveEnterTimestamp", bus_property_append_usec, "t", offsetof(Unit, active_enter_timestamp.realtime) },
+ { "ActiveEnterTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, active_enter_timestamp.monotonic) },
+ { "ActiveExitTimestamp", bus_property_append_usec, "t", offsetof(Unit, active_exit_timestamp.realtime) },
+ { "ActiveExitTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, active_exit_timestamp.monotonic) },
+ { "InactiveEnterTimestamp", bus_property_append_usec, "t", offsetof(Unit, inactive_enter_timestamp.realtime) },
+ { "InactiveEnterTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, inactive_enter_timestamp.monotonic) },
+ { "CanStart", bus_unit_append_can_start, "b", 0 },
+ { "CanStop", bus_unit_append_can_stop, "b", 0 },
+ { "CanReload", bus_unit_append_can_reload, "b", 0 },
+ { "CanIsolate", bus_unit_append_can_isolate, "b", 0 },
+ { "Job", bus_unit_append_job, "(uo)", 0 },
+ { "StopWhenUnneeded", bus_property_append_bool, "b", offsetof(Unit, stop_when_unneeded) },
+ { "RefuseManualStart", bus_property_append_bool, "b", offsetof(Unit, refuse_manual_start) },
+ { "RefuseManualStop", bus_property_append_bool, "b", offsetof(Unit, refuse_manual_stop) },
+ { "AllowIsolate", bus_property_append_bool, "b", offsetof(Unit, allow_isolate) },
+ { "DefaultDependencies", bus_property_append_bool, "b", offsetof(Unit, default_dependencies) },
+ { "OnFailureIsolate", bus_property_append_bool, "b", offsetof(Unit, on_failure_isolate) },
+ { "IgnoreOnIsolate", bus_property_append_bool, "b", offsetof(Unit, ignore_on_isolate) },
+ { "IgnoreOnSnapshot", bus_property_append_bool, "b", offsetof(Unit, ignore_on_snapshot) },
+ { "NeedDaemonReload", bus_unit_append_need_daemon_reload, "b", 0 },
+ { "JobTimeoutUSec", bus_property_append_usec, "t", offsetof(Unit, job_timeout) },
+ { "ConditionTimestamp", bus_property_append_usec, "t", offsetof(Unit, condition_timestamp.realtime) },
+ { "ConditionTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, condition_timestamp.monotonic) },
+ { "ConditionResult", bus_property_append_bool, "b", offsetof(Unit, condition_result) },
+ { "Conditions", bus_property_append_condition_list, "a(sbbsi)", offsetof(Unit, conditions) },
+ { "LoadError", bus_unit_append_load_error, "(ss)", 0 },
+ { "Transient", bus_property_append_bool, "b", offsetof(Unit, transient) },
{}
};
diff --git a/src/core/dbus-unit.h b/src/core/dbus-unit.h
index d3f7ec621e..3064cd552a 100644
--- a/src/core/dbus-unit.h
+++ b/src/core/dbus-unit.h
@@ -125,6 +125,7 @@
" <property name=\"ConditionTimestamp\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"ConditionTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"ConditionResult\" type=\"b\" access=\"read\"/>\n" \
+ " <property name=\"Conditions\" type=\"a(sbbsi)\" access=\"read\"/>\n" \
" <property name=\"LoadError\" type=\"(ss)\" access=\"read\"/>\n" \
" <property name=\"Transient\" type=\"b\" access=\"read\"/>\n" \
" </interface>\n"
diff --git a/src/core/unit.c b/src/core/unit.c
index a201fa4041..0e9329f8c9 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -1125,7 +1125,8 @@ int unit_start(Unit *u) {
}
/* Forward to the main object, if we aren't it. */
- if ((following = unit_following(u))) {
+ following = unit_following(u);
+ if (following) {
log_debug_unit(u->id, "Redirecting start request from %s to %s.",
u->id, following->id);
return unit_start(following);
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 6fdbc417b6..b3b679e0af 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -2534,6 +2534,10 @@ typedef struct UnitStatusInfo {
usec_t condition_timestamp;
bool condition_result;
+ bool failed_condition_trigger;
+ bool failed_condition_negate;
+ const char *failed_condition;
+ const char *failed_condition_param;
/* Socket */
unsigned n_accepted;
@@ -2676,10 +2680,15 @@ static void print_status_info(UnitStatusInfo *i) {
s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
- if (s1)
- printf(" start condition failed at %s; %s\n", s2, s1);
- else if (s2)
- printf(" start condition failed at %s\n", s2);
+ printf(" start condition failed at %s%s%s\n",
+ s2, s1 ? "; " : "", s1 ? s1 : "");
+ if (i->failed_condition_trigger)
+ printf(" none of the trigger conditions were met\n");
+ else if (i->failed_condition)
+ printf(" %s=%s%s was not met\n",
+ i->failed_condition,
+ i->failed_condition_negate ? "!" : "",
+ i->failed_condition_param);
}
if (i->sysfs_path)
@@ -3038,15 +3047,18 @@ static int status_property(const char *name, DBusMessageIter *iter, UnitStatusIn
ExecStatusInfo *info;
int r;
- if (!(info = new0(ExecStatusInfo, 1)))
+ info = new0(ExecStatusInfo, 1);
+ if (!info)
return -ENOMEM;
- if (!(info->name = strdup(name))) {
+ info->name = strdup(name);
+ if (!info->name) {
free(info);
return -ENOMEM;
}
- if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
+ r = exec_status_info_deserialize(&sub, info);
+ if (r < 0) {
free(info);
return r;
}
@@ -3056,7 +3068,8 @@ static int status_property(const char *name, DBusMessageIter *iter, UnitStatusIn
dbus_message_iter_next(&sub);
}
- } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
+ } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
+ streq(name, "Listen")) {
DBusMessageIter sub, sub2;
dbus_message_iter_recurse(iter, &sub);
@@ -3082,7 +3095,8 @@ static int status_property(const char *name, DBusMessageIter *iter, UnitStatusIn
return 0;
- } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING && streq(name, "DropInPaths")) {
+ } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
+ streq(name, "DropInPaths")) {
int r = bus_parse_strv_iter(iter, &i->dropin_paths);
if (r < 0)
return r;
@@ -3105,6 +3119,36 @@ static int status_property(const char *name, DBusMessageIter *iter, UnitStatusIn
dbus_message_iter_next(&sub);
}
+
+ } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
+ streq(name, "Conditions")) {
+ DBusMessageIter sub, sub2;
+
+ dbus_message_iter_recurse(iter, &sub);
+ while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
+ const char *cond, *param;
+ dbus_bool_t trigger, negate;
+ dbus_int32_t state;
+
+ dbus_message_iter_recurse(&sub, &sub2);
+ log_debug("here");
+
+ if(bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &cond, true) >= 0 &&
+ bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &trigger, true) >= 0 &&
+ bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &negate, true) >= 0 &&
+ bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &param, true) >= 0 &&
+ bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &state, false) >= 0) {
+ log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
+ if (state < 0 && (!trigger || !i->failed_condition)) {
+ i->failed_condition = cond;
+ i->failed_condition_trigger = trigger;
+ i->failed_condition_negate = negate;
+ i->failed_condition_param = param;
+ }
+ }
+
+ dbus_message_iter_next(&sub);
+ }
}
break;