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