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