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"
46 static char **arg_property = NULL;
47 static bool arg_all = false;
48 static bool arg_full = false;
49 static bool arg_no_pager = false;
50 static bool arg_legend = true;
51 static const char *arg_kill_who = NULL;
52 static int arg_signal = SIGTERM;
53 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
54 static char *arg_host = NULL;
55 static bool arg_ask_password = true;
56 static bool arg_ignore_inhibitors = false;
57 static unsigned arg_lines = 10;
58 static OutputMode arg_output = OUTPUT_SHORT;
60 static void pager_open_if_enabled(void) {
68 static void polkit_agent_open_if_enabled(void) {
70 /* Open the polkit agent as a child process if necessary */
72 if (!arg_ask_password)
75 if (arg_transport != BUS_TRANSPORT_LOCAL)
81 static OutputFlags get_output_flags(void) {
84 arg_all * OUTPUT_SHOW_ALL |
85 arg_full * OUTPUT_FULL_WIDTH |
86 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
87 on_tty() * OUTPUT_COLOR;
90 static int list_sessions(int argc, char *argv[], void *userdata) {
91 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
92 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
93 const char *id, *user, *seat, *object;
94 sd_bus *bus = userdata;
102 pager_open_if_enabled();
104 r = sd_bus_call_method(
106 "org.freedesktop.login1",
107 "/org/freedesktop/login1",
108 "org.freedesktop.login1.Manager",
113 log_error("Failed to list sessions: %s", bus_error_message(&error, r));
117 r = sd_bus_message_enter_container(reply, 'a', "(susso)");
119 return bus_log_parse_error(r);
122 printf("%10s %10s %-16s %-16s\n", "SESSION", "UID", "USER", "SEAT");
124 while ((r = sd_bus_message_read(reply, "(susso)", &id, &uid, &user, &seat, &object)) > 0) {
125 printf("%10s %10u %-16s %-16s\n", id, (unsigned) uid, user, seat);
129 return bus_log_parse_error(r);
132 printf("\n%u sessions listed.\n", k);
137 static int list_users(int argc, char *argv[], void *userdata) {
138 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
139 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
140 const char *user, *object;
141 sd_bus *bus = userdata;
149 pager_open_if_enabled();
151 r = sd_bus_call_method(
153 "org.freedesktop.login1",
154 "/org/freedesktop/login1",
155 "org.freedesktop.login1.Manager",
160 log_error("Failed to list users: %s", bus_error_message(&error, r));
164 r = sd_bus_message_enter_container(reply, 'a', "(uso)");
166 return bus_log_parse_error(r);
169 printf("%10s %-16s\n", "UID", "USER");
171 while ((r = sd_bus_message_read(reply, "(uso)", &uid, &user, &object)) > 0) {
172 printf("%10u %-16s\n", (unsigned) uid, user);
176 return bus_log_parse_error(r);
179 printf("\n%u users listed.\n", k);
184 static int list_seats(int argc, char *argv[], void *userdata) {
185 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
186 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
187 const char *seat, *object;
188 sd_bus *bus = userdata;
195 pager_open_if_enabled();
197 r = sd_bus_call_method(
199 "org.freedesktop.login1",
200 "/org/freedesktop/login1",
201 "org.freedesktop.login1.Manager",
206 log_error("Failed to list seats: %s", bus_error_message(&error, r));
210 r = sd_bus_message_enter_container(reply, 'a', "(so)");
212 return bus_log_parse_error(r);
215 printf("%-16s\n", "SEAT");
217 while ((r = sd_bus_message_read(reply, "(so)", &seat, &object)) > 0) {
218 printf("%-16s\n", seat);
222 return bus_log_parse_error(r);
225 printf("\n%u seats listed.\n", k);
230 static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit, pid_t leader) {
231 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
232 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
233 _cleanup_free_ char *path = NULL;
241 if (arg_transport != BUS_TRANSPORT_LOCAL)
244 path = unit_dbus_path_from_name(unit);
248 r = sd_bus_get_property(
250 "org.freedesktop.systemd1",
254 &error, &reply, "s");
258 r = sd_bus_message_read(reply, "s", &cgroup);
265 if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup, false) != 0 && leader <= 0)
274 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t ", c, false, &leader, leader > 0, get_output_flags());
278 typedef struct SessionStatusInfo {
282 struct dual_timestamp timestamp;
288 const char *remote_host;
289 const char *remote_user;
299 typedef struct UserStatusInfo {
302 struct dual_timestamp timestamp;
309 typedef struct SeatStatusInfo {
311 const char *active_session;
315 static int prop_map_first_of_struct(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
316 const char *contents;
319 r = sd_bus_message_peek_type(m, NULL, &contents);
323 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, contents);
327 if (contents[0] == 's' || contents[0] == 'o') {
329 char **p = (char **) userdata;
331 r = sd_bus_message_read_basic(m, contents[0], &s);
341 r = sd_bus_message_read_basic(m, contents[0], userdata);
346 r = sd_bus_message_skip(m, contents+1);
350 r = sd_bus_message_exit_container(m);
357 static int prop_map_sessions_strv(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
364 r = sd_bus_message_enter_container(m, 'a', "(so)");
368 while ((r = sd_bus_message_read(m, "(so)", &name, NULL)) > 0) {
369 r = strv_extend(userdata, name);
376 return sd_bus_message_exit_container(m);
379 static int print_session_status_info(sd_bus *bus, const char *path, bool *new_line) {
381 static const struct bus_properties_map map[] = {
382 { "Id", "s", NULL, offsetof(SessionStatusInfo, id) },
383 { "Name", "s", NULL, offsetof(SessionStatusInfo, name) },
384 { "TTY", "s", NULL, offsetof(SessionStatusInfo, tty) },
385 { "Display", "s", NULL, offsetof(SessionStatusInfo, display) },
386 { "RemoteHost", "s", NULL, offsetof(SessionStatusInfo, remote_host) },
387 { "RemoteUser", "s", NULL, offsetof(SessionStatusInfo, remote_user) },
388 { "Service", "s", NULL, offsetof(SessionStatusInfo, service) },
389 { "Desktop", "s", NULL, offsetof(SessionStatusInfo, desktop) },
390 { "Type", "s", NULL, offsetof(SessionStatusInfo, type) },
391 { "Class", "s", NULL, offsetof(SessionStatusInfo, class) },
392 { "Scope", "s", NULL, offsetof(SessionStatusInfo, scope) },
393 { "State", "s", NULL, offsetof(SessionStatusInfo, state) },
394 { "VTNr", "u", NULL, offsetof(SessionStatusInfo, vtnr) },
395 { "Leader", "u", NULL, offsetof(SessionStatusInfo, leader) },
396 { "Remote", "b", NULL, offsetof(SessionStatusInfo, remote) },
397 { "Timestamp", "t", NULL, offsetof(SessionStatusInfo, timestamp.realtime) },
398 { "TimestampMonotonic", "t", NULL, offsetof(SessionStatusInfo, timestamp.monotonic) },
399 { "User", "(uo)", prop_map_first_of_struct, offsetof(SessionStatusInfo, uid) },
400 { "Seat", "(so)", prop_map_first_of_struct, offsetof(SessionStatusInfo, seat) },
404 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
405 char since2[FORMAT_TIMESTAMP_MAX], *s2;
406 SessionStatusInfo i = {};
409 r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i);
411 return log_error_errno(r, "Could not get properties: %m");
418 printf("%s - ", strna(i.id));
421 printf("%s (%u)\n", i.name, (unsigned) i.uid);
423 printf("%u\n", (unsigned) i.uid);
425 s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime);
426 s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime);
429 printf("\t Since: %s; %s\n", s2, s1);
431 printf("\t Since: %s\n", s2);
434 _cleanup_free_ char *t = NULL;
436 printf("\t Leader: %u", (unsigned) i.leader);
438 get_process_comm(i.leader, &t);
445 if (!isempty(i.seat)) {
446 printf("\t Seat: %s", i.seat);
449 printf("; vc%u", i.vtnr);
455 printf("\t TTY: %s\n", i.tty);
457 printf("\t Display: %s\n", i.display);
459 if (i.remote_host && i.remote_user)
460 printf("\t Remote: %s@%s\n", i.remote_user, i.remote_host);
461 else if (i.remote_host)
462 printf("\t Remote: %s\n", i.remote_host);
463 else if (i.remote_user)
464 printf("\t Remote: user %s\n", i.remote_user);
466 printf("\t Remote: Yes\n");
469 printf("\t Service: %s", i.service);
472 printf("; type %s", i.type);
475 printf("; class %s", i.class);
479 printf("\t Type: %s", i.type);
482 printf("; class %s", i.class);
486 printf("\t Class: %s\n", i.class);
488 if (!isempty(i.desktop))
489 printf("\t Desktop: %s\n", i.desktop);
492 printf("\t State: %s\n", i.state);
495 printf("\t Unit: %s\n", i.scope);
496 show_unit_cgroup(bus, "org.freedesktop.systemd1.Scope", i.scope, i.leader);
498 if (arg_transport == BUS_TRANSPORT_LOCAL) {
500 show_journal_by_unit(
505 i.timestamp.monotonic,
508 get_output_flags() | OUTPUT_BEGIN_NEWLINE,
509 SD_JOURNAL_LOCAL_ONLY,
519 static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line) {
521 static const struct bus_properties_map map[] = {
522 { "Name", "s", NULL, offsetof(UserStatusInfo, name) },
523 { "Slice", "s", NULL, offsetof(UserStatusInfo, slice) },
524 { "State", "s", NULL, offsetof(UserStatusInfo, state) },
525 { "UID", "u", NULL, offsetof(UserStatusInfo, uid) },
526 { "Timestamp", "t", NULL, offsetof(UserStatusInfo, timestamp.realtime) },
527 { "TimestampMonotonic", "t", NULL, offsetof(UserStatusInfo, timestamp.monotonic) },
528 { "Display", "(so)", prop_map_first_of_struct, offsetof(UserStatusInfo, display) },
529 { "Sessions", "a(so)", prop_map_sessions_strv, offsetof(UserStatusInfo, sessions) },
533 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
534 char since2[FORMAT_TIMESTAMP_MAX], *s2;
535 UserStatusInfo i = {};
538 r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i);
540 log_error_errno(r, "Could not get properties: %m");
550 printf("%s (%u)\n", i.name, (unsigned) i.uid);
552 printf("%u\n", (unsigned) i.uid);
554 s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime);
555 s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime);
558 printf("\t Since: %s; %s\n", s2, s1);
560 printf("\t Since: %s\n", s2);
562 if (!isempty(i.state))
563 printf("\t State: %s\n", i.state);
565 if (!strv_isempty(i.sessions)) {
567 printf("\tSessions:");
569 STRV_FOREACH(l, i.sessions) {
570 if (streq_ptr(*l, i.display))
580 printf("\t Unit: %s\n", i.slice);
581 show_unit_cgroup(bus, "org.freedesktop.systemd1.Slice", i.slice, 0);
583 show_journal_by_unit(
588 i.timestamp.monotonic,
591 get_output_flags() | OUTPUT_BEGIN_NEWLINE,
592 SD_JOURNAL_LOCAL_ONLY,
599 strv_free(i.sessions);
604 static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line) {
606 static const struct bus_properties_map map[] = {
607 { "Id", "s", NULL, offsetof(SeatStatusInfo, id) },
608 { "ActiveSession", "(so)", prop_map_first_of_struct, offsetof(SeatStatusInfo, active_session) },
609 { "Sessions", "a(so)", prop_map_sessions_strv, offsetof(SeatStatusInfo, sessions) },
613 SeatStatusInfo i = {};
616 r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i);
618 log_error_errno(r, "Could not get properties: %m");
627 printf("%s\n", strna(i.id));
629 if (!strv_isempty(i.sessions)) {
631 printf("\tSessions:");
633 STRV_FOREACH(l, i.sessions) {
634 if (streq_ptr(*l, i.active_session))
643 if (arg_transport == BUS_TRANSPORT_LOCAL) {
652 printf("\t Devices:\n");
654 show_sysfs(i.id, "\t\t ", c);
658 strv_free(i.sessions);
663 static int show_properties(sd_bus *bus, const char *path, bool *new_line) {
671 r = bus_print_all_properties(bus, "org.freedesktop.login1", path, arg_property, arg_all);
673 log_error_errno(r, "Could not get properties: %m");
678 static int show_session(int argc, char *argv[], void *userdata) {
679 bool properties, new_line = false;
680 sd_bus *bus = userdata;
686 properties = !strstr(argv[0], "status");
688 pager_open_if_enabled();
691 /* If not argument is specified inspect the manager
694 return show_properties(bus, "/org/freedesktop/login1", &new_line);
696 /* And in the pretty case, show data of the calling session */
697 return print_session_status_info(bus, "/org/freedesktop/login1/session/self", &new_line);
700 for (i = 1; i < argc; i++) {
701 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
702 _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
703 const char *path = NULL;
705 r = sd_bus_call_method(
707 "org.freedesktop.login1",
708 "/org/freedesktop/login1",
709 "org.freedesktop.login1.Manager",
714 log_error("Failed to get session: %s", bus_error_message(&error, r));
718 r = sd_bus_message_read(reply, "o", &path);
720 return bus_log_parse_error(r);
723 r = show_properties(bus, path, &new_line);
725 r = print_session_status_info(bus, path, &new_line);
734 static int show_user(int argc, char *argv[], void *userdata) {
735 bool properties, new_line = false;
736 sd_bus *bus = userdata;
742 properties = !strstr(argv[0], "status");
744 pager_open_if_enabled();
747 /* If not argument is specified inspect the manager
750 return show_properties(bus, "/org/freedesktop/login1", &new_line);
752 return print_user_status_info(bus, "/org/freedesktop/login1/user/self", &new_line);
755 for (i = 1; i < argc; i++) {
756 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
757 _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
758 const char *path = NULL;
761 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
763 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
765 r = sd_bus_call_method(
767 "org.freedesktop.login1",
768 "/org/freedesktop/login1",
769 "org.freedesktop.login1.Manager",
772 "u", (uint32_t) uid);
774 log_error("Failed to get user: %s", bus_error_message(&error, r));
778 r = sd_bus_message_read(reply, "o", &path);
780 return bus_log_parse_error(r);
783 r = show_properties(bus, path, &new_line);
785 r = print_user_status_info(bus, path, &new_line);
794 static int show_seat(int argc, char *argv[], void *userdata) {
795 bool properties, new_line = false;
796 sd_bus *bus = userdata;
802 properties = !strstr(argv[0], "status");
804 pager_open_if_enabled();
807 /* If not argument is specified inspect the manager
810 return show_properties(bus, "/org/freedesktop/login1", &new_line);
812 return print_seat_status_info(bus, "/org/freedesktop/login1/seat/self", &new_line);
815 for (i = 1; i < argc; i++) {
816 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
817 _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
818 const char *path = NULL;
820 r = sd_bus_call_method(
822 "org.freedesktop.login1",
823 "/org/freedesktop/login1",
824 "org.freedesktop.login1.Manager",
829 log_error("Failed to get seat: %s", bus_error_message(&error, r));
833 r = sd_bus_message_read(reply, "o", &path);
835 return bus_log_parse_error(r);
838 r = show_properties(bus, path, &new_line);
840 r = print_seat_status_info(bus, path, &new_line);
849 static int activate(int argc, char *argv[], void *userdata) {
850 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
851 sd_bus *bus = userdata;
858 polkit_agent_open_if_enabled();
861 /* No argument? Let's convert this into the empty
862 * session name, which the calls will then resolve to
863 * the caller's session. */
865 short_argv[0] = argv[0];
866 short_argv[1] = (char*) "";
867 short_argv[2] = NULL;
873 for (i = 1; i < argc; i++) {
875 r = sd_bus_call_method(
877 "org.freedesktop.login1",
878 "/org/freedesktop/login1",
879 "org.freedesktop.login1.Manager",
880 streq(argv[0], "lock-session") ? "LockSession" :
881 streq(argv[0], "unlock-session") ? "UnlockSession" :
882 streq(argv[0], "terminate-session") ? "TerminateSession" :
887 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
895 static int kill_session(int argc, char *argv[], void *userdata) {
896 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
897 sd_bus *bus = userdata;
903 polkit_agent_open_if_enabled();
906 arg_kill_who = "all";
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",
917 "ssi", argv[i], arg_kill_who, arg_signal);
919 log_error("Could not kill session: %s", bus_error_message(&error, -r));
927 static int enable_linger(int argc, char *argv[], void *userdata) {
928 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
929 sd_bus *bus = userdata;
937 polkit_agent_open_if_enabled();
939 b = streq(argv[0], "enable-linger");
942 short_argv[0] = argv[0];
943 short_argv[1] = (char*) "";
944 short_argv[2] = NULL;
949 for (i = 1; i < argc; i++) {
952 if (isempty(argv[i]))
955 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
957 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
960 r = sd_bus_call_method(
962 "org.freedesktop.login1",
963 "/org/freedesktop/login1",
964 "org.freedesktop.login1.Manager",
967 "ubb", (uint32_t) uid, b, true);
969 log_error("Could not enable linger: %s", bus_error_message(&error, -r));
977 static int terminate_user(int argc, char *argv[], void *userdata) {
978 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
979 sd_bus *bus = userdata;
985 polkit_agent_open_if_enabled();
987 for (i = 1; i < argc; 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]);
994 r = sd_bus_call_method(
996 "org.freedesktop.login1",
997 "/org/freedesktop/login1",
998 "org.freedesktop.login1.Manager",
1001 "u", (uint32_t) uid);
1003 log_error("Could not terminate user: %s", bus_error_message(&error, -r));
1011 static int kill_user(int argc, char *argv[], void *userdata) {
1012 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1013 sd_bus *bus = userdata;
1019 polkit_agent_open_if_enabled();
1022 arg_kill_who = "all";
1024 for (i = 1; i < argc; i++) {
1027 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
1029 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
1031 r = sd_bus_call_method(
1033 "org.freedesktop.login1",
1034 "/org/freedesktop/login1",
1035 "org.freedesktop.login1.Manager",
1038 "ui", (uint32_t) uid, arg_signal);
1040 log_error("Could not kill user: %s", bus_error_message(&error, -r));
1048 static int attach(int argc, char *argv[], void *userdata) {
1049 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1050 sd_bus *bus = userdata;
1056 polkit_agent_open_if_enabled();
1058 for (i = 2; i < argc; i++) {
1060 r = sd_bus_call_method(
1062 "org.freedesktop.login1",
1063 "/org/freedesktop/login1",
1064 "org.freedesktop.login1.Manager",
1067 "ssb", argv[1], argv[i], true);
1070 log_error("Could not attach device: %s", bus_error_message(&error, -r));
1078 static int flush_devices(int argc, char *argv[], void *userdata) {
1079 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1080 sd_bus *bus = userdata;
1086 polkit_agent_open_if_enabled();
1088 r = sd_bus_call_method(
1090 "org.freedesktop.login1",
1091 "/org/freedesktop/login1",
1092 "org.freedesktop.login1.Manager",
1097 log_error("Could not flush devices: %s", bus_error_message(&error, -r));
1102 static int lock_sessions(int argc, char *argv[], void *userdata) {
1103 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1104 sd_bus *bus = userdata;
1110 polkit_agent_open_if_enabled();
1112 r = sd_bus_call_method(
1114 "org.freedesktop.login1",
1115 "/org/freedesktop/login1",
1116 "org.freedesktop.login1.Manager",
1117 streq(argv[0], "lock-sessions") ? "LockSessions" : "UnlockSessions",
1121 log_error("Could not lock sessions: %s", bus_error_message(&error, -r));
1126 static int terminate_seat(int argc, char *argv[], void *userdata) {
1127 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1128 sd_bus *bus = userdata;
1134 polkit_agent_open_if_enabled();
1136 for (i = 1; i < argc; i++) {
1138 r = sd_bus_call_method(
1140 "org.freedesktop.login1",
1141 "/org/freedesktop/login1",
1142 "org.freedesktop.login1.Manager",
1147 log_error("Could not terminate seat: %s", bus_error_message(&error, -r));
1155 static int check_inhibitors(sd_bus *bus, const char *verb, const char *inhibit_what) {
1156 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1157 _cleanup_strv_free_ char **sessions = NULL;
1158 const char *what, *who, *why, *mode;
1166 if (arg_ignore_inhibitors)
1175 r = sd_bus_call_method(
1177 "org.freedesktop.login1",
1178 "/org/freedesktop/login1",
1179 "org.freedesktop.login1.Manager",
1185 /* If logind is not around, then there are no inhibitors... */
1188 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
1190 return bus_log_parse_error(r);
1192 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
1193 _cleanup_free_ char *comm = NULL, *user = NULL;
1194 _cleanup_strv_free_ char **sv = NULL;
1196 if (!streq(mode, "block"))
1199 sv = strv_split(what, ":");
1203 if (!strv_contains(sv, inhibit_what))
1206 get_process_comm(pid, &comm);
1207 user = uid_to_name(uid);
1209 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
1210 who, pid, strna(comm), strna(user), why);
1215 return bus_log_parse_error(r);
1217 r = sd_bus_message_exit_container(reply);
1219 return bus_log_parse_error(r);
1221 /* Check for current sessions */
1222 sd_get_sessions(&sessions);
1223 STRV_FOREACH(s, sessions) {
1224 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
1226 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
1229 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
1232 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
1235 sd_session_get_tty(*s, &tty);
1236 sd_session_get_seat(*s, &seat);
1237 sd_session_get_service(*s, &service);
1238 user = uid_to_name(uid);
1240 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
1247 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'loginctl %s -i'.", verb);
1252 static int poweroff(int argc, char *argv[], void *userdata) {
1253 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1254 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1255 sd_bus *bus = userdata;
1260 r = check_inhibitors(bus, "poweroff", "shutdown");
1264 polkit_agent_open_if_enabled();
1266 r = sd_bus_call_method(
1268 "org.freedesktop.login1",
1269 "/org/freedesktop/login1",
1270 "org.freedesktop.login1.Manager",
1274 "b", arg_ask_password);
1276 log_error("Failed to power off: %s", bus_error_message(&error, r));
1281 static int reboot(int argc, char *argv[], void *userdata) {
1282 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1283 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1284 sd_bus *bus = userdata;
1289 r = check_inhibitors(bus, "reboot", "shutdown");
1293 polkit_agent_open_if_enabled();
1295 r = sd_bus_call_method(
1297 "org.freedesktop.login1",
1298 "/org/freedesktop/login1",
1299 "org.freedesktop.login1.Manager",
1303 "b", arg_ask_password);
1305 log_error("Failed to reboot: %s", bus_error_message(&error, r));
1310 static int suspend(int argc, char *argv[], void *userdata) {
1311 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1312 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1313 sd_bus *bus = userdata;
1318 r = check_inhibitors(bus, "suspend", "sleep");
1322 polkit_agent_open_if_enabled();
1324 r = sd_bus_call_method(
1326 "org.freedesktop.login1",
1327 "/org/freedesktop/login1",
1328 "org.freedesktop.login1.Manager",
1332 "b", arg_ask_password);
1334 log_error("Failed to suspend: %s", bus_error_message(&error, r));
1339 static int hibernate(int argc, char *argv[], void *userdata) {
1340 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1341 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1342 sd_bus *bus = userdata;
1347 r = check_inhibitors(bus, "hibernate", "sleep");
1351 polkit_agent_open_if_enabled();
1353 r = sd_bus_call_method(
1355 "org.freedesktop.login1",
1356 "/org/freedesktop/login1",
1357 "org.freedesktop.login1.Manager",
1361 "b", arg_ask_password);
1363 log_error("Failed to hibernate: %s", bus_error_message(&error, r));
1368 static int hybrid_sleep(int argc, char *argv[], void *userdata) {
1369 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1370 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1371 sd_bus *bus = userdata;
1376 r = check_inhibitors(bus, "hybrid-sleep", "sleep");
1380 polkit_agent_open_if_enabled();
1382 r = sd_bus_call_method(
1384 "org.freedesktop.login1",
1385 "/org/freedesktop/login1",
1386 "org.freedesktop.login1.Manager",
1390 "b", arg_ask_password);
1392 log_error("Failed to hybrid sleep: %s", bus_error_message(&error, r));
1397 static int help(int argc, char *argv[], void *userdata) {
1399 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
1400 "Send control commands to or query the login manager.\n\n"
1401 " -h --help Show this help\n"
1402 " --version Show package version\n"
1403 " --no-pager Do not pipe output into a pager\n"
1404 " --no-legend Do not show the headers and footers\n"
1405 " --no-ask-password Don't prompt for password\n"
1406 " -i --ignore-inhibitors Ignore inhibitors when suspending or shutting down\n"
1407 " -H --host=[USER@]HOST Operate on remote host\n"
1408 " -M --machine=CONTAINER Operate on local container\n"
1409 " -p --property=NAME Show only properties by this name\n"
1410 " -a --all Show all properties, including empty ones\n"
1411 " -l --full Do not ellipsize output\n"
1412 " --kill-who=WHO Who to send signal to\n"
1413 " -s --signal=SIGNAL Which signal to send\n"
1414 " -n --lines=INTEGER Number of journal entries to show\n"
1415 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
1416 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
1417 "Session Commands:\n"
1418 " list-sessions List sessions\n"
1419 " session-status [ID...] Show session status\n"
1420 " show-session [ID...] Show properties of sessions or the manager\n"
1421 " activate [ID] Activate a session\n"
1422 " lock-session [ID...] Screen lock one or more sessions\n"
1423 " unlock-session [ID...] Screen unlock one or more sessions\n"
1424 " lock-sessions Screen lock all current sessions\n"
1425 " unlock-sessions Screen unlock all current sessions\n"
1426 " terminate-session ID... Terminate one or more sessions\n"
1427 " kill-session ID... Send signal to processes of a session\n\n"
1429 " list-users List users\n"
1430 " user-status [USER...] Show user status\n"
1431 " show-user [USER...] Show properties of users or the manager\n"
1432 " enable-linger [USER...] Enable linger state of one or more users\n"
1433 " disable-linger [USER...] Disable linger state of one or more users\n"
1434 " terminate-user USER... Terminate all sessions of one or more users\n"
1435 " kill-user USER... Send signal to processes of a user\n\n"
1437 " list-seats List seats\n"
1438 " seat-status [NAME...] Show seat status\n"
1439 " show-seat [NAME...] Show properties of seats or the manager\n"
1440 " attach NAME DEVICE... Attach one or more devices to a seat\n"
1441 " flush-devices Flush all device associations\n"
1442 " terminate-seat NAME... Terminate all sessions on one or more seats\n\n"
1443 "System Commands:\n"
1444 " poweroff Turn off the machine\n"
1445 " reboot Reboot the machine\n"
1446 " suspend Suspend the machine to memory\n"
1447 " hibernate Suspend the machine to disk\n"
1448 " hybrid-sleep Suspend the machine to memory and disk\n"
1449 , program_invocation_short_name);
1454 static int parse_argv(int argc, char *argv[]) {
1457 ARG_VERSION = 0x100,
1461 ARG_NO_ASK_PASSWORD,
1464 static const struct option options[] = {
1465 { "help", no_argument, NULL, 'h' },
1466 { "version", no_argument, NULL, ARG_VERSION },
1467 { "property", required_argument, NULL, 'p' },
1468 { "all", no_argument, NULL, 'a' },
1469 { "full", no_argument, NULL, 'l' },
1470 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
1471 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
1472 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
1473 { "signal", required_argument, NULL, 's' },
1474 { "host", required_argument, NULL, 'H' },
1475 { "machine", required_argument, NULL, 'M' },
1476 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
1477 { "ignore-inhibitors", no_argument, NULL, 'i' },
1478 { "lines", required_argument, NULL, 'n' },
1479 { "output", required_argument, NULL, 'o' },
1488 while ((c = getopt_long(argc, argv, "hp:als:H:M:n:o:i", options, NULL)) >= 0)
1493 help(0, NULL, NULL);
1497 puts(PACKAGE_STRING);
1498 puts(SYSTEMD_FEATURES);
1502 r = strv_extend(&arg_property, optarg);
1506 /* If the user asked for a particular
1507 * property, show it to him, even if it is
1522 if (safe_atou(optarg, &arg_lines) < 0) {
1523 log_error("Failed to parse lines '%s'", optarg);
1530 arg_output = output_mode_from_string(optarg);
1534 if (arg_output < 0) {
1535 log_error("Unknown output '%s'.", optarg);
1541 arg_ignore_inhibitors = true;
1545 arg_no_pager = true;
1552 case ARG_NO_ASK_PASSWORD:
1553 arg_ask_password = false;
1557 arg_kill_who = optarg;
1561 arg_signal = signal_from_string_try_harder(optarg);
1562 if (arg_signal < 0) {
1563 log_error("Failed to parse signal string %s.", optarg);
1569 arg_transport = BUS_TRANSPORT_REMOTE;
1574 arg_transport = BUS_TRANSPORT_MACHINE;
1582 assert_not_reached("Unhandled option");
1588 static int loginctl_main(int argc, char *argv[], sd_bus *bus) {
1590 static const Verb verbs[] = {
1591 { "help", VERB_ANY, VERB_ANY, 0, help },
1592 { "list-sessions", VERB_ANY, 1, VERB_DEFAULT, list_sessions },
1593 { "session-status", VERB_ANY, VERB_ANY, 0, show_session },
1594 { "show-session", VERB_ANY, VERB_ANY, 0, show_session },
1595 { "activate", VERB_ANY, 2, 0, activate },
1596 { "lock-session", VERB_ANY, VERB_ANY, 0, activate },
1597 { "unlock-session", VERB_ANY, VERB_ANY, 0, activate },
1598 { "lock-sessions", VERB_ANY, 1, 0, lock_sessions },
1599 { "unlock-sessions", VERB_ANY, 1, 0, lock_sessions },
1600 { "terminate-session", 2, VERB_ANY, 0, activate },
1601 { "kill-session", 2, VERB_ANY, 0, kill_session },
1602 { "list-users", VERB_ANY, 1, 0, list_users },
1603 { "user-status", VERB_ANY, VERB_ANY, 0, show_user },
1604 { "show-user", VERB_ANY, VERB_ANY, 0, show_user },
1605 { "enable-linger", VERB_ANY, VERB_ANY, 0, enable_linger },
1606 { "disable-linger", VERB_ANY, VERB_ANY, 0, enable_linger },
1607 { "terminate-user", 2, VERB_ANY, 0, terminate_user },
1608 { "kill-user", 2, VERB_ANY, 0, kill_user },
1609 { "list-seats", VERB_ANY, 1, 0, list_seats },
1610 { "seat-status", VERB_ANY, VERB_ANY, 0, show_seat },
1611 { "show-seat", VERB_ANY, VERB_ANY, 0, show_seat },
1612 { "attach", 3, VERB_ANY, 0, attach },
1613 { "flush-devices", VERB_ANY, 1, 0, flush_devices },
1614 { "terminate-seat", 2, VERB_ANY, 0, terminate_seat },
1615 { "poweroff", VERB_ANY, 1, 0, poweroff },
1616 { "reboot", VERB_ANY, 1, 0, reboot },
1617 { "suspend", VERB_ANY, 1, 0, suspend },
1618 { "hibernate", VERB_ANY, 1, 0, hibernate },
1619 { "hybrid-sleep", VERB_ANY, 1, 0, hybrid_sleep },
1623 return dispatch_verb(argc, argv, verbs, bus);
1626 int main(int argc, char *argv[]) {
1627 _cleanup_bus_close_unref_ sd_bus *bus = NULL;
1630 setlocale(LC_ALL, "");
1631 log_parse_environment();
1634 r = parse_argv(argc, argv);
1638 r = bus_open_transport(arg_transport, arg_host, false, &bus);
1640 log_error_errno(r, "Failed to create bus connection: %m");
1644 sd_bus_set_allow_interactive_authorization(bus, arg_ask_password);
1646 r = loginctl_main(argc, argv, bus);
1650 polkit_agent_close();
1652 strv_free(arg_property);
1654 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;