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/>.
30 #include "alloc-util.h"
31 #include "bus-error.h"
33 //#include "cgroup-show.h"
34 #include "cgroup-util.h"
36 //#include "logs-show.h"
39 #include "parse-util.h"
40 #include "process-util.h"
41 #include "signal-util.h"
42 #include "spawn-polkit-agent.h"
44 #include "sysfs-show.h"
45 #include "terminal-util.h"
46 #include "unit-name.h"
47 #include "user-util.h"
51 /// Additional includes for elogind
52 #include "logind-action.h"
53 #include "musl_missing.h"
57 static char **arg_property = NULL;
58 static bool arg_all = false;
59 static bool arg_full = false;
60 static bool arg_no_pager = false;
61 static bool arg_legend = true;
62 static const char *arg_kill_who = NULL;
63 static int arg_signal = SIGTERM;
64 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
65 static char *arg_host = NULL;
66 static bool arg_ask_password = true;
67 static bool arg_ignore_inhibitors = false;
69 static unsigned arg_lines = 10;
70 static OutputMode arg_output = OUTPUT_SHORT;
79 ACTION_CANCEL_SHUTDOWN,
84 static void pager_open_if_enabled(void) {
92 static void polkit_agent_open_if_enabled(void) {
94 /* Open the polkit agent as a child process if necessary */
96 if (!arg_ask_password)
99 if (arg_transport != BUS_TRANSPORT_LOCAL)
105 #if 0 /// UNNEEDED by elogind
106 static OutputFlags get_output_flags(void) {
109 arg_all * OUTPUT_SHOW_ALL |
110 arg_full * OUTPUT_FULL_WIDTH |
111 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
112 on_tty() * OUTPUT_COLOR;
116 static int list_sessions(int argc, char *argv[], void *userdata) {
117 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
118 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
119 const char *id, *user, *seat, *object;
120 sd_bus *bus = userdata;
128 pager_open_if_enabled();
130 r = sd_bus_call_method(
132 "org.freedesktop.login1",
133 "/org/freedesktop/login1",
134 "org.freedesktop.login1.Manager",
139 log_error("Failed to list sessions: %s", bus_error_message(&error, r));
143 r = sd_bus_message_enter_container(reply, 'a', "(susso)");
145 return bus_log_parse_error(r);
148 printf("%10s %10s %-16s %-16s\n", "SESSION", "UID", "USER", "SEAT");
150 while ((r = sd_bus_message_read(reply, "(susso)", &id, &uid, &user, &seat, &object)) > 0) {
151 printf("%10s %10u %-16s %-16s\n", id, (unsigned) uid, user, seat);
155 return bus_log_parse_error(r);
158 printf("\n%u sessions listed.\n", k);
163 static int list_users(int argc, char *argv[], void *userdata) {
164 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
165 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
166 const char *user, *object;
167 sd_bus *bus = userdata;
175 pager_open_if_enabled();
177 r = sd_bus_call_method(
179 "org.freedesktop.login1",
180 "/org/freedesktop/login1",
181 "org.freedesktop.login1.Manager",
186 log_error("Failed to list users: %s", bus_error_message(&error, r));
190 r = sd_bus_message_enter_container(reply, 'a', "(uso)");
192 return bus_log_parse_error(r);
195 printf("%10s %-16s\n", "UID", "USER");
197 while ((r = sd_bus_message_read(reply, "(uso)", &uid, &user, &object)) > 0) {
198 printf("%10u %-16s\n", (unsigned) uid, user);
202 return bus_log_parse_error(r);
205 printf("\n%u users listed.\n", k);
210 static int list_seats(int argc, char *argv[], void *userdata) {
211 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
212 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
213 const char *seat, *object;
214 sd_bus *bus = userdata;
221 pager_open_if_enabled();
223 r = sd_bus_call_method(
225 "org.freedesktop.login1",
226 "/org/freedesktop/login1",
227 "org.freedesktop.login1.Manager",
232 log_error("Failed to list seats: %s", bus_error_message(&error, r));
236 r = sd_bus_message_enter_container(reply, 'a', "(so)");
238 return bus_log_parse_error(r);
241 printf("%-16s\n", "SEAT");
243 while ((r = sd_bus_message_read(reply, "(so)", &seat, &object)) > 0) {
244 printf("%-16s\n", seat);
248 return bus_log_parse_error(r);
251 printf("\n%u seats listed.\n", k);
256 #if 0 /// UNNEEDED by elogind
257 static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit, pid_t leader) {
258 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
259 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
260 _cleanup_free_ char *path = NULL;
268 if (arg_transport != BUS_TRANSPORT_LOCAL)
271 path = unit_dbus_path_from_name(unit);
275 r = sd_bus_get_property(
277 "org.freedesktop.systemd1",
281 &error, &reply, "s");
285 r = sd_bus_message_read(reply, "s", &cgroup);
292 if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup) != 0 && leader <= 0)
301 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t ", c, false, &leader, leader > 0, get_output_flags());
306 typedef struct SessionStatusInfo {
310 struct dual_timestamp timestamp;
327 typedef struct UserStatusInfo {
330 struct dual_timestamp timestamp;
337 typedef struct SeatStatusInfo {
339 char *active_session;
343 static void session_status_info_clear(SessionStatusInfo *info) {
350 free(info->remote_host);
351 free(info->remote_user);
362 static void user_status_info_clear(UserStatusInfo *info) {
366 strv_free(info->sessions);
373 static void seat_status_info_clear(SeatStatusInfo *info) {
376 free(info->active_session);
377 strv_free(info->sessions);
382 static int prop_map_first_of_struct(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
383 const char *contents;
386 r = sd_bus_message_peek_type(m, NULL, &contents);
390 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, contents);
394 if (contents[0] == 's' || contents[0] == 'o') {
396 char **p = (char **) userdata;
398 r = sd_bus_message_read_basic(m, contents[0], &s);
402 r = free_and_strdup(p, s);
406 r = sd_bus_message_read_basic(m, contents[0], userdata);
411 r = sd_bus_message_skip(m, contents+1);
415 r = sd_bus_message_exit_container(m);
422 static int prop_map_sessions_strv(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
429 r = sd_bus_message_enter_container(m, 'a', "(so)");
433 while ((r = sd_bus_message_read(m, "(so)", &name, NULL)) > 0) {
434 r = strv_extend(userdata, name);
441 return sd_bus_message_exit_container(m);
444 static int print_session_status_info(sd_bus *bus, const char *path, bool *new_line) {
446 static const struct bus_properties_map map[] = {
447 { "Id", "s", NULL, offsetof(SessionStatusInfo, id) },
448 { "Name", "s", NULL, offsetof(SessionStatusInfo, name) },
449 { "TTY", "s", NULL, offsetof(SessionStatusInfo, tty) },
450 { "Display", "s", NULL, offsetof(SessionStatusInfo, display) },
451 { "RemoteHost", "s", NULL, offsetof(SessionStatusInfo, remote_host) },
452 { "RemoteUser", "s", NULL, offsetof(SessionStatusInfo, remote_user) },
453 { "Service", "s", NULL, offsetof(SessionStatusInfo, service) },
454 { "Desktop", "s", NULL, offsetof(SessionStatusInfo, desktop) },
455 { "Type", "s", NULL, offsetof(SessionStatusInfo, type) },
456 { "Class", "s", NULL, offsetof(SessionStatusInfo, class) },
457 { "Scope", "s", NULL, offsetof(SessionStatusInfo, scope) },
458 { "State", "s", NULL, offsetof(SessionStatusInfo, state) },
459 { "VTNr", "u", NULL, offsetof(SessionStatusInfo, vtnr) },
460 { "Leader", "u", NULL, offsetof(SessionStatusInfo, leader) },
461 { "Remote", "b", NULL, offsetof(SessionStatusInfo, remote) },
462 { "Timestamp", "t", NULL, offsetof(SessionStatusInfo, timestamp.realtime) },
463 { "TimestampMonotonic", "t", NULL, offsetof(SessionStatusInfo, timestamp.monotonic) },
464 { "User", "(uo)", prop_map_first_of_struct, offsetof(SessionStatusInfo, uid) },
465 { "Seat", "(so)", prop_map_first_of_struct, offsetof(SessionStatusInfo, seat) },
469 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
470 char since2[FORMAT_TIMESTAMP_MAX], *s2;
471 _cleanup_(session_status_info_clear) SessionStatusInfo i = {};
474 r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i);
476 return log_error_errno(r, "Could not get properties: %m");
483 printf("%s - ", strna(i.id));
486 printf("%s (%u)\n", i.name, (unsigned) i.uid);
488 printf("%u\n", (unsigned) i.uid);
490 s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime);
491 s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime);
494 printf("\t Since: %s; %s\n", s2, s1);
496 printf("\t Since: %s\n", s2);
499 _cleanup_free_ char *t = NULL;
501 printf("\t Leader: %u", (unsigned) i.leader);
503 get_process_comm(i.leader, &t);
510 if (!isempty(i.seat)) {
511 printf("\t Seat: %s", i.seat);
514 printf("; vc%u", i.vtnr);
520 printf("\t TTY: %s\n", i.tty);
522 printf("\t Display: %s\n", i.display);
524 if (i.remote_host && i.remote_user)
525 printf("\t Remote: %s@%s\n", i.remote_user, i.remote_host);
526 else if (i.remote_host)
527 printf("\t Remote: %s\n", i.remote_host);
528 else if (i.remote_user)
529 printf("\t Remote: user %s\n", i.remote_user);
531 printf("\t Remote: Yes\n");
534 printf("\t Service: %s", i.service);
537 printf("; type %s", i.type);
540 printf("; class %s", i.class);
544 printf("\t Type: %s", i.type);
547 printf("; class %s", i.class);
551 printf("\t Class: %s\n", i.class);
553 if (!isempty(i.desktop))
554 printf("\t Desktop: %s\n", i.desktop);
557 printf("\t State: %s\n", i.state);
560 printf("\t Unit: %s\n", i.scope);
562 show_unit_cgroup(bus, "org.freedesktop.systemd1.Scope", i.scope, i.leader);
563 if (arg_transport == BUS_TRANSPORT_LOCAL) {
565 show_journal_by_unit(
570 i.timestamp.monotonic,
573 get_output_flags() | OUTPUT_BEGIN_NEWLINE,
574 SD_JOURNAL_LOCAL_ONLY,
585 static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line) {
587 static const struct bus_properties_map map[] = {
588 { "Name", "s", NULL, offsetof(UserStatusInfo, name) },
589 { "Slice", "s", NULL, offsetof(UserStatusInfo, slice) },
590 { "State", "s", NULL, offsetof(UserStatusInfo, state) },
591 { "UID", "u", NULL, offsetof(UserStatusInfo, uid) },
592 { "Timestamp", "t", NULL, offsetof(UserStatusInfo, timestamp.realtime) },
593 { "TimestampMonotonic", "t", NULL, offsetof(UserStatusInfo, timestamp.monotonic) },
594 { "Display", "(so)", prop_map_first_of_struct, offsetof(UserStatusInfo, display) },
595 { "Sessions", "a(so)", prop_map_sessions_strv, offsetof(UserStatusInfo, sessions) },
599 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
600 char since2[FORMAT_TIMESTAMP_MAX], *s2;
601 _cleanup_(user_status_info_clear) UserStatusInfo i = {};
604 r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i);
606 return log_error_errno(r, "Could not get properties: %m");
614 printf("%s (%u)\n", i.name, (unsigned) i.uid);
616 printf("%u\n", (unsigned) i.uid);
618 s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime);
619 s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime);
622 printf("\t Since: %s; %s\n", s2, s1);
624 printf("\t Since: %s\n", s2);
626 if (!isempty(i.state))
627 printf("\t State: %s\n", i.state);
629 if (!strv_isempty(i.sessions)) {
631 printf("\tSessions:");
633 STRV_FOREACH(l, i.sessions) {
634 if (streq_ptr(*l, i.display))
644 printf("\t Unit: %s\n", i.slice);
646 show_unit_cgroup(bus, "org.freedesktop.systemd1.Slice", i.slice, 0);
647 show_journal_by_unit(
652 i.timestamp.monotonic,
655 get_output_flags() | OUTPUT_BEGIN_NEWLINE,
656 SD_JOURNAL_LOCAL_ONLY,
666 static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line) {
668 static const struct bus_properties_map map[] = {
669 { "Id", "s", NULL, offsetof(SeatStatusInfo, id) },
670 { "ActiveSession", "(so)", prop_map_first_of_struct, offsetof(SeatStatusInfo, active_session) },
671 { "Sessions", "a(so)", prop_map_sessions_strv, offsetof(SeatStatusInfo, sessions) },
675 _cleanup_(seat_status_info_clear) SeatStatusInfo i = {};
678 r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i);
680 return log_error_errno(r, "Could not get properties: %m");
687 printf("%s\n", strna(i.id));
689 if (!strv_isempty(i.sessions)) {
691 printf("\tSessions:");
693 STRV_FOREACH(l, i.sessions) {
694 if (streq_ptr(*l, i.active_session))
703 if (arg_transport == BUS_TRANSPORT_LOCAL) {
712 printf("\t Devices:\n");
714 show_sysfs(i.id, "\t\t ", c);
720 static int print_property(const char *name, sd_bus_message *m, const char *contents) {
727 if (arg_property && !strv_find(arg_property, name))
728 /* skip what we didn't read */
729 return sd_bus_message_skip(m, contents);
731 switch (contents[0]) {
733 case SD_BUS_TYPE_STRUCT_BEGIN:
735 if (contents[1] == SD_BUS_TYPE_STRING && STR_IN_SET(name, "Display", "Seat", "ActiveSession")) {
738 r = sd_bus_message_read(m, "(so)", &s, NULL);
740 return bus_log_parse_error(r);
742 if (arg_all || !isempty(s))
743 printf("%s=%s\n", name, s);
747 } else if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "User")) {
750 r = sd_bus_message_read(m, "(uo)", &uid, NULL);
752 return bus_log_parse_error(r);
754 if (!uid_is_valid(uid)) {
755 log_error("Invalid user ID: " UID_FMT, uid);
759 printf("%s=" UID_FMT "\n", name, uid);
766 case SD_BUS_TYPE_ARRAY:
768 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Sessions")) {
772 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(so)");
774 return bus_log_parse_error(r);
778 while ((r = sd_bus_message_read(m, "(so)", &s, NULL)) > 0) {
779 printf("%s%s", space ? " " : "", s);
786 return bus_log_parse_error(r);
788 r = sd_bus_message_exit_container(m);
790 return bus_log_parse_error(r);
798 r = bus_print_property(name, m, arg_all);
800 return bus_log_parse_error(r);
803 r = sd_bus_message_skip(m, contents);
805 return bus_log_parse_error(r);
808 printf("%s=[unprintable]\n", name);
814 static int show_properties(sd_bus *bus, const char *path, bool *new_line) {
815 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
816 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
823 r = sd_bus_call_method(
825 "org.freedesktop.login1",
827 "org.freedesktop.DBus.Properties",
833 return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r));
835 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
837 return bus_log_parse_error(r);
844 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
845 const char *name, *contents;
847 r = sd_bus_message_read(reply, "s", &name);
849 return bus_log_parse_error(r);
851 r = sd_bus_message_peek_type(reply, NULL, &contents);
853 return bus_log_parse_error(r);
855 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
857 return bus_log_parse_error(r);
859 r = print_property(name, reply, contents);
863 r = sd_bus_message_exit_container(reply);
865 return bus_log_parse_error(r);
867 r = sd_bus_message_exit_container(reply);
869 return bus_log_parse_error(r);
872 return bus_log_parse_error(r);
874 r = sd_bus_message_exit_container(reply);
876 return bus_log_parse_error(r);
881 static int show_session(int argc, char *argv[], void *userdata) {
882 bool properties, new_line = false;
883 sd_bus *bus = userdata;
889 properties = !strstr(argv[0], "status");
891 pager_open_if_enabled();
894 /* If not argument is specified inspect the manager
897 return show_properties(bus, "/org/freedesktop/login1", &new_line);
899 /* And in the pretty case, show data of the calling session */
900 return print_session_status_info(bus, "/org/freedesktop/login1/session/self", &new_line);
903 for (i = 1; i < argc; i++) {
904 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
905 _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
906 const char *path = NULL;
908 r = sd_bus_call_method(
910 "org.freedesktop.login1",
911 "/org/freedesktop/login1",
912 "org.freedesktop.login1.Manager",
917 log_error("Failed to get session: %s", bus_error_message(&error, r));
921 r = sd_bus_message_read(reply, "o", &path);
923 return bus_log_parse_error(r);
926 r = show_properties(bus, path, &new_line);
928 r = print_session_status_info(bus, path, &new_line);
937 static int show_user(int argc, char *argv[], void *userdata) {
938 bool properties, new_line = false;
939 sd_bus *bus = userdata;
945 properties = !strstr(argv[0], "status");
947 pager_open_if_enabled();
950 /* If not argument is specified inspect the manager
953 return show_properties(bus, "/org/freedesktop/login1", &new_line);
955 return print_user_status_info(bus, "/org/freedesktop/login1/user/self", &new_line);
958 for (i = 1; i < argc; i++) {
959 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
960 _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
961 const char *path = NULL;
964 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
966 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
968 r = sd_bus_call_method(
970 "org.freedesktop.login1",
971 "/org/freedesktop/login1",
972 "org.freedesktop.login1.Manager",
975 "u", (uint32_t) uid);
977 log_error("Failed to get user: %s", bus_error_message(&error, r));
981 r = sd_bus_message_read(reply, "o", &path);
983 return bus_log_parse_error(r);
986 r = show_properties(bus, path, &new_line);
988 r = print_user_status_info(bus, path, &new_line);
997 static int show_seat(int argc, char *argv[], void *userdata) {
998 bool properties, new_line = false;
999 sd_bus *bus = userdata;
1005 properties = !strstr(argv[0], "status");
1007 pager_open_if_enabled();
1010 /* If not argument is specified inspect the manager
1013 return show_properties(bus, "/org/freedesktop/login1", &new_line);
1015 return print_seat_status_info(bus, "/org/freedesktop/login1/seat/self", &new_line);
1018 for (i = 1; i < argc; i++) {
1019 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1020 _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
1021 const char *path = NULL;
1023 r = sd_bus_call_method(
1025 "org.freedesktop.login1",
1026 "/org/freedesktop/login1",
1027 "org.freedesktop.login1.Manager",
1032 log_error("Failed to get seat: %s", bus_error_message(&error, r));
1036 r = sd_bus_message_read(reply, "o", &path);
1038 return bus_log_parse_error(r);
1041 r = show_properties(bus, path, &new_line);
1043 r = print_seat_status_info(bus, path, &new_line);
1052 static int activate(int argc, char *argv[], void *userdata) {
1053 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1054 sd_bus *bus = userdata;
1055 char *short_argv[3];
1061 polkit_agent_open_if_enabled();
1064 /* No argument? Let's convert this into the empty
1065 * session name, which the calls will then resolve to
1066 * the caller's session. */
1068 short_argv[0] = argv[0];
1069 short_argv[1] = (char*) "";
1070 short_argv[2] = NULL;
1076 for (i = 1; i < argc; i++) {
1078 r = sd_bus_call_method(
1080 "org.freedesktop.login1",
1081 "/org/freedesktop/login1",
1082 "org.freedesktop.login1.Manager",
1083 streq(argv[0], "lock-session") ? "LockSession" :
1084 streq(argv[0], "unlock-session") ? "UnlockSession" :
1085 streq(argv[0], "terminate-session") ? "TerminateSession" :
1090 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
1098 static int kill_session(int argc, char *argv[], void *userdata) {
1099 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1100 sd_bus *bus = userdata;
1106 polkit_agent_open_if_enabled();
1109 arg_kill_who = "all";
1111 for (i = 1; i < argc; i++) {
1113 r = sd_bus_call_method(
1115 "org.freedesktop.login1",
1116 "/org/freedesktop/login1",
1117 "org.freedesktop.login1.Manager",
1120 "ssi", argv[i], arg_kill_who, arg_signal);
1122 log_error("Could not kill session: %s", bus_error_message(&error, -r));
1130 static int enable_linger(int argc, char *argv[], void *userdata) {
1131 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1132 sd_bus *bus = userdata;
1133 char* short_argv[3];
1140 polkit_agent_open_if_enabled();
1142 b = streq(argv[0], "enable-linger");
1145 short_argv[0] = argv[0];
1146 short_argv[1] = (char*) "";
1147 short_argv[2] = NULL;
1152 for (i = 1; i < argc; i++) {
1155 if (isempty(argv[i]))
1158 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
1160 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
1163 r = sd_bus_call_method(
1165 "org.freedesktop.login1",
1166 "/org/freedesktop/login1",
1167 "org.freedesktop.login1.Manager",
1170 "ubb", (uint32_t) uid, b, true);
1172 log_error("Could not enable linger: %s", bus_error_message(&error, -r));
1180 static int terminate_user(int argc, char *argv[], void *userdata) {
1181 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1182 sd_bus *bus = userdata;
1188 polkit_agent_open_if_enabled();
1190 for (i = 1; i < argc; i++) {
1193 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
1195 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
1197 r = sd_bus_call_method(
1199 "org.freedesktop.login1",
1200 "/org/freedesktop/login1",
1201 "org.freedesktop.login1.Manager",
1204 "u", (uint32_t) uid);
1206 log_error("Could not terminate user: %s", bus_error_message(&error, -r));
1214 static int kill_user(int argc, char *argv[], void *userdata) {
1215 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1216 sd_bus *bus = userdata;
1222 polkit_agent_open_if_enabled();
1225 arg_kill_who = "all";
1227 for (i = 1; i < argc; i++) {
1230 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
1232 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
1234 r = sd_bus_call_method(
1236 "org.freedesktop.login1",
1237 "/org/freedesktop/login1",
1238 "org.freedesktop.login1.Manager",
1241 "ui", (uint32_t) uid, arg_signal);
1243 log_error("Could not kill user: %s", bus_error_message(&error, -r));
1251 static int attach(int argc, char *argv[], void *userdata) {
1252 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1253 sd_bus *bus = userdata;
1259 polkit_agent_open_if_enabled();
1261 for (i = 2; i < argc; i++) {
1263 r = sd_bus_call_method(
1265 "org.freedesktop.login1",
1266 "/org/freedesktop/login1",
1267 "org.freedesktop.login1.Manager",
1270 "ssb", argv[1], argv[i], true);
1273 log_error("Could not attach device: %s", bus_error_message(&error, -r));
1281 static int flush_devices(int argc, char *argv[], void *userdata) {
1282 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1283 sd_bus *bus = userdata;
1289 polkit_agent_open_if_enabled();
1291 r = sd_bus_call_method(
1293 "org.freedesktop.login1",
1294 "/org/freedesktop/login1",
1295 "org.freedesktop.login1.Manager",
1300 log_error("Could not flush devices: %s", bus_error_message(&error, -r));
1305 static int lock_sessions(int argc, char *argv[], void *userdata) {
1306 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1307 sd_bus *bus = userdata;
1313 polkit_agent_open_if_enabled();
1315 r = sd_bus_call_method(
1317 "org.freedesktop.login1",
1318 "/org/freedesktop/login1",
1319 "org.freedesktop.login1.Manager",
1320 streq(argv[0], "lock-sessions") ? "LockSessions" : "UnlockSessions",
1324 log_error("Could not lock sessions: %s", bus_error_message(&error, -r));
1329 static int terminate_seat(int argc, char *argv[], void *userdata) {
1330 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1331 sd_bus *bus = userdata;
1337 polkit_agent_open_if_enabled();
1339 for (i = 1; i < argc; i++) {
1341 r = sd_bus_call_method(
1343 "org.freedesktop.login1",
1344 "/org/freedesktop/login1",
1345 "org.freedesktop.login1.Manager",
1350 log_error("Could not terminate seat: %s", bus_error_message(&error, -r));
1358 /* Ask elogind, which might grant access to unprivileged users
1359 * through PolicyKit */
1360 static int reboot_with_logind(sd_bus *bus, enum action a) {
1361 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1364 static const char *table[_ACTION_MAX] = {
1365 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
1366 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
1367 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
1373 polkit_agent_open_if_enabled();
1377 case ACTION_POWEROFF:
1378 method = "PowerOff";
1385 case ACTION_SUSPEND:
1389 case ACTION_HIBERNATE:
1390 method = "Hibernate";
1393 case ACTION_HYBRID_SLEEP:
1394 method = "HybridSleep";
1397 case ACTION_CANCEL_SHUTDOWN:
1398 method = "CancelScheduledShutdown";
1406 r = sd_bus_call_method(
1408 "org.freedesktop.login1",
1409 "/org/freedesktop/login1",
1410 "org.freedesktop.login1.Manager",
1419 log_warning_errno(r, "Failed to set wall message, ignoring: %s",
1420 bus_error_message(&error, r));
1421 sd_bus_error_free(&error);
1426 r = sd_bus_call_method(
1428 "org.freedesktop.login1",
1429 "/org/freedesktop/login1",
1430 "org.freedesktop.login1.Manager",
1434 "b", arg_ask_password);
1436 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
1441 static const struct {
1442 HandleAction action;
1444 } action_table[_ACTION_MAX] = {
1445 [ACTION_POWEROFF] = { HANDLE_POWEROFF, "poweroff", },
1446 [ACTION_REBOOT] = { HANDLE_REBOOT, "reboot", },
1447 [ACTION_SUSPEND] = { HANDLE_SUSPEND, "suspend", },
1448 [ACTION_HIBERNATE] = { HANDLE_HIBERNATE, "hibernate", },
1449 [ACTION_HYBRID_SLEEP] = { HANDLE_HYBRID_SLEEP, "hybrid-sleep" },
1452 static enum action verb_to_action(const char *verb) {
1455 for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
1456 if (streq_ptr(action_table[i].verb, verb))
1459 return _ACTION_INVALID;
1462 static int check_inhibitors(sd_bus *bus, enum action a) {
1463 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1464 _cleanup_strv_free_ char **sessions = NULL;
1465 const char *what, *who, *why, *mode;
1474 if (arg_ignore_inhibitors)
1483 r = sd_bus_call_method(
1485 "org.freedesktop.login1",
1486 "/org/freedesktop/login1",
1487 "org.freedesktop.login1.Manager",
1493 /* If logind is not around, then there are no inhibitors... */
1496 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
1498 return bus_log_parse_error(r);
1500 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
1501 _cleanup_free_ char *comm = NULL, *user = NULL;
1502 _cleanup_strv_free_ char **sv = NULL;
1504 if (!streq(mode, "block"))
1507 sv = strv_split(what, ":");
1511 if ((pid_t) pid < 0)
1512 return log_error_errno(ERANGE, "Bad PID %"PRIu32": %m", pid);
1514 if (!strv_contains(sv,
1515 a == ACTION_POWEROFF ||
1516 a == ACTION_REBOOT ? "shutdown" : "sleep"))
1519 get_process_comm(pid, &comm);
1520 user = uid_to_name(uid);
1522 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
1523 who, (pid_t) pid, strna(comm), strna(user), why);
1528 return bus_log_parse_error(r);
1530 r = sd_bus_message_exit_container(reply);
1532 return bus_log_parse_error(r);
1534 /* Check for current sessions */
1535 sd_get_sessions(&sessions);
1536 STRV_FOREACH(s, sessions) {
1537 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
1539 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
1542 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
1545 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
1548 sd_session_get_tty(*s, &tty);
1549 sd_session_get_seat(*s, &seat);
1550 sd_session_get_service(*s, &service);
1551 user = uid_to_name(uid);
1553 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
1560 log_error("Please retry operation after closing inhibitors and logging out other users.\n"
1561 "Alternatively, ignore inhibitors and users with 'loginctl %s -i'.",
1562 action_table[a].verb);
1567 static int start_special(int argc, char *argv[], void *userdata) {
1568 sd_bus *bus = userdata;
1574 a = verb_to_action(argv[0]);
1576 r = check_inhibitors(bus, a);
1580 /* Now power off actions in chroot environments */
1581 if ((a == ACTION_POWEROFF ||
1582 a == ACTION_REBOOT) &&
1583 (running_in_chroot() > 0) ) {
1584 log_info("Running in chroot, ignoring request.");
1588 /* Switch to cancel shutdown, if a shutdown action was requested,
1589 and the option to cancel it was set: */
1590 if ((a == ACTION_POWEROFF ||
1591 a == ACTION_REBOOT) &&
1592 (arg_action == ACTION_CANCEL_SHUTDOWN))
1593 return reboot_with_logind(bus, arg_action);
1595 /* Otherwise perform requested action */
1596 if (a == ACTION_POWEROFF ||
1597 a == ACTION_REBOOT ||
1598 a == ACTION_SUSPEND ||
1599 a == ACTION_HIBERNATE ||
1600 a == ACTION_HYBRID_SLEEP)
1601 return reboot_with_logind(bus, a);
1606 static int help(int argc, char *argv[], void *userdata) {
1608 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
1609 "Send control commands to or query the login manager.\n\n"
1610 " -h --help Show this help\n"
1611 " --version Show package version\n"
1612 " --no-pager Do not pipe output into a pager\n"
1613 " --no-legend Do not show the headers and footers\n"
1614 " --no-ask-password Don't prompt for password\n"
1615 " -H --host=[USER@]HOST Operate on remote host\n"
1616 " -M --machine=CONTAINER Operate on local container\n"
1617 " -p --property=NAME Show only properties by this name\n"
1618 " -a --all Show all properties, including empty ones\n"
1619 " -l --full Do not ellipsize output\n"
1620 " --kill-who=WHO Who to send signal to\n"
1621 " -s --signal=SIGNAL Which signal to send\n"
1623 " -n --lines=INTEGER Number of journal entries to show\n"
1624 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
1625 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
1627 " -c Cancel a pending shutdown\n"
1628 " -i --ignore-inhibitors When shutting down or sleeping, ignore inhibitors\n"
1629 "Session Commands:\n"
1630 " list-sessions List sessions\n"
1631 " session-status [ID...] Show session status\n"
1632 " show-session [ID...] Show properties of sessions or the manager\n"
1633 " activate [ID] Activate a session\n"
1634 " lock-session [ID...] Screen lock one or more sessions\n"
1635 " unlock-session [ID...] Screen unlock one or more sessions\n"
1636 " lock-sessions Screen lock all current sessions\n"
1637 " unlock-sessions Screen unlock all current sessions\n"
1638 " terminate-session ID... Terminate one or more sessions\n"
1639 " kill-session ID... Send signal to processes of a session\n\n"
1641 " list-users List users\n"
1642 " user-status [USER...] Show user status\n"
1643 " show-user [USER...] Show properties of users or the manager\n"
1644 " enable-linger [USER...] Enable linger state of one or more users\n"
1645 " disable-linger [USER...] Disable linger state of one or more users\n"
1646 " terminate-user USER... Terminate all sessions of one or more users\n"
1647 " kill-user USER... Send signal to processes of a user\n\n"
1649 " list-seats List seats\n"
1650 " seat-status [NAME...] Show seat status\n"
1651 " show-seat [NAME...] Show properties of seats or the manager\n"
1652 " attach NAME DEVICE... Attach one or more devices to a seat\n"
1653 " flush-devices Flush all device associations\n"
1654 " terminate-seat NAME... Terminate all sessions on one or more seats\n"
1655 "System Commands:\n"
1656 " poweroff Turn off the machine\n"
1657 " reboot Reboot the machine\n"
1658 " suspend Suspend the machine to memory\n"
1659 " hibernate Suspend the machine to disk\n"
1660 " hybrid-sleep Suspend the machine to memory and disk\n"
1661 , program_invocation_short_name);
1666 static int parse_argv(int argc, char *argv[]) {
1669 ARG_VERSION = 0x100,
1673 ARG_NO_ASK_PASSWORD,
1676 static const struct option options[] = {
1677 { "help", no_argument, NULL, 'h' },
1678 { "version", no_argument, NULL, ARG_VERSION },
1679 { "property", required_argument, NULL, 'p' },
1680 { "all", no_argument, NULL, 'a' },
1681 { "full", no_argument, NULL, 'l' },
1682 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
1683 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
1684 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
1685 { "signal", required_argument, NULL, 's' },
1686 { "host", required_argument, NULL, 'H' },
1687 { "machine", required_argument, NULL, 'M' },
1688 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
1690 { "lines", required_argument, NULL, 'n' },
1691 { "output", required_argument, NULL, 'o' },
1693 { "ignore-inhibitors", no_argument, NULL, 'i' },
1702 while ((c = getopt_long(argc, argv, "hp:als:H:M:n:o:ci", options, NULL)) >= 0)
1707 help(0, NULL, NULL);
1714 r = strv_extend(&arg_property, optarg);
1718 /* If the user asked for a particular
1719 * property, show it to him, even if it is
1734 if (safe_atou(optarg, &arg_lines) < 0) {
1735 log_error("Failed to parse lines '%s'", optarg);
1741 arg_output = output_mode_from_string(optarg);
1742 if (arg_output < 0) {
1743 log_error("Unknown output '%s'.", optarg);
1749 arg_no_pager = true;
1756 case ARG_NO_ASK_PASSWORD:
1757 arg_ask_password = false;
1761 arg_kill_who = optarg;
1765 arg_signal = signal_from_string_try_harder(optarg);
1766 if (arg_signal < 0) {
1767 log_error("Failed to parse signal string %s.", optarg);
1773 arg_transport = BUS_TRANSPORT_REMOTE;
1778 arg_transport = BUS_TRANSPORT_MACHINE;
1783 arg_action = ACTION_CANCEL_SHUTDOWN;
1787 arg_ignore_inhibitors = true;
1794 assert_not_reached("Unhandled option");
1800 static int loginctl_main(int argc, char *argv[], sd_bus *bus) {
1802 static const Verb verbs[] = {
1803 { "help", VERB_ANY, VERB_ANY, 0, help },
1804 { "list-sessions", VERB_ANY, 1, VERB_DEFAULT, list_sessions },
1805 { "session-status", VERB_ANY, VERB_ANY, 0, show_session },
1806 { "show-session", VERB_ANY, VERB_ANY, 0, show_session },
1807 { "activate", VERB_ANY, 2, 0, activate },
1808 { "lock-session", VERB_ANY, VERB_ANY, 0, activate },
1809 { "unlock-session", VERB_ANY, VERB_ANY, 0, activate },
1810 { "lock-sessions", VERB_ANY, 1, 0, lock_sessions },
1811 { "unlock-sessions", VERB_ANY, 1, 0, lock_sessions },
1812 { "terminate-session", 2, VERB_ANY, 0, activate },
1813 { "kill-session", 2, VERB_ANY, 0, kill_session },
1814 { "list-users", VERB_ANY, 1, 0, list_users },
1815 { "user-status", VERB_ANY, VERB_ANY, 0, show_user },
1816 { "show-user", VERB_ANY, VERB_ANY, 0, show_user },
1817 { "enable-linger", VERB_ANY, VERB_ANY, 0, enable_linger },
1818 { "disable-linger", VERB_ANY, VERB_ANY, 0, enable_linger },
1819 { "terminate-user", 2, VERB_ANY, 0, terminate_user },
1820 { "kill-user", 2, VERB_ANY, 0, kill_user },
1821 { "list-seats", VERB_ANY, 1, 0, list_seats },
1822 { "seat-status", VERB_ANY, VERB_ANY, 0, show_seat },
1823 { "show-seat", VERB_ANY, VERB_ANY, 0, show_seat },
1824 { "attach", 3, VERB_ANY, 0, attach },
1825 { "flush-devices", VERB_ANY, 1, 0, flush_devices },
1826 { "terminate-seat", 2, VERB_ANY, 0, terminate_seat },
1827 { "poweroff", VERB_ANY, 1, 0, start_special },
1828 { "reboot", VERB_ANY, 1, 0, start_special },
1829 { "suspend", VERB_ANY, 1, 0, start_special },
1830 { "hibernate", VERB_ANY, 1, 0, start_special },
1831 { "hybrid-sleep", VERB_ANY, 1, 0, start_special },
1832 { "cancel-shutdown", VERB_ANY, 1, 0, start_special },
1836 return dispatch_verb(argc, argv, verbs, bus);
1839 int main(int argc, char *argv[]) {
1840 _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
1843 setlocale(LC_ALL, "");
1844 elogind_set_program_name(argv[0]);
1845 log_parse_environment();
1848 r = parse_argv(argc, argv);
1852 r = bus_connect_transport(arg_transport, arg_host, false, &bus);
1854 log_error_errno(r, "Failed to create bus connection: %m");
1858 sd_bus_set_allow_interactive_authorization(bus, arg_ask_password);
1860 r = loginctl_main(argc, argv, bus);
1864 polkit_agent_close();
1866 strv_free(arg_property);
1868 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;