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