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