diff --git a/src/login/loginctl.c b/src/login/loginctl.c index d7db518bf99..81bb8f48ddf 100644 --- a/src/login/loginctl.c +++ b/src/login/loginctl.c @@ -58,7 +58,7 @@ typedef struct SessionStatusInfo { const char *id; uid_t uid; const char *name; - struct dual_timestamp timestamp; + dual_timestamp timestamp; unsigned vtnr; const char *seat; const char *tty; @@ -74,11 +74,39 @@ typedef struct SessionStatusInfo { const char *scope; const char *desktop; bool idle_hint; - dual_timestamp idle_hint_timestamp; + usec_t idle_hint_timestamp; } SessionStatusInfo; -static OutputFlags get_output_flags(void) { +typedef struct UserStatusInfo { + uid_t uid; + bool linger; + const char *name; + dual_timestamp timestamp; + const char *state; + char **sessions; + const char *display; + const char *slice; +} UserStatusInfo; +typedef struct SeatStatusInfo { + const char *id; + const char *active_session; + char **sessions; +} SeatStatusInfo; + +static void user_status_info_done(UserStatusInfo *info) { + assert(info); + + strv_free(info->sessions); +} + +static void seat_status_info_done(SeatStatusInfo *info) { + assert(info); + + strv_free(info->sessions); +} + +static OutputFlags get_output_flags(void) { return FLAGS_SET(arg_print_flags, BUS_PRINT_PROPERTY_SHOW_EMPTY) * OUTPUT_SHOW_ALL | (arg_full || !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH | @@ -87,8 +115,13 @@ static OutputFlags get_output_flags(void) { static int get_session_path(sd_bus *bus, const char *session_id, sd_bus_error *error, char **path) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - int r; char *ans; + int r; + + assert(bus); + assert(session_id); + assert(error); + assert(path); r = bus_call_method(bus, bus_login_mgr, "GetSession", error, &reply, "s", session_id); if (r < 0) @@ -139,11 +172,11 @@ static int show_table(Table *table, const char *word) { static int list_sessions(int argc, char *argv[], void *userdata) { - static const struct bus_properties_map map[] = { - { "IdleHint", "b", NULL, offsetof(SessionStatusInfo, idle_hint) }, - { "IdleSinceHintMonotonic", "t", NULL, offsetof(SessionStatusInfo, idle_hint_timestamp.monotonic) }, - { "State", "s", NULL, offsetof(SessionStatusInfo, state) }, - { "TTY", "s", NULL, offsetof(SessionStatusInfo, tty) }, + static const struct bus_properties_map map[] = { + { "IdleHint", "b", NULL, offsetof(SessionStatusInfo, idle_hint) }, + { "IdleSinceHint", "t", NULL, offsetof(SessionStatusInfo, idle_hint_timestamp) }, + { "State", "s", NULL, offsetof(SessionStatusInfo, state) }, + { "TTY", "s", NULL, offsetof(SessionStatusInfo, tty) }, {}, }; @@ -207,7 +240,7 @@ static int list_sessions(int argc, char *argv[], void *userdata) { return table_log_add_error(r); if (i.idle_hint) - r = table_add_cell(table, NULL, TABLE_TIMESTAMP_RELATIVE, &i.idle_hint_timestamp.monotonic); + r = table_add_cell(table, NULL, TABLE_TIMESTAMP_RELATIVE, &i.idle_hint_timestamp); else r = table_add_cell(table, NULL, TABLE_EMPTY, NULL); if (r < 0) @@ -222,6 +255,13 @@ static int list_sessions(int argc, char *argv[], void *userdata) { } static int list_users(int argc, char *argv[], void *userdata) { + + static const struct bus_properties_map property_map[] = { + { "Linger", "b", NULL, offsetof(UserStatusInfo, linger) }, + { "State", "s", NULL, offsetof(UserStatusInfo, state) }, + {}, + }; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_(table_unrefp) Table *table = NULL; @@ -248,10 +288,10 @@ static int list_users(int argc, char *argv[], void *userdata) { for (;;) { _cleanup_(sd_bus_error_free) sd_bus_error error_property = SD_BUS_ERROR_NULL; - _cleanup_free_ char *state = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply_property = NULL; + _cleanup_(user_status_info_done) UserStatusInfo info = {}; const char *user, *object; uint32_t uid; - int linger; r = sd_bus_message_read(reply, "(uso)", &uid, &user, &object); if (r < 0) @@ -259,44 +299,27 @@ static int list_users(int argc, char *argv[], void *userdata) { if (r == 0) break; - r = sd_bus_get_property_trivial(bus, - "org.freedesktop.login1", - object, - "org.freedesktop.login1.User", - "Linger", - &error_property, - 'b', - &linger); + r = bus_map_all_properties(bus, + "org.freedesktop.login1", + object, + property_map, + BUS_MAP_BOOLEAN_AS_BOOL, + &error_property, + &reply_property, + &info); if (r < 0) { - if (sd_bus_error_has_name(&error_property, SD_BUS_ERROR_UNKNOWN_OBJECT)) - /* The user logged out when we're querying the property */ - continue; - - return log_error_errno(r, "Failed to get linger status for user %s: %s", - user, bus_error_message(&error_property, r)); - } - - r = sd_bus_get_property_string(bus, - "org.freedesktop.login1", - object, - "org.freedesktop.login1.User", - "State", - &error_property, - &state); - if (r < 0) { - if (sd_bus_error_has_name(&error_property, SD_BUS_ERROR_UNKNOWN_OBJECT)) - /* The user logged out when we're querying the property */ - continue; - - return log_error_errno(r, "Failed to get state for user %s: %s", - user, bus_error_message(&error_property, r)); + log_full_errno(sd_bus_error_has_name(&error_property, SD_BUS_ERROR_UNKNOWN_OBJECT) ? LOG_DEBUG : LOG_WARNING, + r, + "Failed to get properties of user %s, ignoring: %s", + user, bus_error_message(&error_property, r)); + continue; } r = table_add_many(table, TABLE_UID, (uid_t) uid, TABLE_STRING, user, - TABLE_BOOLEAN, linger, - TABLE_STRING, state); + TABLE_BOOLEAN, info.linger, + TABLE_STRING, info.state); if (r < 0) return table_log_add_error(r); } @@ -392,41 +415,13 @@ static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit return 0; } -typedef struct UserStatusInfo { - uid_t uid; - bool linger; - const char *name; - struct dual_timestamp timestamp; - const char *state; - char **sessions; - const char *display; - const char *slice; -} UserStatusInfo; - -typedef struct SeatStatusInfo { - const char *id; - const char *active_session; - char **sessions; -} SeatStatusInfo; - -static void user_status_info_clear(UserStatusInfo *info) { - if (info) { - strv_free(info->sessions); - zero(*info); - } -} - -static void seat_status_info_clear(SeatStatusInfo *info) { - if (info) { - strv_free(info->sessions); - zero(*info); - } -} - static int prop_map_first_of_struct(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { const char *contents; int r; + assert(bus); + assert(m); + r = sd_bus_message_peek_type(m, NULL, &contents); if (r < 0) return r; @@ -474,26 +469,28 @@ static int prop_map_sessions_strv(sd_bus *bus, const char *member, sd_bus_messag static int print_session_status_info(sd_bus *bus, const char *path, bool *new_line) { - static const struct bus_properties_map map[] = { - { "Id", "s", NULL, offsetof(SessionStatusInfo, id) }, - { "Name", "s", NULL, offsetof(SessionStatusInfo, name) }, - { "TTY", "s", NULL, offsetof(SessionStatusInfo, tty) }, - { "Display", "s", NULL, offsetof(SessionStatusInfo, display) }, - { "RemoteHost", "s", NULL, offsetof(SessionStatusInfo, remote_host) }, - { "RemoteUser", "s", NULL, offsetof(SessionStatusInfo, remote_user) }, - { "Service", "s", NULL, offsetof(SessionStatusInfo, service) }, - { "Desktop", "s", NULL, offsetof(SessionStatusInfo, desktop) }, - { "Type", "s", NULL, offsetof(SessionStatusInfo, type) }, - { "Class", "s", NULL, offsetof(SessionStatusInfo, class) }, - { "Scope", "s", NULL, offsetof(SessionStatusInfo, scope) }, - { "State", "s", NULL, offsetof(SessionStatusInfo, state) }, - { "VTNr", "u", NULL, offsetof(SessionStatusInfo, vtnr) }, - { "Leader", "u", NULL, offsetof(SessionStatusInfo, leader) }, - { "Remote", "b", NULL, offsetof(SessionStatusInfo, remote) }, - { "Timestamp", "t", NULL, offsetof(SessionStatusInfo, timestamp.realtime) }, - { "TimestampMonotonic", "t", NULL, offsetof(SessionStatusInfo, timestamp.monotonic) }, - { "User", "(uo)", prop_map_first_of_struct, offsetof(SessionStatusInfo, uid) }, - { "Seat", "(so)", prop_map_first_of_struct, offsetof(SessionStatusInfo, seat) }, + static const struct bus_properties_map map[] = { + { "Id", "s", NULL, offsetof(SessionStatusInfo, id) }, + { "Name", "s", NULL, offsetof(SessionStatusInfo, name) }, + { "TTY", "s", NULL, offsetof(SessionStatusInfo, tty) }, + { "Display", "s", NULL, offsetof(SessionStatusInfo, display) }, + { "RemoteHost", "s", NULL, offsetof(SessionStatusInfo, remote_host) }, + { "RemoteUser", "s", NULL, offsetof(SessionStatusInfo, remote_user) }, + { "Service", "s", NULL, offsetof(SessionStatusInfo, service) }, + { "Desktop", "s", NULL, offsetof(SessionStatusInfo, desktop) }, + { "Type", "s", NULL, offsetof(SessionStatusInfo, type) }, + { "Class", "s", NULL, offsetof(SessionStatusInfo, class) }, + { "Scope", "s", NULL, offsetof(SessionStatusInfo, scope) }, + { "State", "s", NULL, offsetof(SessionStatusInfo, state) }, + { "VTNr", "u", NULL, offsetof(SessionStatusInfo, vtnr) }, + { "Leader", "u", NULL, offsetof(SessionStatusInfo, leader) }, + { "Remote", "b", NULL, offsetof(SessionStatusInfo, remote) }, + { "Timestamp", "t", NULL, offsetof(SessionStatusInfo, timestamp.realtime) }, + { "TimestampMonotonic", "t", NULL, offsetof(SessionStatusInfo, timestamp.monotonic) }, + { "IdleHint", "b", NULL, offsetof(SessionStatusInfo, idle_hint) }, + { "IdleSinceHint", "t", NULL, offsetof(SessionStatusInfo, idle_hint_timestamp) }, + { "User", "(uo)", prop_map_first_of_struct, offsetof(SessionStatusInfo, uid) }, + { "Seat", "(so)", prop_map_first_of_struct, offsetof(SessionStatusInfo, seat) }, {} }; @@ -584,6 +581,14 @@ static int print_session_status_info(sd_bus *bus, const char *path, bool *new_li if (i.state) printf("\t State: %s\n", i.state); + if (i.idle_hint && timestamp_is_set(i.idle_hint_timestamp)) + printf("\t Idle: %s since %s (%s)\n", + yes_no(i.idle_hint), + FORMAT_TIMESTAMP(i.idle_hint_timestamp), + FORMAT_TIMESTAMP_RELATIVE(i.idle_hint_timestamp)); + else + printf("\t Idle: %s\n", yes_no(i.idle_hint)); + if (i.scope) { printf("\t Unit: %s\n", i.scope); show_unit_cgroup(bus, "org.freedesktop.systemd1.Scope", i.scope, i.leader); @@ -609,7 +614,7 @@ static int print_session_status_info(sd_bus *bus, const char *path, bool *new_li static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line) { - static const struct bus_properties_map map[] = { + static const struct bus_properties_map map[] = { { "Name", "s", NULL, offsetof(UserStatusInfo, name) }, { "Linger", "b", NULL, offsetof(UserStatusInfo, linger) }, { "Slice", "s", NULL, offsetof(UserStatusInfo, slice) }, @@ -624,7 +629,7 @@ static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line) _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; - _cleanup_(user_status_info_clear) UserStatusInfo i = {}; + _cleanup_(user_status_info_done) UserStatusInfo i = {}; int r; r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, BUS_MAP_BOOLEAN_AS_BOOL, &error, &m, &i); @@ -686,7 +691,7 @@ static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line) static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line) { - static const struct bus_properties_map map[] = { + static const struct bus_properties_map map[] = { { "Id", "s", NULL, offsetof(SeatStatusInfo, id) }, { "ActiveSession", "(so)", prop_map_first_of_struct, offsetof(SeatStatusInfo, active_session) }, { "Sessions", "a(so)", prop_map_sessions_strv, offsetof(SeatStatusInfo, sessions) }, @@ -695,7 +700,7 @@ static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line) _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; - _cleanup_(seat_status_info_clear) SeatStatusInfo i = {}; + _cleanup_(seat_status_info_done) SeatStatusInfo i = {}; int r; r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, 0, &error, &m, &i); @@ -1003,7 +1008,6 @@ static int activate(int argc, char *argv[], void *userdata) { } for (int i = 1; i < argc; i++) { - r = bus_call_method( bus, bus_login_mgr, @@ -1033,7 +1037,6 @@ static int kill_session(int argc, char *argv[], void *userdata) { arg_kill_whom = "all"; for (int i = 1; i < argc; i++) { - r = bus_call_method( bus, bus_login_mgr,