1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
31 #include "bus-error.h"
38 #include "unit-name.h"
39 #include "sysfs-show.h"
40 #include "logs-show.h"
41 #include "cgroup-show.h"
42 #include "cgroup-util.h"
43 #include "spawn-polkit-agent.h"
45 #include "process-util.h"
46 #include "terminal-util.h"
47 #include "signal-util.h"
49 static char **arg_property = NULL;
50 static bool arg_all = false;
51 static bool arg_full = false;
52 static bool arg_no_pager = false;
53 static bool arg_legend = true;
54 static const char *arg_kill_who = NULL;
55 static int arg_signal = SIGTERM;
56 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
57 static char *arg_host = NULL;
58 static bool arg_ask_password = true;
59 static bool arg_ignore_inhibitors = false;
60 static unsigned arg_lines = 10;
61 static OutputMode arg_output = OUTPUT_SHORT;
63 static void pager_open_if_enabled(void) {
71 static void polkit_agent_open_if_enabled(void) {
73 /* Open the polkit agent as a child process if necessary */
75 if (!arg_ask_password)
78 if (arg_transport != BUS_TRANSPORT_LOCAL)
84 static OutputFlags get_output_flags(void) {
87 arg_all * OUTPUT_SHOW_ALL |
88 arg_full * OUTPUT_FULL_WIDTH |
89 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
90 on_tty() * OUTPUT_COLOR;
93 static int list_sessions(int argc, char *argv[], void *userdata) {
94 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
95 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
96 const char *id, *user, *seat, *object;
97 sd_bus *bus = userdata;
105 pager_open_if_enabled();
107 r = sd_bus_call_method(
109 "org.freedesktop.login1",
110 "/org/freedesktop/login1",
111 "org.freedesktop.login1.Manager",
116 log_error("Failed to list sessions: %s", bus_error_message(&error, r));
120 r = sd_bus_message_enter_container(reply, 'a', "(susso)");
122 return bus_log_parse_error(r);
125 printf("%10s %10s %-16s %-16s\n", "SESSION", "UID", "USER", "SEAT");
127 while ((r = sd_bus_message_read(reply, "(susso)", &id, &uid, &user, &seat, &object)) > 0) {
128 printf("%10s %10u %-16s %-16s\n", id, (unsigned) uid, user, seat);
132 return bus_log_parse_error(r);
135 printf("\n%u sessions listed.\n", k);
140 static int list_users(int argc, char *argv[], void *userdata) {
141 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
142 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
143 const char *user, *object;
144 sd_bus *bus = userdata;
152 pager_open_if_enabled();
154 r = sd_bus_call_method(
156 "org.freedesktop.login1",
157 "/org/freedesktop/login1",
158 "org.freedesktop.login1.Manager",
163 log_error("Failed to list users: %s", bus_error_message(&error, r));
167 r = sd_bus_message_enter_container(reply, 'a', "(uso)");
169 return bus_log_parse_error(r);
172 printf("%10s %-16s\n", "UID", "USER");
174 while ((r = sd_bus_message_read(reply, "(uso)", &uid, &user, &object)) > 0) {
175 printf("%10u %-16s\n", (unsigned) uid, user);
179 return bus_log_parse_error(r);
182 printf("\n%u users listed.\n", k);
187 static int list_seats(int argc, char *argv[], void *userdata) {
188 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
189 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
190 const char *seat, *object;
191 sd_bus *bus = userdata;
198 pager_open_if_enabled();
200 r = sd_bus_call_method(
202 "org.freedesktop.login1",
203 "/org/freedesktop/login1",
204 "org.freedesktop.login1.Manager",
209 log_error("Failed to list seats: %s", bus_error_message(&error, r));
213 r = sd_bus_message_enter_container(reply, 'a', "(so)");
215 return bus_log_parse_error(r);
218 printf("%-16s\n", "SEAT");
220 while ((r = sd_bus_message_read(reply, "(so)", &seat, &object)) > 0) {
221 printf("%-16s\n", seat);
225 return bus_log_parse_error(r);
228 printf("\n%u seats listed.\n", k);
233 static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit, pid_t leader) {
234 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
235 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
236 _cleanup_free_ char *path = NULL;
244 if (arg_transport != BUS_TRANSPORT_LOCAL)
247 path = unit_dbus_path_from_name(unit);
251 r = sd_bus_get_property(
253 "org.freedesktop.systemd1",
257 &error, &reply, "s");
261 r = sd_bus_message_read(reply, "s", &cgroup);
268 if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup, false) != 0 && leader <= 0)
277 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t ", c, false, &leader, leader > 0, get_output_flags());
281 typedef struct SessionStatusInfo {
285 struct dual_timestamp timestamp;
302 typedef struct UserStatusInfo {
305 struct dual_timestamp timestamp;
312 typedef struct SeatStatusInfo {
314 char *active_session;
318 static void session_status_info_clear(SessionStatusInfo *info) {
325 free(info->remote_host);
326 free(info->remote_user);
337 static void user_status_info_clear(UserStatusInfo *info) {
341 strv_free(info->sessions);
348 static void seat_status_info_clear(SeatStatusInfo *info) {
351 free(info->active_session);
352 strv_free(info->sessions);
357 static int prop_map_first_of_struct(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
358 const char *contents;
361 r = sd_bus_message_peek_type(m, NULL, &contents);
365 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, contents);
369 if (contents[0] == 's' || contents[0] == 'o') {
371 char **p = (char **) userdata;
373 r = sd_bus_message_read_basic(m, contents[0], &s);
383 r = sd_bus_message_read_basic(m, contents[0], userdata);
388 r = sd_bus_message_skip(m, contents+1);
392 r = sd_bus_message_exit_container(m);
399 static int prop_map_sessions_strv(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
406 r = sd_bus_message_enter_container(m, 'a', "(so)");
410 while ((r = sd_bus_message_read(m, "(so)", &name, NULL)) > 0) {
411 r = strv_extend(userdata, name);
418 return sd_bus_message_exit_container(m);
421 static int print_session_status_info(sd_bus *bus, const char *path, bool *new_line) {
423 static const struct bus_properties_map map[] = {
424 { "Id", "s", NULL, offsetof(SessionStatusInfo, id) },
425 { "Name", "s", NULL, offsetof(SessionStatusInfo, name) },
426 { "TTY", "s", NULL, offsetof(SessionStatusInfo, tty) },
427 { "Display", "s", NULL, offsetof(SessionStatusInfo, display) },
428 { "RemoteHost", "s", NULL, offsetof(SessionStatusInfo, remote_host) },
429 { "RemoteUser", "s", NULL, offsetof(SessionStatusInfo, remote_user) },
430 { "Service", "s", NULL, offsetof(SessionStatusInfo, service) },
431 { "Desktop", "s", NULL, offsetof(SessionStatusInfo, desktop) },
432 { "Type", "s", NULL, offsetof(SessionStatusInfo, type) },
433 { "Class", "s", NULL, offsetof(SessionStatusInfo, class) },
434 { "Scope", "s", NULL, offsetof(SessionStatusInfo, scope) },
435 { "State", "s", NULL, offsetof(SessionStatusInfo, state) },
436 { "VTNr", "u", NULL, offsetof(SessionStatusInfo, vtnr) },
437 { "Leader", "u", NULL, offsetof(SessionStatusInfo, leader) },
438 { "Remote", "b", NULL, offsetof(SessionStatusInfo, remote) },
439 { "Timestamp", "t", NULL, offsetof(SessionStatusInfo, timestamp.realtime) },
440 { "TimestampMonotonic", "t", NULL, offsetof(SessionStatusInfo, timestamp.monotonic) },
441 { "User", "(uo)", prop_map_first_of_struct, offsetof(SessionStatusInfo, uid) },
442 { "Seat", "(so)", prop_map_first_of_struct, offsetof(SessionStatusInfo, seat) },
446 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
447 char since2[FORMAT_TIMESTAMP_MAX], *s2;
448 _cleanup_(session_status_info_clear) SessionStatusInfo i = {};
451 r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i);
453 return log_error_errno(r, "Could not get properties: %m");
460 printf("%s - ", strna(i.id));
463 printf("%s (%u)\n", i.name, (unsigned) i.uid);
465 printf("%u\n", (unsigned) i.uid);
467 s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime);
468 s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime);
471 printf("\t Since: %s; %s\n", s2, s1);
473 printf("\t Since: %s\n", s2);
476 _cleanup_free_ char *t = NULL;
478 printf("\t Leader: %u", (unsigned) i.leader);
480 get_process_comm(i.leader, &t);
487 if (!isempty(i.seat)) {
488 printf("\t Seat: %s", i.seat);
491 printf("; vc%u", i.vtnr);
497 printf("\t TTY: %s\n", i.tty);
499 printf("\t Display: %s\n", i.display);
501 if (i.remote_host && i.remote_user)
502 printf("\t Remote: %s@%s\n", i.remote_user, i.remote_host);
503 else if (i.remote_host)
504 printf("\t Remote: %s\n", i.remote_host);
505 else if (i.remote_user)
506 printf("\t Remote: user %s\n", i.remote_user);
508 printf("\t Remote: Yes\n");
511 printf("\t Service: %s", i.service);
514 printf("; type %s", i.type);
517 printf("; class %s", i.class);
521 printf("\t Type: %s", i.type);
524 printf("; class %s", i.class);
528 printf("\t Class: %s\n", i.class);
530 if (!isempty(i.desktop))
531 printf("\t Desktop: %s\n", i.desktop);
534 printf("\t State: %s\n", i.state);
537 printf("\t Unit: %s\n", i.scope);
538 show_unit_cgroup(bus, "org.freedesktop.systemd1.Scope", i.scope, i.leader);
540 if (arg_transport == BUS_TRANSPORT_LOCAL) {
542 show_journal_by_unit(
547 i.timestamp.monotonic,
550 get_output_flags() | OUTPUT_BEGIN_NEWLINE,
551 SD_JOURNAL_LOCAL_ONLY,
561 static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line) {
563 static const struct bus_properties_map map[] = {
564 { "Name", "s", NULL, offsetof(UserStatusInfo, name) },
565 { "Slice", "s", NULL, offsetof(UserStatusInfo, slice) },
566 { "State", "s", NULL, offsetof(UserStatusInfo, state) },
567 { "UID", "u", NULL, offsetof(UserStatusInfo, uid) },
568 { "Timestamp", "t", NULL, offsetof(UserStatusInfo, timestamp.realtime) },
569 { "TimestampMonotonic", "t", NULL, offsetof(UserStatusInfo, timestamp.monotonic) },
570 { "Display", "(so)", prop_map_first_of_struct, offsetof(UserStatusInfo, display) },
571 { "Sessions", "a(so)", prop_map_sessions_strv, offsetof(UserStatusInfo, sessions) },
575 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
576 char since2[FORMAT_TIMESTAMP_MAX], *s2;
577 _cleanup_(user_status_info_clear) UserStatusInfo i = {};
580 r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i);
582 return log_error_errno(r, "Could not get properties: %m");
590 printf("%s (%u)\n", i.name, (unsigned) i.uid);
592 printf("%u\n", (unsigned) i.uid);
594 s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime);
595 s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime);
598 printf("\t Since: %s; %s\n", s2, s1);
600 printf("\t Since: %s\n", s2);
602 if (!isempty(i.state))
603 printf("\t State: %s\n", i.state);
605 if (!strv_isempty(i.sessions)) {
607 printf("\tSessions:");
609 STRV_FOREACH(l, i.sessions) {
610 if (streq_ptr(*l, i.display))
620 printf("\t Unit: %s\n", i.slice);
621 show_unit_cgroup(bus, "org.freedesktop.systemd1.Slice", i.slice, 0);
623 show_journal_by_unit(
628 i.timestamp.monotonic,
631 get_output_flags() | OUTPUT_BEGIN_NEWLINE,
632 SD_JOURNAL_LOCAL_ONLY,
641 static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line) {
643 static const struct bus_properties_map map[] = {
644 { "Id", "s", NULL, offsetof(SeatStatusInfo, id) },
645 { "ActiveSession", "(so)", prop_map_first_of_struct, offsetof(SeatStatusInfo, active_session) },
646 { "Sessions", "a(so)", prop_map_sessions_strv, offsetof(SeatStatusInfo, sessions) },
650 _cleanup_(seat_status_info_clear) SeatStatusInfo i = {};
653 r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i);
655 return log_error_errno(r, "Could not get properties: %m");
662 printf("%s\n", strna(i.id));
664 if (!strv_isempty(i.sessions)) {
666 printf("\tSessions:");
668 STRV_FOREACH(l, i.sessions) {
669 if (streq_ptr(*l, i.active_session))
678 if (arg_transport == BUS_TRANSPORT_LOCAL) {
687 printf("\t Devices:\n");
689 show_sysfs(i.id, "\t\t ", c);
695 static int show_properties(sd_bus *bus, const char *path, bool *new_line) {
703 r = bus_print_all_properties(bus, "org.freedesktop.login1", path, arg_property, arg_all);
705 log_error_errno(r, "Could not get properties: %m");
710 static int show_session(int argc, char *argv[], void *userdata) {
711 bool properties, new_line = false;
712 sd_bus *bus = userdata;
718 properties = !strstr(argv[0], "status");
720 pager_open_if_enabled();
723 /* If not argument is specified inspect the manager
726 return show_properties(bus, "/org/freedesktop/login1", &new_line);
728 /* And in the pretty case, show data of the calling session */
729 return print_session_status_info(bus, "/org/freedesktop/login1/session/self", &new_line);
732 for (i = 1; i < argc; i++) {
733 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
734 _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
735 const char *path = NULL;
737 r = sd_bus_call_method(
739 "org.freedesktop.login1",
740 "/org/freedesktop/login1",
741 "org.freedesktop.login1.Manager",
746 log_error("Failed to get session: %s", bus_error_message(&error, r));
750 r = sd_bus_message_read(reply, "o", &path);
752 return bus_log_parse_error(r);
755 r = show_properties(bus, path, &new_line);
757 r = print_session_status_info(bus, path, &new_line);
766 static int show_user(int argc, char *argv[], void *userdata) {
767 bool properties, new_line = false;
768 sd_bus *bus = userdata;
774 properties = !strstr(argv[0], "status");
776 pager_open_if_enabled();
779 /* If not argument is specified inspect the manager
782 return show_properties(bus, "/org/freedesktop/login1", &new_line);
784 return print_user_status_info(bus, "/org/freedesktop/login1/user/self", &new_line);
787 for (i = 1; i < argc; i++) {
788 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
789 _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
790 const char *path = NULL;
793 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
795 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
797 r = sd_bus_call_method(
799 "org.freedesktop.login1",
800 "/org/freedesktop/login1",
801 "org.freedesktop.login1.Manager",
804 "u", (uint32_t) uid);
806 log_error("Failed to get user: %s", bus_error_message(&error, r));
810 r = sd_bus_message_read(reply, "o", &path);
812 return bus_log_parse_error(r);
815 r = show_properties(bus, path, &new_line);
817 r = print_user_status_info(bus, path, &new_line);
826 static int show_seat(int argc, char *argv[], void *userdata) {
827 bool properties, new_line = false;
828 sd_bus *bus = userdata;
834 properties = !strstr(argv[0], "status");
836 pager_open_if_enabled();
839 /* If not argument is specified inspect the manager
842 return show_properties(bus, "/org/freedesktop/login1", &new_line);
844 return print_seat_status_info(bus, "/org/freedesktop/login1/seat/self", &new_line);
847 for (i = 1; i < argc; i++) {
848 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
849 _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
850 const char *path = NULL;
852 r = sd_bus_call_method(
854 "org.freedesktop.login1",
855 "/org/freedesktop/login1",
856 "org.freedesktop.login1.Manager",
861 log_error("Failed to get seat: %s", bus_error_message(&error, r));
865 r = sd_bus_message_read(reply, "o", &path);
867 return bus_log_parse_error(r);
870 r = show_properties(bus, path, &new_line);
872 r = print_seat_status_info(bus, path, &new_line);
881 static int activate(int argc, char *argv[], void *userdata) {
882 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
883 sd_bus *bus = userdata;
890 polkit_agent_open_if_enabled();
893 /* No argument? Let's convert this into the empty
894 * session name, which the calls will then resolve to
895 * the caller's session. */
897 short_argv[0] = argv[0];
898 short_argv[1] = (char*) "";
899 short_argv[2] = NULL;
905 for (i = 1; i < argc; i++) {
907 r = sd_bus_call_method(
909 "org.freedesktop.login1",
910 "/org/freedesktop/login1",
911 "org.freedesktop.login1.Manager",
912 streq(argv[0], "lock-session") ? "LockSession" :
913 streq(argv[0], "unlock-session") ? "UnlockSession" :
914 streq(argv[0], "terminate-session") ? "TerminateSession" :
919 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
927 static int kill_session(int argc, char *argv[], void *userdata) {
928 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
929 sd_bus *bus = userdata;
935 polkit_agent_open_if_enabled();
938 arg_kill_who = "all";
940 for (i = 1; i < argc; i++) {
942 r = sd_bus_call_method(
944 "org.freedesktop.login1",
945 "/org/freedesktop/login1",
946 "org.freedesktop.login1.Manager",
949 "ssi", argv[i], arg_kill_who, arg_signal);
951 log_error("Could not kill session: %s", bus_error_message(&error, -r));
959 static int enable_linger(int argc, char *argv[], void *userdata) {
960 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
961 sd_bus *bus = userdata;
969 polkit_agent_open_if_enabled();
971 b = streq(argv[0], "enable-linger");
974 short_argv[0] = argv[0];
975 short_argv[1] = (char*) "";
976 short_argv[2] = NULL;
981 for (i = 1; i < argc; i++) {
984 if (isempty(argv[i]))
987 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
989 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
992 r = sd_bus_call_method(
994 "org.freedesktop.login1",
995 "/org/freedesktop/login1",
996 "org.freedesktop.login1.Manager",
999 "ubb", (uint32_t) uid, b, true);
1001 log_error("Could not enable linger: %s", bus_error_message(&error, -r));
1009 static int terminate_user(int argc, char *argv[], void *userdata) {
1010 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1011 sd_bus *bus = userdata;
1017 polkit_agent_open_if_enabled();
1019 for (i = 1; i < argc; i++) {
1022 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
1024 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
1026 r = sd_bus_call_method(
1028 "org.freedesktop.login1",
1029 "/org/freedesktop/login1",
1030 "org.freedesktop.login1.Manager",
1033 "u", (uint32_t) uid);
1035 log_error("Could not terminate user: %s", bus_error_message(&error, -r));
1043 static int kill_user(int argc, char *argv[], void *userdata) {
1044 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1045 sd_bus *bus = userdata;
1051 polkit_agent_open_if_enabled();
1054 arg_kill_who = "all";
1056 for (i = 1; i < argc; i++) {
1059 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
1061 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
1063 r = sd_bus_call_method(
1065 "org.freedesktop.login1",
1066 "/org/freedesktop/login1",
1067 "org.freedesktop.login1.Manager",
1070 "ui", (uint32_t) uid, arg_signal);
1072 log_error("Could not kill user: %s", bus_error_message(&error, -r));
1080 static int attach(int argc, char *argv[], void *userdata) {
1081 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1082 sd_bus *bus = userdata;
1088 polkit_agent_open_if_enabled();
1090 for (i = 2; i < argc; i++) {
1092 r = sd_bus_call_method(
1094 "org.freedesktop.login1",
1095 "/org/freedesktop/login1",
1096 "org.freedesktop.login1.Manager",
1099 "ssb", argv[1], argv[i], true);
1102 log_error("Could not attach device: %s", bus_error_message(&error, -r));
1110 static int flush_devices(int argc, char *argv[], void *userdata) {
1111 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1112 sd_bus *bus = userdata;
1118 polkit_agent_open_if_enabled();
1120 r = sd_bus_call_method(
1122 "org.freedesktop.login1",
1123 "/org/freedesktop/login1",
1124 "org.freedesktop.login1.Manager",
1129 log_error("Could not flush devices: %s", bus_error_message(&error, -r));
1134 static int lock_sessions(int argc, char *argv[], void *userdata) {
1135 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1136 sd_bus *bus = userdata;
1142 polkit_agent_open_if_enabled();
1144 r = sd_bus_call_method(
1146 "org.freedesktop.login1",
1147 "/org/freedesktop/login1",
1148 "org.freedesktop.login1.Manager",
1149 streq(argv[0], "lock-sessions") ? "LockSessions" : "UnlockSessions",
1153 log_error("Could not lock sessions: %s", bus_error_message(&error, -r));
1158 static int terminate_seat(int argc, char *argv[], void *userdata) {
1159 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1160 sd_bus *bus = userdata;
1166 polkit_agent_open_if_enabled();
1168 for (i = 1; i < argc; i++) {
1170 r = sd_bus_call_method(
1172 "org.freedesktop.login1",
1173 "/org/freedesktop/login1",
1174 "org.freedesktop.login1.Manager",
1179 log_error("Could not terminate seat: %s", bus_error_message(&error, -r));
1187 static int check_inhibitors(sd_bus *bus, const char *verb, const char *inhibit_what) {
1188 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1189 _cleanup_strv_free_ char **sessions = NULL;
1190 const char *what, *who, *why, *mode;
1198 if (arg_ignore_inhibitors)
1207 r = sd_bus_call_method(
1209 "org.freedesktop.login1",
1210 "/org/freedesktop/login1",
1211 "org.freedesktop.login1.Manager",
1217 /* If logind is not around, then there are no inhibitors... */
1220 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
1222 return bus_log_parse_error(r);
1224 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
1225 _cleanup_free_ char *comm = NULL, *user = NULL;
1226 _cleanup_strv_free_ char **sv = NULL;
1228 if (!streq(mode, "block"))
1231 sv = strv_split(what, ":");
1235 if (!strv_contains(sv, inhibit_what))
1238 get_process_comm(pid, &comm);
1239 user = uid_to_name(uid);
1241 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
1242 who, pid, strna(comm), strna(user), why);
1247 return bus_log_parse_error(r);
1249 r = sd_bus_message_exit_container(reply);
1251 return bus_log_parse_error(r);
1253 /* Check for current sessions */
1254 sd_get_sessions(&sessions);
1255 STRV_FOREACH(s, sessions) {
1256 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
1258 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
1261 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
1264 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
1267 sd_session_get_tty(*s, &tty);
1268 sd_session_get_seat(*s, &seat);
1269 sd_session_get_service(*s, &service);
1270 user = uid_to_name(uid);
1272 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
1279 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'loginctl %s -i'.", verb);
1284 static int poweroff(int argc, char *argv[], void *userdata) {
1285 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1286 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1287 sd_bus *bus = userdata;
1292 r = check_inhibitors(bus, "poweroff", "shutdown");
1296 polkit_agent_open_if_enabled();
1298 r = sd_bus_call_method(
1300 "org.freedesktop.login1",
1301 "/org/freedesktop/login1",
1302 "org.freedesktop.login1.Manager",
1306 "b", arg_ask_password);
1308 log_error("Failed to power off: %s", bus_error_message(&error, r));
1313 static int reboot(int argc, char *argv[], void *userdata) {
1314 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1315 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1316 sd_bus *bus = userdata;
1321 r = check_inhibitors(bus, "reboot", "shutdown");
1325 polkit_agent_open_if_enabled();
1327 r = sd_bus_call_method(
1329 "org.freedesktop.login1",
1330 "/org/freedesktop/login1",
1331 "org.freedesktop.login1.Manager",
1335 "b", arg_ask_password);
1337 log_error("Failed to reboot: %s", bus_error_message(&error, r));
1342 static int suspend(int argc, char *argv[], void *userdata) {
1343 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1344 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1345 sd_bus *bus = userdata;
1350 r = check_inhibitors(bus, "suspend", "sleep");
1354 polkit_agent_open_if_enabled();
1356 r = sd_bus_call_method(
1358 "org.freedesktop.login1",
1359 "/org/freedesktop/login1",
1360 "org.freedesktop.login1.Manager",
1364 "b", arg_ask_password);
1366 log_error("Failed to suspend: %s", bus_error_message(&error, r));
1371 static int hibernate(int argc, char *argv[], void *userdata) {
1372 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1373 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1374 sd_bus *bus = userdata;
1379 r = check_inhibitors(bus, "hibernate", "sleep");
1383 polkit_agent_open_if_enabled();
1385 r = sd_bus_call_method(
1387 "org.freedesktop.login1",
1388 "/org/freedesktop/login1",
1389 "org.freedesktop.login1.Manager",
1393 "b", arg_ask_password);
1395 log_error("Failed to hibernate: %s", bus_error_message(&error, r));
1400 static int hybrid_sleep(int argc, char *argv[], void *userdata) {
1401 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1402 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1403 sd_bus *bus = userdata;
1408 r = check_inhibitors(bus, "hybrid-sleep", "sleep");
1412 polkit_agent_open_if_enabled();
1414 r = sd_bus_call_method(
1416 "org.freedesktop.login1",
1417 "/org/freedesktop/login1",
1418 "org.freedesktop.login1.Manager",
1422 "b", arg_ask_password);
1424 log_error("Failed to hybrid sleep: %s", bus_error_message(&error, r));
1429 static int help(int argc, char *argv[], void *userdata) {
1431 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
1432 "Send control commands to or query the login manager.\n\n"
1433 " -h --help Show this help\n"
1434 " --version Show package version\n"
1435 " --no-pager Do not pipe output into a pager\n"
1436 " --no-legend Do not show the headers and footers\n"
1437 " --no-ask-password Don't prompt for password\n"
1438 " -i --ignore-inhibitors Ignore inhibitors when suspending or shutting down\n"
1439 " -H --host=[USER@]HOST Operate on remote host\n"
1440 " -M --machine=CONTAINER Operate on local container\n"
1441 " -p --property=NAME Show only properties by this name\n"
1442 " -a --all Show all properties, including empty ones\n"
1443 " -l --full Do not ellipsize output\n"
1444 " --kill-who=WHO Who to send signal to\n"
1445 " -s --signal=SIGNAL Which signal to send\n"
1446 " -n --lines=INTEGER Number of journal entries to show\n"
1447 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
1448 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
1449 "Session Commands:\n"
1450 " list-sessions List sessions\n"
1451 " session-status [ID...] Show session status\n"
1452 " show-session [ID...] Show properties of sessions or the manager\n"
1453 " activate [ID] Activate a session\n"
1454 " lock-session [ID...] Screen lock one or more sessions\n"
1455 " unlock-session [ID...] Screen unlock one or more sessions\n"
1456 " lock-sessions Screen lock all current sessions\n"
1457 " unlock-sessions Screen unlock all current sessions\n"
1458 " terminate-session ID... Terminate one or more sessions\n"
1459 " kill-session ID... Send signal to processes of a session\n\n"
1461 " list-users List users\n"
1462 " user-status [USER...] Show user status\n"
1463 " show-user [USER...] Show properties of users or the manager\n"
1464 " enable-linger [USER...] Enable linger state of one or more users\n"
1465 " disable-linger [USER...] Disable linger state of one or more users\n"
1466 " terminate-user USER... Terminate all sessions of one or more users\n"
1467 " kill-user USER... Send signal to processes of a user\n\n"
1469 " list-seats List seats\n"
1470 " seat-status [NAME...] Show seat status\n"
1471 " show-seat [NAME...] Show properties of seats or the manager\n"
1472 " attach NAME DEVICE... Attach one or more devices to a seat\n"
1473 " flush-devices Flush all device associations\n"
1474 " terminate-seat NAME... Terminate all sessions on one or more seats\n\n"
1475 "System Commands:\n"
1476 " poweroff Turn off the machine\n"
1477 " reboot Reboot the machine\n"
1478 " suspend Suspend the machine to memory\n"
1479 " hibernate Suspend the machine to disk\n"
1480 " hybrid-sleep Suspend the machine to memory and disk\n"
1481 , program_invocation_short_name);
1486 static int parse_argv(int argc, char *argv[]) {
1489 ARG_VERSION = 0x100,
1493 ARG_NO_ASK_PASSWORD,
1496 static const struct option options[] = {
1497 { "help", no_argument, NULL, 'h' },
1498 { "version", no_argument, NULL, ARG_VERSION },
1499 { "property", required_argument, NULL, 'p' },
1500 { "all", no_argument, NULL, 'a' },
1501 { "full", no_argument, NULL, 'l' },
1502 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
1503 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
1504 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
1505 { "signal", required_argument, NULL, 's' },
1506 { "host", required_argument, NULL, 'H' },
1507 { "machine", required_argument, NULL, 'M' },
1508 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
1509 { "ignore-inhibitors", no_argument, NULL, 'i' },
1510 { "lines", required_argument, NULL, 'n' },
1511 { "output", required_argument, NULL, 'o' },
1520 while ((c = getopt_long(argc, argv, "hp:als:H:M:n:o:i", options, NULL)) >= 0)
1525 help(0, NULL, NULL);
1529 puts(PACKAGE_STRING);
1530 puts(SYSTEMD_FEATURES);
1534 r = strv_extend(&arg_property, optarg);
1538 /* If the user asked for a particular
1539 * property, show it to him, even if it is
1554 if (safe_atou(optarg, &arg_lines) < 0) {
1555 log_error("Failed to parse lines '%s'", optarg);
1562 arg_output = output_mode_from_string(optarg);
1566 if (arg_output < 0) {
1567 log_error("Unknown output '%s'.", optarg);
1573 arg_ignore_inhibitors = true;
1577 arg_no_pager = true;
1584 case ARG_NO_ASK_PASSWORD:
1585 arg_ask_password = false;
1589 arg_kill_who = optarg;
1593 arg_signal = signal_from_string_try_harder(optarg);
1594 if (arg_signal < 0) {
1595 log_error("Failed to parse signal string %s.", optarg);
1601 arg_transport = BUS_TRANSPORT_REMOTE;
1606 arg_transport = BUS_TRANSPORT_MACHINE;
1614 assert_not_reached("Unhandled option");
1620 static int loginctl_main(int argc, char *argv[], sd_bus *bus) {
1622 static const Verb verbs[] = {
1623 { "help", VERB_ANY, VERB_ANY, 0, help },
1624 { "list-sessions", VERB_ANY, 1, VERB_DEFAULT, list_sessions },
1625 { "session-status", VERB_ANY, VERB_ANY, 0, show_session },
1626 { "show-session", VERB_ANY, VERB_ANY, 0, show_session },
1627 { "activate", VERB_ANY, 2, 0, activate },
1628 { "lock-session", VERB_ANY, VERB_ANY, 0, activate },
1629 { "unlock-session", VERB_ANY, VERB_ANY, 0, activate },
1630 { "lock-sessions", VERB_ANY, 1, 0, lock_sessions },
1631 { "unlock-sessions", VERB_ANY, 1, 0, lock_sessions },
1632 { "terminate-session", 2, VERB_ANY, 0, activate },
1633 { "kill-session", 2, VERB_ANY, 0, kill_session },
1634 { "list-users", VERB_ANY, 1, 0, list_users },
1635 { "user-status", VERB_ANY, VERB_ANY, 0, show_user },
1636 { "show-user", VERB_ANY, VERB_ANY, 0, show_user },
1637 { "enable-linger", VERB_ANY, VERB_ANY, 0, enable_linger },
1638 { "disable-linger", VERB_ANY, VERB_ANY, 0, enable_linger },
1639 { "terminate-user", 2, VERB_ANY, 0, terminate_user },
1640 { "kill-user", 2, VERB_ANY, 0, kill_user },
1641 { "list-seats", VERB_ANY, 1, 0, list_seats },
1642 { "seat-status", VERB_ANY, VERB_ANY, 0, show_seat },
1643 { "show-seat", VERB_ANY, VERB_ANY, 0, show_seat },
1644 { "attach", 3, VERB_ANY, 0, attach },
1645 { "flush-devices", VERB_ANY, 1, 0, flush_devices },
1646 { "terminate-seat", 2, VERB_ANY, 0, terminate_seat },
1647 { "poweroff", VERB_ANY, 1, 0, poweroff },
1648 { "reboot", VERB_ANY, 1, 0, reboot },
1649 { "suspend", VERB_ANY, 1, 0, suspend },
1650 { "hibernate", VERB_ANY, 1, 0, hibernate },
1651 { "hybrid-sleep", VERB_ANY, 1, 0, hybrid_sleep },
1655 return dispatch_verb(argc, argv, verbs, bus);
1658 int main(int argc, char *argv[]) {
1659 _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
1662 setlocale(LC_ALL, "");
1663 log_parse_environment();
1666 r = parse_argv(argc, argv);
1670 r = bus_open_transport(arg_transport, arg_host, false, &bus);
1672 log_error_errno(r, "Failed to create bus connection: %m");
1676 sd_bus_set_allow_interactive_authorization(bus, arg_ask_password);
1678 r = loginctl_main(argc, argv, bus);
1682 polkit_agent_close();
1684 strv_free(arg_property);
1686 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;