return state_translation_table[AUTOMOUNT(u)->state];
}
+static const char *automount_sub_state_to_string(Unit *u) {
+ assert(u);
+
+ return state_string_table[AUTOMOUNT(u)->state];
+}
+
const UnitVTable automount_vtable = {
.suffix = ".mount",
.dump = automount_dump,
- .active_state = automount_active_state
+ .active_state = automount_active_state,
+ .sub_state_to_string = automount_sub_state_to_string
};
" </method>" \
" <method name=\"ClearJobs\"/>" \
" <method name=\"ListUnits\">" \
- " <arg name=\"units\" type=\"a(ssssouso)\" direction=\"out\"/>" \
+ " <arg name=\"units\" type=\"a(sssssouso)\" direction=\"out\"/>" \
" </method>" \
" <method name=\"ListJobs\">" \
" <arg name=\"jobs\" type=\"a(usssoo)\" direction=\"out\"/>" \
dbus_message_iter_init_append(reply, &iter);
- if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ssssouso)", &sub))
+ if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sssssouso)", &sub))
goto oom;
HASHMAP_FOREACH_KEY(u, k, m->units, i) {
char *u_path, *j_path;
- const char *id, *description, *load_state, *active_state, *job_type;
+ const char *id, *description, *load_state, *active_state, *sub_state, *job_type;
DBusMessageIter sub2;
uint32_t job_id;
description = unit_description(u);
load_state = unit_load_state_to_string(u->meta.load_state);
active_state = unit_active_state_to_string(unit_active_state(u));
+ sub_state = unit_sub_state_to_string(u);
if (!(u_path = unit_dbus_path(u)))
goto oom;
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &description) ||
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &load_state) ||
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &active_state) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sub_state) ||
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path) ||
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &job_id) ||
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &job_type) ||
" <property name=\"Description\" type=\"s\" access=\"read\"/>"
" <property name=\"LoadState\" type=\"s\" access=\"read\"/>"
" <property name=\"ActiveState\" type=\"s\" access=\"read\"/>"
+ " <property name=\"SubState\" type=\"s\" access=\"read\"/>"
" <property name=\"FragmentPath\" type=\"s\" access=\"read\"/>"
" <property name=\"ActiveEnterTimestamp\" type=\"t\" access=\"read\"/>"
" <property name=\"ActiveExitTimestamp\" type=\"t\" access=\"read\"/>"
return 0;
}
+static int bus_unit_append_sub_state(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+ Unit *u = data;
+ const char *state;
+
+ assert(m);
+ assert(i);
+ assert(property);
+ assert(u);
+
+ state = unit_sub_state_to_string(u);
+
+ if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &state))
+ return -ENOMEM;
+
+ return 0;
+}
+
static int bus_unit_append_can_reload(Manager *m, DBusMessageIter *i, const char *property, void *data) {
Unit *u = data;
dbus_bool_t b;
{ "org.freedesktop.systemd1.Unit", "Description", bus_unit_append_description, "s", u },
{ "org.freedesktop.systemd1.Unit", "LoadState", bus_unit_append_load_state, "s", &u->meta.load_state },
{ "org.freedesktop.systemd1.Unit", "ActiveState", bus_unit_append_active_state, "s", u },
+ { "org.freedesktop.systemd1.Unit", "SubState", bus_unit_append_sub_state, "s", u },
{ "org.freedesktop.systemd1.Unit", "FragmentPath", bus_property_append_string, "s", u->meta.fragment_path },
{ "org.freedesktop.systemd1.Unit", "ActiveEnterTimestamp", bus_property_append_uint64, "t", &u->meta.active_enter_timestamp },
{ "org.freedesktop.systemd1.Unit", "ActiveExitTimestamp", bus_property_append_uint64, "t", &u->meta.active_exit_timestamp },
return state_translation_table[DEVICE(u)->state];
}
+static const char *device_sub_state_to_string(Unit *u) {
+ assert(u);
+
+ return state_string_table[DEVICE(u)->state];
+}
+
static int device_add_escaped_name(Unit *u, const char *dn, bool make_id) {
char *e;
int r;
.dump = device_dump,
.active_state = device_active_state,
+ .sub_state_to_string = device_sub_state_to_string,
.enumerate = device_enumerate,
.shutdown = device_shutdown
return state_translation_table[MOUNT(u)->state];
}
+static const char *mount_sub_state_to_string(Unit *u) {
+ assert(u);
+
+ return state_string_table[MOUNT(u)->state];
+}
+
static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
Mount *m = MOUNT(u);
bool success;
.reload = mount_reload,
.active_state = mount_active_state,
+ .sub_state_to_string = mount_sub_state_to_string,
.sigchld_event = mount_sigchld_event,
.timer_event = mount_timer_event,
return state_translation_table[SERVICE(u)->state];
}
+static const char *service_sub_state_to_string(Unit *u) {
+ assert(u);
+
+ return service_state_to_string(SERVICE(u)->state);
+}
+
static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
Service *s = SERVICE(u);
bool success;
.can_reload = service_can_reload,
.active_state = service_active_state,
+ .sub_state_to_string = service_sub_state_to_string,
.sigchld_event = service_sigchld_event,
.timer_event = service_timer_event,
return state_translation_table[SOCKET(u)->state];
}
+static const char *socket_sub_state_to_string(Unit *u) {
+ assert(u);
+
+ return state_string_table[SOCKET(u)->state];
+}
+
static void socket_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
Socket *s = SOCKET(u);
.stop = socket_stop,
.active_state = socket_active_state,
+ .sub_state_to_string = socket_sub_state_to_string,
.fd_event = socket_fd_event,
.sigchld_event = socket_sigchld_event,
uint n = 0;
Posix.qsort(list, list.length, sizeof(Manager.UnitInfo), unit_info_compare);
- stdout.printf("%-45s %-6s %-12s %-17s\n", "UNIT", "LOAD", "ACTIVE", "JOB");
+ stdout.printf("%-45s %-6s %-12s %-12s %-17s\n", "UNIT", "LOAD", "ACTIVE", "SUB", "JOB");
foreach (var i in list) {
if (!all && i.active_state == "inactive")
continue;
- stdout.printf("%-45s %-6s %-12s", i.id, i.load_state, i.active_state);
+ stdout.printf("%-45s %-6s %-12s %-12s", i.id, i.load_state, i.active_state, i.sub_state);
if (i.job_id != 0)
stdout.printf(" → %-15s", i.job_type);
string description;
string load_state;
string active_state;
+ string sub_state;
ObjectPath unit_path;
uint32 job_id;
string job_type;
return state_translation_table[TARGET(u)->state];
}
+static const char *target_sub_state_to_string(Unit *u) {
+ assert(u);
+
+ return state_string_table[TARGET(u)->state];
+}
+
int target_get_runlevel(Target *t) {
static const struct {
.start = target_start,
.stop = target_stop,
- .active_state = target_active_state
+ .active_state = target_active_state,
+ .sub_state_to_string = target_sub_state_to_string
};
return UNIT_VTABLE(u)->active_state(u);
}
+const char* unit_sub_state_to_string(Unit *u) {
+ assert(u);
+
+ return UNIT_VTABLE(u)->sub_state_to_string(u);
+}
+
static void complete_move(Set **s, Set **other) {
assert(s);
assert(other);
* a simpler one that the engine can understand */
UnitActiveState (*active_state)(Unit *u);
+ /* Returns the substate specific to this unit type as
+ * string. This is purely information so that we can give the
+ * user a more finegrained explanation in which actual state a
+ * unit is in. */
+ const char* (*sub_state_to_string)(Unit *u);
+
void (*fd_event)(Unit *u, int fd, uint32_t events, Watch *w);
void (*sigchld_event)(Unit *u, pid_t pid, int code, int status);
void (*timer_event)(Unit *u, uint64_t n_elapsed, Watch *w);
UnitActiveState unit_active_state(Unit *u);
+const char* unit_sub_state_to_string(Unit *u);
+
void unit_dump(Unit *u, FILE *f, const char *prefix);
bool unit_can_reload(Unit *u);