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"
47 static char **arg_property = NULL;
48 static bool arg_all = false;
49 static bool arg_full = false;
50 static bool arg_no_pager = false;
51 static bool arg_legend = true;
52 static const char *arg_kill_who = NULL;
53 static int arg_signal = SIGTERM;
54 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
55 static char *arg_host = NULL;
56 static bool arg_ask_password = true;
57 static bool arg_ignore_inhibitors = false;
58 static unsigned arg_lines = 10;
59 static OutputMode arg_output = OUTPUT_SHORT;
61 static void pager_open_if_enabled(void) {
69 static void polkit_agent_open_if_enabled(void) {
71 /* Open the polkit agent as a child process if necessary */
73 if (!arg_ask_password)
76 if (arg_transport != BUS_TRANSPORT_LOCAL)
82 static OutputFlags get_output_flags(void) {
85 arg_all * OUTPUT_SHOW_ALL |
86 arg_full * OUTPUT_FULL_WIDTH |
87 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
88 on_tty() * OUTPUT_COLOR;
91 static int list_sessions(int argc, char *argv[], void *userdata) {
92 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
93 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
94 const char *id, *user, *seat, *object;
95 sd_bus *bus = userdata;
103 pager_open_if_enabled();
105 r = sd_bus_call_method(
107 "org.freedesktop.login1",
108 "/org/freedesktop/login1",
109 "org.freedesktop.login1.Manager",
114 log_error("Failed to list sessions: %s", bus_error_message(&error, r));
118 r = sd_bus_message_enter_container(reply, 'a', "(susso)");
120 return bus_log_parse_error(r);
123 printf("%10s %10s %-16s %-16s\n", "SESSION", "UID", "USER", "SEAT");
125 while ((r = sd_bus_message_read(reply, "(susso)", &id, &uid, &user, &seat, &object)) > 0) {
126 printf("%10s %10u %-16s %-16s\n", id, (unsigned) uid, user, seat);
130 return bus_log_parse_error(r);
133 printf("\n%u sessions listed.\n", k);
138 static int list_users(int argc, char *argv[], void *userdata) {
139 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
140 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
141 const char *user, *object;
142 sd_bus *bus = userdata;
150 pager_open_if_enabled();
152 r = sd_bus_call_method(
154 "org.freedesktop.login1",
155 "/org/freedesktop/login1",
156 "org.freedesktop.login1.Manager",
161 log_error("Failed to list users: %s", bus_error_message(&error, r));
165 r = sd_bus_message_enter_container(reply, 'a', "(uso)");
167 return bus_log_parse_error(r);
170 printf("%10s %-16s\n", "UID", "USER");
172 while ((r = sd_bus_message_read(reply, "(uso)", &uid, &user, &object)) > 0) {
173 printf("%10u %-16s\n", (unsigned) uid, user);
177 return bus_log_parse_error(r);
180 printf("\n%u users listed.\n", k);
185 static int list_seats(int argc, char *argv[], void *userdata) {
186 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
187 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
188 const char *seat, *object;
189 sd_bus *bus = userdata;
196 pager_open_if_enabled();
198 r = sd_bus_call_method(
200 "org.freedesktop.login1",
201 "/org/freedesktop/login1",
202 "org.freedesktop.login1.Manager",
207 log_error("Failed to list seats: %s", bus_error_message(&error, r));
211 r = sd_bus_message_enter_container(reply, 'a', "(so)");
213 return bus_log_parse_error(r);
216 printf("%-16s\n", "SEAT");
218 while ((r = sd_bus_message_read(reply, "(so)", &seat, &object)) > 0) {
219 printf("%-16s\n", seat);
223 return bus_log_parse_error(r);
226 printf("\n%u seats listed.\n", k);
231 static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit, pid_t leader) {
232 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
233 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
234 _cleanup_free_ char *path = NULL;
242 if (arg_transport != BUS_TRANSPORT_LOCAL)
245 path = unit_dbus_path_from_name(unit);
249 r = sd_bus_get_property(
251 "org.freedesktop.systemd1",
255 &error, &reply, "s");
259 r = sd_bus_message_read(reply, "s", &cgroup);
266 if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup, false) != 0 && leader <= 0)
275 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t ", c, false, &leader, leader > 0, get_output_flags());
279 typedef struct SessionStatusInfo {
283 struct dual_timestamp timestamp;
289 const char *remote_host;
290 const char *remote_user;
300 typedef struct UserStatusInfo {
303 struct dual_timestamp timestamp;
310 typedef struct SeatStatusInfo {
312 const char *active_session;
316 static int prop_map_first_of_struct(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
317 const char *contents;
320 r = sd_bus_message_peek_type(m, NULL, &contents);
324 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, contents);
328 if (contents[0] == 's' || contents[0] == 'o') {
330 char **p = (char **) userdata;
332 r = sd_bus_message_read_basic(m, contents[0], &s);
342 r = sd_bus_message_read_basic(m, contents[0], userdata);
347 r = sd_bus_message_skip(m, contents+1);
351 r = sd_bus_message_exit_container(m);
358 static int prop_map_sessions_strv(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
365 r = sd_bus_message_enter_container(m, 'a', "(so)");
369 while ((r = sd_bus_message_read(m, "(so)", &name, NULL)) > 0) {
370 r = strv_extend(userdata, name);
377 return sd_bus_message_exit_container(m);
380 static int print_session_status_info(sd_bus *bus, const char *path, bool *new_line) {
382 static const struct bus_properties_map map[] = {
383 { "Id", "s", NULL, offsetof(SessionStatusInfo, id) },
384 { "Name", "s", NULL, offsetof(SessionStatusInfo, name) },
385 { "TTY", "s", NULL, offsetof(SessionStatusInfo, tty) },
386 { "Display", "s", NULL, offsetof(SessionStatusInfo, display) },
387 { "RemoteHost", "s", NULL, offsetof(SessionStatusInfo, remote_host) },
388 { "RemoteUser", "s", NULL, offsetof(SessionStatusInfo, remote_user) },
389 { "Service", "s", NULL, offsetof(SessionStatusInfo, service) },
390 { "Desktop", "s", NULL, offsetof(SessionStatusInfo, desktop) },
391 { "Type", "s", NULL, offsetof(SessionStatusInfo, type) },
392 { "Class", "s", NULL, offsetof(SessionStatusInfo, class) },
393 { "Scope", "s", NULL, offsetof(SessionStatusInfo, scope) },
394 { "State", "s", NULL, offsetof(SessionStatusInfo, state) },
395 { "VTNr", "u", NULL, offsetof(SessionStatusInfo, vtnr) },
396 { "Leader", "u", NULL, offsetof(SessionStatusInfo, leader) },
397 { "Remote", "b", NULL, offsetof(SessionStatusInfo, remote) },
398 { "Timestamp", "t", NULL, offsetof(SessionStatusInfo, timestamp.realtime) },
399 { "TimestampMonotonic", "t", NULL, offsetof(SessionStatusInfo, timestamp.monotonic) },
400 { "User", "(uo)", prop_map_first_of_struct, offsetof(SessionStatusInfo, uid) },
401 { "Seat", "(so)", prop_map_first_of_struct, offsetof(SessionStatusInfo, seat) },
405 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
406 char since2[FORMAT_TIMESTAMP_MAX], *s2;
407 SessionStatusInfo i = {};
410 r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i);
412 return log_error_errno(r, "Could not get properties: %m");
419 printf("%s - ", strna(i.id));
422 printf("%s (%u)\n", i.name, (unsigned) i.uid);
424 printf("%u\n", (unsigned) i.uid);
426 s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime);
427 s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime);
430 printf("\t Since: %s; %s\n", s2, s1);
432 printf("\t Since: %s\n", s2);
435 _cleanup_free_ char *t = NULL;
437 printf("\t Leader: %u", (unsigned) i.leader);
439 get_process_comm(i.leader, &t);
446 if (!isempty(i.seat)) {
447 printf("\t Seat: %s", i.seat);
450 printf("; vc%u", i.vtnr);
456 printf("\t TTY: %s\n", i.tty);
458 printf("\t Display: %s\n", i.display);
460 if (i.remote_host && i.remote_user)
461 printf("\t Remote: %s@%s\n", i.remote_user, i.remote_host);
462 else if (i.remote_host)
463 printf("\t Remote: %s\n", i.remote_host);
464 else if (i.remote_user)
465 printf("\t Remote: user %s\n", i.remote_user);
467 printf("\t Remote: Yes\n");
470 printf("\t Service: %s", i.service);
473 printf("; type %s", i.type);
476 printf("; class %s", i.class);
480 printf("\t Type: %s", i.type);
483 printf("; class %s", i.class);
487 printf("\t Class: %s\n", i.class);
489 if (!isempty(i.desktop))
490 printf("\t Desktop: %s\n", i.desktop);
493 printf("\t State: %s\n", i.state);
496 printf("\t Unit: %s\n", i.scope);
497 show_unit_cgroup(bus, "org.freedesktop.systemd1.Scope", i.scope, i.leader);
499 if (arg_transport == BUS_TRANSPORT_LOCAL) {
501 show_journal_by_unit(
506 i.timestamp.monotonic,
509 get_output_flags() | OUTPUT_BEGIN_NEWLINE,
510 SD_JOURNAL_LOCAL_ONLY,
520 static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line) {
522 static const struct bus_properties_map map[] = {
523 { "Name", "s", NULL, offsetof(UserStatusInfo, name) },
524 { "Slice", "s", NULL, offsetof(UserStatusInfo, slice) },
525 { "State", "s", NULL, offsetof(UserStatusInfo, state) },
526 { "UID", "u", NULL, offsetof(UserStatusInfo, uid) },
527 { "Timestamp", "t", NULL, offsetof(UserStatusInfo, timestamp.realtime) },
528 { "TimestampMonotonic", "t", NULL, offsetof(UserStatusInfo, timestamp.monotonic) },
529 { "Display", "(so)", prop_map_first_of_struct, offsetof(UserStatusInfo, display) },
530 { "Sessions", "a(so)", prop_map_sessions_strv, offsetof(UserStatusInfo, sessions) },
534 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
535 char since2[FORMAT_TIMESTAMP_MAX], *s2;
536 UserStatusInfo i = {};
539 r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i);
541 log_error_errno(r, "Could not get properties: %m");
551 printf("%s (%u)\n", i.name, (unsigned) i.uid);
553 printf("%u\n", (unsigned) i.uid);
555 s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime);
556 s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime);
559 printf("\t Since: %s; %s\n", s2, s1);
561 printf("\t Since: %s\n", s2);
563 if (!isempty(i.state))
564 printf("\t State: %s\n", i.state);
566 if (!strv_isempty(i.sessions)) {
568 printf("\tSessions:");
570 STRV_FOREACH(l, i.sessions) {
571 if (streq_ptr(*l, i.display))
581 printf("\t Unit: %s\n", i.slice);
582 show_unit_cgroup(bus, "org.freedesktop.systemd1.Slice", i.slice, 0);
584 show_journal_by_unit(
589 i.timestamp.monotonic,
592 get_output_flags() | OUTPUT_BEGIN_NEWLINE,
593 SD_JOURNAL_LOCAL_ONLY,
600 strv_free(i.sessions);
605 static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line) {
607 static const struct bus_properties_map map[] = {
608 { "Id", "s", NULL, offsetof(SeatStatusInfo, id) },
609 { "ActiveSession", "(so)", prop_map_first_of_struct, offsetof(SeatStatusInfo, active_session) },
610 { "Sessions", "a(so)", prop_map_sessions_strv, offsetof(SeatStatusInfo, sessions) },
614 SeatStatusInfo i = {};
617 r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i);
619 log_error_errno(r, "Could not get properties: %m");
628 printf("%s\n", strna(i.id));
630 if (!strv_isempty(i.sessions)) {
632 printf("\tSessions:");
634 STRV_FOREACH(l, i.sessions) {
635 if (streq_ptr(*l, i.active_session))
644 if (arg_transport == BUS_TRANSPORT_LOCAL) {
653 printf("\t Devices:\n");
655 show_sysfs(i.id, "\t\t ", c);
659 strv_free(i.sessions);
664 static int show_properties(sd_bus *bus, const char *path, bool *new_line) {
672 r = bus_print_all_properties(bus, "org.freedesktop.login1", path, arg_property, arg_all);
674 log_error_errno(r, "Could not get properties: %m");
679 static int show_session(int argc, char *argv[], void *userdata) {
680 bool properties, new_line = false;
681 sd_bus *bus = userdata;
687 properties = !strstr(argv[0], "status");
689 pager_open_if_enabled();
692 /* If not argument is specified inspect the manager
695 return show_properties(bus, "/org/freedesktop/login1", &new_line);
697 /* And in the pretty case, show data of the calling session */
698 return print_session_status_info(bus, "/org/freedesktop/login1/session/self", &new_line);
701 for (i = 1; i < argc; i++) {
702 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
703 _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
704 const char *path = NULL;
706 r = sd_bus_call_method(
708 "org.freedesktop.login1",
709 "/org/freedesktop/login1",
710 "org.freedesktop.login1.Manager",
715 log_error("Failed to get session: %s", bus_error_message(&error, r));
719 r = sd_bus_message_read(reply, "o", &path);
721 return bus_log_parse_error(r);
724 r = show_properties(bus, path, &new_line);
726 r = print_session_status_info(bus, path, &new_line);
735 static int show_user(int argc, char *argv[], void *userdata) {
736 bool properties, new_line = false;
737 sd_bus *bus = userdata;
743 properties = !strstr(argv[0], "status");
745 pager_open_if_enabled();
748 /* If not argument is specified inspect the manager
751 return show_properties(bus, "/org/freedesktop/login1", &new_line);
753 return print_user_status_info(bus, "/org/freedesktop/login1/user/self", &new_line);
756 for (i = 1; i < argc; i++) {
757 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
758 _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
759 const char *path = NULL;
762 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
764 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
766 r = sd_bus_call_method(
768 "org.freedesktop.login1",
769 "/org/freedesktop/login1",
770 "org.freedesktop.login1.Manager",
773 "u", (uint32_t) uid);
775 log_error("Failed to get user: %s", bus_error_message(&error, r));
779 r = sd_bus_message_read(reply, "o", &path);
781 return bus_log_parse_error(r);
784 r = show_properties(bus, path, &new_line);
786 r = print_user_status_info(bus, path, &new_line);
795 static int show_seat(int argc, char *argv[], void *userdata) {
796 bool properties, new_line = false;
797 sd_bus *bus = userdata;
803 properties = !strstr(argv[0], "status");
805 pager_open_if_enabled();
808 /* If not argument is specified inspect the manager
811 return show_properties(bus, "/org/freedesktop/login1", &new_line);
813 return print_seat_status_info(bus, "/org/freedesktop/login1/seat/self", &new_line);
816 for (i = 1; i < argc; i++) {
817 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
818 _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
819 const char *path = NULL;
821 r = sd_bus_call_method(
823 "org.freedesktop.login1",
824 "/org/freedesktop/login1",
825 "org.freedesktop.login1.Manager",
830 log_error("Failed to get seat: %s", bus_error_message(&error, r));
834 r = sd_bus_message_read(reply, "o", &path);
836 return bus_log_parse_error(r);
839 r = show_properties(bus, path, &new_line);
841 r = print_seat_status_info(bus, path, &new_line);
850 static int activate(int argc, char *argv[], void *userdata) {
851 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
852 sd_bus *bus = userdata;
859 polkit_agent_open_if_enabled();
862 /* No argument? Let's convert this into the empty
863 * session name, which the calls will then resolve to
864 * the caller's session. */
866 short_argv[0] = argv[0];
867 short_argv[1] = (char*) "";
868 short_argv[2] = NULL;
874 for (i = 1; i < argc; i++) {
876 r = sd_bus_call_method(
878 "org.freedesktop.login1",
879 "/org/freedesktop/login1",
880 "org.freedesktop.login1.Manager",
881 streq(argv[0], "lock-session") ? "LockSession" :
882 streq(argv[0], "unlock-session") ? "UnlockSession" :
883 streq(argv[0], "terminate-session") ? "TerminateSession" :
888 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
896 static int kill_session(int argc, char *argv[], void *userdata) {
897 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
898 sd_bus *bus = userdata;
904 polkit_agent_open_if_enabled();
907 arg_kill_who = "all";
909 for (i = 1; i < argc; i++) {
911 r = sd_bus_call_method(
913 "org.freedesktop.login1",
914 "/org/freedesktop/login1",
915 "org.freedesktop.login1.Manager",
918 "ssi", argv[i], arg_kill_who, arg_signal);
920 log_error("Could not kill session: %s", bus_error_message(&error, -r));
928 static int enable_linger(int argc, char *argv[], void *userdata) {
929 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
930 sd_bus *bus = userdata;
938 polkit_agent_open_if_enabled();
940 b = streq(argv[0], "enable-linger");
943 short_argv[0] = argv[0];
944 short_argv[1] = (char*) "";
945 short_argv[2] = NULL;
950 for (i = 1; i < argc; i++) {
953 if (isempty(argv[i]))
956 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
958 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
961 r = sd_bus_call_method(
963 "org.freedesktop.login1",
964 "/org/freedesktop/login1",
965 "org.freedesktop.login1.Manager",
968 "ubb", (uint32_t) uid, b, true);
970 log_error("Could not enable linger: %s", bus_error_message(&error, -r));
978 static int terminate_user(int argc, char *argv[], void *userdata) {
979 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
980 sd_bus *bus = userdata;
986 polkit_agent_open_if_enabled();
988 for (i = 1; i < argc; i++) {
991 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
993 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 "u", (uint32_t) uid);
1004 log_error("Could not terminate user: %s", bus_error_message(&error, -r));
1012 static int kill_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();
1023 arg_kill_who = "all";
1025 for (i = 1; i < argc; i++) {
1028 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
1030 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
1032 r = sd_bus_call_method(
1034 "org.freedesktop.login1",
1035 "/org/freedesktop/login1",
1036 "org.freedesktop.login1.Manager",
1039 "ui", (uint32_t) uid, arg_signal);
1041 log_error("Could not kill user: %s", bus_error_message(&error, -r));
1049 static int attach(int argc, char *argv[], void *userdata) {
1050 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1051 sd_bus *bus = userdata;
1057 polkit_agent_open_if_enabled();
1059 for (i = 2; i < argc; i++) {
1061 r = sd_bus_call_method(
1063 "org.freedesktop.login1",
1064 "/org/freedesktop/login1",
1065 "org.freedesktop.login1.Manager",
1068 "ssb", argv[1], argv[i], true);
1071 log_error("Could not attach device: %s", bus_error_message(&error, -r));
1079 static int flush_devices(int argc, char *argv[], void *userdata) {
1080 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1081 sd_bus *bus = userdata;
1087 polkit_agent_open_if_enabled();
1089 r = sd_bus_call_method(
1091 "org.freedesktop.login1",
1092 "/org/freedesktop/login1",
1093 "org.freedesktop.login1.Manager",
1098 log_error("Could not flush devices: %s", bus_error_message(&error, -r));
1103 static int lock_sessions(int argc, char *argv[], void *userdata) {
1104 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1105 sd_bus *bus = userdata;
1111 polkit_agent_open_if_enabled();
1113 r = sd_bus_call_method(
1115 "org.freedesktop.login1",
1116 "/org/freedesktop/login1",
1117 "org.freedesktop.login1.Manager",
1118 streq(argv[0], "lock-sessions") ? "LockSessions" : "UnlockSessions",
1122 log_error("Could not lock sessions: %s", bus_error_message(&error, -r));
1127 static int terminate_seat(int argc, char *argv[], void *userdata) {
1128 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1129 sd_bus *bus = userdata;
1135 polkit_agent_open_if_enabled();
1137 for (i = 1; i < argc; i++) {
1139 r = sd_bus_call_method(
1141 "org.freedesktop.login1",
1142 "/org/freedesktop/login1",
1143 "org.freedesktop.login1.Manager",
1148 log_error("Could not terminate seat: %s", bus_error_message(&error, -r));
1156 static int check_inhibitors(sd_bus *bus, const char *verb, const char *inhibit_what) {
1157 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1158 _cleanup_strv_free_ char **sessions = NULL;
1159 const char *what, *who, *why, *mode;
1167 if (arg_ignore_inhibitors)
1176 r = sd_bus_call_method(
1178 "org.freedesktop.login1",
1179 "/org/freedesktop/login1",
1180 "org.freedesktop.login1.Manager",
1186 /* If logind is not around, then there are no inhibitors... */
1189 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
1191 return bus_log_parse_error(r);
1193 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
1194 _cleanup_free_ char *comm = NULL, *user = NULL;
1195 _cleanup_strv_free_ char **sv = NULL;
1197 if (!streq(mode, "block"))
1200 sv = strv_split(what, ":");
1204 if (!strv_contains(sv, inhibit_what))
1207 get_process_comm(pid, &comm);
1208 user = uid_to_name(uid);
1210 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
1211 who, pid, strna(comm), strna(user), why);
1216 return bus_log_parse_error(r);
1218 r = sd_bus_message_exit_container(reply);
1220 return bus_log_parse_error(r);
1222 /* Check for current sessions */
1223 sd_get_sessions(&sessions);
1224 STRV_FOREACH(s, sessions) {
1225 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
1227 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
1230 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
1233 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
1236 sd_session_get_tty(*s, &tty);
1237 sd_session_get_seat(*s, &seat);
1238 sd_session_get_service(*s, &service);
1239 user = uid_to_name(uid);
1241 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
1248 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'loginctl %s -i'.", verb);
1253 static int poweroff(int argc, char *argv[], void *userdata) {
1254 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1255 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1256 sd_bus *bus = userdata;
1261 r = check_inhibitors(bus, "poweroff", "shutdown");
1265 polkit_agent_open_if_enabled();
1267 r = sd_bus_call_method(
1269 "org.freedesktop.login1",
1270 "/org/freedesktop/login1",
1271 "org.freedesktop.login1.Manager",
1275 "b", arg_ask_password);
1277 log_error("Failed to power off: %s", bus_error_message(&error, r));
1282 static int reboot(int argc, char *argv[], void *userdata) {
1283 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1284 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1285 sd_bus *bus = userdata;
1290 r = check_inhibitors(bus, "reboot", "shutdown");
1294 polkit_agent_open_if_enabled();
1296 r = sd_bus_call_method(
1298 "org.freedesktop.login1",
1299 "/org/freedesktop/login1",
1300 "org.freedesktop.login1.Manager",
1304 "b", arg_ask_password);
1306 log_error("Failed to reboot: %s", bus_error_message(&error, r));
1311 static int suspend(int argc, char *argv[], void *userdata) {
1312 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1313 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1314 sd_bus *bus = userdata;
1319 r = check_inhibitors(bus, "suspend", "sleep");
1323 polkit_agent_open_if_enabled();
1325 r = sd_bus_call_method(
1327 "org.freedesktop.login1",
1328 "/org/freedesktop/login1",
1329 "org.freedesktop.login1.Manager",
1333 "b", arg_ask_password);
1335 log_error("Failed to suspend: %s", bus_error_message(&error, r));
1340 static int hibernate(int argc, char *argv[], void *userdata) {
1341 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1342 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1343 sd_bus *bus = userdata;
1348 r = check_inhibitors(bus, "hibernate", "sleep");
1352 polkit_agent_open_if_enabled();
1354 r = sd_bus_call_method(
1356 "org.freedesktop.login1",
1357 "/org/freedesktop/login1",
1358 "org.freedesktop.login1.Manager",
1362 "b", arg_ask_password);
1364 log_error("Failed to hibernate: %s", bus_error_message(&error, r));
1369 static int hybrid_sleep(int argc, char *argv[], void *userdata) {
1370 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1371 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1372 sd_bus *bus = userdata;
1377 r = check_inhibitors(bus, "hybrid-sleep", "sleep");
1381 polkit_agent_open_if_enabled();
1383 r = sd_bus_call_method(
1385 "org.freedesktop.login1",
1386 "/org/freedesktop/login1",
1387 "org.freedesktop.login1.Manager",
1391 "b", arg_ask_password);
1393 log_error("Failed to hybrid sleep: %s", bus_error_message(&error, r));
1398 static int help(int argc, char *argv[], void *userdata) {
1400 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
1401 "Send control commands to or query the login manager.\n\n"
1402 " -h --help Show this help\n"
1403 " --version Show package version\n"
1404 " --no-pager Do not pipe output into a pager\n"
1405 " --no-legend Do not show the headers and footers\n"
1406 " --no-ask-password Don't prompt for password\n"
1407 " -i --ignore-inhibitors Ignore inhibitors when suspending or shutting down\n"
1408 " -H --host=[USER@]HOST Operate on remote host\n"
1409 " -M --machine=CONTAINER Operate on local container\n"
1410 " -p --property=NAME Show only properties by this name\n"
1411 " -a --all Show all properties, including empty ones\n"
1412 " -l --full Do not ellipsize output\n"
1413 " --kill-who=WHO Who to send signal to\n"
1414 " -s --signal=SIGNAL Which signal to send\n"
1415 " -n --lines=INTEGER Number of journal entries to show\n"
1416 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
1417 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
1418 "Session Commands:\n"
1419 " list-sessions List sessions\n"
1420 " session-status [ID...] Show session status\n"
1421 " show-session [ID...] Show properties of sessions or the manager\n"
1422 " activate [ID] Activate a session\n"
1423 " lock-session [ID...] Screen lock one or more sessions\n"
1424 " unlock-session [ID...] Screen unlock one or more sessions\n"
1425 " lock-sessions Screen lock all current sessions\n"
1426 " unlock-sessions Screen unlock all current sessions\n"
1427 " terminate-session ID... Terminate one or more sessions\n"
1428 " kill-session ID... Send signal to processes of a session\n\n"
1430 " list-users List users\n"
1431 " user-status [USER...] Show user status\n"
1432 " show-user [USER...] Show properties of users or the manager\n"
1433 " enable-linger [USER...] Enable linger state of one or more users\n"
1434 " disable-linger [USER...] Disable linger state of one or more users\n"
1435 " terminate-user USER... Terminate all sessions of one or more users\n"
1436 " kill-user USER... Send signal to processes of a user\n\n"
1438 " list-seats List seats\n"
1439 " seat-status [NAME...] Show seat status\n"
1440 " show-seat [NAME...] Show properties of seats or the manager\n"
1441 " attach NAME DEVICE... Attach one or more devices to a seat\n"
1442 " flush-devices Flush all device associations\n"
1443 " terminate-seat NAME... Terminate all sessions on one or more seats\n\n"
1444 "System Commands:\n"
1445 " poweroff Turn off the machine\n"
1446 " reboot Reboot the machine\n"
1447 " suspend Suspend the machine to memory\n"
1448 " hibernate Suspend the machine to disk\n"
1449 " hybrid-sleep Suspend the machine to memory and disk\n"
1450 , program_invocation_short_name);
1455 static int parse_argv(int argc, char *argv[]) {
1458 ARG_VERSION = 0x100,
1462 ARG_NO_ASK_PASSWORD,
1465 static const struct option options[] = {
1466 { "help", no_argument, NULL, 'h' },
1467 { "version", no_argument, NULL, ARG_VERSION },
1468 { "property", required_argument, NULL, 'p' },
1469 { "all", no_argument, NULL, 'a' },
1470 { "full", no_argument, NULL, 'l' },
1471 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
1472 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
1473 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
1474 { "signal", required_argument, NULL, 's' },
1475 { "host", required_argument, NULL, 'H' },
1476 { "machine", required_argument, NULL, 'M' },
1477 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
1478 { "ignore-inhibitors", no_argument, NULL, 'i' },
1479 { "lines", required_argument, NULL, 'n' },
1480 { "output", required_argument, NULL, 'o' },
1489 while ((c = getopt_long(argc, argv, "hp:als:H:M:n:o:i", options, NULL)) >= 0)
1494 help(0, NULL, NULL);
1498 puts(PACKAGE_STRING);
1499 puts(SYSTEMD_FEATURES);
1503 r = strv_extend(&arg_property, optarg);
1507 /* If the user asked for a particular
1508 * property, show it to him, even if it is
1523 if (safe_atou(optarg, &arg_lines) < 0) {
1524 log_error("Failed to parse lines '%s'", optarg);
1531 arg_output = output_mode_from_string(optarg);
1535 if (arg_output < 0) {
1536 log_error("Unknown output '%s'.", optarg);
1542 arg_ignore_inhibitors = true;
1546 arg_no_pager = true;
1553 case ARG_NO_ASK_PASSWORD:
1554 arg_ask_password = false;
1558 arg_kill_who = optarg;
1562 arg_signal = signal_from_string_try_harder(optarg);
1563 if (arg_signal < 0) {
1564 log_error("Failed to parse signal string %s.", optarg);
1570 arg_transport = BUS_TRANSPORT_REMOTE;
1575 arg_transport = BUS_TRANSPORT_MACHINE;
1583 assert_not_reached("Unhandled option");
1589 static int loginctl_main(int argc, char *argv[], sd_bus *bus) {
1591 static const Verb verbs[] = {
1592 { "help", VERB_ANY, VERB_ANY, 0, help },
1593 { "list-sessions", VERB_ANY, 1, VERB_DEFAULT, list_sessions },
1594 { "session-status", VERB_ANY, VERB_ANY, 0, show_session },
1595 { "show-session", VERB_ANY, VERB_ANY, 0, show_session },
1596 { "activate", VERB_ANY, 2, 0, activate },
1597 { "lock-session", VERB_ANY, VERB_ANY, 0, activate },
1598 { "unlock-session", VERB_ANY, VERB_ANY, 0, activate },
1599 { "lock-sessions", VERB_ANY, 1, 0, lock_sessions },
1600 { "unlock-sessions", VERB_ANY, 1, 0, lock_sessions },
1601 { "terminate-session", 2, VERB_ANY, 0, activate },
1602 { "kill-session", 2, VERB_ANY, 0, kill_session },
1603 { "list-users", VERB_ANY, 1, 0, list_users },
1604 { "user-status", VERB_ANY, VERB_ANY, 0, show_user },
1605 { "show-user", VERB_ANY, VERB_ANY, 0, show_user },
1606 { "enable-linger", VERB_ANY, VERB_ANY, 0, enable_linger },
1607 { "disable-linger", VERB_ANY, VERB_ANY, 0, enable_linger },
1608 { "terminate-user", 2, VERB_ANY, 0, terminate_user },
1609 { "kill-user", 2, VERB_ANY, 0, kill_user },
1610 { "list-seats", VERB_ANY, 1, 0, list_seats },
1611 { "seat-status", VERB_ANY, VERB_ANY, 0, show_seat },
1612 { "show-seat", VERB_ANY, VERB_ANY, 0, show_seat },
1613 { "attach", 3, VERB_ANY, 0, attach },
1614 { "flush-devices", VERB_ANY, 1, 0, flush_devices },
1615 { "terminate-seat", 2, VERB_ANY, 0, terminate_seat },
1616 { "poweroff", VERB_ANY, 1, 0, poweroff },
1617 { "reboot", VERB_ANY, 1, 0, reboot },
1618 { "suspend", VERB_ANY, 1, 0, suspend },
1619 { "hibernate", VERB_ANY, 1, 0, hibernate },
1620 { "hybrid-sleep", VERB_ANY, 1, 0, hybrid_sleep },
1624 return dispatch_verb(argc, argv, verbs, bus);
1627 int main(int argc, char *argv[]) {
1628 _cleanup_bus_close_unref_ sd_bus *bus = NULL;
1631 setlocale(LC_ALL, "");
1632 log_parse_environment();
1635 r = parse_argv(argc, argv);
1639 r = bus_open_transport(arg_transport, arg_host, false, &bus);
1641 log_error_errno(r, "Failed to create bus connection: %m");
1645 sd_bus_set_allow_interactive_authorization(bus, arg_ask_password);
1647 r = loginctl_main(argc, argv, bus);
1651 polkit_agent_close();
1653 strv_free(arg_property);
1655 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;