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;
60 static unsigned arg_lines = 10;
61 static OutputMode arg_output = OUTPUT_SHORT;
64 static void pager_open_if_enabled(void) {
72 static void polkit_agent_open_if_enabled(void) {
74 /* Open the polkit agent as a child process if necessary */
76 if (!arg_ask_password)
79 if (arg_transport != BUS_TRANSPORT_LOCAL)
85 static OutputFlags get_output_flags(void) {
88 arg_all * OUTPUT_SHOW_ALL |
89 arg_full * OUTPUT_FULL_WIDTH |
90 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
91 on_tty() * OUTPUT_COLOR;
94 static int list_sessions(int argc, char *argv[], void *userdata) {
95 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
96 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
97 const char *id, *user, *seat, *object;
98 sd_bus *bus = userdata;
106 pager_open_if_enabled();
108 r = sd_bus_call_method(
110 "org.freedesktop.login1",
111 "/org/freedesktop/login1",
112 "org.freedesktop.login1.Manager",
117 log_error("Failed to list sessions: %s", bus_error_message(&error, r));
121 r = sd_bus_message_enter_container(reply, 'a', "(susso)");
123 return bus_log_parse_error(r);
126 printf("%10s %10s %-16s %-16s\n", "SESSION", "UID", "USER", "SEAT");
128 while ((r = sd_bus_message_read(reply, "(susso)", &id, &uid, &user, &seat, &object)) > 0) {
129 printf("%10s %10u %-16s %-16s\n", id, (unsigned) uid, user, seat);
133 return bus_log_parse_error(r);
136 printf("\n%u sessions listed.\n", k);
141 static int list_users(int argc, char *argv[], void *userdata) {
142 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
143 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
144 const char *user, *object;
145 sd_bus *bus = userdata;
153 pager_open_if_enabled();
155 r = sd_bus_call_method(
157 "org.freedesktop.login1",
158 "/org/freedesktop/login1",
159 "org.freedesktop.login1.Manager",
164 log_error("Failed to list users: %s", bus_error_message(&error, r));
168 r = sd_bus_message_enter_container(reply, 'a', "(uso)");
170 return bus_log_parse_error(r);
173 printf("%10s %-16s\n", "UID", "USER");
175 while ((r = sd_bus_message_read(reply, "(uso)", &uid, &user, &object)) > 0) {
176 printf("%10u %-16s\n", (unsigned) uid, user);
180 return bus_log_parse_error(r);
183 printf("\n%u users listed.\n", k);
188 static int list_seats(int argc, char *argv[], void *userdata) {
189 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
190 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
191 const char *seat, *object;
192 sd_bus *bus = userdata;
199 pager_open_if_enabled();
201 r = sd_bus_call_method(
203 "org.freedesktop.login1",
204 "/org/freedesktop/login1",
205 "org.freedesktop.login1.Manager",
210 log_error("Failed to list seats: %s", bus_error_message(&error, r));
214 r = sd_bus_message_enter_container(reply, 'a', "(so)");
216 return bus_log_parse_error(r);
219 printf("%-16s\n", "SEAT");
221 while ((r = sd_bus_message_read(reply, "(so)", &seat, &object)) > 0) {
222 printf("%-16s\n", seat);
226 return bus_log_parse_error(r);
229 printf("\n%u seats listed.\n", k);
234 static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit, pid_t leader) {
235 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
236 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
237 _cleanup_free_ char *path = NULL;
245 if (arg_transport != BUS_TRANSPORT_LOCAL)
248 path = unit_dbus_path_from_name(unit);
252 r = sd_bus_get_property(
254 "org.freedesktop.systemd1",
258 &error, &reply, "s");
262 r = sd_bus_message_read(reply, "s", &cgroup);
269 if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup, false) != 0 && leader <= 0)
278 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t ", c, false, &leader, leader > 0, get_output_flags());
282 typedef struct SessionStatusInfo {
286 struct dual_timestamp timestamp;
303 typedef struct UserStatusInfo {
306 struct dual_timestamp timestamp;
313 typedef struct SeatStatusInfo {
315 char *active_session;
319 static void session_status_info_clear(SessionStatusInfo *info) {
326 free(info->remote_host);
327 free(info->remote_user);
338 static void user_status_info_clear(UserStatusInfo *info) {
342 strv_free(info->sessions);
349 static void seat_status_info_clear(SeatStatusInfo *info) {
352 free(info->active_session);
353 strv_free(info->sessions);
358 static int prop_map_first_of_struct(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
359 const char *contents;
362 r = sd_bus_message_peek_type(m, NULL, &contents);
366 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, contents);
370 if (contents[0] == 's' || contents[0] == 'o') {
372 char **p = (char **) userdata;
374 r = sd_bus_message_read_basic(m, contents[0], &s);
384 r = sd_bus_message_read_basic(m, contents[0], userdata);
389 r = sd_bus_message_skip(m, contents+1);
393 r = sd_bus_message_exit_container(m);
400 static int prop_map_sessions_strv(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
407 r = sd_bus_message_enter_container(m, 'a', "(so)");
411 while ((r = sd_bus_message_read(m, "(so)", &name, NULL)) > 0) {
412 r = strv_extend(userdata, name);
419 return sd_bus_message_exit_container(m);
422 static int print_session_status_info(sd_bus *bus, const char *path, bool *new_line) {
424 static const struct bus_properties_map map[] = {
425 { "Id", "s", NULL, offsetof(SessionStatusInfo, id) },
426 { "Name", "s", NULL, offsetof(SessionStatusInfo, name) },
427 { "TTY", "s", NULL, offsetof(SessionStatusInfo, tty) },
428 { "Display", "s", NULL, offsetof(SessionStatusInfo, display) },
429 { "RemoteHost", "s", NULL, offsetof(SessionStatusInfo, remote_host) },
430 { "RemoteUser", "s", NULL, offsetof(SessionStatusInfo, remote_user) },
431 { "Service", "s", NULL, offsetof(SessionStatusInfo, service) },
432 { "Desktop", "s", NULL, offsetof(SessionStatusInfo, desktop) },
433 { "Type", "s", NULL, offsetof(SessionStatusInfo, type) },
434 { "Class", "s", NULL, offsetof(SessionStatusInfo, class) },
435 { "Scope", "s", NULL, offsetof(SessionStatusInfo, scope) },
436 { "State", "s", NULL, offsetof(SessionStatusInfo, state) },
437 { "VTNr", "u", NULL, offsetof(SessionStatusInfo, vtnr) },
438 { "Leader", "u", NULL, offsetof(SessionStatusInfo, leader) },
439 { "Remote", "b", NULL, offsetof(SessionStatusInfo, remote) },
440 { "Timestamp", "t", NULL, offsetof(SessionStatusInfo, timestamp.realtime) },
441 { "TimestampMonotonic", "t", NULL, offsetof(SessionStatusInfo, timestamp.monotonic) },
442 { "User", "(uo)", prop_map_first_of_struct, offsetof(SessionStatusInfo, uid) },
443 { "Seat", "(so)", prop_map_first_of_struct, offsetof(SessionStatusInfo, seat) },
447 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
448 char since2[FORMAT_TIMESTAMP_MAX], *s2;
449 _cleanup_(session_status_info_clear) SessionStatusInfo i = {};
452 r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i);
454 return log_error_errno(r, "Could not get properties: %m");
461 printf("%s - ", strna(i.id));
464 printf("%s (%u)\n", i.name, (unsigned) i.uid);
466 printf("%u\n", (unsigned) i.uid);
468 s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime);
469 s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime);
472 printf("\t Since: %s; %s\n", s2, s1);
474 printf("\t Since: %s\n", s2);
477 _cleanup_free_ char *t = NULL;
479 printf("\t Leader: %u", (unsigned) i.leader);
481 get_process_comm(i.leader, &t);
488 if (!isempty(i.seat)) {
489 printf("\t Seat: %s", i.seat);
492 printf("; vc%u", i.vtnr);
498 printf("\t TTY: %s\n", i.tty);
500 printf("\t Display: %s\n", i.display);
502 if (i.remote_host && i.remote_user)
503 printf("\t Remote: %s@%s\n", i.remote_user, i.remote_host);
504 else if (i.remote_host)
505 printf("\t Remote: %s\n", i.remote_host);
506 else if (i.remote_user)
507 printf("\t Remote: user %s\n", i.remote_user);
509 printf("\t Remote: Yes\n");
512 printf("\t Service: %s", i.service);
515 printf("; type %s", i.type);
518 printf("; class %s", i.class);
522 printf("\t Type: %s", i.type);
525 printf("; class %s", i.class);
529 printf("\t Class: %s\n", i.class);
531 if (!isempty(i.desktop))
532 printf("\t Desktop: %s\n", i.desktop);
535 printf("\t State: %s\n", i.state);
538 printf("\t Unit: %s\n", i.scope);
539 show_unit_cgroup(bus, "org.freedesktop.systemd1.Scope", i.scope, i.leader);
541 if (arg_transport == BUS_TRANSPORT_LOCAL) {
543 show_journal_by_unit(
548 i.timestamp.monotonic,
551 get_output_flags() | OUTPUT_BEGIN_NEWLINE,
552 SD_JOURNAL_LOCAL_ONLY,
563 static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line) {
565 static const struct bus_properties_map map[] = {
566 { "Name", "s", NULL, offsetof(UserStatusInfo, name) },
567 { "Slice", "s", NULL, offsetof(UserStatusInfo, slice) },
568 { "State", "s", NULL, offsetof(UserStatusInfo, state) },
569 { "UID", "u", NULL, offsetof(UserStatusInfo, uid) },
570 { "Timestamp", "t", NULL, offsetof(UserStatusInfo, timestamp.realtime) },
571 { "TimestampMonotonic", "t", NULL, offsetof(UserStatusInfo, timestamp.monotonic) },
572 { "Display", "(so)", prop_map_first_of_struct, offsetof(UserStatusInfo, display) },
573 { "Sessions", "a(so)", prop_map_sessions_strv, offsetof(UserStatusInfo, sessions) },
577 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
578 char since2[FORMAT_TIMESTAMP_MAX], *s2;
579 _cleanup_(user_status_info_clear) UserStatusInfo i = {};
582 r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i);
584 return log_error_errno(r, "Could not get properties: %m");
592 printf("%s (%u)\n", i.name, (unsigned) i.uid);
594 printf("%u\n", (unsigned) i.uid);
596 s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime);
597 s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime);
600 printf("\t Since: %s; %s\n", s2, s1);
602 printf("\t Since: %s\n", s2);
604 if (!isempty(i.state))
605 printf("\t State: %s\n", i.state);
607 if (!strv_isempty(i.sessions)) {
609 printf("\tSessions:");
611 STRV_FOREACH(l, i.sessions) {
612 if (streq_ptr(*l, i.display))
622 printf("\t Unit: %s\n", i.slice);
623 show_unit_cgroup(bus, "org.freedesktop.systemd1.Slice", i.slice, 0);
625 show_journal_by_unit(
630 i.timestamp.monotonic,
633 get_output_flags() | OUTPUT_BEGIN_NEWLINE,
634 SD_JOURNAL_LOCAL_ONLY,
644 static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line) {
646 static const struct bus_properties_map map[] = {
647 { "Id", "s", NULL, offsetof(SeatStatusInfo, id) },
648 { "ActiveSession", "(so)", prop_map_first_of_struct, offsetof(SeatStatusInfo, active_session) },
649 { "Sessions", "a(so)", prop_map_sessions_strv, offsetof(SeatStatusInfo, sessions) },
653 _cleanup_(seat_status_info_clear) SeatStatusInfo i = {};
656 r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i);
658 return log_error_errno(r, "Could not get properties: %m");
665 printf("%s\n", strna(i.id));
667 if (!strv_isempty(i.sessions)) {
669 printf("\tSessions:");
671 STRV_FOREACH(l, i.sessions) {
672 if (streq_ptr(*l, i.active_session))
681 if (arg_transport == BUS_TRANSPORT_LOCAL) {
690 printf("\t Devices:\n");
692 show_sysfs(i.id, "\t\t ", c);
698 static int show_properties(sd_bus *bus, const char *path, bool *new_line) {
706 r = bus_print_all_properties(bus, "org.freedesktop.login1", path, arg_property, arg_all);
708 log_error_errno(r, "Could not get properties: %m");
713 static int show_session(int argc, char *argv[], void *userdata) {
714 bool properties, new_line = false;
715 sd_bus *bus = userdata;
721 properties = !strstr(argv[0], "status");
723 pager_open_if_enabled();
726 /* If not argument is specified inspect the manager
729 return show_properties(bus, "/org/freedesktop/login1", &new_line);
731 /* And in the pretty case, show data of the calling session */
732 return print_session_status_info(bus, "/org/freedesktop/login1/session/self", &new_line);
735 for (i = 1; i < argc; i++) {
736 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
737 _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
738 const char *path = NULL;
740 r = sd_bus_call_method(
742 "org.freedesktop.login1",
743 "/org/freedesktop/login1",
744 "org.freedesktop.login1.Manager",
749 log_error("Failed to get session: %s", bus_error_message(&error, r));
753 r = sd_bus_message_read(reply, "o", &path);
755 return bus_log_parse_error(r);
758 r = show_properties(bus, path, &new_line);
760 r = print_session_status_info(bus, path, &new_line);
769 static int show_user(int argc, char *argv[], void *userdata) {
770 bool properties, new_line = false;
771 sd_bus *bus = userdata;
777 properties = !strstr(argv[0], "status");
779 pager_open_if_enabled();
782 /* If not argument is specified inspect the manager
785 return show_properties(bus, "/org/freedesktop/login1", &new_line);
787 return print_user_status_info(bus, "/org/freedesktop/login1/user/self", &new_line);
790 for (i = 1; i < argc; i++) {
791 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
792 _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
793 const char *path = NULL;
796 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
798 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
800 r = sd_bus_call_method(
802 "org.freedesktop.login1",
803 "/org/freedesktop/login1",
804 "org.freedesktop.login1.Manager",
807 "u", (uint32_t) uid);
809 log_error("Failed to get user: %s", bus_error_message(&error, r));
813 r = sd_bus_message_read(reply, "o", &path);
815 return bus_log_parse_error(r);
818 r = show_properties(bus, path, &new_line);
820 r = print_user_status_info(bus, path, &new_line);
829 static int show_seat(int argc, char *argv[], void *userdata) {
830 bool properties, new_line = false;
831 sd_bus *bus = userdata;
837 properties = !strstr(argv[0], "status");
839 pager_open_if_enabled();
842 /* If not argument is specified inspect the manager
845 return show_properties(bus, "/org/freedesktop/login1", &new_line);
847 return print_seat_status_info(bus, "/org/freedesktop/login1/seat/self", &new_line);
850 for (i = 1; i < argc; i++) {
851 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
852 _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
853 const char *path = NULL;
855 r = sd_bus_call_method(
857 "org.freedesktop.login1",
858 "/org/freedesktop/login1",
859 "org.freedesktop.login1.Manager",
864 log_error("Failed to get seat: %s", bus_error_message(&error, r));
868 r = sd_bus_message_read(reply, "o", &path);
870 return bus_log_parse_error(r);
873 r = show_properties(bus, path, &new_line);
875 r = print_seat_status_info(bus, path, &new_line);
884 static int activate(int argc, char *argv[], void *userdata) {
885 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
886 sd_bus *bus = userdata;
893 polkit_agent_open_if_enabled();
896 /* No argument? Let's convert this into the empty
897 * session name, which the calls will then resolve to
898 * the caller's session. */
900 short_argv[0] = argv[0];
901 short_argv[1] = (char*) "";
902 short_argv[2] = NULL;
908 for (i = 1; i < argc; i++) {
910 r = sd_bus_call_method(
912 "org.freedesktop.login1",
913 "/org/freedesktop/login1",
914 "org.freedesktop.login1.Manager",
915 streq(argv[0], "lock-session") ? "LockSession" :
916 streq(argv[0], "unlock-session") ? "UnlockSession" :
917 streq(argv[0], "terminate-session") ? "TerminateSession" :
922 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
930 static int kill_session(int argc, char *argv[], void *userdata) {
931 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
932 sd_bus *bus = userdata;
938 polkit_agent_open_if_enabled();
941 arg_kill_who = "all";
943 for (i = 1; i < argc; i++) {
945 r = sd_bus_call_method(
947 "org.freedesktop.login1",
948 "/org/freedesktop/login1",
949 "org.freedesktop.login1.Manager",
952 "ssi", argv[i], arg_kill_who, arg_signal);
954 log_error("Could not kill session: %s", bus_error_message(&error, -r));
962 static int enable_linger(int argc, char *argv[], void *userdata) {
963 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
964 sd_bus *bus = userdata;
972 polkit_agent_open_if_enabled();
974 b = streq(argv[0], "enable-linger");
977 short_argv[0] = argv[0];
978 short_argv[1] = (char*) "";
979 short_argv[2] = NULL;
984 for (i = 1; i < argc; i++) {
987 if (isempty(argv[i]))
990 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
992 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
995 r = sd_bus_call_method(
997 "org.freedesktop.login1",
998 "/org/freedesktop/login1",
999 "org.freedesktop.login1.Manager",
1002 "ubb", (uint32_t) uid, b, true);
1004 log_error("Could not enable linger: %s", bus_error_message(&error, -r));
1012 static int terminate_user(int argc, char *argv[], void *userdata) {
1013 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1014 sd_bus *bus = userdata;
1020 polkit_agent_open_if_enabled();
1022 for (i = 1; i < argc; i++) {
1025 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
1027 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
1029 r = sd_bus_call_method(
1031 "org.freedesktop.login1",
1032 "/org/freedesktop/login1",
1033 "org.freedesktop.login1.Manager",
1036 "u", (uint32_t) uid);
1038 log_error("Could not terminate user: %s", bus_error_message(&error, -r));
1046 static int kill_user(int argc, char *argv[], void *userdata) {
1047 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1048 sd_bus *bus = userdata;
1054 polkit_agent_open_if_enabled();
1057 arg_kill_who = "all";
1059 for (i = 1; i < argc; i++) {
1062 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
1064 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
1066 r = sd_bus_call_method(
1068 "org.freedesktop.login1",
1069 "/org/freedesktop/login1",
1070 "org.freedesktop.login1.Manager",
1073 "ui", (uint32_t) uid, arg_signal);
1075 log_error("Could not kill user: %s", bus_error_message(&error, -r));
1083 static int attach(int argc, char *argv[], void *userdata) {
1084 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1085 sd_bus *bus = userdata;
1091 polkit_agent_open_if_enabled();
1093 for (i = 2; i < argc; i++) {
1095 r = sd_bus_call_method(
1097 "org.freedesktop.login1",
1098 "/org/freedesktop/login1",
1099 "org.freedesktop.login1.Manager",
1102 "ssb", argv[1], argv[i], true);
1105 log_error("Could not attach device: %s", bus_error_message(&error, -r));
1113 static int flush_devices(int argc, char *argv[], void *userdata) {
1114 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1115 sd_bus *bus = userdata;
1121 polkit_agent_open_if_enabled();
1123 r = sd_bus_call_method(
1125 "org.freedesktop.login1",
1126 "/org/freedesktop/login1",
1127 "org.freedesktop.login1.Manager",
1132 log_error("Could not flush devices: %s", bus_error_message(&error, -r));
1137 static int lock_sessions(int argc, char *argv[], void *userdata) {
1138 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1139 sd_bus *bus = userdata;
1145 polkit_agent_open_if_enabled();
1147 r = sd_bus_call_method(
1149 "org.freedesktop.login1",
1150 "/org/freedesktop/login1",
1151 "org.freedesktop.login1.Manager",
1152 streq(argv[0], "lock-sessions") ? "LockSessions" : "UnlockSessions",
1156 log_error("Could not lock sessions: %s", bus_error_message(&error, -r));
1161 static int terminate_seat(int argc, char *argv[], void *userdata) {
1162 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1163 sd_bus *bus = userdata;
1169 polkit_agent_open_if_enabled();
1171 for (i = 1; i < argc; i++) {
1173 r = sd_bus_call_method(
1175 "org.freedesktop.login1",
1176 "/org/freedesktop/login1",
1177 "org.freedesktop.login1.Manager",
1182 log_error("Could not terminate seat: %s", bus_error_message(&error, -r));
1190 static int check_inhibitors(sd_bus *bus, const char *verb, const char *inhibit_what) {
1191 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1192 _cleanup_strv_free_ char **sessions = NULL;
1193 const char *what, *who, *why, *mode;
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 " -H --host=[USER@]HOST Operate on remote host\n"
1439 " -M --machine=CONTAINER Operate on local container\n"
1440 " -p --property=NAME Show only properties by this name\n"
1441 " -a --all Show all properties, including empty ones\n"
1442 " -l --full Do not ellipsize output\n"
1443 " --kill-who=WHO Who to send signal to\n"
1444 " -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"
1450 "Session Commands:\n"
1451 " list-sessions List sessions\n"
1452 " session-status [ID...] Show session status\n"
1453 " show-session [ID...] Show properties of sessions or the manager\n"
1454 " activate [ID] Activate a session\n"
1455 " lock-session [ID...] Screen lock one or more sessions\n"
1456 " unlock-session [ID...] Screen unlock one or more sessions\n"
1457 " lock-sessions Screen lock all current sessions\n"
1458 " unlock-sessions Screen unlock all current sessions\n"
1459 " terminate-session ID... Terminate one or more sessions\n"
1460 " kill-session ID... Send signal to processes of a session\n\n"
1462 " list-users List users\n"
1463 " user-status [USER...] Show user status\n"
1464 " show-user [USER...] Show properties of users or the manager\n"
1465 " enable-linger [USER...] Enable linger state of one or more users\n"
1466 " disable-linger [USER...] Disable linger state of one or more users\n"
1467 " terminate-user USER... Terminate all sessions of one or more users\n"
1468 " kill-user USER... Send signal to processes of a user\n\n"
1470 " list-seats List seats\n"
1471 " seat-status [NAME...] Show seat status\n"
1472 " show-seat [NAME...] Show properties of seats or the manager\n"
1473 " attach NAME DEVICE... Attach one or more devices to a seat\n"
1474 " flush-devices Flush all device associations\n"
1475 " terminate-seat NAME... Terminate all sessions on one or more seats\n"
1476 "System Commands:\n"
1477 " poweroff Turn off the machine\n"
1478 " reboot Reboot the machine\n"
1479 " suspend Suspend the machine to memory\n"
1480 " hibernate Suspend the machine to disk\n"
1481 " hybrid-sleep Suspend the machine to memory and disk\n"
1482 , program_invocation_short_name);
1487 static int parse_argv(int argc, char *argv[]) {
1490 ARG_VERSION = 0x100,
1494 ARG_NO_ASK_PASSWORD,
1497 static const struct option options[] = {
1498 { "help", no_argument, NULL, 'h' },
1499 { "version", no_argument, NULL, ARG_VERSION },
1500 { "property", required_argument, NULL, 'p' },
1501 { "all", no_argument, NULL, 'a' },
1502 { "full", no_argument, NULL, 'l' },
1503 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
1504 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
1505 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
1506 { "signal", required_argument, NULL, 's' },
1507 { "host", required_argument, NULL, 'H' },
1508 { "machine", required_argument, NULL, 'M' },
1509 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
1511 { "lines", required_argument, NULL, 'n' },
1512 { "output", required_argument, NULL, 'o' },
1522 while ((c = getopt_long(argc, argv, "hp:als:H:M:", options, NULL)) >= 0)
1527 help(0, NULL, NULL);
1531 puts(PACKAGE_STRING);
1532 puts(SYSTEMD_FEATURES);
1536 r = strv_extend(&arg_property, optarg);
1540 /* If the user asked for a particular
1541 * property, show it to him, even if it is
1556 if (safe_atou(optarg, &arg_lines) < 0) {
1557 log_error("Failed to parse lines '%s'", optarg);
1563 arg_output = output_mode_from_string(optarg);
1564 if (arg_output < 0) {
1565 log_error("Unknown output '%s'.", optarg);
1571 arg_no_pager = true;
1578 case ARG_NO_ASK_PASSWORD:
1579 arg_ask_password = false;
1583 arg_kill_who = optarg;
1587 arg_signal = signal_from_string_try_harder(optarg);
1588 if (arg_signal < 0) {
1589 log_error("Failed to parse signal string %s.", optarg);
1595 arg_transport = BUS_TRANSPORT_REMOTE;
1600 arg_transport = BUS_TRANSPORT_MACHINE;
1608 assert_not_reached("Unhandled option");
1614 static int loginctl_main(int argc, char *argv[], sd_bus *bus) {
1616 static const Verb verbs[] = {
1617 { "help", VERB_ANY, VERB_ANY, 0, help },
1618 { "list-sessions", VERB_ANY, 1, VERB_DEFAULT, list_sessions },
1619 { "session-status", VERB_ANY, VERB_ANY, 0, show_session },
1620 { "show-session", VERB_ANY, VERB_ANY, 0, show_session },
1621 { "activate", VERB_ANY, 2, 0, activate },
1622 { "lock-session", VERB_ANY, VERB_ANY, 0, activate },
1623 { "unlock-session", VERB_ANY, VERB_ANY, 0, activate },
1624 { "lock-sessions", VERB_ANY, 1, 0, lock_sessions },
1625 { "unlock-sessions", VERB_ANY, 1, 0, lock_sessions },
1626 { "terminate-session", 2, VERB_ANY, 0, activate },
1627 { "kill-session", 2, VERB_ANY, 0, kill_session },
1628 { "list-users", VERB_ANY, 1, 0, list_users },
1629 { "user-status", VERB_ANY, VERB_ANY, 0, show_user },
1630 { "show-user", VERB_ANY, VERB_ANY, 0, show_user },
1631 { "enable-linger", VERB_ANY, VERB_ANY, 0, enable_linger },
1632 { "disable-linger", VERB_ANY, VERB_ANY, 0, enable_linger },
1633 { "terminate-user", 2, VERB_ANY, 0, terminate_user },
1634 { "kill-user", 2, VERB_ANY, 0, kill_user },
1635 { "list-seats", VERB_ANY, 1, 0, list_seats },
1636 { "seat-status", VERB_ANY, VERB_ANY, 0, show_seat },
1637 { "show-seat", VERB_ANY, VERB_ANY, 0, show_seat },
1638 { "attach", 3, VERB_ANY, 0, attach },
1639 { "flush-devices", VERB_ANY, 1, 0, flush_devices },
1640 { "terminate-seat", 2, VERB_ANY, 0, terminate_seat },
1641 { "poweroff", VERB_ANY, 1, 0, poweroff },
1642 { "reboot", VERB_ANY, 1, 0, reboot },
1643 { "suspend", VERB_ANY, 1, 0, suspend },
1644 { "hibernate", VERB_ANY, 1, 0, hibernate },
1645 { "hybrid-sleep", VERB_ANY, 1, 0, hybrid_sleep },
1649 return dispatch_verb(argc, argv, verbs, bus);
1652 int main(int argc, char *argv[]) {
1653 _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
1656 setlocale(LC_ALL, "");
1657 log_parse_environment();
1660 r = parse_argv(argc, argv);
1664 r = bus_open_transport(arg_transport, arg_host, false, &bus);
1666 log_error_errno(r, "Failed to create bus connection: %m");
1670 sd_bus_set_allow_interactive_authorization(bus, arg_ask_password);
1672 r = loginctl_main(argc, argv, bus);
1676 polkit_agent_close();
1678 strv_free(arg_property);
1680 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;