chiark / gitweb /
systemctl: add --value option
[elogind.git] / src / login / loginctl.c
1 /***
2   This file is part of systemd.
3
4   Copyright 2010 Lennart Poettering
5
6   systemd is free software; you can redistribute it and/or modify it
7   under the terms of the GNU Lesser General Public License as published by
8   the Free Software Foundation; either version 2.1 of the License, or
9   (at your option) any later version.
10
11   systemd is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14   Lesser General Public License for more details.
15
16   You should have received a copy of the GNU Lesser General Public License
17   along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #include <errno.h>
21 #include <getopt.h>
22 #include <locale.h>
23 #include <string.h>
24 #include <unistd.h>
25
26 #include "sd-bus.h"
27
28 #include "alloc-util.h"
29 #include "bus-error.h"
30 #include "bus-util.h"
31 //#include "cgroup-show.h"
32 #include "cgroup-util.h"
33 #include "log.h"
34 //#include "logs-show.h"
35 #include "macro.h"
36 #include "pager.h"
37 #include "parse-util.h"
38 #include "process-util.h"
39 #include "signal-util.h"
40 #include "spawn-polkit-agent.h"
41 #include "strv.h"
42 #include "sysfs-show.h"
43 #include "terminal-util.h"
44 #include "unit-name.h"
45 #include "user-util.h"
46 #include "util.h"
47 #include "verbs.h"
48
49 /// Additional includes for elogind
50 #include "logind-action.h"
51 #include "musl_missing.h"
52 #include "sd-login.h"
53 #include "virt.h"
54
55 static char **arg_property = NULL;
56 static bool arg_all = false;
57 static bool arg_full = false;
58 static bool arg_no_pager = false;
59 static bool arg_legend = true;
60 static const char *arg_kill_who = NULL;
61 static int arg_signal = SIGTERM;
62 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
63 static char *arg_host = NULL;
64 static bool arg_ask_password = true;
65 static bool arg_ignore_inhibitors = false;
66 #if 0
67 static unsigned arg_lines = 10;
68 static OutputMode arg_output = OUTPUT_SHORT;
69 #endif // 0
70 static enum action {
71         _ACTION_INVALID,
72         ACTION_POWEROFF,
73         ACTION_REBOOT,
74         ACTION_SUSPEND,
75         ACTION_HIBERNATE,
76         ACTION_HYBRID_SLEEP,
77         ACTION_CANCEL_SHUTDOWN,
78         _ACTION_MAX
79 } arg_action;
80
81
82 static void pager_open_if_enabled(void) {
83
84         if (arg_no_pager)
85                 return;
86
87         pager_open(false);
88 }
89
90 static void polkit_agent_open_if_enabled(void) {
91
92         /* Open the polkit agent as a child process if necessary */
93
94         if (!arg_ask_password)
95                 return;
96
97         if (arg_transport != BUS_TRANSPORT_LOCAL)
98                 return;
99
100         polkit_agent_open();
101 }
102
103 #if 0 /// UNNEEDED by elogind
104 static OutputFlags get_output_flags(void) {
105
106         return
107                 arg_all * OUTPUT_SHOW_ALL |
108                 arg_full * OUTPUT_FULL_WIDTH |
109                 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
110                 colors_enabled() * OUTPUT_COLOR;
111 }
112 #endif // 0
113
114 static int list_sessions(int argc, char *argv[], void *userdata) {
115         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
116         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
117         const char *id, *user, *seat, *object;
118         sd_bus *bus = userdata;
119         unsigned k = 0;
120         uint32_t uid;
121         int r;
122
123         assert(bus);
124         assert(argv);
125
126         pager_open_if_enabled();
127
128         r = sd_bus_call_method(
129                         bus,
130                         "org.freedesktop.login1",
131                         "/org/freedesktop/login1",
132                         "org.freedesktop.login1.Manager",
133                         "ListSessions",
134                         &error, &reply,
135                         "");
136         if (r < 0) {
137                 log_error("Failed to list sessions: %s", bus_error_message(&error, r));
138                 return r;
139         }
140
141         r = sd_bus_message_enter_container(reply, 'a', "(susso)");
142         if (r < 0)
143                 return bus_log_parse_error(r);
144
145         if (arg_legend)
146                 printf("%10s %10s %-16s %-16s\n", "SESSION", "UID", "USER", "SEAT");
147
148         while ((r = sd_bus_message_read(reply, "(susso)", &id, &uid, &user, &seat, &object)) > 0) {
149                 printf("%10s %10u %-16s %-16s\n", id, (unsigned) uid, user, seat);
150                 k++;
151         }
152         if (r < 0)
153                 return bus_log_parse_error(r);
154
155         if (arg_legend)
156                 printf("\n%u sessions listed.\n", k);
157
158         return 0;
159 }
160
161 static int list_users(int argc, char *argv[], void *userdata) {
162         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
163         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
164         const char *user, *object;
165         sd_bus *bus = userdata;
166         unsigned k = 0;
167         uint32_t uid;
168         int r;
169
170         assert(bus);
171         assert(argv);
172
173         pager_open_if_enabled();
174
175         r = sd_bus_call_method(
176                         bus,
177                         "org.freedesktop.login1",
178                         "/org/freedesktop/login1",
179                         "org.freedesktop.login1.Manager",
180                         "ListUsers",
181                         &error, &reply,
182                         "");
183         if (r < 0) {
184                 log_error("Failed to list users: %s", bus_error_message(&error, r));
185                 return r;
186         }
187
188         r = sd_bus_message_enter_container(reply, 'a', "(uso)");
189         if (r < 0)
190                 return bus_log_parse_error(r);
191
192         if (arg_legend)
193                 printf("%10s %-16s\n", "UID", "USER");
194
195         while ((r = sd_bus_message_read(reply, "(uso)", &uid, &user, &object)) > 0) {
196                 printf("%10u %-16s\n", (unsigned) uid, user);
197                 k++;
198         }
199         if (r < 0)
200                 return bus_log_parse_error(r);
201
202         if (arg_legend)
203                 printf("\n%u users listed.\n", k);
204
205         return 0;
206 }
207
208 static int list_seats(int argc, char *argv[], void *userdata) {
209         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
210         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
211         const char *seat, *object;
212         sd_bus *bus = userdata;
213         unsigned k = 0;
214         int r;
215
216         assert(bus);
217         assert(argv);
218
219         pager_open_if_enabled();
220
221         r = sd_bus_call_method(
222                         bus,
223                         "org.freedesktop.login1",
224                         "/org/freedesktop/login1",
225                         "org.freedesktop.login1.Manager",
226                         "ListSeats",
227                         &error, &reply,
228                         "");
229         if (r < 0) {
230                 log_error("Failed to list seats: %s", bus_error_message(&error, r));
231                 return r;
232         }
233
234         r = sd_bus_message_enter_container(reply, 'a', "(so)");
235         if (r < 0)
236                 return bus_log_parse_error(r);
237
238         if (arg_legend)
239                 printf("%-16s\n", "SEAT");
240
241         while ((r = sd_bus_message_read(reply, "(so)", &seat, &object)) > 0) {
242                 printf("%-16s\n", seat);
243                 k++;
244         }
245         if (r < 0)
246                 return bus_log_parse_error(r);
247
248         if (arg_legend)
249                 printf("\n%u seats listed.\n", k);
250
251         return 0;
252 }
253
254 #if 0 /// UNNEEDED by elogind
255 static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit, pid_t leader) {
256         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
257         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
258         _cleanup_free_ char *path = NULL;
259         const char *cgroup;
260         int r;
261         unsigned c;
262
263         assert(bus);
264         assert(unit);
265
266         if (arg_transport != BUS_TRANSPORT_LOCAL)
267                 return 0;
268
269         path = unit_dbus_path_from_name(unit);
270         if (!path)
271                 return -ENOMEM;
272
273         r = sd_bus_get_property(
274                         bus,
275                         "org.freedesktop.systemd1",
276                         path,
277                         interface,
278                         "ControlGroup",
279                         &error, &reply, "s");
280         if (r < 0)
281                 return r;
282
283         r = sd_bus_message_read(reply, "s", &cgroup);
284         if (r < 0)
285                 return r;
286
287         if (isempty(cgroup))
288                 return 0;
289
290         if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup) != 0 && leader <= 0)
291                 return 0;
292
293         c = columns();
294         if (c > 18)
295                 c -= 18;
296         else
297                 c = 0;
298
299         show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t  ", c, false, &leader, leader > 0, get_output_flags());
300         return 0;
301 }
302 #endif // 0
303
304 typedef struct SessionStatusInfo {
305         char *id;
306         uid_t uid;
307         char *name;
308         struct dual_timestamp timestamp;
309         unsigned int vtnr;
310         char *seat;
311         char *tty;
312         char *display;
313         bool remote;
314         char *remote_host;
315         char *remote_user;
316         char *service;
317         pid_t leader;
318         char *type;
319         char *class;
320         char *state;
321         char *scope;
322         char *desktop;
323 } SessionStatusInfo;
324
325 typedef struct UserStatusInfo {
326         uid_t uid;
327         char *name;
328         struct dual_timestamp timestamp;
329         char *state;
330         char **sessions;
331         char *display;
332         char *slice;
333 } UserStatusInfo;
334
335 typedef struct SeatStatusInfo {
336         char *id;
337         char *active_session;
338         char **sessions;
339 } SeatStatusInfo;
340
341 static void session_status_info_clear(SessionStatusInfo *info) {
342         if (info) {
343                 free(info->id);
344                 free(info->name);
345                 free(info->seat);
346                 free(info->tty);
347                 free(info->display);
348                 free(info->remote_host);
349                 free(info->remote_user);
350                 free(info->service);
351                 free(info->type);
352                 free(info->class);
353                 free(info->state);
354                 free(info->scope);
355                 free(info->desktop);
356                 zero(*info);
357         }
358 }
359
360 static void user_status_info_clear(UserStatusInfo *info) {
361         if (info) {
362                 free(info->name);
363                 free(info->state);
364                 strv_free(info->sessions);
365                 free(info->display);
366                 free(info->slice);
367                 zero(*info);
368         }
369 }
370
371 static void seat_status_info_clear(SeatStatusInfo *info) {
372         if (info) {
373                 free(info->id);
374                 free(info->active_session);
375                 strv_free(info->sessions);
376                 zero(*info);
377         }
378 }
379
380 static int prop_map_first_of_struct(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
381         const char *contents;
382         int r;
383
384         r = sd_bus_message_peek_type(m, NULL, &contents);
385         if (r < 0)
386                 return r;
387
388         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, contents);
389         if (r < 0)
390                 return r;
391
392         if (contents[0] == 's' || contents[0] == 'o') {
393                 const char *s;
394                 char **p = (char **) userdata;
395
396                 r = sd_bus_message_read_basic(m, contents[0], &s);
397                 if (r < 0)
398                         return r;
399
400                 r = free_and_strdup(p, s);
401                 if (r < 0)
402                         return r;
403         } else {
404                 r = sd_bus_message_read_basic(m, contents[0], userdata);
405                 if (r < 0)
406                         return r;
407         }
408
409         r = sd_bus_message_skip(m, contents+1);
410         if (r < 0)
411                 return r;
412
413         r = sd_bus_message_exit_container(m);
414         if (r < 0)
415                 return r;
416
417         return 0;
418 }
419
420 static int prop_map_sessions_strv(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
421         const char *name;
422         int r;
423
424         assert(bus);
425         assert(m);
426
427         r = sd_bus_message_enter_container(m, 'a', "(so)");
428         if (r < 0)
429                 return r;
430
431         while ((r = sd_bus_message_read(m, "(so)", &name, NULL)) > 0) {
432                 r = strv_extend(userdata, name);
433                 if (r < 0)
434                         return r;
435         }
436         if (r < 0)
437                 return r;
438
439         return sd_bus_message_exit_container(m);
440 }
441
442 static int print_session_status_info(sd_bus *bus, const char *path, bool *new_line) {
443
444         static const struct bus_properties_map map[]  = {
445                 { "Id",                  "s",    NULL,                     offsetof(SessionStatusInfo, id)                  },
446                 { "Name",                "s",    NULL,                     offsetof(SessionStatusInfo, name)                },
447                 { "TTY",                 "s",    NULL,                     offsetof(SessionStatusInfo, tty)                 },
448                 { "Display",             "s",    NULL,                     offsetof(SessionStatusInfo, display)             },
449                 { "RemoteHost",          "s",    NULL,                     offsetof(SessionStatusInfo, remote_host)         },
450                 { "RemoteUser",          "s",    NULL,                     offsetof(SessionStatusInfo, remote_user)         },
451                 { "Service",             "s",    NULL,                     offsetof(SessionStatusInfo, service)             },
452                 { "Desktop",             "s",    NULL,                     offsetof(SessionStatusInfo, desktop)             },
453                 { "Type",                "s",    NULL,                     offsetof(SessionStatusInfo, type)                },
454                 { "Class",               "s",    NULL,                     offsetof(SessionStatusInfo, class)               },
455                 { "Scope",               "s",    NULL,                     offsetof(SessionStatusInfo, scope)               },
456                 { "State",               "s",    NULL,                     offsetof(SessionStatusInfo, state)               },
457                 { "VTNr",                "u",    NULL,                     offsetof(SessionStatusInfo, vtnr)                },
458                 { "Leader",              "u",    NULL,                     offsetof(SessionStatusInfo, leader)              },
459                 { "Remote",              "b",    NULL,                     offsetof(SessionStatusInfo, remote)              },
460                 { "Timestamp",           "t",    NULL,                     offsetof(SessionStatusInfo, timestamp.realtime)  },
461                 { "TimestampMonotonic",  "t",    NULL,                     offsetof(SessionStatusInfo, timestamp.monotonic) },
462                 { "User",                "(uo)", prop_map_first_of_struct, offsetof(SessionStatusInfo, uid)                 },
463                 { "Seat",                "(so)", prop_map_first_of_struct, offsetof(SessionStatusInfo, seat)                },
464                 {}
465         };
466
467         char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
468         char since2[FORMAT_TIMESTAMP_MAX], *s2;
469         _cleanup_(session_status_info_clear) SessionStatusInfo i = {};
470         int r;
471
472         r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i);
473         if (r < 0)
474                 return log_error_errno(r, "Could not get properties: %m");
475
476         if (*new_line)
477                 printf("\n");
478
479         *new_line = true;
480
481         printf("%s - ", strna(i.id));
482
483         if (i.name)
484                 printf("%s (%u)\n", i.name, (unsigned) i.uid);
485         else
486                 printf("%u\n", (unsigned) i.uid);
487
488         s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime);
489         s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime);
490
491         if (s1)
492                 printf("\t   Since: %s; %s\n", s2, s1);
493         else if (s2)
494                 printf("\t   Since: %s\n", s2);
495
496         if (i.leader > 0) {
497                 _cleanup_free_ char *t = NULL;
498
499                 printf("\t  Leader: %u", (unsigned) i.leader);
500
501                 get_process_comm(i.leader, &t);
502                 if (t)
503                         printf(" (%s)", t);
504
505                 printf("\n");
506         }
507
508         if (!isempty(i.seat)) {
509                 printf("\t    Seat: %s", i.seat);
510
511                 if (i.vtnr > 0)
512                         printf("; vc%u", i.vtnr);
513
514                 printf("\n");
515         }
516
517         if (i.tty)
518                 printf("\t     TTY: %s\n", i.tty);
519         else if (i.display)
520                 printf("\t Display: %s\n", i.display);
521
522         if (i.remote_host && i.remote_user)
523                 printf("\t  Remote: %s@%s\n", i.remote_user, i.remote_host);
524         else if (i.remote_host)
525                 printf("\t  Remote: %s\n", i.remote_host);
526         else if (i.remote_user)
527                 printf("\t  Remote: user %s\n", i.remote_user);
528         else if (i.remote)
529                 printf("\t  Remote: Yes\n");
530
531         if (i.service) {
532                 printf("\t Service: %s", i.service);
533
534                 if (i.type)
535                         printf("; type %s", i.type);
536
537                 if (i.class)
538                         printf("; class %s", i.class);
539
540                 printf("\n");
541         } else if (i.type) {
542                 printf("\t    Type: %s", i.type);
543
544                 if (i.class)
545                         printf("; class %s", i.class);
546
547                 printf("\n");
548         } else if (i.class)
549                 printf("\t   Class: %s\n", i.class);
550
551         if (!isempty(i.desktop))
552                 printf("\t Desktop: %s\n", i.desktop);
553
554         if (i.state)
555                 printf("\t   State: %s\n", i.state);
556
557         if (i.scope) {
558                 printf("\t    Unit: %s\n", i.scope);
559 #if 0
560                 show_unit_cgroup(bus, "org.freedesktop.systemd1.Scope", i.scope, i.leader);
561                 if (arg_transport == BUS_TRANSPORT_LOCAL) {
562
563                         show_journal_by_unit(
564                                         stdout,
565                                         i.scope,
566                                         arg_output,
567                                         0,
568                                         i.timestamp.monotonic,
569                                         arg_lines,
570                                         0,
571                                         get_output_flags() | OUTPUT_BEGIN_NEWLINE,
572                                         SD_JOURNAL_LOCAL_ONLY,
573                                         true,
574                                         NULL);
575                 }
576
577 #endif // 0
578         }
579
580         return 0;
581 }
582
583 static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line) {
584
585         static const struct bus_properties_map map[]  = {
586                 { "Name",               "s",     NULL,                     offsetof(UserStatusInfo, name)                },
587                 { "Slice",              "s",     NULL,                     offsetof(UserStatusInfo, slice)               },
588                 { "State",              "s",     NULL,                     offsetof(UserStatusInfo, state)               },
589                 { "UID",                "u",     NULL,                     offsetof(UserStatusInfo, uid)                 },
590                 { "Timestamp",          "t",     NULL,                     offsetof(UserStatusInfo, timestamp.realtime)  },
591                 { "TimestampMonotonic", "t",     NULL,                     offsetof(UserStatusInfo, timestamp.monotonic) },
592                 { "Display",            "(so)",  prop_map_first_of_struct, offsetof(UserStatusInfo, display)             },
593                 { "Sessions",           "a(so)", prop_map_sessions_strv,   offsetof(UserStatusInfo, sessions)            },
594                 {}
595         };
596
597         char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
598         char since2[FORMAT_TIMESTAMP_MAX], *s2;
599         _cleanup_(user_status_info_clear) UserStatusInfo i = {};
600         int r;
601
602         r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i);
603         if (r < 0)
604                 return log_error_errno(r, "Could not get properties: %m");
605
606         if (*new_line)
607                 printf("\n");
608
609         *new_line = true;
610
611         if (i.name)
612                 printf("%s (%u)\n", i.name, (unsigned) i.uid);
613         else
614                 printf("%u\n", (unsigned) i.uid);
615
616         s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime);
617         s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime);
618
619         if (s1)
620                 printf("\t   Since: %s; %s\n", s2, s1);
621         else if (s2)
622                 printf("\t   Since: %s\n", s2);
623
624         if (!isempty(i.state))
625                 printf("\t   State: %s\n", i.state);
626
627         if (!strv_isempty(i.sessions)) {
628                 char **l;
629                 printf("\tSessions:");
630
631                 STRV_FOREACH(l, i.sessions) {
632                         if (streq_ptr(*l, i.display))
633                                 printf(" *%s", *l);
634                         else
635                                 printf(" %s", *l);
636                 }
637
638                 printf("\n");
639         }
640
641         if (i.slice) {
642                 printf("\t    Unit: %s\n", i.slice);
643 #if 0
644                 show_unit_cgroup(bus, "org.freedesktop.systemd1.Slice", i.slice, 0);
645                 show_journal_by_unit(
646                                 stdout,
647                                 i.slice,
648                                 arg_output,
649                                 0,
650                                 i.timestamp.monotonic,
651                                 arg_lines,
652                                 0,
653                                 get_output_flags() | OUTPUT_BEGIN_NEWLINE,
654                                 SD_JOURNAL_LOCAL_ONLY,
655                                 true,
656                                 NULL);
657
658 #endif // 0
659         }
660
661         return 0;
662 }
663
664 static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line) {
665
666         static const struct bus_properties_map map[]  = {
667                 { "Id",            "s",     NULL, offsetof(SeatStatusInfo, id) },
668                 { "ActiveSession", "(so)",  prop_map_first_of_struct, offsetof(SeatStatusInfo, active_session) },
669                 { "Sessions",      "a(so)", prop_map_sessions_strv, offsetof(SeatStatusInfo, sessions) },
670                 {}
671         };
672
673         _cleanup_(seat_status_info_clear) SeatStatusInfo i = {};
674         int r;
675
676         r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i);
677         if (r < 0)
678                 return log_error_errno(r, "Could not get properties: %m");
679
680         if (*new_line)
681                 printf("\n");
682
683         *new_line = true;
684
685         printf("%s\n", strna(i.id));
686
687         if (!strv_isempty(i.sessions)) {
688                 char **l;
689                 printf("\tSessions:");
690
691                 STRV_FOREACH(l, i.sessions) {
692                         if (streq_ptr(*l, i.active_session))
693                                 printf(" *%s", *l);
694                         else
695                                 printf(" %s", *l);
696                 }
697
698                 printf("\n");
699         }
700
701         if (arg_transport == BUS_TRANSPORT_LOCAL) {
702                 unsigned c;
703
704                 c = columns();
705                 if (c > 21)
706                         c -= 21;
707                 else
708                         c = 0;
709
710                 printf("\t Devices:\n");
711
712                 show_sysfs(i.id, "\t\t  ", c);
713         }
714
715         return 0;
716 }
717
718 static int print_property(const char *name, sd_bus_message *m, const char *contents) {
719         int r;
720
721         assert(name);
722         assert(m);
723         assert(contents);
724
725         if (arg_property && !strv_find(arg_property, name))
726                 /* skip what we didn't read */
727                 return sd_bus_message_skip(m, contents);
728
729         switch (contents[0]) {
730
731         case SD_BUS_TYPE_STRUCT_BEGIN:
732
733                 if (contents[1] == SD_BUS_TYPE_STRING && STR_IN_SET(name, "Display", "Seat", "ActiveSession")) {
734                         const char *s;
735
736                         r = sd_bus_message_read(m, "(so)", &s, NULL);
737                         if (r < 0)
738                                 return bus_log_parse_error(r);
739
740                         if (arg_all || !isempty(s))
741                                 printf("%s=%s\n", name, s);
742
743                         return 0;
744
745                 } else if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "User")) {
746                         uint32_t uid;
747
748                         r = sd_bus_message_read(m, "(uo)", &uid, NULL);
749                         if (r < 0)
750                                 return bus_log_parse_error(r);
751
752                         if (!uid_is_valid(uid)) {
753                                 log_error("Invalid user ID: " UID_FMT, uid);
754                                 return -EINVAL;
755                         }
756
757                         printf("%s=" UID_FMT "\n", name, uid);
758
759                         return 0;
760                 }
761
762                 break;
763
764         case SD_BUS_TYPE_ARRAY:
765
766                 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Sessions")) {
767                         const char *s;
768                         bool space = false;
769
770                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(so)");
771                         if (r < 0)
772                                 return bus_log_parse_error(r);
773
774                         printf("%s=", name);
775
776                         while ((r = sd_bus_message_read(m, "(so)", &s, NULL)) > 0) {
777                                 printf("%s%s", space ? " " : "", s);
778                                 space = true;
779                         }
780
781                         printf("\n");
782
783                         if (r < 0)
784                                 return bus_log_parse_error(r);
785
786                         r = sd_bus_message_exit_container(m);
787                         if (r < 0)
788                                 return bus_log_parse_error(r);
789
790                         return 0;
791                 }
792
793                 break;
794         }
795
796         r = bus_print_property(name, m, false, arg_all);
797         if (r < 0)
798                 return bus_log_parse_error(r);
799
800         if (r == 0) {
801                 r = sd_bus_message_skip(m, contents);
802                 if (r < 0)
803                         return bus_log_parse_error(r);
804
805                 if (arg_all)
806                         printf("%s=[unprintable]\n", name);
807         }
808
809         return 0;
810 }
811
812 static int show_properties(sd_bus *bus, const char *path, bool *new_line) {
813         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
814         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
815         int r;
816
817         assert(bus);
818         assert(path);
819         assert(new_line);
820
821         r = sd_bus_call_method(
822                         bus,
823                         "org.freedesktop.login1",
824                         path,
825                         "org.freedesktop.DBus.Properties",
826                         "GetAll",
827                         &error,
828                         &reply,
829                         "s", "");
830         if (r < 0)
831                 return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r));
832
833         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
834         if (r < 0)
835                 return bus_log_parse_error(r);
836
837         if (*new_line)
838                 printf("\n");
839
840         *new_line = true;
841
842         while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
843                 const char *name, *contents;
844
845                 r = sd_bus_message_read(reply, "s", &name);
846                 if (r < 0)
847                         return bus_log_parse_error(r);
848
849                 r = sd_bus_message_peek_type(reply, NULL, &contents);
850                 if (r < 0)
851                         return bus_log_parse_error(r);
852
853                 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
854                 if (r < 0)
855                         return bus_log_parse_error(r);
856
857                 r = print_property(name, reply, contents);
858                 if (r < 0)
859                         return r;
860
861                 r = sd_bus_message_exit_container(reply);
862                 if (r < 0)
863                         return bus_log_parse_error(r);
864
865                 r = sd_bus_message_exit_container(reply);
866                 if (r < 0)
867                         return bus_log_parse_error(r);
868         }
869         if (r < 0)
870                 return bus_log_parse_error(r);
871
872         r = sd_bus_message_exit_container(reply);
873         if (r < 0)
874                 return bus_log_parse_error(r);
875
876         return 0;
877 }
878
879 static int show_session(int argc, char *argv[], void *userdata) {
880         bool properties, new_line = false;
881         sd_bus *bus = userdata;
882         int r, i;
883
884         assert(bus);
885         assert(argv);
886
887         properties = !strstr(argv[0], "status");
888
889         pager_open_if_enabled();
890
891         if (argc <= 1) {
892                 /* If not argument is specified inspect the manager
893                  * itself */
894                 if (properties)
895                         return show_properties(bus, "/org/freedesktop/login1", &new_line);
896
897                 /* And in the pretty case, show data of the calling session */
898                 return print_session_status_info(bus, "/org/freedesktop/login1/session/self", &new_line);
899         }
900
901         for (i = 1; i < argc; i++) {
902                 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
903                 _cleanup_(sd_bus_message_unrefp) sd_bus_message * reply = NULL;
904                 const char *path = NULL;
905
906                 r = sd_bus_call_method(
907                                 bus,
908                                 "org.freedesktop.login1",
909                                 "/org/freedesktop/login1",
910                                 "org.freedesktop.login1.Manager",
911                                 "GetSession",
912                                 &error, &reply,
913                                 "s", argv[i]);
914                 if (r < 0) {
915                         log_error("Failed to get session: %s", bus_error_message(&error, r));
916                         return r;
917                 }
918
919                 r = sd_bus_message_read(reply, "o", &path);
920                 if (r < 0)
921                         return bus_log_parse_error(r);
922
923                 if (properties)
924                         r = show_properties(bus, path, &new_line);
925                 else
926                         r = print_session_status_info(bus, path, &new_line);
927
928                 if (r < 0)
929                         return r;
930         }
931
932         return 0;
933 }
934
935 static int show_user(int argc, char *argv[], void *userdata) {
936         bool properties, new_line = false;
937         sd_bus *bus = userdata;
938         int r, i;
939
940         assert(bus);
941         assert(argv);
942
943         properties = !strstr(argv[0], "status");
944
945         pager_open_if_enabled();
946
947         if (argc <= 1) {
948                 /* If not argument is specified inspect the manager
949                  * itself */
950                 if (properties)
951                         return show_properties(bus, "/org/freedesktop/login1", &new_line);
952
953                 return print_user_status_info(bus, "/org/freedesktop/login1/user/self", &new_line);
954         }
955
956         for (i = 1; i < argc; i++) {
957                 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
958                 _cleanup_(sd_bus_message_unrefp) sd_bus_message * reply = NULL;
959                 const char *path = NULL;
960                 uid_t uid;
961
962                 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
963                 if (r < 0)
964                         return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
965
966                 r = sd_bus_call_method(
967                                 bus,
968                                 "org.freedesktop.login1",
969                                 "/org/freedesktop/login1",
970                                 "org.freedesktop.login1.Manager",
971                                 "GetUser",
972                                 &error, &reply,
973                                 "u", (uint32_t) uid);
974                 if (r < 0) {
975                         log_error("Failed to get user: %s", bus_error_message(&error, r));
976                         return r;
977                 }
978
979                 r = sd_bus_message_read(reply, "o", &path);
980                 if (r < 0)
981                         return bus_log_parse_error(r);
982
983                 if (properties)
984                         r = show_properties(bus, path, &new_line);
985                 else
986                         r = print_user_status_info(bus, path, &new_line);
987
988                 if (r < 0)
989                         return r;
990         }
991
992         return 0;
993 }
994
995 static int show_seat(int argc, char *argv[], void *userdata) {
996         bool properties, new_line = false;
997         sd_bus *bus = userdata;
998         int r, i;
999
1000         assert(bus);
1001         assert(argv);
1002
1003         properties = !strstr(argv[0], "status");
1004
1005         pager_open_if_enabled();
1006
1007         if (argc <= 1) {
1008                 /* If not argument is specified inspect the manager
1009                  * itself */
1010                 if (properties)
1011                         return show_properties(bus, "/org/freedesktop/login1", &new_line);
1012
1013                 return print_seat_status_info(bus, "/org/freedesktop/login1/seat/self", &new_line);
1014         }
1015
1016         for (i = 1; i < argc; i++) {
1017                 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1018                 _cleanup_(sd_bus_message_unrefp) sd_bus_message * reply = NULL;
1019                 const char *path = NULL;
1020
1021                 r = sd_bus_call_method(
1022                                 bus,
1023                                 "org.freedesktop.login1",
1024                                 "/org/freedesktop/login1",
1025                                 "org.freedesktop.login1.Manager",
1026                                 "GetSeat",
1027                                 &error, &reply,
1028                                 "s", argv[i]);
1029                 if (r < 0) {
1030                         log_error("Failed to get seat: %s", bus_error_message(&error, r));
1031                         return r;
1032                 }
1033
1034                 r = sd_bus_message_read(reply, "o", &path);
1035                 if (r < 0)
1036                         return bus_log_parse_error(r);
1037
1038                 if (properties)
1039                         r = show_properties(bus, path, &new_line);
1040                 else
1041                         r = print_seat_status_info(bus, path, &new_line);
1042
1043                 if (r < 0)
1044                         return r;
1045         }
1046
1047         return 0;
1048 }
1049
1050 static int activate(int argc, char *argv[], void *userdata) {
1051         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1052         sd_bus *bus = userdata;
1053         char *short_argv[3];
1054         int r, i;
1055
1056         assert(bus);
1057         assert(argv);
1058
1059         polkit_agent_open_if_enabled();
1060
1061         if (argc < 2) {
1062                 /* No argument? Let's convert this into the empty
1063                  * session name, which the calls will then resolve to
1064                  * the caller's session. */
1065
1066                 short_argv[0] = argv[0];
1067                 short_argv[1] = (char*) "";
1068                 short_argv[2] = NULL;
1069
1070                 argv = short_argv;
1071                 argc = 2;
1072         }
1073
1074         for (i = 1; i < argc; i++) {
1075
1076                 r = sd_bus_call_method(
1077                                 bus,
1078                                 "org.freedesktop.login1",
1079                                 "/org/freedesktop/login1",
1080                                 "org.freedesktop.login1.Manager",
1081                                 streq(argv[0], "lock-session")      ? "LockSession" :
1082                                 streq(argv[0], "unlock-session")    ? "UnlockSession" :
1083                                 streq(argv[0], "terminate-session") ? "TerminateSession" :
1084                                                                       "ActivateSession",
1085                                 &error, NULL,
1086                                 "s", argv[i]);
1087                 if (r < 0) {
1088                         log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
1089                         return r;
1090                 }
1091         }
1092
1093         return 0;
1094 }
1095
1096 static int kill_session(int argc, char *argv[], void *userdata) {
1097         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1098         sd_bus *bus = userdata;
1099         int r, i;
1100
1101         assert(bus);
1102         assert(argv);
1103
1104         polkit_agent_open_if_enabled();
1105
1106         if (!arg_kill_who)
1107                 arg_kill_who = "all";
1108
1109         for (i = 1; i < argc; i++) {
1110
1111                 r = sd_bus_call_method(
1112                         bus,
1113                         "org.freedesktop.login1",
1114                         "/org/freedesktop/login1",
1115                         "org.freedesktop.login1.Manager",
1116                         "KillSession",
1117                         &error, NULL,
1118                         "ssi", argv[i], arg_kill_who, arg_signal);
1119                 if (r < 0) {
1120                         log_error("Could not kill session: %s", bus_error_message(&error, -r));
1121                         return r;
1122                 }
1123         }
1124
1125         return 0;
1126 }
1127
1128 static int enable_linger(int argc, char *argv[], void *userdata) {
1129         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1130         sd_bus *bus = userdata;
1131         char* short_argv[3];
1132         bool b;
1133         int r, i;
1134
1135         assert(bus);
1136         assert(argv);
1137
1138         polkit_agent_open_if_enabled();
1139
1140         b = streq(argv[0], "enable-linger");
1141
1142         if (argc < 2) {
1143                 short_argv[0] = argv[0];
1144                 short_argv[1] = (char*) "";
1145                 short_argv[2] = NULL;
1146                 argv = short_argv;
1147                 argc = 2;
1148         }
1149
1150         for (i = 1; i < argc; i++) {
1151                 uid_t uid;
1152
1153                 if (isempty(argv[i]))
1154                         uid = UID_INVALID;
1155                 else {
1156                         r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
1157                         if (r < 0)
1158                                 return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
1159                 }
1160
1161                 r = sd_bus_call_method(
1162                         bus,
1163                         "org.freedesktop.login1",
1164                         "/org/freedesktop/login1",
1165                         "org.freedesktop.login1.Manager",
1166                         "SetUserLinger",
1167                         &error, NULL,
1168                         "ubb", (uint32_t) uid, b, true);
1169                 if (r < 0) {
1170                         log_error("Could not enable linger: %s", bus_error_message(&error, -r));
1171                         return r;
1172                 }
1173         }
1174
1175         return 0;
1176 }
1177
1178 static int terminate_user(int argc, char *argv[], void *userdata) {
1179         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1180         sd_bus *bus = userdata;
1181         int r, i;
1182
1183         assert(bus);
1184         assert(argv);
1185
1186         polkit_agent_open_if_enabled();
1187
1188         for (i = 1; i < argc; i++) {
1189                 uid_t uid;
1190
1191                 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
1192                 if (r < 0)
1193                         return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
1194
1195                 r = sd_bus_call_method(
1196                         bus,
1197                         "org.freedesktop.login1",
1198                         "/org/freedesktop/login1",
1199                         "org.freedesktop.login1.Manager",
1200                         "TerminateUser",
1201                         &error, NULL,
1202                         "u", (uint32_t) uid);
1203                 if (r < 0) {
1204                         log_error("Could not terminate user: %s", bus_error_message(&error, -r));
1205                         return r;
1206                 }
1207         }
1208
1209         return 0;
1210 }
1211
1212 static int kill_user(int argc, char *argv[], void *userdata) {
1213         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1214         sd_bus *bus = userdata;
1215         int r, i;
1216
1217         assert(bus);
1218         assert(argv);
1219
1220         polkit_agent_open_if_enabled();
1221
1222         if (!arg_kill_who)
1223                 arg_kill_who = "all";
1224
1225         for (i = 1; i < argc; i++) {
1226                 uid_t uid;
1227
1228                 r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
1229                 if (r < 0)
1230                         return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
1231
1232                 r = sd_bus_call_method(
1233                         bus,
1234                         "org.freedesktop.login1",
1235                         "/org/freedesktop/login1",
1236                         "org.freedesktop.login1.Manager",
1237                         "KillUser",
1238                         &error, NULL,
1239                         "ui", (uint32_t) uid, arg_signal);
1240                 if (r < 0) {
1241                         log_error("Could not kill user: %s", bus_error_message(&error, -r));
1242                         return r;
1243                 }
1244         }
1245
1246         return 0;
1247 }
1248
1249 static int attach(int argc, char *argv[], void *userdata) {
1250         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1251         sd_bus *bus = userdata;
1252         int r, i;
1253
1254         assert(bus);
1255         assert(argv);
1256
1257         polkit_agent_open_if_enabled();
1258
1259         for (i = 2; i < argc; i++) {
1260
1261                 r = sd_bus_call_method(
1262                         bus,
1263                         "org.freedesktop.login1",
1264                         "/org/freedesktop/login1",
1265                         "org.freedesktop.login1.Manager",
1266                         "AttachDevice",
1267                         &error, NULL,
1268                         "ssb", argv[1], argv[i], true);
1269
1270                 if (r < 0) {
1271                         log_error("Could not attach device: %s", bus_error_message(&error, -r));
1272                         return r;
1273                 }
1274         }
1275
1276         return 0;
1277 }
1278
1279 static int flush_devices(int argc, char *argv[], void *userdata) {
1280         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1281         sd_bus *bus = userdata;
1282         int r;
1283
1284         assert(bus);
1285         assert(argv);
1286
1287         polkit_agent_open_if_enabled();
1288
1289         r = sd_bus_call_method(
1290                         bus,
1291                         "org.freedesktop.login1",
1292                         "/org/freedesktop/login1",
1293                         "org.freedesktop.login1.Manager",
1294                         "FlushDevices",
1295                         &error, NULL,
1296                         "b", true);
1297         if (r < 0)
1298                 log_error("Could not flush devices: %s", bus_error_message(&error, -r));
1299
1300         return r;
1301 }
1302
1303 static int lock_sessions(int argc, char *argv[], void *userdata) {
1304         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1305         sd_bus *bus = userdata;
1306         int r;
1307
1308         assert(bus);
1309         assert(argv);
1310
1311         polkit_agent_open_if_enabled();
1312
1313         r = sd_bus_call_method(
1314                         bus,
1315                         "org.freedesktop.login1",
1316                         "/org/freedesktop/login1",
1317                         "org.freedesktop.login1.Manager",
1318                         streq(argv[0], "lock-sessions") ? "LockSessions" : "UnlockSessions",
1319                         &error, NULL,
1320                         NULL);
1321         if (r < 0)
1322                 log_error("Could not lock sessions: %s", bus_error_message(&error, -r));
1323
1324         return r;
1325 }
1326
1327 static int terminate_seat(int argc, char *argv[], void *userdata) {
1328         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1329         sd_bus *bus = userdata;
1330         int r, i;
1331
1332         assert(bus);
1333         assert(argv);
1334
1335         polkit_agent_open_if_enabled();
1336
1337         for (i = 1; i < argc; i++) {
1338
1339                 r = sd_bus_call_method(
1340                         bus,
1341                         "org.freedesktop.login1",
1342                         "/org/freedesktop/login1",
1343                         "org.freedesktop.login1.Manager",
1344                         "TerminateSeat",
1345                         &error, NULL,
1346                         "s", argv[i]);
1347                 if (r < 0) {
1348                         log_error("Could not terminate seat: %s", bus_error_message(&error, -r));
1349                         return r;
1350                 }
1351         }
1352
1353         return 0;
1354 }
1355
1356 /* Ask elogind, which might grant access to unprivileged users
1357  * through PolicyKit */
1358 static int reboot_with_logind(sd_bus *bus, enum action a) {
1359         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1360         const char *method;
1361         int r;
1362         static const char *table[_ACTION_MAX] = {
1363                 [ACTION_REBOOT]          = "The system is going down for reboot NOW!",
1364                 [ACTION_POWEROFF]        = "The system is going down for power-off NOW!",
1365                 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
1366         };
1367
1368         if (!bus)
1369                 return -EIO;
1370
1371         polkit_agent_open_if_enabled();
1372
1373         switch (a) {
1374
1375         case ACTION_POWEROFF:
1376                 method = "PowerOff";
1377                 break;
1378
1379         case ACTION_REBOOT:
1380                 method = "Reboot";
1381                 break;
1382
1383         case ACTION_SUSPEND:
1384                 method = "Suspend";
1385                 break;
1386
1387         case ACTION_HIBERNATE:
1388                 method = "Hibernate";
1389                 break;
1390
1391         case ACTION_HYBRID_SLEEP:
1392                 method = "HybridSleep";
1393                 break;
1394
1395         case ACTION_CANCEL_SHUTDOWN:
1396                 method = "CancelScheduledShutdown";
1397                 break;
1398
1399         default:
1400                 return -EINVAL;
1401         }
1402
1403         if (table[a]) {
1404                 r = sd_bus_call_method(
1405                                bus,
1406                                "org.freedesktop.login1",
1407                                "/org/freedesktop/login1",
1408                                "org.freedesktop.login1.Manager",
1409                                "SetWallMessage",
1410                                &error,
1411                                NULL,
1412                                "sb",
1413                                table[a],
1414                                true);
1415
1416                 if (r < 0) {
1417                         log_warning_errno(r, "Failed to set wall message, ignoring: %s",
1418                                           bus_error_message(&error, r));
1419                         sd_bus_error_free(&error);
1420                 }
1421         }
1422
1423
1424         r = sd_bus_call_method(
1425                         bus,
1426                         "org.freedesktop.login1",
1427                         "/org/freedesktop/login1",
1428                         "org.freedesktop.login1.Manager",
1429                         method,
1430                         &error,
1431                         NULL,
1432                         "b", arg_ask_password);
1433         if (r < 0)
1434                 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
1435
1436         return r;
1437 }
1438
1439 static const struct {
1440         HandleAction action;
1441         const char*  verb;
1442 } action_table[_ACTION_MAX] = {
1443         [ACTION_POWEROFF]     = { HANDLE_POWEROFF,     "poweroff",    },
1444         [ACTION_REBOOT]       = { HANDLE_REBOOT,       "reboot",      },
1445         [ACTION_SUSPEND]      = { HANDLE_SUSPEND,      "suspend",     },
1446         [ACTION_HIBERNATE]    = { HANDLE_HIBERNATE,    "hibernate",   },
1447         [ACTION_HYBRID_SLEEP] = { HANDLE_HYBRID_SLEEP, "hybrid-sleep" },
1448 };
1449
1450 static enum action verb_to_action(const char *verb) {
1451         enum action i;
1452
1453         for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
1454                 if (streq_ptr(action_table[i].verb, verb))
1455                         return i;
1456
1457         return _ACTION_INVALID;
1458 }
1459
1460 static int check_inhibitors(sd_bus *bus, enum action a) {
1461         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1462         _cleanup_strv_free_ char **sessions = NULL;
1463         const char *what, *who, *why, *mode;
1464         uint32_t uid, pid;
1465         unsigned c = 0;
1466         char **s;
1467         int r;
1468
1469         if (!bus)
1470                 return 0;
1471
1472         if (arg_ignore_inhibitors)
1473                 return 0;
1474
1475         if (geteuid() == 0)
1476                 return 0;
1477
1478         if (!on_tty())
1479                 return 0;
1480
1481         r = sd_bus_call_method(
1482                         bus,
1483                         "org.freedesktop.login1",
1484                         "/org/freedesktop/login1",
1485                         "org.freedesktop.login1.Manager",
1486                         "ListInhibitors",
1487                         NULL,
1488                         &reply,
1489                         NULL);
1490         if (r < 0)
1491                 /* If logind is not around, then there are no inhibitors... */
1492                 return 0;
1493
1494         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
1495         if (r < 0)
1496                 return bus_log_parse_error(r);
1497
1498         while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
1499                 _cleanup_free_ char *comm = NULL, *user = NULL;
1500                 _cleanup_strv_free_ char **sv = NULL;
1501
1502                 if (!streq(mode, "block"))
1503                         continue;
1504
1505                 sv = strv_split(what, ":");
1506                 if (!sv)
1507                         return log_oom();
1508
1509                 if ((pid_t) pid < 0)
1510                         return log_error_errno(ERANGE, "Bad PID %"PRIu32": %m", pid);
1511
1512                 if (!strv_contains(sv,
1513                                   a == ACTION_POWEROFF ||
1514                                   a == ACTION_REBOOT ? "shutdown" : "sleep"))
1515                         continue;
1516
1517                 get_process_comm(pid, &comm);
1518                 user = uid_to_name(uid);
1519
1520                 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
1521                             who, (pid_t) pid, strna(comm), strna(user), why);
1522
1523                 c++;
1524         }
1525         if (r < 0)
1526                 return bus_log_parse_error(r);
1527
1528         r = sd_bus_message_exit_container(reply);
1529         if (r < 0)
1530                 return bus_log_parse_error(r);
1531
1532         /* Check for current sessions */
1533         sd_get_sessions(&sessions);
1534         STRV_FOREACH(s, sessions) {
1535                 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
1536
1537                 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
1538                         continue;
1539
1540                 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
1541                         continue;
1542
1543                 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
1544                         continue;
1545
1546                 sd_session_get_tty(*s, &tty);
1547                 sd_session_get_seat(*s, &seat);
1548                 sd_session_get_service(*s, &service);
1549                 user = uid_to_name(uid);
1550
1551                 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
1552                 c++;
1553         }
1554
1555         if (c <= 0)
1556                 return 0;
1557
1558         log_error("Please retry operation after closing inhibitors and logging out other users.\n"
1559                   "Alternatively, ignore inhibitors and users with 'loginctl %s -i'.",
1560                   action_table[a].verb);
1561
1562         return -EPERM;
1563 }
1564
1565 static int start_special(int argc, char *argv[], void *userdata) {
1566         sd_bus *bus = userdata;
1567         enum action a;
1568         int r;
1569
1570         assert(argv);
1571
1572         a = verb_to_action(argv[0]);
1573
1574         r = check_inhibitors(bus, a);
1575         if (r < 0)
1576                 return r;
1577
1578         /* Now power off actions in chroot environments */
1579         if ((a == ACTION_POWEROFF ||
1580              a == ACTION_REBOOT) &&
1581             (running_in_chroot() > 0) ) {
1582                 log_info("Running in chroot, ignoring request.");
1583                 return 0;
1584         }
1585
1586         /* Switch to cancel shutdown, if a shutdown action was requested,
1587            and the option to cancel it was set: */
1588         if ((a == ACTION_POWEROFF ||
1589              a == ACTION_REBOOT) &&
1590             (arg_action == ACTION_CANCEL_SHUTDOWN))
1591                 return reboot_with_logind(bus, arg_action);
1592
1593         /* Otherwise perform requested action */
1594         if (a == ACTION_POWEROFF ||
1595             a == ACTION_REBOOT ||
1596             a == ACTION_SUSPEND ||
1597             a == ACTION_HIBERNATE ||
1598             a == ACTION_HYBRID_SLEEP)
1599                 return reboot_with_logind(bus, a);
1600
1601         return -EOPNOTSUPP;
1602 }
1603
1604 static int help(int argc, char *argv[], void *userdata) {
1605
1606         printf("%s [OPTIONS...] {COMMAND} ...\n\n"
1607                "Send control commands to or query the login manager.\n\n"
1608                "  -h --help                Show this help\n"
1609                "     --version             Show package version\n"
1610                "     --no-pager            Do not pipe output into a pager\n"
1611                "     --no-legend           Do not show the headers and footers\n"
1612                "     --no-ask-password     Don't prompt for password\n"
1613                "  -H --host=[USER@]HOST    Operate on remote host\n"
1614                "  -M --machine=CONTAINER   Operate on local container\n"
1615                "  -p --property=NAME       Show only properties by this name\n"
1616                "  -a --all                 Show all properties, including empty ones\n"
1617                "  -l --full                Do not ellipsize output\n"
1618                "     --kill-who=WHO        Who to send signal to\n"
1619                "  -s --signal=SIGNAL       Which signal to send\n"
1620 #if 0
1621                "  -n --lines=INTEGER       Number of journal entries to show\n"
1622                "  -o --output=STRING       Change journal output mode (short, short-monotonic,\n"
1623                "                           verbose, export, json, json-pretty, json-sse, cat)\n\n"
1624 #endif // 0
1625                "  -c                       Cancel a pending shutdown\n"
1626                "  -i --ignore-inhibitors   When shutting down or sleeping, ignore inhibitors\n"
1627                "Session Commands:\n"
1628                "  list-sessions            List sessions\n"
1629                "  session-status [ID...]   Show session status\n"
1630                "  show-session [ID...]     Show properties of sessions or the manager\n"
1631                "  activate [ID]            Activate a session\n"
1632                "  lock-session [ID...]     Screen lock one or more sessions\n"
1633                "  unlock-session [ID...]   Screen unlock one or more sessions\n"
1634                "  lock-sessions            Screen lock all current sessions\n"
1635                "  unlock-sessions          Screen unlock all current sessions\n"
1636                "  terminate-session ID...  Terminate one or more sessions\n"
1637                "  kill-session ID...       Send signal to processes of a session\n\n"
1638                "User Commands:\n"
1639                "  list-users               List users\n"
1640                "  user-status [USER...]    Show user status\n"
1641                "  show-user [USER...]      Show properties of users or the manager\n"
1642                "  enable-linger [USER...]  Enable linger state of one or more users\n"
1643                "  disable-linger [USER...] Disable linger state of one or more users\n"
1644                "  terminate-user USER...   Terminate all sessions of one or more users\n"
1645                "  kill-user USER...        Send signal to processes of a user\n\n"
1646                "Seat Commands:\n"
1647                "  list-seats               List seats\n"
1648                "  seat-status [NAME...]    Show seat status\n"
1649                "  show-seat [NAME...]      Show properties of seats or the manager\n"
1650                "  attach NAME DEVICE...    Attach one or more devices to a seat\n"
1651                "  flush-devices            Flush all device associations\n"
1652                "  terminate-seat NAME...   Terminate all sessions on one or more seats\n"
1653                "System Commands:\n"
1654                "  poweroff                 Turn off the machine\n"
1655                "  reboot                   Reboot the machine\n"
1656                "  suspend                  Suspend the machine to memory\n"
1657                "  hibernate                Suspend the machine to disk\n"
1658                "  hybrid-sleep             Suspend the machine to memory and disk\n"
1659                , program_invocation_short_name);
1660
1661         return 0;
1662 }
1663
1664 static int parse_argv(int argc, char *argv[]) {
1665
1666         enum {
1667                 ARG_VERSION = 0x100,
1668                 ARG_NO_PAGER,
1669                 ARG_NO_LEGEND,
1670                 ARG_KILL_WHO,
1671                 ARG_NO_ASK_PASSWORD,
1672         };
1673
1674         static const struct option options[] = {
1675                 { "help",            no_argument,       NULL, 'h'                 },
1676                 { "version",         no_argument,       NULL, ARG_VERSION         },
1677                 { "property",        required_argument, NULL, 'p'                 },
1678                 { "all",             no_argument,       NULL, 'a'                 },
1679                 { "full",            no_argument,       NULL, 'l'                 },
1680                 { "no-pager",        no_argument,       NULL, ARG_NO_PAGER        },
1681                 { "no-legend",       no_argument,       NULL, ARG_NO_LEGEND       },
1682                 { "kill-who",        required_argument, NULL, ARG_KILL_WHO        },
1683                 { "signal",          required_argument, NULL, 's'                 },
1684                 { "host",            required_argument, NULL, 'H'                 },
1685                 { "machine",         required_argument, NULL, 'M'                 },
1686                 { "no-ask-password", no_argument,       NULL, ARG_NO_ASK_PASSWORD },
1687 #if 0
1688                 { "lines",           required_argument, NULL, 'n'                 },
1689                 { "output",          required_argument, NULL, 'o'                 },
1690 #endif // 0
1691                 { "ignore-inhibitors", no_argument,     NULL, 'i'                 },
1692                 {}
1693         };
1694
1695         int c, r;
1696
1697         assert(argc >= 0);
1698         assert(argv);
1699
1700         while ((c = getopt_long(argc, argv, "hp:als:H:M:n:o:ci", options, NULL)) >= 0)
1701
1702                 switch (c) {
1703
1704                 case 'h':
1705                         help(0, NULL, NULL);
1706                         return 0;
1707
1708                 case ARG_VERSION:
1709                         return version();
1710
1711                 case 'p': {
1712                         r = strv_extend(&arg_property, optarg);
1713                         if (r < 0)
1714                                 return log_oom();
1715
1716                         /* If the user asked for a particular
1717                          * property, show it to him, even if it is
1718                          * empty. */
1719                         arg_all = true;
1720                         break;
1721                 }
1722
1723                 case 'a':
1724                         arg_all = true;
1725                         break;
1726
1727                 case 'l':
1728                         arg_full = true;
1729                         break;
1730 #if 0
1731                 case 'n':
1732                         if (safe_atou(optarg, &arg_lines) < 0) {
1733                                 log_error("Failed to parse lines '%s'", optarg);
1734                                 return -EINVAL;
1735                         }
1736                         break;
1737
1738                 case 'o':
1739                         arg_output = output_mode_from_string(optarg);
1740                         if (arg_output < 0) {
1741                                 log_error("Unknown output '%s'.", optarg);
1742                                 return -EINVAL;
1743                         }
1744                         break;
1745 #endif // 0
1746                 case ARG_NO_PAGER:
1747                         arg_no_pager = true;
1748                         break;
1749
1750                 case ARG_NO_LEGEND:
1751                         arg_legend = false;
1752                         break;
1753
1754                 case ARG_NO_ASK_PASSWORD:
1755                         arg_ask_password = false;
1756                         break;
1757
1758                 case ARG_KILL_WHO:
1759                         arg_kill_who = optarg;
1760                         break;
1761
1762                 case 's':
1763                         arg_signal = signal_from_string_try_harder(optarg);
1764                         if (arg_signal < 0) {
1765                                 log_error("Failed to parse signal string %s.", optarg);
1766                                 return -EINVAL;
1767                         }
1768                         break;
1769
1770                 case 'H':
1771                         arg_transport = BUS_TRANSPORT_REMOTE;
1772                         arg_host = optarg;
1773                         break;
1774
1775                 case 'M':
1776                         arg_transport = BUS_TRANSPORT_MACHINE;
1777                         arg_host = optarg;
1778                         break;
1779
1780                 case 'c':
1781                         arg_action = ACTION_CANCEL_SHUTDOWN;
1782                         break;
1783
1784                 case 'i':
1785                         arg_ignore_inhibitors = true;
1786                         break;
1787
1788                 case '?':
1789                         return -EINVAL;
1790
1791                 default:
1792                         assert_not_reached("Unhandled option");
1793                 }
1794
1795         return 1;
1796 }
1797
1798 static int loginctl_main(int argc, char *argv[], sd_bus *bus) {
1799
1800         static const Verb verbs[] = {
1801                 { "help",              VERB_ANY, VERB_ANY, 0,            help              },
1802                 { "list-sessions",     VERB_ANY, 1,        VERB_DEFAULT, list_sessions     },
1803                 { "session-status",    VERB_ANY, VERB_ANY, 0,            show_session      },
1804                 { "show-session",      VERB_ANY, VERB_ANY, 0,            show_session      },
1805                 { "activate",          VERB_ANY, 2,        0,            activate          },
1806                 { "lock-session",      VERB_ANY, VERB_ANY, 0,            activate          },
1807                 { "unlock-session",    VERB_ANY, VERB_ANY, 0,            activate          },
1808                 { "lock-sessions",     VERB_ANY, 1,        0,            lock_sessions     },
1809                 { "unlock-sessions",   VERB_ANY, 1,        0,            lock_sessions     },
1810                 { "terminate-session", 2,        VERB_ANY, 0,            activate          },
1811                 { "kill-session",      2,        VERB_ANY, 0,            kill_session      },
1812                 { "list-users",        VERB_ANY, 1,        0,            list_users        },
1813                 { "user-status",       VERB_ANY, VERB_ANY, 0,            show_user         },
1814                 { "show-user",         VERB_ANY, VERB_ANY, 0,            show_user         },
1815                 { "enable-linger",     VERB_ANY, VERB_ANY, 0,            enable_linger     },
1816                 { "disable-linger",    VERB_ANY, VERB_ANY, 0,            enable_linger     },
1817                 { "terminate-user",    2,        VERB_ANY, 0,            terminate_user    },
1818                 { "kill-user",         2,        VERB_ANY, 0,            kill_user         },
1819                 { "list-seats",        VERB_ANY, 1,        0,            list_seats        },
1820                 { "seat-status",       VERB_ANY, VERB_ANY, 0,            show_seat         },
1821                 { "show-seat",         VERB_ANY, VERB_ANY, 0,            show_seat         },
1822                 { "attach",            3,        VERB_ANY, 0,            attach            },
1823                 { "flush-devices",     VERB_ANY, 1,        0,            flush_devices     },
1824                 { "terminate-seat",    2,        VERB_ANY, 0,            terminate_seat    },
1825                 { "poweroff",          VERB_ANY, 1,        0,            start_special     },
1826                 { "reboot",            VERB_ANY, 1,        0,            start_special     },
1827                 { "suspend",           VERB_ANY, 1,        0,            start_special     },
1828                 { "hibernate",         VERB_ANY, 1,        0,            start_special     },
1829                 { "hybrid-sleep",      VERB_ANY, 1,        0,            start_special     },
1830                 { "cancel-shutdown",   VERB_ANY, 1,        0,            start_special     },
1831                 {}
1832         };
1833
1834         return dispatch_verb(argc, argv, verbs, bus);
1835 }
1836
1837 int main(int argc, char *argv[]) {
1838         _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
1839         int r;
1840
1841         setlocale(LC_ALL, "");
1842         elogind_set_program_name(argv[0]);
1843         log_parse_environment();
1844         log_open();
1845
1846         r = parse_argv(argc, argv);
1847         if (r <= 0)
1848                 goto finish;
1849
1850         r = bus_connect_transport(arg_transport, arg_host, false, &bus);
1851         if (r < 0) {
1852                 log_error_errno(r, "Failed to create bus connection: %m");
1853                 goto finish;
1854         }
1855
1856         sd_bus_set_allow_interactive_authorization(bus, arg_ask_password);
1857
1858         r = loginctl_main(argc, argv, bus);
1859
1860 finish:
1861         pager_close();
1862         polkit_agent_close();
1863
1864         strv_free(arg_property);
1865
1866         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1867 }