chiark / gitweb /
systemctl: delete REBOOT_PARAM_FILE if no parameter is specified
[elogind.git] / src / systemctl / systemctl.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 Lennart Poettering
7   Copyright 2013 Marc-Antoine Perennou
8
9   systemd is free software; you can redistribute it and/or modify it
10   under the terms of the GNU Lesser General Public License as published by
11   the Free Software Foundation; either version 2.1 of the License, or
12   (at your option) any later version.
13
14   systemd is distributed in the hope that it will be useful, but
15   WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   Lesser General Public License for more details.
18
19   You should have received a copy of the GNU Lesser General Public License
20   along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 ***/
22
23 #include <sys/reboot.h>
24 #include <linux/reboot.h>
25 #include <sys/syscall.h>
26 #include <stdio.h>
27 #include <getopt.h>
28 #include <locale.h>
29 #include <stdbool.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <sys/ioctl.h>
33 #include <termios.h>
34 #include <unistd.h>
35 #include <fcntl.h>
36 #include <sys/socket.h>
37 #include <sys/stat.h>
38 #include <stddef.h>
39 #include <sys/prctl.h>
40 #include <fnmatch.h>
41
42 #include "sd-daemon.h"
43 #include "sd-shutdown.h"
44 #include "sd-login.h"
45 #include "sd-bus.h"
46 #include "log.h"
47 #include "util.h"
48 #include "macro.h"
49 #include "set.h"
50 #include "utmp-wtmp.h"
51 #include "special.h"
52 #include "initreq.h"
53 #include "path-util.h"
54 #include "strv.h"
55 #include "cgroup-show.h"
56 #include "cgroup-util.h"
57 #include "list.h"
58 #include "path-lookup.h"
59 #include "conf-parser.h"
60 #include "exit-status.h"
61 #include "build.h"
62 #include "unit-name.h"
63 #include "pager.h"
64 #include "spawn-ask-password-agent.h"
65 #include "spawn-polkit-agent.h"
66 #include "install.h"
67 #include "logs-show.h"
68 #include "socket-util.h"
69 #include "fileio.h"
70 #include "env-util.h"
71 #include "bus-util.h"
72 #include "bus-message.h"
73 #include "bus-error.h"
74 #include "bus-errors.h"
75
76 static char **arg_types = NULL;
77 static char **arg_states = NULL;
78 static char **arg_properties = NULL;
79 static bool arg_all = false;
80 static enum dependency {
81         DEPENDENCY_FORWARD,
82         DEPENDENCY_REVERSE,
83         DEPENDENCY_AFTER,
84         DEPENDENCY_BEFORE,
85         _DEPENDENCY_MAX
86 } arg_dependency = DEPENDENCY_FORWARD;
87 static const char *arg_job_mode = "replace";
88 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
89 static bool arg_no_block = false;
90 static bool arg_no_legend = false;
91 static bool arg_no_pager = false;
92 static bool arg_no_wtmp = false;
93 static bool arg_no_wall = false;
94 static bool arg_no_reload = false;
95 static bool arg_show_types = false;
96 static bool arg_ignore_inhibitors = false;
97 static bool arg_dry = false;
98 static bool arg_quiet = false;
99 static bool arg_full = false;
100 static bool arg_recursive = false;
101 static int arg_force = 0;
102 static bool arg_ask_password = true;
103 static bool arg_runtime = false;
104 static char **arg_wall = NULL;
105 static const char *arg_kill_who = NULL;
106 static int arg_signal = SIGTERM;
107 static const char *arg_root = NULL;
108 static usec_t arg_when = 0;
109 static enum action {
110         _ACTION_INVALID,
111         ACTION_SYSTEMCTL,
112         ACTION_HALT,
113         ACTION_POWEROFF,
114         ACTION_REBOOT,
115         ACTION_KEXEC,
116         ACTION_EXIT,
117         ACTION_SUSPEND,
118         ACTION_HIBERNATE,
119         ACTION_HYBRID_SLEEP,
120         ACTION_RUNLEVEL2,
121         ACTION_RUNLEVEL3,
122         ACTION_RUNLEVEL4,
123         ACTION_RUNLEVEL5,
124         ACTION_RESCUE,
125         ACTION_EMERGENCY,
126         ACTION_DEFAULT,
127         ACTION_RELOAD,
128         ACTION_REEXEC,
129         ACTION_RUNLEVEL,
130         ACTION_CANCEL_SHUTDOWN,
131         _ACTION_MAX
132 } arg_action = ACTION_SYSTEMCTL;
133 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
134 static char *arg_host = NULL;
135 static unsigned arg_lines = 10;
136 static OutputMode arg_output = OUTPUT_SHORT;
137 static bool arg_plain = false;
138
139 static const struct {
140         const char *verb;
141         const char *method;
142 } unit_actions[] = {
143         { "start",                 "StartUnit" },
144         { "stop",                  "StopUnit" },
145         { "condstop",              "StopUnit" },
146         { "reload",                "ReloadUnit" },
147         { "restart",               "RestartUnit" },
148         { "try-restart",           "TryRestartUnit" },
149         { "condrestart",           "TryRestartUnit" },
150         { "reload-or-restart",     "ReloadOrRestartUnit" },
151         { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
152         { "condreload",            "ReloadOrTryRestartUnit" },
153         { "force-reload",          "ReloadOrTryRestartUnit" }
154 };
155
156 static bool original_stdout_is_tty;
157
158 static int daemon_reload(sd_bus *bus, char **args);
159 static int halt_now(enum action a);
160 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet);
161
162 static char** strv_skip_first(char **strv) {
163         if (strv_length(strv) > 0)
164                 return strv + 1;
165         return NULL;
166 }
167
168 static void pager_open_if_enabled(void) {
169
170         if (arg_no_pager)
171                 return;
172
173         pager_open(false);
174 }
175
176 static void ask_password_agent_open_if_enabled(void) {
177
178         /* Open the password agent as a child process if necessary */
179
180         if (!arg_ask_password)
181                 return;
182
183         if (arg_scope != UNIT_FILE_SYSTEM)
184                 return;
185
186         if (arg_transport != BUS_TRANSPORT_LOCAL)
187                 return;
188
189         ask_password_agent_open();
190 }
191
192 #ifdef HAVE_LOGIND
193 static void polkit_agent_open_if_enabled(void) {
194
195         /* Open the polkit agent as a child process if necessary */
196
197         if (!arg_ask_password)
198                 return;
199
200         if (arg_scope != UNIT_FILE_SYSTEM)
201                 return;
202
203         if (arg_transport != BUS_TRANSPORT_LOCAL)
204                 return;
205
206         polkit_agent_open();
207 }
208 #endif
209
210 static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) {
211         assert(error);
212
213         if (!sd_bus_error_is_set(error))
214                 return r;
215
216         if (sd_bus_error_has_name(error, SD_BUS_ERROR_ACCESS_DENIED) ||
217             sd_bus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
218             sd_bus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
219             sd_bus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
220                 return EXIT_NOPERMISSION;
221
222         if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
223                 return EXIT_NOTINSTALLED;
224
225         if (sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
226             sd_bus_error_has_name(error, SD_BUS_ERROR_NOT_SUPPORTED))
227                 return EXIT_NOTIMPLEMENTED;
228
229         if (sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
230                 return EXIT_NOTCONFIGURED;
231
232         if (r != 0)
233                 return r;
234
235         return EXIT_FAILURE;
236 }
237
238 static void warn_wall(enum action a) {
239         static const char *table[_ACTION_MAX] = {
240                 [ACTION_HALT]            = "The system is going down for system halt NOW!",
241                 [ACTION_REBOOT]          = "The system is going down for reboot NOW!",
242                 [ACTION_POWEROFF]        = "The system is going down for power-off NOW!",
243                 [ACTION_KEXEC]           = "The system is going down for kexec reboot NOW!",
244                 [ACTION_RESCUE]          = "The system is going down to rescue mode NOW!",
245                 [ACTION_EMERGENCY]       = "The system is going down to emergency mode NOW!",
246                 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
247         };
248
249         if (arg_no_wall)
250                 return;
251
252         if (arg_wall) {
253                 _cleanup_free_ char *p;
254
255                 p = strv_join(arg_wall, " ");
256                 if (!p) {
257                         log_oom();
258                         return;
259                 }
260
261                 if (*p) {
262                         utmp_wall(p, NULL, NULL);
263                         return;
264                 }
265         }
266
267         if (!table[a])
268                 return;
269
270         utmp_wall(table[a], NULL, NULL);
271 }
272
273 static bool avoid_bus(void) {
274
275         if (running_in_chroot() > 0)
276                 return true;
277
278         if (sd_booted() <= 0)
279                 return true;
280
281         if (!isempty(arg_root))
282                 return true;
283
284         if (arg_scope == UNIT_FILE_GLOBAL)
285                 return true;
286
287         return false;
288 }
289
290 static int compare_unit_info(const void *a, const void *b) {
291         const UnitInfo *u = a, *v = b;
292         const char *d1, *d2;
293         int r;
294
295         /* First, order by machine */
296         if (!u->machine && v->machine)
297                 return -1;
298         if (u->machine && !v->machine)
299                 return 1;
300         if (u->machine && v->machine) {
301                 r = strcasecmp(u->machine, v->machine);
302                 if (r != 0)
303                         return r;
304         }
305
306         /* Second, order by unit type */
307         d1 = strrchr(u->id, '.');
308         d2 = strrchr(v->id, '.');
309         if (d1 && d2) {
310                 r = strcasecmp(d1, d2);
311                 if (r != 0)
312                         return r;
313         }
314
315         /* Third, order by name */
316         return strcasecmp(u->id, v->id);
317 }
318
319 static bool output_show_unit(const UnitInfo *u, char **patterns) {
320         const char *dot;
321
322         if (!strv_isempty(arg_states))
323                 return
324                         strv_contains(arg_states, u->load_state) ||
325                         strv_contains(arg_states, u->sub_state) ||
326                         strv_contains(arg_states, u->active_state);
327
328         if (!strv_isempty(patterns)) {
329                 char **pattern;
330
331                 STRV_FOREACH(pattern, patterns)
332                         if (fnmatch(*pattern, u->id, FNM_NOESCAPE) == 0)
333                                 return true;
334                 return false;
335         }
336
337         return (!arg_types || ((dot = strrchr(u->id, '.')) &&
338                                strv_find(arg_types, dot+1))) &&
339                 (arg_all || !(streq(u->active_state, "inactive")
340                               || u->following[0]) || u->job_id > 0);
341 }
342
343 static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
344         unsigned circle_len = 0, id_len, max_id_len, load_len, active_len, sub_len, job_len, desc_len;
345         const UnitInfo *u;
346         unsigned n_shown = 0;
347         int job_count = 0;
348
349         max_id_len = strlen("UNIT");
350         load_len = strlen("LOAD");
351         active_len = strlen("ACTIVE");
352         sub_len = strlen("SUB");
353         job_len = strlen("JOB");
354         desc_len = 0;
355
356         for (u = unit_infos; u < unit_infos + c; u++) {
357                 max_id_len = MAX(max_id_len, strlen(u->id) + (u->machine ? strlen(u->machine)+1 : 0));
358                 load_len = MAX(load_len, strlen(u->load_state));
359                 active_len = MAX(active_len, strlen(u->active_state));
360                 sub_len = MAX(sub_len, strlen(u->sub_state));
361
362                 if (u->job_id != 0) {
363                         job_len = MAX(job_len, strlen(u->job_type));
364                         job_count++;
365                 }
366
367                 if (!arg_no_legend &&
368                     (streq(u->active_state, "failed") ||
369                      STR_IN_SET(u->load_state, "error", "not-found", "masked")))
370                         circle_len = 2;
371         }
372
373         if (!arg_full && original_stdout_is_tty) {
374                 unsigned basic_len;
375
376                 id_len = MIN(max_id_len, 25u);
377                 basic_len = circle_len + 5 + id_len + 5 + active_len + sub_len;
378
379                 if (job_count)
380                         basic_len += job_len + 1;
381
382                 if (basic_len < (unsigned) columns()) {
383                         unsigned extra_len, incr;
384                         extra_len = columns() - basic_len;
385
386                         /* Either UNIT already got 25, or is fully satisfied.
387                          * Grant up to 25 to DESC now. */
388                         incr = MIN(extra_len, 25u);
389                         desc_len += incr;
390                         extra_len -= incr;
391
392                         /* split the remaining space between UNIT and DESC,
393                          * but do not give UNIT more than it needs. */
394                         if (extra_len > 0) {
395                                 incr = MIN(extra_len / 2, max_id_len - id_len);
396                                 id_len += incr;
397                                 desc_len += extra_len - incr;
398                         }
399                 }
400         } else
401                 id_len = max_id_len;
402
403         for (u = unit_infos; u < unit_infos + c; u++) {
404                 _cleanup_free_ char *e = NULL, *j = NULL;
405                 const char *on_loaded = "", *off_loaded = "";
406                 const char *on_active = "", *off_active = "";
407                 const char *on_circle = "", *off_circle = "";
408                 const char *id;
409                 bool circle = false;
410
411                 if (!n_shown && !arg_no_legend) {
412
413                         if (circle_len > 0)
414                                 fputs("  ", stdout);
415
416                         printf("%-*s %-*s %-*s %-*s ",
417                                id_len, "UNIT",
418                                load_len, "LOAD",
419                                active_len, "ACTIVE",
420                                sub_len, "SUB");
421
422                         if (job_count)
423                                 printf("%-*s ", job_len, "JOB");
424
425                         if (!arg_full && arg_no_pager)
426                                 printf("%.*s\n", desc_len, "DESCRIPTION");
427                         else
428                                 printf("%s\n", "DESCRIPTION");
429                 }
430
431                 n_shown++;
432
433                 if (STR_IN_SET(u->load_state, "error", "not-found", "masked")) {
434                         on_loaded = ansi_highlight_red();
435                         on_circle = ansi_highlight_yellow();
436                         off_loaded = off_circle = ansi_highlight_off();
437                         circle = true;
438                 }
439
440                 if (streq(u->active_state, "failed")) {
441                         on_circle = on_active = ansi_highlight_red();
442                         off_circle = off_active = ansi_highlight_off();
443                         circle = true;
444                 }
445
446                 if (u->machine) {
447                         j = strjoin(u->machine, ":", u->id, NULL);
448                         if (!j)
449                                 return log_oom();
450
451                         id = j;
452                 } else
453                         id = u->id;
454
455                 if (arg_full) {
456                         e = ellipsize(id, id_len, 33);
457                         if (!e)
458                                 return log_oom();
459
460                         id = e;
461                 }
462
463                 if (circle_len > 0)
464                         printf("%s%s%s", on_circle, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : "  ", off_circle);
465
466                 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
467                        on_active, id_len, id, off_active,
468                        on_loaded, load_len, u->load_state, off_loaded,
469                        on_active, active_len, u->active_state,
470                        sub_len, u->sub_state, off_active,
471                        job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
472
473                 if (desc_len > 0)
474                         printf("%.*s\n", desc_len, u->description);
475                 else
476                         printf("%s\n", u->description);
477         }
478
479         if (!arg_no_legend) {
480                 const char *on, *off;
481
482                 if (n_shown) {
483                         puts("\n"
484                              "LOAD   = Reflects whether the unit definition was properly loaded.\n"
485                              "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
486                              "SUB    = The low-level unit activation state, values depend on unit type.");
487                         puts(job_count ? "JOB    = Pending job for the unit.\n" : "");
488                         on = ansi_highlight();
489                         off = ansi_highlight_off();
490                 } else {
491                         on = ansi_highlight_red();
492                         off = ansi_highlight_off();
493                 }
494
495                 if (arg_all)
496                         printf("%s%u loaded units listed.%s\n"
497                                "To show all installed unit files use 'systemctl list-unit-files'.\n",
498                                on, n_shown, off);
499                 else
500                         printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
501                                "To show all installed unit files use 'systemctl list-unit-files'.\n",
502                                on, n_shown, off);
503         }
504
505         return 0;
506 }
507
508 static int get_unit_list(
509                 sd_bus *bus,
510                 const char *machine,
511                 char **patterns,
512                 UnitInfo **unit_infos,
513                 int c,
514                 sd_bus_message **_reply) {
515
516         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
517         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
518         size_t size = c;
519         int r;
520         UnitInfo u;
521
522         assert(bus);
523         assert(unit_infos);
524         assert(_reply);
525
526         r = sd_bus_call_method(
527                         bus,
528                         "org.freedesktop.systemd1",
529                         "/org/freedesktop/systemd1",
530                         "org.freedesktop.systemd1.Manager",
531                         "ListUnits",
532                         &error,
533                         &reply,
534                         NULL);
535         if (r < 0) {
536                 log_error("Failed to list units: %s", bus_error_message(&error, r));
537                 return r;
538         }
539
540         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
541         if (r < 0)
542                 return bus_log_parse_error(r);
543
544         while ((r = bus_parse_unit_info(reply, &u)) > 0) {
545                 u.machine = machine;
546
547                 if (!output_show_unit(&u, patterns))
548                         continue;
549
550                 if (!GREEDY_REALLOC(*unit_infos, size, c+1))
551                         return log_oom();
552
553                 (*unit_infos)[c++] = u;
554         }
555         if (r < 0)
556                 return bus_log_parse_error(r);
557
558         r = sd_bus_message_exit_container(reply);
559         if (r < 0)
560                 return bus_log_parse_error(r);
561
562         *_reply = reply;
563         reply = NULL;
564
565         return c;
566 }
567
568 static void message_set_freep(Set **set) {
569         sd_bus_message *m;
570
571         while ((m = set_steal_first(*set)))
572                 sd_bus_message_unref(m);
573
574         set_free(*set);
575 }
576
577 static int get_unit_list_recursive(
578                 sd_bus *bus,
579                 char **patterns,
580                 UnitInfo **_unit_infos,
581                 Set **_replies,
582                 char ***_machines) {
583
584         _cleanup_free_ UnitInfo *unit_infos = NULL;
585         _cleanup_(message_set_freep) Set *replies;
586         sd_bus_message *reply;
587         int c, r;
588
589         assert(bus);
590         assert(_replies);
591         assert(_unit_infos);
592         assert(_machines);
593
594         replies = set_new(NULL, NULL);
595         if (!replies)
596                 return log_oom();
597
598         c = get_unit_list(bus, NULL, patterns, &unit_infos, 0, &reply);
599         if (c < 0)
600                 return c;
601
602         r = set_put(replies, reply);
603         if (r < 0) {
604                 sd_bus_message_unref(reply);
605                 return r;
606         }
607
608         if (arg_recursive) {
609                 _cleanup_strv_free_ char **machines = NULL;
610                 char **i;
611
612                 r = sd_get_machine_names(&machines);
613                 if (r < 0)
614                         return r;
615
616                 STRV_FOREACH(i, machines) {
617                         _cleanup_bus_unref_ sd_bus *container = NULL;
618                         int k;
619
620                         r = sd_bus_open_system_container(&container, *i);
621                         if (r < 0) {
622                                 log_error("Failed to connect to container %s: %s", *i, strerror(-r));
623                                 continue;
624                         }
625
626                         k = get_unit_list(container, *i, patterns, &unit_infos, c, &reply);
627                         if (k < 0)
628                                 return k;
629
630                         c = k;
631
632                         r = set_put(replies, reply);
633                         if (r < 0) {
634                                 sd_bus_message_unref(reply);
635                                 return r;
636                         }
637                 }
638
639                 *_machines = machines;
640                 machines = NULL;
641         } else
642                 *_machines = NULL;
643
644         *_unit_infos = unit_infos;
645         unit_infos = NULL;
646
647         *_replies = replies;
648         replies = NULL;
649
650         return c;
651 }
652
653 static int list_units(sd_bus *bus, char **args) {
654         _cleanup_free_ UnitInfo *unit_infos = NULL;
655         _cleanup_(message_set_freep) Set *replies = NULL;
656         _cleanup_strv_free_ char **machines = NULL;
657         int r;
658
659         pager_open_if_enabled();
660
661         r = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
662         if (r < 0)
663                 return r;
664
665         qsort_safe(unit_infos, r, sizeof(UnitInfo), compare_unit_info);
666         return output_units_list(unit_infos, r);
667 }
668
669 static int get_triggered_units(
670                 sd_bus *bus,
671                 const char* path,
672                 char*** ret) {
673
674         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
675         int r;
676
677         r = sd_bus_get_property_strv(
678                         bus,
679                         "org.freedesktop.systemd1",
680                         path,
681                         "org.freedesktop.systemd1.Unit",
682                         "Triggers",
683                         &error,
684                         ret);
685
686         if (r < 0)
687                 log_error("Failed to determine triggers: %s", bus_error_message(&error, r));
688
689         return 0;
690 }
691
692 static int get_listening(
693                 sd_bus *bus,
694                 const char* unit_path,
695                 char*** listening) {
696
697         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
698         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
699         const char *type, *path;
700         int r, n = 0;
701
702         r = sd_bus_get_property(
703                         bus,
704                         "org.freedesktop.systemd1",
705                         unit_path,
706                         "org.freedesktop.systemd1.Socket",
707                         "Listen",
708                         &error,
709                         &reply,
710                         "a(ss)");
711         if (r < 0) {
712                 log_error("Failed to get list of listening sockets: %s", bus_error_message(&error, r));
713                 return r;
714         }
715
716         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
717         if (r < 0)
718                 return bus_log_parse_error(r);
719
720         while ((r = sd_bus_message_read(reply, "(ss)", &type, &path)) > 0) {
721
722                 r = strv_extend(listening, type);
723                 if (r < 0)
724                         return log_oom();
725
726                 r = strv_extend(listening, path);
727                 if (r < 0)
728                         return log_oom();
729
730                 n++;
731         }
732         if (r < 0)
733                 return bus_log_parse_error(r);
734
735         r = sd_bus_message_exit_container(reply);
736         if (r < 0)
737                 return bus_log_parse_error(r);
738
739         return n;
740 }
741
742 struct socket_info {
743         const char *machine;
744         const char* id;
745
746         char* type;
747         char* path;
748
749         /* Note: triggered is a list here, although it almost certainly
750          * will always be one unit. Nevertheless, dbus API allows for multiple
751          * values, so let's follow that.*/
752         char** triggered;
753
754         /* The strv above is shared. free is set only in the first one. */
755         bool own_triggered;
756 };
757
758 static int socket_info_compare(const struct socket_info *a, const struct socket_info *b) {
759         int o;
760
761         assert(a);
762         assert(b);
763
764         if (!a->machine && b->machine)
765                 return -1;
766         if (a->machine && !b->machine)
767                 return 1;
768         if (a->machine && b->machine) {
769                 o = strcasecmp(a->machine, b->machine);
770                 if (o != 0)
771                         return o;
772         }
773
774         o = strcmp(a->path, b->path);
775         if (o == 0)
776                 o = strcmp(a->type, b->type);
777
778         return o;
779 }
780
781 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
782         struct socket_info *s;
783         unsigned pathlen = strlen("LISTEN"),
784                 typelen = strlen("TYPE") * arg_show_types,
785                 socklen = strlen("UNIT"),
786                 servlen = strlen("ACTIVATES");
787         const char *on, *off;
788
789         for (s = socket_infos; s < socket_infos + cs; s++) {
790                 unsigned tmp = 0;
791                 char **a;
792
793                 socklen = MAX(socklen, strlen(s->id));
794                 if (arg_show_types)
795                         typelen = MAX(typelen, strlen(s->type));
796                 pathlen = MAX(pathlen, strlen(s->path) + (s->machine ? strlen(s->machine)+1 : 0));
797
798                 STRV_FOREACH(a, s->triggered)
799                         tmp += strlen(*a) + 2*(a != s->triggered);
800                 servlen = MAX(servlen, tmp);
801         }
802
803         if (cs) {
804                 if (!arg_no_legend)
805                         printf("%-*s %-*.*s%-*s %s\n",
806                                pathlen, "LISTEN",
807                                typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
808                                socklen, "UNIT",
809                                "ACTIVATES");
810
811                 for (s = socket_infos; s < socket_infos + cs; s++) {
812                         _cleanup_free_ char *j = NULL;
813                         const char *path;
814                         char **a;
815
816                         if (s->machine) {
817                                 j = strjoin(s->machine, ":", s->path, NULL);
818                                 if (!j)
819                                         return log_oom();
820                                 path = j;
821                         } else
822                                 path = s->path;
823
824                         if (arg_show_types)
825                                 printf("%-*s %-*s %-*s",
826                                        pathlen, path, typelen, s->type, socklen, s->id);
827                         else
828                                 printf("%-*s %-*s",
829                                        pathlen, path, socklen, s->id);
830                         STRV_FOREACH(a, s->triggered)
831                                 printf("%s %s",
832                                        a == s->triggered ? "" : ",", *a);
833                         printf("\n");
834                 }
835
836                 on = ansi_highlight();
837                 off = ansi_highlight_off();
838                 if (!arg_no_legend)
839                         printf("\n");
840         } else {
841                 on = ansi_highlight_red();
842                 off = ansi_highlight_off();
843         }
844
845         if (!arg_no_legend) {
846                 printf("%s%u sockets listed.%s\n", on, cs, off);
847                 if (!arg_all)
848                         printf("Pass --all to see loaded but inactive sockets, too.\n");
849         }
850
851         return 0;
852 }
853
854 static int list_sockets(sd_bus *bus, char **args) {
855         _cleanup_(message_set_freep) Set *replies = NULL;
856         _cleanup_strv_free_ char **machines = NULL;
857         _cleanup_free_ UnitInfo *unit_infos = NULL;
858         _cleanup_free_ struct socket_info *socket_infos = NULL;
859         const UnitInfo *u;
860         struct socket_info *s;
861         unsigned cs = 0;
862         size_t size = 0;
863         int r = 0, n;
864
865         pager_open_if_enabled();
866
867         n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
868         if (n < 0)
869                 return n;
870
871         for (u = unit_infos; u < unit_infos + n; u++) {
872                 _cleanup_strv_free_ char **listening = NULL, **triggered = NULL;
873                 int i, c;
874
875                 if (!endswith(u->id, ".socket"))
876                         continue;
877
878                 r = get_triggered_units(bus, u->unit_path, &triggered);
879                 if (r < 0)
880                         goto cleanup;
881
882                 c = get_listening(bus, u->unit_path, &listening);
883                 if (c < 0) {
884                         r = c;
885                         goto cleanup;
886                 }
887
888                 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
889                         r = log_oom();
890                         goto cleanup;
891                 }
892
893                 for (i = 0; i < c; i++)
894                         socket_infos[cs + i] = (struct socket_info) {
895                                 .machine = u->machine,
896                                 .id = u->id,
897                                 .type = listening[i*2],
898                                 .path = listening[i*2 + 1],
899                                 .triggered = triggered,
900                                 .own_triggered = i==0,
901                         };
902
903                 /* from this point on we will cleanup those socket_infos */
904                 cs += c;
905                 free(listening);
906                 listening = triggered = NULL; /* avoid cleanup */
907         }
908
909         qsort_safe(socket_infos, cs, sizeof(struct socket_info),
910                    (__compar_fn_t) socket_info_compare);
911
912         output_sockets_list(socket_infos, cs);
913
914  cleanup:
915         assert(cs == 0 || socket_infos);
916         for (s = socket_infos; s < socket_infos + cs; s++) {
917                 free(s->type);
918                 free(s->path);
919                 if (s->own_triggered)
920                         strv_free(s->triggered);
921         }
922
923         return r;
924 }
925
926 static int get_next_elapse(
927                 sd_bus *bus,
928                 const char *path,
929                 dual_timestamp *next) {
930
931         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
932         dual_timestamp t;
933         int r;
934
935         assert(bus);
936         assert(path);
937         assert(next);
938
939         r = sd_bus_get_property_trivial(
940                         bus,
941                         "org.freedesktop.systemd1",
942                         path,
943                         "org.freedesktop.systemd1.Timer",
944                         "NextElapseUSecMonotonic",
945                         &error,
946                         't',
947                         &t.monotonic);
948         if (r < 0) {
949                 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
950                 return r;
951         }
952
953         r = sd_bus_get_property_trivial(
954                         bus,
955                         "org.freedesktop.systemd1",
956                         path,
957                         "org.freedesktop.systemd1.Timer",
958                         "NextElapseUSecRealtime",
959                         &error,
960                         't',
961                         &t.realtime);
962         if (r < 0) {
963                 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
964                 return r;
965         }
966
967         *next = t;
968         return 0;
969 }
970
971 static int get_last_trigger(
972                 sd_bus *bus,
973                 const char *path,
974                 usec_t *last) {
975
976         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
977         int r;
978
979         assert(bus);
980         assert(path);
981         assert(last);
982
983         r = sd_bus_get_property_trivial(
984                         bus,
985                         "org.freedesktop.systemd1",
986                         path,
987                         "org.freedesktop.systemd1.Timer",
988                         "LastTriggerUSec",
989                         &error,
990                         't',
991                         last);
992         if (r < 0) {
993                 log_error("Failed to get last trigger time: %s", bus_error_message(&error, r));
994                 return r;
995         }
996
997         return 0;
998 }
999
1000 struct timer_info {
1001         const char* machine;
1002         const char* id;
1003         usec_t next_elapse;
1004         usec_t last_trigger;
1005         char** triggered;
1006 };
1007
1008 static int timer_info_compare(const struct timer_info *a, const struct timer_info *b) {
1009         int o;
1010
1011         assert(a);
1012         assert(b);
1013
1014         if (!a->machine && b->machine)
1015                 return -1;
1016         if (a->machine && !b->machine)
1017                 return 1;
1018         if (a->machine && b->machine) {
1019                 o = strcasecmp(a->machine, b->machine);
1020                 if (o != 0)
1021                         return o;
1022         }
1023
1024         if (a->next_elapse < b->next_elapse)
1025                 return -1;
1026         if (a->next_elapse > b->next_elapse)
1027                 return 1;
1028
1029         return strcmp(a->id, b->id);
1030 }
1031
1032 static int output_timers_list(struct timer_info *timer_infos, unsigned n) {
1033         struct timer_info *t;
1034         unsigned
1035                 nextlen = strlen("NEXT"),
1036                 leftlen = strlen("LEFT"),
1037                 lastlen = strlen("LAST"),
1038                 passedlen = strlen("PASSED"),
1039                 unitlen = strlen("UNIT"),
1040                 activatelen = strlen("ACTIVATES");
1041
1042         const char *on, *off;
1043
1044         assert(timer_infos || n == 0);
1045
1046         for (t = timer_infos; t < timer_infos + n; t++) {
1047                 unsigned ul = 0;
1048                 char **a;
1049
1050                 if (t->next_elapse > 0) {
1051                         char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1052
1053                         format_timestamp(tstamp, sizeof(tstamp), t->next_elapse);
1054                         nextlen = MAX(nextlen, strlen(tstamp) + 1);
1055
1056                         format_timestamp_relative(trel, sizeof(trel), t->next_elapse);
1057                         leftlen = MAX(leftlen, strlen(trel));
1058                 }
1059
1060                 if (t->last_trigger > 0) {
1061                         char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1062
1063                         format_timestamp(tstamp, sizeof(tstamp), t->last_trigger);
1064                         lastlen = MAX(lastlen, strlen(tstamp) + 1);
1065
1066                         format_timestamp_relative(trel, sizeof(trel), t->last_trigger);
1067                         passedlen = MAX(passedlen, strlen(trel));
1068                 }
1069
1070                 unitlen = MAX(unitlen, strlen(t->id) + (t->machine ? strlen(t->machine)+1 : 0));
1071
1072                 STRV_FOREACH(a, t->triggered)
1073                         ul += strlen(*a) + 2*(a != t->triggered);
1074
1075                 activatelen = MAX(activatelen, ul);
1076         }
1077
1078         if (n > 0) {
1079                 if (!arg_no_legend)
1080                         printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1081                                nextlen,   "NEXT",
1082                                leftlen,   "LEFT",
1083                                lastlen,   "LAST",
1084                                passedlen, "PASSED",
1085                                unitlen,   "UNIT",
1086                                           "ACTIVATES");
1087
1088                 for (t = timer_infos; t < timer_infos + n; t++) {
1089                         _cleanup_free_ char *j = NULL;
1090                         const char *unit;
1091                         char tstamp1[FORMAT_TIMESTAMP_MAX] = "n/a", trel1[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1092                         char tstamp2[FORMAT_TIMESTAMP_MAX] = "n/a", trel2[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1093                         char **a;
1094
1095                         format_timestamp(tstamp1, sizeof(tstamp1), t->next_elapse);
1096                         format_timestamp_relative(trel1, sizeof(trel1), t->next_elapse);
1097
1098                         format_timestamp(tstamp2, sizeof(tstamp2), t->last_trigger);
1099                         format_timestamp_relative(trel2, sizeof(trel2), t->last_trigger);
1100
1101                         if (t->machine) {
1102                                 j = strjoin(t->machine, ":", t->id, NULL);
1103                                 if (!j)
1104                                         return log_oom();
1105                                 unit = j;
1106                         } else
1107                                 unit = t->id;
1108
1109                         printf("%-*s %-*s %-*s %-*s %-*s",
1110                                nextlen, tstamp1, leftlen, trel1, lastlen, tstamp2, passedlen, trel2, unitlen, unit);
1111
1112                         STRV_FOREACH(a, t->triggered)
1113                                 printf("%s %s",
1114                                        a == t->triggered ? "" : ",", *a);
1115                         printf("\n");
1116                 }
1117
1118                 on = ansi_highlight();
1119                 off = ansi_highlight_off();
1120                 if (!arg_no_legend)
1121                         printf("\n");
1122         } else {
1123                 on = ansi_highlight_red();
1124                 off = ansi_highlight_off();
1125         }
1126
1127         if (!arg_no_legend) {
1128                 printf("%s%u timers listed.%s\n", on, n, off);
1129                 if (!arg_all)
1130                         printf("Pass --all to see loaded but inactive timers, too.\n");
1131         }
1132
1133         return 0;
1134 }
1135
1136 static usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next) {
1137         usec_t next_elapse;
1138
1139         assert(nw);
1140         assert(next);
1141
1142         if (next->monotonic != (usec_t) -1 && next->monotonic > 0) {
1143                 usec_t converted;
1144
1145                 if (next->monotonic > nw->monotonic)
1146                         converted = nw->realtime + (next->monotonic - nw->monotonic);
1147                 else
1148                         converted = nw->realtime - (nw->monotonic - next->monotonic);
1149
1150                 if (next->realtime != (usec_t) -1 && next->realtime > 0)
1151                         next_elapse = MIN(converted, next->realtime);
1152                 else
1153                         next_elapse = converted;
1154
1155         } else
1156                 next_elapse = next->realtime;
1157
1158         return next_elapse;
1159 }
1160
1161 static int list_timers(sd_bus *bus, char **args) {
1162         _cleanup_(message_set_freep) Set *replies = NULL;
1163         _cleanup_strv_free_ char **machines = NULL;
1164         _cleanup_free_ struct timer_info *timer_infos = NULL;
1165         _cleanup_free_ UnitInfo *unit_infos = NULL;
1166         struct timer_info *t;
1167         const UnitInfo *u;
1168         size_t size = 0;
1169         int n, c = 0;
1170         dual_timestamp nw;
1171         int r = 0;
1172
1173         pager_open_if_enabled();
1174
1175         n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
1176         if (n < 0)
1177                 return n;
1178
1179         dual_timestamp_get(&nw);
1180
1181         for (u = unit_infos; u < unit_infos + n; u++) {
1182                 _cleanup_strv_free_ char **triggered = NULL;
1183                 dual_timestamp next = {};
1184                 usec_t m, last = 0;
1185
1186                 if (!endswith(u->id, ".timer"))
1187                         continue;
1188
1189                 r = get_triggered_units(bus, u->unit_path, &triggered);
1190                 if (r < 0)
1191                         goto cleanup;
1192
1193                 r = get_next_elapse(bus, u->unit_path, &next);
1194                 if (r < 0)
1195                         goto cleanup;
1196
1197                 get_last_trigger(bus, u->unit_path, &last);
1198
1199                 if (!GREEDY_REALLOC(timer_infos, size, c+1)) {
1200                         r = log_oom();
1201                         goto cleanup;
1202                 }
1203
1204                 m = calc_next_elapse(&nw, &next);
1205
1206                 timer_infos[c++] = (struct timer_info) {
1207                         .machine = u->machine,
1208                         .id = u->id,
1209                         .next_elapse = m,
1210                         .last_trigger = last,
1211                         .triggered = triggered,
1212                 };
1213
1214                 triggered = NULL; /* avoid cleanup */
1215         }
1216
1217         qsort_safe(timer_infos, c, sizeof(struct timer_info),
1218                    (__compar_fn_t) timer_info_compare);
1219
1220         output_timers_list(timer_infos, c);
1221
1222  cleanup:
1223         for (t = timer_infos; t < timer_infos + c; t++)
1224                 strv_free(t->triggered);
1225
1226         return r;
1227 }
1228
1229 static int compare_unit_file_list(const void *a, const void *b) {
1230         const char *d1, *d2;
1231         const UnitFileList *u = a, *v = b;
1232
1233         d1 = strrchr(u->path, '.');
1234         d2 = strrchr(v->path, '.');
1235
1236         if (d1 && d2) {
1237                 int r;
1238
1239                 r = strcasecmp(d1, d2);
1240                 if (r != 0)
1241                         return r;
1242         }
1243
1244         return strcasecmp(basename(u->path), basename(v->path));
1245 }
1246
1247 static bool output_show_unit_file(const UnitFileList *u, char **patterns) {
1248         const char *dot;
1249
1250         if (!strv_isempty(patterns)) {
1251                 char **pattern;
1252
1253                 STRV_FOREACH(pattern, patterns)
1254                         if (fnmatch(*pattern, basename(u->path), FNM_NOESCAPE) == 0)
1255                                 return true;
1256                 return false;
1257         }
1258
1259         return !arg_types || ((dot = strrchr(u->path, '.')) && strv_find(arg_types, dot+1));
1260 }
1261
1262 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
1263         unsigned max_id_len, id_cols, state_cols;
1264         const UnitFileList *u;
1265
1266         max_id_len = strlen("UNIT FILE");
1267         state_cols = strlen("STATE");
1268
1269         for (u = units; u < units + c; u++) {
1270                 max_id_len = MAX(max_id_len, strlen(basename(u->path)));
1271                 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
1272         }
1273
1274         if (!arg_full) {
1275                 unsigned basic_cols;
1276
1277                 id_cols = MIN(max_id_len, 25u);
1278                 basic_cols = 1 + id_cols + state_cols;
1279                 if (basic_cols < (unsigned) columns())
1280                         id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
1281         } else
1282                 id_cols = max_id_len;
1283
1284         if (!arg_no_legend)
1285                 printf("%-*s %-*s\n",
1286                        id_cols, "UNIT FILE",
1287                        state_cols, "STATE");
1288
1289         for (u = units; u < units + c; u++) {
1290                 _cleanup_free_ char *e = NULL;
1291                 const char *on, *off;
1292                 const char *id;
1293
1294                 if (u->state == UNIT_FILE_MASKED ||
1295                     u->state == UNIT_FILE_MASKED_RUNTIME ||
1296                     u->state == UNIT_FILE_DISABLED ||
1297                     u->state == UNIT_FILE_INVALID) {
1298                         on  = ansi_highlight_red();
1299                         off = ansi_highlight_off();
1300                 } else if (u->state == UNIT_FILE_ENABLED) {
1301                         on  = ansi_highlight_green();
1302                         off = ansi_highlight_off();
1303                 } else
1304                         on = off = "";
1305
1306                 id = basename(u->path);
1307
1308                 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
1309
1310                 printf("%-*s %s%-*s%s\n",
1311                        id_cols, e ? e : id,
1312                        on, state_cols, unit_file_state_to_string(u->state), off);
1313         }
1314
1315         if (!arg_no_legend)
1316                 printf("\n%u unit files listed.\n", c);
1317 }
1318
1319 static int list_unit_files(sd_bus *bus, char **args) {
1320         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1321         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1322         _cleanup_free_ UnitFileList *units = NULL;
1323         UnitFileList *unit;
1324         size_t size = 0;
1325         unsigned c = 0;
1326         const char *state;
1327         char *path;
1328         int r;
1329
1330         pager_open_if_enabled();
1331
1332         if (avoid_bus()) {
1333                 Hashmap *h;
1334                 UnitFileList *u;
1335                 Iterator i;
1336                 unsigned n_units;
1337
1338                 h = hashmap_new(string_hash_func, string_compare_func);
1339                 if (!h)
1340                         return log_oom();
1341
1342                 r = unit_file_get_list(arg_scope, arg_root, h);
1343                 if (r < 0) {
1344                         unit_file_list_free(h);
1345                         log_error("Failed to get unit file list: %s", strerror(-r));
1346                         return r;
1347                 }
1348
1349                 n_units = hashmap_size(h);
1350                 units = new(UnitFileList, n_units);
1351                 if (!units) {
1352                         unit_file_list_free(h);
1353                         return log_oom();
1354                 }
1355
1356                 HASHMAP_FOREACH(u, h, i) {
1357                         if (!output_show_unit_file(u, strv_skip_first(args)))
1358                                 continue;
1359
1360                         units[c++] = *u;
1361                         free(u);
1362                 }
1363
1364                 assert(c <= n_units);
1365                 hashmap_free(h);
1366         } else {
1367                 r = sd_bus_call_method(
1368                                 bus,
1369                                 "org.freedesktop.systemd1",
1370                                 "/org/freedesktop/systemd1",
1371                                 "org.freedesktop.systemd1.Manager",
1372                                 "ListUnitFiles",
1373                                 &error,
1374                                 &reply,
1375                                 NULL);
1376                 if (r < 0) {
1377                         log_error("Failed to list unit files: %s", bus_error_message(&error, r));
1378                         return r;
1379                 }
1380
1381                 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
1382                 if (r < 0)
1383                         return bus_log_parse_error(r);
1384
1385                 while ((r = sd_bus_message_read(reply, "(ss)", &path, &state)) > 0) {
1386
1387                         if (!GREEDY_REALLOC(units, size, c + 1))
1388                                 return log_oom();
1389
1390                         units[c] = (struct UnitFileList) {
1391                                 path,
1392                                 unit_file_state_from_string(state)
1393                         };
1394
1395                         if (output_show_unit_file(&units[c], strv_skip_first(args)))
1396                                 c ++;
1397
1398                 }
1399                 if (r < 0)
1400                         return bus_log_parse_error(r);
1401
1402                 r = sd_bus_message_exit_container(reply);
1403                 if (r < 0)
1404                         return bus_log_parse_error(r);
1405         }
1406
1407         if (c > 0) {
1408                 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
1409                 output_unit_file_list(units, c);
1410         }
1411
1412         if (avoid_bus())
1413                 for (unit = units; unit < units + c; unit++)
1414                         free(unit->path);
1415
1416         return 0;
1417 }
1418
1419 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
1420         _cleanup_free_ char *n = NULL;
1421         size_t max_len = MAX(columns(),20u);
1422         size_t len = 0;
1423         int i;
1424
1425         if (!arg_plain) {
1426
1427                 for (i = level - 1; i >= 0; i--) {
1428                         len += 2;
1429                         if (len > max_len - 3 && !arg_full) {
1430                                 printf("%s...\n",max_len % 2 ? "" : " ");
1431                                 return 0;
1432                         }
1433                         printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
1434                 }
1435                 len += 2;
1436
1437                 if (len > max_len - 3 && !arg_full) {
1438                         printf("%s...\n",max_len % 2 ? "" : " ");
1439                         return 0;
1440                 }
1441
1442                 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
1443         }
1444
1445         if (arg_full){
1446                 printf("%s\n", name);
1447                 return 0;
1448         }
1449
1450         n = ellipsize(name, max_len-len, 100);
1451         if (!n)
1452                 return log_oom();
1453
1454         printf("%s\n", n);
1455         return 0;
1456 }
1457
1458 static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) {
1459
1460         static const char *dependencies[_DEPENDENCY_MAX] = {
1461                 [DEPENDENCY_FORWARD] = "Requires\0"
1462                                        "RequiresOverridable\0"
1463                                        "Requisite\0"
1464                                        "RequisiteOverridable\0"
1465                                        "Wants\0",
1466                 [DEPENDENCY_REVERSE] = "RequiredBy\0"
1467                                        "RequiredByOverridable\0"
1468                                        "WantedBy\0"
1469                                        "PartOf\0",
1470                 [DEPENDENCY_AFTER]   = "After\0",
1471                 [DEPENDENCY_BEFORE]  = "Before\0",
1472         };
1473
1474         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1475         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1476         _cleanup_strv_free_ char **ret = NULL;
1477         _cleanup_free_ char *path = NULL;
1478         int r;
1479
1480         assert(bus);
1481         assert(name);
1482         assert(deps);
1483         assert_cc(ELEMENTSOF(dependencies) == _DEPENDENCY_MAX);
1484
1485         path = unit_dbus_path_from_name(name);
1486         if (!path)
1487                 return log_oom();
1488
1489         r = sd_bus_call_method(
1490                         bus,
1491                         "org.freedesktop.systemd1",
1492                         path,
1493                         "org.freedesktop.DBus.Properties",
1494                         "GetAll",
1495                         &error,
1496                         &reply,
1497                         "s", "org.freedesktop.systemd1.Unit");
1498         if (r < 0) {
1499                 log_error("Failed to get properties of %s: %s", name, bus_error_message(&error, r));
1500                 return r;
1501         }
1502
1503         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
1504         if (r < 0)
1505                 return bus_log_parse_error(r);
1506
1507         while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1508                 const char *prop;
1509
1510                 r = sd_bus_message_read(reply, "s", &prop);
1511                 if (r < 0)
1512                         return bus_log_parse_error(r);
1513
1514                 if (!nulstr_contains(dependencies[arg_dependency], prop)) {
1515                         r = sd_bus_message_skip(reply, "v");
1516                         if (r < 0)
1517                                 return bus_log_parse_error(r);
1518                 } else {
1519
1520                         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, "as");
1521                         if (r < 0)
1522                                 return bus_log_parse_error(r);
1523
1524                         r = bus_message_read_strv_extend(reply, &ret);
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
1533                 r = sd_bus_message_exit_container(reply);
1534                 if (r < 0)
1535                         return bus_log_parse_error(r);
1536
1537         }
1538         if (r < 0)
1539                 return bus_log_parse_error(r);
1540
1541         r = sd_bus_message_exit_container(reply);
1542         if (r < 0)
1543                 return bus_log_parse_error(r);
1544
1545         *deps = ret;
1546         ret = NULL;
1547
1548         return 0;
1549 }
1550
1551 static int list_dependencies_compare(const void *_a, const void *_b) {
1552         const char **a = (const char**) _a, **b = (const char**) _b;
1553
1554         if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1555                 return 1;
1556         if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1557                 return -1;
1558
1559         return strcasecmp(*a, *b);
1560 }
1561
1562 static int list_dependencies_one(
1563                 sd_bus *bus,
1564                 const char *name,
1565                 int level,
1566                 char ***units,
1567                 unsigned int branches) {
1568
1569         _cleanup_strv_free_ char **deps = NULL;
1570         char **c;
1571         int r = 0;
1572
1573         assert(bus);
1574         assert(name);
1575         assert(units);
1576
1577         r = strv_extend(units, name);
1578         if (r < 0)
1579                 return log_oom();
1580
1581         r = list_dependencies_get_dependencies(bus, name, &deps);
1582         if (r < 0)
1583                 return r;
1584
1585         qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1586
1587         STRV_FOREACH(c, deps) {
1588                 int state;
1589
1590                 if (strv_contains(*units, *c)) {
1591                         if (!arg_plain) {
1592                                 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1593                                 if (r < 0)
1594                                         return r;
1595                         }
1596                         continue;
1597                 }
1598
1599                 state = check_one_unit(bus, *c, "activating\0active\0reloading\0", true);
1600                 if (state > 0)
1601                         printf("%s%s%s", ansi_highlight_green(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1602                 else
1603                         printf("%s%s%s", ansi_highlight_red(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1604
1605                 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1606                 if (r < 0)
1607                         return r;
1608
1609                 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1610                        r = list_dependencies_one(bus, *c, level + 1, units, (branches << 1) | (c[1] == NULL ? 0 : 1));
1611                        if (r < 0)
1612                                return r;
1613                 }
1614         }
1615
1616         if (!arg_plain)
1617                 strv_remove(*units, name);
1618
1619         return 0;
1620 }
1621
1622 static int list_dependencies(sd_bus *bus, char **args) {
1623         _cleanup_strv_free_ char **units = NULL;
1624         _cleanup_free_ char *unit = NULL;
1625         const char *u;
1626
1627         assert(bus);
1628
1629         if (args[1]) {
1630                 unit = unit_name_mangle(args[1], MANGLE_NOGLOB);
1631                 if (!unit)
1632                         return log_oom();
1633                 u = unit;
1634         } else
1635                 u = SPECIAL_DEFAULT_TARGET;
1636
1637         pager_open_if_enabled();
1638
1639         puts(u);
1640
1641         return list_dependencies_one(bus, u, 0, &units, 0);
1642 }
1643
1644 struct machine_info {
1645         bool is_host;
1646         char *name;
1647         char *state;
1648         char *control_group;
1649         uint32_t n_failed_units;
1650         uint32_t n_jobs;
1651         usec_t timestamp;
1652 };
1653
1654 static const struct bus_properties_map machine_info_property_map[] = {
1655         { "SystemState",        "s", NULL, offsetof(struct machine_info, state)          },
1656         { "NJobs",              "u", NULL, offsetof(struct machine_info, n_jobs)         },
1657         { "NFailedUnits",       "u", NULL, offsetof(struct machine_info, n_failed_units) },
1658         { "ControlGroup",       "s", NULL, offsetof(struct machine_info, control_group)  },
1659         { "UserspaceTimestamp", "t", NULL, offsetof(struct machine_info, timestamp)      },
1660         {}
1661 };
1662
1663 static void free_machines_list(struct machine_info *machine_infos, int n) {
1664         int i;
1665
1666         if (!machine_infos)
1667                 return;
1668
1669         for (i = 0; i < n; i++) {
1670                 free(machine_infos[i].name);
1671                 free(machine_infos[i].state);
1672                 free(machine_infos[i].control_group);
1673         }
1674
1675         free(machine_infos);
1676 }
1677
1678 static int compare_machine_info(const void *a, const void *b) {
1679         const struct machine_info *u = a, *v = b;
1680
1681         if (u->is_host != v->is_host)
1682                 return u->is_host > v->is_host ? -1 : 1;
1683
1684         return strcasecmp(u->name, v->name);
1685 }
1686
1687 static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
1688         _cleanup_bus_unref_ sd_bus *container = NULL;
1689         int r;
1690
1691         assert(mi);
1692
1693         if (!bus) {
1694                 r = sd_bus_open_system_container(&container, mi->name);
1695                 if (r < 0)
1696                         return r;
1697
1698                 bus = container;
1699         }
1700
1701         r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, mi);
1702         if (r < 0)
1703                 return r;
1704
1705         return 0;
1706 }
1707
1708 static bool output_show_machine(const char *name, char **patterns) {
1709         char **i;
1710
1711         assert(name);
1712
1713         if (strv_isempty(patterns))
1714                 return true;
1715
1716         STRV_FOREACH(i, patterns)
1717                 if (fnmatch(*i, name, FNM_NOESCAPE) == 0)
1718                         return true;
1719
1720         return false;
1721 }
1722
1723 static int get_machine_list(
1724                 sd_bus *bus,
1725                 struct machine_info **_machine_infos,
1726                 char **patterns) {
1727
1728         struct machine_info *machine_infos = NULL;
1729         _cleanup_strv_free_ char **m = NULL;
1730         _cleanup_free_ char *hn = NULL;
1731         size_t sz = 0;
1732         char **i;
1733         int c = 0;
1734
1735         hn = gethostname_malloc();
1736         if (!hn)
1737                 return log_oom();
1738
1739         if (output_show_machine(hn, patterns)) {
1740                 if (!GREEDY_REALLOC0(machine_infos, sz, c+1))
1741                         return log_oom();
1742
1743                 machine_infos[c].is_host = true;
1744                 machine_infos[c].name = hn;
1745                 hn = NULL;
1746
1747                 get_machine_properties(bus, &machine_infos[c]);
1748                 c++;
1749         }
1750
1751         sd_get_machine_names(&m);
1752         STRV_FOREACH(i, m) {
1753                 _cleanup_free_ char *class = NULL;
1754
1755                 if (!output_show_machine(*i, patterns))
1756                         continue;
1757
1758                 sd_machine_get_class(*i, &class);
1759                 if (!streq_ptr(class, "container"))
1760                         continue;
1761
1762                 if (!GREEDY_REALLOC0(machine_infos, sz, c+1)) {
1763                         free_machines_list(machine_infos, c);
1764                         return log_oom();
1765                 }
1766
1767                 machine_infos[c].is_host = false;
1768                 machine_infos[c].name = strdup(*i);
1769                 if (!machine_infos[c].name) {
1770                         free_machines_list(machine_infos, c);
1771                         return log_oom();
1772                 }
1773
1774                 get_machine_properties(NULL, &machine_infos[c]);
1775                 c++;
1776         }
1777
1778         *_machine_infos = machine_infos;
1779         return c;
1780 }
1781
1782 static void output_machines_list(struct machine_info *machine_infos, unsigned n) {
1783         struct machine_info *m;
1784         unsigned
1785                 circle_len = 0,
1786                 namelen = sizeof("NAME") - 1,
1787                 statelen = sizeof("STATE") - 1,
1788                 failedlen = sizeof("FAILED") - 1,
1789                 jobslen = sizeof("JOBS") - 1;
1790
1791         assert(machine_infos || n == 0);
1792
1793         for (m = machine_infos; m < machine_infos + n; m++) {
1794                 namelen = MAX(namelen, strlen(m->name) + (m->is_host ? sizeof(" (host)") - 1 : 0));
1795                 statelen = MAX(statelen, m->state ? strlen(m->state) : 0);
1796                 failedlen = MAX(failedlen, DECIMAL_STR_WIDTH(m->n_failed_units));
1797                 jobslen = MAX(jobslen, DECIMAL_STR_WIDTH(m->n_jobs));
1798
1799                 if (!arg_no_legend && !streq_ptr(m->state, "running"))
1800                         circle_len = 2;
1801         }
1802
1803         if (!arg_no_legend) {
1804                 if (circle_len > 0)
1805                         fputs("  ", stdout);
1806
1807                 printf("%-*s %-*s %-*s %-*s\n",
1808                          namelen, "NAME",
1809                         statelen, "STATE",
1810                        failedlen, "FAILED",
1811                          jobslen, "JOBS");
1812         }
1813
1814         for (m = machine_infos; m < machine_infos + n; m++) {
1815                 const char *on_state = "", *off_state = "";
1816                 const char *on_failed = "", *off_failed = "";
1817                 bool circle = false;
1818
1819                 if (streq_ptr(m->state, "degraded")) {
1820                         on_state = ansi_highlight_red();
1821                         off_state = ansi_highlight_off();
1822                         circle = true;
1823                 } else if (!streq_ptr(m->state, "running")) {
1824                         on_state = ansi_highlight_yellow();
1825                         off_state = ansi_highlight_off();
1826                         circle = true;
1827                 }
1828
1829                 if (m->n_failed_units > 0) {
1830                         on_failed = ansi_highlight_red();
1831                         off_failed = ansi_highlight_off();
1832                 } else
1833                         on_failed = off_failed = "";
1834
1835                 if (circle_len > 0)
1836                         printf("%s%s%s", on_state, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : "  ", off_state);
1837
1838                 if (m->is_host)
1839                         printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
1840                                (int) (namelen - (sizeof(" (host)")-1)), strna(m->name),
1841                                on_state, statelen, strna(m->state), off_state,
1842                                on_failed, failedlen, m->n_failed_units, off_failed,
1843                                jobslen, m->n_jobs);
1844                 else
1845                         printf("%-*s %s%-*s%s %s%*u%s %*u\n",
1846                                namelen, strna(m->name),
1847                                on_state, statelen, strna(m->state), off_state,
1848                                on_failed, failedlen, m->n_failed_units, off_failed,
1849                                jobslen, m->n_jobs);
1850         }
1851
1852         if (!arg_no_legend)
1853                 printf("\n%u machines listed.\n", n);
1854 }
1855
1856 static int list_machines(sd_bus *bus, char **args) {
1857         struct machine_info *machine_infos = NULL;
1858         int r;
1859
1860         assert(bus);
1861
1862         if (geteuid() != 0) {
1863                 log_error("Must be root.");
1864                 return -EPERM;
1865         }
1866
1867         pager_open_if_enabled();
1868
1869         r = get_machine_list(bus, &machine_infos, strv_skip_first(args));
1870         if (r < 0)
1871                 return r;
1872
1873         qsort_safe(machine_infos, r, sizeof(struct machine_info), compare_machine_info);
1874         output_machines_list(machine_infos, r);
1875         free_machines_list(machine_infos, r);
1876
1877         return 0;
1878 }
1879
1880 static int get_default(sd_bus *bus, char **args) {
1881         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1882         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1883         _cleanup_free_ char *_path = NULL;
1884         const char *path;
1885         int r;
1886
1887         if (!bus || avoid_bus()) {
1888                 r = unit_file_get_default(arg_scope, arg_root, &_path);
1889                 if (r < 0) {
1890                         log_error("Failed to get default target: %s", strerror(-r));
1891                         return r;
1892                 }
1893                 path = _path;
1894
1895         } else {
1896                 r = sd_bus_call_method(
1897                                 bus,
1898                                 "org.freedesktop.systemd1",
1899                                 "/org/freedesktop/systemd1",
1900                                 "org.freedesktop.systemd1.Manager",
1901                                 "GetDefaultTarget",
1902                                 &error,
1903                                 &reply,
1904                                 NULL);
1905                 if (r < 0) {
1906                         log_error("Failed to get default target: %s", bus_error_message(&error, -r));
1907                         return r;
1908                 }
1909
1910                 r = sd_bus_message_read(reply, "s", &path);
1911                 if (r < 0)
1912                         return bus_log_parse_error(r);
1913         }
1914
1915         if (path)
1916                 printf("%s\n", path);
1917
1918         return 0;
1919 }
1920
1921 static void dump_unit_file_changes(const UnitFileChange *changes, unsigned n_changes) {
1922         unsigned i;
1923
1924         assert(changes || n_changes == 0);
1925
1926         for (i = 0; i < n_changes; i++) {
1927                 if (changes[i].type == UNIT_FILE_SYMLINK)
1928                         log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
1929                 else
1930                         log_info("rm '%s'", changes[i].path);
1931         }
1932 }
1933
1934 static int deserialize_and_dump_unit_file_changes(sd_bus_message *m) {
1935         const char *type, *path, *source;
1936         int r;
1937
1938         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
1939         if (r < 0)
1940                 return bus_log_parse_error(r);
1941
1942         while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
1943                 if (!arg_quiet) {
1944                         if (streq(type, "symlink"))
1945                                 log_info("ln -s '%s' '%s'", source, path);
1946                         else
1947                                 log_info("rm '%s'", path);
1948                 }
1949         }
1950         if (r < 0)
1951                 return bus_log_parse_error(r);
1952
1953         r = sd_bus_message_exit_container(m);
1954         if (r < 0)
1955                 return bus_log_parse_error(r);
1956
1957         return 0;
1958 }
1959
1960 static int set_default(sd_bus *bus, char **args) {
1961         _cleanup_free_ char *unit = NULL;
1962         UnitFileChange *changes = NULL;
1963         unsigned n_changes = 0;
1964         int r;
1965
1966         unit = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
1967         if (!unit)
1968                 return log_oom();
1969
1970         if (!bus || avoid_bus()) {
1971                 r = unit_file_set_default(arg_scope, arg_root, unit, true, &changes, &n_changes);
1972                 if (r < 0) {
1973                         log_error("Failed to set default target: %s", strerror(-r));
1974                         return r;
1975                 }
1976
1977                 if (!arg_quiet)
1978                         dump_unit_file_changes(changes, n_changes);
1979
1980                 r = 0;
1981         } else {
1982                 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1983                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1984
1985                 r = sd_bus_call_method(
1986                                 bus,
1987                                 "org.freedesktop.systemd1",
1988                                 "/org/freedesktop/systemd1",
1989                                 "org.freedesktop.systemd1.Manager",
1990                                 "SetDefaultTarget",
1991                                 &error,
1992                                 &reply,
1993                                 "sb", unit, true);
1994                 if (r < 0) {
1995                         log_error("Failed to set default target: %s", bus_error_message(&error, -r));
1996                         return r;
1997                 }
1998
1999                 r = deserialize_and_dump_unit_file_changes(reply);
2000                 if (r < 0)
2001                         return r;
2002
2003                 /* Try to reload if enabled */
2004                 if (!arg_no_reload)
2005                         r = daemon_reload(bus, args);
2006                 else
2007                         r = 0;
2008         }
2009
2010         unit_file_changes_free(changes, n_changes);
2011
2012         return r;
2013 }
2014
2015 struct job_info {
2016         uint32_t id;
2017         const char *name, *type, *state;
2018 };
2019
2020 static void output_jobs_list(const struct job_info* jobs, unsigned n, bool skipped) {
2021         unsigned id_len, unit_len, type_len, state_len;
2022         const struct job_info *j;
2023         const char *on, *off;
2024         bool shorten = false;
2025
2026         assert(n == 0 || jobs);
2027
2028         if (n == 0) {
2029                 on = ansi_highlight_green();
2030                 off = ansi_highlight_off();
2031
2032                 printf("%sNo jobs %s.%s\n", on, skipped ? "listed" : "running", off);
2033                 return;
2034         }
2035
2036         pager_open_if_enabled();
2037
2038         id_len = strlen("JOB");
2039         unit_len = strlen("UNIT");
2040         type_len = strlen("TYPE");
2041         state_len = strlen("STATE");
2042
2043         for (j = jobs; j < jobs + n; j++) {
2044                 uint32_t id = j->id;
2045                 assert(j->name && j->type && j->state);
2046
2047                 id_len = MAX(id_len, DECIMAL_STR_WIDTH(id));
2048                 unit_len = MAX(unit_len, strlen(j->name));
2049                 type_len = MAX(type_len, strlen(j->type));
2050                 state_len = MAX(state_len, strlen(j->state));
2051         }
2052
2053         if (!arg_full && id_len + 1 + unit_len + type_len + 1 + state_len > columns()) {
2054                 unit_len = MAX(33u, columns() - id_len - type_len - state_len - 3);
2055                 shorten = true;
2056         }
2057
2058         if (!arg_no_legend)
2059                 printf("%*s %-*s %-*s %-*s\n",
2060                        id_len, "JOB",
2061                        unit_len, "UNIT",
2062                        type_len, "TYPE",
2063                        state_len, "STATE");
2064
2065         for (j = jobs; j < jobs + n; j++) {
2066                 _cleanup_free_ char *e = NULL;
2067
2068                 if (streq(j->state, "running")) {
2069                         on = ansi_highlight();
2070                         off = ansi_highlight_off();
2071                 } else
2072                         on = off = "";
2073
2074                 e = shorten ? ellipsize(j->name, unit_len, 33) : NULL;
2075                 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2076                        id_len, j->id,
2077                        on, unit_len, e ? e : j->name, off,
2078                        type_len, j->type,
2079                        on, state_len, j->state, off);
2080         }
2081
2082         if (!arg_no_legend) {
2083                 on = ansi_highlight();
2084                 off = ansi_highlight_off();
2085
2086                 printf("\n%s%u jobs listed%s.\n", on, n, off);
2087         }
2088 }
2089
2090 static bool output_show_job(struct job_info *job, char **patterns) {
2091         char **pattern;
2092
2093         assert(job);
2094
2095         if (strv_isempty(patterns))
2096                 return true;
2097
2098         STRV_FOREACH(pattern, patterns)
2099                 if (fnmatch(*pattern, job->name, FNM_NOESCAPE) == 0)
2100                         return true;
2101         return false;
2102 }
2103
2104 static int list_jobs(sd_bus *bus, char **args) {
2105         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2106         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2107         const char *name, *type, *state, *job_path, *unit_path;
2108         _cleanup_free_ struct job_info *jobs = NULL;
2109         size_t size = 0;
2110         unsigned c = 0;
2111         uint32_t id;
2112         int r;
2113         bool skipped = false;
2114
2115         r = sd_bus_call_method(
2116                         bus,
2117                         "org.freedesktop.systemd1",
2118                         "/org/freedesktop/systemd1",
2119                         "org.freedesktop.systemd1.Manager",
2120                         "ListJobs",
2121                         &error,
2122                         &reply,
2123                         NULL);
2124         if (r < 0) {
2125                 log_error("Failed to list jobs: %s", bus_error_message(&error, r));
2126                 return r;
2127         }
2128
2129         r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
2130         if (r < 0)
2131                 return bus_log_parse_error(r);
2132
2133         while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, &job_path, &unit_path)) > 0) {
2134                 struct job_info job = { id, name, type, state };
2135
2136                 if (!output_show_job(&job, strv_skip_first(args))) {
2137                         skipped = true;
2138                         continue;
2139                 }
2140
2141                 if (!GREEDY_REALLOC(jobs, size, c + 1))
2142                         return log_oom();
2143
2144                 jobs[c++] = job;
2145         }
2146         if (r < 0)
2147                 return bus_log_parse_error(r);
2148
2149         r = sd_bus_message_exit_container(reply);
2150         if (r < 0)
2151                 return bus_log_parse_error(r);
2152
2153         output_jobs_list(jobs, c, skipped);
2154         return r;
2155 }
2156
2157 static int cancel_job(sd_bus *bus, char **args) {
2158         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2159         char **name;
2160
2161         assert(args);
2162
2163         if (strv_length(args) <= 1)
2164                 return daemon_reload(bus, args);
2165
2166         STRV_FOREACH(name, args+1) {
2167                 uint32_t id;
2168                 int r;
2169
2170                 r = safe_atou32(*name, &id);
2171                 if (r < 0) {
2172                         log_error("Failed to parse job id \"%s\": %s", *name, strerror(-r));
2173                         return r;
2174                 }
2175
2176                 r = sd_bus_call_method(
2177                                 bus,
2178                                 "org.freedesktop.systemd1",
2179                                 "/org/freedesktop/systemd1",
2180                                 "org.freedesktop.systemd1.Manager",
2181                                 "CancelJob",
2182                                 &error,
2183                                 NULL,
2184                                 "u", id);
2185                 if (r < 0) {
2186                         log_error("Failed to cancel job %u: %s", (unsigned) id, bus_error_message(&error, r));
2187                         return r;
2188                 }
2189         }
2190
2191         return 0;
2192 }
2193
2194 static int need_daemon_reload(sd_bus *bus, const char *unit) {
2195         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2196         const char *path;
2197         int b, r;
2198
2199         /* We ignore all errors here, since this is used to show a
2200          * warning only */
2201
2202         /* We don't use unit_dbus_path_from_name() directly since we
2203          * don't want to load the unit if it isn't loaded. */
2204
2205         r = sd_bus_call_method(
2206                         bus,
2207                         "org.freedesktop.systemd1",
2208                         "/org/freedesktop/systemd1",
2209                         "org.freedesktop.systemd1.Manager",
2210                         "GetUnit",
2211                         NULL,
2212                         &reply,
2213                         "s", unit);
2214         if (r < 0)
2215                 return r;
2216
2217         r = sd_bus_message_read(reply, "o", &path);
2218         if (r < 0)
2219                 return r;
2220
2221         r = sd_bus_get_property_trivial(
2222                         bus,
2223                         "org.freedesktop.systemd1",
2224                         path,
2225                         "org.freedesktop.systemd1.Unit",
2226                         "NeedDaemonReload",
2227                         NULL,
2228                         'b', &b);
2229         if (r < 0)
2230                 return r;
2231
2232         return b;
2233 }
2234
2235 typedef struct WaitData {
2236         Set *set;
2237
2238         char *name;
2239         char *result;
2240 } WaitData;
2241
2242 static int wait_filter(sd_bus *bus, sd_bus_message *m, void *data, sd_bus_error *error) {
2243         WaitData *d = data;
2244
2245         assert(bus);
2246         assert(m);
2247         assert(d);
2248
2249         log_debug("Got D-Bus request: %s.%s() on %s",
2250                   sd_bus_message_get_interface(m),
2251                   sd_bus_message_get_member(m),
2252                   sd_bus_message_get_path(m));
2253
2254         if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
2255                 log_error("Warning! D-Bus connection terminated.");
2256                 sd_bus_close(bus);
2257         } else if (sd_bus_message_is_signal(m, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
2258                 uint32_t id;
2259                 const char *path, *result, *unit;
2260                 char *ret;
2261                 int r;
2262
2263                 r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
2264                 if (r >= 0) {
2265                         ret = set_remove(d->set, (char*) path);
2266                         if (!ret)
2267                                 return 0;
2268
2269                         free(ret);
2270
2271                         if (!isempty(result))
2272                                 d->result = strdup(result);
2273
2274                         if (!isempty(unit))
2275                                 d->name = strdup(unit);
2276
2277                         return 0;
2278                 }
2279 #ifndef NOLEGACY
2280                 r = sd_bus_message_read(m, "uos", &id, &path, &result);
2281                 if (r >= 0) {
2282                         ret = set_remove(d->set, (char*) path);
2283                         if (!ret)
2284                                 return 0;
2285
2286                         free(ret);
2287
2288                         if (*result)
2289                                 d->result = strdup(result);
2290
2291                         return 0;
2292                 }
2293 #endif
2294
2295                 bus_log_parse_error(r);
2296         }
2297
2298         return 0;
2299 }
2300
2301 static int enable_wait_for_jobs(sd_bus *bus) {
2302         int r;
2303
2304         assert(bus);
2305
2306         r = sd_bus_add_match(
2307                         bus,
2308                         "type='signal',"
2309                         "sender='org.freedesktop.systemd1',"
2310                         "interface='org.freedesktop.systemd1.Manager',"
2311                         "member='JobRemoved',"
2312                         "path='/org/freedesktop/systemd1'",
2313                         NULL, NULL);
2314         if (r < 0) {
2315                 log_error("Failed to add match");
2316                 return -EIO;
2317         }
2318
2319         /* This is slightly dirty, since we don't undo the match registrations. */
2320         return 0;
2321 }
2322
2323 static int bus_process_wait(sd_bus *bus) {
2324         int r;
2325
2326         for (;;) {
2327                 r = sd_bus_process(bus, NULL);
2328                 if (r < 0)
2329                         return r;
2330                 if (r > 0)
2331                         return 0;
2332                 r = sd_bus_wait(bus, (uint64_t) -1);
2333                 if (r < 0)
2334                         return r;
2335         }
2336 }
2337
2338 static int check_wait_response(WaitData *d) {
2339         int r = 0;
2340
2341         assert(d->result);
2342
2343         if (!arg_quiet) {
2344                 if (streq(d->result, "timeout"))
2345                         log_error("Job for %s timed out.", strna(d->name));
2346                 else if (streq(d->result, "canceled"))
2347                         log_error("Job for %s canceled.", strna(d->name));
2348                 else if (streq(d->result, "dependency"))
2349                         log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d->name));
2350                 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
2351                         log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d->name), strna(d->name));
2352         }
2353
2354         if (streq(d->result, "timeout"))
2355                 r = -ETIME;
2356         else if (streq(d->result, "canceled"))
2357                 r = -ECANCELED;
2358         else if (streq(d->result, "dependency"))
2359                 r = -EIO;
2360         else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
2361                 r = -EIO;
2362
2363         return r;
2364 }
2365
2366 static int wait_for_jobs(sd_bus *bus, Set *s) {
2367         WaitData d = { .set = s };
2368         int r = 0, q;
2369
2370         assert(bus);
2371         assert(s);
2372
2373         q = sd_bus_add_filter(bus, wait_filter, &d);
2374         if (q < 0)
2375                 return log_oom();
2376
2377         while (!set_isempty(s)) {
2378                 q = bus_process_wait(bus);
2379                 if (q < 0) {
2380                         log_error("Failed to wait for response: %s", strerror(-r));
2381                         return q;
2382                 }
2383
2384                 if (d.result) {
2385                         q = check_wait_response(&d);
2386                         /* Return the first error as it is most likely to be
2387                          * meaningful. */
2388                         if (q < 0 && r == 0)
2389                                 r = q;
2390                         log_debug("Got result %s/%s for job %s",
2391                                   strna(d.result), strerror(-q), strna(d.name));
2392                 }
2393
2394                 free(d.name);
2395                 d.name = NULL;
2396
2397                 free(d.result);
2398                 d.result = NULL;
2399         }
2400
2401         q = sd_bus_remove_filter(bus, wait_filter, &d);
2402         if (q < 0 && r == 0)
2403                 r = q;
2404
2405         return r;
2406 }
2407
2408 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
2409         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2410         _cleanup_free_ char *n = NULL, *state = NULL;
2411         const char *path;
2412         int r;
2413
2414         assert(name);
2415
2416         n = unit_name_mangle(name, MANGLE_NOGLOB);
2417         if (!n)
2418                 return log_oom();
2419
2420         /* We don't use unit_dbus_path_from_name() directly since we
2421          * don't want to load the unit if it isn't loaded. */
2422
2423         r = sd_bus_call_method(
2424                         bus,
2425                         "org.freedesktop.systemd1",
2426                         "/org/freedesktop/systemd1",
2427                         "org.freedesktop.systemd1.Manager",
2428                         "GetUnit",
2429                         NULL,
2430                         &reply,
2431                         "s", n);
2432         if (r < 0) {
2433                 if (!quiet)
2434                         puts("unknown");
2435                 return 0;
2436         }
2437
2438         r = sd_bus_message_read(reply, "o", &path);
2439         if (r < 0)
2440                 return bus_log_parse_error(r);
2441
2442         r = sd_bus_get_property_string(
2443                         bus,
2444                         "org.freedesktop.systemd1",
2445                         path,
2446                         "org.freedesktop.systemd1.Unit",
2447                         "ActiveState",
2448                         NULL,
2449                         &state);
2450         if (r < 0) {
2451                 if (!quiet)
2452                         puts("unknown");
2453                 return 0;
2454         }
2455
2456         if (!quiet)
2457                 puts(state);
2458
2459         return nulstr_contains(good_states, state);
2460 }
2461
2462 static int check_triggering_units(
2463                 sd_bus *bus,
2464                 const char *name) {
2465
2466         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2467         _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
2468         _cleanup_strv_free_ char **triggered_by = NULL;
2469         bool print_warning_label = true;
2470         char **i;
2471         int r;
2472
2473         n = unit_name_mangle(name, MANGLE_NOGLOB);
2474         if (!n)
2475                 return log_oom();
2476
2477         path = unit_dbus_path_from_name(n);
2478         if (!path)
2479                 return log_oom();
2480
2481         r = sd_bus_get_property_string(
2482                         bus,
2483                         "org.freedesktop.systemd1",
2484                         path,
2485                         "org.freedesktop.systemd1.Unit",
2486                         "LoadState",
2487                         &error,
2488                         &state);
2489         if (r < 0) {
2490                 log_error("Failed to get load state of %s: %s", n, bus_error_message(&error, r));
2491                 return r;
2492         }
2493
2494         if (streq(state, "masked"))
2495                 return 0;
2496
2497         r = sd_bus_get_property_strv(
2498                         bus,
2499                         "org.freedesktop.systemd1",
2500                         path,
2501                         "org.freedesktop.systemd1.Unit",
2502                         "TriggeredBy",
2503                         &error,
2504                         &triggered_by);
2505         if (r < 0) {
2506                 log_error("Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
2507                 return r;
2508         }
2509
2510         STRV_FOREACH(i, triggered_by) {
2511                 r = check_one_unit(bus, *i, "active\0reloading\0", true);
2512                 if (r < 0) {
2513                         log_error("Failed to check unit: %s", strerror(-r));
2514                         return r;
2515                 }
2516
2517                 if (r == 0)
2518                         continue;
2519
2520                 if (print_warning_label) {
2521                         log_warning("Warning: Stopping %s, but it can still be activated by:", n);
2522                         print_warning_label = false;
2523                 }
2524
2525                 log_warning("  %s", *i);
2526         }
2527
2528         return 0;
2529 }
2530
2531 static const char *verb_to_method(const char *verb) {
2532        uint i;
2533
2534        for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2535                 if (streq_ptr(unit_actions[i].verb, verb))
2536                         return unit_actions[i].method;
2537
2538        return "StartUnit";
2539 }
2540
2541 static const char *method_to_verb(const char *method) {
2542        uint i;
2543
2544        for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2545                 if (streq_ptr(unit_actions[i].method, method))
2546                         return unit_actions[i].verb;
2547
2548        return "n/a";
2549 }
2550
2551 static int start_unit_one(
2552                 sd_bus *bus,
2553                 const char *method,
2554                 const char *name,
2555                 const char *mode,
2556                 sd_bus_error *error,
2557                 Set *s) {
2558
2559         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2560         const char *path;
2561         int r;
2562
2563         assert(method);
2564         assert(name);
2565         assert(mode);
2566         assert(error);
2567
2568         log_debug("Calling manager for %s on %s, %s", method, name, mode);
2569         r = sd_bus_call_method(
2570                         bus,
2571                         "org.freedesktop.systemd1",
2572                         "/org/freedesktop/systemd1",
2573                         "org.freedesktop.systemd1.Manager",
2574                         method,
2575                         error,
2576                         &reply,
2577                         "ss", name, mode);
2578         if (r < 0) {
2579                 const char *verb;
2580
2581                 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
2582                         /* There's always a fallback possible for
2583                          * legacy actions. */
2584                         return -EADDRNOTAVAIL;
2585
2586                 verb = method_to_verb(method);
2587
2588                 log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r));
2589                 return r;
2590         }
2591
2592         r = sd_bus_message_read(reply, "o", &path);
2593         if (r < 0)
2594                 return bus_log_parse_error(r);
2595
2596         if (need_daemon_reload(bus, name) > 0)
2597                 log_warning("Warning: Unit file of %s changed on disk, 'systemctl%s daemon-reload' recommended.",
2598                             name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
2599
2600         if (s) {
2601                 char *p;
2602
2603                 p = strdup(path);
2604                 if (!p)
2605                         return log_oom();
2606
2607                 log_debug("Adding %s to the set", p);
2608                 r = set_consume(s, p);
2609                 if (r < 0)
2610                         return log_oom();
2611         }
2612
2613         return 0;
2614 }
2615
2616 static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret) {
2617
2618         _cleanup_strv_free_ char **mangled = NULL, **globs = NULL;
2619         char **name;
2620         int r = 0, i;
2621
2622         STRV_FOREACH(name, names) {
2623                 char *t;
2624
2625                 if (suffix)
2626                         t = unit_name_mangle_with_suffix(*name, MANGLE_GLOB, suffix);
2627                 else
2628                         t = unit_name_mangle(*name, MANGLE_GLOB);
2629                 if (!t)
2630                         return log_oom();
2631
2632                 if (string_is_glob(t))
2633                         r = strv_consume(&globs, t);
2634                 else
2635                         r = strv_consume(&mangled, t);
2636                 if (r < 0)
2637                         return log_oom();
2638         }
2639
2640         /* Query the manager only if any of the names are a glob, since
2641          * this is fairly expensive */
2642         if (!strv_isempty(globs)) {
2643                 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2644                 _cleanup_free_ UnitInfo *unit_infos = NULL;
2645
2646                 r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
2647                 if (r < 0)
2648                         return r;
2649
2650                 for (i = 0; i < r; i++)
2651                         if (strv_extend(&mangled, unit_infos[i].id) < 0)
2652                                 return log_oom();
2653         }
2654
2655         *ret = mangled;
2656         mangled = NULL; /* do not free */
2657
2658         return 0;
2659 }
2660
2661 static const struct {
2662         const char *target;
2663         const char *verb;
2664         const char *mode;
2665 } action_table[_ACTION_MAX] = {
2666         [ACTION_HALT]         = { SPECIAL_HALT_TARGET,         "halt",         "replace-irreversibly" },
2667         [ACTION_POWEROFF]     = { SPECIAL_POWEROFF_TARGET,     "poweroff",     "replace-irreversibly" },
2668         [ACTION_REBOOT]       = { SPECIAL_REBOOT_TARGET,       "reboot",       "replace-irreversibly" },
2669         [ACTION_KEXEC]        = { SPECIAL_KEXEC_TARGET,        "kexec",        "replace-irreversibly" },
2670         [ACTION_RUNLEVEL2]    = { SPECIAL_RUNLEVEL2_TARGET,    NULL,           "isolate" },
2671         [ACTION_RUNLEVEL3]    = { SPECIAL_RUNLEVEL3_TARGET,    NULL,           "isolate" },
2672         [ACTION_RUNLEVEL4]    = { SPECIAL_RUNLEVEL4_TARGET,    NULL,           "isolate" },
2673         [ACTION_RUNLEVEL5]    = { SPECIAL_RUNLEVEL5_TARGET,    NULL,           "isolate" },
2674         [ACTION_RESCUE]       = { SPECIAL_RESCUE_TARGET,       "rescue",       "isolate" },
2675         [ACTION_EMERGENCY]    = { SPECIAL_EMERGENCY_TARGET,    "emergency",    "isolate" },
2676         [ACTION_DEFAULT]      = { SPECIAL_DEFAULT_TARGET,      "default",      "isolate" },
2677         [ACTION_EXIT]         = { SPECIAL_EXIT_TARGET,         "exit",         "replace-irreversibly" },
2678         [ACTION_SUSPEND]      = { SPECIAL_SUSPEND_TARGET,      "suspend",      "replace-irreversibly" },
2679         [ACTION_HIBERNATE]    = { SPECIAL_HIBERNATE_TARGET,    "hibernate",    "replace-irreversibly" },
2680         [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
2681 };
2682
2683 static enum action verb_to_action(const char *verb) {
2684         enum action i;
2685
2686         for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
2687                 if (streq_ptr(action_table[i].verb, verb))
2688                         return i;
2689
2690         return _ACTION_INVALID;
2691 }
2692
2693 static int start_unit(sd_bus *bus, char **args) {
2694         _cleanup_set_free_free_ Set *s = NULL;
2695         _cleanup_strv_free_ char **names = NULL;
2696         const char *method, *mode, *one_name;
2697         char **name;
2698         int r = 0;
2699
2700         assert(bus);
2701
2702         ask_password_agent_open_if_enabled();
2703
2704         if (arg_action == ACTION_SYSTEMCTL) {
2705                 enum action action;
2706                 method = verb_to_method(args[0]);
2707                 action = verb_to_action(args[0]);
2708
2709                 mode = streq(args[0], "isolate") ? "isolate" :
2710                        action_table[action].mode ?: arg_job_mode;
2711
2712                 one_name = action_table[action].target;
2713         } else {
2714                 assert(arg_action < ELEMENTSOF(action_table));
2715                 assert(action_table[arg_action].target);
2716
2717                 method = "StartUnit";
2718
2719                 mode = action_table[arg_action].mode;
2720                 one_name = action_table[arg_action].target;
2721         }
2722
2723         if (one_name)
2724                 names = strv_new(one_name, NULL);
2725         else {
2726                 r = expand_names(bus, args + 1, NULL, &names);
2727                 if (r < 0)
2728                         log_error("Failed to expand names: %s", strerror(-r));
2729         }
2730
2731         if (!arg_no_block) {
2732                 r = enable_wait_for_jobs(bus);
2733                 if (r < 0) {
2734                         log_error("Could not watch jobs: %s", strerror(-r));
2735                         return r;
2736                 }
2737
2738                 s = set_new(string_hash_func, string_compare_func);
2739                 if (!s)
2740                         return log_oom();
2741         }
2742
2743         STRV_FOREACH(name, names) {
2744                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2745                 int q;
2746
2747                 q = start_unit_one(bus, method, *name, mode, &error, s);
2748                 if (r >= 0 && q < 0)
2749                         r = translate_bus_error_to_exit_status(q, &error);
2750         }
2751
2752         if (!arg_no_block) {
2753                 int q;
2754
2755                 q = wait_for_jobs(bus, s);
2756                 if (q < 0)
2757                         return q;
2758
2759                 /* When stopping units, warn if they can still be triggered by
2760                  * another active unit (socket, path, timer) */
2761                 if (!arg_quiet && streq(method, "StopUnit"))
2762                         STRV_FOREACH(name, names)
2763                                 check_triggering_units(bus, *name);
2764         }
2765
2766         return r;
2767 }
2768
2769 /* Ask systemd-logind, which might grant access to unprivileged users
2770  * through PolicyKit */
2771 static int reboot_with_logind(sd_bus *bus, enum action a) {
2772 #ifdef HAVE_LOGIND
2773         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2774         const char *method;
2775         int r;
2776
2777         if (!bus)
2778                 return -EIO;
2779
2780         polkit_agent_open_if_enabled();
2781
2782         switch (a) {
2783
2784         case ACTION_REBOOT:
2785                 method = "Reboot";
2786                 break;
2787
2788         case ACTION_POWEROFF:
2789                 method = "PowerOff";
2790                 break;
2791
2792         case ACTION_SUSPEND:
2793                 method = "Suspend";
2794                 break;
2795
2796         case ACTION_HIBERNATE:
2797                 method = "Hibernate";
2798                 break;
2799
2800         case ACTION_HYBRID_SLEEP:
2801                 method = "HybridSleep";
2802                 break;
2803
2804         default:
2805                 return -EINVAL;
2806         }
2807
2808         r = sd_bus_call_method(
2809                         bus,
2810                         "org.freedesktop.login1",
2811                         "/org/freedesktop/login1",
2812                         "org.freedesktop.login1.Manager",
2813                         method,
2814                         &error,
2815                         NULL,
2816                         "b", true);
2817         if (r < 0)
2818                 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
2819
2820         return r;
2821 #else
2822         return -ENOSYS;
2823 #endif
2824 }
2825
2826 static int check_inhibitors(sd_bus *bus, enum action a) {
2827 #ifdef HAVE_LOGIND
2828         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2829         _cleanup_strv_free_ char **sessions = NULL;
2830         const char *what, *who, *why, *mode;
2831         uint32_t uid, pid;
2832         unsigned c = 0;
2833         char **s;
2834         int r;
2835
2836         if (!bus)
2837                 return 0;
2838
2839         if (arg_ignore_inhibitors || arg_force > 0)
2840                 return 0;
2841
2842         if (arg_when > 0)
2843                 return 0;
2844
2845         if (geteuid() == 0)
2846                 return 0;
2847
2848         if (!on_tty())
2849                 return 0;
2850
2851         r = sd_bus_call_method(
2852                         bus,
2853                         "org.freedesktop.login1",
2854                         "/org/freedesktop/login1",
2855                         "org.freedesktop.login1.Manager",
2856                         "ListInhibitors",
2857                         NULL,
2858                         &reply,
2859                         NULL);
2860         if (r < 0)
2861                 /* If logind is not around, then there are no inhibitors... */
2862                 return 0;
2863
2864         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
2865         if (r < 0)
2866                 return bus_log_parse_error(r);
2867
2868         while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
2869                 _cleanup_free_ char *comm = NULL, *user = NULL;
2870                 _cleanup_strv_free_ char **sv = NULL;
2871
2872                 if (!streq(mode, "block"))
2873                         continue;
2874
2875                 sv = strv_split(what, ":");
2876                 if (!sv)
2877                         return log_oom();
2878
2879                 if (!strv_contains(sv,
2880                                   a == ACTION_HALT ||
2881                                   a == ACTION_POWEROFF ||
2882                                   a == ACTION_REBOOT ||
2883                                   a == ACTION_KEXEC ? "shutdown" : "sleep"))
2884                         continue;
2885
2886                 get_process_comm(pid, &comm);
2887                 user = uid_to_name(uid);
2888
2889                 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
2890                             who, (unsigned long) pid, strna(comm), strna(user), why);
2891
2892                 c++;
2893         }
2894         if (r < 0)
2895                 return bus_log_parse_error(r);
2896
2897         r = sd_bus_message_exit_container(reply);
2898         if (r < 0)
2899                 return bus_log_parse_error(r);
2900
2901         /* Check for current sessions */
2902         sd_get_sessions(&sessions);
2903         STRV_FOREACH(s, sessions) {
2904                 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2905
2906                 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2907                         continue;
2908
2909                 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2910                         continue;
2911
2912                 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2913                         continue;
2914
2915                 sd_session_get_tty(*s, &tty);
2916                 sd_session_get_seat(*s, &seat);
2917                 sd_session_get_service(*s, &service);
2918                 user = uid_to_name(uid);
2919
2920                 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2921                 c++;
2922         }
2923
2924         if (c <= 0)
2925                 return 0;
2926
2927         log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2928                   action_table[a].verb);
2929
2930         return -EPERM;
2931 #else
2932         return 0;
2933 #endif
2934 }
2935
2936 static int start_special(sd_bus *bus, char **args) {
2937         enum action a;
2938         int r;
2939
2940         assert(args);
2941
2942         a = verb_to_action(args[0]);
2943
2944         r = check_inhibitors(bus, a);
2945         if (r < 0)
2946                 return r;
2947
2948         if (arg_force >= 2 && geteuid() != 0) {
2949                 log_error("Must be root.");
2950                 return -EPERM;
2951         }
2952
2953         if (arg_force >= 2 &&
2954             (a == ACTION_HALT ||
2955              a == ACTION_POWEROFF ||
2956              a == ACTION_REBOOT))
2957                 return halt_now(a);
2958
2959         if (arg_force >= 1 &&
2960             (a == ACTION_HALT ||
2961              a == ACTION_POWEROFF ||
2962              a == ACTION_REBOOT ||
2963              a == ACTION_KEXEC ||
2964              a == ACTION_EXIT))
2965                 return daemon_reload(bus, args);
2966
2967         /* first try logind, to allow authentication with polkit */
2968         if (geteuid() != 0 &&
2969             (a == ACTION_POWEROFF ||
2970              a == ACTION_REBOOT ||
2971              a == ACTION_SUSPEND ||
2972              a == ACTION_HIBERNATE ||
2973              a == ACTION_HYBRID_SLEEP)) {
2974                 r = reboot_with_logind(bus, a);
2975                 if (r >= 0)
2976                         return r;
2977         }
2978
2979         r = start_unit(bus, args);
2980         if (r == EXIT_SUCCESS)
2981                 warn_wall(a);
2982
2983         return r;
2984 }
2985
2986 static int check_unit_generic(sd_bus *bus, int code, const char *good_states, char **args) {
2987         _cleanup_strv_free_ char **names = NULL;
2988         char **name;
2989         int r;
2990
2991         assert(bus);
2992         assert(args);
2993
2994         r = expand_names(bus, args, NULL, &names);
2995         if (r < 0) {
2996                 log_error("Failed to expand names: %s", strerror(-r));
2997                 return r;
2998         }
2999
3000         STRV_FOREACH(name, names) {
3001                 int state;
3002
3003                 state = check_one_unit(bus, *name, good_states, arg_quiet);
3004                 if (state < 0)
3005                         return state;
3006                 if (state == 0)
3007                         r = code;
3008         }
3009
3010         return r;
3011 }
3012
3013 static int check_unit_active(sd_bus *bus, char **args) {
3014         /* According to LSB: 3, "program is not running" */
3015         return check_unit_generic(bus, 3, "active\0reloading\0", args + 1);
3016 }
3017
3018 static int check_unit_failed(sd_bus *bus, char **args) {
3019         return check_unit_generic(bus, 1, "failed\0", args + 1);
3020 }
3021
3022 static int kill_unit(sd_bus *bus, char **args) {
3023         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3024         _cleanup_strv_free_ char **names = NULL;
3025         char **name;
3026         int r, q;
3027
3028         assert(bus);
3029         assert(args);
3030
3031         if (!arg_kill_who)
3032                 arg_kill_who = "all";
3033
3034         r = expand_names(bus, args + 1, NULL, &names);
3035         if (r < 0)
3036                 log_error("Failed to expand names: %s", strerror(-r));
3037
3038         STRV_FOREACH(name, names) {
3039                 q = sd_bus_call_method(
3040                                 bus,
3041                                 "org.freedesktop.systemd1",
3042                                 "/org/freedesktop/systemd1",
3043                                 "org.freedesktop.systemd1.Manager",
3044                                 "KillUnit",
3045                                 &error,
3046                                 NULL,
3047                                 "ssi", *names, arg_kill_who, arg_signal);
3048                 if (q < 0) {
3049                         log_error("Failed to kill unit %s: %s",
3050                                   *names, bus_error_message(&error, r));
3051                         if (r == 0)
3052                                 r = q;
3053                 }
3054         }
3055
3056         return r;
3057 }
3058
3059 typedef struct ExecStatusInfo {
3060         char *name;
3061
3062         char *path;
3063         char **argv;
3064
3065         bool ignore;
3066
3067         usec_t start_timestamp;
3068         usec_t exit_timestamp;
3069         pid_t pid;
3070         int code;
3071         int status;
3072
3073         LIST_FIELDS(struct ExecStatusInfo, exec);
3074 } ExecStatusInfo;
3075
3076 static void exec_status_info_free(ExecStatusInfo *i) {
3077         assert(i);
3078
3079         free(i->name);
3080         free(i->path);
3081         strv_free(i->argv);
3082         free(i);
3083 }
3084
3085 static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
3086         uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
3087         const char *path;
3088         uint32_t pid;
3089         int32_t code, status;
3090         int ignore, r;
3091
3092         assert(m);
3093         assert(i);
3094
3095         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii");
3096         if (r < 0)
3097                 return bus_log_parse_error(r);
3098         else if (r == 0)
3099                 return 0;
3100
3101         r = sd_bus_message_read(m, "s", &path);
3102         if (r < 0)
3103                 return bus_log_parse_error(r);
3104
3105         i->path = strdup(path);
3106         if (!i->path)
3107                 return log_oom();
3108
3109         r = sd_bus_message_read_strv(m, &i->argv);
3110         if (r < 0)
3111                 return bus_log_parse_error(r);
3112
3113         r = sd_bus_message_read(m,
3114                                 "bttttuii",
3115                                 &ignore,
3116                                 &start_timestamp, &start_timestamp_monotonic,
3117                                 &exit_timestamp, &exit_timestamp_monotonic,
3118                                 &pid,
3119                                 &code, &status);
3120         if (r < 0)
3121                 return bus_log_parse_error(r);
3122
3123         i->ignore = ignore;
3124         i->start_timestamp = (usec_t) start_timestamp;
3125         i->exit_timestamp = (usec_t) exit_timestamp;
3126         i->pid = (pid_t) pid;
3127         i->code = code;
3128         i->status = status;
3129
3130         r = sd_bus_message_exit_container(m);
3131         if (r < 0)
3132                 return bus_log_parse_error(r);
3133
3134         return 1;
3135 }
3136
3137 typedef struct UnitStatusInfo {
3138         const char *id;
3139         const char *load_state;
3140         const char *active_state;
3141         const char *sub_state;
3142         const char *unit_file_state;
3143
3144         const char *description;
3145         const char *following;
3146
3147         char **documentation;
3148
3149         const char *fragment_path;
3150         const char *source_path;
3151         const char *control_group;
3152
3153         char **dropin_paths;
3154
3155         const char *load_error;
3156         const char *result;
3157
3158         usec_t inactive_exit_timestamp;
3159         usec_t inactive_exit_timestamp_monotonic;
3160         usec_t active_enter_timestamp;
3161         usec_t active_exit_timestamp;
3162         usec_t inactive_enter_timestamp;
3163
3164         bool need_daemon_reload;
3165
3166         /* Service */
3167 &nb