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 "bus-error.h"
37 #include "unit-name.h"
38 #include "sysfs-show.h"
39 #include "logs-show.h"
40 #include "cgroup-show.h"
41 #include "cgroup-util.h"
42 #include "spawn-polkit-agent.h"
45 static char **arg_property = NULL;
46 static bool arg_all = false;
47 static bool arg_full = false;
48 static bool arg_no_pager = false;
49 static bool arg_legend = true;
50 static const char *arg_kill_who = NULL;
51 static int arg_signal = SIGTERM;
52 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
53 static char *arg_host = NULL;
54 static bool arg_ask_password = true;
55 static unsigned arg_lines = 10;
56 static OutputMode arg_output = OUTPUT_SHORT;
58 static void pager_open_if_enabled(void) {
66 static void polkit_agent_open_if_enabled(void) {
68 /* Open the polkit agent as a child process if necessary */
70 if (!arg_ask_password)
73 if (arg_transport != BUS_TRANSPORT_LOCAL)
79 static OutputFlags get_output_flags(void) {
82 arg_all * OUTPUT_SHOW_ALL |
83 arg_full * OUTPUT_FULL_WIDTH |
84 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
85 on_tty() * OUTPUT_COLOR;
88 static int list_sessions(int argc, char *argv[], void *userdata) {
89 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
90 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
91 const char *id, *user, *seat, *object;
92 sd_bus *bus = userdata;
100 pager_open_if_enabled();
102 r = sd_bus_call_method(
104 "org.freedesktop.login1",
105 "/org/freedesktop/login1",
106 "org.freedesktop.login1.Manager",
111 log_error("Failed to list sessions: %s", bus_error_message(&error, r));
115 r = sd_bus_message_enter_container(reply, 'a', "(susso)");
117 return bus_log_parse_error(r);
120 printf("%10s %10s %-16s %-16s\n", "SESSION", "UID", "USER", "SEAT");
122 while ((r = sd_bus_message_read(reply, "(susso)", &id, &uid, &user, &seat, &object)) > 0) {
123 printf("%10s %10u %-16s %-16s\n", id, (unsigned) uid, user, seat);
127 return bus_log_parse_error(r);
130 printf("\n%u sessions listed.\n", k);
135 static int list_users(int argc, char *argv[], void *userdata) {
136 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
137 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
138 const char *user, *object;
139 sd_bus *bus = userdata;
147 pager_open_if_enabled();
149 r = sd_bus_call_method(
151 "org.freedesktop.login1",
152 "/org/freedesktop/login1",
153 "org.freedesktop.login1.Manager",
158 log_error("Failed to list users: %s", bus_error_message(&error, r));
162 r = sd_bus_message_enter_container(reply, 'a', "(uso)");
164 return bus_log_parse_error(r);
167 printf("%10s %-16s\n", "UID", "USER");
169 while ((r = sd_bus_message_read(reply, "(uso)", &uid, &user, &object)) > 0) {
170 printf("%10u %-16s\n", (unsigned) uid, user);
174 return bus_log_parse_error(r);
177 printf("\n%u users listed.\n", k);
182 static int list_seats(int argc, char *argv[], void *userdata) {
183 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
184 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
185 const char *seat, *object;
186 sd_bus *bus = userdata;
193 pager_open_if_enabled();
195 r = sd_bus_call_method(
197 "org.freedesktop.login1",
198 "/org/freedesktop/login1",
199 "org.freedesktop.login1.Manager",
204 log_error("Failed to list seats: %s", bus_error_message(&error, r));
208 r = sd_bus_message_enter_container(reply, 'a', "(so)");
210 return bus_log_parse_error(r);
213 printf("%-16s\n", "SEAT");
215 while ((r = sd_bus_message_read(reply, "(so)", &seat, &object)) > 0) {
216 printf("%-16s\n", seat);
220 return bus_log_parse_error(r);
223 printf("\n%u seats listed.\n", k);
228 static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit, pid_t leader) {
229 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
230 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
231 _cleanup_free_ char *path = NULL;
239 if (arg_transport != BUS_TRANSPORT_LOCAL)
242 path = unit_dbus_path_from_name(unit);
246 r = sd_bus_get_property(
248 "org.freedesktop.systemd1",
252 &error, &reply, "s");
256 r = sd_bus_message_read(reply, "s", &cgroup);
263 if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup, false) != 0 && leader <= 0)
272 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t ", c, false, &leader, leader > 0, get_output_flags());
276 typedef struct SessionStatusInfo {
280 struct dual_timestamp timestamp;
286 const char *remote_host;
287 const char *remote_user;
297 typedef struct UserStatusInfo {
300 struct dual_timestamp timestamp;
307 typedef struct SeatStatusInfo {
309 const char *active_session;
313 static int prop_map_first_of_struct(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
314 const char *contents;
317 r = sd_bus_message_peek_type(m, NULL, &contents);
321 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, contents);
325 if (contents[0] == 's' || contents[0] == 'o') {
327 char **p = (char **) userdata;
329 r = sd_bus_message_read_basic(m, contents[0], &s);
339 r = sd_bus_message_read_basic(m, contents[0], userdata);
344 r = sd_bus_message_skip(m, contents+1);
348 r = sd_bus_message_exit_container(m);
355 static int prop_map_sessions_strv(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
362 r = sd_bus_message_enter_container(m, 'a', "(so)");
366 while ((r = sd_bus_message_read(m, "(so)", &name, NULL)) > 0) {
367 r = strv_extend(userdata, name);
374 return sd_bus_message_exit_container(m);
377 static int print_session_status_info(sd_bus *bus, const char *path, bool *new_line) {
379 static const struct bus_properties_map map[] = {
380 { "Id", "s", NULL, offsetof(SessionStatusInfo, id) },
381 { "Name", "s", NULL, offsetof(SessionStatusInfo, name) },
382 { "TTY", "s", NULL, offsetof(SessionStatusInfo, tty) },
383 { "Display", "s", NULL, offsetof(SessionStatusInfo, display) },
384 { "RemoteHost", "s", NULL, offsetof(SessionStatusInfo, remote_host) },
385 { "RemoteUser", "s", NULL, offsetof(SessionStatusInfo, remote_user) },
386 { "Service", "s", NULL, offsetof(SessionStatusInfo, service) },
387 { "Desktop", "s", NULL, offsetof(SessionStatusInfo, desktop) },
388 { "Type", "s", NULL, offsetof(SessionStatusInfo, type) },
389 { "Class", "s", NULL, offsetof(SessionStatusInfo, class) },
390 { "Scope", "s", NULL, offsetof(SessionStatusInfo, scope) },
391 { "State", "s", NULL, offsetof(SessionStatusInfo, state) },
392 { "VTNr", "u", NULL, offsetof(SessionStatusInfo, vtnr) },
393 { "Leader", "u", NULL, offsetof(SessionStatusInfo, leader) },
394 { "Remote", "b", NULL, offsetof(SessionStatusInfo, remote) },
395 { "Timestamp", "t", NULL, offsetof(SessionStatusInfo, timestamp.realtime) },
396 { "TimestampMonotonic", "t", NULL, offsetof(SessionStatusInfo, timestamp.monotonic) },
397 { "User", "(uo)", prop_map_first_of_struct, offsetof(SessionStatusInfo, uid) },
398 { "Seat", "(so)", prop_map_first_of_struct, offsetof(SessionStatusInfo, seat) },
402 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
403 char since2[FORMAT_TIMESTAMP_MAX], *s2;
404 SessionStatusInfo i = {};
407 r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i);
409 return log_error_errno(r, "Could not get properties: %m");
416 printf("%s - ", strna(i.id));
419 printf("%s (%u)\n", i.name, (unsigned) i.uid);
421 printf("%u\n", (unsigned) i.uid);
423 s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime);
424 s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime);
427 printf("\t Since: %s; %s\n", s2, s1);
429 printf("\t Since: %s\n", s2);
432 _cleanup_free_ char *t = NULL;
434 printf("\t Leader: %u", (unsigned) i.leader);
436 get_process_comm(i.leader, &t);
443 if (!isempty(i.seat)) {
444 printf("\t Seat: %s", i.seat);
447 printf("; vc%u", i.vtnr);
453 printf("\t TTY: %s\n", i.tty);
455 printf("\t Display: %s\n", i.display);
457 if (i.remote_host && i.remote_user)
458 printf("\t Remote: %s@%s\n", i.remote_user, i.remote_host);
459 else if (i.remote_host)
460 printf("\t Remote: %s\n", i.remote_host);
461 else if (i.remote_user)
462 printf("\t Remote: user %s\n", i.remote_user);
464 printf("\t Remote: Yes\n");
467 printf("\t Service: %s", i.service);
470 printf("; type %s", i.type);
473 printf("; class %s", i.class);
477 printf("\t Type: %s", i.type);
480 printf("; class %s", i.class);
484 printf("\t Class: %s\n", i.class);
486 if (!isempty(i.desktop))
487 printf("\t Desktop: %s\n", i.desktop);
490 printf("\t State: %s\n", i.state);
493 printf("\t Unit: %s\n", i.scope);
494 show_unit_cgroup(bus, "org.freedesktop.systemd1.Scope", i.scope, i.leader);
496 if (arg_transport == BUS_TRANSPORT_LOCAL) {
498 show_journal_by_unit(
503 i.timestamp.monotonic,
506 get_output_flags() | OUTPUT_BEGIN_NEWLINE,
507 SD_JOURNAL_LOCAL_ONLY,
517 static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line) {
519 static const struct bus_properties_map map[] = {
520 { "Name", "s", NULL, offsetof(UserStatusInfo, name) },
521 { "Slice", "s", NULL, offsetof(UserStatusInfo, slice) },
522 { "State", "s", NULL, offsetof(UserStatusInfo, state) },
523 { "UID", "u", NULL, offsetof(UserStatusInfo, uid) },
524 { "Timestamp", "t", NULL, offsetof(UserStatusInfo, timestamp.realtime) },
525 { "TimestampMonotonic", "t", NULL, offsetof(UserStatusInfo, timestamp.monotonic) },
526 { "Display", "(so)", prop_map_first_of_struct, offsetof(UserStatusInfo, display) },
527 { "Sessions", "a(so)", prop_map_sessions_strv, offsetof(UserStatusInfo, sessions) },
531 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
532 char since2[FORMAT_TIMESTAMP_MAX], *s2;
533 UserStatusInfo i = {};
536 r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i);
538 log_error_errno(r, "Could not get properties: %m");
548 printf("%s (%u)\n", i.name, (unsigned) i.uid);
550 printf("%u\n", (unsigned) i.uid);
552 s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime);
553 s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime);
556 printf("\t Since: %s; %s\n", s2, s1);
558 printf("\t Since: %s\n", s2);
560 if (!isempty(i.state))
561 printf("\t State: %s\n", i.state);
563 if (!strv_isempty(i.sessions)) {
565 printf("\tSessions:");
567 STRV_FOREACH(l, i.sessions) {
568 if (streq_ptr(*l, i.display))
578 printf("\t Unit: %s\n", i.slice);
579 show_unit_cgroup(bus, "org.freedesktop.systemd1.Slice", i.slice, 0);
581 show_journal_by_unit(
586 i.timestamp.monotonic,
589 get_output_flags() | OUTPUT_BEGIN_NEWLINE,
590 SD_JOURNAL_LOCAL_ONLY,
597 strv_free(i.sessions);
602 static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line) {
604 static const struct bus_properties_map map[] = {
605 { "Id", "s", NULL, offsetof(SeatStatusInfo, id) },
606 { "ActiveSession", "(so)", prop_map_first_of_struct, offsetof(SeatStatusInfo, active_session) },
607 { "Sessions", "a(so)", prop_map_sessions_strv, offsetof(SeatStatusInfo, sessions) },
611 SeatStatusInfo i = {};
614 r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i);
616 log_error_errno(r, "Could not get properties: %m");
625 printf("%s\n", strna(i.id));
627 if (!strv_isempty(i.sessions)) {
629 printf("\tSessions:");
631 STRV_FOREACH(l, i.sessions) {
632 if (streq_ptr(*l, i.active_session))
641 if (arg_transport == BUS_TRANSPORT_LOCAL) {
650 printf("\t Devices:\n");
652 show_sysfs(i.id, "\t\t ", c);
656 strv_free(i.sessions);
661 static int show_properties(sd_bus *bus, const char *path, bool *new_line) {
669 r = bus_print_all_properties(bus, "org.freedesktop.login1", path, arg_property, arg_all);
671 log_error_errno(r, "Could not get properties: %m");
676 static int show_session(int argc, char *argv[], void *userdata) {
677 bool properties, new_line = false;
678 sd_bus *bus = userdata;
684 properties = !strstr(argv[0], "status");
686 pager_open_if_enabled();
689 /* If not argument is specified inspect the manager
692 return show_properties(bus, "/org/freedesktop/login1", &new_line);
694 /* And in the pretty case, show data of the calling session */
695 return print_session_status_info(bus, "/org/freedesktop/login1/session/self", &new_line);
698 for (i = 1; i < argc; i++) {
699 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
700 _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
701 const char *path = NULL;
703 r = sd_bus_call_method(
705 "org.freedesktop.login1",
706 "/org/freedesktop/login1",
707 "org.freedesktop.login1.Manager",
712 log_error("Failed to get session: %s", bus_error_message(&error, r));
716 r = sd_bus_message_read(reply, "o", &path);
718 return bus_log_parse_error(r);
721 r = show_properties(bus, path, &new_line);
723 r = print_session_status_info(bus, path, &new_line);
732 static int show_user(int argc, char *argv[], void *userdata) {
733 bool properties, new_line = false;
734 sd_bus *bus = userdata;
740 properties = !strstr(argv[0], "status");
742 pager_open_if_enabled();
745 /* If not argument is specified inspect the manager
748 return show_properties(bus, "/org/freedesktop/login1", &new_line);
750 return print_user_status_info(bus, "/org/freedesktop/login1/user/self", &new_line);
753 for (i = 1; i < argc; i++) {
754 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
755 _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
756 const char *path = NULL;
759 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
761 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
763 r = sd_bus_call_method(
765 "org.freedesktop.login1",
766 "/org/freedesktop/login1",
767 "org.freedesktop.login1.Manager",
770 "u", (uint32_t) uid);
772 log_error("Failed to get user: %s", bus_error_message(&error, r));
776 r = sd_bus_message_read(reply, "o", &path);
778 return bus_log_parse_error(r);
781 r = show_properties(bus, path, &new_line);
783 r = print_user_status_info(bus, path, &new_line);
792 static int show_seat(int argc, char *argv[], void *userdata) {
793 bool properties, new_line = false;
794 sd_bus *bus = userdata;
800 properties = !strstr(argv[0], "status");
802 pager_open_if_enabled();
805 /* If not argument is specified inspect the manager
808 return show_properties(bus, "/org/freedesktop/login1", &new_line);
810 return print_seat_status_info(bus, "/org/freedesktop/login1/seat/self", &new_line);
813 for (i = 1; i < argc; i++) {
814 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
815 _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
816 const char *path = NULL;
818 r = sd_bus_call_method(
820 "org.freedesktop.login1",
821 "/org/freedesktop/login1",
822 "org.freedesktop.login1.Manager",
827 log_error("Failed to get seat: %s", bus_error_message(&error, r));
831 r = sd_bus_message_read(reply, "o", &path);
833 return bus_log_parse_error(r);
836 r = show_properties(bus, path, &new_line);
838 r = print_seat_status_info(bus, path, &new_line);
847 static int activate(int argc, char *argv[], void *userdata) {
848 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
849 sd_bus *bus = userdata;
856 polkit_agent_open_if_enabled();
859 /* No argument? Let's convert this into the empty
860 * session name, which the calls will then resolve to
861 * the caller's session. */
863 short_argv[0] = argv[0];
864 short_argv[1] = (char*) "";
865 short_argv[2] = NULL;
871 for (i = 1; i < argc; i++) {
873 r = sd_bus_call_method(
875 "org.freedesktop.login1",
876 "/org/freedesktop/login1",
877 "org.freedesktop.login1.Manager",
878 streq(argv[0], "lock-session") ? "LockSession" :
879 streq(argv[0], "unlock-session") ? "UnlockSession" :
880 streq(argv[0], "terminate-session") ? "TerminateSession" :
885 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
893 static int kill_session(int argc, char *argv[], void *userdata) {
894 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
895 sd_bus *bus = userdata;
901 polkit_agent_open_if_enabled();
904 arg_kill_who = "all";
906 for (i = 1; i < argc; i++) {
908 r = sd_bus_call_method(
910 "org.freedesktop.login1",
911 "/org/freedesktop/login1",
912 "org.freedesktop.login1.Manager",
915 "ssi", argv[i], arg_kill_who, arg_signal);
917 log_error("Could not kill session: %s", bus_error_message(&error, -r));
925 static int enable_linger(int argc, char *argv[], void *userdata) {
926 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
927 sd_bus *bus = userdata;
935 polkit_agent_open_if_enabled();
937 b = streq(argv[0], "enable-linger");
940 short_argv[0] = argv[0];
941 short_argv[1] = (char*) "";
942 short_argv[2] = NULL;
947 for (i = 1; i < argc; i++) {
950 if (isempty(argv[i]))
953 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
955 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
958 r = sd_bus_call_method(
960 "org.freedesktop.login1",
961 "/org/freedesktop/login1",
962 "org.freedesktop.login1.Manager",
965 "ubb", (uint32_t) uid, b, true);
967 log_error("Could not enable linger: %s", bus_error_message(&error, -r));
975 static int terminate_user(int argc, char *argv[], void *userdata) {
976 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
977 sd_bus *bus = userdata;
983 polkit_agent_open_if_enabled();
985 for (i = 1; i < argc; i++) {
988 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
990 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
992 r = sd_bus_call_method(
994 "org.freedesktop.login1",
995 "/org/freedesktop/login1",
996 "org.freedesktop.login1.Manager",
999 "u", (uint32_t) uid);
1001 log_error("Could not terminate user: %s", bus_error_message(&error, -r));
1009 static int kill_user(int argc, char *argv[], void *userdata) {
1010 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1011 sd_bus *bus = userdata;
1017 polkit_agent_open_if_enabled();
1020 arg_kill_who = "all";
1022 for (i = 1; i < argc; i++) {
1025 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
1027 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
1029 r = sd_bus_call_method(
1031 "org.freedesktop.login1",
1032 "/org/freedesktop/login1",
1033 "org.freedesktop.login1.Manager",
1036 "ui", (uint32_t) uid, arg_signal);
1038 log_error("Could not kill user: %s", bus_error_message(&error, -r));
1046 static int attach(int argc, char *argv[], void *userdata) {
1047 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1048 sd_bus *bus = userdata;
1054 polkit_agent_open_if_enabled();
1056 for (i = 2; i < argc; i++) {
1058 r = sd_bus_call_method(
1060 "org.freedesktop.login1",
1061 "/org/freedesktop/login1",
1062 "org.freedesktop.login1.Manager",
1065 "ssb", argv[1], argv[i], true);
1068 log_error("Could not attach device: %s", bus_error_message(&error, -r));
1076 static int flush_devices(int argc, char *argv[], void *userdata) {
1077 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1078 sd_bus *bus = userdata;
1084 polkit_agent_open_if_enabled();
1086 r = sd_bus_call_method(
1088 "org.freedesktop.login1",
1089 "/org/freedesktop/login1",
1090 "org.freedesktop.login1.Manager",
1095 log_error("Could not flush devices: %s", bus_error_message(&error, -r));
1100 static int lock_sessions(int argc, char *argv[], void *userdata) {
1101 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1102 sd_bus *bus = userdata;
1108 polkit_agent_open_if_enabled();
1110 r = sd_bus_call_method(
1112 "org.freedesktop.login1",
1113 "/org/freedesktop/login1",
1114 "org.freedesktop.login1.Manager",
1115 streq(argv[0], "lock-sessions") ? "LockSessions" : "UnlockSessions",
1119 log_error("Could not lock sessions: %s", bus_error_message(&error, -r));
1124 static int terminate_seat(int argc, char *argv[], void *userdata) {
1125 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1126 sd_bus *bus = userdata;
1132 polkit_agent_open_if_enabled();
1134 for (i = 1; i < argc; i++) {
1136 r = sd_bus_call_method(
1138 "org.freedesktop.login1",
1139 "/org/freedesktop/login1",
1140 "org.freedesktop.login1.Manager",
1145 log_error("Could not terminate seat: %s", bus_error_message(&error, -r));
1153 static int help(int argc, char *argv[], void *userdata) {
1155 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
1156 "Send control commands to or query the login manager.\n\n"
1157 " -h --help Show this help\n"
1158 " --version Show package version\n"
1159 " --no-pager Do not pipe output into a pager\n"
1160 " --no-legend Do not show the headers and footers\n"
1161 " --no-ask-password Don't prompt for password\n"
1162 " -H --host=[USER@]HOST Operate on remote host\n"
1163 " -M --machine=CONTAINER Operate on local container\n"
1164 " -p --property=NAME Show only properties by this name\n"
1165 " -a --all Show all properties, including empty ones\n"
1166 " -l --full Do not ellipsize output\n"
1167 " --kill-who=WHO Who to send signal to\n"
1168 " -s --signal=SIGNAL Which signal to send\n"
1169 " -n --lines=INTEGER Number of journal entries to show\n"
1170 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
1171 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
1172 "Session Commands:\n"
1173 " list-sessions List sessions\n"
1174 " session-status [ID...] Show session status\n"
1175 " show-session [ID...] Show properties of sessions or the manager\n"
1176 " activate [ID] Activate a session\n"
1177 " lock-session [ID...] Screen lock one or more sessions\n"
1178 " unlock-session [ID...] Screen unlock one or more sessions\n"
1179 " lock-sessions Screen lock all current sessions\n"
1180 " unlock-sessions Screen unlock all current sessions\n"
1181 " terminate-session ID... Terminate one or more sessions\n"
1182 " kill-session ID... Send signal to processes of a session\n\n"
1184 " list-users List users\n"
1185 " user-status [USER...] Show user status\n"
1186 " show-user [USER...] Show properties of users or the manager\n"
1187 " enable-linger [USER...] Enable linger state of one or more users\n"
1188 " disable-linger [USER...] Disable linger state of one or more users\n"
1189 " terminate-user USER... Terminate all sessions of one or more users\n"
1190 " kill-user USER... Send signal to processes of a user\n\n"
1192 " list-seats List seats\n"
1193 " seat-status [NAME...] Show seat status\n"
1194 " show-seat [NAME...] Show properties of seats or the manager\n"
1195 " attach NAME DEVICE... Attach one or more devices to a seat\n"
1196 " flush-devices Flush all device associations\n"
1197 " terminate-seat NAME... Terminate all sessions on one or more seats\n"
1198 , program_invocation_short_name);
1203 static int parse_argv(int argc, char *argv[]) {
1206 ARG_VERSION = 0x100,
1210 ARG_NO_ASK_PASSWORD,
1213 static const struct option options[] = {
1214 { "help", no_argument, NULL, 'h' },
1215 { "version", no_argument, NULL, ARG_VERSION },
1216 { "property", required_argument, NULL, 'p' },
1217 { "all", no_argument, NULL, 'a' },
1218 { "full", no_argument, NULL, 'l' },
1219 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
1220 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
1221 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
1222 { "signal", required_argument, NULL, 's' },
1223 { "host", required_argument, NULL, 'H' },
1224 { "machine", required_argument, NULL, 'M' },
1225 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
1226 { "lines", required_argument, NULL, 'n' },
1227 { "output", required_argument, NULL, 'o' },
1236 while ((c = getopt_long(argc, argv, "hp:als:H:M:n:o:", options, NULL)) >= 0)
1241 help(0, NULL, NULL);
1245 puts(PACKAGE_STRING);
1246 puts(SYSTEMD_FEATURES);
1250 r = strv_extend(&arg_property, optarg);
1254 /* If the user asked for a particular
1255 * property, show it to him, even if it is
1270 if (safe_atou(optarg, &arg_lines) < 0) {
1271 log_error("Failed to parse lines '%s'", optarg);
1278 arg_output = output_mode_from_string(optarg);
1282 if (arg_output < 0) {
1283 log_error("Unknown output '%s'.", optarg);
1289 arg_no_pager = true;
1296 case ARG_NO_ASK_PASSWORD:
1297 arg_ask_password = false;
1301 arg_kill_who = optarg;
1305 arg_signal = signal_from_string_try_harder(optarg);
1306 if (arg_signal < 0) {
1307 log_error("Failed to parse signal string %s.", optarg);
1313 arg_transport = BUS_TRANSPORT_REMOTE;
1318 arg_transport = BUS_TRANSPORT_MACHINE;
1326 assert_not_reached("Unhandled option");
1332 static int loginctl_main(int argc, char *argv[], sd_bus *bus) {
1334 static const Verb verbs[] = {
1335 { "help", VERB_ANY, VERB_ANY, 0, help },
1336 { "list-sessions", VERB_ANY, 1, VERB_DEFAULT, list_sessions },
1337 { "session-status", VERB_ANY, VERB_ANY, 0, show_session },
1338 { "show-session", VERB_ANY, VERB_ANY, 0, show_session },
1339 { "activate", VERB_ANY, 2, 0, activate },
1340 { "lock-session", VERB_ANY, VERB_ANY, 0, activate },
1341 { "unlock-session", VERB_ANY, VERB_ANY, 0, activate },
1342 { "lock-sessions", VERB_ANY, 1, 0, lock_sessions },
1343 { "unlock-sessions", VERB_ANY, 1, 0, lock_sessions },
1344 { "terminate-session", 2, VERB_ANY, 0, activate },
1345 { "kill-session", 2, VERB_ANY, 0, kill_session },
1346 { "list-users", VERB_ANY, 1, 0, list_users },
1347 { "user-status", VERB_ANY, VERB_ANY, 0, show_user },
1348 { "show-user", VERB_ANY, VERB_ANY, 0, show_user },
1349 { "enable-linger", VERB_ANY, VERB_ANY, 0, enable_linger },
1350 { "disable-linger", VERB_ANY, VERB_ANY, 0, enable_linger },
1351 { "terminate-user", 2, VERB_ANY, 0, terminate_user },
1352 { "kill-user", 2, VERB_ANY, 0, kill_user },
1353 { "list-seats", VERB_ANY, 1, 0, list_seats },
1354 { "seat-status", VERB_ANY, VERB_ANY, 0, show_seat },
1355 { "show-seat", VERB_ANY, VERB_ANY, 0, show_seat },
1356 { "attach", 3, VERB_ANY, 0, attach },
1357 { "flush-devices", VERB_ANY, 1, 0, flush_devices },
1358 { "terminate-seat", 2, VERB_ANY, 0, terminate_seat },
1362 return dispatch_verb(argc, argv, verbs, bus);
1365 int main(int argc, char *argv[]) {
1366 _cleanup_bus_close_unref_ sd_bus *bus = NULL;
1369 setlocale(LC_ALL, "");
1370 log_parse_environment();
1373 r = parse_argv(argc, argv);
1377 r = bus_open_transport(arg_transport, arg_host, false, &bus);
1379 log_error_errno(r, "Failed to create bus connection: %m");
1383 sd_bus_set_allow_interactive_authorization(bus, arg_ask_password);
1385 r = loginctl_main(argc, argv, bus);
1389 polkit_agent_close();
1391 strv_free(arg_property);
1393 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;