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;
291 const char *remote_host;
292 const char *remote_user;
302 typedef struct UserStatusInfo {
305 struct dual_timestamp timestamp;
312 typedef struct SeatStatusInfo {
314 const char *active_session;
318 static int prop_map_first_of_struct(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
319 const char *contents;
322 r = sd_bus_message_peek_type(m, NULL, &contents);
326 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, contents);
330 if (contents[0] == 's' || contents[0] == 'o') {
332 char **p = (char **) userdata;
334 r = sd_bus_message_read_basic(m, contents[0], &s);
344 r = sd_bus_message_read_basic(m, contents[0], userdata);
349 r = sd_bus_message_skip(m, contents+1);
353 r = sd_bus_message_exit_container(m);
360 static int prop_map_sessions_strv(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
367 r = sd_bus_message_enter_container(m, 'a', "(so)");
371 while ((r = sd_bus_message_read(m, "(so)", &name, NULL)) > 0) {
372 r = strv_extend(userdata, name);
379 return sd_bus_message_exit_container(m);
382 static int print_session_status_info(sd_bus *bus, const char *path, bool *new_line) {
384 static const struct bus_properties_map map[] = {
385 { "Id", "s", NULL, offsetof(SessionStatusInfo, id) },
386 { "Name", "s", NULL, offsetof(SessionStatusInfo, name) },
387 { "TTY", "s", NULL, offsetof(SessionStatusInfo, tty) },
388 { "Display", "s", NULL, offsetof(SessionStatusInfo, display) },
389 { "RemoteHost", "s", NULL, offsetof(SessionStatusInfo, remote_host) },
390 { "RemoteUser", "s", NULL, offsetof(SessionStatusInfo, remote_user) },
391 { "Service", "s", NULL, offsetof(SessionStatusInfo, service) },
392 { "Desktop", "s", NULL, offsetof(SessionStatusInfo, desktop) },
393 { "Type", "s", NULL, offsetof(SessionStatusInfo, type) },
394 { "Class", "s", NULL, offsetof(SessionStatusInfo, class) },
395 { "Scope", "s", NULL, offsetof(SessionStatusInfo, scope) },
396 { "State", "s", NULL, offsetof(SessionStatusInfo, state) },
397 { "VTNr", "u", NULL, offsetof(SessionStatusInfo, vtnr) },
398 { "Leader", "u", NULL, offsetof(SessionStatusInfo, leader) },
399 { "Remote", "b", NULL, offsetof(SessionStatusInfo, remote) },
400 { "Timestamp", "t", NULL, offsetof(SessionStatusInfo, timestamp.realtime) },
401 { "TimestampMonotonic", "t", NULL, offsetof(SessionStatusInfo, timestamp.monotonic) },
402 { "User", "(uo)", prop_map_first_of_struct, offsetof(SessionStatusInfo, uid) },
403 { "Seat", "(so)", prop_map_first_of_struct, offsetof(SessionStatusInfo, seat) },
407 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
408 char since2[FORMAT_TIMESTAMP_MAX], *s2;
409 SessionStatusInfo i = {};
412 r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i);
414 return log_error_errno(r, "Could not get properties: %m");
421 printf("%s - ", strna(i.id));
424 printf("%s (%u)\n", i.name, (unsigned) i.uid);
426 printf("%u\n", (unsigned) i.uid);
428 s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime);
429 s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime);
432 printf("\t Since: %s; %s\n", s2, s1);
434 printf("\t Since: %s\n", s2);
437 _cleanup_free_ char *t = NULL;
439 printf("\t Leader: %u", (unsigned) i.leader);
441 get_process_comm(i.leader, &t);
448 if (!isempty(i.seat)) {
449 printf("\t Seat: %s", i.seat);
452 printf("; vc%u", i.vtnr);
458 printf("\t TTY: %s\n", i.tty);
460 printf("\t Display: %s\n", i.display);
462 if (i.remote_host && i.remote_user)
463 printf("\t Remote: %s@%s\n", i.remote_user, i.remote_host);
464 else if (i.remote_host)
465 printf("\t Remote: %s\n", i.remote_host);
466 else if (i.remote_user)
467 printf("\t Remote: user %s\n", i.remote_user);
469 printf("\t Remote: Yes\n");
472 printf("\t Service: %s", i.service);
475 printf("; type %s", i.type);
478 printf("; class %s", i.class);
482 printf("\t Type: %s", i.type);
485 printf("; class %s", i.class);
489 printf("\t Class: %s\n", i.class);
491 if (!isempty(i.desktop))
492 printf("\t Desktop: %s\n", i.desktop);
495 printf("\t State: %s\n", i.state);
498 printf("\t Unit: %s\n", i.scope);
499 show_unit_cgroup(bus, "org.freedesktop.systemd1.Scope", i.scope, i.leader);
501 if (arg_transport == BUS_TRANSPORT_LOCAL) {
503 show_journal_by_unit(
508 i.timestamp.monotonic,
511 get_output_flags() | OUTPUT_BEGIN_NEWLINE,
512 SD_JOURNAL_LOCAL_ONLY,
522 static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line) {
524 static const struct bus_properties_map map[] = {
525 { "Name", "s", NULL, offsetof(UserStatusInfo, name) },
526 { "Slice", "s", NULL, offsetof(UserStatusInfo, slice) },
527 { "State", "s", NULL, offsetof(UserStatusInfo, state) },
528 { "UID", "u", NULL, offsetof(UserStatusInfo, uid) },
529 { "Timestamp", "t", NULL, offsetof(UserStatusInfo, timestamp.realtime) },
530 { "TimestampMonotonic", "t", NULL, offsetof(UserStatusInfo, timestamp.monotonic) },
531 { "Display", "(so)", prop_map_first_of_struct, offsetof(UserStatusInfo, display) },
532 { "Sessions", "a(so)", prop_map_sessions_strv, offsetof(UserStatusInfo, sessions) },
536 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
537 char since2[FORMAT_TIMESTAMP_MAX], *s2;
538 UserStatusInfo i = {};
541 r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i);
543 log_error_errno(r, "Could not get properties: %m");
553 printf("%s (%u)\n", i.name, (unsigned) i.uid);
555 printf("%u\n", (unsigned) i.uid);
557 s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime);
558 s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime);
561 printf("\t Since: %s; %s\n", s2, s1);
563 printf("\t Since: %s\n", s2);
565 if (!isempty(i.state))
566 printf("\t State: %s\n", i.state);
568 if (!strv_isempty(i.sessions)) {
570 printf("\tSessions:");
572 STRV_FOREACH(l, i.sessions) {
573 if (streq_ptr(*l, i.display))
583 printf("\t Unit: %s\n", i.slice);
584 show_unit_cgroup(bus, "org.freedesktop.systemd1.Slice", i.slice, 0);
586 show_journal_by_unit(
591 i.timestamp.monotonic,
594 get_output_flags() | OUTPUT_BEGIN_NEWLINE,
595 SD_JOURNAL_LOCAL_ONLY,
602 strv_free(i.sessions);
607 static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line) {
609 static const struct bus_properties_map map[] = {
610 { "Id", "s", NULL, offsetof(SeatStatusInfo, id) },
611 { "ActiveSession", "(so)", prop_map_first_of_struct, offsetof(SeatStatusInfo, active_session) },
612 { "Sessions", "a(so)", prop_map_sessions_strv, offsetof(SeatStatusInfo, sessions) },
616 SeatStatusInfo i = {};
619 r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i);
621 log_error_errno(r, "Could not get properties: %m");
630 printf("%s\n", strna(i.id));
632 if (!strv_isempty(i.sessions)) {
634 printf("\tSessions:");
636 STRV_FOREACH(l, i.sessions) {
637 if (streq_ptr(*l, i.active_session))
646 if (arg_transport == BUS_TRANSPORT_LOCAL) {
655 printf("\t Devices:\n");
657 show_sysfs(i.id, "\t\t ", c);
661 strv_free(i.sessions);
666 static int show_properties(sd_bus *bus, const char *path, bool *new_line) {
674 r = bus_print_all_properties(bus, "org.freedesktop.login1", path, arg_property, arg_all);
676 log_error_errno(r, "Could not get properties: %m");
681 static int show_session(int argc, char *argv[], void *userdata) {
682 bool properties, new_line = false;
683 sd_bus *bus = userdata;
689 properties = !strstr(argv[0], "status");
691 pager_open_if_enabled();
694 /* If not argument is specified inspect the manager
697 return show_properties(bus, "/org/freedesktop/login1", &new_line);
699 /* And in the pretty case, show data of the calling session */
700 return print_session_status_info(bus, "/org/freedesktop/login1/session/self", &new_line);
703 for (i = 1; i < argc; i++) {
704 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
705 _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
706 const char *path = NULL;
708 r = sd_bus_call_method(
710 "org.freedesktop.login1",
711 "/org/freedesktop/login1",
712 "org.freedesktop.login1.Manager",
717 log_error("Failed to get session: %s", bus_error_message(&error, r));
721 r = sd_bus_message_read(reply, "o", &path);
723 return bus_log_parse_error(r);
726 r = show_properties(bus, path, &new_line);
728 r = print_session_status_info(bus, path, &new_line);
737 static int show_user(int argc, char *argv[], void *userdata) {
738 bool properties, new_line = false;
739 sd_bus *bus = userdata;
745 properties = !strstr(argv[0], "status");
747 pager_open_if_enabled();
750 /* If not argument is specified inspect the manager
753 return show_properties(bus, "/org/freedesktop/login1", &new_line);
755 return print_user_status_info(bus, "/org/freedesktop/login1/user/self", &new_line);
758 for (i = 1; i < argc; i++) {
759 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
760 _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
761 const char *path = NULL;
764 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
766 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
768 r = sd_bus_call_method(
770 "org.freedesktop.login1",
771 "/org/freedesktop/login1",
772 "org.freedesktop.login1.Manager",
775 "u", (uint32_t) uid);
777 log_error("Failed to get user: %s", bus_error_message(&error, r));
781 r = sd_bus_message_read(reply, "o", &path);
783 return bus_log_parse_error(r);
786 r = show_properties(bus, path, &new_line);
788 r = print_user_status_info(bus, path, &new_line);
797 static int show_seat(int argc, char *argv[], void *userdata) {
798 bool properties, new_line = false;
799 sd_bus *bus = userdata;
805 properties = !strstr(argv[0], "status");
807 pager_open_if_enabled();
810 /* If not argument is specified inspect the manager
813 return show_properties(bus, "/org/freedesktop/login1", &new_line);
815 return print_seat_status_info(bus, "/org/freedesktop/login1/seat/self", &new_line);
818 for (i = 1; i < argc; i++) {
819 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
820 _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
821 const char *path = NULL;
823 r = sd_bus_call_method(
825 "org.freedesktop.login1",
826 "/org/freedesktop/login1",
827 "org.freedesktop.login1.Manager",
832 log_error("Failed to get seat: %s", bus_error_message(&error, r));
836 r = sd_bus_message_read(reply, "o", &path);
838 return bus_log_parse_error(r);
841 r = show_properties(bus, path, &new_line);
843 r = print_seat_status_info(bus, path, &new_line);
852 static int activate(int argc, char *argv[], void *userdata) {
853 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
854 sd_bus *bus = userdata;
861 polkit_agent_open_if_enabled();
864 /* No argument? Let's convert this into the empty
865 * session name, which the calls will then resolve to
866 * the caller's session. */
868 short_argv[0] = argv[0];
869 short_argv[1] = (char*) "";
870 short_argv[2] = NULL;
876 for (i = 1; i < argc; i++) {
878 r = sd_bus_call_method(
880 "org.freedesktop.login1",
881 "/org/freedesktop/login1",
882 "org.freedesktop.login1.Manager",
883 streq(argv[0], "lock-session") ? "LockSession" :
884 streq(argv[0], "unlock-session") ? "UnlockSession" :
885 streq(argv[0], "terminate-session") ? "TerminateSession" :
890 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
898 static int kill_session(int argc, char *argv[], void *userdata) {
899 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
900 sd_bus *bus = userdata;
906 polkit_agent_open_if_enabled();
909 arg_kill_who = "all";
911 for (i = 1; i < argc; i++) {
913 r = sd_bus_call_method(
915 "org.freedesktop.login1",
916 "/org/freedesktop/login1",
917 "org.freedesktop.login1.Manager",
920 "ssi", argv[i], arg_kill_who, arg_signal);
922 log_error("Could not kill session: %s", bus_error_message(&error, -r));
930 static int enable_linger(int argc, char *argv[], void *userdata) {
931 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
932 sd_bus *bus = userdata;
940 polkit_agent_open_if_enabled();
942 b = streq(argv[0], "enable-linger");
945 short_argv[0] = argv[0];
946 short_argv[1] = (char*) "";
947 short_argv[2] = NULL;
952 for (i = 1; i < argc; i++) {
955 if (isempty(argv[i]))
958 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
960 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
963 r = sd_bus_call_method(
965 "org.freedesktop.login1",
966 "/org/freedesktop/login1",
967 "org.freedesktop.login1.Manager",
970 "ubb", (uint32_t) uid, b, true);
972 log_error("Could not enable linger: %s", bus_error_message(&error, -r));
980 static int terminate_user(int argc, char *argv[], void *userdata) {
981 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
982 sd_bus *bus = userdata;
988 polkit_agent_open_if_enabled();
990 for (i = 1; i < argc; i++) {
993 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
995 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
997 r = sd_bus_call_method(
999 "org.freedesktop.login1",
1000 "/org/freedesktop/login1",
1001 "org.freedesktop.login1.Manager",
1004 "u", (uint32_t) uid);
1006 log_error("Could not terminate user: %s", bus_error_message(&error, -r));
1014 static int kill_user(int argc, char *argv[], void *userdata) {
1015 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1016 sd_bus *bus = userdata;
1022 polkit_agent_open_if_enabled();
1025 arg_kill_who = "all";
1027 for (i = 1; i < argc; i++) {
1030 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
1032 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
1034 r = sd_bus_call_method(
1036 "org.freedesktop.login1",
1037 "/org/freedesktop/login1",
1038 "org.freedesktop.login1.Manager",
1041 "ui", (uint32_t) uid, arg_signal);
1043 log_error("Could not kill user: %s", bus_error_message(&error, -r));
1051 static int attach(int argc, char *argv[], void *userdata) {
1052 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1053 sd_bus *bus = userdata;
1059 polkit_agent_open_if_enabled();
1061 for (i = 2; i < argc; i++) {
1063 r = sd_bus_call_method(
1065 "org.freedesktop.login1",
1066 "/org/freedesktop/login1",
1067 "org.freedesktop.login1.Manager",
1070 "ssb", argv[1], argv[i], true);
1073 log_error("Could not attach device: %s", bus_error_message(&error, -r));
1081 static int flush_devices(int argc, char *argv[], void *userdata) {
1082 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1083 sd_bus *bus = userdata;
1089 polkit_agent_open_if_enabled();
1091 r = sd_bus_call_method(
1093 "org.freedesktop.login1",
1094 "/org/freedesktop/login1",
1095 "org.freedesktop.login1.Manager",
1100 log_error("Could not flush devices: %s", bus_error_message(&error, -r));
1105 static int lock_sessions(int argc, char *argv[], void *userdata) {
1106 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1107 sd_bus *bus = userdata;
1113 polkit_agent_open_if_enabled();
1115 r = sd_bus_call_method(
1117 "org.freedesktop.login1",
1118 "/org/freedesktop/login1",
1119 "org.freedesktop.login1.Manager",
1120 streq(argv[0], "lock-sessions") ? "LockSessions" : "UnlockSessions",
1124 log_error("Could not lock sessions: %s", bus_error_message(&error, -r));
1129 static int terminate_seat(int argc, char *argv[], void *userdata) {
1130 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1131 sd_bus *bus = userdata;
1137 polkit_agent_open_if_enabled();
1139 for (i = 1; i < argc; i++) {
1141 r = sd_bus_call_method(
1143 "org.freedesktop.login1",
1144 "/org/freedesktop/login1",
1145 "org.freedesktop.login1.Manager",
1150 log_error("Could not terminate seat: %s", bus_error_message(&error, -r));
1158 static int check_inhibitors(sd_bus *bus, const char *verb, const char *inhibit_what) {
1159 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1160 _cleanup_strv_free_ char **sessions = NULL;
1161 const char *what, *who, *why, *mode;
1169 if (arg_ignore_inhibitors)
1178 r = sd_bus_call_method(
1180 "org.freedesktop.login1",
1181 "/org/freedesktop/login1",
1182 "org.freedesktop.login1.Manager",
1188 /* If logind is not around, then there are no inhibitors... */
1191 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
1193 return bus_log_parse_error(r);
1195 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
1196 _cleanup_free_ char *comm = NULL, *user = NULL;
1197 _cleanup_strv_free_ char **sv = NULL;
1199 if (!streq(mode, "block"))
1202 sv = strv_split(what, ":");
1206 if (!strv_contains(sv, inhibit_what))
1209 get_process_comm(pid, &comm);
1210 user = uid_to_name(uid);
1212 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
1213 who, pid, strna(comm), strna(user), why);
1218 return bus_log_parse_error(r);
1220 r = sd_bus_message_exit_container(reply);
1222 return bus_log_parse_error(r);
1224 /* Check for current sessions */
1225 sd_get_sessions(&sessions);
1226 STRV_FOREACH(s, sessions) {
1227 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
1229 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
1232 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
1235 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
1238 sd_session_get_tty(*s, &tty);
1239 sd_session_get_seat(*s, &seat);
1240 sd_session_get_service(*s, &service);
1241 user = uid_to_name(uid);
1243 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
1250 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'loginctl %s -i'.", verb);
1255 static int poweroff(int argc, char *argv[], void *userdata) {
1256 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1257 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1258 sd_bus *bus = userdata;
1263 r = check_inhibitors(bus, "poweroff", "shutdown");
1267 polkit_agent_open_if_enabled();
1269 r = sd_bus_call_method(
1271 "org.freedesktop.login1",
1272 "/org/freedesktop/login1",
1273 "org.freedesktop.login1.Manager",
1277 "b", arg_ask_password);
1279 log_error("Failed to power off: %s", bus_error_message(&error, r));
1284 static int reboot(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, "reboot", "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 reboot: %s", bus_error_message(&error, r));
1313 static int suspend(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, "suspend", "sleep");
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 suspend: %s", bus_error_message(&error, r));
1342 static int hibernate(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, "hibernate", "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 hibernate: %s", bus_error_message(&error, r));
1371 static int hybrid_sleep(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, "hybrid-sleep", "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 hybrid sleep: %s", bus_error_message(&error, r));
1400 static int help(int argc, char *argv[], void *userdata) {
1402 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
1403 "Send control commands to or query the login manager.\n\n"
1404 " -h --help Show this help\n"
1405 " --version Show package version\n"
1406 " --no-pager Do not pipe output into a pager\n"
1407 " --no-legend Do not show the headers and footers\n"
1408 " --no-ask-password Don't prompt for password\n"
1409 " -i --ignore-inhibitors Ignore inhibitors when suspending or shutting down\n"
1410 " -H --host=[USER@]HOST Operate on remote host\n"
1411 " -M --machine=CONTAINER Operate on local container\n"
1412 " -p --property=NAME Show only properties by this name\n"
1413 " -a --all Show all properties, including empty ones\n"
1414 " -l --full Do not ellipsize output\n"
1415 " --kill-who=WHO Who to send signal to\n"
1416 " -s --signal=SIGNAL Which signal to send\n"
1417 " -n --lines=INTEGER Number of journal entries to show\n"
1418 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
1419 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
1420 "Session Commands:\n"
1421 " list-sessions List sessions\n"
1422 " session-status [ID...] Show session status\n"
1423 " show-session [ID...] Show properties of sessions or the manager\n"
1424 " activate [ID] Activate a session\n"
1425 " lock-session [ID...] Screen lock one or more sessions\n"
1426 " unlock-session [ID...] Screen unlock one or more sessions\n"
1427 " lock-sessions Screen lock all current sessions\n"
1428 " unlock-sessions Screen unlock all current sessions\n"
1429 " terminate-session ID... Terminate one or more sessions\n"
1430 " kill-session ID... Send signal to processes of a session\n\n"
1432 " list-users List users\n"
1433 " user-status [USER...] Show user status\n"
1434 " show-user [USER...] Show properties of users or the manager\n"
1435 " enable-linger [USER...] Enable linger state of one or more users\n"
1436 " disable-linger [USER...] Disable linger state of one or more users\n"
1437 " terminate-user USER... Terminate all sessions of one or more users\n"
1438 " kill-user USER... Send signal to processes of a user\n\n"
1440 " list-seats List seats\n"
1441 " seat-status [NAME...] Show seat status\n"
1442 " show-seat [NAME...] Show properties of seats or the manager\n"
1443 " attach NAME DEVICE... Attach one or more devices to a seat\n"
1444 " flush-devices Flush all device associations\n"
1445 " terminate-seat NAME... Terminate all sessions on one or more seats\n\n"
1446 "System Commands:\n"
1447 " poweroff Turn off the machine\n"
1448 " reboot Reboot the machine\n"
1449 " suspend Suspend the machine to memory\n"
1450 " hibernate Suspend the machine to disk\n"
1451 " hybrid-sleep Suspend the machine to memory and disk\n"
1452 , program_invocation_short_name);
1457 static int parse_argv(int argc, char *argv[]) {
1460 ARG_VERSION = 0x100,
1464 ARG_NO_ASK_PASSWORD,
1467 static const struct option options[] = {
1468 { "help", no_argument, NULL, 'h' },
1469 { "version", no_argument, NULL, ARG_VERSION },
1470 { "property", required_argument, NULL, 'p' },
1471 { "all", no_argument, NULL, 'a' },
1472 { "full", no_argument, NULL, 'l' },
1473 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
1474 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
1475 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
1476 { "signal", required_argument, NULL, 's' },
1477 { "host", required_argument, NULL, 'H' },
1478 { "machine", required_argument, NULL, 'M' },
1479 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
1480 { "ignore-inhibitors", no_argument, NULL, 'i' },
1481 { "lines", required_argument, NULL, 'n' },
1482 { "output", required_argument, NULL, 'o' },
1491 while ((c = getopt_long(argc, argv, "hp:als:H:M:n:o:i", options, NULL)) >= 0)
1496 help(0, NULL, NULL);
1500 puts(PACKAGE_STRING);
1501 puts(SYSTEMD_FEATURES);
1505 r = strv_extend(&arg_property, optarg);
1509 /* If the user asked for a particular
1510 * property, show it to him, even if it is
1525 if (safe_atou(optarg, &arg_lines) < 0) {
1526 log_error("Failed to parse lines '%s'", optarg);
1533 arg_output = output_mode_from_string(optarg);
1537 if (arg_output < 0) {
1538 log_error("Unknown output '%s'.", optarg);
1544 arg_ignore_inhibitors = true;
1548 arg_no_pager = true;
1555 case ARG_NO_ASK_PASSWORD:
1556 arg_ask_password = false;
1560 arg_kill_who = optarg;
1564 arg_signal = signal_from_string_try_harder(optarg);
1565 if (arg_signal < 0) {
1566 log_error("Failed to parse signal string %s.", optarg);
1572 arg_transport = BUS_TRANSPORT_REMOTE;
1577 arg_transport = BUS_TRANSPORT_MACHINE;
1585 assert_not_reached("Unhandled option");
1591 static int loginctl_main(int argc, char *argv[], sd_bus *bus) {
1593 static const Verb verbs[] = {
1594 { "help", VERB_ANY, VERB_ANY, 0, help },
1595 { "list-sessions", VERB_ANY, 1, VERB_DEFAULT, list_sessions },
1596 { "session-status", VERB_ANY, VERB_ANY, 0, show_session },
1597 { "show-session", VERB_ANY, VERB_ANY, 0, show_session },
1598 { "activate", VERB_ANY, 2, 0, activate },
1599 { "lock-session", VERB_ANY, VERB_ANY, 0, activate },
1600 { "unlock-session", VERB_ANY, VERB_ANY, 0, activate },
1601 { "lock-sessions", VERB_ANY, 1, 0, lock_sessions },
1602 { "unlock-sessions", VERB_ANY, 1, 0, lock_sessions },
1603 { "terminate-session", 2, VERB_ANY, 0, activate },
1604 { "kill-session", 2, VERB_ANY, 0, kill_session },
1605 { "list-users", VERB_ANY, 1, 0, list_users },
1606 { "user-status", VERB_ANY, VERB_ANY, 0, show_user },
1607 { "show-user", VERB_ANY, VERB_ANY, 0, show_user },
1608 { "enable-linger", VERB_ANY, VERB_ANY, 0, enable_linger },
1609 { "disable-linger", VERB_ANY, VERB_ANY, 0, enable_linger },
1610 { "terminate-user", 2, VERB_ANY, 0, terminate_user },
1611 { "kill-user", 2, VERB_ANY, 0, kill_user },
1612 { "list-seats", VERB_ANY, 1, 0, list_seats },
1613 { "seat-status", VERB_ANY, VERB_ANY, 0, show_seat },
1614 { "show-seat", VERB_ANY, VERB_ANY, 0, show_seat },
1615 { "attach", 3, VERB_ANY, 0, attach },
1616 { "flush-devices", VERB_ANY, 1, 0, flush_devices },
1617 { "terminate-seat", 2, VERB_ANY, 0, terminate_seat },
1618 { "poweroff", VERB_ANY, 1, 0, poweroff },
1619 { "reboot", VERB_ANY, 1, 0, reboot },
1620 { "suspend", VERB_ANY, 1, 0, suspend },
1621 { "hibernate", VERB_ANY, 1, 0, hibernate },
1622 { "hybrid-sleep", VERB_ANY, 1, 0, hybrid_sleep },
1626 return dispatch_verb(argc, argv, verbs, bus);
1629 int main(int argc, char *argv[]) {
1630 _cleanup_bus_close_unref_ sd_bus *bus = NULL;
1633 setlocale(LC_ALL, "");
1634 log_parse_environment();
1637 r = parse_argv(argc, argv);
1641 r = bus_open_transport(arg_transport, arg_host, false, &bus);
1643 log_error_errno(r, "Failed to create bus connection: %m");
1647 sd_bus_set_allow_interactive_authorization(bus, arg_ask_password);
1649 r = loginctl_main(argc, argv, bus);
1653 polkit_agent_close();
1655 strv_free(arg_property);
1657 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;