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