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