1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
31 #include "bus-error.h"
38 #include "unit-name.h"
39 #include "sysfs-show.h"
40 #include "logs-show.h"
41 #include "cgroup-show.h"
42 #include "cgroup-util.h"
43 #include "spawn-polkit-agent.h"
46 static char **arg_property = NULL;
47 static bool arg_all = false;
48 static bool arg_full = false;
49 static bool arg_no_pager = false;
50 static bool arg_legend = true;
51 static const char *arg_kill_who = NULL;
52 static int arg_signal = SIGTERM;
53 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
54 static char *arg_host = NULL;
55 static bool arg_ask_password = true;
56 static unsigned arg_lines = 10;
57 static OutputMode arg_output = OUTPUT_SHORT;
59 static void pager_open_if_enabled(void) {
67 static void polkit_agent_open_if_enabled(void) {
69 /* Open the polkit agent as a child process if necessary */
71 if (!arg_ask_password)
74 if (arg_transport != BUS_TRANSPORT_LOCAL)
80 static OutputFlags get_output_flags(void) {
83 arg_all * OUTPUT_SHOW_ALL |
84 arg_full * OUTPUT_FULL_WIDTH |
85 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
86 on_tty() * OUTPUT_COLOR;
89 static int list_sessions(int argc, char *argv[], void *userdata) {
90 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
91 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
92 const char *id, *user, *seat, *object;
93 sd_bus *bus = userdata;
101 pager_open_if_enabled();
103 r = sd_bus_call_method(
105 "org.freedesktop.login1",
106 "/org/freedesktop/login1",
107 "org.freedesktop.login1.Manager",
112 log_error("Failed to list sessions: %s", bus_error_message(&error, r));
116 r = sd_bus_message_enter_container(reply, 'a', "(susso)");
118 return bus_log_parse_error(r);
121 printf("%10s %10s %-16s %-16s\n", "SESSION", "UID", "USER", "SEAT");
123 while ((r = sd_bus_message_read(reply, "(susso)", &id, &uid, &user, &seat, &object)) > 0) {
124 printf("%10s %10u %-16s %-16s\n", id, (unsigned) uid, user, seat);
128 return bus_log_parse_error(r);
131 printf("\n%u sessions listed.\n", k);
136 static int list_users(int argc, char *argv[], void *userdata) {
137 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
138 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
139 const char *user, *object;
140 sd_bus *bus = userdata;
148 pager_open_if_enabled();
150 r = sd_bus_call_method(
152 "org.freedesktop.login1",
153 "/org/freedesktop/login1",
154 "org.freedesktop.login1.Manager",
159 log_error("Failed to list users: %s", bus_error_message(&error, r));
163 r = sd_bus_message_enter_container(reply, 'a', "(uso)");
165 return bus_log_parse_error(r);
168 printf("%10s %-16s\n", "UID", "USER");
170 while ((r = sd_bus_message_read(reply, "(uso)", &uid, &user, &object)) > 0) {
171 printf("%10u %-16s\n", (unsigned) uid, user);
175 return bus_log_parse_error(r);
178 printf("\n%u users listed.\n", k);
183 static int list_seats(int argc, char *argv[], void *userdata) {
184 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
185 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
186 const char *seat, *object;
187 sd_bus *bus = userdata;
194 pager_open_if_enabled();
196 r = sd_bus_call_method(
198 "org.freedesktop.login1",
199 "/org/freedesktop/login1",
200 "org.freedesktop.login1.Manager",
205 log_error("Failed to list seats: %s", bus_error_message(&error, r));
209 r = sd_bus_message_enter_container(reply, 'a', "(so)");
211 return bus_log_parse_error(r);
214 printf("%-16s\n", "SEAT");
216 while ((r = sd_bus_message_read(reply, "(so)", &seat, &object)) > 0) {
217 printf("%-16s\n", seat);
221 return bus_log_parse_error(r);
224 printf("\n%u seats listed.\n", k);
229 static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit, pid_t leader) {
230 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
231 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
232 _cleanup_free_ char *path = NULL;
240 if (arg_transport != BUS_TRANSPORT_LOCAL)
243 path = unit_dbus_path_from_name(unit);
247 r = sd_bus_get_property(
249 "org.freedesktop.systemd1",
253 &error, &reply, "s");
257 r = sd_bus_message_read(reply, "s", &cgroup);
264 if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup, false) != 0 && leader <= 0)
273 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t ", c, false, &leader, leader > 0, get_output_flags());
277 typedef struct SessionStatusInfo {
281 struct dual_timestamp timestamp;
287 const char *remote_host;
288 const char *remote_user;
298 typedef struct UserStatusInfo {
301 struct dual_timestamp timestamp;
308 typedef struct SeatStatusInfo {
310 const char *active_session;
314 static int prop_map_first_of_struct(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
315 const char *contents;
318 r = sd_bus_message_peek_type(m, NULL, &contents);
322 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, contents);
326 if (contents[0] == 's' || contents[0] == 'o') {
328 char **p = (char **) userdata;
330 r = sd_bus_message_read_basic(m, contents[0], &s);
340 r = sd_bus_message_read_basic(m, contents[0], userdata);
345 r = sd_bus_message_skip(m, contents+1);
349 r = sd_bus_message_exit_container(m);
356 static int prop_map_sessions_strv(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
363 r = sd_bus_message_enter_container(m, 'a', "(so)");
367 while ((r = sd_bus_message_read(m, "(so)", &name, NULL)) > 0) {
368 r = strv_extend(userdata, name);
375 return sd_bus_message_exit_container(m);
378 static int print_session_status_info(sd_bus *bus, const char *path, bool *new_line) {
380 static const struct bus_properties_map map[] = {
381 { "Id", "s", NULL, offsetof(SessionStatusInfo, id) },
382 { "Name", "s", NULL, offsetof(SessionStatusInfo, name) },
383 { "TTY", "s", NULL, offsetof(SessionStatusInfo, tty) },
384 { "Display", "s", NULL, offsetof(SessionStatusInfo, display) },
385 { "RemoteHost", "s", NULL, offsetof(SessionStatusInfo, remote_host) },
386 { "RemoteUser", "s", NULL, offsetof(SessionStatusInfo, remote_user) },
387 { "Service", "s", NULL, offsetof(SessionStatusInfo, service) },
388 { "Desktop", "s", NULL, offsetof(SessionStatusInfo, desktop) },
389 { "Type", "s", NULL, offsetof(SessionStatusInfo, type) },
390 { "Class", "s", NULL, offsetof(SessionStatusInfo, class) },
391 { "Scope", "s", NULL, offsetof(SessionStatusInfo, scope) },
392 { "State", "s", NULL, offsetof(SessionStatusInfo, state) },
393 { "VTNr", "u", NULL, offsetof(SessionStatusInfo, vtnr) },
394 { "Leader", "u", NULL, offsetof(SessionStatusInfo, leader) },
395 { "Remote", "b", NULL, offsetof(SessionStatusInfo, remote) },
396 { "Timestamp", "t", NULL, offsetof(SessionStatusInfo, timestamp.realtime) },
397 { "TimestampMonotonic", "t", NULL, offsetof(SessionStatusInfo, timestamp.monotonic) },
398 { "User", "(uo)", prop_map_first_of_struct, offsetof(SessionStatusInfo, uid) },
399 { "Seat", "(so)", prop_map_first_of_struct, offsetof(SessionStatusInfo, seat) },
403 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
404 char since2[FORMAT_TIMESTAMP_MAX], *s2;
405 SessionStatusInfo i = {};
408 r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i);
410 return log_error_errno(r, "Could not get properties: %m");
417 printf("%s - ", strna(i.id));
420 printf("%s (%u)\n", i.name, (unsigned) i.uid);
422 printf("%u\n", (unsigned) i.uid);
424 s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime);
425 s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime);
428 printf("\t Since: %s; %s\n", s2, s1);
430 printf("\t Since: %s\n", s2);
433 _cleanup_free_ char *t = NULL;
435 printf("\t Leader: %u", (unsigned) i.leader);
437 get_process_comm(i.leader, &t);
444 if (!isempty(i.seat)) {
445 printf("\t Seat: %s", i.seat);
448 printf("; vc%u", i.vtnr);
454 printf("\t TTY: %s\n", i.tty);
456 printf("\t Display: %s\n", i.display);
458 if (i.remote_host && i.remote_user)
459 printf("\t Remote: %s@%s\n", i.remote_user, i.remote_host);
460 else if (i.remote_host)
461 printf("\t Remote: %s\n", i.remote_host);
462 else if (i.remote_user)
463 printf("\t Remote: user %s\n", i.remote_user);
465 printf("\t Remote: Yes\n");
468 printf("\t Service: %s", i.service);
471 printf("; type %s", i.type);
474 printf("; class %s", i.class);
478 printf("\t Type: %s", i.type);
481 printf("; class %s", i.class);
485 printf("\t Class: %s\n", i.class);
487 if (!isempty(i.desktop))
488 printf("\t Desktop: %s\n", i.desktop);
491 printf("\t State: %s\n", i.state);
494 printf("\t Unit: %s\n", i.scope);
495 show_unit_cgroup(bus, "org.freedesktop.systemd1.Scope", i.scope, i.leader);
497 if (arg_transport == BUS_TRANSPORT_LOCAL) {
499 show_journal_by_unit(
504 i.timestamp.monotonic,
507 get_output_flags() | OUTPUT_BEGIN_NEWLINE,
508 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,
596 strv_free(i.sessions);
601 static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line) {
603 static const struct bus_properties_map map[] = {
604 { "Id", "s", NULL, offsetof(SeatStatusInfo, id) },
605 { "ActiveSession", "(so)", prop_map_first_of_struct, offsetof(SeatStatusInfo, active_session) },
606 { "Sessions", "a(so)", prop_map_sessions_strv, offsetof(SeatStatusInfo, sessions) },
610 SeatStatusInfo i = {};
613 r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i);
615 log_error_errno(r, "Could not get properties: %m");
624 printf("%s\n", strna(i.id));
626 if (!strv_isempty(i.sessions)) {
628 printf("\tSessions:");
630 STRV_FOREACH(l, i.sessions) {
631 if (streq_ptr(*l, i.active_session))
640 if (arg_transport == BUS_TRANSPORT_LOCAL) {
649 printf("\t Devices:\n");
651 show_sysfs(i.id, "\t\t ", c);
655 strv_free(i.sessions);
660 static int show_properties(sd_bus *bus, const char *path, bool *new_line) {
668 r = bus_print_all_properties(bus, "org.freedesktop.login1", path, arg_property, arg_all);
670 log_error_errno(r, "Could not get properties: %m");
675 static int show_session(int argc, char *argv[], void *userdata) {
676 bool properties, new_line = false;
677 sd_bus *bus = userdata;
683 properties = !strstr(argv[0], "status");
685 pager_open_if_enabled();
688 /* If not argument is specified inspect the manager
691 return show_properties(bus, "/org/freedesktop/login1", &new_line);
693 /* And in the pretty case, show data of the calling session */
694 return print_session_status_info(bus, "/org/freedesktop/login1/session/self", &new_line);
697 for (i = 1; i < argc; i++) {
698 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
699 _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
700 const char *path = NULL;
702 r = sd_bus_call_method(
704 "org.freedesktop.login1",
705 "/org/freedesktop/login1",
706 "org.freedesktop.login1.Manager",
711 log_error("Failed to get session: %s", bus_error_message(&error, r));
715 r = sd_bus_message_read(reply, "o", &path);
717 return bus_log_parse_error(r);
720 r = show_properties(bus, path, &new_line);
722 r = print_session_status_info(bus, path, &new_line);
731 static int show_user(int argc, char *argv[], void *userdata) {
732 bool properties, new_line = false;
733 sd_bus *bus = userdata;
739 properties = !strstr(argv[0], "status");
741 pager_open_if_enabled();
744 /* If not argument is specified inspect the manager
747 return show_properties(bus, "/org/freedesktop/login1", &new_line);
749 return print_user_status_info(bus, "/org/freedesktop/login1/user/self", &new_line);
752 for (i = 1; i < argc; i++) {
753 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
754 _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
755 const char *path = NULL;
758 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
760 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
762 r = sd_bus_call_method(
764 "org.freedesktop.login1",
765 "/org/freedesktop/login1",
766 "org.freedesktop.login1.Manager",
769 "u", (uint32_t) uid);
771 log_error("Failed to get user: %s", bus_error_message(&error, r));
775 r = sd_bus_message_read(reply, "o", &path);
777 return bus_log_parse_error(r);
780 r = show_properties(bus, path, &new_line);
782 r = print_user_status_info(bus, path, &new_line);
791 static int show_seat(int argc, char *argv[], void *userdata) {
792 bool properties, new_line = false;
793 sd_bus *bus = userdata;
799 properties = !strstr(argv[0], "status");
801 pager_open_if_enabled();
804 /* If not argument is specified inspect the manager
807 return show_properties(bus, "/org/freedesktop/login1", &new_line);
809 return print_seat_status_info(bus, "/org/freedesktop/login1/seat/self", &new_line);
812 for (i = 1; i < argc; i++) {
813 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
814 _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
815 const char *path = NULL;
817 r = sd_bus_call_method(
819 "org.freedesktop.login1",
820 "/org/freedesktop/login1",
821 "org.freedesktop.login1.Manager",
826 log_error("Failed to get seat: %s", bus_error_message(&error, r));
830 r = sd_bus_message_read(reply, "o", &path);
832 return bus_log_parse_error(r);
835 r = show_properties(bus, path, &new_line);
837 r = print_seat_status_info(bus, path, &new_line);
846 static int activate(int argc, char *argv[], void *userdata) {
847 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
848 sd_bus *bus = userdata;
854 polkit_agent_open_if_enabled();
857 /* No argument? Let's convert this into the empty
858 * session name, which the calls will then resolve to
859 * the caller's session. */
861 argv = STRV_MAKE(argv[0], "");
865 for (i = 1; i < argc; i++) {
867 r = sd_bus_call_method (
869 "org.freedesktop.login1",
870 "/org/freedesktop/login1",
871 "org.freedesktop.login1.Manager",
872 streq(argv[0], "lock-session") ? "LockSession" :
873 streq(argv[0], "unlock-session") ? "UnlockSession" :
874 streq(argv[0], "terminate-session") ? "TerminateSession" :
879 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
887 static int kill_session(int argc, char *argv[], void *userdata) {
888 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
889 sd_bus *bus = userdata;
895 polkit_agent_open_if_enabled();
898 arg_kill_who = "all";
900 for (i = 1; i < argc; i++) {
902 r = sd_bus_call_method (
904 "org.freedesktop.login1",
905 "/org/freedesktop/login1",
906 "org.freedesktop.login1.Manager",
909 "ssi", argv[i], arg_kill_who, arg_signal);
911 log_error("Could not kill session: %s", bus_error_message(&error, -r));
919 static int enable_linger(int argc, char *argv[], void *userdata) {
920 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
921 sd_bus *bus = userdata;
928 polkit_agent_open_if_enabled();
930 b = streq(argv[0], "enable-linger");
933 argv = STRV_MAKE(argv[0], "");
937 for (i = 1; i < argc; i++) {
940 if (isempty(argv[i]))
943 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
945 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
948 r = sd_bus_call_method (
950 "org.freedesktop.login1",
951 "/org/freedesktop/login1",
952 "org.freedesktop.login1.Manager",
955 "ubb", (uint32_t) uid, b, true);
957 log_error("Could not enable linger: %s", bus_error_message(&error, -r));
965 static int terminate_user(int argc, char *argv[], void *userdata) {
966 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
967 sd_bus *bus = userdata;
973 polkit_agent_open_if_enabled();
975 for (i = 1; i < argc; i++) {
978 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
980 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
982 r = sd_bus_call_method (
984 "org.freedesktop.login1",
985 "/org/freedesktop/login1",
986 "org.freedesktop.login1.Manager",
989 "u", (uint32_t) uid);
991 log_error("Could not terminate user: %s", bus_error_message(&error, -r));
999 static int kill_user(int argc, char *argv[], void *userdata) {
1000 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1001 sd_bus *bus = userdata;
1007 polkit_agent_open_if_enabled();
1010 arg_kill_who = "all";
1012 for (i = 1; i < argc; i++) {
1015 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
1017 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
1019 r = sd_bus_call_method (
1021 "org.freedesktop.login1",
1022 "/org/freedesktop/login1",
1023 "org.freedesktop.login1.Manager",
1026 "ui", (uint32_t) uid, arg_signal);
1028 log_error("Could not kill user: %s", bus_error_message(&error, -r));
1036 static int attach(int argc, char *argv[], void *userdata) {
1037 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1038 sd_bus *bus = userdata;
1044 polkit_agent_open_if_enabled();
1046 for (i = 2; i < argc; i++) {
1048 r = sd_bus_call_method (
1050 "org.freedesktop.login1",
1051 "/org/freedesktop/login1",
1052 "org.freedesktop.login1.Manager",
1055 "ssb", argv[1], argv[i], true);
1058 log_error("Could not attach device: %s", bus_error_message(&error, -r));
1066 static int flush_devices(int argc, char *argv[], void *userdata) {
1067 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1068 sd_bus *bus = userdata;
1074 polkit_agent_open_if_enabled();
1076 r = sd_bus_call_method (
1078 "org.freedesktop.login1",
1079 "/org/freedesktop/login1",
1080 "org.freedesktop.login1.Manager",
1085 log_error("Could not flush devices: %s", bus_error_message(&error, -r));
1090 static int lock_sessions(int argc, char *argv[], void *userdata) {
1091 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1092 sd_bus *bus = userdata;
1098 polkit_agent_open_if_enabled();
1100 r = sd_bus_call_method(
1102 "org.freedesktop.login1",
1103 "/org/freedesktop/login1",
1104 "org.freedesktop.login1.Manager",
1105 streq(argv[0], "lock-sessions") ? "LockSessions" : "UnlockSessions",
1109 log_error("Could not lock sessions: %s", bus_error_message(&error, -r));
1114 static int terminate_seat(int argc, char *argv[], void *userdata) {
1115 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1116 sd_bus *bus = userdata;
1122 polkit_agent_open_if_enabled();
1124 for (i = 1; i < argc; i++) {
1126 r = sd_bus_call_method(
1128 "org.freedesktop.login1",
1129 "/org/freedesktop/login1",
1130 "org.freedesktop.login1.Manager",
1135 log_error("Could not terminate seat: %s", bus_error_message(&error, -r));
1143 static int help(int argc, char *argv[], void *userdata) {
1145 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
1146 "Send control commands to or query the login manager.\n\n"
1147 " -h --help Show this help\n"
1148 " --version Show package version\n"
1149 " --no-pager Do not pipe output into a pager\n"
1150 " --no-legend Do not show the headers and footers\n"
1151 " --no-ask-password Don't prompt for password\n"
1152 " -H --host=[USER@]HOST Operate on remote host\n"
1153 " -M --machine=CONTAINER Operate on local container\n"
1154 " -p --property=NAME Show only properties by this name\n"
1155 " -a --all Show all properties, including empty ones\n"
1156 " -l --full Do not ellipsize output\n"
1157 " --kill-who=WHO Who to send signal to\n"
1158 " -s --signal=SIGNAL Which signal to send\n"
1159 " -n --lines=INTEGER Number of journal entries to show\n"
1160 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
1161 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
1162 "Session Commands:\n"
1163 " list-sessions List sessions\n"
1164 " session-status [ID...] Show session status\n"
1165 " show-session [ID...] Show properties of sessions or the manager\n"
1166 " activate [ID] Activate a session\n"
1167 " lock-session [ID...] Screen lock one or more sessions\n"
1168 " unlock-session [ID...] Screen unlock one or more sessions\n"
1169 " lock-sessions Screen lock all current sessions\n"
1170 " unlock-sessions Screen unlock all current sessions\n"
1171 " terminate-session ID... Terminate one or more sessions\n"
1172 " kill-session ID... Send signal to processes of a session\n\n"
1174 " list-users List users\n"
1175 " user-status [USER...] Show user status\n"
1176 " show-user [USER...] Show properties of users or the manager\n"
1177 " enable-linger [USER...] Enable linger state of one or more users\n"
1178 " disable-linger [USER...] Disable linger state of one or more users\n"
1179 " terminate-user USER... Terminate all sessions of one or more users\n"
1180 " kill-user USER... Send signal to processes of a user\n\n"
1182 " list-seats List seats\n"
1183 " seat-status [NAME...] Show seat status\n"
1184 " show-seat [NAME...] Show properties of seats or the manager\n"
1185 " attach NAME DEVICE... Attach one or more devices to a seat\n"
1186 " flush-devices Flush all device associations\n"
1187 " terminate-seat NAME... Terminate all sessions on one or more seats\n"
1188 , program_invocation_short_name);
1193 static int parse_argv(int argc, char *argv[]) {
1196 ARG_VERSION = 0x100,
1200 ARG_NO_ASK_PASSWORD,
1203 static const struct option options[] = {
1204 { "help", no_argument, NULL, 'h' },
1205 { "version", no_argument, NULL, ARG_VERSION },
1206 { "property", required_argument, NULL, 'p' },
1207 { "all", no_argument, NULL, 'a' },
1208 { "full", no_argument, NULL, 'l' },
1209 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
1210 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
1211 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
1212 { "signal", required_argument, NULL, 's' },
1213 { "host", required_argument, NULL, 'H' },
1214 { "machine", required_argument, NULL, 'M' },
1215 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
1216 { "lines", required_argument, NULL, 'n' },
1217 { "output", required_argument, NULL, 'o' },
1226 while ((c = getopt_long(argc, argv, "hp:als:H:M:n:o:", options, NULL)) >= 0)
1231 help(0, NULL, NULL);
1235 puts(PACKAGE_STRING);
1236 puts(SYSTEMD_FEATURES);
1240 r = strv_extend(&arg_property, optarg);
1244 /* If the user asked for a particular
1245 * property, show it to him, even if it is
1260 if (safe_atou(optarg, &arg_lines) < 0) {
1261 log_error("Failed to parse lines '%s'", optarg);
1267 arg_output = output_mode_from_string(optarg);
1268 if (arg_output < 0) {
1269 log_error("Unknown output '%s'.", optarg);
1275 arg_no_pager = true;
1282 case ARG_NO_ASK_PASSWORD:
1283 arg_ask_password = false;
1287 arg_kill_who = optarg;
1291 arg_signal = signal_from_string_try_harder(optarg);
1292 if (arg_signal < 0) {
1293 log_error("Failed to parse signal string %s.", optarg);
1299 arg_transport = BUS_TRANSPORT_REMOTE;
1304 arg_transport = BUS_TRANSPORT_MACHINE;
1312 assert_not_reached("Unhandled option");
1318 static int loginctl_main(int argc, char *argv[], sd_bus *bus) {
1320 static const Verb verbs[] = {
1321 { "help", VERB_ANY, VERB_ANY, 0, help },
1322 { "list-sessions", VERB_ANY, 1, VERB_DEFAULT, list_sessions },
1323 { "session-status", VERB_ANY, VERB_ANY, 0, show_session },
1324 { "show-session", VERB_ANY, VERB_ANY, 0, show_session },
1325 { "activate", VERB_ANY, 2, 0, activate },
1326 { "lock-session", VERB_ANY, VERB_ANY, 0, activate },
1327 { "unlock-session", VERB_ANY, VERB_ANY, 0, activate },
1328 { "lock-sessions", VERB_ANY, 1, 0, lock_sessions },
1329 { "unlock-sessions", VERB_ANY, 1, 0, lock_sessions },
1330 { "terminate-session", 2, VERB_ANY, 0, activate },
1331 { "kill-session", 2, VERB_ANY, 0, kill_session },
1332 { "list-users", VERB_ANY, 1, 0, list_users },
1333 { "user-status", VERB_ANY, VERB_ANY, 0, show_user },
1334 { "show-user", VERB_ANY, VERB_ANY, 0, show_user },
1335 { "enable-linger", VERB_ANY, VERB_ANY, 0, enable_linger },
1336 { "disable-linger", VERB_ANY, VERB_ANY, 0, enable_linger },
1337 { "terminate-user", 2, VERB_ANY, 0, terminate_user },
1338 { "kill-user", 2, VERB_ANY, 0, kill_user },
1339 { "list-seats", VERB_ANY, 1, 0, list_seats },
1340 { "seat-status", VERB_ANY, VERB_ANY, 0, show_seat },
1341 { "show-seat", VERB_ANY, VERB_ANY, 0, show_seat },
1342 { "attach", 3, VERB_ANY, 0, attach },
1343 { "flush-devices", VERB_ANY, 1, 0, flush_devices },
1344 { "terminate-seat", 2, VERB_ANY, 0, terminate_seat },
1348 return dispatch_verb(argc, argv, verbs, bus);
1351 int main(int argc, char *argv[]) {
1352 _cleanup_bus_close_unref_ sd_bus *bus = NULL;
1355 setlocale(LC_ALL, "");
1356 log_parse_environment();
1359 r = parse_argv(argc, argv);
1363 r = bus_open_transport(arg_transport, arg_host, false, &bus);
1365 log_error_errno(r, "Failed to create bus connection: %m");
1369 r = loginctl_main(argc, argv, bus);
1373 polkit_agent_close();
1375 strv_free(arg_property);
1377 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;