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