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