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