chiark / gitweb /
e1e4640ae8f47ef6d3419360eb73ba5f157dae92
[elogind.git] / src / systemctl / systemctl.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 Lennart Poettering
7   Copyright 2013 Marc-Antoine Perennou
8
9   systemd is free software; you can redistribute it and/or modify it
10   under the terms of the GNU Lesser General Public License as published by
11   the Free Software Foundation; either version 2.1 of the License, or
12   (at your option) any later version.
13
14   systemd is distributed in the hope that it will be useful, but
15   WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   Lesser General Public License for more details.
18
19   You should have received a copy of the GNU Lesser General Public License
20   along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 ***/
22
23 #include <sys/reboot.h>
24 #include <linux/reboot.h>
25 #include <sys/syscall.h>
26 #include <stdio.h>
27 #include <getopt.h>
28 #include <locale.h>
29 #include <stdbool.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <sys/ioctl.h>
33 #include <termios.h>
34 #include <unistd.h>
35 #include <fcntl.h>
36 #include <sys/socket.h>
37 #include <sys/stat.h>
38 #include <stddef.h>
39 #include <sys/prctl.h>
40 #include <fnmatch.h>
41
42 #include "sd-daemon.h"
43 #include "sd-shutdown.h"
44 #include "sd-login.h"
45 #include "sd-bus.h"
46 #include "log.h"
47 #include "util.h"
48 #include "macro.h"
49 #include "set.h"
50 #include "utmp-wtmp.h"
51 #include "special.h"
52 #include "initreq.h"
53 #include "path-util.h"
54 #include "strv.h"
55 #include "cgroup-show.h"
56 #include "cgroup-util.h"
57 #include "list.h"
58 #include "path-lookup.h"
59 #include "conf-parser.h"
60 #include "exit-status.h"
61 #include "build.h"
62 #include "unit-name.h"
63 #include "pager.h"
64 #include "spawn-ask-password-agent.h"
65 #include "spawn-polkit-agent.h"
66 #include "install.h"
67 #include "logs-show.h"
68 #include "socket-util.h"
69 #include "fileio.h"
70 #include "env-util.h"
71 #include "bus-util.h"
72 #include "bus-message.h"
73 #include "bus-error.h"
74 #include "bus-errors.h"
75
76 static char **arg_types = NULL;
77 static char **arg_states = NULL;
78 static char **arg_properties = NULL;
79 static bool arg_all = false;
80 static enum dependency {
81         DEPENDENCY_FORWARD,
82         DEPENDENCY_REVERSE,
83         DEPENDENCY_AFTER,
84         DEPENDENCY_BEFORE,
85         _DEPENDENCY_MAX
86 } arg_dependency = DEPENDENCY_FORWARD;
87 static const char *arg_job_mode = "replace";
88 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
89 static bool arg_no_block = false;
90 static bool arg_no_legend = false;
91 static bool arg_no_pager = false;
92 static bool arg_no_wtmp = false;
93 static bool arg_no_wall = false;
94 static bool arg_no_reload = false;
95 static bool arg_show_types = false;
96 static bool arg_ignore_inhibitors = false;
97 static bool arg_dry = false;
98 static bool arg_quiet = false;
99 static bool arg_full = false;
100 static bool arg_recursive = false;
101 static int arg_force = 0;
102 static bool arg_ask_password = true;
103 static bool arg_runtime = false;
104 static char **arg_wall = NULL;
105 static const char *arg_kill_who = NULL;
106 static int arg_signal = SIGTERM;
107 static const char *arg_root = NULL;
108 static usec_t arg_when = 0;
109 static enum action {
110         _ACTION_INVALID,
111         ACTION_SYSTEMCTL,
112         ACTION_HALT,
113         ACTION_POWEROFF,
114         ACTION_REBOOT,
115         ACTION_KEXEC,
116         ACTION_EXIT,
117         ACTION_SUSPEND,
118         ACTION_HIBERNATE,
119         ACTION_HYBRID_SLEEP,
120         ACTION_RUNLEVEL2,
121         ACTION_RUNLEVEL3,
122         ACTION_RUNLEVEL4,
123         ACTION_RUNLEVEL5,
124         ACTION_RESCUE,
125         ACTION_EMERGENCY,
126         ACTION_DEFAULT,
127         ACTION_RELOAD,
128         ACTION_REEXEC,
129         ACTION_RUNLEVEL,
130         ACTION_CANCEL_SHUTDOWN,
131         _ACTION_MAX
132 } arg_action = ACTION_SYSTEMCTL;
133 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
134 static char *arg_host = NULL;
135 static unsigned arg_lines = 10;
136 static OutputMode arg_output = OUTPUT_SHORT;
137 static bool arg_plain = false;
138
139 static const struct {
140         const char *verb;
141         const char *method;
142 } unit_actions[] = {
143         { "start",                 "StartUnit" },
144         { "stop",                  "StopUnit" },
145         { "condstop",              "StopUnit" },
146         { "reload",                "ReloadUnit" },
147         { "restart",               "RestartUnit" },
148         { "try-restart",           "TryRestartUnit" },
149         { "condrestart",           "TryRestartUnit" },
150         { "reload-or-restart",     "ReloadOrRestartUnit" },
151         { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
152         { "condreload",            "ReloadOrTryRestartUnit" },
153         { "force-reload",          "ReloadOrTryRestartUnit" }
154 };
155
156 static bool original_stdout_is_tty;
157
158 static int daemon_reload(sd_bus *bus, char **args);
159 static int halt_now(enum action a);
160 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet);
161
162 static char** strv_skip_first(char **strv) {
163         if (strv_length(strv) > 0)
164                 return strv + 1;
165         return NULL;
166 }
167
168 static void pager_open_if_enabled(void) {
169
170         if (arg_no_pager)
171                 return;
172
173         pager_open(false);
174 }
175
176 static void ask_password_agent_open_if_enabled(void) {
177
178         /* Open the password agent as a child process if necessary */
179
180         if (!arg_ask_password)
181                 return;
182
183         if (arg_scope != UNIT_FILE_SYSTEM)
184                 return;
185
186         if (arg_transport != BUS_TRANSPORT_LOCAL)
187                 return;
188
189         ask_password_agent_open();
190 }
191
192 #ifdef HAVE_LOGIND
193 static void polkit_agent_open_if_enabled(void) {
194
195         /* Open the polkit agent as a child process if necessary */
196
197         if (!arg_ask_password)
198                 return;
199
200         if (arg_scope != UNIT_FILE_SYSTEM)
201                 return;
202
203         if (arg_transport != BUS_TRANSPORT_LOCAL)
204                 return;
205
206         polkit_agent_open();
207 }
208 #endif
209
210 static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) {
211         assert(error);
212
213         if (!sd_bus_error_is_set(error))
214                 return r;
215
216         if (sd_bus_error_has_name(error, SD_BUS_ERROR_ACCESS_DENIED) ||
217             sd_bus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
218             sd_bus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
219             sd_bus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
220                 return EXIT_NOPERMISSION;
221
222         if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
223                 return EXIT_NOTINSTALLED;
224
225         if (sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
226             sd_bus_error_has_name(error, SD_BUS_ERROR_NOT_SUPPORTED))
227                 return EXIT_NOTIMPLEMENTED;
228
229         if (sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
230                 return EXIT_NOTCONFIGURED;
231
232         if (r != 0)
233                 return r;
234
235         return EXIT_FAILURE;
236 }
237
238 static void warn_wall(enum action a) {
239         static const char *table[_ACTION_MAX] = {
240                 [ACTION_HALT]            = "The system is going down for system halt NOW!",
241                 [ACTION_REBOOT]          = "The system is going down for reboot NOW!",
242                 [ACTION_POWEROFF]        = "The system is going down for power-off NOW!",
243                 [ACTION_KEXEC]           = "The system is going down for kexec reboot NOW!",
244                 [ACTION_RESCUE]          = "The system is going down to rescue mode NOW!",
245                 [ACTION_EMERGENCY]       = "The system is going down to emergency mode NOW!",
246                 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
247         };
248
249         if (arg_no_wall)
250                 return;
251
252         if (arg_wall) {
253                 _cleanup_free_ char *p;
254
255                 p = strv_join(arg_wall, " ");
256                 if (!p) {
257                         log_oom();
258                         return;
259                 }
260
261                 if (*p) {
262                         utmp_wall(p, NULL, NULL);
263                         return;
264                 }
265         }
266
267         if (!table[a])
268                 return;
269
270         utmp_wall(table[a], NULL, NULL);
271 }
272
273 static bool avoid_bus(void) {
274
275         if (running_in_chroot() > 0)
276                 return true;
277
278         if (sd_booted() <= 0)
279                 return true;
280
281         if (!isempty(arg_root))
282                 return true;
283
284         if (arg_scope == UNIT_FILE_GLOBAL)
285                 return true;
286
287         return false;
288 }
289
290 static int compare_unit_info(const void *a, const void *b) {
291         const UnitInfo *u = a, *v = b;
292         const char *d1, *d2;
293         int r;
294
295         /* First, order by machine */
296         if (!u->machine && v->machine)
297                 return -1;
298         if (u->machine && !v->machine)
299                 return 1;
300         if (u->machine && v->machine) {
301                 r = strcasecmp(u->machine, v->machine);
302                 if (r != 0)
303                         return r;
304         }
305
306         /* Second, order by unit type */
307         d1 = strrchr(u->id, '.');
308         d2 = strrchr(v->id, '.');
309         if (d1 && d2) {
310                 r = strcasecmp(d1, d2);
311                 if (r != 0)
312                         return r;
313         }
314
315         /* Third, order by name */
316         return strcasecmp(u->id, v->id);
317 }
318
319 static bool output_show_unit(const UnitInfo *u, char **patterns) {
320         const char *dot;
321
322         if (!strv_isempty(arg_states))
323                 return
324                         strv_contains(arg_states, u->load_state) ||
325                         strv_contains(arg_states, u->sub_state) ||
326                         strv_contains(arg_states, u->active_state);
327
328         if (!strv_isempty(patterns)) {
329                 char **pattern;
330
331                 STRV_FOREACH(pattern, patterns)
332                         if (fnmatch(*pattern, u->id, FNM_NOESCAPE) == 0)
333                                 return true;
334                 return false;
335         }
336
337         return (!arg_types || ((dot = strrchr(u->id, '.')) &&
338                                strv_find(arg_types, dot+1))) &&
339                 (arg_all || !(streq(u->active_state, "inactive")
340                               || u->following[0]) || u->job_id > 0);
341 }
342
343 static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
344         unsigned circle_len = 0, id_len, max_id_len, load_len, active_len, sub_len, job_len, desc_len;
345         const UnitInfo *u;
346         unsigned n_shown = 0;
347         int job_count = 0;
348
349         max_id_len = strlen("UNIT");
350         load_len = strlen("LOAD");
351         active_len = strlen("ACTIVE");
352         sub_len = strlen("SUB");
353         job_len = strlen("JOB");
354         desc_len = 0;
355
356         for (u = unit_infos; u < unit_infos + c; u++) {
357                 max_id_len = MAX(max_id_len, strlen(u->id) + (u->machine ? strlen(u->machine)+1 : 0));
358                 load_len = MAX(load_len, strlen(u->load_state));
359                 active_len = MAX(active_len, strlen(u->active_state));
360                 sub_len = MAX(sub_len, strlen(u->sub_state));
361
362                 if (u->job_id != 0) {
363                         job_len = MAX(job_len, strlen(u->job_type));
364                         job_count++;
365                 }
366
367                 if (!arg_no_legend &&
368                     (streq(u->active_state, "failed") ||
369                      STR_IN_SET(u->load_state, "error", "not-found", "masked")))
370                         circle_len = 2;
371         }
372
373         if (!arg_full && original_stdout_is_tty) {
374                 unsigned basic_len;
375
376                 id_len = MIN(max_id_len, 25u);
377                 basic_len = circle_len + 5 + id_len + 5 + active_len + sub_len;
378
379                 if (job_count)
380                         basic_len += job_len + 1;
381
382                 if (basic_len < (unsigned) columns()) {
383                         unsigned extra_len, incr;
384                         extra_len = columns() - basic_len;
385
386                         /* Either UNIT already got 25, or is fully satisfied.
387                          * Grant up to 25 to DESC now. */
388                         incr = MIN(extra_len, 25u);
389                         desc_len += incr;
390                         extra_len -= incr;
391
392                         /* split the remaining space between UNIT and DESC,
393                          * but do not give UNIT more than it needs. */
394                         if (extra_len > 0) {
395                                 incr = MIN(extra_len / 2, max_id_len - id_len);
396                                 id_len += incr;
397                                 desc_len += extra_len - incr;
398                         }
399                 }
400         } else
401                 id_len = max_id_len;
402
403         for (u = unit_infos; u < unit_infos + c; u++) {
404                 _cleanup_free_ char *e = NULL, *j = NULL;
405                 const char *on_loaded = "", *off_loaded = "";
406                 const char *on_active = "", *off_active = "";
407                 const char *on_circle = "", *off_circle = "";
408                 const char *id;
409                 bool circle = false;
410
411                 if (!n_shown && !arg_no_legend) {
412
413                         if (circle_len > 0)
414                                 fputs("  ", stdout);
415
416                         printf("%-*s %-*s %-*s %-*s ",
417                                id_len, "UNIT",
418                                load_len, "LOAD",
419                                active_len, "ACTIVE",
420                                sub_len, "SUB");
421
422                         if (job_count)
423                                 printf("%-*s ", job_len, "JOB");
424
425                         if (!arg_full && arg_no_pager)
426                                 printf("%.*s\n", desc_len, "DESCRIPTION");
427                         else
428                                 printf("%s\n", "DESCRIPTION");
429                 }
430
431                 n_shown++;
432
433                 if (STR_IN_SET(u->load_state, "error", "not-found", "masked")) {
434                         on_loaded = ansi_highlight_red();
435                         on_circle = ansi_highlight_yellow();
436                         off_loaded = off_circle = ansi_highlight_off();
437                         circle = true;
438                 }
439
440                 if (streq(u->active_state, "failed")) {
441                         on_circle = on_active = ansi_highlight_red();
442                         off_circle = off_active = ansi_highlight_off();
443                         circle = true;
444                 }
445
446                 if (u->machine) {
447                         j = strjoin(u->machine, ":", u->id, NULL);
448                         if (!j)
449                                 return log_oom();
450
451                         id = j;
452                 } else
453                         id = u->id;
454
455                 if (arg_full) {
456                         e = ellipsize(id, id_len, 33);
457                         if (!e)
458                                 return log_oom();
459
460                         id = e;
461                 }
462
463                 if (circle_len > 0)
464                         printf("%s%s%s", on_circle, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : "  ", off_circle);
465
466                 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
467                        on_active, id_len, id, off_active,
468                        on_loaded, load_len, u->load_state, off_loaded,
469                        on_active, active_len, u->active_state,
470                        sub_len, u->sub_state, off_active,
471                        job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
472
473                 if (desc_len > 0)
474                         printf("%.*s\n", desc_len, u->description);
475                 else
476                         printf("%s\n", u->description);
477         }
478
479         if (!arg_no_legend) {
480                 const char *on, *off;
481
482                 if (n_shown) {
483                         puts("\n"
484                              "LOAD   = Reflects whether the unit definition was properly loaded.\n"
485                              "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
486                              "SUB    = The low-level unit activation state, values depend on unit type.");
487                         puts(job_count ? "JOB    = Pending job for the unit.\n" : "");
488                         on = ansi_highlight();
489                         off = ansi_highlight_off();
490                 } else {
491                         on = ansi_highlight_red();
492                         off = ansi_highlight_off();
493                 }
494
495                 if (arg_all)
496                         printf("%s%u loaded units listed.%s\n"
497                                "To show all installed unit files use 'systemctl list-unit-files'.\n",
498                                on, n_shown, off);
499                 else
500                         printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
501                                "To show all installed unit files use 'systemctl list-unit-files'.\n",
502                                on, n_shown, off);
503         }
504
505         return 0;
506 }
507
508 static int get_unit_list(
509                 sd_bus *bus,
510                 const char *machine,
511                 char **patterns,
512                 UnitInfo **unit_infos,
513                 int c,
514                 sd_bus_message **_reply) {
515
516         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
517         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
518         size_t size = c;
519         int r;
520         UnitInfo u;
521
522         assert(bus);
523         assert(unit_infos);
524         assert(_reply);
525
526         r = sd_bus_call_method(
527                         bus,
528                         "org.freedesktop.systemd1",
529                         "/org/freedesktop/systemd1",
530                         "org.freedesktop.systemd1.Manager",
531                         "ListUnits",
532                         &error,
533                         &reply,
534                         NULL);
535         if (r < 0) {
536                 log_error("Failed to list units: %s", bus_error_message(&error, r));
537                 return r;
538         }
539
540         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
541         if (r < 0)
542                 return bus_log_parse_error(r);
543
544         while ((r = bus_parse_unit_info(reply, &u)) > 0) {
545                 u.machine = machine;
546
547                 if (!output_show_unit(&u, patterns))
548                         continue;
549
550                 if (!GREEDY_REALLOC(*unit_infos, size, c+1))
551                         return log_oom();
552
553                 (*unit_infos)[c++] = u;
554         }
555         if (r < 0)
556                 return bus_log_parse_error(r);
557
558         r = sd_bus_message_exit_container(reply);
559         if (r < 0)
560                 return bus_log_parse_error(r);
561
562         *_reply = reply;
563         reply = NULL;
564
565         return c;
566 }
567
568 static void message_set_freep(Set **set) {
569         sd_bus_message *m;
570
571         while ((m = set_steal_first(*set)))
572                 sd_bus_message_unref(m);
573
574         set_free(*set);
575 }
576
577 static int get_unit_list_recursive(
578                 sd_bus *bus,
579                 char **patterns,
580                 UnitInfo **_unit_infos,
581                 Set **_replies,
582                 char ***_machines) {
583
584         _cleanup_free_ UnitInfo *unit_infos = NULL;
585         _cleanup_(message_set_freep) Set *replies;
586         sd_bus_message *reply;
587         int c, r;
588
589         assert(bus);
590         assert(_replies);
591         assert(_unit_infos);
592         assert(_machines);
593
594         replies = set_new(NULL, NULL);
595         if (!replies)
596                 return log_oom();
597
598         c = get_unit_list(bus, NULL, patterns, &unit_infos, 0, &reply);
599         if (c < 0)
600                 return c;
601
602         r = set_put(replies, reply);
603         if (r < 0) {
604                 sd_bus_message_unref(reply);
605                 return r;
606         }
607
608         if (arg_recursive) {
609                 _cleanup_strv_free_ char **machines = NULL;
610                 char **i;
611
612                 r = sd_get_machine_names(&machines);
613                 if (r < 0)
614                         return r;
615
616                 STRV_FOREACH(i, machines) {
617                         _cleanup_bus_unref_ sd_bus *container = NULL;
618                         int k;
619
620                         r = sd_bus_open_system_container(&container, *i);
621                         if (r < 0) {
622                                 log_error("Failed to connect to container %s: %s", *i, strerror(-r));
623                                 continue;
624                         }
625
626                         k = get_unit_list(container, *i, patterns, &unit_infos, c, &reply);
627                         if (k < 0)
628                                 return k;
629
630                         c = k;
631
632                         r = set_put(replies, reply);
633                         if (r < 0) {
634                                 sd_bus_message_unref(reply);
635                                 return r;
636                         }
637                 }
638
639                 *_machines = machines;
640                 machines = NULL;
641         } else
642                 *_machines = NULL;
643
644         *_unit_infos = unit_infos;
645         unit_infos = NULL;
646
647         *_replies = replies;
648         replies = NULL;
649
650         return c;
651 }
652
653 static int list_units(sd_bus *bus, char **args) {
654         _cleanup_free_ UnitInfo *unit_infos = NULL;
655         _cleanup_(message_set_freep) Set *replies = NULL;
656         _cleanup_strv_free_ char **machines = NULL;
657         int r;
658
659         pager_open_if_enabled();
660
661         r = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
662         if (r < 0)
663                 return r;
664
665         qsort_safe(unit_infos, r, sizeof(UnitInfo), compare_unit_info);
666         return output_units_list(unit_infos, r);
667 }
668
669 static int get_triggered_units(
670                 sd_bus *bus,
671                 const char* path,
672                 char*** ret) {
673
674         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
675         int r;
676
677         r = sd_bus_get_property_strv(
678                         bus,
679                         "org.freedesktop.systemd1",
680                         path,
681                         "org.freedesktop.systemd1.Unit",
682                         "Triggers",
683                         &error,
684                         ret);
685
686         if (r < 0)
687                 log_error("Failed to determine triggers: %s", bus_error_message(&error, r));
688
689         return 0;
690 }
691
692 static int get_listening(
693                 sd_bus *bus,
694                 const char* unit_path,
695                 char*** listening) {
696
697         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
698         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
699         const char *type, *path;
700         int r, n = 0;
701
702         r = sd_bus_get_property(
703                         bus,
704                         "org.freedesktop.systemd1",
705                         unit_path,
706                         "org.freedesktop.systemd1.Socket",
707                         "Listen",
708                         &error,
709                         &reply,
710                         "a(ss)");
711         if (r < 0) {
712                 log_error("Failed to get list of listening sockets: %s", bus_error_message(&error, r));
713                 return r;
714         }
715
716         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
717         if (r < 0)
718                 return bus_log_parse_error(r);
719
720         while ((r = sd_bus_message_read(reply, "(ss)", &type, &path)) > 0) {
721
722                 r = strv_extend(listening, type);
723                 if (r < 0)
724                         return log_oom();
725
726                 r = strv_extend(listening, path);
727                 if (r < 0)
728                         return log_oom();
729
730                 n++;
731         }
732         if (r < 0)
733                 return bus_log_parse_error(r);
734
735         r = sd_bus_message_exit_container(reply);
736         if (r < 0)
737                 return bus_log_parse_error(r);
738
739         return n;
740 }
741
742 struct socket_info {
743         const char *machine;
744         const char* id;
745
746         char* type;
747         char* path;
748
749         /* Note: triggered is a list here, although it almost certainly
750          * will always be one unit. Nevertheless, dbus API allows for multiple
751          * values, so let's follow that.*/
752         char** triggered;
753
754         /* The strv above is shared. free is set only in the first one. */
755         bool own_triggered;
756 };
757
758 static int socket_info_compare(const struct socket_info *a, const struct socket_info *b) {
759         int o;
760
761         assert(a);
762         assert(b);
763
764         if (!a->machine && b->machine)
765                 return -1;
766         if (a->machine && !b->machine)
767                 return 1;
768         if (a->machine && b->machine) {
769                 o = strcasecmp(a->machine, b->machine);
770                 if (o != 0)
771                         return o;
772         }
773
774         o = strcmp(a->path, b->path);
775         if (o == 0)
776                 o = strcmp(a->type, b->type);
777
778         return o;
779 }
780
781 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
782         struct socket_info *s;
783         unsigned pathlen = strlen("LISTEN"),
784                 typelen = strlen("TYPE") * arg_show_types,
785                 socklen = strlen("UNIT"),
786                 servlen = strlen("ACTIVATES");
787         const char *on, *off;
788
789         for (s = socket_infos; s < socket_infos + cs; s++) {
790                 unsigned tmp = 0;
791                 char **a;
792
793                 socklen = MAX(socklen, strlen(s->id));
794                 if (arg_show_types)
795                         typelen = MAX(typelen, strlen(s->type));
796                 pathlen = MAX(pathlen, strlen(s->path) + (s->machine ? strlen(s->machine)+1 : 0));
797
798                 STRV_FOREACH(a, s->triggered)
799                         tmp += strlen(*a) + 2*(a != s->triggered);
800                 servlen = MAX(servlen, tmp);
801         }
802
803         if (cs) {
804                 if (!arg_no_legend)
805                         printf("%-*s %-*.*s%-*s %s\n",
806                                pathlen, "LISTEN",
807                                typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
808                                socklen, "UNIT",
809                                "ACTIVATES");
810
811                 for (s = socket_infos; s < socket_infos + cs; s++) {
812                         _cleanup_free_ char *j = NULL;
813                         const char *path;
814                         char **a;
815
816                         if (s->machine) {
817                                 j = strjoin(s->machine, ":", s->path, NULL);
818                                 if (!j)
819                                         return log_oom();
820                                 path = j;
821                         } else
822                                 path = s->path;
823
824                         if (arg_show_types)
825                                 printf("%-*s %-*s %-*s",
826                                        pathlen, path, typelen, s->type, socklen, s->id);
827                         else
828                                 printf("%-*s %-*s",
829                                        pathlen, path, socklen, s->id);
830                         STRV_FOREACH(a, s->triggered)
831                                 printf("%s %s",
832                                        a == s->triggered ? "" : ",", *a);
833                         printf("\n");
834                 }
835
836                 on = ansi_highlight();
837                 off = ansi_highlight_off();
838                 if (!arg_no_legend)
839                         printf("\n");
840         } else {
841                 on = ansi_highlight_red();
842                 off = ansi_highlight_off();
843         }
844
845         if (!arg_no_legend) {
846                 printf("%s%u sockets listed.%s\n", on, cs, off);
847                 if (!arg_all)
848                         printf("Pass --all to see loaded but inactive sockets, too.\n");
849         }
850
851         return 0;
852 }
853
854 static int list_sockets(sd_bus *bus, char **args) {
855         _cleanup_(message_set_freep) Set *replies = NULL;
856         _cleanup_strv_free_ char **machines = NULL;
857         _cleanup_free_ UnitInfo *unit_infos = NULL;
858         _cleanup_free_ struct socket_info *socket_infos = NULL;
859         const UnitInfo *u;
860         struct socket_info *s;
861         unsigned cs = 0;
862         size_t size = 0;
863         int r = 0, n;
864
865         pager_open_if_enabled();
866
867         n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
868         if (n < 0)
869                 return n;
870
871         for (u = unit_infos; u < unit_infos + n; u++) {
872                 _cleanup_strv_free_ char **listening = NULL, **triggered = NULL;
873                 int i, c;
874
875                 if (!endswith(u->id, ".socket"))
876                         continue;
877
878                 r = get_triggered_units(bus, u->unit_path, &triggered);
879                 if (r < 0)
880                         goto cleanup;
881
882                 c = get_listening(bus, u->unit_path, &listening);
883                 if (c < 0) {
884                         r = c;
885                         goto cleanup;
886                 }
887
888                 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
889                         r = log_oom();
890                         goto cleanup;
891                 }
892
893                 for (i = 0; i < c; i++)
894                         socket_infos[cs + i] = (struct socket_info) {
895                                 .machine = u->machine,
896                                 .id = u->id,
897                                 .type = listening[i*2],
898                                 .path = listening[i*2 + 1],
899                                 .triggered = triggered,
900                                 .own_triggered = i==0,
901                         };
902
903                 /* from this point on we will cleanup those socket_infos */
904                 cs += c;
905                 free(listening);
906                 listening = triggered = NULL; /* avoid cleanup */
907         }
908
909         qsort_safe(socket_infos, cs, sizeof(struct socket_info),
910                    (__compar_fn_t) socket_info_compare);
911
912         output_sockets_list(socket_infos, cs);
913
914  cleanup:
915         assert(cs == 0 || socket_infos);
916         for (s = socket_infos; s < socket_infos + cs; s++) {
917                 free(s->type);
918                 free(s->path);
919                 if (s->own_triggered)
920                         strv_free(s->triggered);
921         }
922
923         return r;
924 }
925
926 static int get_next_elapse(
927                 sd_bus *bus,
928                 const char *path,
929                 dual_timestamp *next) {
930
931         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
932         dual_timestamp t;
933         int r;
934
935         assert(bus);
936         assert(path);
937         assert(next);
938
939         r = sd_bus_get_property_trivial(
940                         bus,
941                         "org.freedesktop.systemd1",
942                         path,
943                         "org.freedesktop.systemd1.Timer",
944                         "NextElapseUSecMonotonic",
945                         &error,
946                         't',
947                         &t.monotonic);
948         if (r < 0) {
949                 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
950                 return r;
951         }
952
953         r = sd_bus_get_property_trivial(
954                         bus,
955                         "org.freedesktop.systemd1",
956                         path,
957                         "org.freedesktop.systemd1.Timer",
958                         "NextElapseUSecRealtime",
959                         &error,
960                         't',
961                         &t.realtime);
962         if (r < 0) {
963                 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
964                 return r;
965         }
966
967         *next = t;
968         return 0;
969 }
970
971 static int get_last_trigger(
972                 sd_bus *bus,
973                 const char *path,
974                 usec_t *last) {
975
976         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
977         int r;
978
979         assert(bus);
980         assert(path);
981         assert(last);
982
983         r = sd_bus_get_property_trivial(
984                         bus,
985                         "org.freedesktop.systemd1",
986                         path,
987                         "org.freedesktop.systemd1.Timer",
988                         "LastTriggerUSec",
989                         &error,
990                         't',
991                         last);
992         if (r < 0) {
993                 log_error("Failed to get last trigger time: %s", bus_error_message(&error, r));
994                 return r;
995         }
996
997         return 0;
998 }
999
1000 struct timer_info {
1001         const char* machine;
1002         const char* id;
1003         usec_t next_elapse;
1004         usec_t last_trigger;
1005         char** triggered;
1006 };
1007
1008 static int timer_info_compare(const struct timer_info *a, const struct timer_info *b) {
1009         int o;
1010
1011         assert(a);
1012         assert(b);
1013
1014         if (!a->machine && b->machine)
1015                 return -1;
1016         if (a->machine && !b->machine)
1017                 return 1;
1018         if (a->machine && b->machine) {
1019                 o = strcasecmp(a->machine, b->machine);
1020                 if (o != 0)
1021                         return o;
1022         }
1023
1024         if (a->next_elapse < b->next_elapse)
1025                 return -1;
1026         if (a->next_elapse > b->next_elapse)
1027                 return 1;
1028
1029         return strcmp(a->id, b->id);
1030 }
1031
1032 static int output_timers_list(struct timer_info *timer_infos, unsigned n) {
1033         struct timer_info *t;
1034         unsigned
1035                 nextlen = strlen("NEXT"),
1036                 leftlen = strlen("LEFT"),
1037                 lastlen = strlen("LAST"),
1038                 passedlen = strlen("PASSED"),
1039                 unitlen = strlen("UNIT"),
1040                 activatelen = strlen("ACTIVATES");
1041
1042         const char *on, *off;
1043
1044         assert(timer_infos || n == 0);
1045
1046         for (t = timer_infos; t < timer_infos + n; t++) {
1047                 unsigned ul = 0;
1048                 char **a;
1049
1050                 if (t->next_elapse > 0) {
1051                         char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1052
1053                         format_timestamp(tstamp, sizeof(tstamp), t->next_elapse);
1054                         nextlen = MAX(nextlen, strlen(tstamp) + 1);
1055
1056                         format_timestamp_relative(trel, sizeof(trel), t->next_elapse);
1057                         leftlen = MAX(leftlen, strlen(trel));
1058                 }
1059
1060                 if (t->last_trigger > 0) {
1061                         char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1062
1063                         format_timestamp(tstamp, sizeof(tstamp), t->last_trigger);
1064                         lastlen = MAX(lastlen, strlen(tstamp) + 1);
1065
1066                         format_timestamp_relative(trel, sizeof(trel), t->last_trigger);
1067                         passedlen = MAX(passedlen, strlen(trel));
1068                 }
1069
1070                 unitlen = MAX(unitlen, strlen(t->id) + (t->machine ? strlen(t->machine)+1 : 0));
1071
1072                 STRV_FOREACH(a, t->triggered)
1073                         ul += strlen(*a) + 2*(a != t->triggered);
1074
1075                 activatelen = MAX(activatelen, ul);
1076         }
1077
1078         if (n > 0) {
1079                 if (!arg_no_legend)
1080                         printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1081                                nextlen,   "NEXT",
1082                                leftlen,   "LEFT",
1083                                lastlen,   "LAST",
1084                                passedlen, "PASSED",
1085                                unitlen,   "UNIT",
1086                                           "ACTIVATES");
1087
1088                 for (t = timer_infos; t < timer_infos + n; t++) {
1089                         _cleanup_free_ char *j = NULL;
1090                         const char *unit;
1091                         char tstamp1[FORMAT_TIMESTAMP_MAX] = "n/a", trel1[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1092                         char tstamp2[FORMAT_TIMESTAMP_MAX] = "n/a", trel2[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1093                         char **a;
1094
1095                         format_timestamp(tstamp1, sizeof(tstamp1), t->next_elapse);
1096                         format_timestamp_relative(trel1, sizeof(trel1), t->next_elapse);
1097
1098                         format_timestamp(tstamp2, sizeof(tstamp2), t->last_trigger);
1099                         format_timestamp_relative(trel2, sizeof(trel2), t->last_trigger);
1100
1101                         if (t->machine) {
1102                                 j = strjoin(t->machine, ":", t->id, NULL);
1103                                 if (!j)
1104                                         return log_oom();
1105                                 unit = j;
1106                         } else
1107                                 unit = t->id;
1108
1109                         printf("%-*s %-*s %-*s %-*s %-*s",
1110                                nextlen, tstamp1, leftlen, trel1, lastlen, tstamp2, passedlen, trel2, unitlen, unit);
1111
1112                         STRV_FOREACH(a, t->triggered)
1113                                 printf("%s %s",
1114                                        a == t->triggered ? "" : ",", *a);
1115                         printf("\n");
1116                 }
1117
1118                 on = ansi_highlight();
1119                 off = ansi_highlight_off();
1120                 if (!arg_no_legend)
1121                         printf("\n");
1122         } else {
1123                 on = ansi_highlight_red();
1124                 off = ansi_highlight_off();
1125         }
1126
1127         if (!arg_no_legend) {
1128                 printf("%s%u timers listed.%s\n", on, n, off);
1129                 if (!arg_all)
1130                         printf("Pass --all to see loaded but inactive timers, too.\n");
1131         }
1132
1133         return 0;
1134 }
1135
1136 static usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next) {
1137         usec_t next_elapse;
1138
1139         assert(nw);
1140         assert(next);
1141
1142         if (next->monotonic != (usec_t) -1 && next->monotonic > 0) {
1143                 usec_t converted;
1144
1145                 if (next->monotonic > nw->monotonic)
1146                         converted = nw->realtime + (next->monotonic - nw->monotonic);
1147                 else
1148                         converted = nw->realtime - (nw->monotonic - next->monotonic);
1149
1150                 if (next->realtime != (usec_t) -1 && next->realtime > 0)
1151                         next_elapse = MIN(converted, next->realtime);
1152                 else
1153                         next_elapse = converted;
1154
1155         } else
1156                 next_elapse = next->realtime;
1157
1158         return next_elapse;
1159 }
1160
1161 static int list_timers(sd_bus *bus, char **args) {
1162         _cleanup_(message_set_freep) Set *replies = NULL;
1163         _cleanup_strv_free_ char **machines = NULL;
1164         _cleanup_free_ struct timer_info *timer_infos = NULL;
1165         _cleanup_free_ UnitInfo *unit_infos = NULL;
1166         struct timer_info *t;
1167         const UnitInfo *u;
1168         size_t size = 0;
1169         int n, c = 0;
1170         dual_timestamp nw;
1171         int r = 0;
1172
1173         pager_open_if_enabled();
1174
1175         n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
1176         if (n < 0)
1177                 return n;
1178
1179         dual_timestamp_get(&nw);
1180
1181         for (u = unit_infos; u < unit_infos + n; u++) {
1182                 _cleanup_strv_free_ char **triggered = NULL;
1183                 dual_timestamp next = {};
1184                 usec_t m, last = 0;
1185
1186                 if (!endswith(u->id, ".timer"))
1187                         continue;
1188
1189                 r = get_triggered_units(bus, u->unit_path, &triggered);
1190                 if (r < 0)
1191                         goto cleanup;
1192
1193                 r = get_next_elapse(bus, u->unit_path, &next);
1194                 if (r < 0)
1195                         goto cleanup;
1196
1197                 get_last_trigger(bus, u->unit_path, &last);
1198
1199                 if (!GREEDY_REALLOC(timer_infos, size, c+1)) {
1200                         r = log_oom();
1201                         goto cleanup;
1202                 }
1203
1204                 m = calc_next_elapse(&nw, &next);
1205
1206                 timer_infos[c++] = (struct timer_info) {
1207                         .machine = u->machine,
1208                         .id = u->id,
1209                         .next_elapse = m,
1210                         .last_trigger = last,
1211                         .triggered = triggered,
1212                 };
1213
1214                 triggered = NULL; /* avoid cleanup */
1215         }
1216
1217         qsort_safe(timer_infos, c, sizeof(struct timer_info),
1218                    (__compar_fn_t) timer_info_compare);
1219
1220         output_timers_list(timer_infos, c);
1221
1222  cleanup:
1223         for (t = timer_infos; t < timer_infos + c; t++)
1224                 strv_free(t->triggered);
1225
1226         return r;
1227 }
1228
1229 static int compare_unit_file_list(const void *a, const void *b) {
1230         const char *d1, *d2;
1231         const UnitFileList *u = a, *v = b;
1232
1233         d1 = strrchr(u->path, '.');
1234         d2 = strrchr(v->path, '.');
1235
1236         if (d1 && d2) {
1237                 int r;
1238
1239                 r = strcasecmp(d1, d2);
1240                 if (r != 0)
1241                         return r;
1242         }
1243
1244         return strcasecmp(basename(u->path), basename(v->path));
1245 }
1246
1247 static bool output_show_unit_file(const UnitFileList *u, char **patterns) {
1248         const char *dot;
1249
1250         if (!strv_isempty(patterns)) {
1251                 char **pattern;
1252
1253                 STRV_FOREACH(pattern, patterns)
1254                         if (fnmatch(*pattern, basename(u->path), FNM_NOESCAPE) == 0)
1255                                 return true;
1256                 return false;
1257         }
1258
1259         return !arg_types || ((dot = strrchr(u->path, '.')) && strv_find(arg_types, dot+1));
1260 }
1261
1262 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
1263         unsigned max_id_len, id_cols, state_cols;
1264         const UnitFileList *u;
1265
1266         max_id_len = strlen("UNIT FILE");
1267         state_cols = strlen("STATE");
1268
1269         for (u = units; u < units + c; u++) {
1270                 max_id_len = MAX(max_id_len, strlen(basename(u->path)));
1271                 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
1272         }
1273
1274         if (!arg_full) {
1275                 unsigned basic_cols;
1276
1277                 id_cols = MIN(max_id_len, 25u);
1278                 basic_cols = 1 + id_cols + state_cols;
1279                 if (basic_cols < (unsigned) columns())
1280                         id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
1281         } else
1282                 id_cols = max_id_len;
1283
1284         if (!arg_no_legend)
1285                 printf("%-*s %-*s\n",
1286                        id_cols, "UNIT FILE",
1287                        state_cols, "STATE");
1288
1289         for (u = units; u < units + c; u++) {
1290                 _cleanup_free_ char *e = NULL;
1291                 const char *on, *off;
1292                 const char *id;
1293
1294                 if (u->state == UNIT_FILE_MASKED ||
1295                     u->state == UNIT_FILE_MASKED_RUNTIME ||
1296                     u->state == UNIT_FILE_DISABLED ||
1297                     u->state == UNIT_FILE_INVALID) {
1298                         on  = ansi_highlight_red();
1299                         off = ansi_highlight_off();
1300                 } else if (u->state == UNIT_FILE_ENABLED) {
1301                         on  = ansi_highlight_green();
1302                         off = ansi_highlight_off();
1303                 } else
1304                         on = off = "";
1305
1306                 id = basename(u->path);
1307
1308                 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
1309
1310                 printf("%-*s %s%-*s%s\n",
1311                        id_cols, e ? e : id,
1312                        on, state_cols, unit_file_state_to_string(u->state), off);
1313         }
1314
1315         if (!arg_no_legend)
1316                 printf("\n%u unit files listed.\n", c);
1317 }
1318
1319 static int list_unit_files(sd_bus *bus, char **args) {
1320         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1321         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1322         _cleanup_free_ UnitFileList *units = NULL;
1323         UnitFileList *unit;
1324         size_t size = 0;
1325         unsigned c = 0;
1326         const char *state;
1327         char *path;
1328         int r;
1329
1330         pager_open_if_enabled();
1331
1332         if (avoid_bus()) {
1333                 Hashmap *h;
1334                 UnitFileList *u;
1335                 Iterator i;
1336                 unsigned n_units;
1337
1338                 h = hashmap_new(string_hash_func, string_compare_func);
1339                 if (!h)
1340                         return log_oom();
1341
1342                 r = unit_file_get_list(arg_scope, arg_root, h);
1343                 if (r < 0) {
1344                         unit_file_list_free(h);
1345                         log_error("Failed to get unit file list: %s", strerror(-r));
1346                         return r;
1347                 }
1348
1349                 n_units = hashmap_size(h);
1350                 units = new(UnitFileList, n_units);
1351                 if (!units) {
1352                         unit_file_list_free(h);
1353                         return log_oom();
1354                 }
1355
1356                 HASHMAP_FOREACH(u, h, i) {
1357                         if (!output_show_unit_file(u, strv_skip_first(args)))
1358                                 continue;
1359
1360                         units[c++] = *u;
1361                         free(u);
1362                 }
1363
1364                 assert(c <= n_units);
1365                 hashmap_free(h);
1366         } else {
1367                 r = sd_bus_call_method(
1368                                 bus,
1369                                 "org.freedesktop.systemd1",
1370                                 "/org/freedesktop/systemd1",
1371                                 "org.freedesktop.systemd1.Manager",
1372                                 "ListUnitFiles",
1373                                 &error,
1374                                 &reply,
1375                                 NULL);
1376                 if (r < 0) {
1377                         log_error("Failed to list unit files: %s", bus_error_message(&error, r));
1378                         return r;
1379                 }
1380
1381                 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
1382                 if (r < 0)
1383                         return bus_log_parse_error(r);
1384
1385                 while ((r = sd_bus_message_read(reply, "(ss)", &path, &state)) > 0) {
1386
1387                         if (!GREEDY_REALLOC(units, size, c + 1))
1388                                 return log_oom();
1389
1390                         units[c] = (struct UnitFileList) {
1391                                 path,
1392                                 unit_file_state_from_string(state)
1393                         };
1394
1395                         if (output_show_unit_file(&units[c], strv_skip_first(args)))
1396                                 c ++;
1397
1398                 }
1399                 if (r < 0)
1400                         return bus_log_parse_error(r);
1401
1402                 r = sd_bus_message_exit_container(reply);
1403                 if (r < 0)
1404                         return bus_log_parse_error(r);
1405         }
1406
1407         if (c > 0) {
1408                 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
1409                 output_unit_file_list(units, c);
1410         }
1411
1412         if (avoid_bus())
1413                 for (unit = units; unit < units + c; unit++)
1414                         free(unit->path);
1415
1416         return 0;
1417 }
1418
1419 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
1420         _cleanup_free_ char *n = NULL;
1421         size_t max_len = MAX(columns(),20u);
1422         size_t len = 0;
1423         int i;
1424
1425         if (!arg_plain) {
1426
1427                 for (i = level - 1; i >= 0; i--) {
1428                         len += 2;
1429                         if (len > max_len - 3 && !arg_full) {
1430                                 printf("%s...\n",max_len % 2 ? "" : " ");
1431                                 return 0;
1432                         }
1433                         printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERTICAL : DRAW_TREE_SPACE));
1434                 }
1435                 len += 2;
1436
1437                 if (len > max_len - 3 && !arg_full) {
1438                         printf("%s...\n",max_len % 2 ? "" : " ");
1439                         return 0;
1440                 }
1441
1442                 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
1443         }
1444
1445         if (arg_full){
1446                 printf("%s\n", name);
1447                 return 0;
1448         }
1449
1450         n = ellipsize(name, max_len-len, 100);
1451         if (!n)
1452                 return log_oom();
1453
1454         printf("%s\n", n);
1455         return 0;
1456 }
1457
1458 static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) {
1459
1460         static const char *dependencies[_DEPENDENCY_MAX] = {
1461                 [DEPENDENCY_FORWARD] = "Requires\0"
1462                                        "RequiresOverridable\0"
1463                                        "Requisite\0"
1464                                        "RequisiteOverridable\0"
1465                                        "Wants\0",
1466                 [DEPENDENCY_REVERSE] = "RequiredBy\0"
1467                                        "RequiredByOverridable\0"
1468                                        "WantedBy\0"
1469                                        "PartOf\0",
1470                 [DEPENDENCY_AFTER]   = "After\0",
1471                 [DEPENDENCY_BEFORE]  = "Before\0",
1472         };
1473
1474         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1475         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1476         _cleanup_strv_free_ char **ret = NULL;
1477         _cleanup_free_ char *path = NULL;
1478         int r;
1479
1480         assert(bus);
1481         assert(name);
1482         assert(deps);
1483         assert_cc(ELEMENTSOF(dependencies) == _DEPENDENCY_MAX);
1484
1485         path = unit_dbus_path_from_name(name);
1486         if (!path)
1487                 return log_oom();
1488
1489         r = sd_bus_call_method(
1490                         bus,
1491                         "org.freedesktop.systemd1",
1492                         path,
1493                         "org.freedesktop.DBus.Properties",
1494                         "GetAll",
1495                         &error,
1496                         &reply,
1497                         "s", "org.freedesktop.systemd1.Unit");
1498         if (r < 0) {
1499                 log_error("Failed to get properties of %s: %s", name, bus_error_message(&error, r));
1500                 return r;
1501         }
1502
1503         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
1504         if (r < 0)
1505                 return bus_log_parse_error(r);
1506
1507         while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1508                 const char *prop;
1509
1510                 r = sd_bus_message_read(reply, "s", &prop);
1511                 if (r < 0)
1512                         return bus_log_parse_error(r);
1513
1514                 if (!nulstr_contains(dependencies[arg_dependency], prop)) {
1515                         r = sd_bus_message_skip(reply, "v");
1516                         if (r < 0)
1517                                 return bus_log_parse_error(r);
1518                 } else {
1519
1520                         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, "as");
1521                         if (r < 0)
1522                                 return bus_log_parse_error(r);
1523
1524                         r = bus_message_read_strv_extend(reply, &ret);
1525                         if (r < 0)
1526                                 return bus_log_parse_error(r);
1527
1528                         r = sd_bus_message_exit_container(reply);
1529                         if (r < 0)
1530                                 return bus_log_parse_error(r);
1531                 }
1532
1533                 r = sd_bus_message_exit_container(reply);
1534                 if (r < 0)
1535                         return bus_log_parse_error(r);
1536
1537         }
1538         if (r < 0)
1539                 return bus_log_parse_error(r);
1540
1541         r = sd_bus_message_exit_container(reply);
1542         if (r < 0)
1543                 return bus_log_parse_error(r);
1544
1545         *deps = ret;
1546         ret = NULL;
1547
1548         return 0;
1549 }
1550
1551 static int list_dependencies_compare(const void *_a, const void *_b) {
1552         const char **a = (const char**) _a, **b = (const char**) _b;
1553
1554         if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1555                 return 1;
1556         if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1557                 return -1;
1558
1559         return strcasecmp(*a, *b);
1560 }
1561
1562 static int list_dependencies_one(
1563                 sd_bus *bus,
1564                 const char *name,
1565                 int level,
1566                 char ***units,
1567                 unsigned int branches) {
1568
1569         _cleanup_strv_free_ char **deps = NULL;
1570         char **c;
1571         int r = 0;
1572
1573         assert(bus);
1574         assert(name);
1575         assert(units);
1576
1577         r = strv_extend(units, name);
1578         if (r < 0)
1579                 return log_oom();
1580
1581         r = list_dependencies_get_dependencies(bus, name, &deps);
1582         if (r < 0)
1583                 return r;
1584
1585         qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1586
1587         STRV_FOREACH(c, deps) {
1588                 int state;
1589
1590                 if (strv_contains(*units, *c)) {
1591                         if (!arg_plain) {
1592                                 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1593                                 if (r < 0)
1594                                         return r;
1595                         }
1596                         continue;
1597                 }
1598
1599                 state = check_one_unit(bus, *c, "activating\0active\0reloading\0", true);
1600                 if (state > 0)
1601                         printf("%s%s%s ", ansi_highlight_green(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1602                 else
1603                         printf("%s%s%s ", ansi_highlight_red(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1604
1605                 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1606                 if (r < 0)
1607                         return r;
1608
1609                 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1610                        r = list_dependencies_one(bus, *c, level + 1, units, (branches << 1) | (c[1] == NULL ? 0 : 1));
1611                        if (r < 0)
1612                                return r;
1613                 }
1614         }
1615
1616         if (!arg_plain)
1617                 strv_remove(*units, name);
1618
1619         return 0;
1620 }
1621
1622 static int list_dependencies(sd_bus *bus, char **args) {
1623         _cleanup_strv_free_ char **units = NULL;
1624         _cleanup_free_ char *unit = NULL;
1625         const char *u;
1626
1627         assert(bus);
1628
1629         if (args[1]) {
1630                 unit = unit_name_mangle(args[1], MANGLE_NOGLOB);
1631                 if (!unit)
1632                         return log_oom();
1633                 u = unit;
1634         } else
1635                 u = SPECIAL_DEFAULT_TARGET;
1636
1637         pager_open_if_enabled();
1638
1639         puts(u);
1640
1641         return list_dependencies_one(bus, u, 0, &units, 0);
1642 }
1643
1644 struct machine_info {
1645         bool is_host;
1646         char *name;
1647         char *state;
1648         char *control_group;
1649         uint32_t n_failed_units;
1650         uint32_t n_jobs;
1651         usec_t timestamp;
1652 };
1653
1654 static const struct bus_properties_map machine_info_property_map[] = {
1655         { "SystemState",        "s", NULL, offsetof(struct machine_info, state)          },
1656         { "NJobs",              "u", NULL, offsetof(struct machine_info, n_jobs)         },
1657         { "NFailedUnits",       "u", NULL, offsetof(struct machine_info, n_failed_units) },
1658         { "ControlGroup",       "s", NULL, offsetof(struct machine_info, control_group)  },
1659         { "UserspaceTimestamp", "t", NULL, offsetof(struct machine_info, timestamp)      },
1660         {}
1661 };
1662
1663 static void free_machines_list(struct machine_info *machine_infos, int n) {
1664         int i;
1665
1666         if (!machine_infos)
1667                 return;
1668
1669         for (i = 0; i < n; i++) {
1670                 free(machine_infos[i].name);
1671                 free(machine_infos[i].state);
1672                 free(machine_infos[i].control_group);
1673         }
1674
1675         free(machine_infos);
1676 }
1677
1678 static int compare_machine_info(const void *a, const void *b) {
1679         const struct machine_info *u = a, *v = b;
1680
1681         if (u->is_host != v->is_host)
1682                 return u->is_host > v->is_host ? -1 : 1;
1683
1684         return strcasecmp(u->name, v->name);
1685 }
1686
1687 static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
1688         _cleanup_bus_unref_ sd_bus *container = NULL;
1689         int r;
1690
1691         assert(mi);
1692
1693         if (!bus) {
1694                 r = sd_bus_open_system_container(&container, mi->name);
1695                 if (r < 0)
1696                         return r;
1697
1698                 bus = container;
1699         }
1700
1701         r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, mi);
1702         if (r < 0)
1703                 return r;
1704
1705         return 0;
1706 }
1707
1708 static bool output_show_machine(const char *name, char **patterns) {
1709         char **i;
1710
1711         assert(name);
1712
1713         if (strv_isempty(patterns))
1714                 return true;
1715
1716         STRV_FOREACH(i, patterns)
1717                 if (fnmatch(*i, name, FNM_NOESCAPE) == 0)
1718                         return true;
1719
1720         return false;
1721 }
1722
1723 static int get_machine_list(
1724                 sd_bus *bus,
1725                 struct machine_info **_machine_infos,
1726                 char **patterns) {
1727
1728         struct machine_info *machine_infos = NULL;
1729         _cleanup_strv_free_ char **m = NULL;
1730         _cleanup_free_ char *hn = NULL;
1731         size_t sz = 0;
1732         char **i;
1733         int c = 0;
1734
1735         hn = gethostname_malloc();
1736         if (!hn)
1737                 return log_oom();
1738
1739         if (output_show_machine(hn, patterns)) {
1740                 if (!GREEDY_REALLOC0(machine_infos, sz, c+1))
1741                         return log_oom();
1742
1743                 machine_infos[c].is_host = true;
1744                 machine_infos[c].name = hn;
1745                 hn = NULL;
1746
1747                 get_machine_properties(bus, &machine_infos[c]);
1748                 c++;
1749         }
1750
1751         sd_get_machine_names(&m);
1752         STRV_FOREACH(i, m) {
1753                 _cleanup_free_ char *class = NULL;
1754
1755                 if (!output_show_machine(*i, patterns))
1756                         continue;
1757
1758                 sd_machine_get_class(*i, &class);
1759                 if (!streq_ptr(class, "container"))
1760                         continue;
1761
1762                 if (!GREEDY_REALLOC0(machine_infos, sz, c+1)) {
1763                         free_machines_list(machine_infos, c);
1764                         return log_oom();
1765                 }
1766
1767                 machine_infos[c].is_host = false;
1768                 machine_infos[c].name = strdup(*i);
1769                 if (!machine_infos[c].name) {
1770                         free_machines_list(machine_infos, c);
1771                         return log_oom();
1772                 }
1773
1774                 get_machine_properties(NULL, &machine_infos[c]);
1775                 c++;
1776         }
1777
1778         *_machine_infos = machine_infos;
1779         return c;
1780 }
1781
1782 static void output_machines_list(struct machine_info *machine_infos, unsigned n) {
1783         struct machine_info *m;
1784         unsigned
1785                 circle_len = 0,
1786                 namelen = sizeof("NAME") - 1,
1787                 statelen = sizeof("STATE") - 1,
1788                 failedlen = sizeof("FAILED") - 1,
1789                 jobslen = sizeof("JOBS") - 1;
1790
1791         assert(machine_infos || n == 0);
1792
1793         for (m = machine_infos; m < machine_infos + n; m++) {
1794                 namelen = MAX(namelen, strlen(m->name) + (m->is_host ? sizeof(" (host)") - 1 : 0));
1795                 statelen = MAX(statelen, m->state ? strlen(m->state) : 0);
1796                 failedlen = MAX(failedlen, DECIMAL_STR_WIDTH(m->n_failed_units));
1797                 jobslen = MAX(jobslen, DECIMAL_STR_WIDTH(m->n_jobs));
1798
1799                 if (!arg_no_legend && !streq_ptr(m->state, "running"))
1800                         circle_len = 2;
1801         }
1802
1803         if (!arg_no_legend) {
1804                 if (circle_len > 0)
1805                         fputs("  ", stdout);
1806
1807                 printf("%-*s %-*s %-*s %-*s\n",
1808                          namelen, "NAME",
1809                         statelen, "STATE",
1810                        failedlen, "FAILED",
1811                          jobslen, "JOBS");
1812         }
1813
1814         for (m = machine_infos; m < machine_infos + n; m++) {
1815                 const char *on_state = "", *off_state = "";
1816                 const char *on_failed = "", *off_failed = "";
1817                 bool circle = false;
1818
1819                 if (streq_ptr(m->state, "degraded")) {
1820                         on_state = ansi_highlight_red();
1821                         off_state = ansi_highlight_off();
1822                         circle = true;
1823                 } else if (!streq_ptr(m->state, "running")) {
1824                         on_state = ansi_highlight_yellow();
1825                         off_state = ansi_highlight_off();
1826                         circle = true;
1827                 }
1828
1829                 if (m->n_failed_units > 0) {
1830                         on_failed = ansi_highlight_red();
1831                         off_failed = ansi_highlight_off();
1832                 } else
1833                         on_failed = off_failed = "";
1834
1835                 if (circle_len > 0)
1836                         printf("%s%s%s ", on_state, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_state);
1837
1838                 if (m->is_host)
1839                         printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
1840                                (int) (namelen - (sizeof(" (host)")-1)), strna(m->name),
1841                                on_state, statelen, strna(m->state), off_state,
1842                                on_failed, failedlen, m->n_failed_units, off_failed,
1843                                jobslen, m->n_jobs);
1844                 else
1845                         printf("%-*s %s%-*s%s %s%*u%s %*u\n",
1846                                namelen, strna(m->name),
1847                                on_state, statelen, strna(m->state), off_state,
1848                                on_failed, failedlen, m->n_failed_units, off_failed,
1849                                jobslen, m->n_jobs);
1850         }
1851
1852         if (!arg_no_legend)
1853                 printf("\n%u machines listed.\n", n);
1854 }
1855
1856 static int list_machines(sd_bus *bus, char **args) {
1857         struct machine_info *machine_infos = NULL;
1858         int r;
1859
1860         assert(bus);
1861
1862         if (geteuid() != 0) {
1863                 log_error("Must be root.");
1864                 return -EPERM;
1865         }
1866
1867         pager_open_if_enabled();
1868
1869         r = get_machine_list(bus, &machine_infos, strv_skip_first(args));
1870         if (r < 0)
1871                 return r;
1872
1873         qsort_safe(machine_infos, r, sizeof(struct machine_info), compare_machine_info);
1874         output_machines_list(machine_infos, r);
1875         free_machines_list(machine_infos, r);
1876
1877         return 0;
1878 }
1879
1880 static int get_default(sd_bus *bus, char **args) {
1881         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1882         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1883         _cleanup_free_ char *_path = NULL;
1884         const char *path;
1885         int r;
1886
1887         if (!bus || avoid_bus()) {
1888                 r = unit_file_get_default(arg_scope, arg_root, &_path);
1889                 if (r < 0) {
1890                         log_error("Failed to get default target: %s", strerror(-r));
1891                         return r;
1892                 }
1893                 path = _path;
1894
1895         } else {
1896                 r = sd_bus_call_method(
1897                                 bus,
1898                                 "org.freedesktop.systemd1",
1899                                 "/org/freedesktop/systemd1",
1900                                 "org.freedesktop.systemd1.Manager",
1901                                 "GetDefaultTarget",
1902                                 &error,
1903                                 &reply,
1904                                 NULL);
1905                 if (r < 0) {
1906                         log_error("Failed to get default target: %s", bus_error_message(&error, -r));
1907                         return r;
1908                 }
1909
1910                 r = sd_bus_message_read(reply, "s", &path);
1911                 if (r < 0)
1912                         return bus_log_parse_error(r);
1913         }
1914
1915         if (path)
1916                 printf("%s\n", path);
1917
1918         return 0;
1919 }
1920
1921 static void dump_unit_file_changes(const UnitFileChange *changes, unsigned n_changes) {
1922         unsigned i;
1923
1924         assert(changes || n_changes == 0);
1925
1926         for (i = 0; i < n_changes; i++) {
1927                 if (changes[i].type == UNIT_FILE_SYMLINK)
1928                         log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
1929                 else
1930                         log_info("rm '%s'", changes[i].path);
1931         }
1932 }
1933
1934 static int deserialize_and_dump_unit_file_changes(sd_bus_message *m) {
1935         const char *type, *path, *source;
1936         int r;
1937
1938         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
1939         if (r < 0)
1940                 return bus_log_parse_error(r);
1941
1942         while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
1943                 if (!arg_quiet) {
1944                         if (streq(type, "symlink"))
1945                                 log_info("ln -s '%s' '%s'", source, path);
1946                         else
1947                                 log_info("rm '%s'", path);
1948                 }
1949         }
1950         if (r < 0)
1951                 return bus_log_parse_error(r);
1952
1953         r = sd_bus_message_exit_container(m);
1954         if (r < 0)
1955                 return bus_log_parse_error(r);
1956
1957         return 0;
1958 }
1959
1960 static int set_default(sd_bus *bus, char **args) {
1961         _cleanup_free_ char *unit = NULL;
1962         UnitFileChange *changes = NULL;
1963         unsigned n_changes = 0;
1964         int r;
1965
1966         unit = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
1967         if (!unit)
1968                 return log_oom();
1969
1970         if (!bus || avoid_bus()) {
1971                 r = unit_file_set_default(arg_scope, arg_root, unit, true, &changes, &n_changes);
1972                 if (r < 0) {
1973                         log_error("Failed to set default target: %s", strerror(-r));
1974                         return r;
1975                 }
1976
1977                 if (!arg_quiet)
1978                         dump_unit_file_changes(changes, n_changes);
1979
1980                 r = 0;
1981         } else {
1982                 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1983                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1984
1985                 r = sd_bus_call_method(
1986                                 bus,
1987                                 "org.freedesktop.systemd1",
1988                                 "/org/freedesktop/systemd1",
1989                                 "org.freedesktop.systemd1.Manager",
1990                                 "SetDefaultTarget",
1991                                 &error,
1992                                 &reply,
1993                                 "sb", unit, true);
1994                 if (r < 0) {
1995                         log_error("Failed to set default target: %s", bus_error_message(&error, -r));
1996                         return r;
1997                 }
1998
1999                 r = deserialize_and_dump_unit_file_changes(reply);
2000                 if (r < 0)
2001                         return r;
2002
2003                 /* Try to reload if enabled */
2004                 if (!arg_no_reload)
2005                         r = daemon_reload(bus, args);
2006                 else
2007                         r = 0;
2008         }
2009
2010         unit_file_changes_free(changes, n_changes);
2011
2012         return r;
2013 }
2014
2015 struct job_info {
2016         uint32_t id;
2017         const char *name, *type, *state;
2018 };
2019
2020 static void output_jobs_list(const struct job_info* jobs, unsigned n, bool skipped) {
2021         unsigned id_len, unit_len, type_len, state_len;
2022         const struct job_info *j;
2023         const char *on, *off;
2024         bool shorten = false;
2025
2026         assert(n == 0 || jobs);
2027
2028         if (n == 0) {
2029                 on = ansi_highlight_green();
2030                 off = ansi_highlight_off();
2031
2032                 printf("%sNo jobs %s.%s\n", on, skipped ? "listed" : "running", off);
2033                 return;
2034         }
2035
2036         pager_open_if_enabled();
2037
2038         id_len = strlen("JOB");
2039         unit_len = strlen("UNIT");
2040         type_len = strlen("TYPE");
2041         state_len = strlen("STATE");
2042
2043         for (j = jobs; j < jobs + n; j++) {
2044                 uint32_t id = j->id;
2045                 assert(j->name && j->type && j->state);
2046
2047                 id_len = MAX(id_len, DECIMAL_STR_WIDTH(id));
2048                 unit_len = MAX(unit_len, strlen(j->name));
2049                 type_len = MAX(type_len, strlen(j->type));
2050                 state_len = MAX(state_len, strlen(j->state));
2051         }
2052
2053         if (!arg_full && id_len + 1 + unit_len + type_len + 1 + state_len > columns()) {
2054                 unit_len = MAX(33u, columns() - id_len - type_len - state_len - 3);
2055                 shorten = true;
2056         }
2057
2058         if (!arg_no_legend)
2059                 printf("%*s %-*s %-*s %-*s\n",
2060                        id_len, "JOB",
2061                        unit_len, "UNIT",
2062                        type_len, "TYPE",
2063                        state_len, "STATE");
2064
2065         for (j = jobs; j < jobs + n; j++) {
2066                 _cleanup_free_ char *e = NULL;
2067
2068                 if (streq(j->state, "running")) {
2069                         on = ansi_highlight();
2070                         off = ansi_highlight_off();
2071                 } else
2072                         on = off = "";
2073
2074                 e = shorten ? ellipsize(j->name, unit_len, 33) : NULL;
2075                 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2076                        id_len, j->id,
2077                        on, unit_len, e ? e : j->name, off,
2078                        type_len, j->type,
2079                        on, state_len, j->state, off);
2080         }
2081
2082         if (!arg_no_legend) {
2083                 on = ansi_highlight();
2084                 off = ansi_highlight_off();
2085
2086                 printf("\n%s%u jobs listed%s.\n", on, n, off);
2087         }
2088 }
2089
2090 static bool output_show_job(struct job_info *job, char **patterns) {
2091         char **pattern;
2092
2093         assert(job);
2094
2095         if (strv_isempty(patterns))
2096                 return true;
2097
2098         STRV_FOREACH(pattern, patterns)
2099                 if (fnmatch(*pattern, job->name, FNM_NOESCAPE) == 0)
2100                         return true;
2101         return false;
2102 }
2103
2104 static int list_jobs(sd_bus *bus, char **args) {
2105         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2106         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2107         const char *name, *type, *state, *job_path, *unit_path;
2108         _cleanup_free_ struct job_info *jobs = NULL;
2109         size_t size = 0;
2110         unsigned c = 0;
2111         uint32_t id;
2112         int r;
2113         bool skipped = false;
2114
2115         r = sd_bus_call_method(
2116                         bus,
2117                         "org.freedesktop.systemd1",
2118                         "/org/freedesktop/systemd1",
2119                         "org.freedesktop.systemd1.Manager",
2120                         "ListJobs",
2121                         &error,
2122                         &reply,
2123                         NULL);
2124         if (r < 0) {
2125                 log_error("Failed to list jobs: %s", bus_error_message(&error, r));
2126                 return r;
2127         }
2128
2129         r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
2130         if (r < 0)
2131                 return bus_log_parse_error(r);
2132
2133         while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, &job_path, &unit_path)) > 0) {
2134                 struct job_info job = { id, name, type, state };
2135
2136                 if (!output_show_job(&job, strv_skip_first(args))) {
2137                         skipped = true;
2138                         continue;
2139                 }
2140
2141                 if (!GREEDY_REALLOC(jobs, size, c + 1))
2142                         return log_oom();
2143
2144                 jobs[c++] = job;
2145         }
2146         if (r < 0)
2147                 return bus_log_parse_error(r);
2148
2149         r = sd_bus_message_exit_container(reply);
2150         if (r < 0)
2151                 return bus_log_parse_error(r);
2152
2153         output_jobs_list(jobs, c, skipped);
2154         return r;
2155 }
2156
2157 static int cancel_job(sd_bus *bus, char **args) {
2158         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2159         char **name;
2160
2161         assert(args);
2162
2163         if (strv_length(args) <= 1)
2164                 return daemon_reload(bus, args);
2165
2166         STRV_FOREACH(name, args+1) {
2167                 uint32_t id;
2168                 int r;
2169
2170                 r = safe_atou32(*name, &id);
2171                 if (r < 0) {
2172                         log_error("Failed to parse job id \"%s\": %s", *name, strerror(-r));
2173                         return r;
2174                 }
2175
2176                 r = sd_bus_call_method(
2177                                 bus,
2178                                 "org.freedesktop.systemd1",
2179                                 "/org/freedesktop/systemd1",
2180                                 "org.freedesktop.systemd1.Manager",
2181                                 "CancelJob",
2182                                 &error,
2183                                 NULL,
2184                                 "u", id);
2185                 if (r < 0) {
2186                         log_error("Failed to cancel job %u: %s", (unsigned) id, bus_error_message(&error, r));
2187                         return r;
2188                 }
2189         }
2190
2191         return 0;
2192 }
2193
2194 static int need_daemon_reload(sd_bus *bus, const char *unit) {
2195         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2196         const char *path;
2197         int b, r;
2198
2199         /* We ignore all errors here, since this is used to show a
2200          * warning only */
2201
2202         /* We don't use unit_dbus_path_from_name() directly since we
2203          * don't want to load the unit if it isn't loaded. */
2204
2205         r = sd_bus_call_method(
2206                         bus,
2207                         "org.freedesktop.systemd1",
2208                         "/org/freedesktop/systemd1",
2209                         "org.freedesktop.systemd1.Manager",
2210                         "GetUnit",
2211                         NULL,
2212                         &reply,
2213                         "s", unit);
2214         if (r < 0)
2215                 return r;
2216
2217         r = sd_bus_message_read(reply, "o", &path);
2218         if (r < 0)
2219                 return r;
2220
2221         r = sd_bus_get_property_trivial(
2222                         bus,
2223                         "org.freedesktop.systemd1",
2224                         path,
2225                         "org.freedesktop.systemd1.Unit",
2226                         "NeedDaemonReload",
2227                         NULL,
2228                         'b', &b);
2229         if (r < 0)
2230                 return r;
2231
2232         return b;
2233 }
2234
2235 typedef struct WaitData {
2236         Set *set;
2237
2238         char *name;
2239         char *result;
2240 } WaitData;
2241
2242 static int wait_filter(sd_bus *bus, sd_bus_message *m, void *data, sd_bus_error *error) {
2243         WaitData *d = data;
2244
2245         assert(bus);
2246         assert(m);
2247         assert(d);
2248
2249         log_debug("Got D-Bus request: %s.%s() on %s",
2250                   sd_bus_message_get_interface(m),
2251                   sd_bus_message_get_member(m),
2252                   sd_bus_message_get_path(m));
2253
2254         if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
2255                 log_error("Warning! D-Bus connection terminated.");
2256                 sd_bus_close(bus);
2257         } else if (sd_bus_message_is_signal(m, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
2258                 uint32_t id;
2259                 const char *path, *result, *unit;
2260                 char *ret;
2261                 int r;
2262
2263                 r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
2264                 if (r >= 0) {
2265                         ret = set_remove(d->set, (char*) path);
2266                         if (!ret)
2267                                 return 0;
2268
2269                         free(ret);
2270
2271                         if (!isempty(result))
2272                                 d->result = strdup(result);
2273
2274                         if (!isempty(unit))
2275                                 d->name = strdup(unit);
2276
2277                         return 0;
2278                 }
2279 #ifndef NOLEGACY
2280                 r = sd_bus_message_read(m, "uos", &id, &path, &result);
2281                 if (r >= 0) {
2282                         ret = set_remove(d->set, (char*) path);
2283                         if (!ret)
2284                                 return 0;
2285
2286                         free(ret);
2287
2288                         if (*result)
2289                                 d->result = strdup(result);
2290
2291                         return 0;
2292                 }
2293 #endif
2294
2295                 bus_log_parse_error(r);
2296         }
2297
2298         return 0;
2299 }
2300
2301 static int enable_wait_for_jobs(sd_bus *bus) {
2302         int r;
2303
2304         assert(bus);
2305
2306         r = sd_bus_add_match(
2307                         bus,
2308                         "type='signal',"
2309                         "sender='org.freedesktop.systemd1',"
2310                         "interface='org.freedesktop.systemd1.Manager',"
2311                         "member='JobRemoved',"
2312                         "path='/org/freedesktop/systemd1'",
2313                         NULL, NULL);
2314         if (r < 0) {
2315                 log_error("Failed to add match");
2316                 return -EIO;
2317         }
2318
2319         /* This is slightly dirty, since we don't undo the match registrations. */
2320         return 0;
2321 }
2322
2323 static int bus_process_wait(sd_bus *bus) {
2324         int r;
2325
2326         for (;;) {
2327                 r = sd_bus_process(bus, NULL);
2328                 if (r < 0)
2329                         return r;
2330                 if (r > 0)
2331                         return 0;
2332                 r = sd_bus_wait(bus, (uint64_t) -1);
2333                 if (r < 0)
2334                         return r;
2335         }
2336 }
2337
2338 static int check_wait_response(WaitData *d) {
2339         int r = 0;
2340
2341         assert(d->result);
2342
2343         if (!arg_quiet) {
2344                 if (streq(d->result, "timeout"))
2345                         log_error("Job for %s timed out.", strna(d->name));
2346                 else if (streq(d->result, "canceled"))
2347                         log_error("Job for %s canceled.", strna(d->name));
2348                 else if (streq(d->result, "dependency"))
2349                         log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d->name));
2350                 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
2351                         log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d->name), strna(d->name));
2352         }
2353
2354         if (streq(d->result, "timeout"))
2355                 r = -ETIME;
2356         else if (streq(d->result, "canceled"))
2357                 r = -ECANCELED;
2358         else if (streq(d->result, "dependency"))
2359                 r = -EIO;
2360         else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
2361                 r = -EIO;
2362
2363         return r;
2364 }
2365
2366 static int wait_for_jobs(sd_bus *bus, Set *s) {
2367         WaitData d = { .set = s };
2368         int r = 0, q;
2369
2370         assert(bus);
2371         assert(s);
2372
2373         q = sd_bus_add_filter(bus, wait_filter, &d);
2374         if (q < 0)
2375                 return log_oom();
2376
2377         while (!set_isempty(s)) {
2378                 q = bus_process_wait(bus);
2379                 if (q < 0) {
2380                         log_error("Failed to wait for response: %s", strerror(-r));
2381                         return q;
2382                 }
2383
2384                 if (d.result) {
2385                         q = check_wait_response(&d);
2386                         /* Return the first error as it is most likely to be
2387                          * meaningful. */
2388                         if (q < 0 && r == 0)
2389                                 r = q;
2390                         log_debug("Got result %s/%s for job %s",
2391                                   strna(d.result), strerror(-q), strna(d.name));
2392                 }
2393
2394                 free(d.name);
2395                 d.name = NULL;
2396
2397                 free(d.result);
2398                 d.result = NULL;
2399         }
2400
2401         q = sd_bus_remove_filter(bus, wait_filter, &d);
2402         if (q < 0 && r == 0)
2403                 r = q;
2404
2405         return r;
2406 }
2407
2408 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
2409         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2410         _cleanup_free_ char *n = NULL, *state = NULL;
2411         const char *path;
2412         int r;
2413
2414         assert(name);
2415
2416         n = unit_name_mangle(name, MANGLE_NOGLOB);
2417         if (!n)
2418                 return log_oom();
2419
2420         /* We don't use unit_dbus_path_from_name() directly since we
2421          * don't want to load the unit if it isn't loaded. */
2422
2423         r = sd_bus_call_method(
2424                         bus,
2425                         "org.freedesktop.systemd1",
2426                         "/org/freedesktop/systemd1",
2427                         "org.freedesktop.systemd1.Manager",
2428                         "GetUnit",
2429                         NULL,
2430                         &reply,
2431                         "s", n);
2432         if (r < 0) {
2433                 if (!quiet)
2434                         puts("unknown");
2435                 return 0;
2436         }
2437
2438         r = sd_bus_message_read(reply, "o", &path);
2439         if (r < 0)
2440                 return bus_log_parse_error(r);
2441
2442         r = sd_bus_get_property_string(
2443                         bus,
2444                         "org.freedesktop.systemd1",
2445                         path,
2446                         "org.freedesktop.systemd1.Unit",
2447                         "ActiveState",
2448                         NULL,
2449                         &state);
2450         if (r < 0) {
2451                 if (!quiet)
2452                         puts("unknown");
2453                 return 0;
2454         }
2455
2456         if (!quiet)
2457                 puts(state);
2458
2459         return nulstr_contains(good_states, state);
2460 }
2461
2462 static int check_triggering_units(
2463                 sd_bus *bus,
2464                 const char *name) {
2465
2466         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2467         _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
2468         _cleanup_strv_free_ char **triggered_by = NULL;
2469         bool print_warning_label = true;
2470         char **i;
2471         int r;
2472
2473         n = unit_name_mangle(name, MANGLE_NOGLOB);
2474         if (!n)
2475                 return log_oom();
2476
2477         path = unit_dbus_path_from_name(n);
2478         if (!path)
2479                 return log_oom();
2480
2481         r = sd_bus_get_property_string(
2482                         bus,
2483                         "org.freedesktop.systemd1",
2484                         path,
2485                         "org.freedesktop.systemd1.Unit",
2486                         "LoadState",
2487                         &error,
2488                         &state);
2489         if (r < 0) {
2490                 log_error("Failed to get load state of %s: %s", n, bus_error_message(&error, r));
2491                 return r;
2492         }
2493
2494         if (streq(state, "masked"))
2495                 return 0;
2496
2497         r = sd_bus_get_property_strv(
2498                         bus,
2499                         "org.freedesktop.systemd1",
2500                         path,
2501                         "org.freedesktop.systemd1.Unit",
2502                         "TriggeredBy",
2503                         &error,
2504                         &triggered_by);
2505         if (r < 0) {
2506                 log_error("Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
2507                 return r;
2508         }
2509
2510         STRV_FOREACH(i, triggered_by) {
2511                 r = check_one_unit(bus, *i, "active\0reloading\0", true);
2512                 if (r < 0) {
2513                         log_error("Failed to check unit: %s", strerror(-r));
2514                         return r;
2515                 }
2516
2517                 if (r == 0)
2518                         continue;
2519
2520                 if (print_warning_label) {
2521                         log_warning("Warning: Stopping %s, but it can still be activated by:", n);
2522                         print_warning_label = false;
2523                 }
2524
2525                 log_warning("  %s", *i);
2526         }
2527
2528         return 0;
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                 Set *s) {
2558
2559         _cleanup_bus_message_unref_ sd_bus_message *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         r = sd_bus_call_method(
2570                         bus,
2571                         "org.freedesktop.systemd1",
2572                         "/org/freedesktop/systemd1",
2573                         "org.freedesktop.systemd1.Manager",
2574                         method,
2575                         error,
2576                         &reply,
2577                         "ss", name, mode);
2578         if (r < 0) {
2579                 const char *verb;
2580
2581                 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
2582                         /* There's always a fallback possible for
2583                          * legacy actions. */
2584                         return -EADDRNOTAVAIL;
2585
2586                 verb = method_to_verb(method);
2587
2588                 log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r));
2589                 return r;
2590         }
2591
2592         r = sd_bus_message_read(reply, "o", &path);
2593         if (r < 0)
2594                 return bus_log_parse_error(r);
2595
2596         if (need_daemon_reload(bus, name) > 0)
2597                 log_warning("Warning: Unit file of %s changed on disk, 'systemctl%s daemon-reload' recommended.",
2598                             name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
2599
2600         if (s) {
2601                 char *p;
2602
2603                 p = strdup(path);
2604                 if (!p)
2605                         return log_oom();
2606
2607                 log_debug("Adding %s to the set", p);
2608                 r = set_consume(s, p);
2609                 if (r < 0)
2610                         return log_oom();
2611         }
2612
2613         return 0;
2614 }
2615
2616 static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret) {
2617
2618         _cleanup_strv_free_ char **mangled = NULL, **globs = NULL;
2619         char **name;
2620         int r = 0, i;
2621
2622         STRV_FOREACH(name, names) {
2623                 char *t;
2624
2625                 if (suffix)
2626                         t = unit_name_mangle_with_suffix(*name, MANGLE_GLOB, suffix);
2627                 else
2628                         t = unit_name_mangle(*name, MANGLE_GLOB);
2629                 if (!t)
2630                         return log_oom();
2631
2632                 if (string_is_glob(t))
2633                         r = strv_consume(&globs, t);
2634                 else
2635                         r = strv_consume(&mangled, t);
2636                 if (r < 0)
2637                         return log_oom();
2638         }
2639
2640         /* Query the manager only if any of the names are a glob, since
2641          * this is fairly expensive */
2642         if (!strv_isempty(globs)) {
2643                 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2644                 _cleanup_free_ UnitInfo *unit_infos = NULL;
2645
2646                 r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
2647                 if (r < 0)
2648                         return r;
2649
2650                 for (i = 0; i < r; i++)
2651                         if (strv_extend(&mangled, unit_infos[i].id) < 0)
2652                                 return log_oom();
2653         }
2654
2655         *ret = mangled;
2656         mangled = NULL; /* do not free */
2657
2658         return 0;
2659 }
2660
2661 static const struct {
2662         const char *target;
2663         const char *verb;
2664         const char *mode;
2665 } action_table[_ACTION_MAX] = {
2666         [ACTION_HALT]         = { SPECIAL_HALT_TARGET,         "halt",         "replace-irreversibly" },
2667         [ACTION_POWEROFF]     = { SPECIAL_POWEROFF_TARGET,     "poweroff",     "replace-irreversibly" },
2668         [ACTION_REBOOT]       = { SPECIAL_REBOOT_TARGET,       "reboot",       "replace-irreversibly" },
2669         [ACTION_KEXEC]        = { SPECIAL_KEXEC_TARGET,        "kexec",        "replace-irreversibly" },
2670         [ACTION_RUNLEVEL2]    = { SPECIAL_RUNLEVEL2_TARGET,    NULL,           "isolate" },
2671         [ACTION_RUNLEVEL3]    = { SPECIAL_RUNLEVEL3_TARGET,    NULL,           "isolate" },
2672         [ACTION_RUNLEVEL4]    = { SPECIAL_RUNLEVEL4_TARGET,    NULL,           "isolate" },
2673         [ACTION_RUNLEVEL5]    = { SPECIAL_RUNLEVEL5_TARGET,    NULL,           "isolate" },
2674         [ACTION_RESCUE]       = { SPECIAL_RESCUE_TARGET,       "rescue",       "isolate" },
2675         [ACTION_EMERGENCY]    = { SPECIAL_EMERGENCY_TARGET,    "emergency",    "isolate" },
2676         [ACTION_DEFAULT]      = { SPECIAL_DEFAULT_TARGET,      "default",      "isolate" },
2677         [ACTION_EXIT]         = { SPECIAL_EXIT_TARGET,         "exit",         "replace-irreversibly" },
2678         [ACTION_SUSPEND]      = { SPECIAL_SUSPEND_TARGET,      "suspend",      "replace-irreversibly" },
2679         [ACTION_HIBERNATE]    = { SPECIAL_HIBERNATE_TARGET,    "hibernate",    "replace-irreversibly" },
2680         [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
2681 };
2682
2683 static enum action verb_to_action(const char *verb) {
2684         enum action i;
2685
2686         for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
2687                 if (streq_ptr(action_table[i].verb, verb))
2688                         return i;
2689
2690         return _ACTION_INVALID;
2691 }
2692
2693 static int start_unit(sd_bus *bus, char **args) {
2694         _cleanup_set_free_free_ Set *s = NULL;
2695         _cleanup_strv_free_ char **names = NULL;
2696         const char *method, *mode, *one_name;
2697         char **name;
2698         int r = 0;
2699
2700         assert(bus);
2701
2702         ask_password_agent_open_if_enabled();
2703
2704         if (arg_action == ACTION_SYSTEMCTL) {
2705                 enum action action;
2706                 method = verb_to_method(args[0]);
2707                 action = verb_to_action(args[0]);
2708
2709                 mode = streq(args[0], "isolate") ? "isolate" :
2710                        action_table[action].mode ?: arg_job_mode;
2711
2712                 one_name = action_table[action].target;
2713         } else {
2714                 assert(arg_action < ELEMENTSOF(action_table));
2715                 assert(action_table[arg_action].target);
2716
2717                 method = "StartUnit";
2718
2719                 mode = action_table[arg_action].mode;
2720                 one_name = action_table[arg_action].target;
2721         }
2722
2723         if (one_name)
2724                 names = strv_new(one_name, NULL);
2725         else {
2726                 r = expand_names(bus, args + 1, NULL, &names);
2727                 if (r < 0)
2728                         log_error("Failed to expand names: %s", strerror(-r));
2729         }
2730
2731         if (!arg_no_block) {
2732                 r = enable_wait_for_jobs(bus);
2733                 if (r < 0) {
2734                         log_error("Could not watch jobs: %s", strerror(-r));
2735                         return r;
2736                 }
2737
2738                 s = set_new(string_hash_func, string_compare_func);
2739                 if (!s)
2740                         return log_oom();
2741         }
2742
2743         STRV_FOREACH(name, names) {
2744                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2745                 int q;
2746
2747                 q = start_unit_one(bus, method, *name, mode, &error, s);
2748                 if (r >= 0 && q < 0)
2749                         r = translate_bus_error_to_exit_status(q, &error);
2750         }
2751
2752         if (!arg_no_block) {
2753                 int q;
2754
2755                 q = wait_for_jobs(bus, s);
2756                 if (q < 0)
2757                         return q;
2758
2759                 /* When stopping units, warn if they can still be triggered by
2760                  * another active unit (socket, path, timer) */
2761                 if (!arg_quiet && streq(method, "StopUnit"))
2762                         STRV_FOREACH(name, names)
2763                                 check_triggering_units(bus, *name);
2764         }
2765
2766         return r;
2767 }
2768
2769 /* Ask systemd-logind, which might grant access to unprivileged users
2770  * through PolicyKit */
2771 static int reboot_with_logind(sd_bus *bus, enum action a) {
2772 #ifdef HAVE_LOGIND
2773         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2774         const char *method;
2775         int r;
2776
2777         if (!bus)
2778                 return -EIO;
2779
2780         polkit_agent_open_if_enabled();
2781
2782         switch (a) {
2783
2784         case ACTION_REBOOT:
2785                 method = "Reboot";
2786                 break;
2787
2788         case ACTION_POWEROFF:
2789                 method = "PowerOff";
2790                 break;
2791
2792         case ACTION_SUSPEND:
2793                 method = "Suspend";
2794                 break;
2795
2796         case ACTION_HIBERNATE:
2797                 method = "Hibernate";
2798                 break;
2799
2800         case ACTION_HYBRID_SLEEP:
2801                 method = "HybridSleep";
2802                 break;
2803
2804         default:
2805                 return -EINVAL;
2806         }
2807
2808         r = sd_bus_call_method(
2809                         bus,
2810                         "org.freedesktop.login1",
2811                         "/org/freedesktop/login1",
2812                         "org.freedesktop.login1.Manager",
2813                         method,
2814                         &error,
2815                         NULL,
2816                         "b", true);
2817         if (r < 0)
2818                 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
2819
2820         return r;
2821 #else
2822         return -ENOSYS;
2823 #endif
2824 }
2825
2826 static int check_inhibitors(sd_bus *bus, enum action a) {
2827 #ifdef HAVE_LOGIND
2828         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2829         _cleanup_strv_free_ char **sessions = NULL;
2830         const char *what, *who, *why, *mode;
2831         uint32_t uid, pid;
2832         unsigned c = 0;
2833         char **s;
2834         int r;
2835
2836         if (!bus)
2837                 return 0;
2838
2839         if (arg_ignore_inhibitors || arg_force > 0)
2840                 return 0;
2841
2842         if (arg_when > 0)
2843                 return 0;
2844
2845         if (geteuid() == 0)
2846                 return 0;
2847
2848         if (!on_tty())
2849                 return 0;
2850
2851         r = sd_bus_call_method(
2852                         bus,
2853                         "org.freedesktop.login1",
2854                         "/org/freedesktop/login1",
2855                         "org.freedesktop.login1.Manager",
2856                         "ListInhibitors",
2857                         NULL,
2858                         &reply,
2859                         NULL);
2860         if (r < 0)
2861                 /* If logind is not around, then there are no inhibitors... */
2862                 return 0;
2863
2864         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
2865         if (r < 0)
2866                 return bus_log_parse_error(r);
2867
2868         while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
2869                 _cleanup_free_ char *comm = NULL, *user = NULL;
2870                 _cleanup_strv_free_ char **sv = NULL;
2871
2872                 if (!streq(mode, "block"))
2873                         continue;
2874
2875                 sv = strv_split(what, ":");
2876                 if (!sv)
2877                         return log_oom();
2878
2879                 if (!strv_contains(sv,
2880                                   a == ACTION_HALT ||
2881                                   a == ACTION_POWEROFF ||
2882                                   a == ACTION_REBOOT ||
2883                                   a == ACTION_KEXEC ? "shutdown" : "sleep"))
2884                         continue;
2885
2886                 get_process_comm(pid, &comm);
2887                 user = uid_to_name(uid);
2888
2889                 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
2890                             who, (unsigned long) pid, strna(comm), strna(user), why);
2891
2892                 c++;
2893         }
2894         if (r < 0)
2895                 return bus_log_parse_error(r);
2896
2897         r = sd_bus_message_exit_container(reply);
2898         if (r < 0)
2899                 return bus_log_parse_error(r);
2900
2901         /* Check for current sessions */
2902         sd_get_sessions(&sessions);
2903         STRV_FOREACH(s, sessions) {
2904                 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2905
2906                 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2907                         continue;
2908
2909                 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2910                         continue;
2911
2912                 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2913                         continue;
2914
2915                 sd_session_get_tty(*s, &tty);
2916                 sd_session_get_seat(*s, &seat);
2917                 sd_session_get_service(*s, &service);
2918                 user = uid_to_name(uid);
2919
2920                 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2921                 c++;
2922         }
2923
2924         if (c <= 0)
2925                 return 0;
2926
2927         log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2928                   action_table[a].verb);
2929
2930         return -EPERM;
2931 #else
2932         return 0;
2933 #endif
2934 }
2935
2936 static int start_special(sd_bus *bus, char **args) {
2937         enum action a;
2938         int r;
2939
2940         assert(args);
2941
2942         a = verb_to_action(args[0]);
2943
2944         r = check_inhibitors(bus, a);
2945         if (r < 0)
2946                 return r;
2947
2948         if (arg_force >= 2 && geteuid() != 0) {
2949                 log_error("Must be root.");
2950                 return -EPERM;
2951         }
2952
2953         if (arg_force >= 2 &&
2954             (a == ACTION_HALT ||
2955              a == ACTION_POWEROFF ||
2956              a == ACTION_REBOOT))
2957                 return halt_now(a);
2958
2959         if (arg_force >= 1 &&
2960             (a == ACTION_HALT ||
2961              a == ACTION_POWEROFF ||
2962              a == ACTION_REBOOT ||
2963              a == ACTION_KEXEC ||
2964              a == ACTION_EXIT))
2965                 return daemon_reload(bus, args);
2966
2967         /* first try logind, to allow authentication with polkit */
2968         if (geteuid() != 0 &&
2969             (a == ACTION_POWEROFF ||
2970              a == ACTION_REBOOT ||
2971              a == ACTION_SUSPEND ||
2972              a == ACTION_HIBERNATE ||
2973              a == ACTION_HYBRID_SLEEP)) {
2974                 r = reboot_with_logind(bus, a);
2975                 if (r >= 0)
2976                         return r;
2977         }
2978
2979         r = start_unit(bus, args);
2980         if (r == EXIT_SUCCESS)
2981                 warn_wall(a);
2982
2983         return r;
2984 }
2985
2986 static int check_unit_generic(sd_bus *bus, int code, const char *good_states, char **args) {
2987         _cleanup_strv_free_ char **names = NULL;
2988         char **name;
2989         int r;
2990
2991         assert(bus);
2992         assert(args);
2993
2994         r = expand_names(bus, args, NULL, &names);
2995         if (r < 0) {
2996                 log_error("Failed to expand names: %s", strerror(-r));
2997                 return r;
2998         }
2999
3000         STRV_FOREACH(name, names) {
3001                 int state;
3002
3003                 state = check_one_unit(bus, *name, good_states, arg_quiet);
3004                 if (state < 0)
3005                         return state;
3006                 if (state == 0)
3007                         r = code;
3008         }
3009
3010         return r;
3011 }
3012
3013 static int check_unit_active(sd_bus *bus, char **args) {
3014         /* According to LSB: 3, "program is not running" */
3015         return check_unit_generic(bus, 3, "active\0reloading\0", args + 1);
3016 }
3017
3018 static int check_unit_failed(sd_bus *bus, char **args) {
3019         return check_unit_generic(bus, 1, "failed\0", args + 1);
3020 }
3021
3022 static int kill_unit(sd_bus *bus, char **args) {
3023         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3024         _cleanup_strv_free_ char **names = NULL;
3025         char **name;
3026         int r, q;
3027
3028         assert(bus);
3029         assert(args);
3030
3031         if (!arg_kill_who)
3032                 arg_kill_who = "all";
3033
3034         r = expand_names(bus, args + 1, NULL, &names);
3035         if (r < 0)
3036                 log_error("Failed to expand names: %s", strerror(-r));
3037
3038         STRV_FOREACH(name, names) {
3039                 q = sd_bus_call_method(
3040                                 bus,
3041                                 "org.freedesktop.systemd1",
3042                                 "/org/freedesktop/systemd1",
3043                                 "org.freedesktop.systemd1.Manager",
3044                                 "KillUnit",
3045                                 &error,
3046                                 NULL,
3047                                 "ssi", *names, arg_kill_who, arg_signal);
3048                 if (q < 0) {
3049                         log_error("Failed to kill unit %s: %s",
3050                                   *names, bus_error_message(&error, r));
3051                         if (r == 0)
3052                                 r = q;
3053                 }
3054         }
3055
3056         return r;
3057 }
3058
3059 typedef struct ExecStatusInfo {
3060         char *name;
3061
3062         char *path;
3063         char **argv;
3064
3065         bool ignore;
3066
3067         usec_t start_timestamp;
3068         usec_t exit_timestamp;
3069         pid_t pid;
3070         int code;
3071         int status;
3072
3073         LIST_FIELDS(struct ExecStatusInfo, exec);
3074 } ExecStatusInfo;
3075
3076 static void exec_status_info_free(ExecStatusInfo *i) {
3077         assert(i);
3078
3079         free(i->name);
3080         free(i->path);
3081         strv_free(i->argv);
3082         free(i);
3083 }
3084
3085 static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
3086         uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
3087         const char *path;
3088         uint32_t pid;
3089         int32_t code, status;
3090         int ignore, r;
3091
3092         assert(m);
3093         assert(i);
3094
3095         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii");
3096         if (r < 0)
3097                 return bus_log_parse_error(r);
3098         else if (r == 0)
3099                 return 0;
3100
3101         r = sd_bus_message_read(m, "s", &path);
3102         if (r < 0)
3103                 return bus_log_parse_error(r);
3104
3105         i->path = strdup(path);
3106         if (!i->path)
3107                 return log_oom();
3108
3109         r = sd_bus_message_read_strv(m, &i->argv);
3110         if (r < 0)
3111                 return bus_log_parse_error(r);
3112
3113         r = sd_bus_message_read(m,
3114                                 "bttttuii",
3115                                 &ignore,
3116                                 &start_timestamp, &start_timestamp_monotonic,
3117                                 &exit_timestamp, &exit_timestamp_monotonic,
3118                                 &pid,
3119                                 &code, &status);
3120         if (r < 0)
3121                 return bus_log_parse_error(r);
3122
3123         i->ignore = ignore;
3124         i->start_timestamp = (usec_t) start_timestamp;
3125         i->exit_timestamp = (usec_t) exit_timestamp;
3126         i->pid = (pid_t) pid;
3127         i->code = code;
3128         i->status = status;
3129
3130         r = sd_bus_message_exit_container(m);
3131         if (r < 0)
3132                 return bus_log_parse_error(r);
3133
3134         return 1;
3135 }
3136
3137 typedef struct UnitStatusInfo {
3138         const char *id;
3139         const char *load_state;
3140         const char *active_state;
3141         const char *sub_state;
3142         const char *unit_file_state;
3143
3144         const char *description;
3145         const char *following;
3146
3147         char **documentation;
3148
3149         const char *fragment_path;
3150         const char *source_path;
3151         const char *control_group;
3152
3153         char **dropin_paths;
3154
3155         const char *load_error;
3156         const char *result;
3157
3158         usec_t inactive_exit_timestamp;
3159         usec_t inactive_exit_timestamp_monotonic;
3160         usec_t active_enter_timestamp;
3161         usec_t active_exit_timestamp;
3162         usec_t inactive_enter_timestamp;
3163
3164         bool need_daemon_reload;
3165
3166         /* Service */
3167         pid_t main_pid;
3168         pid_t control_pid;
3169         const char *status_text;
3170         const char *pid_file;
3171         bool running:1;
3172
3173         usec_t start_timestamp;
3174         usec_t exit_timestamp;
3175
3176         int exit_code, exit_status;
3177
3178         usec_t condition_timestamp;
3179         bool condition_result;
3180         bool failed_condition_trigger;
3181         bool failed_condition_negate;
3182         const char *failed_condition;
3183         const char *failed_condition_param;
3184
3185         /* Socket */
3186         unsigned n_accepted;
3187         unsigned n_connections;
3188         bool accept;
3189
3190         /* Pairs of type, path */
3191         char **listen;
3192
3193         /* Device */
3194         const char *sysfs_path;
3195
3196         /* Mount, Automount */
3197         const char *where;
3198
3199         /* Swap */
3200         const char *what;
3201
3202         LIST_HEAD(ExecStatusInfo, exec);
3203 } UnitStatusInfo;
3204
3205 static void print_status_info(
3206                 UnitStatusInfo *i,
3207                 bool *ellipsized) {
3208
3209         ExecStatusInfo *p;
3210         const char *active_on, *active_off, *on, *off, *ss;
3211         usec_t timestamp;
3212         char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
3213         char since2[FORMAT_TIMESTAMP_MAX], *s2;
3214         const char *path;
3215         int flags =
3216                 arg_all * OUTPUT_SHOW_ALL |
3217                 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
3218                 on_tty() * OUTPUT_COLOR |
3219                 !arg_quiet * OUTPUT_WARN_CUTOFF |
3220                 arg_full * OUTPUT_FULL_WIDTH;
3221         char **t, **t2;
3222
3223         assert(i);
3224
3225         /* This shows pretty information about a unit. See
3226          * print_property() for a low-level property printer */
3227
3228         if (streq_ptr(i->active_state, "failed")) {
3229                 active_on = ansi_highlight_red();
3230                 active_off = ansi_highlight_off();
3231         } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
3232                 active_on = ansi_highlight_green();
3233                 active_off = ansi_highlight_off();
3234         } else
3235                 active_on = active_off = "";
3236
3237         printf("%s%s%s %s", active_on, draw_special_char(DRAW_BLACK_CIRCLE), active_off, strna(i->id));
3238
3239         if (i->description && !streq_ptr(i->id, i->description))
3240                 printf(" - %s", i->description);
3241
3242         printf("\n");
3243
3244         if (i->following)
3245                 printf("   Follow: unit currently follows state of %s\n", i->following);
3246
3247         if (streq_ptr(i->load_state, "error")) {
3248                 on = ansi_highlight_red();
3249                 off = ansi_highlight_off();
3250         } else
3251                 on = off = "";
3252
3253         path = i->source_path ? i->source_path : i->fragment_path;
3254
3255         if (i->load_error)
3256                 printf("   Loaded: %s%s%s (Reason: %s)\n",
3257                        on, strna(i->load_state), off, i->load_error);
3258         else if (path && i->unit_file_state)
3259                 printf("   Loaded: %s%s%s (%s; %s)\n",
3260                        on, strna(i->load_state), off, path, i->unit_file_state);
3261         else if (path)
3262                 printf("   Loaded: %s%s%s (%s)\n",
3263                        on, strna(i->load_state), off, path);
3264         else
3265                 printf("   Loaded: %s%s%s\n",
3266                        on, strna(i->load_state), off);
3267
3268         if (!strv_isempty(i->dropin_paths)) {
3269                 _cleanup_free_ char *dir = NULL;
3270                 bool last = false;
3271                 char ** dropin;
3272
3273                 STRV_FOREACH(dropin, i->dropin_paths) {
3274                         if (! dir || last) {
3275                                 printf(dir ? "        " : "  Drop-In: ");
3276
3277                                 free(dir);
3278                                 dir = NULL;
3279
3280                                 if (path_get_parent(*dropin, &dir) < 0) {
3281                                         log_oom();
3282                                         return;
3283                                 }
3284
3285                                 printf("%s\n           %s", dir,
3286                                        draw_special_char(DRAW_TREE_RIGHT));
3287                         }
3288
3289                         last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
3290
3291                         printf("%s%s", basename(*dropin), last ? "\n" : ", ");
3292                 }
3293         }
3294
3295         ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
3296         if (ss)
3297                 printf("   Active: %s%s (%s)%s",
3298                        active_on, strna(i->active_state), ss, active_off);
3299         else
3300                 printf("   Active: %s%s%s",
3301                        active_on, strna(i->active_state), active_off);
3302
3303         if (!isempty(i->result) && !streq(i->result, "success"))
3304                 printf(" (Result: %s)", i->result);
3305
3306         timestamp = (streq_ptr(i->active_state, "active")      ||
3307                      streq_ptr(i->active_state, "reloading"))   ? i->active_enter_timestamp :
3308                     (streq_ptr(i->active_state, "inactive")    ||
3309                      streq_ptr(i->active_state, "failed"))      ? i->inactive_enter_timestamp :
3310                     streq_ptr(i->active_state, "activating")    ? i->inactive_exit_timestamp :
3311                                                                   i->active_exit_timestamp;
3312
3313         s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
3314         s2 = format_timestamp(since2, sizeof(since2), timestamp);
3315
3316         if (s1)
3317                 printf(" since %s; %s\n", s2, s1);
3318         else if (s2)
3319                 printf(" since %s\n", s2);
3320         else
3321                 printf("\n");
3322
3323         if (!i->condition_result && i->condition_timestamp > 0) {
3324                 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
3325                 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
3326
3327                 printf("           start condition failed at %s%s%s\n",
3328                        s2, s1 ? "; " : "", s1 ? s1 : "");
3329                 if (i->failed_condition_trigger)
3330                         printf("           none of the trigger conditions were met\n");
3331                 else if (i->failed_condition)
3332                         printf("           %s=%s%s was not met\n",
3333                                i->failed_condition,
3334                                i->failed_condition_negate ? "!" : "",
3335                                i->failed_condition_param);
3336         }
3337
3338         if (i->sysfs_path)
3339                 printf("   Device: %s\n", i->sysfs_path);
3340         if (i->where)
3341                 printf("    Where: %s\n", i->where);
3342         if (i->what)
3343                 printf("     What: %s\n", i->what);
3344
3345         STRV_FOREACH(t, i->documentation)
3346                 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
3347
3348         STRV_FOREACH_PAIR(t, t2, i->listen)
3349                 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
3350
3351         if (i->accept)
3352                 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
3353
3354         LIST_FOREACH(exec, p, i->exec) {
3355                 _cleanup_free_ char *argv = NULL;
3356                 bool good;
3357
3358                 /* Only show exited processes here */
3359                 if (p->code == 0)
3360                         continue;
3361
3362                 argv = strv_join(p->argv, " ");
3363                 printf("  Process: %u %s=%s ", p->pid, p->name, strna(argv));
3364
3365                 good = is_clean_exit_lsb(p->code, p->status, NULL);
3366                 if (!good) {
3367                         on = ansi_highlight_red();
3368                         off = ansi_highlight_off();
3369                 } else
3370                         on = off = "";
3371
3372                 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
3373
3374                 if (p->code == CLD_EXITED) {
3375                         const char *c;
3376
3377                         printf("status=%i", p->status);
3378
3379                         c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
3380                         if (c)
3381                                 printf("/%s", c);
3382
3383                 } else
3384                         printf("signal=%s", signal_to_string(p->status));
3385
3386                 printf(")%s\n", off);
3387
3388                 if (i->main_pid == p->pid &&
3389                     i->start_timestamp == p->start_timestamp &&
3390                     i->exit_timestamp == p->start_timestamp)
3391                         /* Let's not show this twice */
3392                         i->main_pid = 0;
3393
3394                 if (p->pid == i->control_pid)
3395                         i->control_pid = 0;
3396         }
3397
3398         if (i->main_pid > 0 || i->control_pid > 0) {
3399                 if (i->main_pid > 0) {
3400                         printf(" Main PID: %u", (unsigned) i->main_pid);
3401
3402                         if (i->running) {
3403                                 _cleanup_free_ char *comm = NULL;
3404                                 get_process_comm(i->main_pid, &comm);
3405                                 if (comm)
3406                                         printf(" (%s)", comm);
3407                         } else if (i->exit_code > 0) {
3408                                 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
3409
3410                                 if (i->exit_code == CLD_EXITED) {
3411                                         const char *c;
3412
3413                                         printf("status=%i", i->exit_status);
3414
3415                                         c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
3416                                         if (c)
3417                                                 printf("/%s", c);
3418
3419                                 } else
3420                                         printf("signal=%s", signal_to_string(i->exit_status));
3421                                 printf(")");
3422                         }
3423
3424                         if (i->control_pid > 0)
3425                                 printf(";");
3426                 }
3427
3428                 if (i->control_pid > 0) {
3429                         _cleanup_free_ char *c = NULL;
3430
3431                         printf(" %8s: %u", i->main_pid ? "" : " Control", (unsigned) i->control_pid);
3432
3433                         get_process_comm(i->control_pid, &c);
3434                         if (c)
3435                                 printf(" (%s)", c);
3436                 }
3437
3438                 printf("\n");
3439         }
3440
3441         if (i->status_text)
3442                 printf("   Status: \"%s\"\n", i->status_text);
3443
3444         if (i->control_group &&
3445             (i->main_pid > 0 || i->control_pid > 0 ||
3446              ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_CONTAINER) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) {
3447                 unsigned c;
3448
3449                 printf("   CGroup: %s\n", i->control_group);
3450
3451                 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
3452                         unsigned k = 0;
3453                         pid_t extra[2];
3454                         static const char prefix[] = "           ";
3455
3456                         c = columns();
3457                         if (c > sizeof(prefix) - 1)
3458                                 c -= sizeof(prefix) - 1;
3459                         else
3460                                 c = 0;
3461
3462                         if (i->main_pid > 0)
3463                                 extra[k++] = i->main_pid;
3464
3465                         if (i->control_pid > 0)
3466                                 extra[k++] = i->control_pid;
3467
3468                         show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, false, extra, k, flags);
3469                 }
3470         }
3471
3472         if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) {
3473                 show_journal_by_unit(stdout,
3474                                      i->id,
3475                                      arg_output,
3476                                      0,
3477                                      i->inactive_exit_timestamp_monotonic,
3478                                      arg_lines,
3479                                      getuid(),
3480                                      flags | OUTPUT_BEGIN_NEWLINE,
3481                                      arg_scope == UNIT_FILE_SYSTEM,
3482                                      ellipsized);
3483         }
3484
3485         if (i->need_daemon_reload)
3486                 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
3487                        ansi_highlight_red(),
3488                        ansi_highlight_off(),
3489                        arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
3490 }
3491
3492 static void show_unit_help(UnitStatusInfo *i) {
3493         char **p;
3494
3495         assert(i);
3496
3497         if (!i->documentation) {
3498                 log_info("Documentation for %s not known.", i->id);
3499                 return;
3500         }
3501
3502         STRV_FOREACH(p, i->documentation) {
3503
3504                 if (startswith(*p, "man:")) {
3505                         const char *args[4] = { "man", NULL, NULL, NULL };
3506                         _cleanup_free_ char *page = NULL, *section = NULL;
3507                         char *e = NULL;
3508                         pid_t pid;
3509                         size_t k;
3510
3511                         k = strlen(*p);
3512
3513                         if ((*p)[k-1] == ')')
3514                                 e = strrchr(*p, '(');
3515
3516                         if (e) {
3517                                 page = strndup((*p) + 4, e - *p - 4);
3518                                 section = strndup(e + 1, *p + k - e - 2);
3519                                 if (!page || !section) {
3520                                         log_oom();
3521                                         return;
3522                                 }
3523
3524                                 args[1] = section;
3525                                 args[2] = page;
3526                         } else
3527                                 args[1] = *p + 4;
3528
3529                         pid = fork();
3530                         if (pid < 0) {
3531                                 log_error("Failed to fork: %m");
3532                                 continue;
3533                         }
3534
3535                         if (pid == 0) {
3536                                 /* Child */
3537                                 execvp(args[0], (char**) args);
3538                                 log_error("Failed to execute man: %m");
3539                                 _exit(EXIT_FAILURE);
3540                         }
3541
3542                         wait_for_terminate(pid, NULL);
3543                 } else
3544                         log_info("Can't show: %s", *p);
3545         }
3546 }
3547
3548 static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) {
3549         int r;
3550
3551         assert(name);
3552         assert(m);
3553         assert(i);
3554
3555         switch (contents[0]) {
3556
3557         case SD_BUS_TYPE_STRING: {
3558                 const char *s;
3559
3560                 r = sd_bus_message_read(m, "s", &s);
3561                 if (r < 0)
3562                         return bus_log_parse_error(r);
3563
3564                 if (!isempty(s)) {
3565                         if (streq(name, "Id"))
3566                                 i->id = s;
3567                         else if (streq(name, "LoadState"))
3568                                 i->load_state = s;
3569                         else if (streq(name, "ActiveState"))
3570                                 i->active_state = s;
3571                         else if (streq(name, "SubState"))
3572                                 i->sub_state = s;
3573                         else if (streq(name, "Description"))
3574                                 i->description = s;
3575                         else if (streq(name, "FragmentPath"))
3576                                 i->fragment_path = s;
3577                         else if (streq(name, "SourcePath"))
3578                                 i->source_path = s;
3579 #ifndef NOLEGACY
3580                         else if (streq(name, "DefaultControlGroup")) {
3581                                 const char *e;
3582                                 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
3583                                 if (e)
3584                                         i->control_group = e;
3585                         }
3586 #endif
3587                         else if (streq(name, "ControlGroup"))
3588                                 i->control_group = s;
3589                         else if (streq(name, "StatusText"))
3590                                 i->status_text = s;
3591                         else if (streq(name, "PIDFile"))
3592                                 i->pid_file = s;
3593                         else if (streq(name, "SysFSPath"))
3594                                 i->sysfs_path = s;
3595                         else if (streq(name, "Where"))
3596                                 i->where = s;
3597                         else if (streq(name, "What"))
3598                                 i->what = s;
3599                         else if (streq(name, "Following"))
3600                                 i->following = s;
3601                         else if (streq(name, "UnitFileState"))
3602                                 i->unit_file_state = s;
3603                         else if (streq(name, "Result"))
3604                                 i->result = s;
3605                 }
3606
3607                 break;
3608         }
3609
3610         case SD_BUS_TYPE_BOOLEAN: {
3611                 int b;
3612
3613                 r = sd_bus_message_read(m, "b", &b);
3614                 if (r < 0)
3615                         return bus_log_parse_error(r);
3616
3617                 if (streq(name, "Accept"))
3618                         i->accept = b;
3619                 else if (streq(name, "NeedDaemonReload"))
3620                         i->need_daemon_reload = b;
3621                 else if (streq(name, "ConditionResult"))
3622                         i->condition_result = b;
3623
3624                 break;
3625         }
3626
3627         case SD_BUS_TYPE_UINT32: {
3628                 uint32_t u;
3629
3630                 r = sd_bus_message_read(m, "u", &u);
3631                 if (r < 0)
3632                         return bus_log_parse_error(r);
3633
3634                 if (streq(name, "MainPID")) {
3635                         if (u > 0) {
3636                                 i->main_pid = (pid_t) u;
3637                                 i->running = true;
3638                         }
3639                 } else if (streq(name, "ControlPID"))
3640                         i->control_pid = (pid_t) u;
3641                 else if (streq(name, "ExecMainPID")) {
3642                         if (u > 0)
3643                                 i->main_pid = (pid_t) u;
3644                 } else if (streq(name, "NAccepted"))
3645                         i->n_accepted = u;
3646                 else if (streq(name, "NConnections"))
3647                         i->n_connections = u;
3648
3649                 break;
3650         }
3651
3652         case SD_BUS_TYPE_INT32: {
3653                 int32_t j;
3654
3655                 r = sd_bus_message_read(m, "i", &j);
3656                 if (r < 0)
3657                         return bus_log_parse_error(r);
3658
3659                 if (streq(name, "ExecMainCode"))
3660                         i->exit_code = (int) j;
3661                 else if (streq(name, "ExecMainStatus"))
3662                         i->exit_status = (int) j;
3663
3664                 break;
3665         }
3666
3667         case SD_BUS_TYPE_UINT64: {
3668                 uint64_t u;
3669
3670                 r = sd_bus_message_read(m, "t", &u);
3671                 if (r < 0)
3672                         return bus_log_parse_error(r);
3673
3674                 if (streq(name, "ExecMainStartTimestamp"))
3675                         i->start_timestamp = (usec_t) u;
3676                 else if (streq(name, "ExecMainExitTimestamp"))
3677                         i->exit_timestamp = (usec_t) u;
3678                 else if (streq(name, "ActiveEnterTimestamp"))
3679                         i->active_enter_timestamp = (usec_t) u;
3680                 else if (streq(name, "InactiveEnterTimestamp"))
3681                         i->inactive_enter_timestamp = (usec_t) u;
3682                 else if (streq(name, "InactiveExitTimestamp"))
3683                         i->inactive_exit_timestamp = (usec_t) u;
3684                 else if (streq(name, "InactiveExitTimestampMonotonic"))
3685                         i->inactive_exit_timestamp_monotonic = (usec_t) u;
3686                 else if (streq(name, "ActiveExitTimestamp"))
3687                         i->active_exit_timestamp = (usec_t) u;
3688                 else if (streq(name, "ConditionTimestamp"))
3689                         i->condition_timestamp = (usec_t) u;
3690
3691                 break;
3692         }
3693
3694         case SD_BUS_TYPE_ARRAY:
3695
3696                 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3697                         _cleanup_free_ ExecStatusInfo *info = NULL;
3698
3699                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3700                         if (r < 0)
3701                                 return bus_log_parse_error(r);
3702
3703                         info = new0(ExecStatusInfo, 1);
3704                         if (!info)
3705                                 return log_oom();
3706
3707                         while ((r = exec_status_info_deserialize(m, info)) > 0) {
3708
3709                                 info->name = strdup(name);
3710                                 if (!info->name)
3711                                         log_oom();
3712
3713                                 LIST_PREPEND(exec, i->exec, info);
3714
3715                                 info = new0(ExecStatusInfo, 1);
3716                                 if (!info)
3717                                         log_oom();
3718                         }
3719
3720                         if (r < 0)
3721                                 return bus_log_parse_error(r);
3722
3723                         r = sd_bus_message_exit_container(m);
3724                         if (r < 0)
3725                                 return bus_log_parse_error(r);
3726
3727                         return 0;
3728
3729                 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3730                         const char *type, *path;
3731
3732                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3733                         if (r < 0)
3734                                 return bus_log_parse_error(r);
3735
3736                         while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
3737
3738                                 r = strv_extend(&i->listen, type);
3739                                 if (r < 0)
3740                                         return r;
3741
3742                                 r = strv_extend(&i->listen, path);
3743                                 if (r < 0)
3744                                         return r;
3745                         }
3746                         if (r < 0)
3747                                 return bus_log_parse_error(r);
3748
3749                         r = sd_bus_message_exit_container(m);
3750                         if (r < 0)
3751                                 return bus_log_parse_error(r);
3752
3753                         return 0;
3754
3755                 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "DropInPaths")) {
3756
3757                         r = sd_bus_message_read_strv(m, &i->dropin_paths);
3758                         if (r < 0)
3759                                 return bus_log_parse_error(r);
3760
3761                 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Documentation")) {
3762
3763                         r = sd_bus_message_read_strv(m, &i->documentation);
3764                         if (r < 0)
3765                                 return bus_log_parse_error(r);
3766
3767                 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Conditions")) {
3768                         const char *cond, *param;
3769                         int trigger, negate;
3770                         int32_t state;
3771
3772                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3773                         if (r < 0)
3774                                 return bus_log_parse_error(r);
3775
3776                         while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, &param, &state)) > 0) {
3777                                 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3778                                 if (state < 0 && (!trigger || !i->failed_condition)) {
3779                                         i->failed_condition = cond;
3780                                         i->failed_condition_trigger = trigger;
3781                                         i->failed_condition_negate = negate;
3782                                         i->failed_condition_param = param;
3783                                 }
3784                         }
3785                         if (r < 0)
3786                                 return bus_log_parse_error(r);
3787
3788                         r = sd_bus_message_exit_container(m);
3789                         if (r < 0)
3790                                 return bus_log_parse_error(r);
3791
3792                 } else
3793                         goto skip;
3794
3795                 break;
3796
3797         case SD_BUS_TYPE_STRUCT_BEGIN:
3798
3799                 if (streq(name, "LoadError")) {
3800                         const char *n, *message;
3801
3802                         r = sd_bus_message_read(m, "(ss)", &n, &message);
3803                         if (r < 0)
3804                                 return bus_log_parse_error(r);
3805
3806                         if (!isempty(message))
3807                                 i->load_error = message;
3808                 } else
3809                         goto skip;
3810
3811                 break;
3812
3813         default:
3814                 goto skip;
3815         }
3816
3817         return 0;
3818
3819 skip:
3820         r = sd_bus_message_skip(m, contents);
3821         if (r < 0)
3822                 return bus_log_parse_error(r);
3823
3824         return 0;
3825 }
3826
3827 static int print_property(const char *name, sd_bus_message *m, const char *contents) {
3828         int r;
3829
3830         assert(name);
3831         assert(m);
3832
3833         /* This is a low-level property printer, see
3834          * print_status_info() for the nicer output */
3835
3836         if (arg_properties && !strv_find(arg_properties, name)) {
3837                 /* skip what we didn't read */
3838                 r = sd_bus_message_skip(m, contents);
3839                 return r;
3840         }
3841
3842         switch (contents[0]) {
3843
3844         case SD_BUS_TYPE_STRUCT_BEGIN:
3845
3846                 if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
3847                         uint32_t u;
3848
3849                         r = sd_bus_message_read(m, "(uo)", &u, NULL);
3850                         if (r < 0)
3851                                 return bus_log_parse_error(r);
3852
3853                         if (u > 0)
3854                                 printf("%s=%u\n", name, (unsigned) u);
3855                         else if (arg_all)
3856                                 printf("%s=\n", name);
3857
3858                         return 0;
3859
3860                 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
3861                         const char *s;
3862
3863                         r = sd_bus_message_read(m, "(so)", &s, NULL);
3864                         if (r < 0)
3865                                 return bus_log_parse_error(r);
3866
3867                         if (arg_all || !isempty(s))
3868                                 printf("%s=%s\n", name, s);
3869
3870                         return 0;
3871
3872                 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
3873                         const char *a = NULL, *b = NULL;
3874
3875                         r = sd_bus_message_read(m, "(ss)", &a, &b);
3876                         if (r < 0)
3877                                 return bus_log_parse_error(r);
3878
3879                         if (arg_all || !isempty(a) || !isempty(b))
3880                                 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3881
3882                         return 0;
3883                 } else if (streq_ptr(name, "SystemCallFilter")) {
3884                         _cleanup_strv_free_ char **l = NULL;
3885                         int whitelist;
3886
3887                         r = sd_bus_message_enter_container(m, 'r', "bas");
3888                         if (r < 0)
3889                                 return bus_log_parse_error(r);
3890
3891                         r = sd_bus_message_read(m, "b", &whitelist);
3892                         if (r < 0)
3893                                 return bus_log_parse_error(r);
3894
3895                         r = sd_bus_message_read_strv(m, &l);
3896                         if (r < 0)
3897                                 return bus_log_parse_error(r);
3898
3899                         r = sd_bus_message_exit_container(m);
3900                         if (r < 0)
3901                                 return bus_log_parse_error(r);
3902
3903                         if (arg_all || whitelist || !strv_isempty(l)) {
3904                                 bool first = true;
3905                                 char **i;
3906
3907                                 fputs(name, stdout);
3908                                 fputc('=', stdout);
3909
3910                                 if (!whitelist)
3911                                         fputc('~', stdout);
3912
3913                                 STRV_FOREACH(i, l) {
3914                                         if (first)
3915                                                 first = false;
3916                                         else
3917                                                 fputc(' ', stdout);
3918
3919                                         fputs(*i, stdout);
3920                                 }
3921                                 fputc('\n', stdout);
3922                         }
3923
3924                         return 0;
3925                 }
3926
3927                 break;
3928
3929         case SD_BUS_TYPE_ARRAY:
3930
3931                 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
3932                         const char *path;
3933                         int ignore;
3934
3935                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)");
3936                         if (r < 0)
3937                                 return bus_log_parse_error(r);
3938
3939                         while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
3940                                 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3941
3942                         if (r < 0)
3943                                 return bus_log_parse_error(r);
3944
3945                         r = sd_bus_message_exit_container(m);
3946                         if (r < 0)
3947                                 return bus_log_parse_error(r);
3948
3949                         return 0;
3950
3951                 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
3952                         const char *type, *path;
3953
3954                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3955                         if (r < 0)
3956                                 return bus_log_parse_error(r);
3957
3958                         while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
3959                                 printf("%s=%s\n", type, path);
3960                         if (r < 0)
3961                                 return bus_log_parse_error(r);
3962
3963                         r = sd_bus_message_exit_container(m);
3964                         if (r < 0)
3965                                 return bus_log_parse_error(r);
3966
3967                         return 0;
3968
3969                 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3970                         const char *type, *path;
3971
3972                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3973                         if (r < 0)
3974                                 return bus_log_parse_error(r);
3975
3976                         while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
3977                                 printf("Listen%s=%s\n", type, path);
3978                         if (r < 0)
3979                                 return bus_log_parse_error(r);
3980
3981                         r = sd_bus_message_exit_container(m);
3982                         if (r < 0)
3983                                 return bus_log_parse_error(r);
3984
3985                         return 0;
3986
3987                 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Timers")) {
3988                         const char *base;
3989                         uint64_t value, next_elapse;
3990
3991                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
3992                         if (r < 0)
3993                                 return bus_log_parse_error(r);
3994
3995                         while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) {
3996                                 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3997
3998                                 printf("%s={ value=%s ; next_elapse=%s }\n",
3999                                        base,
4000                                        format_timespan(timespan1, sizeof(timespan1), value, 0),
4001                                        format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
4002                         }
4003                         if (r < 0)
4004                                 return bus_log_parse_error(r);
4005
4006                         r = sd_bus_message_exit_container(m);
4007                         if (r < 0)
4008                                 return bus_log_parse_error(r);
4009
4010                         return 0;
4011
4012                 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
4013                         ExecStatusInfo info = {};
4014
4015                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
4016                         if (r < 0)
4017                                 return bus_log_parse_error(r);
4018
4019                         while ((r = exec_status_info_deserialize(m, &info)) > 0) {
4020                                 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
4021                                 _cleanup_free_ char *tt;
4022
4023                                 tt = strv_join(info.argv, " ");
4024
4025                                 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
4026                                        name,
4027                                        strna(info.path),
4028                                        strna(tt),
4029                                        yes_no(info.ignore),
4030                                        strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
4031                                        strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
4032                                        (unsigned) info. pid,
4033                                        sigchld_code_to_string(info.code),
4034                                        info.status,
4035                                        info.code == CLD_EXITED ? "" : "/",
4036                                        strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
4037
4038                                 free(info.path);
4039                                 strv_free(info.argv);
4040                                 zero(info);
4041                         }
4042
4043                         r = sd_bus_message_exit_container(m);
4044                         if (r < 0)
4045                                 return bus_log_parse_error(r);
4046
4047                         return 0;
4048
4049                 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
4050                         const char *path, *rwm;
4051
4052                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4053                         if (r < 0)
4054                                 return bus_log_parse_error(r);
4055
4056                         while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
4057                                 printf("%s=%s %s\n", name, strna(path), strna(rwm));
4058                         if (r < 0)
4059                                 return bus_log_parse_error(r);
4060
4061                         r = sd_bus_message_exit_container(m);
4062                         if (r < 0)
4063                                 return bus_log_parse_error(r);
4064
4065                         return 0;
4066
4067                 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "BlockIODeviceWeight")) {
4068                         const char *path;
4069                         uint64_t weight;
4070
4071                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4072                         if (r < 0)
4073                                 return bus_log_parse_error(r);
4074
4075                         while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
4076                                 printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
4077                         if (r < 0)
4078                                 return bus_log_parse_error(r);
4079
4080                         r = sd_bus_message_exit_container(m);
4081                         if (r < 0)
4082                                 return bus_log_parse_error(r);
4083
4084                         return 0;
4085
4086                 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
4087                         const char *path;
4088                         uint64_t bandwidth;
4089
4090                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4091                         if (r < 0)
4092                                 return bus_log_parse_error(r);
4093
4094                         while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
4095                                 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
4096                         if (r < 0)
4097                                 return bus_log_parse_error(r);
4098
4099                         r = sd_bus_message_exit_container(m);
4100                         if (r < 0)
4101                                 return bus_log_parse_error(r);
4102
4103                         return 0;
4104                 }
4105
4106                 break;
4107         }
4108
4109         r = bus_print_property(name, m, arg_all);
4110         if (r < 0)
4111                 return bus_log_parse_error(r);
4112
4113         if (r == 0) {
4114                 r = sd_bus_message_skip(m, contents);
4115                 if (r < 0)
4116                         return bus_log_parse_error(r);
4117
4118                 if (arg_all)
4119                         printf("%s=[unprintable]\n", name);
4120         }
4121
4122         return 0;
4123 }
4124
4125 static int show_one(
4126                 const char *verb,
4127                 sd_bus *bus,
4128                 const char *path,
4129                 bool show_properties,
4130                 bool *new_line,
4131                 bool *ellipsized) {
4132
4133         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4134         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4135         UnitStatusInfo info = {};
4136         ExecStatusInfo *p;
4137         int r;
4138
4139         assert(path);
4140         assert(new_line);
4141
4142         log_debug("Showing one %s", path);
4143
4144         r = sd_bus_call_method(
4145                         bus,
4146                         "org.freedesktop.systemd1",
4147                         path,
4148                         "org.freedesktop.DBus.Properties",
4149                         "GetAll",
4150                         &error,
4151                         &reply,
4152                         "s", "");
4153         if (r < 0) {
4154                 log_error("Failed to get properties: %s", bus_error_message(&error, r));
4155                 return r;
4156         }
4157
4158         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
4159         if (r < 0)
4160                 return bus_log_parse_error(r);
4161
4162         if (*new_line)
4163                 printf("\n");
4164
4165         *new_line = true;
4166
4167         while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
4168                 const char *name, *contents;
4169
4170                 r = sd_bus_message_read(reply, "s", &name);
4171                 if (r < 0)
4172                         return bus_log_parse_error(r);
4173
4174                 r = sd_bus_message_peek_type(reply, NULL, &contents);
4175                 if (r < 0)
4176                         return bus_log_parse_error(r);
4177
4178                 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
4179                 if (r < 0)
4180                         return bus_log_parse_error(r);
4181
4182                 if (show_properties)
4183                         r = print_property(name, reply, contents);
4184                 else
4185                         r = status_property(name, reply, &info, contents);
4186                 if (r < 0)
4187                         return r;
4188
4189                 r = sd_bus_message_exit_container(reply);
4190                 if (r < 0)
4191                         return bus_log_parse_error(r);
4192
4193                 r = sd_bus_message_exit_container(reply);
4194                 if (r < 0)
4195                         return bus_log_parse_error(r);
4196         }
4197         if (r < 0)
4198                 return bus_log_parse_error(r);
4199
4200         r = sd_bus_message_exit_container(reply);
4201         if (r < 0)
4202                 return bus_log_parse_error(r);
4203
4204         r = 0;
4205
4206         if (!show_properties) {
4207                 if (streq(verb, "help"))
4208                         show_unit_help(&info);
4209                 else
4210                         print_status_info(&info, ellipsized);
4211         }
4212
4213         strv_free(info.documentation);
4214         strv_free(info.dropin_paths);
4215         strv_free(info.listen);
4216
4217         if (!streq_ptr(info.active_state, "active") &&
4218             !streq_ptr(info.active_state, "reloading") &&
4219             streq(verb, "status")) {
4220                 /* According to LSB: "program not running" */
4221                 /* 0: program is running or service is OK
4222                  * 1: program is dead and /run PID file exists
4223                  * 2: program is dead and /run/lock lock file exists
4224                  * 3: program is not running
4225                  * 4: program or service status is unknown
4226                  */
4227                 if (info.pid_file && access(info.pid_file, F_OK) == 0)
4228                         r = 1;
4229                 else
4230                         r = 3;
4231         }
4232
4233         while ((p = info.exec)) {
4234                 LIST_REMOVE(exec, info.exec, p);
4235                 exec_status_info_free(p);
4236         }
4237
4238         return r;
4239 }
4240
4241 static int get_unit_dbus_path_by_pid(
4242                 sd_bus *bus,
4243                 uint32_t pid,
4244                 char **unit) {
4245
4246         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4247         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4248         char *u;
4249         int r;
4250
4251         r = sd_bus_call_method(
4252                         bus,
4253                         "org.freedesktop.systemd1",
4254                         "/org/freedesktop/systemd1",
4255                         "org.freedesktop.systemd1.Manager",
4256                         "GetUnitByPID",
4257                         &error,
4258                         &reply,
4259                         "u", pid);
4260         if (r < 0) {
4261                 log_error("Failed to get unit for PID %lu: %s", (unsigned long) pid, bus_error_message(&error, r));
4262                 return r;
4263         }
4264
4265         r = sd_bus_message_read(reply, "o", &u);
4266         if (r < 0)
4267                 return bus_log_parse_error(r);
4268
4269         u = strdup(u);
4270         if (!u)
4271                 return log_oom();
4272
4273         *unit = u;
4274         return 0;
4275 }
4276
4277 static int show_all(
4278                 const char* verb,
4279                 sd_bus *bus,
4280                 bool show_properties,
4281                 bool *new_line,
4282                 bool *ellipsized) {
4283
4284         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4285         _cleanup_free_ UnitInfo *unit_infos = NULL;
4286         const UnitInfo *u;
4287         unsigned c;
4288         int r, ret = 0;
4289
4290         r = get_unit_list(bus, NULL, NULL, &unit_infos, 0, &reply);
4291         if (r < 0)
4292                 return r;
4293
4294         pager_open_if_enabled();
4295
4296         c = (unsigned) r;
4297
4298         qsort_safe(unit_infos, c, sizeof(UnitInfo), compare_unit_info);
4299
4300         for (u = unit_infos; u < unit_infos + c; u++) {
4301                 _cleanup_free_ char *p = NULL;
4302
4303                 p = unit_dbus_path_from_name(u->id);
4304                 if (!p)
4305                         return log_oom();
4306
4307                 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
4308                 if (r < 0)
4309                         return r;
4310                 else if (r > 0 && ret == 0)
4311                         ret = r;
4312         }
4313
4314         return ret;
4315 }
4316
4317 static int show_system_status(sd_bus *bus) {
4318         char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
4319         _cleanup_free_ char *hn = NULL;
4320         struct machine_info mi = {};
4321         const char *on, *off;
4322         int r;
4323
4324         hn = gethostname_malloc();
4325         if (!hn)
4326                 return log_oom();
4327
4328         r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &mi);
4329         if (r < 0) {
4330                 log_error("Failed to read server status: %s", strerror(-r));
4331                 return r;
4332         }
4333
4334         if (streq_ptr(mi.state, "degraded")) {
4335                 on = ansi_highlight_red();
4336                 off = ansi_highlight_off();
4337         } else if (!streq_ptr(mi.state, "running")) {
4338                 on = ansi_highlight_yellow();
4339                 off = ansi_highlight_off();
4340         } else
4341                 on = off = "";
4342
4343         printf("%s%s%s %s\n", on, draw_special_char(DRAW_BLACK_CIRCLE), off, arg_host ? arg_host : hn);
4344
4345         printf("    State: %s%s%s\n",
4346                on, strna(mi.state), off);
4347
4348         printf("     Jobs: %u queued\n", mi.n_jobs);
4349         printf("   Failed: %u units\n", mi.n_failed_units);
4350
4351         printf("    Since: %s; %s\n",
4352                format_timestamp(since2, sizeof(since2), mi.timestamp),
4353                format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
4354
4355         printf("   CGroup: %s\n", mi.control_group ?: "/");
4356         if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
4357                 int flags =
4358                         arg_all * OUTPUT_SHOW_ALL |
4359                         (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
4360                         on_tty() * OUTPUT_COLOR |
4361                         !arg_quiet * OUTPUT_WARN_CUTOFF |
4362                         arg_full * OUTPUT_FULL_WIDTH;
4363
4364                 static const char prefix[] = "           ";
4365                 unsigned c;
4366
4367                 c = columns();
4368                 if (c > sizeof(prefix) - 1)
4369                         c -= sizeof(prefix) - 1;
4370                 else
4371                         c = 0;
4372
4373                 show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, flags);
4374         }
4375
4376         free(mi.state);
4377         free(mi.control_group);
4378
4379         return 0;
4380 }
4381
4382 static int show(sd_bus *bus, char **args) {
4383         bool show_properties, show_status, new_line = false;
4384         bool ellipsized = false;
4385         int r, ret = 0;
4386
4387         assert(bus);
4388         assert(args);
4389
4390         show_properties = streq(args[0], "show");
4391         show_status = streq(args[0], "status");
4392
4393         if (show_properties)
4394                 pager_open_if_enabled();
4395
4396         /* If no argument is specified inspect the manager itself */
4397
4398         if (show_properties && strv_length(args) <= 1)
4399                 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
4400
4401         if (show_status && strv_length(args) <= 1) {
4402
4403                 pager_open_if_enabled();
4404                 show_system_status(bus);
4405                 new_line = true;
4406
4407                 if (arg_all)
4408                         ret = show_all(args[0], bus, false, &new_line, &ellipsized);
4409         } else {
4410                 _cleanup_free_ char **patterns = NULL;
4411                 char **name;
4412
4413                 STRV_FOREACH(name, args + 1) {
4414                         _cleanup_free_ char *unit = NULL;
4415                         uint32_t id;
4416
4417                         if (safe_atou32(*name, &id) < 0) {
4418                                 if (strv_push(&patterns, *name) < 0)
4419                                         return log_oom();
4420
4421                                 continue;
4422                         } else if (show_properties) {
4423                                 /* Interpret as job id */
4424                                 if (asprintf(&unit, "/org/freedesktop/systemd1/job/%u", id) < 0)
4425                                         return log_oom();
4426
4427                         } else {
4428                                 /* Interpret as PID */
4429                                 r = get_unit_dbus_path_by_pid(bus, id, &unit);
4430                                 if (r < 0) {
4431                                         ret = r;
4432                                         continue;
4433                                 }
4434                         }
4435
4436                         r = show_one(args[0], bus, unit, show_properties,
4437                                      &new_line, &ellipsized);
4438                         if (r < 0)
4439                                 return r;
4440                         else if (r > 0 && ret == 0)
4441                                 ret = r;
4442                 }
4443
4444                 if (!strv_isempty(patterns)) {
4445                         _cleanup_strv_free_ char **names = NULL;
4446
4447                         r = expand_names(bus, patterns, NULL, &names);
4448                         if (r < 0)
4449                                 log_error("Failed to expand names: %s", strerror(-r));
4450
4451                         STRV_FOREACH(name, names) {
4452                                 _cleanup_free_ char *unit;
4453
4454                                 unit = unit_dbus_path_from_name(*name);
4455                                 if (!unit)
4456                                         return log_oom();
4457
4458                                 r = show_one(args[0], bus, unit, show_properties,
4459                                              &new_line, &ellipsized);
4460                                 if (r < 0)
4461                                         return r;
4462                                 else if (r > 0 && ret == 0)
4463                                         ret = r;
4464                         }
4465                 }
4466         }
4467
4468         if (ellipsized && !arg_quiet)
4469                 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4470
4471         return ret;
4472 }
4473
4474 static int cat(sd_bus *bus, char **args) {
4475         _cleanup_free_ char *unit = NULL;
4476         _cleanup_strv_free_ char **names = NULL;
4477         char **name;
4478         bool first = true;
4479         int r = 0;
4480
4481         assert(bus);
4482         assert(args);
4483
4484         r = expand_names(bus, args + 1, NULL, &names);
4485         if (r < 0)
4486                 log_error("Failed to expand names: %s", strerror(-r));
4487
4488         pager_open_if_enabled();
4489
4490         STRV_FOREACH(name, names) {
4491                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4492                 _cleanup_strv_free_ char **dropin_paths = NULL;
4493                 _cleanup_free_ char *fragment_path = NULL;
4494                 char **path;
4495
4496                 unit = unit_dbus_path_from_name(*name);
4497                 if (!unit)
4498                         return log_oom();
4499
4500                 if (need_daemon_reload(bus, *name) > 0)
4501                         log_warning("Unit file of %s changed on disk. Run 'systemctl%s daemon-reload'.",
4502                                     *name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
4503
4504                 r = sd_bus_get_property_string(
4505                                 bus,
4506                                 "org.freedesktop.systemd1",
4507                                 unit,
4508                                 "org.freedesktop.systemd1.Unit",
4509                                 "FragmentPath",
4510                                 &error,
4511                                 &fragment_path);
4512                 if (r < 0) {
4513                         log_warning("Failed to get FragmentPath: %s", bus_error_message(&error, r));
4514                         continue;
4515                 }
4516
4517                 r = sd_bus_get_property_strv(
4518                                 bus,
4519                                 "org.freedesktop.systemd1",
4520                                 unit,
4521                                 "org.freedesktop.systemd1.Unit",
4522                                 "DropInPaths",
4523                                 &error,
4524                                 &dropin_paths);
4525                 if (r < 0) {
4526                         log_warning("Failed to get DropInPaths: %s", bus_error_message(&error, r));
4527                         continue;
4528                 }
4529
4530                 if (first)
4531                         first = false;
4532                 else
4533                         puts("");
4534
4535                 if (!isempty(fragment_path)) {
4536                         printf("%s# %s%s\n",
4537                                ansi_highlight_blue(),
4538                                fragment_path,
4539                                ansi_highlight_off());
4540                         fflush(stdout);
4541
4542                         r = sendfile_full(STDOUT_FILENO, fragment_path);
4543                         if (r < 0) {
4544                                 log_warning("Failed to cat %s: %s", fragment_path, strerror(-r));
4545                                 continue;
4546                         }
4547                 }
4548
4549                 STRV_FOREACH(path, dropin_paths) {
4550                         printf("%s%s# %s%s\n",
4551                                isempty(fragment_path) && path == dropin_paths ? "" : "\n",
4552                                ansi_highlight_blue(),
4553                                *path,
4554                                ansi_highlight_off());
4555                         fflush(stdout);
4556
4557                         r = sendfile_full(STDOUT_FILENO, *path);
4558                         if (r < 0) {
4559                                 log_warning("Failed to cat %s: %s", *path, strerror(-r));
4560                                 continue;
4561                         }
4562                 }
4563         }
4564
4565         return r < 0 ? r : 0;
4566 }
4567
4568 static int set_property(sd_bus *bus, char **args) {
4569         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4570         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4571         _cleanup_free_ char *n = NULL;
4572         char **i;
4573         int r;
4574
4575         r = sd_bus_message_new_method_call(
4576                         bus,
4577                         &m,
4578                         "org.freedesktop.systemd1",
4579                         "/org/freedesktop/systemd1",
4580                         "org.freedesktop.systemd1.Manager",
4581                         "SetUnitProperties");
4582         if (r < 0)
4583                 return bus_log_create_error(r);
4584
4585         n = unit_name_mangle(args[1], MANGLE_NOGLOB);
4586         if (!n)
4587                 return log_oom();
4588
4589         r = sd_bus_message_append(m, "sb", n, arg_runtime);
4590         if (r < 0)
4591                 return bus_log_create_error(r);
4592
4593         r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)");
4594         if (r < 0)
4595                 return bus_log_create_error(r);
4596
4597         STRV_FOREACH(i, args + 2) {
4598                 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
4599                 if (r < 0)
4600                         return bus_log_create_error(r);
4601
4602                 r = bus_append_unit_property_assignment(m, *i);
4603                 if (r < 0)
4604                         return r;
4605
4606                 r = sd_bus_message_close_container(m);
4607                 if (r < 0)
4608                         return bus_log_create_error(r);
4609         }
4610
4611         r = sd_bus_message_close_container(m);
4612         if (r < 0)
4613                 return bus_log_create_error(r);
4614
4615         r = sd_bus_call(bus, m, 0, &error, NULL);
4616         if (r < 0) {
4617                 log_error("Failed to set unit properties on %s: %s", n, bus_error_message(&error, r));
4618                 return r;
4619         }
4620
4621         return 0;
4622 }
4623
4624 static int snapshot(sd_bus *bus, char **args) {
4625         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4626         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4627         _cleanup_free_ char *n = NULL, *id = NULL;
4628         const char *path;
4629         int r;
4630
4631         if (strv_length(args) > 1)
4632                 n = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".snapshot");
4633         else
4634                 n = strdup("");
4635         if (!n)
4636                 return log_oom();
4637
4638         r = sd_bus_call_method(
4639                         bus,
4640                         "org.freedesktop.systemd1",
4641                         "/org/freedesktop/systemd1",
4642                         "org.freedesktop.systemd1.Manager",
4643                         "CreateSnapshot",
4644                         &error,
4645                         &reply,
4646                         "sb", n, false);
4647         if (r < 0) {
4648                 log_error("Failed to create snapshot: %s", bus_error_message(&error, r));
4649                 return r;
4650         }
4651
4652         r = sd_bus_message_read(reply, "o", &path);
4653         if (r < 0)
4654                 return bus_log_parse_error(r);
4655
4656         r = sd_bus_get_property_string(
4657                         bus,
4658                         "org.freedesktop.systemd1",
4659                         path,
4660                         "org.freedesktop.systemd1.Unit",
4661                         "Id",
4662                         &error,
4663                         &id);
4664         if (r < 0) {
4665                 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error, r));
4666                 return r;
4667         }
4668
4669         if (!arg_quiet)
4670                 puts(id);
4671
4672         return 0;
4673 }
4674
4675 static int delete_snapshot(sd_bus *bus, char **args) {
4676         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4677         _cleanup_strv_free_ char **names = NULL;
4678         char **name;
4679         int r, q;
4680
4681         assert(args);
4682
4683         r = expand_names(bus, args + 1, ".snapshot", &names);
4684         if (r < 0)
4685                 log_error("Failed to expand names: %s", strerror(-r));
4686
4687         STRV_FOREACH(name, names) {
4688                 q = sd_bus_call_method(
4689                                 bus,
4690                                 "org.freedesktop.systemd1",
4691                                 "/org/freedesktop/systemd1",
4692                                 "org.freedesktop.systemd1.Manager",
4693                                 "RemoveSnapshot",
4694                                 &error,
4695                                 NULL,
4696                                 "s", *name);
4697                 if (q < 0) {
4698                         log_error("Failed to remove snapshot %s: %s",
4699                                   *name, bus_error_message(&error, r));
4700                         if (r == 0)
4701                                 r = q;
4702                 }
4703         }
4704
4705         return r;
4706 }
4707
4708 static int daemon_reload(sd_bus *bus, char **args) {
4709         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4710         const char *method;
4711         int r;
4712
4713         if (arg_action == ACTION_RELOAD)
4714                 method = "Reload";
4715         else if (arg_action == ACTION_REEXEC)
4716                 method = "Reexecute";
4717         else {
4718                 assert(arg_action == ACTION_SYSTEMCTL);
4719
4720                 method =
4721                         streq(args[0], "clear-jobs")    ||
4722                         streq(args[0], "cancel")        ? "ClearJobs" :
4723                         streq(args[0], "daemon-reexec") ? "Reexecute" :
4724                         streq(args[0], "reset-failed")  ? "ResetFailed" :
4725                         streq(args[0], "halt")          ? "Halt" :
4726                         streq(args[0], "poweroff")      ? "PowerOff" :
4727                         streq(args[0], "reboot")        ? "Reboot" :
4728                         streq(args[0], "kexec")         ? "KExec" :
4729                         streq(args[0], "exit")          ? "Exit" :
4730                                     /* "daemon-reload" */ "Reload";
4731         }
4732
4733         r = sd_bus_call_method(
4734                         bus,
4735                         "org.freedesktop.systemd1",
4736                         "/org/freedesktop/systemd1",
4737                         "org.freedesktop.systemd1.Manager",
4738                         method,
4739                         &error,
4740                         NULL,
4741                         NULL);
4742
4743         if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
4744                 /* There's always a fallback possible for
4745                  * legacy actions. */
4746                 r = -EADDRNOTAVAIL;
4747         else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
4748                 /* On reexecution, we expect a disconnect, not a
4749                  * reply */
4750                 r = 0;
4751         else if (r < 0)
4752                 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
4753
4754         return r < 0 ? r : 0;
4755 }
4756
4757 static int reset_failed(sd_bus *bus, char **args) {
4758         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4759         _cleanup_strv_free_ char **names = NULL;
4760         char **name;
4761         int r, q;
4762
4763         if (strv_length(args) <= 1)
4764                 return daemon_reload(bus, args);
4765
4766         r = expand_names(bus, args + 1, NULL, &names);
4767         if (r < 0)
4768                 log_error("Failed to expand names: %s", strerror(-r));
4769
4770         STRV_FOREACH(name, names) {
4771                 q = sd_bus_call_method(
4772                                 bus,
4773                                 "org.freedesktop.systemd1",
4774                                 "/org/freedesktop/systemd1",
4775                                 "org.freedesktop.systemd1.Manager",
4776                                 "ResetFailedUnit",
4777                                 &error,
4778                                 NULL,
4779                                 "s", *name);
4780                 if (q < 0) {
4781                         log_error("Failed to reset failed state of unit %s: %s",
4782                                   *name, bus_error_message(&error, r));
4783                         if (r == 0)
4784                                 r = q;
4785                 }
4786         }
4787
4788         return r;
4789 }
4790
4791 static int show_environment(sd_bus *bus, char **args) {
4792         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4793         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4794         const char *text;
4795         int r;
4796
4797         pager_open_if_enabled();
4798
4799         r = sd_bus_get_property(
4800                         bus,
4801                         "org.freedesktop.systemd1",
4802                         "/org/freedesktop/systemd1",
4803                         "org.freedesktop.systemd1.Manager",
4804                         "Environment",
4805                         &error,
4806                         &reply,
4807                         "as");
4808         if (r < 0) {
4809                 log_error("Failed to get environment: %s", bus_error_message(&error, r));
4810                 return r;
4811         }
4812
4813         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
4814         if (r < 0)
4815                 return bus_log_parse_error(r);
4816
4817         while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0)
4818                 puts(text);
4819         if (r < 0)
4820                 return bus_log_parse_error(r);
4821
4822         r = sd_bus_message_exit_container(reply);
4823         if (r < 0)
4824                 return bus_log_parse_error(r);
4825
4826         return 0;
4827 }
4828
4829 static int switch_root(sd_bus *bus, char **args) {
4830         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4831         _cleanup_free_ char *cmdline_init = NULL;
4832         const char *root, *init;
4833         unsigned l;
4834         int r;
4835
4836         l = strv_length(args);
4837         if (l < 2 || l > 3) {
4838                 log_error("Wrong number of arguments.");
4839                 return -EINVAL;
4840         }
4841
4842         root = args[1];
4843
4844         if (l >= 3)
4845                 init = args[2];
4846         else {
4847                 r = parse_env_file("/proc/cmdline", WHITESPACE,
4848                                    "init", &cmdline_init,
4849                                    NULL);
4850                 if (r < 0)
4851                         log_debug("Failed to parse /proc/cmdline: %s", strerror(-r));
4852
4853                 init = cmdline_init;
4854         }
4855
4856         if (isempty(init))
4857                 init = NULL;
4858
4859         if (init) {
4860                 const char *root_systemd_path = NULL, *root_init_path = NULL;
4861
4862                 root_systemd_path = strappenda(root, "/" SYSTEMD_BINARY_PATH);
4863                 root_init_path = strappenda3(root, "/", init);
4864
4865                 /* If the passed init is actually the same as the
4866                  * systemd binary, then let's suppress it. */
4867                 if (files_same(root_init_path, root_systemd_path) > 0)
4868                         init = NULL;
4869         }
4870
4871         log_debug("Switching root - root: %s; init: %s", root, strna(init));
4872
4873         r = sd_bus_call_method(
4874                         bus,
4875                         "org.freedesktop.systemd1",
4876                         "/org/freedesktop/systemd1",
4877                         "org.freedesktop.systemd1.Manager",
4878                         "SwitchRoot",
4879                         &error,
4880                         NULL,
4881                         "ss", root, init);
4882         if (r < 0) {
4883                 log_error("Failed to switch root: %s", bus_error_message(&error, r));
4884                 return r;
4885         }
4886
4887         return 0;
4888 }
4889
4890 static int set_environment(sd_bus *bus, char **args) {
4891         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4892         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4893         const char *method;
4894         int r;
4895
4896         assert(bus);
4897         assert(args);
4898
4899         method = streq(args[0], "set-environment")
4900                 ? "SetEnvironment"
4901                 : "UnsetEnvironment";
4902
4903         r = sd_bus_message_new_method_call(
4904                         bus,
4905                         &m,
4906                         "org.freedesktop.systemd1",
4907                         "/org/freedesktop/systemd1",
4908                         "org.freedesktop.systemd1.Manager",
4909                         method);
4910         if (r < 0)
4911                 return bus_log_create_error(r);
4912
4913         r = sd_bus_message_append_strv(m, args + 1);
4914         if (r < 0)
4915                 return bus_log_create_error(r);
4916
4917         r = sd_bus_call(bus, m, 0, &error, NULL);
4918         if (r < 0) {
4919                 log_error("Failed to set environment: %s", bus_error_message(&error, r));
4920                 return r;
4921         }
4922
4923         return 0;
4924 }
4925
4926 static int import_environment(sd_bus *bus, char **args) {
4927         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4928         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4929         int r;
4930
4931         assert(bus);
4932         assert(args);
4933
4934         r = sd_bus_message_new_method_call(
4935                         bus,
4936                         &m,
4937                         "org.freedesktop.systemd1",
4938                         "/org/freedesktop/systemd1",
4939                         "org.freedesktop.systemd1.Manager",
4940                         "SetEnvironment");
4941         if (r < 0)
4942                 return bus_log_create_error(r);
4943
4944         if (strv_isempty(args + 1))
4945                 r = sd_bus_message_append_strv(m, environ);
4946         else {
4947                 char **a, **b;
4948
4949                 r = sd_bus_message_open_container(m, 'a', "s");
4950                 if (r < 0)
4951                         return bus_log_create_error(r);
4952
4953                 STRV_FOREACH(a, args + 1) {
4954
4955                         if (!env_name_is_valid(*a)) {
4956                                 log_error("Not a valid environment variable name: %s", *a);
4957                                 return -EINVAL;
4958                         }
4959
4960                         STRV_FOREACH(b, environ) {
4961                                 const char *eq;
4962
4963                                 eq = startswith(*b, *a);
4964                                 if (eq && *eq == '=') {
4965
4966                                         r = sd_bus_message_append(m, "s", *b);
4967                                         if (r < 0)
4968                                                 return bus_log_create_error(r);
4969
4970                                         break;
4971                                 }
4972                         }
4973                 }
4974
4975                 r = sd_bus_message_close_container(m);
4976         }
4977         if (r < 0)
4978                 return bus_log_create_error(r);
4979
4980         r = sd_bus_call(bus, m, 0, &error, NULL);
4981         if (r < 0) {
4982                 log_error("Failed to import environment: %s", bus_error_message(&error, r));
4983                 return r;
4984         }
4985
4986         return 0;
4987 }
4988
4989 static int enable_sysv_units(const char *verb, char **args) {
4990         int r = 0;
4991
4992 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4993         unsigned f = 1, t = 1;
4994         _cleanup_lookup_paths_free_ LookupPaths paths = {};
4995
4996         if (arg_scope != UNIT_FILE_SYSTEM)
4997                 return 0;
4998
4999         if (!streq(verb, "enable") &&
5000             !streq(verb, "disable") &&
5001             !streq(verb, "is-enabled"))
5002                 return 0;
5003
5004         /* Processes all SysV units, and reshuffles the array so that
5005          * afterwards only the native units remain */
5006
5007         r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
5008         if (r < 0)
5009                 return r;
5010
5011         r = 0;
5012         for (f = 0; args[f]; f++) {
5013                 const char *name;
5014                 _cleanup_free_ char *p = NULL, *q = NULL;
5015                 bool found_native = false, found_sysv;
5016                 unsigned c = 1;
5017                 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
5018                 char **k, *l;
5019                 int j;
5020                 pid_t pid;
5021                 siginfo_t status;
5022
5023                 name = args[f];
5024
5025                 if (!endswith(name, ".service"))
5026                         continue;
5027
5028                 if (path_is_absolute(name))
5029                         continue;
5030
5031                 STRV_FOREACH(k, paths.unit_path) {
5032                         if (!isempty(arg_root))
5033                                 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
5034                         else
5035                                 asprintf(&p, "%s/%s", *k, name);
5036
5037                         if (!p) {
5038                                 r = log_oom();
5039                                 goto finish;
5040                         }
5041
5042                         found_native = access(p, F_OK) >= 0;
5043                         free(p);
5044                         p = NULL;
5045
5046                         if (found_native)
5047                                 break;
5048                 }
5049
5050                 if (found_native)
5051                         continue;
5052
5053                 if (!isempty(arg_root))
5054                         asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
5055                 else
5056                         asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
5057                 if (!p) {
5058                         r = log_oom();
5059                         goto finish;
5060                 }
5061
5062                 p[strlen(p) - sizeof(".service") + 1] = 0;
5063                 found_sysv = access(p, F_OK) >= 0;
5064
5065                 if (!found_sysv)
5066                         continue;
5067
5068                 /* Mark this entry, so that we don't try enabling it as native unit */
5069                 args[f] = (char*) "";
5070
5071                 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
5072
5073                 if (!isempty(arg_root))
5074                         argv[c++] = q = strappend("--root=", arg_root);
5075
5076                 argv[c++] = basename(p);
5077                 argv[c++] =
5078                         streq(verb, "enable") ? "on" :
5079                         streq(verb, "disable") ? "off" : "--level=5";
5080                 argv[c] = NULL;
5081
5082                 l = strv_join((char**)argv, " ");
5083                 if (!l) {
5084                         r = log_oom();
5085                         goto finish;
5086                 }
5087
5088                 log_info("Executing %s", l);
5089                 free(l);
5090
5091                 pid = fork();
5092                 if (pid < 0) {
5093                         log_error("Failed to fork: %m");
5094                         r = -errno;
5095                         goto finish;
5096                 } else if (pid == 0) {
5097                         /* Child */
5098
5099                         execv(argv[0], (char**) argv);
5100                         _exit(EXIT_FAILURE);
5101                 }
5102
5103                 j = wait_for_terminate(pid, &status);
5104                 if (j < 0) {
5105                         log_error("Failed to wait for child: %s", strerror(-r));
5106                         r = j;
5107                         goto finish;
5108                 }
5109
5110                 if (status.si_code == CLD_EXITED) {
5111                         if (streq(verb, "is-enabled")) {
5112                                 if (status.si_status == 0) {
5113                                         if (!arg_quiet)
5114                                                 puts("enabled");
5115                                         r = 1;
5116                                 } else {
5117                                         if (!arg_quiet)
5118                                                 puts("disabled");
5119                                 }
5120
5121                         } else if (status.si_status != 0) {
5122                                 r = -EINVAL;
5123                                 goto finish;
5124                         }
5125                 } else {
5126                         r = -EPROTO;
5127                         goto finish;
5128                 }
5129         }
5130
5131 finish:
5132         /* Drop all SysV units */
5133         for (f = 0, t = 0; args[f]; f++) {
5134
5135                 if (isempty(args[f]))
5136                         continue;
5137
5138                 args[t++] = args[f];
5139         }
5140
5141         args[t] = NULL;
5142
5143 #endif
5144         return r;
5145 }
5146
5147 static int mangle_names(char **original_names, char ***mangled_names) {
5148         char **i, **l, **name;
5149
5150         l = new(char*, strv_length(original_names) + 1);
5151         if (!l)
5152                 return log_oom();
5153
5154         i = l;
5155         STRV_FOREACH(name, original_names) {
5156
5157                 /* When enabling units qualified path names are OK,
5158                  * too, hence allow them explicitly. */
5159
5160                 if (is_path(*name))
5161                         *i = strdup(*name);
5162                 else
5163                         *i = unit_name_mangle(*name, MANGLE_NOGLOB);
5164
5165                 if (!*i) {
5166                         strv_free(l);
5167                         return log_oom();
5168                 }
5169
5170                 i++;
5171         }
5172
5173         *i = NULL;
5174         *mangled_names = l;
5175
5176         return 0;
5177 }
5178
5179 static int enable_unit(sd_bus *bus, char **args) {
5180         _cleanup_strv_free_ char **names = NULL;
5181         const char *verb = args[0];
5182         UnitFileChange *changes = NULL;
5183         unsigned n_changes = 0;
5184         int carries_install_info = -1;
5185         int r;
5186
5187         if (!args[1])
5188                 return 0;
5189
5190         r = mangle_names(args+1, &names);
5191         if (r < 0)
5192                 return r;
5193
5194         r = enable_sysv_units(verb, names);
5195         if (r < 0)
5196                 return r;
5197
5198         /* If the operation was fully executed by the SysV compat,
5199          * let's finish early */
5200         if (strv_isempty(names))
5201                 return 0;
5202
5203         if (!bus || avoid_bus()) {
5204                 if (streq(verb, "enable")) {
5205                         r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5206                         carries_install_info = r;
5207                 } else if (streq(verb, "disable"))
5208                         r = unit_file_disable(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5209                 else if (streq(verb, "reenable")) {
5210                         r = unit_file_reenable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5211                         carries_install_info = r;
5212                 } else if (streq(verb, "link"))
5213                         r = unit_file_link(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5214                 else if (streq(verb, "preset")) {
5215                         r = unit_file_preset(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5216                         carries_install_info = r;
5217                 } else if (streq(verb, "mask"))
5218                         r = unit_file_mask(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5219                 else if (streq(verb, "unmask"))
5220                         r = unit_file_unmask(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5221                 else
5222                         assert_not_reached("Unknown verb");
5223
5224                 if (r < 0) {
5225                         log_error("Operation failed: %s", strerror(-r));
5226                         goto finish;
5227                 }
5228
5229                 if (!arg_quiet)
5230                         dump_unit_file_changes(changes, n_changes);
5231
5232                 r = 0;
5233         } else {
5234                 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5235                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5236                 int expect_carries_install_info = false;
5237                 bool send_force = true;
5238                 const char *method;
5239
5240                 if (streq(verb, "enable")) {
5241                         method = "EnableUnitFiles";
5242                         expect_carries_install_info = true;
5243                 } else if (streq(verb, "disable")) {
5244                         method = "DisableUnitFiles";
5245                         send_force = false;
5246                 } else if (streq(verb, "reenable")) {
5247                         method = "ReenableUnitFiles";
5248                         expect_carries_install_info = true;
5249                 } else if (streq(verb, "link"))
5250                         method = "LinkUnitFiles";
5251                 else if (streq(verb, "preset")) {
5252                         method = "PresetUnitFiles";
5253                         expect_carries_install_info = true;
5254                 } else if (streq(verb, "mask"))
5255                         method = "MaskUnitFiles";
5256                 else if (streq(verb, "unmask")) {
5257                         method = "UnmaskUnitFiles";
5258                         send_force = false;
5259                 } else
5260                         assert_not_reached("Unknown verb");
5261
5262                 r = sd_bus_message_new_method_call(
5263                                 bus,
5264                                 &m,
5265                                 "org.freedesktop.systemd1",
5266                                 "/org/freedesktop/systemd1",
5267                                 "org.freedesktop.systemd1.Manager",
5268                                 method);
5269                 if (r < 0)
5270                         return bus_log_create_error(r);
5271
5272                 r = sd_bus_message_append_strv(m, names);
5273                 if (r < 0)
5274                         return bus_log_create_error(r);
5275
5276                 r = sd_bus_message_append(m, "b", arg_runtime);
5277                 if (r < 0)
5278                         return bus_log_create_error(r);
5279
5280                 if (send_force) {
5281                         r = sd_bus_message_append(m, "b", arg_force);
5282                         if (r < 0)
5283                                 return bus_log_create_error(r);
5284                 }
5285
5286                 r = sd_bus_call(bus, m, 0, &error, &reply);
5287                 if (r < 0) {
5288                         log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5289                         return r;
5290                 }
5291
5292                 if (expect_carries_install_info) {
5293                         r = sd_bus_message_read(reply, "b", &carries_install_info);
5294                         if (r < 0)
5295                                 return bus_log_parse_error(r);
5296                 }
5297
5298                 r = deserialize_and_dump_unit_file_changes(reply);
5299                 if (r < 0)
5300                         return r;
5301
5302                 /* Try to reload if enabled */
5303                 if (!arg_no_reload)
5304                         r = daemon_reload(bus, args);
5305                 else
5306                         r = 0;
5307         }
5308
5309         if (carries_install_info == 0)
5310                 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5311                             "using systemctl.\n"
5312                             "Possible reasons for having this kind of units are:\n"
5313                             "1) A unit may be statically enabled by being symlinked from another unit's\n"
5314                             "   .wants/ or .requires/ directory.\n"
5315                             "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5316                             "   a requirement dependency on it.\n"
5317                             "3) A unit may be started when needed via activation (socket, path, timer,\n"
5318                             "   D-Bus, udev, scripted systemctl call, ...).\n");
5319
5320 finish:
5321         unit_file_changes_free(changes, n_changes);
5322
5323         return r;
5324 }
5325
5326 static int unit_is_enabled(sd_bus *bus, char **args) {
5327
5328         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5329         _cleanup_strv_free_ char **names = NULL;
5330         bool enabled;
5331         char **name;
5332         int r;
5333
5334         r = mangle_names(args+1, &names);
5335         if (r < 0)
5336                 return r;
5337
5338         r = enable_sysv_units(args[0], names);
5339         if (r < 0)
5340                 return r;
5341
5342         enabled = r > 0;
5343
5344         if (!bus || avoid_bus()) {
5345
5346                 STRV_FOREACH(name, names) {
5347                         UnitFileState state;
5348
5349                         state = unit_file_get_state(arg_scope, arg_root, *name);
5350                         if (state < 0) {
5351                                 log_error("Failed to get unit file state for %s: %s", *name, strerror(-state));
5352                                 return state;
5353                         }
5354
5355                         if (state == UNIT_FILE_ENABLED ||
5356                             state == UNIT_FILE_ENABLED_RUNTIME ||
5357                             state == UNIT_FILE_STATIC)
5358                                 enabled = true;
5359
5360                         if (!arg_quiet)
5361                                 puts(unit_file_state_to_string(state));
5362                 }
5363
5364         } else {
5365                 STRV_FOREACH(name, names) {
5366                         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
5367                         const char *s;
5368
5369                         r = sd_bus_call_method(
5370                                         bus,
5371                                         "org.freedesktop.systemd1",
5372                                         "/org/freedesktop/systemd1",
5373                                         "org.freedesktop.systemd1.Manager",
5374                                         "GetUnitFileState",
5375                                         &error,
5376                                         &reply,
5377                                         "s", *name);
5378                         if (r < 0) {
5379                                 log_error("Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
5380                                 return r;
5381                         }
5382
5383                         r = sd_bus_message_read(reply, "s", &s);
5384                         if (r < 0)
5385                                 return bus_log_parse_error(r);
5386
5387                         if (streq(s, "enabled") ||
5388                             streq(s, "enabled-runtime") ||
5389                             streq(s, "static"))
5390                                 enabled = true;
5391
5392                         if (!arg_quiet)
5393                                 puts(s);
5394                 }
5395         }
5396
5397         return !enabled;
5398 }
5399
5400 static int systemctl_help(void) {
5401
5402         pager_open_if_enabled();
5403
5404         printf("%s [OPTIONS...] {COMMAND} ...\n\n"
5405                "Query or send control commands to the systemd manager.\n\n"
5406                "  -h --help           Show this help\n"
5407                "     --version        Show package version\n"
5408                "     --system         Connect to system manager\n"
5409                "     --user           Connect to user service manager\n"
5410                "  -H --host=[USER@]HOST\n"
5411                "                      Operate on remote host\n"
5412                "  -M --machine=CONTAINER\n"
5413                "                      Operate on local container\n"
5414                "  -t --type=TYPE      List only units of a particular type\n"
5415                "     --state=STATE    List only units with particular LOAD or SUB or ACTIVE state\n"
5416                "  -p --property=NAME  Show only properties by this name\n"
5417                "  -a --all            Show all loaded units/properties, including dead/empty\n"
5418                "                      ones. To list all units installed on the system, use\n"
5419                "                      the 'list-unit-files' command instead.\n"
5420                "  -l --full           Don't ellipsize unit names on output\n"
5421                "  -r --recursive      Show unit list of host and local containers\n"
5422                "     --reverse        Show reverse dependencies with 'list-dependencies'\n"
5423                "     --job-mode=MODE  Specify how to deal with already queued jobs, when\n"
5424                "                      queueing a new job\n"
5425                "     --show-types     When showing sockets, explicitly show their type\n"
5426                "  -i --ignore-inhibitors\n"
5427                "                      When shutting down or sleeping, ignore inhibitors\n"
5428                "     --kill-who=WHO   Who to send signal to\n"
5429                "  -s --signal=SIGNAL  Which signal to send\n"
5430                "  -q --quiet          Suppress output\n"
5431                "     --no-block       Do not wait until operation finished\n"
5432                "     --no-wall        Don't send wall message before halt/power-off/reboot\n"
5433                "     --no-reload      When enabling/disabling unit files, don't reload daemon\n"
5434                "                      configuration\n"
5435                "     --no-legend      Do not print a legend (column headers and hints)\n"
5436                "     --no-pager       Do not pipe output into a pager\n"
5437                "     --no-ask-password\n"
5438                "                      Do not ask for system passwords\n"
5439                "     --global         Enable/disable unit files globally\n"
5440                "     --runtime        Enable unit files only temporarily until next reboot\n"
5441                "  -f --force          When enabling unit files, override existing symlinks\n"
5442                "                      When shutting down, execute action immediately\n"
5443                "     --root=PATH      Enable unit files in the specified root directory\n"
5444                "  -n --lines=INTEGER  Number of journal entries to show\n"
5445                "  -o --output=STRING  Change journal output mode (short, short-monotonic,\n"
5446                "                      verbose, export, json, json-pretty, json-sse, cat)\n"
5447                "     --plain          Print unit dependencies as a list instead of a tree\n\n"
5448                "Unit Commands:\n"
5449                "  list-units [PATTERN...]         List loaded units\n"
5450                "  list-sockets [PATTERN...]       List loaded sockets ordered by address\n"
5451                "  list-timers [PATTERN...]        List loaded timers ordered by next elapse\n"
5452                "  start NAME...                   Start (activate) one or more units\n"
5453                "  stop NAME...                    Stop (deactivate) one or more units\n"
5454                "  reload NAME...                  Reload one or more units\n"
5455                "  restart NAME...                 Start or restart one or more units\n"
5456                "  try-restart NAME...             Restart one or more units if active\n"
5457                "  reload-or-restart NAME...       Reload one or more units if possible,\n"
5458                "                                  otherwise start or restart\n"
5459                "  reload-or-try-restart NAME...   Reload one or more units if possible,\n"
5460                "                                  otherwise restart if active\n"
5461                "  isolate NAME                    Start one unit and stop all others\n"
5462                "  kill NAME...                    Send signal to processes of a unit\n"
5463                "  is-active PATTERN...            Check whether units are active\n"
5464                "  is-failed PATTERN...            Check whether units are failed\n"
5465                "  status [PATTERN...|PID...]      Show runtime status of one or more units\n"
5466                "  show [PATTERN...|JOB...]        Show properties of one or more\n"
5467                "                                  units/jobs or the manager\n"
5468                "  cat PATTERN...                  Show files and drop-ins of one or more units\n"
5469                "  set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
5470                "  help PATTERN...|PID...          Show manual for one or more units\n"
5471                "  reset-failed [PATTERN...]       Reset failed state for all, one, or more\n"
5472                "                                  units\n"
5473                "  list-dependencies [NAME]        Recursively show units which are required\n"
5474                "                                  or wanted by this unit or by which this\n"
5475                "                                  unit is required or wanted\n\n"
5476                "Unit File Commands:\n"
5477                "  list-unit-files [PATTERN...]    List installed unit files\n"
5478                "  enable NAME...                  Enable one or more unit files\n"
5479                "  disable NAME...                 Disable one or more unit files\n"
5480                "  reenable NAME...                Reenable one or more unit files\n"
5481                "  preset NAME...                  Enable/disable one or more unit files\n"
5482                "                                  based on preset configuration\n"
5483                "  is-enabled NAME...              Check whether unit files are enabled\n\n"
5484                "  mask NAME...                    Mask one or more units\n"
5485                "  unmask NAME...                  Unmask one or more units\n"
5486                "  link PATH...                    Link one or more units files into\n"
5487                "                                  the search path\n"
5488                "  get-default                     Get the name of the default target\n"
5489                "  set-default NAME                Set the default target\n\n"
5490                "Machine Commands:\n"
5491                "  list-machines [PATTERN...]      List local containers and host\n\n"
5492                "Job Commands:\n"
5493                "  list-jobs [PATTERN...]          List jobs\n"
5494                "  cancel [JOB...]                 Cancel all, one, or more jobs\n\n"
5495                "Snapshot Commands:\n"
5496                "  snapshot [NAME]                 Create a snapshot\n"
5497                "  delete NAME...                  Remove one or more snapshots\n\n"
5498                "Environment Commands:\n"
5499                "  show-environment                Dump environment\n"
5500                "  set-environment NAME=VALUE...   Set one or more environment variables\n"
5501                "  unset-environment NAME...       Unset one or more environment variables\n"
5502                "  import-environment NAME...      Import all, one or more environment variables\n\n"
5503                "Manager Lifecycle Commands:\n"
5504                "  daemon-reload                   Reload systemd manager configuration\n"
5505                "  daemon-reexec                   Reexecute systemd manager\n\n"
5506                "System Commands:\n"
5507                "  default                         Enter system default mode\n"
5508                "  rescue                          Enter system rescue mode\n"
5509                "  emergency                       Enter system emergency mode\n"
5510                "  halt                            Shut down and halt the system\n"
5511                "  poweroff                        Shut down and power-off the system\n"
5512                "  reboot [ARG]                    Shut down and reboot the system\n"
5513                "  kexec                           Shut down and reboot the system with kexec\n"
5514                "  exit                            Request user instance exit\n"
5515                "  switch-root ROOT [INIT]         Change to a different root file system\n"
5516                "  suspend                         Suspend the system\n"
5517                "  hibernate                       Hibernate the system\n"
5518                "  hybrid-sleep                    Hibernate and suspend the system\n",
5519                program_invocation_short_name);
5520
5521         return 0;
5522 }
5523
5524 static int halt_help(void) {
5525
5526         printf("%s [OPTIONS...]%s\n\n"
5527                "%s the system.\n\n"
5528                "     --help      Show this help\n"
5529                "     --halt      Halt the machine\n"
5530                "  -p --poweroff  Switch off the machine\n"
5531                "     --reboot    Reboot the machine\n"
5532                "  -f --force     Force immediate halt/power-off/reboot\n"
5533                "  -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
5534                "  -d --no-wtmp   Don't write wtmp record\n"
5535                "     --no-wall   Don't send wall message before halt/power-off/reboot\n",
5536                program_invocation_short_name,
5537                arg_action == ACTION_REBOOT   ? " [ARG]" : "",
5538                arg_action == ACTION_REBOOT   ? "Reboot" :
5539                arg_action == ACTION_POWEROFF ? "Power off" :
5540                                                "Halt");
5541
5542         return 0;
5543 }
5544
5545 static int shutdown_help(void) {
5546
5547         printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
5548                "Shut down the system.\n\n"
5549                "     --help      Show this help\n"
5550                "  -H --halt      Halt the machine\n"
5551                "  -P --poweroff  Power-off the machine\n"
5552                "  -r --reboot    Reboot the machine\n"
5553                "  -h             Equivalent to --poweroff, overridden by --halt\n"
5554                "  -k             Don't halt/power-off/reboot, just send warnings\n"
5555                "     --no-wall   Don't send wall message before halt/power-off/reboot\n"
5556                "  -c             Cancel a pending shutdown\n",
5557                program_invocation_short_name);
5558
5559         return 0;
5560 }
5561
5562 static int telinit_help(void) {
5563
5564         printf("%s [OPTIONS...] {COMMAND}\n\n"
5565                "Send control commands to the init daemon.\n\n"
5566                "     --help      Show this help\n"
5567                "     --no-wall   Don't send wall message before halt/power-off/reboot\n\n"
5568                "Commands:\n"
5569                "  0              Power-off the machine\n"
5570                "  6              Reboot the machine\n"
5571                "  2, 3, 4, 5     Start runlevelX.target unit\n"
5572                "  1, s, S        Enter rescue mode\n"
5573                "  q, Q           Reload init daemon configuration\n"
5574                "  u, U           Reexecute init daemon\n",
5575                program_invocation_short_name);
5576
5577         return 0;
5578 }
5579
5580 static int runlevel_help(void) {
5581
5582         printf("%s [OPTIONS...]\n\n"
5583                "Prints the previous and current runlevel of the init system.\n\n"
5584                "     --help      Show this help\n",
5585                program_invocation_short_name);
5586
5587         return 0;
5588 }
5589
5590 static int help_types(void) {
5591         int i;
5592         const char *t;
5593
5594         puts("Available unit types:");
5595         for (i = 0; i < _UNIT_TYPE_MAX; i++) {
5596                 t = unit_type_to_string(i);
5597                 if (t)
5598                         puts(t);
5599         }
5600
5601         return 0;
5602 }
5603
5604 static int systemctl_parse_argv(int argc, char *argv[]) {
5605
5606         enum {
5607                 ARG_FAIL = 0x100,
5608                 ARG_REVERSE,
5609                 ARG_AFTER,
5610                 ARG_BEFORE,
5611                 ARG_SHOW_TYPES,
5612                 ARG_IRREVERSIBLE,
5613                 ARG_IGNORE_DEPENDENCIES,
5614                 ARG_VERSION,
5615                 ARG_USER,
5616                 ARG_SYSTEM,
5617                 ARG_GLOBAL,
5618                 ARG_NO_BLOCK,
5619                 ARG_NO_LEGEND,
5620                 ARG_NO_PAGER,
5621                 ARG_NO_WALL,
5622                 ARG_ROOT,
5623                 ARG_NO_RELOAD,
5624                 ARG_KILL_WHO,
5625                 ARG_NO_ASK_PASSWORD,
5626                 ARG_FAILED,
5627                 ARG_RUNTIME,
5628                 ARG_FORCE,
5629                 ARG_PLAIN,
5630                 ARG_STATE,
5631                 ARG_JOB_MODE
5632         };
5633
5634         static const struct option options[] = {
5635                 { "help",                no_argument,       NULL, 'h'                     },
5636                 { "version",             no_argument,       NULL, ARG_VERSION             },
5637                 { "type",                required_argument, NULL, 't'                     },
5638                 { "property",            required_argument, NULL, 'p'                     },
5639                 { "all",                 no_argument,       NULL, 'a'                     },
5640                 { "reverse",             no_argument,       NULL, ARG_REVERSE             },
5641                 { "after",               no_argument,       NULL, ARG_AFTER               },
5642                 { "before",              no_argument,       NULL, ARG_BEFORE              },
5643                 { "show-types",          no_argument,       NULL, ARG_SHOW_TYPES          },
5644                 { "failed",              no_argument,       NULL, ARG_FAILED              }, /* compatibility only */
5645                 { "full",                no_argument,       NULL, 'l'                     },
5646                 { "job-mode",            required_argument, NULL, ARG_JOB_MODE            },
5647                 { "fail",                no_argument,       NULL, ARG_FAIL                }, /* compatibility only */
5648                 { "irreversible",        no_argument,       NULL, ARG_IRREVERSIBLE        }, /* compatibility only */
5649                 { "ignore-dependencies", no_argument,       NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
5650                 { "ignore-inhibitors",   no_argument,       NULL, 'i'                     },
5651                 { "user",                no_argument,       NULL, ARG_USER                },
5652                 { "system",              no_argument,       NULL, ARG_SYSTEM              },
5653                 { "global",              no_argument,       NULL, ARG_GLOBAL              },
5654                 { "no-block",            no_argument,       NULL, ARG_NO_BLOCK            },
5655                 { "no-legend",           no_argument,       NULL, ARG_NO_LEGEND           },
5656                 { "no-pager",            no_argument,       NULL, ARG_NO_PAGER            },
5657                 { "no-wall",             no_argument,       NULL, ARG_NO_WALL             },
5658                 { "quiet",               no_argument,       NULL, 'q'                     },
5659                 { "root",                required_argument, NULL, ARG_ROOT                },
5660                 { "force",               no_argument,       NULL, ARG_FORCE               },
5661                 { "no-reload",           no_argument,       NULL, ARG_NO_RELOAD           },
5662                 { "kill-who",            required_argument, NULL, ARG_KILL_WHO            },
5663                 { "signal",              required_argument, NULL, 's'                     },
5664                 { "no-ask-password",     no_argument,       NULL, ARG_NO_ASK_PASSWORD     },
5665                 { "host",                required_argument, NULL, 'H'                     },
5666                 { "machine",             required_argument, NULL, 'M'                     },
5667                 { "runtime",             no_argument,       NULL, ARG_RUNTIME             },
5668                 { "lines",               required_argument, NULL, 'n'                     },
5669                 { "output",              required_argument, NULL, 'o'                     },
5670                 { "plain",               no_argument,       NULL, ARG_PLAIN               },
5671                 { "state",               required_argument, NULL, ARG_STATE               },
5672                 { "recursive",           no_argument,       NULL, 'r'                     },
5673                 {}
5674         };
5675
5676         int c;
5677
5678         assert(argc >= 0);
5679         assert(argv);
5680
5681         while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0) {
5682
5683                 switch (c) {
5684
5685                 case 'h':
5686                         return systemctl_help();
5687
5688                 case ARG_VERSION:
5689                         puts(PACKAGE_STRING);
5690                         puts(SYSTEMD_FEATURES);
5691                         return 0;
5692
5693                 case 't': {
5694                         char *word, *state;
5695                         size_t size;
5696
5697                         FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5698                                 _cleanup_free_ char *type;
5699
5700                                 type = strndup(word, size);
5701                                 if (!type)
5702                                         return -ENOMEM;
5703
5704                                 if (streq(type, "help")) {
5705                                         help_types();
5706                                         return 0;
5707                                 }
5708
5709                                 if (unit_type_from_string(type) >= 0) {
5710                                         if (strv_push(&arg_types, type))
5711                                                 return log_oom();
5712                                         type = NULL;
5713                                         continue;
5714                                 }
5715
5716                                 /* It's much nicer to use --state= for
5717                                  * load states, but let's support this
5718                                  * in --types= too for compatibility
5719                                  * with old versions */
5720                                 if (unit_load_state_from_string(optarg) >= 0) {
5721                                         if (strv_push(&arg_states, type) < 0)
5722                                                 return log_oom();
5723                                         type = NULL;
5724                                         continue;
5725                                 }
5726
5727                                 log_error("Unknown unit type or load state '%s'.", type);
5728                                 log_info("Use -t help to see a list of allowed values.");
5729                                 return -EINVAL;
5730                         }
5731
5732                         break;
5733                 }
5734
5735                 case 'p': {
5736                         /* Make sure that if the empty property list
5737                            was specified, we won't show any properties. */
5738                         if (isempty(optarg) && !arg_properties) {
5739                                 arg_properties = new0(char*, 1);
5740                                 if (!arg_properties)
5741                                         return log_oom();
5742                         } else {
5743                                 char *word, *state;
5744                                 size_t size;
5745
5746                                 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5747                                         char *prop;
5748
5749                                         prop = strndup(word, size);
5750                                         if (!prop)
5751                                                 return log_oom();
5752
5753                                         if (strv_consume(&arg_properties, prop) < 0)
5754                                                 return log_oom();
5755                                 }
5756                         }
5757
5758                         /* If the user asked for a particular
5759                          * property, show it to him, even if it is
5760                          * empty. */
5761                         arg_all = true;
5762
5763                         break;
5764                 }
5765
5766                 case 'a':
5767                         arg_all = true;
5768                         break;
5769
5770                 case ARG_REVERSE:
5771                         arg_dependency = DEPENDENCY_REVERSE;
5772                         break;
5773
5774                 case ARG_AFTER:
5775                         arg_dependency = DEPENDENCY_AFTER;
5776                         break;
5777
5778                 case ARG_BEFORE:
5779                         arg_dependency = DEPENDENCY_BEFORE;
5780                         break;
5781
5782                 case ARG_SHOW_TYPES:
5783                         arg_show_types = true;
5784                         break;
5785
5786                 case ARG_JOB_MODE:
5787                         arg_job_mode = optarg;
5788                         break;
5789
5790                 case ARG_FAIL:
5791                         arg_job_mode = "fail";
5792                         break;
5793
5794                 case ARG_IRREVERSIBLE:
5795                         arg_job_mode = "replace-irreversibly";
5796                         break;
5797
5798                 case ARG_IGNORE_DEPENDENCIES:
5799                         arg_job_mode = "ignore-dependencies";
5800                         break;
5801
5802                 case ARG_USER:
5803                         arg_scope = UNIT_FILE_USER;
5804                         break;
5805
5806                 case ARG_SYSTEM:
5807                         arg_scope = UNIT_FILE_SYSTEM;
5808                         break;
5809
5810                 case ARG_GLOBAL:
5811                         arg_scope = UNIT_FILE_GLOBAL;
5812                         break;
5813
5814                 case ARG_NO_BLOCK:
5815                         arg_no_block = true;
5816                         break;
5817
5818                 case ARG_NO_LEGEND:
5819                         arg_no_legend = true;
5820                         break;
5821
5822                 case ARG_NO_PAGER:
5823                         arg_no_pager = true;
5824                         break;
5825
5826                 case ARG_NO_WALL:
5827                         arg_no_wall = true;
5828                         break;
5829
5830                 case ARG_ROOT:
5831                         arg_root = optarg;
5832                         break;
5833
5834                 case 'l':
5835                         arg_full = true;
5836                         break;
5837
5838                 case ARG_FAILED:
5839                         if (strv_extend(&arg_states, "failed") < 0)
5840                                 return log_oom();
5841
5842                         break;
5843
5844                 case 'q':
5845                         arg_quiet = true;
5846                         break;
5847
5848                 case ARG_FORCE:
5849                         arg_force ++;
5850                         break;
5851
5852                 case 'f':
5853                         arg_force ++;
5854                         break;
5855
5856                 case ARG_NO_RELOAD:
5857                         arg_no_reload = true;
5858                         break;
5859
5860                 case ARG_KILL_WHO:
5861                         arg_kill_who = optarg;
5862                         break;
5863
5864                 case 's':
5865                         if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
5866                                 log_error("Failed to parse signal string %s.", optarg);
5867                                 return -EINVAL;
5868                         }
5869                         break;
5870
5871                 case ARG_NO_ASK_PASSWORD:
5872                         arg_ask_password = false;
5873                         break;
5874
5875                 case 'H':
5876                         arg_transport = BUS_TRANSPORT_REMOTE;
5877                         arg_host = optarg;
5878                         break;
5879
5880                 case 'M':
5881                         arg_transport = BUS_TRANSPORT_CONTAINER;
5882                         arg_host = optarg;
5883                         break;
5884
5885                 case ARG_RUNTIME:
5886                         arg_runtime = true;
5887                         break;
5888
5889                 case 'n':
5890                         if (safe_atou(optarg, &arg_lines) < 0) {
5891                                 log_error("Failed to parse lines '%s'", optarg);
5892                                 return -EINVAL;
5893                         }
5894                         break;
5895
5896                 case 'o':
5897                         arg_output = output_mode_from_string(optarg);
5898                         if (arg_output < 0) {
5899                                 log_error("Unknown output '%s'.", optarg);
5900                                 return -EINVAL;
5901                         }
5902                         break;
5903
5904                 case 'i':
5905                         arg_ignore_inhibitors = true;
5906                         break;
5907
5908                 case ARG_PLAIN:
5909                         arg_plain = true;
5910                         break;
5911
5912                 case ARG_STATE: {
5913                         char *word, *state;
5914                         size_t size;
5915
5916                         FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5917                                 char *s;
5918
5919                                 s = strndup(word, size);
5920                                 if (!s)
5921                                         return log_oom();
5922
5923                                 if (strv_consume(&arg_states, s) < 0)
5924                                         return log_oom();
5925                         }
5926                         break;
5927                 }
5928
5929                 case 'r':
5930                         if (geteuid() != 0) {
5931                                 log_error("--recursive requires root priviliges.");
5932                                 return -EPERM;
5933                         }
5934
5935                         arg_recursive = true;
5936                         break;
5937
5938                 case '?':
5939                         return -EINVAL;
5940
5941                 default:
5942                         assert_not_reached("Unhandled option");
5943                 }
5944         }
5945
5946         if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM) {
5947                 log_error("Cannot access user instance remotely.");
5948                 return -EINVAL;
5949         }
5950
5951         return 1;
5952 }
5953
5954 static int halt_parse_argv(int argc, char *argv[]) {
5955
5956         enum {
5957                 ARG_HELP = 0x100,
5958                 ARG_HALT,
5959                 ARG_REBOOT,
5960                 ARG_NO_WALL
5961         };
5962
5963         static const struct option options[] = {
5964                 { "help",      no_argument,       NULL, ARG_HELP    },
5965                 { "halt",      no_argument,       NULL, ARG_HALT    },
5966                 { "poweroff",  no_argument,       NULL, 'p'         },
5967                 { "reboot",    no_argument,       NULL, ARG_REBOOT  },
5968                 { "force",     no_argument,       NULL, 'f'         },
5969                 { "wtmp-only", no_argument,       NULL, 'w'         },
5970                 { "no-wtmp",   no_argument,       NULL, 'd'         },
5971                 { "no-wall",   no_argument,       NULL, ARG_NO_WALL },
5972                 {}
5973         };
5974
5975         int c, r, runlevel;
5976
5977         assert(argc >= 0);
5978         assert(argv);
5979
5980         if (utmp_get_runlevel(&runlevel, NULL) >= 0)
5981                 if (runlevel == '0' || runlevel == '6')
5982                         arg_force = 2;
5983
5984         while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
5985                 switch (c) {
5986
5987                 case ARG_HELP:
5988                         return halt_help();
5989
5990                 case ARG_HALT:
5991                         arg_action = ACTION_HALT;
5992                         break;
5993
5994                 case 'p':
5995                         if (arg_action != ACTION_REBOOT)
5996                                 arg_action = ACTION_POWEROFF;
5997                         break;
5998
5999                 case ARG_REBOOT:
6000                         arg_action = ACTION_REBOOT;
6001                         break;
6002
6003                 case 'f':
6004                         arg_force = 2;
6005                         break;
6006
6007                 case 'w':
6008                         arg_dry = true;
6009                         break;
6010
6011                 case 'd':
6012                         arg_no_wtmp = true;
6013                         break;
6014
6015                 case ARG_NO_WALL:
6016                         arg_no_wall = true;
6017                         break;
6018
6019                 case 'i':
6020                 case 'h':
6021                 case 'n':
6022                         /* Compatibility nops */
6023                         break;
6024
6025                 case '?':
6026                         return -EINVAL;
6027
6028                 default:
6029                         assert_not_reached("Unhandled option");
6030                 }
6031         }
6032
6033         if (arg_action == ACTION_REBOOT && (argc == optind || argc == optind + 1)) {
6034                 r = update_reboot_param_file(argc == optind + 1 ? argv[optind] : NULL);
6035                 if (r < 0)
6036                         return r;
6037         } else if (optind < argc) {
6038                 log_error("Too many arguments.");
6039                 return -EINVAL;
6040         }
6041
6042         return 1;
6043 }
6044
6045 static int parse_time_spec(const char *t, usec_t *_u) {
6046         assert(t);
6047         assert(_u);
6048
6049         if (streq(t, "now"))
6050                 *_u = 0;
6051         else if (!strchr(t, ':')) {
6052                 uint64_t u;
6053
6054                 if (safe_atou64(t, &u) < 0)
6055                         return -EINVAL;
6056
6057                 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
6058         } else {
6059                 char *e = NULL;
6060                 long hour, minute;
6061                 struct tm tm = {};
6062                 time_t s;
6063                 usec_t n;
6064
6065                 errno = 0;
6066                 hour = strtol(t, &e, 10);
6067                 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
6068                         return -EINVAL;
6069
6070                 minute = strtol(e+1, &e, 10);
6071                 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
6072                         return -EINVAL;
6073
6074                 n = now(CLOCK_REALTIME);
6075                 s = (time_t) (n / USEC_PER_SEC);
6076
6077                 assert_se(localtime_r(&s, &tm));
6078
6079                 tm.tm_hour = (int) hour;
6080                 tm.tm_min = (int) minute;
6081                 tm.tm_sec = 0;
6082
6083                 assert_se(s = mktime(&tm));
6084
6085                 *_u = (usec_t) s * USEC_PER_SEC;
6086
6087                 while (*_u <= n)
6088                         *_u += USEC_PER_DAY;
6089         }
6090
6091         return 0;
6092 }
6093
6094 static int shutdown_parse_argv(int argc, char *argv[]) {
6095
6096         enum {
6097                 ARG_HELP = 0x100,
6098                 ARG_NO_WALL
6099         };
6100
6101         static const struct option options[] = {
6102                 { "help",      no_argument,       NULL, ARG_HELP    },
6103                 { "halt",      no_argument,       NULL, 'H'         },
6104                 { "poweroff",  no_argument,       NULL, 'P'         },
6105                 { "reboot",    no_argument,       NULL, 'r'         },
6106                 { "kexec",     no_argument,       NULL, 'K'         }, /* not documented extension */
6107                 { "no-wall",   no_argument,       NULL, ARG_NO_WALL },
6108                 {}
6109         };
6110
6111         int c, r;
6112
6113         assert(argc >= 0);
6114         assert(argv);
6115
6116         while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
6117                 switch (c) {
6118
6119                 case ARG_HELP:
6120                         return shutdown_help();
6121
6122                 case 'H':
6123                         arg_action = ACTION_HALT;
6124                         break;
6125
6126                 case 'P':
6127                         arg_action = ACTION_POWEROFF;
6128                         break;
6129
6130                 case 'r':
6131                         if (kexec_loaded())
6132                                 arg_action = ACTION_KEXEC;
6133                         else
6134                                 arg_action = ACTION_REBOOT;
6135                         break;
6136
6137                 case 'K':
6138                         arg_action = ACTION_KEXEC;
6139                         break;
6140
6141                 case 'h':
6142                         if (arg_action != ACTION_HALT)
6143                                 arg_action = ACTION_POWEROFF;
6144                         break;
6145
6146                 case 'k':
6147                         arg_dry = true;
6148                         break;
6149
6150                 case ARG_NO_WALL:
6151                         arg_no_wall = true;
6152                         break;
6153
6154                 case 't':
6155                 case 'a':
6156                         /* Compatibility nops */
6157                         break;
6158
6159                 case 'c':
6160                         arg_action = ACTION_CANCEL_SHUTDOWN;
6161                         break;
6162
6163                 case '?':
6164                         return -EINVAL;
6165
6166                 default:
6167                         assert_not_reached("Unhandled option");
6168                 }
6169         }
6170
6171         if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
6172                 r = parse_time_spec(argv[optind], &arg_when);
6173                 if (r < 0) {
6174                         log_error("Failed to parse time specification: %s", argv[optind]);
6175                         return r;
6176                 }
6177         } else
6178                 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
6179
6180         if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
6181                 /* No time argument for shutdown cancel */
6182                 arg_wall = argv + optind;
6183         else if (argc > optind + 1)
6184                 /* We skip the time argument */
6185                 arg_wall = argv + optind + 1;
6186
6187         optind = argc;
6188
6189         return 1;
6190 }
6191
6192 static int telinit_parse_argv(int argc, char *argv[]) {
6193
6194         enum {
6195                 ARG_HELP = 0x100,
6196                 ARG_NO_WALL
6197         };
6198
6199         static const struct option options[] = {
6200                 { "help",      no_argument,       NULL, ARG_HELP    },
6201                 { "no-wall",   no_argument,       NULL, ARG_NO_WALL },
6202                 {}
6203         };
6204
6205         static const struct {
6206                 char from;
6207                 enum action to;
6208         } table[] = {
6209                 { '0', ACTION_POWEROFF },
6210                 { '6', ACTION_REBOOT },
6211                 { '1', ACTION_RESCUE },
6212                 { '2', ACTION_RUNLEVEL2 },
6213                 { '3', ACTION_RUNLEVEL3 },
6214                 { '4', ACTION_RUNLEVEL4 },
6215                 { '5', ACTION_RUNLEVEL5 },
6216                 { 's', ACTION_RESCUE },
6217                 { 'S', ACTION_RESCUE },
6218                 { 'q', ACTION_RELOAD },
6219                 { 'Q', ACTION_RELOAD },
6220                 { 'u', ACTION_REEXEC },
6221                 { 'U', ACTION_REEXEC }
6222         };
6223
6224         unsigned i;
6225         int c;
6226
6227         assert(argc >= 0);
6228         assert(argv);
6229
6230         while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
6231                 switch (c) {
6232
6233                 case ARG_HELP:
6234                         return telinit_help();
6235
6236                 case ARG_NO_WALL:
6237                         arg_no_wall = true;
6238                         break;
6239
6240                 case '?':
6241                         return -EINVAL;
6242
6243                 default:
6244                         assert_not_reached("Unhandled option");
6245                 }
6246         }
6247
6248         if (optind >= argc) {
6249                 telinit_help();
6250                 return -EINVAL;
6251         }
6252
6253         if (optind + 1 < argc) {
6254                 log_error("Too many arguments.");
6255                 return -EINVAL;
6256         }
6257
6258         if (strlen(argv[optind]) != 1) {
6259                 log_error("Expected single character argument.");
6260                 return -EINVAL;
6261         }
6262
6263         for (i = 0; i < ELEMENTSOF(table); i++)
6264                 if (table[i].from == argv[optind][0])
6265                         break;
6266
6267         if (i >= ELEMENTSOF(table)) {
6268                 log_error("Unknown command '%s'.", argv[optind]);
6269                 return -EINVAL;
6270         }
6271
6272         arg_action = table[i].to;
6273
6274         optind ++;
6275
6276         return 1;
6277 }
6278
6279 static int runlevel_parse_argv(int argc, char *argv[]) {
6280
6281         enum {
6282                 ARG_HELP = 0x100,
6283         };
6284
6285         static const struct option options[] = {
6286                 { "help",      no_argument,       NULL, ARG_HELP    },
6287                 {}
6288         };
6289
6290         int c;
6291
6292         assert(argc >= 0);
6293         assert(argv);
6294
6295         while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
6296                 switch (c) {
6297
6298                 case ARG_HELP:
6299                         return runlevel_help();
6300
6301                 case '?':
6302                         return -EINVAL;
6303
6304                 default:
6305                         assert_not_reached("Unhandled option");
6306                 }
6307         }
6308
6309         if (optind < argc) {
6310                 log_error("Too many arguments.");
6311                 return -EINVAL;
6312         }
6313
6314         return 1;
6315 }
6316
6317 static int parse_argv(int argc, char *argv[]) {
6318         assert(argc >= 0);
6319         assert(argv);
6320
6321         if (program_invocation_short_name) {
6322
6323                 if (strstr(program_invocation_short_name, "halt")) {
6324                         arg_action = ACTION_HALT;
6325                         return halt_parse_argv(argc, argv);
6326                 } else if (strstr(program_invocation_short_name, "poweroff")) {
6327                         arg_action = ACTION_POWEROFF;
6328                         return halt_parse_argv(argc, argv);
6329                 } else if (strstr(program_invocation_short_name, "reboot")) {
6330                         if (kexec_loaded())
6331                                 arg_action = ACTION_KEXEC;
6332                         else
6333                                 arg_action = ACTION_REBOOT;
6334                         return halt_parse_argv(argc, argv);
6335                 } else if (strstr(program_invocation_short_name, "shutdown")) {
6336                         arg_action = ACTION_POWEROFF;
6337                         return shutdown_parse_argv(argc, argv);
6338                 } else if (strstr(program_invocation_short_name, "init")) {
6339
6340                         if (sd_booted() > 0) {
6341                                 arg_action = _ACTION_INVALID;
6342                                 return telinit_parse_argv(argc, argv);
6343                         } else {
6344                                 /* Hmm, so some other init system is
6345                                  * running, we need to forward this
6346                                  * request to it. For now we simply
6347                                  * guess that it is Upstart. */
6348
6349                                 execv(TELINIT, argv);
6350
6351                                 log_error("Couldn't find an alternative telinit implementation to spawn.");
6352                                 return -EIO;
6353                         }
6354
6355                 } else if (strstr(program_invocation_short_name, "runlevel")) {
6356                         arg_action = ACTION_RUNLEVEL;
6357                         return runlevel_parse_argv(argc, argv);
6358                 }
6359         }
6360
6361         arg_action = ACTION_SYSTEMCTL;
6362         return systemctl_parse_argv(argc, argv);
6363 }
6364
6365 _pure_ static int action_to_runlevel(void) {
6366
6367         static const char table[_ACTION_MAX] = {
6368                 [ACTION_HALT] =      '0',
6369                 [ACTION_POWEROFF] =  '0',
6370                 [ACTION_REBOOT] =    '6',
6371                 [ACTION_RUNLEVEL2] = '2',
6372                 [ACTION_RUNLEVEL3] = '3',
6373                 [ACTION_RUNLEVEL4] = '4',
6374                 [ACTION_RUNLEVEL5] = '5',
6375                 [ACTION_RESCUE] =    '1'
6376         };
6377
6378         assert(arg_action < _ACTION_MAX);
6379
6380         return table[arg_action];
6381 }
6382
6383 static int talk_initctl(void) {
6384
6385         struct init_request request = {
6386                 .magic = INIT_MAGIC,
6387                 .sleeptime  = 0,
6388                 .cmd = INIT_CMD_RUNLVL
6389         };
6390
6391         _cleanup_close_ int fd = -1;
6392         char rl;
6393         int r;
6394
6395         rl = action_to_runlevel();
6396         if (!rl)
6397                 return 0;
6398
6399         request.runlevel = rl;
6400
6401         fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
6402         if (fd < 0) {
6403                 if (errno == ENOENT)
6404                         return 0;
6405
6406                 log_error("Failed to open "INIT_FIFO": %m");
6407                 return -errno;
6408         }
6409
6410         errno = 0;
6411         r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
6412         if (r) {
6413                 log_error("Failed to write to "INIT_FIFO": %m");
6414                 return errno > 0 ? -errno : -EIO;
6415         }
6416
6417         return 1;
6418 }
6419
6420 static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
6421
6422         static const struct {
6423                 const char* verb;
6424                 const enum {
6425                         MORE,
6426                         LESS,
6427                         EQUAL
6428                 } argc_cmp;
6429                 const int argc;
6430                 int (* const dispatch)(sd_bus *bus, char **args);
6431                 const enum {
6432                         NOBUS = 1,
6433                         FORCE,
6434                 } bus;
6435         } verbs[] = {
6436                 { "list-units",            MORE,  0, list_units        },
6437                 { "list-unit-files",       MORE,  1, list_unit_files,  NOBUS },
6438                 { "list-sockets",          MORE,  1, list_sockets      },
6439                 { "list-timers",           MORE,  1, list_timers       },
6440                 { "list-jobs",             MORE,  1, list_jobs         },
6441                 { "list-machines",         MORE,  1, list_machines     },
6442                 { "clear-jobs",            EQUAL, 1, daemon_reload     },
6443                 { "cancel",                MORE,  2, cancel_job        },
6444                 { "start",                 MORE,  2, start_unit        },
6445                 { "stop",                  MORE,  2, start_unit        },
6446                 { "condstop",              MORE,  2, start_unit        }, /* For compatibility with ALTLinux */
6447                 { "reload",                MORE,  2, start_unit        },
6448                 { "restart",               MORE,  2, start_unit        },
6449                 { "try-restart",           MORE,  2, start_unit        },
6450                 { "reload-or-restart",     MORE,  2, start_unit        },
6451                 { "reload-or-try-restart", MORE,  2, start_unit        },
6452                 { "force-reload",          MORE,  2, start_unit        }, /* For compatibility with SysV */
6453                 { "condreload",            MORE,  2, start_unit        }, /* For compatibility with ALTLinux */
6454                 { "condrestart",           MORE,  2, start_unit        }, /* For compatibility with RH */
6455                 { "isolate",               EQUAL, 2, start_unit        },
6456                 { "kill",                  MORE,  2, kill_unit         },
6457                 { "is-active",             MORE,  2, check_unit_active },
6458                 { "check",                 MORE,  2, check_unit_active },
6459                 { "is-failed",             MORE,  2, check_unit_failed },
6460                 { "show",                  MORE,  1, show              },
6461                 { "cat",                   MORE,  2, cat               },
6462                 { "status",                MORE,  1, show              },
6463                 { "help",                  MORE,  2, show              },
6464                 { "snapshot",              LESS,  2, snapshot          },
6465                 { "delete",                MORE,  2, delete_snapshot   },
6466                 { "daemon-reload",         EQUAL, 1, daemon_reload     },
6467                 { "daemon-reexec",         EQUAL, 1, daemon_reload     },
6468                 { "show-environment",      EQUAL, 1, show_environment  },
6469                 { "set-environment",       MORE,  2, set_environment   },
6470                 { "unset-environment",     MORE,  2, set_environment   },
6471                 { "import-environment",    MORE,  1, import_environment},
6472                 { "halt",                  EQUAL, 1, start_special,    FORCE },
6473                 { "poweroff",              EQUAL, 1, start_special,    FORCE },
6474                 { "reboot",                EQUAL, 1, start_special,    FORCE },
6475                 { "kexec",                 EQUAL, 1, start_special     },
6476                 { "suspend",               EQUAL, 1, start_special     },
6477                 { "hibernate",             EQUAL, 1, start_special     },
6478                 { "hybrid-sleep",          EQUAL, 1, start_special     },
6479                 { "default",               EQUAL, 1, start_special     },
6480                 { "rescue",                EQUAL, 1, start_special     },
6481                 { "emergency",             EQUAL, 1, start_special     },
6482                 { "exit",                  EQUAL, 1, start_special     },
6483                 { "reset-failed",          MORE,  1, reset_failed      },
6484                 { "enable",                MORE,  2, enable_unit,      NOBUS },
6485                 { "disable",               MORE,  2, enable_unit,      NOBUS },
6486                 { "is-enabled",            MORE,  2, unit_is_enabled,  NOBUS },
6487                 { "reenable",              MORE,  2, enable_unit,      NOBUS },
6488                 { "preset",                MORE,  2, enable_unit,      NOBUS },
6489                 { "mask",                  MORE,  2, enable_unit,      NOBUS },
6490                 { "unmask",                MORE,  2, enable_unit,      NOBUS },
6491                 { "link",                  MORE,  2, enable_unit,      NOBUS },
6492                 { "switch-root",           MORE,  2, switch_root       },
6493                 { "list-dependencies",     LESS,  2, list_dependencies },
6494                 { "set-default",           EQUAL, 2, set_default,      NOBUS },
6495                 { "get-default",           EQUAL, 1, get_default,      NOBUS },
6496                 { "set-property",          MORE,  3, set_property      },
6497                 {}
6498         }, *verb = verbs;
6499
6500         int left;
6501
6502         assert(argc >= 0);
6503         assert(argv);
6504
6505         left = argc - optind;
6506
6507         /* Special rule: no arguments (left == 0) means "list-units" */
6508         if (left > 0) {
6509                 if (streq(argv[optind], "help") && !argv[optind+1]) {
6510                         log_error("This command expects one or more "
6511                                   "unit names. Did you mean --help?");
6512                         return -EINVAL;
6513                 }
6514
6515                 for (; verb->verb; verb++)
6516                         if (streq(argv[optind], verb->verb))
6517                                 goto found;
6518
6519                 log_error("Unknown operation '%s'.", argv[optind]);
6520                 return -EINVAL;
6521         }
6522 found:
6523
6524         switch (verb->argc_cmp) {
6525
6526         case EQUAL:
6527                 if (left != verb->argc) {
6528                         log_error("Invalid number of arguments.");
6529                         return -EINVAL;
6530                 }
6531
6532                 break;
6533
6534         case MORE:
6535                 if (left < verb->argc) {
6536                         log_error("Too few arguments.");
6537                         return -EINVAL;
6538                 }
6539
6540                 break;
6541
6542         case LESS:
6543                 if (left > verb->argc) {
6544                         log_error("Too many arguments.");
6545                         return -EINVAL;
6546                 }
6547
6548                 break;
6549
6550         default:
6551                 assert_not_reached("Unknown comparison operator.");
6552         }
6553
6554         /* Require a bus connection for all operations but
6555          * enable/disable */
6556         if (verb->bus == NOBUS) {
6557                 if (!bus && !avoid_bus()) {
6558                         log_error("Failed to get D-Bus connection: %s", strerror(-bus_error));
6559                         return -EIO;
6560                 }
6561
6562         } else {
6563                 if (running_in_chroot() > 0) {
6564                         log_info("Running in chroot, ignoring request.");
6565                         return 0;
6566                 }
6567
6568                 if ((verb->bus != FORCE || arg_force <= 0) && !bus) {
6569                         log_error("Failed to get D-Bus connection: %s", strerror(-bus_error));
6570                         return -EIO;
6571                 }
6572         }
6573
6574         return verb->dispatch(bus, argv + optind);
6575 }
6576
6577 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
6578
6579         struct sd_shutdown_command c = {
6580                 .usec = t,
6581                 .mode = mode,
6582                 .dry_run = dry_run,
6583                 .warn_wall = warn,
6584         };
6585
6586         union sockaddr_union sockaddr = {
6587                 .un.sun_family = AF_UNIX,
6588                 .un.sun_path = "/run/systemd/shutdownd",
6589         };
6590
6591         struct iovec iovec[2] = {{
6592                  .iov_base = (char*) &c,
6593                  .iov_len = offsetof(struct sd_shutdown_command, wall_message),
6594         }};
6595
6596         struct msghdr msghdr = {
6597                 .msg_name = &sockaddr,
6598                 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
6599                                + strlen("/run/systemd/shutdownd"),
6600                 .msg_iov = iovec,
6601                 .msg_iovlen = 1,
6602         };
6603
6604         _cleanup_close_ int fd;
6605
6606         fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
6607         if (fd < 0)
6608                 return -errno;
6609
6610         if (!isempty(message)) {
6611                 iovec[1].iov_base = (char*) message;
6612                 iovec[1].iov_len = strlen(message);
6613                 msghdr.msg_iovlen++;
6614         }
6615
6616         if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
6617                 return -errno;
6618
6619         return 0;
6620 }
6621
6622 static int reload_with_fallback(sd_bus *bus) {
6623
6624         if (bus) {
6625                 /* First, try systemd via D-Bus. */
6626                 if (daemon_reload(bus, NULL) >= 0)
6627                         return 0;
6628         }
6629
6630         /* Nothing else worked, so let's try signals */
6631         assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
6632
6633         if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
6634                 log_error("kill() failed: %m");
6635                 return -errno;
6636         }
6637
6638         return 0;
6639 }
6640
6641 static int start_with_fallback(sd_bus *bus) {
6642
6643         if (bus) {
6644                 /* First, try systemd via D-Bus. */
6645                 if (start_unit(bus, NULL) >= 0)
6646                         goto done;
6647         }
6648
6649         /* Nothing else worked, so let's try
6650          * /dev/initctl */
6651         if (talk_initctl() > 0)
6652                 goto done;
6653
6654         log_error("Failed to talk to init daemon.");
6655         return -EIO;
6656
6657 done:
6658         warn_wall(arg_action);
6659         return 0;
6660 }
6661
6662 static int halt_now(enum action a) {
6663
6664 /* Make sure C-A-D is handled by the kernel from this
6665          * point on... */
6666         reboot(RB_ENABLE_CAD);
6667
6668         switch (a) {
6669
6670         case ACTION_HALT:
6671                 log_info("Halting.");
6672                 reboot(RB_HALT_SYSTEM);
6673                 return -errno;
6674
6675         case ACTION_POWEROFF:
6676                 log_info("Powering off.");
6677                 reboot(RB_POWER_OFF);
6678                 return -errno;
6679
6680         case ACTION_REBOOT: {
6681                 _cleanup_free_ char *param = NULL;
6682
6683                 if (read_one_line_file(REBOOT_PARAM_FILE, &param) >= 0) {
6684                         log_info("Rebooting with argument '%s'.", param);
6685                         syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
6686                                 LINUX_REBOOT_CMD_RESTART2, param);
6687                 }
6688
6689                 log_info("Rebooting.");
6690                 reboot(RB_AUTOBOOT);
6691                 return -errno;
6692         }
6693
6694         default:
6695                 assert_not_reached("Unknown action.");
6696         }
6697 }
6698
6699 static int halt_main(sd_bus *bus) {
6700         int r;
6701
6702         r = check_inhibitors(bus, arg_action);
6703         if (r < 0)
6704                 return r;
6705
6706         if (geteuid() != 0) {
6707                 /* Try logind if we are a normal user and no special
6708                  * mode applies. Maybe PolicyKit allows us to shutdown
6709                  * the machine. */
6710
6711                 if (arg_when <= 0 &&
6712                     !arg_dry &&
6713                     arg_force <= 0 &&
6714                     (arg_action == ACTION_POWEROFF ||
6715                      arg_action == ACTION_REBOOT)) {
6716                         r = reboot_with_logind(bus, arg_action);
6717                         if (r >= 0)
6718                                 return r;
6719                 }
6720
6721                 log_error("Must be root.");
6722                 return -EPERM;
6723         }
6724
6725         if (arg_when > 0) {
6726                 _cleanup_free_ char *m;
6727
6728                 m = strv_join(arg_wall, " ");
6729                 if (!m)
6730                         return log_oom();
6731
6732                 r = send_shutdownd(arg_when,
6733                                    arg_action == ACTION_HALT     ? 'H' :
6734                                    arg_action == ACTION_POWEROFF ? 'P' :
6735                                    arg_action == ACTION_KEXEC    ? 'K' :
6736                                                                    'r',
6737                                    arg_dry,
6738                                    !arg_no_wall,
6739                                    m);
6740
6741                 if (r < 0)
6742                         log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
6743                 else {
6744                         char date[FORMAT_TIMESTAMP_MAX];
6745
6746                         log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
6747                                  format_timestamp(date, sizeof(date), arg_when));
6748                         return 0;
6749                 }
6750         }
6751
6752         if (!arg_dry && !arg_force)
6753                 return start_with_fallback(bus);
6754
6755         if (!arg_no_wtmp) {
6756                 if (sd_booted() > 0)
6757                         log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
6758                 else {
6759                         r = utmp_put_shutdown();
6760                         if (r < 0)
6761                                 log_warning("Failed to write utmp record: %s", strerror(-r));
6762                 }
6763         }
6764
6765         if (arg_dry)
6766                 return 0;
6767
6768         r = halt_now(arg_action);
6769         log_error("Failed to reboot: %s", strerror(-r));
6770
6771         return r;
6772 }
6773
6774 static int runlevel_main(void) {
6775         int r, runlevel, previous;
6776
6777         r = utmp_get_runlevel(&runlevel, &previous);
6778         if (r < 0) {
6779                 puts("unknown");
6780                 return r;
6781         }
6782
6783         printf("%c %c\n",
6784                previous <= 0 ? 'N' : previous,
6785                runlevel <= 0 ? 'N' : runlevel);
6786
6787         return 0;
6788 }
6789
6790 int main(int argc, char*argv[]) {
6791         _cleanup_bus_unref_ sd_bus *bus = NULL;
6792         int r;
6793
6794         setlocale(LC_ALL, "");
6795         log_parse_environment();
6796         log_open();
6797
6798         /* Explicitly not on_tty() to avoid setting cached value.
6799          * This becomes relevant for piping output which might be
6800          * ellipsized. */
6801         original_stdout_is_tty = isatty(STDOUT_FILENO);
6802
6803         r = parse_argv(argc, argv);
6804         if (r <= 0)
6805                 goto finish;
6806
6807         /* /sbin/runlevel doesn't need to communicate via D-Bus, so
6808          * let's shortcut this */
6809         if (arg_action == ACTION_RUNLEVEL) {
6810                 r = runlevel_main();
6811                 goto finish;
6812         }
6813
6814         if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
6815                 log_info("Running in chroot, ignoring request.");
6816                 r = 0;
6817                 goto finish;
6818         }
6819
6820         if (!avoid_bus())
6821                 r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus);
6822
6823         /* systemctl_main() will print an error message for the bus
6824          * connection, but only if it needs to */
6825
6826         switch (arg_action) {
6827
6828         case ACTION_SYSTEMCTL:
6829                 r = systemctl_main(bus, argc, argv, r);
6830                 break;
6831
6832         case ACTION_HALT:
6833         case ACTION_POWEROFF:
6834         case ACTION_REBOOT:
6835         case ACTION_KEXEC:
6836                 r = halt_main(bus);
6837                 break;
6838
6839         case ACTION_RUNLEVEL2:
6840         case ACTION_RUNLEVEL3:
6841         case ACTION_RUNLEVEL4:
6842         case ACTION_RUNLEVEL5:
6843         case ACTION_RESCUE:
6844         case ACTION_EMERGENCY:
6845         case ACTION_DEFAULT:
6846                 r = start_with_fallback(bus);
6847                 break;
6848
6849         case ACTION_RELOAD:
6850         case ACTION_REEXEC:
6851                 r = reload_with_fallback(bus);
6852                 break;
6853
6854         case ACTION_CANCEL_SHUTDOWN: {
6855                 _cleanup_free_ char *m = NULL;
6856
6857                 if (arg_wall) {
6858                         m = strv_join(arg_wall, " ");
6859                         if (!m) {
6860                                 r = log_oom();
6861                                 goto finish;
6862                         }
6863                 }
6864
6865                 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
6866                 if (r < 0)
6867                         log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
6868                 break;
6869         }
6870
6871         case ACTION_RUNLEVEL:
6872         case _ACTION_INVALID:
6873         default:
6874                 assert_not_reached("Unknown action");
6875         }
6876
6877 finish:
6878         pager_close();
6879         ask_password_agent_close();
6880         polkit_agent_close();
6881
6882         strv_free(arg_types);
6883         strv_free(arg_states);
6884         strv_free(arg_properties);
6885
6886         return r < 0 ? EXIT_FAILURE : r;
6887 }