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