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();
856 for (i = 1; i < argc; i++) {
858 r = sd_bus_call_method (
860 "org.freedesktop.login1",
861 "/org/freedesktop/login1",
862 "org.freedesktop.login1.Manager",
863 streq(argv[0], "lock-session") ? "LockSession" :
864 streq(argv[0], "unlock-session") ? "UnlockSession" :
865 streq(argv[0], "terminate-session") ? "TerminateSession" :
870 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
878 static int kill_session(int argc, char *argv[], void *userdata) {
879 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
880 sd_bus *bus = userdata;
886 polkit_agent_open_if_enabled();
889 arg_kill_who = "all";
891 for (i = 1; i < argc; i++) {
893 r = sd_bus_call_method (
895 "org.freedesktop.login1",
896 "/org/freedesktop/login1",
897 "org.freedesktop.login1.Manager",
900 "ssi", argv[i], arg_kill_who, arg_signal);
902 log_error("Could not kill session: %s", bus_error_message(&error, -r));
910 static int enable_linger(int argc, char *argv[], void *userdata) {
911 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
912 sd_bus *bus = userdata;
919 polkit_agent_open_if_enabled();
921 b = streq(argv[0], "enable-linger");
923 for (i = 1; i < argc; i++) {
926 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
928 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
930 r = sd_bus_call_method (
932 "org.freedesktop.login1",
933 "/org/freedesktop/login1",
934 "org.freedesktop.login1.Manager",
937 "ubb", (uint32_t) uid, b, true);
939 log_error("Could not enable linger: %s", bus_error_message(&error, -r));
947 static int terminate_user(int argc, char *argv[], void *userdata) {
948 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
949 sd_bus *bus = userdata;
955 polkit_agent_open_if_enabled();
957 for (i = 1; i < argc; i++) {
960 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
962 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
964 r = sd_bus_call_method (
966 "org.freedesktop.login1",
967 "/org/freedesktop/login1",
968 "org.freedesktop.login1.Manager",
971 "u", (uint32_t) uid);
973 log_error("Could not terminate user: %s", bus_error_message(&error, -r));
981 static int kill_user(int argc, char *argv[], void *userdata) {
982 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
983 sd_bus *bus = userdata;
989 polkit_agent_open_if_enabled();
992 arg_kill_who = "all";
994 for (i = 1; i < argc; i++) {
997 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
999 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
1001 r = sd_bus_call_method (
1003 "org.freedesktop.login1",
1004 "/org/freedesktop/login1",
1005 "org.freedesktop.login1.Manager",
1008 "ui", (uint32_t) uid, arg_signal);
1010 log_error("Could not kill user: %s", bus_error_message(&error, -r));
1018 static int attach(int argc, char *argv[], void *userdata) {
1019 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1020 sd_bus *bus = userdata;
1026 polkit_agent_open_if_enabled();
1028 for (i = 2; i < argc; i++) {
1030 r = sd_bus_call_method (
1032 "org.freedesktop.login1",
1033 "/org/freedesktop/login1",
1034 "org.freedesktop.login1.Manager",
1037 "ssb", argv[1], argv[i], true);
1040 log_error("Could not attach device: %s", bus_error_message(&error, -r));
1048 static int flush_devices(int argc, char *argv[], void *userdata) {
1049 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1050 sd_bus *bus = userdata;
1056 polkit_agent_open_if_enabled();
1058 r = sd_bus_call_method (
1060 "org.freedesktop.login1",
1061 "/org/freedesktop/login1",
1062 "org.freedesktop.login1.Manager",
1067 log_error("Could not flush devices: %s", bus_error_message(&error, -r));
1072 static int lock_sessions(int argc, char *argv[], void *userdata) {
1073 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1074 sd_bus *bus = userdata;
1080 polkit_agent_open_if_enabled();
1082 r = sd_bus_call_method(
1084 "org.freedesktop.login1",
1085 "/org/freedesktop/login1",
1086 "org.freedesktop.login1.Manager",
1087 streq(argv[0], "lock-sessions") ? "LockSessions" : "UnlockSessions",
1091 log_error("Could not lock sessions: %s", bus_error_message(&error, -r));
1096 static int terminate_seat(int argc, char *argv[], void *userdata) {
1097 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1098 sd_bus *bus = userdata;
1104 polkit_agent_open_if_enabled();
1106 for (i = 1; i < argc; i++) {
1108 r = sd_bus_call_method(
1110 "org.freedesktop.login1",
1111 "/org/freedesktop/login1",
1112 "org.freedesktop.login1.Manager",
1117 log_error("Could not terminate seat: %s", bus_error_message(&error, -r));
1125 static int help(int argc, char *argv[], void *userdata) {
1127 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
1128 "Send control commands to or query the login manager.\n\n"
1129 " -h --help Show this help\n"
1130 " --version Show package version\n"
1131 " --no-pager Do not pipe output into a pager\n"
1132 " --no-legend Do not show the headers and footers\n"
1133 " --no-ask-password Don't prompt for password\n"
1134 " -H --host=[USER@]HOST Operate on remote host\n"
1135 " -M --machine=CONTAINER Operate on local container\n"
1136 " -p --property=NAME Show only properties by this name\n"
1137 " -a --all Show all properties, including empty ones\n"
1138 " -l --full Do not ellipsize output\n"
1139 " --kill-who=WHO Who to send signal to\n"
1140 " -s --signal=SIGNAL Which signal to send\n"
1141 " -n --lines=INTEGER Number of journal entries to show\n"
1142 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
1143 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
1144 "Session Commands:\n"
1145 " list-sessions List sessions\n"
1146 " session-status [ID...] Show session status\n"
1147 " show-session [ID...] Show properties of sessions or the manager\n"
1148 " activate ID Activate a session\n"
1149 " lock-session ID... Screen lock one or more sessions\n"
1150 " unlock-session ID... Screen unlock one or more sessions\n"
1151 " lock-sessions Screen lock all current sessions\n"
1152 " unlock-sessions Screen unlock all current sessions\n"
1153 " terminate-session ID... Terminate one or more sessions\n"
1154 " kill-session ID... Send signal to processes of a session\n\n"
1156 " list-users List users\n"
1157 " user-status [USER...] Show user status\n"
1158 " show-user [USER...] Show properties of users or the manager\n"
1159 " enable-linger USER... Enable linger state of one or more users\n"
1160 " disable-linger USER... Disable linger state of one or more users\n"
1161 " terminate-user USER... Terminate all sessions of one or more users\n"
1162 " kill-user USER... Send signal to processes of a user\n\n"
1164 " list-seats List seats\n"
1165 " seat-status [NAME...] Show seat status\n"
1166 " show-seat [NAME...] Show properties of seats or the manager\n"
1167 " attach NAME DEVICE... Attach one or more devices to a seat\n"
1168 " flush-devices Flush all device associations\n"
1169 " terminate-seat NAME... Terminate all sessions on one or more seats\n"
1170 , program_invocation_short_name);
1175 static int parse_argv(int argc, char *argv[]) {
1178 ARG_VERSION = 0x100,
1182 ARG_NO_ASK_PASSWORD,
1185 static const struct option options[] = {
1186 { "help", no_argument, NULL, 'h' },
1187 { "version", no_argument, NULL, ARG_VERSION },
1188 { "property", required_argument, NULL, 'p' },
1189 { "all", no_argument, NULL, 'a' },
1190 { "full", no_argument, NULL, 'l' },
1191 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
1192 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
1193 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
1194 { "signal", required_argument, NULL, 's' },
1195 { "host", required_argument, NULL, 'H' },
1196 { "machine", required_argument, NULL, 'M' },
1197 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
1198 { "lines", required_argument, NULL, 'n' },
1199 { "output", required_argument, NULL, 'o' },
1208 while ((c = getopt_long(argc, argv, "hp:als:H:M:n:o:", options, NULL)) >= 0)
1213 help(0, NULL, NULL);
1217 puts(PACKAGE_STRING);
1218 puts(SYSTEMD_FEATURES);
1222 r = strv_extend(&arg_property, optarg);
1226 /* If the user asked for a particular
1227 * property, show it to him, even if it is
1242 if (safe_atou(optarg, &arg_lines) < 0) {
1243 log_error("Failed to parse lines '%s'", optarg);
1249 arg_output = output_mode_from_string(optarg);
1250 if (arg_output < 0) {
1251 log_error("Unknown output '%s'.", optarg);
1257 arg_no_pager = true;
1264 case ARG_NO_ASK_PASSWORD:
1265 arg_ask_password = false;
1269 arg_kill_who = optarg;
1273 arg_signal = signal_from_string_try_harder(optarg);
1274 if (arg_signal < 0) {
1275 log_error("Failed to parse signal string %s.", optarg);
1281 arg_transport = BUS_TRANSPORT_REMOTE;
1286 arg_transport = BUS_TRANSPORT_MACHINE;
1294 assert_not_reached("Unhandled option");
1300 static int loginctl_main(int argc, char *argv[], sd_bus *bus) {
1302 static const Verb verbs[] = {
1303 { "help", VERB_ANY, VERB_ANY, 0, help },
1304 { "list-sessions", VERB_ANY, 1, VERB_DEFAULT, list_sessions },
1305 { "session-status", VERB_ANY, VERB_ANY, 0, show_session },
1306 { "show-session", VERB_ANY, VERB_ANY, 0, show_session },
1307 { "activate", 2, 2, 0, activate },
1308 { "lock-session", 2, VERB_ANY, 0, activate },
1309 { "unlock-session", 2, VERB_ANY, 0, activate },
1310 { "lock-sessions", VERB_ANY, 1, 0, lock_sessions },
1311 { "unlock-sessions", VERB_ANY, 1, 0, lock_sessions },
1312 { "terminate-session", 2, VERB_ANY, 0, activate },
1313 { "kill-session", 2, VERB_ANY, 0, kill_session },
1314 { "list-users", VERB_ANY, 1, 0, list_users },
1315 { "user-status", VERB_ANY, VERB_ANY, 0, show_user },
1316 { "show-user", VERB_ANY, VERB_ANY, 0, show_user },
1317 { "enable-linger", 2, VERB_ANY, 0, enable_linger },
1318 { "disable-linger", 2, VERB_ANY, 0, enable_linger },
1319 { "terminate-user", 2, VERB_ANY, 0, terminate_user },
1320 { "kill-user", 2, VERB_ANY, 0, kill_user },
1321 { "list-seats", VERB_ANY, 1, 0, list_seats },
1322 { "seat-status", VERB_ANY, VERB_ANY, 0, show_seat },
1323 { "show-seat", VERB_ANY, VERB_ANY, 0, show_seat },
1324 { "attach", 3, VERB_ANY, 0, attach },
1325 { "flush-devices", VERB_ANY, 1, 0, flush_devices },
1326 { "terminate-seat", 2, VERB_ANY, 0, terminate_seat },
1330 return dispatch_verb(argc, argv, verbs, bus);
1333 int main(int argc, char *argv[]) {
1334 _cleanup_bus_close_unref_ sd_bus *bus = NULL;
1337 setlocale(LC_ALL, "");
1338 log_parse_environment();
1341 r = parse_argv(argc, argv);
1345 r = bus_open_transport(arg_transport, arg_host, false, &bus);
1347 log_error_errno(r, "Failed to create bus connection: %m");
1351 r = loginctl_main(argc, argv, bus);
1355 polkit_agent_close();
1357 strv_free(arg_property);
1359 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;