mirror of
https://github.com/systemd/systemd.git
synced 2025-03-28 02:50:16 +03:00
systemd,systemctl: export condition status and show failing condition
$ systemctl --user status hoohoo hoohoo.service Loaded: loaded (/home/zbyszek/.config/systemd/user/hoohoo.service; static) Active: inactive (dead) start condition failed at Tue 2013-06-25 18:08:42 EDT; 1s ago ConditionPathExists=/tmp/hoo was not met Full information is exported over D-Bus: [(condition, trigger, negate, param, state),...] where state is one of "failed" (<0), "untested" (0), "OK" (>0). I've decided to use 0 for "untested", because it might be useful to differentiate different types of failure later on, without breaking compatibility. systemctl shows the failing condition, if there was a non-trigger failing condition, or says "none of the trigger conditions were met", because there're often many trigger conditions, and they must all fail for the condition to fail, so printing them all would consume a lot of space, and bring unnecessary attention to something that is quite low-level.
This commit is contained in:
parent
4b744dfabe
commit
52990c2e0e
2
TODO
2
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
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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, ¶m) ||
|
||||
!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) },
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
|
@ -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, ¶m, 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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user