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"
48 static char **arg_property = NULL;
49 static bool arg_all = false;
50 static bool arg_full = false;
51 static bool arg_no_pager = false;
52 static bool arg_legend = true;
53 static const char *arg_kill_who = NULL;
54 static int arg_signal = SIGTERM;
55 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
56 static char *arg_host = NULL;
57 static bool arg_ask_password = true;
58 static bool arg_ignore_inhibitors = false;
59 static unsigned arg_lines = 10;
60 static OutputMode arg_output = OUTPUT_SHORT;
62 static void pager_open_if_enabled(void) {
70 static void polkit_agent_open_if_enabled(void) {
72 /* Open the polkit agent as a child process if necessary */
74 if (!arg_ask_password)
77 if (arg_transport != BUS_TRANSPORT_LOCAL)
83 static OutputFlags get_output_flags(void) {
86 arg_all * OUTPUT_SHOW_ALL |
87 arg_full * OUTPUT_FULL_WIDTH |
88 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
89 on_tty() * OUTPUT_COLOR;
92 static int list_sessions(int argc, char *argv[], void *userdata) {
93 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
94 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
95 const char *id, *user, *seat, *object;
96 sd_bus *bus = userdata;
104 pager_open_if_enabled();
106 r = sd_bus_call_method(
108 "org.freedesktop.login1",
109 "/org/freedesktop/login1",
110 "org.freedesktop.login1.Manager",
115 log_error("Failed to list sessions: %s", bus_error_message(&error, r));
119 r = sd_bus_message_enter_container(reply, 'a', "(susso)");
121 return bus_log_parse_error(r);
124 printf("%10s %10s %-16s %-16s\n", "SESSION", "UID", "USER", "SEAT");
126 while ((r = sd_bus_message_read(reply, "(susso)", &id, &uid, &user, &seat, &object)) > 0) {
127 printf("%10s %10u %-16s %-16s\n", id, (unsigned) uid, user, seat);
131 return bus_log_parse_error(r);
134 printf("\n%u sessions listed.\n", k);
139 static int list_users(int argc, char *argv[], void *userdata) {
140 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
141 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
142 const char *user, *object;
143 sd_bus *bus = userdata;
151 pager_open_if_enabled();
153 r = sd_bus_call_method(
155 "org.freedesktop.login1",
156 "/org/freedesktop/login1",
157 "org.freedesktop.login1.Manager",
162 log_error("Failed to list users: %s", bus_error_message(&error, r));
166 r = sd_bus_message_enter_container(reply, 'a', "(uso)");
168 return bus_log_parse_error(r);
171 printf("%10s %-16s\n", "UID", "USER");
173 while ((r = sd_bus_message_read(reply, "(uso)", &uid, &user, &object)) > 0) {
174 printf("%10u %-16s\n", (unsigned) uid, user);
178 return bus_log_parse_error(r);
181 printf("\n%u users listed.\n", k);
186 static int list_seats(int argc, char *argv[], void *userdata) {
187 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
188 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
189 const char *seat, *object;
190 sd_bus *bus = userdata;
197 pager_open_if_enabled();
199 r = sd_bus_call_method(
201 "org.freedesktop.login1",
202 "/org/freedesktop/login1",
203 "org.freedesktop.login1.Manager",
208 log_error("Failed to list seats: %s", bus_error_message(&error, r));
212 r = sd_bus_message_enter_container(reply, 'a', "(so)");
214 return bus_log_parse_error(r);
217 printf("%-16s\n", "SEAT");
219 while ((r = sd_bus_message_read(reply, "(so)", &seat, &object)) > 0) {
220 printf("%-16s\n", seat);
224 return bus_log_parse_error(r);
227 printf("\n%u seats listed.\n", k);
232 static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit, pid_t leader) {
233 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
234 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
235 _cleanup_free_ char *path = NULL;
243 if (arg_transport != BUS_TRANSPORT_LOCAL)
246 path = unit_dbus_path_from_name(unit);
250 r = sd_bus_get_property(
252 "org.freedesktop.systemd1",
256 &error, &reply, "s");
260 r = sd_bus_message_read(reply, "s", &cgroup);
267 if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup, false) != 0 && leader <= 0)
276 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t ", c, false, &leader, leader > 0, get_output_flags());
280 typedef struct SessionStatusInfo {
284 struct dual_timestamp timestamp;
290 const char *remote_host;
291 const char *remote_user;
301 typedef struct UserStatusInfo {
304 struct dual_timestamp timestamp;
311 typedef struct SeatStatusInfo {
313 const char *active_session;
317 static int prop_map_first_of_struct(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
318 const char *contents;
321 r = sd_bus_message_peek_type(m, NULL, &contents);
325 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, contents);
329 if (contents[0] == 's' || contents[0] == 'o') {
331 char **p = (char **) userdata;
333 r = sd_bus_message_read_basic(m, contents[0], &s);
343 r = sd_bus_message_read_basic(m, contents[0], userdata);
348 r = sd_bus_message_skip(m, contents+1);
352 r = sd_bus_message_exit_container(m);
359 static int prop_map_sessions_strv(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
366 r = sd_bus_message_enter_container(m, 'a', "(so)");
370 while ((r = sd_bus_message_read(m, "(so)", &name, NULL)) > 0) {
371 r = strv_extend(userdata, name);
378 return sd_bus_message_exit_container(m);
381 static int print_session_status_info(sd_bus *bus, const char *path, bool *new_line) {
383 static const struct bus_properties_map map[] = {
384 { "Id", "s", NULL, offsetof(SessionStatusInfo, id) },
385 { "Name", "s", NULL, offsetof(SessionStatusInfo, name) },
386 { "TTY", "s", NULL, offsetof(SessionStatusInfo, tty) },
387 { "Display", "s", NULL, offsetof(SessionStatusInfo, display) },
388 { "RemoteHost", "s", NULL, offsetof(SessionStatusInfo, remote_host) },
389 { "RemoteUser", "s", NULL, offsetof(SessionStatusInfo, remote_user) },
390 { "Service", "s", NULL, offsetof(SessionStatusInfo, service) },
391 { "Desktop", "s", NULL, offsetof(SessionStatusInfo, desktop) },
392 { "Type", "s", NULL, offsetof(SessionStatusInfo, type) },
393 { "Class", "s", NULL, offsetof(SessionStatusInfo, class) },
394 { "Scope", "s", NULL, offsetof(SessionStatusInfo, scope) },
395 { "State", "s", NULL, offsetof(SessionStatusInfo, state) },
396 { "VTNr", "u", NULL, offsetof(SessionStatusInfo, vtnr) },
397 { "Leader", "u", NULL, offsetof(SessionStatusInfo, leader) },
398 { "Remote", "b", NULL, offsetof(SessionStatusInfo, remote) },
399 { "Timestamp", "t", NULL, offsetof(SessionStatusInfo, timestamp.realtime) },
400 { "TimestampMonotonic", "t", NULL, offsetof(SessionStatusInfo, timestamp.monotonic) },
401 { "User", "(uo)", prop_map_first_of_struct, offsetof(SessionStatusInfo, uid) },
402 { "Seat", "(so)", prop_map_first_of_struct, offsetof(SessionStatusInfo, seat) },
406 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
407 char since2[FORMAT_TIMESTAMP_MAX], *s2;
408 SessionStatusInfo i = {};
411 r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i);
413 return log_error_errno(r, "Could not get properties: %m");
420 printf("%s - ", strna(i.id));
423 printf("%s (%u)\n", i.name, (unsigned) i.uid);
425 printf("%u\n", (unsigned) i.uid);
427 s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime);
428 s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime);
431 printf("\t Since: %s; %s\n", s2, s1);
433 printf("\t Since: %s\n", s2);
436 _cleanup_free_ char *t = NULL;
438 printf("\t Leader: %u", (unsigned) i.leader);
440 get_process_comm(i.leader, &t);
447 if (!isempty(i.seat)) {
448 printf("\t Seat: %s", i.seat);
451 printf("; vc%u", i.vtnr);
457 printf("\t TTY: %s\n", i.tty);
459 printf("\t Display: %s\n", i.display);
461 if (i.remote_host && i.remote_user)
462 printf("\t Remote: %s@%s\n", i.remote_user, i.remote_host);
463 else if (i.remote_host)
464 printf("\t Remote: %s\n", i.remote_host);
465 else if (i.remote_user)
466 printf("\t Remote: user %s\n", i.remote_user);
468 printf("\t Remote: Yes\n");
471 printf("\t Service: %s", i.service);
474 printf("; type %s", i.type);
477 printf("; class %s", i.class);
481 printf("\t Type: %s", i.type);
484 printf("; class %s", i.class);
488 printf("\t Class: %s\n", i.class);
490 if (!isempty(i.desktop))
491 printf("\t Desktop: %s\n", i.desktop);
494 printf("\t State: %s\n", i.state);
497 printf("\t Unit: %s\n", i.scope);
498 show_unit_cgroup(bus, "org.freedesktop.systemd1.Scope", i.scope, i.leader);
500 if (arg_transport == BUS_TRANSPORT_LOCAL) {
502 show_journal_by_unit(
507 i.timestamp.monotonic,
510 get_output_flags() | OUTPUT_BEGIN_NEWLINE,
511 SD_JOURNAL_LOCAL_ONLY,
521 static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line) {
523 static const struct bus_properties_map map[] = {
524 { "Name", "s", NULL, offsetof(UserStatusInfo, name) },
525 { "Slice", "s", NULL, offsetof(UserStatusInfo, slice) },
526 { "State", "s", NULL, offsetof(UserStatusInfo, state) },
527 { "UID", "u", NULL, offsetof(UserStatusInfo, uid) },
528 { "Timestamp", "t", NULL, offsetof(UserStatusInfo, timestamp.realtime) },
529 { "TimestampMonotonic", "t", NULL, offsetof(UserStatusInfo, timestamp.monotonic) },
530 { "Display", "(so)", prop_map_first_of_struct, offsetof(UserStatusInfo, display) },
531 { "Sessions", "a(so)", prop_map_sessions_strv, offsetof(UserStatusInfo, sessions) },
535 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
536 char since2[FORMAT_TIMESTAMP_MAX], *s2;
537 UserStatusInfo i = {};
540 r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i);
542 log_error_errno(r, "Could not get properties: %m");
552 printf("%s (%u)\n", i.name, (unsigned) i.uid);
554 printf("%u\n", (unsigned) i.uid);
556 s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime);
557 s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime);
560 printf("\t Since: %s; %s\n", s2, s1);
562 printf("\t Since: %s\n", s2);
564 if (!isempty(i.state))
565 printf("\t State: %s\n", i.state);
567 if (!strv_isempty(i.sessions)) {
569 printf("\tSessions:");
571 STRV_FOREACH(l, i.sessions) {
572 if (streq_ptr(*l, i.display))
582 printf("\t Unit: %s\n", i.slice);
583 show_unit_cgroup(bus, "org.freedesktop.systemd1.Slice", i.slice, 0);
585 show_journal_by_unit(
590 i.timestamp.monotonic,
593 get_output_flags() | OUTPUT_BEGIN_NEWLINE,
594 SD_JOURNAL_LOCAL_ONLY,
601 strv_free(i.sessions);
606 static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line) {
608 static const struct bus_properties_map map[] = {
609 { "Id", "s", NULL, offsetof(SeatStatusInfo, id) },
610 { "ActiveSession", "(so)", prop_map_first_of_struct, offsetof(SeatStatusInfo, active_session) },
611 { "Sessions", "a(so)", prop_map_sessions_strv, offsetof(SeatStatusInfo, sessions) },
615 SeatStatusInfo i = {};
618 r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i);
620 log_error_errno(r, "Could not get properties: %m");
629 printf("%s\n", strna(i.id));
631 if (!strv_isempty(i.sessions)) {
633 printf("\tSessions:");
635 STRV_FOREACH(l, i.sessions) {
636 if (streq_ptr(*l, i.active_session))
645 if (arg_transport == BUS_TRANSPORT_LOCAL) {
654 printf("\t Devices:\n");
656 show_sysfs(i.id, "\t\t ", c);
660 strv_free(i.sessions);
665 static int show_properties(sd_bus *bus, const char *path, bool *new_line) {
673 r = bus_print_all_properties(bus, "org.freedesktop.login1", path, arg_property, arg_all);
675 log_error_errno(r, "Could not get properties: %m");
680 static int show_session(int argc, char *argv[], void *userdata) {
681 bool properties, new_line = false;
682 sd_bus *bus = userdata;
688 properties = !strstr(argv[0], "status");
690 pager_open_if_enabled();
693 /* If not argument is specified inspect the manager
696 return show_properties(bus, "/org/freedesktop/login1", &new_line);
698 /* And in the pretty case, show data of the calling session */
699 return print_session_status_info(bus, "/org/freedesktop/login1/session/self", &new_line);
702 for (i = 1; i < argc; i++) {
703 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
704 _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
705 const char *path = NULL;
707 r = sd_bus_call_method(
709 "org.freedesktop.login1",
710 "/org/freedesktop/login1",
711 "org.freedesktop.login1.Manager",
716 log_error("Failed to get session: %s", bus_error_message(&error, r));
720 r = sd_bus_message_read(reply, "o", &path);
722 return bus_log_parse_error(r);
725 r = show_properties(bus, path, &new_line);
727 r = print_session_status_info(bus, path, &new_line);
736 static int show_user(int argc, char *argv[], void *userdata) {
737 bool properties, new_line = false;
738 sd_bus *bus = userdata;
744 properties = !strstr(argv[0], "status");
746 pager_open_if_enabled();
749 /* If not argument is specified inspect the manager
752 return show_properties(bus, "/org/freedesktop/login1", &new_line);
754 return print_user_status_info(bus, "/org/freedesktop/login1/user/self", &new_line);
757 for (i = 1; i < argc; i++) {
758 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
759 _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
760 const char *path = NULL;
763 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
765 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
767 r = sd_bus_call_method(
769 "org.freedesktop.login1",
770 "/org/freedesktop/login1",
771 "org.freedesktop.login1.Manager",
774 "u", (uint32_t) uid);
776 log_error("Failed to get user: %s", bus_error_message(&error, r));
780 r = sd_bus_message_read(reply, "o", &path);
782 return bus_log_parse_error(r);
785 r = show_properties(bus, path, &new_line);
787 r = print_user_status_info(bus, path, &new_line);
796 static int show_seat(int argc, char *argv[], void *userdata) {
797 bool properties, new_line = false;
798 sd_bus *bus = userdata;
804 properties = !strstr(argv[0], "status");
806 pager_open_if_enabled();
809 /* If not argument is specified inspect the manager
812 return show_properties(bus, "/org/freedesktop/login1", &new_line);
814 return print_seat_status_info(bus, "/org/freedesktop/login1/seat/self", &new_line);
817 for (i = 1; i < argc; i++) {
818 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
819 _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
820 const char *path = NULL;
822 r = sd_bus_call_method(
824 "org.freedesktop.login1",
825 "/org/freedesktop/login1",
826 "org.freedesktop.login1.Manager",
831 log_error("Failed to get seat: %s", bus_error_message(&error, r));
835 r = sd_bus_message_read(reply, "o", &path);
837 return bus_log_parse_error(r);
840 r = show_properties(bus, path, &new_line);
842 r = print_seat_status_info(bus, path, &new_line);
851 static int activate(int argc, char *argv[], void *userdata) {
852 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
853 sd_bus *bus = userdata;
860 polkit_agent_open_if_enabled();
863 /* No argument? Let's convert this into the empty
864 * session name, which the calls will then resolve to
865 * the caller's session. */
867 short_argv[0] = argv[0];
868 short_argv[1] = (char*) "";
869 short_argv[2] = NULL;
875 for (i = 1; i < argc; i++) {
877 r = sd_bus_call_method(
879 "org.freedesktop.login1",
880 "/org/freedesktop/login1",
881 "org.freedesktop.login1.Manager",
882 streq(argv[0], "lock-session") ? "LockSession" :
883 streq(argv[0], "unlock-session") ? "UnlockSession" :
884 streq(argv[0], "terminate-session") ? "TerminateSession" :
889 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
897 static int kill_session(int argc, char *argv[], void *userdata) {
898 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
899 sd_bus *bus = userdata;
905 polkit_agent_open_if_enabled();
908 arg_kill_who = "all";
910 for (i = 1; i < argc; i++) {
912 r = sd_bus_call_method(
914 "org.freedesktop.login1",
915 "/org/freedesktop/login1",
916 "org.freedesktop.login1.Manager",
919 "ssi", argv[i], arg_kill_who, arg_signal);
921 log_error("Could not kill session: %s", bus_error_message(&error, -r));
929 static int enable_linger(int argc, char *argv[], void *userdata) {
930 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
931 sd_bus *bus = userdata;
939 polkit_agent_open_if_enabled();
941 b = streq(argv[0], "enable-linger");
944 short_argv[0] = argv[0];
945 short_argv[1] = (char*) "";
946 short_argv[2] = NULL;
951 for (i = 1; i < argc; i++) {
954 if (isempty(argv[i]))
957 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
959 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
962 r = sd_bus_call_method(
964 "org.freedesktop.login1",
965 "/org/freedesktop/login1",
966 "org.freedesktop.login1.Manager",
969 "ubb", (uint32_t) uid, b, true);
971 log_error("Could not enable linger: %s", bus_error_message(&error, -r));
979 static int terminate_user(int argc, char *argv[], void *userdata) {
980 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
981 sd_bus *bus = userdata;
987 polkit_agent_open_if_enabled();
989 for (i = 1; i < argc; i++) {
992 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
994 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
996 r = sd_bus_call_method(
998 "org.freedesktop.login1",
999 "/org/freedesktop/login1",
1000 "org.freedesktop.login1.Manager",
1003 "u", (uint32_t) uid);
1005 log_error("Could not terminate user: %s", bus_error_message(&error, -r));
1013 static int kill_user(int argc, char *argv[], void *userdata) {
1014 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1015 sd_bus *bus = userdata;
1021 polkit_agent_open_if_enabled();
1024 arg_kill_who = "all";
1026 for (i = 1; i < argc; i++) {
1029 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
1031 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
1033 r = sd_bus_call_method(
1035 "org.freedesktop.login1",
1036 "/org/freedesktop/login1",
1037 "org.freedesktop.login1.Manager",
1040 "ui", (uint32_t) uid, arg_signal);
1042 log_error("Could not kill user: %s", bus_error_message(&error, -r));
1050 static int attach(int argc, char *argv[], void *userdata) {
1051 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1052 sd_bus *bus = userdata;
1058 polkit_agent_open_if_enabled();
1060 for (i = 2; i < argc; i++) {
1062 r = sd_bus_call_method(
1064 "org.freedesktop.login1",
1065 "/org/freedesktop/login1",
1066 "org.freedesktop.login1.Manager",
1069 "ssb", argv[1], argv[i], true);
1072 log_error("Could not attach device: %s", bus_error_message(&error, -r));
1080 static int flush_devices(int argc, char *argv[], void *userdata) {
1081 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1082 sd_bus *bus = userdata;
1088 polkit_agent_open_if_enabled();
1090 r = sd_bus_call_method(
1092 "org.freedesktop.login1",
1093 "/org/freedesktop/login1",
1094 "org.freedesktop.login1.Manager",
1099 log_error("Could not flush devices: %s", bus_error_message(&error, -r));
1104 static int lock_sessions(int argc, char *argv[], void *userdata) {
1105 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1106 sd_bus *bus = userdata;
1112 polkit_agent_open_if_enabled();
1114 r = sd_bus_call_method(
1116 "org.freedesktop.login1",
1117 "/org/freedesktop/login1",
1118 "org.freedesktop.login1.Manager",
1119 streq(argv[0], "lock-sessions") ? "LockSessions" : "UnlockSessions",
1123 log_error("Could not lock sessions: %s", bus_error_message(&error, -r));
1128 static int terminate_seat(int argc, char *argv[], void *userdata) {
1129 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1130 sd_bus *bus = userdata;
1136 polkit_agent_open_if_enabled();
1138 for (i = 1; i < argc; i++) {
1140 r = sd_bus_call_method(
1142 "org.freedesktop.login1",
1143 "/org/freedesktop/login1",
1144 "org.freedesktop.login1.Manager",
1149 log_error("Could not terminate seat: %s", bus_error_message(&error, -r));
1157 static int check_inhibitors(sd_bus *bus, const char *verb, const char *inhibit_what) {
1158 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1159 _cleanup_strv_free_ char **sessions = NULL;
1160 const char *what, *who, *why, *mode;
1168 if (arg_ignore_inhibitors)
1177 r = sd_bus_call_method(
1179 "org.freedesktop.login1",
1180 "/org/freedesktop/login1",
1181 "org.freedesktop.login1.Manager",
1187 /* If logind is not around, then there are no inhibitors... */
1190 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
1192 return bus_log_parse_error(r);
1194 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
1195 _cleanup_free_ char *comm = NULL, *user = NULL;
1196 _cleanup_strv_free_ char **sv = NULL;
1198 if (!streq(mode, "block"))
1201 sv = strv_split(what, ":");
1205 if (!strv_contains(sv, inhibit_what))
1208 get_process_comm(pid, &comm);
1209 user = uid_to_name(uid);
1211 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
1212 who, pid, strna(comm), strna(user), why);
1217 return bus_log_parse_error(r);
1219 r = sd_bus_message_exit_container(reply);
1221 return bus_log_parse_error(r);
1223 /* Check for current sessions */
1224 sd_get_sessions(&sessions);
1225 STRV_FOREACH(s, sessions) {
1226 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
1228 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
1231 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
1234 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
1237 sd_session_get_tty(*s, &tty);
1238 sd_session_get_seat(*s, &seat);
1239 sd_session_get_service(*s, &service);
1240 user = uid_to_name(uid);
1242 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
1249 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'loginctl %s -i'.", verb);
1254 static int poweroff(int argc, char *argv[], void *userdata) {
1255 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1256 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1257 sd_bus *bus = userdata;
1262 r = check_inhibitors(bus, "poweroff", "shutdown");
1266 polkit_agent_open_if_enabled();
1268 r = sd_bus_call_method(
1270 "org.freedesktop.login1",
1271 "/org/freedesktop/login1",
1272 "org.freedesktop.login1.Manager",
1276 "b", arg_ask_password);
1278 log_error("Failed to power off: %s", bus_error_message(&error, r));
1283 static int reboot(int argc, char *argv[], void *userdata) {
1284 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1285 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1286 sd_bus *bus = userdata;
1291 r = check_inhibitors(bus, "reboot", "shutdown");
1295 polkit_agent_open_if_enabled();
1297 r = sd_bus_call_method(
1299 "org.freedesktop.login1",
1300 "/org/freedesktop/login1",
1301 "org.freedesktop.login1.Manager",
1305 "b", arg_ask_password);
1307 log_error("Failed to reboot: %s", bus_error_message(&error, r));
1312 static int suspend(int argc, char *argv[], void *userdata) {
1313 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1314 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1315 sd_bus *bus = userdata;
1320 r = check_inhibitors(bus, "suspend", "sleep");
1324 polkit_agent_open_if_enabled();
1326 r = sd_bus_call_method(
1328 "org.freedesktop.login1",
1329 "/org/freedesktop/login1",
1330 "org.freedesktop.login1.Manager",
1334 "b", arg_ask_password);
1336 log_error("Failed to suspend: %s", bus_error_message(&error, r));
1341 static int hibernate(int argc, char *argv[], void *userdata) {
1342 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1343 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1344 sd_bus *bus = userdata;
1349 r = check_inhibitors(bus, "hibernate", "sleep");
1353 polkit_agent_open_if_enabled();
1355 r = sd_bus_call_method(
1357 "org.freedesktop.login1",
1358 "/org/freedesktop/login1",
1359 "org.freedesktop.login1.Manager",
1363 "b", arg_ask_password);
1365 log_error("Failed to hibernate: %s", bus_error_message(&error, r));
1370 static int hybrid_sleep(int argc, char *argv[], void *userdata) {
1371 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1372 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1373 sd_bus *bus = userdata;
1378 r = check_inhibitors(bus, "hybrid-sleep", "sleep");
1382 polkit_agent_open_if_enabled();
1384 r = sd_bus_call_method(
1386 "org.freedesktop.login1",
1387 "/org/freedesktop/login1",
1388 "org.freedesktop.login1.Manager",
1392 "b", arg_ask_password);
1394 log_error("Failed to hybrid sleep: %s", bus_error_message(&error, r));
1399 static int help(int argc, char *argv[], void *userdata) {
1401 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
1402 "Send control commands to or query the login manager.\n\n"
1403 " -h --help Show this help\n"
1404 " --version Show package version\n"
1405 " --no-pager Do not pipe output into a pager\n"
1406 " --no-legend Do not show the headers and footers\n"
1407 " --no-ask-password Don't prompt for password\n"
1408 " -i --ignore-inhibitors Ignore inhibitors when suspending or shutting down\n"
1409 " -H --host=[USER@]HOST Operate on remote host\n"
1410 " -M --machine=CONTAINER Operate on local container\n"
1411 " -p --property=NAME Show only properties by this name\n"
1412 " -a --all Show all properties, including empty ones\n"
1413 " -l --full Do not ellipsize output\n"
1414 " --kill-who=WHO Who to send signal to\n"
1415 " -s --signal=SIGNAL Which signal to send\n"
1416 " -n --lines=INTEGER Number of journal entries to show\n"
1417 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
1418 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
1419 "Session Commands:\n"
1420 " list-sessions List sessions\n"
1421 " session-status [ID...] Show session status\n"
1422 " show-session [ID...] Show properties of sessions or the manager\n"
1423 " activate [ID] Activate a session\n"
1424 " lock-session [ID...] Screen lock one or more sessions\n"
1425 " unlock-session [ID...] Screen unlock one or more sessions\n"
1426 " lock-sessions Screen lock all current sessions\n"
1427 " unlock-sessions Screen unlock all current sessions\n"
1428 " terminate-session ID... Terminate one or more sessions\n"
1429 " kill-session ID... Send signal to processes of a session\n\n"
1431 " list-users List users\n"
1432 " user-status [USER...] Show user status\n"
1433 " show-user [USER...] Show properties of users or the manager\n"
1434 " enable-linger [USER...] Enable linger state of one or more users\n"
1435 " disable-linger [USER...] Disable linger state of one or more users\n"
1436 " terminate-user USER... Terminate all sessions of one or more users\n"
1437 " kill-user USER... Send signal to processes of a user\n\n"
1439 " list-seats List seats\n"
1440 " seat-status [NAME...] Show seat status\n"
1441 " show-seat [NAME...] Show properties of seats or the manager\n"
1442 " attach NAME DEVICE... Attach one or more devices to a seat\n"
1443 " flush-devices Flush all device associations\n"
1444 " terminate-seat NAME... Terminate all sessions on one or more seats\n\n"
1445 "System Commands:\n"
1446 " poweroff Turn off the machine\n"
1447 " reboot Reboot the machine\n"
1448 " suspend Suspend the machine to memory\n"
1449 " hibernate Suspend the machine to disk\n"
1450 " hybrid-sleep Suspend the machine to memory and disk\n"
1451 , program_invocation_short_name);
1456 static int parse_argv(int argc, char *argv[]) {
1459 ARG_VERSION = 0x100,
1463 ARG_NO_ASK_PASSWORD,
1466 static const struct option options[] = {
1467 { "help", no_argument, NULL, 'h' },
1468 { "version", no_argument, NULL, ARG_VERSION },
1469 { "property", required_argument, NULL, 'p' },
1470 { "all", no_argument, NULL, 'a' },
1471 { "full", no_argument, NULL, 'l' },
1472 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
1473 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
1474 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
1475 { "signal", required_argument, NULL, 's' },
1476 { "host", required_argument, NULL, 'H' },
1477 { "machine", required_argument, NULL, 'M' },
1478 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
1479 { "ignore-inhibitors", no_argument, NULL, 'i' },
1480 { "lines", required_argument, NULL, 'n' },
1481 { "output", required_argument, NULL, 'o' },
1490 while ((c = getopt_long(argc, argv, "hp:als:H:M:n:o:i", options, NULL)) >= 0)
1495 help(0, NULL, NULL);
1499 puts(PACKAGE_STRING);
1500 puts(SYSTEMD_FEATURES);
1504 r = strv_extend(&arg_property, optarg);
1508 /* If the user asked for a particular
1509 * property, show it to him, even if it is
1524 if (safe_atou(optarg, &arg_lines) < 0) {
1525 log_error("Failed to parse lines '%s'", optarg);
1532 arg_output = output_mode_from_string(optarg);
1536 if (arg_output < 0) {
1537 log_error("Unknown output '%s'.", optarg);
1543 arg_ignore_inhibitors = true;
1547 arg_no_pager = true;
1554 case ARG_NO_ASK_PASSWORD:
1555 arg_ask_password = false;
1559 arg_kill_who = optarg;
1563 arg_signal = signal_from_string_try_harder(optarg);
1564 if (arg_signal < 0) {
1565 log_error("Failed to parse signal string %s.", optarg);
1571 arg_transport = BUS_TRANSPORT_REMOTE;
1576 arg_transport = BUS_TRANSPORT_MACHINE;
1584 assert_not_reached("Unhandled option");
1590 static int loginctl_main(int argc, char *argv[], sd_bus *bus) {
1592 static const Verb verbs[] = {
1593 { "help", VERB_ANY, VERB_ANY, 0, help },
1594 { "list-sessions", VERB_ANY, 1, VERB_DEFAULT, list_sessions },
1595 { "session-status", VERB_ANY, VERB_ANY, 0, show_session },
1596 { "show-session", VERB_ANY, VERB_ANY, 0, show_session },
1597 { "activate", VERB_ANY, 2, 0, activate },
1598 { "lock-session", VERB_ANY, VERB_ANY, 0, activate },
1599 { "unlock-session", VERB_ANY, VERB_ANY, 0, activate },
1600 { "lock-sessions", VERB_ANY, 1, 0, lock_sessions },
1601 { "unlock-sessions", VERB_ANY, 1, 0, lock_sessions },
1602 { "terminate-session", 2, VERB_ANY, 0, activate },
1603 { "kill-session", 2, VERB_ANY, 0, kill_session },
1604 { "list-users", VERB_ANY, 1, 0, list_users },
1605 { "user-status", VERB_ANY, VERB_ANY, 0, show_user },
1606 { "show-user", VERB_ANY, VERB_ANY, 0, show_user },
1607 { "enable-linger", VERB_ANY, VERB_ANY, 0, enable_linger },
1608 { "disable-linger", VERB_ANY, VERB_ANY, 0, enable_linger },
1609 { "terminate-user", 2, VERB_ANY, 0, terminate_user },
1610 { "kill-user", 2, VERB_ANY, 0, kill_user },
1611 { "list-seats", VERB_ANY, 1, 0, list_seats },
1612 { "seat-status", VERB_ANY, VERB_ANY, 0, show_seat },
1613 { "show-seat", VERB_ANY, VERB_ANY, 0, show_seat },
1614 { "attach", 3, VERB_ANY, 0, attach },
1615 { "flush-devices", VERB_ANY, 1, 0, flush_devices },
1616 { "terminate-seat", 2, VERB_ANY, 0, terminate_seat },
1617 { "poweroff", VERB_ANY, 1, 0, poweroff },
1618 { "reboot", VERB_ANY, 1, 0, reboot },
1619 { "suspend", VERB_ANY, 1, 0, suspend },
1620 { "hibernate", VERB_ANY, 1, 0, hibernate },
1621 { "hybrid-sleep", VERB_ANY, 1, 0, hybrid_sleep },
1625 return dispatch_verb(argc, argv, verbs, bus);
1628 int main(int argc, char *argv[]) {
1629 _cleanup_bus_close_unref_ sd_bus *bus = NULL;
1632 setlocale(LC_ALL, "");
1633 log_parse_environment();
1636 r = parse_argv(argc, argv);
1640 r = bus_open_transport(arg_transport, arg_host, false, &bus);
1642 log_error_errno(r, "Failed to create bus connection: %m");
1646 sd_bus_set_allow_interactive_authorization(bus, arg_ask_password);
1648 r = loginctl_main(argc, argv, bus);
1652 polkit_agent_close();
1654 strv_free(arg_property);
1656 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;