chiark / gitweb /
b13b2731ce7b09ddfb2d8ee98524915d4d92d854
[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                         NULL,
2309                         "type='signal',"
2310                         "sender='org.freedesktop.systemd1',"
2311                         "interface='org.freedesktop.systemd1.Manager',"
2312                         "member='JobRemoved',"
2313                         "path='/org/freedesktop/systemd1'",
2314                         NULL, NULL);
2315         if (r < 0) {
2316                 log_error("Failed to add match");
2317                 return -EIO;
2318         }
2319
2320         /* This is slightly dirty, since we don't undo the match registrations. */
2321         return 0;
2322 }
2323
2324 static int bus_process_wait(sd_bus *bus) {
2325         int r;
2326
2327         for (;;) {
2328                 r = sd_bus_process(bus, NULL);
2329                 if (r < 0)
2330                         return r;
2331                 if (r > 0)
2332                         return 0;
2333                 r = sd_bus_wait(bus, (uint64_t) -1);
2334                 if (r < 0)
2335                         return r;
2336         }
2337 }
2338
2339 static int check_wait_response(WaitData *d) {
2340         int r = 0;
2341
2342         assert(d->result);
2343
2344         if (!arg_quiet) {
2345                 if (streq(d->result, "timeout"))
2346                         log_error("Job for %s timed out.", strna(d->name));
2347                 else if (streq(d->result, "canceled"))
2348                         log_error("Job for %s canceled.", strna(d->name));
2349                 else if (streq(d->result, "dependency"))
2350                         log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d->name));
2351                 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
2352                         log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d->name), strna(d->name));
2353         }
2354
2355         if (streq(d->result, "timeout"))
2356                 r = -ETIME;
2357         else if (streq(d->result, "canceled"))
2358                 r = -ECANCELED;
2359         else if (streq(d->result, "dependency"))
2360                 r = -EIO;
2361         else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
2362                 r = -EIO;
2363
2364         return r;
2365 }
2366
2367 static int wait_for_jobs(sd_bus *bus, Set *s) {
2368         _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL;
2369         WaitData d = { .set = s };
2370         int r = 0, q;
2371
2372         assert(bus);
2373         assert(s);
2374
2375         q = sd_bus_add_filter(bus, &slot, wait_filter, &d);
2376         if (q < 0)
2377                 return log_oom();
2378
2379         while (!set_isempty(s)) {
2380                 q = bus_process_wait(bus);
2381                 if (q < 0) {
2382                         log_error("Failed to wait for response: %s", strerror(-r));
2383                         return q;
2384                 }
2385
2386                 if (d.result) {
2387                         q = check_wait_response(&d);
2388                         /* Return the first error as it is most likely to be
2389                          * meaningful. */
2390                         if (q < 0 && r == 0)
2391                                 r = q;
2392                         log_debug("Got result %s/%s for job %s",
2393                                   strna(d.result), strerror(-q), strna(d.name));
2394                 }
2395
2396                 free(d.name);
2397                 d.name = NULL;
2398
2399                 free(d.result);
2400                 d.result = NULL;
2401         }
2402
2403         return r;
2404 }
2405
2406 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
2407         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2408         _cleanup_free_ char *n = NULL, *state = NULL;
2409         const char *path;
2410         int r;
2411
2412         assert(name);
2413
2414         n = unit_name_mangle(name, MANGLE_NOGLOB);
2415         if (!n)
2416                 return log_oom();
2417
2418         /* We don't use unit_dbus_path_from_name() directly since we
2419          * don't want to load the unit if it isn't loaded. */
2420
2421         r = sd_bus_call_method(
2422                         bus,
2423                         "org.freedesktop.systemd1",
2424                         "/org/freedesktop/systemd1",
2425                         "org.freedesktop.systemd1.Manager",
2426                         "GetUnit",
2427                         NULL,
2428                         &reply,
2429                         "s", n);
2430         if (r < 0) {
2431                 if (!quiet)
2432                         puts("unknown");
2433                 return 0;
2434         }
2435
2436         r = sd_bus_message_read(reply, "o", &path);
2437         if (r < 0)
2438                 return bus_log_parse_error(r);
2439
2440         r = sd_bus_get_property_string(
2441                         bus,
2442                         "org.freedesktop.systemd1",
2443                         path,
2444                         "org.freedesktop.systemd1.Unit",
2445                         "ActiveState",
2446                         NULL,
2447                         &state);
2448         if (r < 0) {
2449                 if (!quiet)
2450                         puts("unknown");
2451                 return 0;
2452         }
2453
2454         if (!quiet)
2455                 puts(state);
2456
2457         return nulstr_contains(good_states, state);
2458 }
2459
2460 static int check_triggering_units(
2461                 sd_bus *bus,
2462                 const char *name) {
2463
2464         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2465         _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
2466         _cleanup_strv_free_ char **triggered_by = NULL;
2467         bool print_warning_label = true;
2468         char **i;
2469         int r;
2470
2471         n = unit_name_mangle(name, MANGLE_NOGLOB);
2472         if (!n)
2473                 return log_oom();
2474
2475         path = unit_dbus_path_from_name(n);
2476         if (!path)
2477                 return log_oom();
2478
2479         r = sd_bus_get_property_string(
2480                         bus,
2481                         "org.freedesktop.systemd1",
2482                         path,
2483                         "org.freedesktop.systemd1.Unit",
2484                         "LoadState",
2485                         &error,
2486                         &state);
2487         if (r < 0) {
2488                 log_error("Failed to get load state of %s: %s", n, bus_error_message(&error, r));
2489                 return r;
2490         }
2491
2492         if (streq(state, "masked"))
2493                 return 0;
2494
2495         r = sd_bus_get_property_strv(
2496                         bus,
2497                         "org.freedesktop.systemd1",
2498                         path,
2499                         "org.freedesktop.systemd1.Unit",
2500                         "TriggeredBy",
2501                         &error,
2502                         &triggered_by);
2503         if (r < 0) {
2504                 log_error("Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
2505                 return r;
2506         }
2507
2508         STRV_FOREACH(i, triggered_by) {
2509                 r = check_one_unit(bus, *i, "active\0reloading\0", true);
2510                 if (r < 0) {
2511                         log_error("Failed to check unit: %s", strerror(-r));
2512                         return r;
2513                 }
2514
2515                 if (r == 0)
2516                         continue;
2517
2518                 if (print_warning_label) {
2519                         log_warning("Warning: Stopping %s, but it can still be activated by:", n);
2520                         print_warning_label = false;
2521                 }
2522
2523                 log_warning("  %s", *i);
2524         }
2525
2526         return 0;
2527 }
2528
2529 static const char *verb_to_method(const char *verb) {
2530        uint i;
2531
2532        for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2533                 if (streq_ptr(unit_actions[i].verb, verb))
2534                         return unit_actions[i].method;
2535
2536        return "StartUnit";
2537 }
2538
2539 static const char *method_to_verb(const char *method) {
2540        uint i;
2541
2542        for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2543                 if (streq_ptr(unit_actions[i].method, method))
2544                         return unit_actions[i].verb;
2545
2546        return "n/a";
2547 }
2548
2549 static int start_unit_one(
2550                 sd_bus *bus,
2551                 const char *method,
2552                 const char *name,
2553                 const char *mode,
2554                 sd_bus_error *error,
2555                 Set *s) {
2556
2557         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2558         const char *path;
2559         int r;
2560
2561         assert(method);
2562         assert(name);
2563         assert(mode);
2564         assert(error);
2565
2566         log_debug("Calling manager for %s on %s, %s", method, name, mode);
2567         r = sd_bus_call_method(
2568                         bus,
2569                         "org.freedesktop.systemd1",
2570                         "/org/freedesktop/systemd1",
2571                         "org.freedesktop.systemd1.Manager",
2572                         method,
2573                         error,
2574                         &reply,
2575                         "ss", name, mode);
2576         if (r < 0) {
2577                 const char *verb;
2578
2579                 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
2580                         /* There's always a fallback possible for
2581                          * legacy actions. */
2582                         return -EADDRNOTAVAIL;
2583
2584                 verb = method_to_verb(method);
2585
2586                 log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r));
2587                 return r;
2588         }
2589
2590         r = sd_bus_message_read(reply, "o", &path);
2591         if (r < 0)
2592                 return bus_log_parse_error(r);
2593
2594         if (need_daemon_reload(bus, name) > 0)
2595                 log_warning("Warning: Unit file of %s changed on disk, 'systemctl%s daemon-reload' recommended.",
2596                             name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
2597
2598         if (s) {
2599                 char *p;
2600
2601                 p = strdup(path);
2602                 if (!p)
2603                         return log_oom();
2604
2605                 log_debug("Adding %s to the set", p);
2606                 r = set_consume(s, p);
2607                 if (r < 0)
2608                         return log_oom();
2609         }
2610
2611         return 0;
2612 }
2613
2614 static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret) {
2615
2616         _cleanup_strv_free_ char **mangled = NULL, **globs = NULL;
2617         char **name;
2618         int r = 0, i;
2619
2620         STRV_FOREACH(name, names) {
2621                 char *t;
2622
2623                 if (suffix)
2624                         t = unit_name_mangle_with_suffix(*name, MANGLE_GLOB, suffix);
2625                 else
2626                         t = unit_name_mangle(*name, MANGLE_GLOB);
2627                 if (!t)
2628                         return log_oom();
2629
2630                 if (string_is_glob(t))
2631                         r = strv_consume(&globs, t);
2632                 else
2633                         r = strv_consume(&mangled, t);
2634                 if (r < 0)
2635                         return log_oom();
2636         }
2637
2638         /* Query the manager only if any of the names are a glob, since
2639          * this is fairly expensive */
2640         if (!strv_isempty(globs)) {
2641                 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2642                 _cleanup_free_ UnitInfo *unit_infos = NULL;
2643
2644                 r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
2645                 if (r < 0)
2646                         return r;
2647
2648                 for (i = 0; i < r; i++)
2649                         if (strv_extend(&mangled, unit_infos[i].id) < 0)
2650                                 return log_oom();
2651         }
2652
2653         *ret = mangled;
2654         mangled = NULL; /* do not free */
2655
2656         return 0;
2657 }
2658
2659 static const struct {
2660         const char *target;
2661         const char *verb;
2662         const char *mode;
2663 } action_table[_ACTION_MAX] = {
2664         [ACTION_HALT]         = { SPECIAL_HALT_TARGET,         "halt",         "replace-irreversibly" },
2665         [ACTION_POWEROFF]     = { SPECIAL_POWEROFF_TARGET,     "poweroff",     "replace-irreversibly" },
2666         [ACTION_REBOOT]       = { SPECIAL_REBOOT_TARGET,       "reboot",       "replace-irreversibly" },
2667         [ACTION_KEXEC]        = { SPECIAL_KEXEC_TARGET,        "kexec",        "replace-irreversibly" },
2668         [ACTION_RUNLEVEL2]    = { SPECIAL_RUNLEVEL2_TARGET,    NULL,           "isolate" },
2669         [ACTION_RUNLEVEL3]    = { SPECIAL_RUNLEVEL3_TARGET,    NULL,           "isolate" },
2670         [ACTION_RUNLEVEL4]    = { SPECIAL_RUNLEVEL4_TARGET,    NULL,           "isolate" },
2671         [ACTION_RUNLEVEL5]    = { SPECIAL_RUNLEVEL5_TARGET,    NULL,           "isolate" },
2672         [ACTION_RESCUE]       = { SPECIAL_RESCUE_TARGET,       "rescue",       "isolate" },
2673         [ACTION_EMERGENCY]    = { SPECIAL_EMERGENCY_TARGET,    "emergency",    "isolate" },
2674         [ACTION_DEFAULT]      = { SPECIAL_DEFAULT_TARGET,      "default",      "isolate" },
2675         [ACTION_EXIT]         = { SPECIAL_EXIT_TARGET,         "exit",         "replace-irreversibly" },
2676         [ACTION_SUSPEND]      = { SPECIAL_SUSPEND_TARGET,      "suspend",      "replace-irreversibly" },
2677         [ACTION_HIBERNATE]    = { SPECIAL_HIBERNATE_TARGET,    "hibernate",    "replace-irreversibly" },
2678         [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
2679 };
2680
2681 static enum action verb_to_action(const char *verb) {
2682         enum action i;
2683
2684         for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
2685                 if (streq_ptr(action_table[i].verb, verb))
2686                         return i;
2687
2688         return _ACTION_INVALID;
2689 }
2690
2691 static int start_unit(sd_bus *bus, char **args) {
2692         _cleanup_set_free_free_ Set *s = NULL;
2693         _cleanup_strv_free_ char **names = NULL;
2694         const char *method, *mode, *one_name;
2695         char **name;
2696         int r = 0;
2697
2698         assert(bus);
2699
2700         ask_password_agent_open_if_enabled();
2701
2702         if (arg_action == ACTION_SYSTEMCTL) {
2703                 enum action action;
2704                 method = verb_to_method(args[0]);
2705                 action = verb_to_action(args[0]);
2706
2707                 mode = streq(args[0], "isolate") ? "isolate" :
2708                        action_table[action].mode ?: arg_job_mode;
2709
2710                 one_name = action_table[action].target;
2711         } else {
2712                 assert(arg_action < ELEMENTSOF(action_table));
2713                 assert(action_table[arg_action].target);
2714
2715                 method = "StartUnit";
2716
2717                 mode = action_table[arg_action].mode;
2718                 one_name = action_table[arg_action].target;
2719         }
2720
2721         if (one_name)
2722                 names = strv_new(one_name, NULL);
2723         else {
2724                 r = expand_names(bus, args + 1, NULL, &names);
2725                 if (r < 0)
2726                         log_error("Failed to expand names: %s", strerror(-r));
2727         }
2728
2729         if (!arg_no_block) {
2730                 r = enable_wait_for_jobs(bus);
2731                 if (r < 0) {
2732                         log_error("Could not watch jobs: %s", strerror(-r));
2733                         return r;
2734                 }
2735
2736                 s = set_new(string_hash_func, string_compare_func);
2737                 if (!s)
2738                         return log_oom();
2739         }
2740
2741         STRV_FOREACH(name, names) {
2742                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2743                 int q;
2744
2745                 q = start_unit_one(bus, method, *name, mode, &error, s);
2746                 if (r >= 0 && q < 0)
2747                         r = translate_bus_error_to_exit_status(q, &error);
2748         }
2749
2750         if (!arg_no_block) {
2751                 int q;
2752
2753                 q = wait_for_jobs(bus, s);
2754                 if (q < 0)
2755                         return q;
2756
2757                 /* When stopping units, warn if they can still be triggered by
2758                  * another active unit (socket, path, timer) */
2759                 if (!arg_quiet && streq(method, "StopUnit"))
2760                         STRV_FOREACH(name, names)
2761                                 check_triggering_units(bus, *name);
2762         }
2763
2764         return r;
2765 }
2766
2767 /* Ask systemd-logind, which might grant access to unprivileged users
2768  * through PolicyKit */
2769 static int reboot_with_logind(sd_bus *bus, enum action a) {
2770 #ifdef HAVE_LOGIND
2771         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2772         const char *method;
2773         int r;
2774
2775         if (!bus)
2776                 return -EIO;
2777
2778         polkit_agent_open_if_enabled();
2779
2780         switch (a) {
2781
2782         case ACTION_REBOOT:
2783                 method = "Reboot";
2784                 break;
2785
2786         case ACTION_POWEROFF:
2787                 method = "PowerOff";
2788                 break;
2789
2790         case ACTION_SUSPEND:
2791                 method = "Suspend";
2792                 break;
2793
2794         case ACTION_HIBERNATE:
2795                 method = "Hibernate";
2796                 break;
2797
2798         case ACTION_HYBRID_SLEEP:
2799                 method = "HybridSleep";
2800                 break;
2801
2802         default:
2803                 return -EINVAL;
2804         }
2805
2806         r = sd_bus_call_method(
2807                         bus,
2808                         "org.freedesktop.login1",
2809                         "/org/freedesktop/login1",
2810                         "org.freedesktop.login1.Manager",
2811                         method,
2812                         &error,
2813                         NULL,
2814                         "b", true);
2815         if (r < 0)
2816                 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
2817
2818         return r;
2819 #else
2820         return -ENOSYS;
2821 #endif
2822 }
2823
2824 static int check_inhibitors(sd_bus *bus, enum action a) {
2825 #ifdef HAVE_LOGIND
2826         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2827         _cleanup_strv_free_ char **sessions = NULL;
2828         const char *what, *who, *why, *mode;
2829         uint32_t uid, pid;
2830         unsigned c = 0;
2831         char **s;
2832         int r;
2833
2834         if (!bus)
2835                 return 0;
2836
2837         if (arg_ignore_inhibitors || arg_force > 0)
2838                 return 0;
2839
2840         if (arg_when > 0)
2841                 return 0;
2842
2843         if (geteuid() == 0)
2844                 return 0;
2845
2846         if (!on_tty())
2847                 return 0;
2848
2849         r = sd_bus_call_method(
2850                         bus,
2851                         "org.freedesktop.login1",
2852                         "/org/freedesktop/login1",
2853                         "org.freedesktop.login1.Manager",
2854                         "ListInhibitors",
2855                         NULL,
2856                         &reply,
2857                         NULL);
2858         if (r < 0)
2859                 /* If logind is not around, then there are no inhibitors... */
2860                 return 0;
2861
2862         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
2863         if (r < 0)
2864                 return bus_log_parse_error(r);
2865
2866         while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
2867                 _cleanup_free_ char *comm = NULL, *user = NULL;
2868                 _cleanup_strv_free_ char **sv = NULL;
2869
2870                 if (!streq(mode, "block"))
2871                         continue;
2872
2873                 sv = strv_split(what, ":");
2874                 if (!sv)
2875                         return log_oom();
2876
2877                 if (!strv_contains(sv,
2878                                   a == ACTION_HALT ||
2879                                   a == ACTION_POWEROFF ||
2880                                   a == ACTION_REBOOT ||
2881                                   a == ACTION_KEXEC ? "shutdown" : "sleep"))
2882                         continue;
2883
2884                 get_process_comm(pid, &comm);
2885                 user = uid_to_name(uid);
2886
2887                 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
2888                             who, pid, strna(comm), strna(user), why);
2889
2890                 c++;
2891         }
2892         if (r < 0)
2893                 return bus_log_parse_error(r);
2894
2895         r = sd_bus_message_exit_container(reply);
2896         if (r < 0)
2897                 return bus_log_parse_error(r);
2898
2899         /* Check for current sessions */
2900         sd_get_sessions(&sessions);
2901         STRV_FOREACH(s, sessions) {
2902                 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2903
2904                 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2905                         continue;
2906
2907                 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2908                         continue;
2909
2910                 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2911                         continue;
2912
2913                 sd_session_get_tty(*s, &tty);
2914                 sd_session_get_seat(*s, &seat);
2915                 sd_session_get_service(*s, &service);
2916                 user = uid_to_name(uid);
2917
2918                 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2919                 c++;
2920         }
2921
2922         if (c <= 0)
2923                 return 0;
2924
2925         log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2926                   action_table[a].verb);
2927
2928         return -EPERM;
2929 #else
2930         return 0;
2931 #endif
2932 }
2933
2934 static int start_special(sd_bus *bus, char **args) {
2935         enum action a;
2936         int r;
2937
2938         assert(args);
2939
2940         a = verb_to_action(args[0]);
2941
2942         r = check_inhibitors(bus, a);
2943         if (r < 0)
2944                 return r;
2945
2946         if (arg_force >= 2 && geteuid() != 0) {
2947                 log_error("Must be root.");
2948                 return -EPERM;
2949         }
2950
2951         if (arg_force >= 2 &&
2952             (a == ACTION_HALT ||
2953              a == ACTION_POWEROFF ||
2954              a == ACTION_REBOOT))
2955                 return halt_now(a);
2956
2957         if (arg_force >= 1 &&
2958             (a == ACTION_HALT ||
2959              a == ACTION_POWEROFF ||
2960              a == ACTION_REBOOT ||
2961              a == ACTION_KEXEC ||
2962              a == ACTION_EXIT))
2963                 return daemon_reload(bus, args);
2964
2965         /* first try logind, to allow authentication with polkit */
2966         if (geteuid() != 0 &&
2967             (a == ACTION_POWEROFF ||
2968              a == ACTION_REBOOT ||
2969              a == ACTION_SUSPEND ||
2970              a == ACTION_HIBERNATE ||
2971              a == ACTION_HYBRID_SLEEP)) {
2972                 r = reboot_with_logind(bus, a);
2973                 if (r >= 0)
2974                         return r;
2975         }
2976
2977         r = start_unit(bus, args);
2978         if (r == EXIT_SUCCESS)
2979                 warn_wall(a);
2980
2981         return r;
2982 }
2983
2984 static int check_unit_generic(sd_bus *bus, int code, const char *good_states, char **args) {
2985         _cleanup_strv_free_ char **names = NULL;
2986         char **name;
2987         int r;
2988
2989         assert(bus);
2990         assert(args);
2991
2992         r = expand_names(bus, args, NULL, &names);
2993         if (r < 0) {
2994                 log_error("Failed to expand names: %s", strerror(-r));
2995                 return r;
2996         }
2997
2998         STRV_FOREACH(name, names) {
2999                 int state;
3000
3001                 state = check_one_unit(bus, *name, good_states, arg_quiet);
3002                 if (state < 0)
3003                         return state;
3004                 if (state == 0)
3005                         r = code;
3006         }
3007
3008         return r;
3009 }
3010
3011 static int check_unit_active(sd_bus *bus, char **args) {
3012         /* According to LSB: 3, "program is not running" */
3013         return check_unit_generic(bus, 3, "active\0reloading\0", args + 1);
3014 }
3015
3016 static int check_unit_failed(sd_bus *bus, char **args) {
3017         return check_unit_generic(bus, 1, "failed\0", args + 1);
3018 }
3019
3020 static int kill_unit(sd_bus *bus, char **args) {
3021         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3022         _cleanup_strv_free_ char **names = NULL;
3023         char **name;
3024         int r, q;
3025
3026         assert(bus);
3027         assert(args);
3028
3029         if (!arg_kill_who)
3030                 arg_kill_who = "all";
3031
3032         r = expand_names(bus, args + 1, NULL, &names);
3033         if (r < 0)
3034                 log_error("Failed to expand names: %s", strerror(-r));
3035
3036         STRV_FOREACH(name, names) {
3037                 q = sd_bus_call_method(
3038                                 bus,
3039                                 "org.freedesktop.systemd1",
3040                                 "/org/freedesktop/systemd1",
3041                                 "org.freedesktop.systemd1.Manager",
3042                                 "KillUnit",
3043                                 &error,
3044                                 NULL,
3045                                 "ssi", *names, arg_kill_who, arg_signal);
3046                 if (q < 0) {
3047                         log_error("Failed to kill unit %s: %s",
3048                                   *names, bus_error_message(&error, r));
3049                         if (r == 0)
3050                                 r = q;
3051                 }
3052         }
3053
3054         return r;
3055 }
3056
3057 typedef struct ExecStatusInfo {
3058         char *name;
3059
3060         char *path;
3061         char **argv;
3062
3063         bool ignore;
3064
3065         usec_t start_timestamp;
3066         usec_t exit_timestamp;
3067         pid_t pid;
3068         int code;
3069         int status;
3070
3071         LIST_FIELDS(struct ExecStatusInfo, exec);
3072 } ExecStatusInfo;
3073
3074 static void exec_status_info_free(ExecStatusInfo *i) {
3075         assert(i);
3076
3077         free(i->name);
3078         free(i->path);
3079         strv_free(i->argv);
3080         free(i);
3081 }
3082
3083 static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
3084         uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
3085         const char *path;
3086         uint32_t pid;
3087         int32_t code, status;
3088         int ignore, r;
3089
3090         assert(m);
3091         assert(i);
3092
3093         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii");
3094         if (r < 0)
3095                 return bus_log_parse_error(r);
3096         else if (r == 0)
3097                 return 0;
3098
3099         r = sd_bus_message_read(m, "s", &path);
3100         if (r < 0)
3101                 return bus_log_parse_error(r);
3102
3103         i->path = strdup(path);
3104         if (!i->path)
3105                 return log_oom();
3106
3107         r = sd_bus_message_read_strv(m, &i->argv);
3108         if (r < 0)
3109                 return bus_log_parse_error(r);
3110
3111         r = sd_bus_message_read(m,
3112                                 "bttttuii",
3113                                 &ignore,
3114                                 &start_timestamp, &start_timestamp_monotonic,
3115                                 &exit_timestamp, &exit_timestamp_monotonic,
3116                                 &pid,
3117                                 &code, &status);
3118         if (r < 0)
3119                 return bus_log_parse_error(r);
3120
3121         i->ignore = ignore;
3122         i->start_timestamp = (usec_t) start_timestamp;
3123         i->exit_timestamp = (usec_t) exit_timestamp;
3124         i->pid = (pid_t) pid;
3125         i->code = code;
3126         i->status = status;
3127
3128         r = sd_bus_message_exit_container(m);
3129         if (r < 0)
3130                 return bus_log_parse_error(r);
3131
3132         return 1;
3133 }
3134
3135 typedef struct UnitStatusInfo {
3136         const char *id;
3137         const char *load_state;
3138         const char *active_state;
3139         const char *sub_state;
3140         const char *unit_file_state;
3141
3142         const char *description;
3143         const char *following;
3144
3145         char **documentation;
3146
3147         const char *fragment_path;
3148         const char *source_path;
3149         const char *control_group;
3150
3151         char **dropin_paths;
3152
3153         const char *load_error;
3154         const char *result;
3155
3156         usec_t inactive_exit_timestamp;
3157         usec_t inactive_exit_timestamp_monotonic;
3158         usec_t active_enter_timestamp;
3159         usec_t active_exit_timestamp;
3160         usec_t inactive_enter_timestamp;
3161
3162         bool need_daemon_reload;
3163
3164         /* Service */
3165         pid_t main_pid;
3166         pid_t control_pid;
3167         const char *status_text;
3168         const char *pid_file;
3169         bool running:1;
3170
3171         usec_t start_timestamp;
3172         usec_t exit_timestamp;
3173
3174         int exit_code, exit_status;
3175
3176         usec_t condition_timestamp;
3177         bool condition_result;
3178         bool failed_condition_trigger;
3179         bool failed_condition_negate;
3180         const char *failed_condition;
3181         const char *failed_condition_param;
3182
3183         /* Socket */
3184         unsigned n_accepted;
3185         unsigned n_connections;
3186         bool accept;
3187
3188         /* Pairs of type, path */
3189         char **listen;
3190
3191         /* Device */
3192         const char *sysfs_path;
3193
3194         /* Mount, Automount */
3195         const char *where;
3196
3197         /* Swap */
3198         const char *what;
3199
3200         LIST_HEAD(ExecStatusInfo, exec);
3201 } UnitStatusInfo;
3202
3203 static void print_status_info(
3204                 UnitStatusInfo *i,
3205                 bool *ellipsized) {
3206
3207         ExecStatusInfo *p;
3208         const char *active_on, *active_off, *on, *off, *ss;
3209         usec_t timestamp;
3210         char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
3211         char since2[FORMAT_TIMESTAMP_MAX], *s2;
3212         const char *path;
3213         int flags =
3214                 arg_all * OUTPUT_SHOW_ALL |
3215                 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
3216                 on_tty() * OUTPUT_COLOR |
3217                 !arg_quiet * OUTPUT_WARN_CUTOFF |
3218                 arg_full * OUTPUT_FULL_WIDTH;
3219         char **t, **t2;
3220
3221         assert(i);
3222
3223         /* This shows pretty information about a unit. See
3224          * print_property() for a low-level property printer */
3225
3226         if (streq_ptr(i->active_state, "failed")) {
3227                 active_on = ansi_highlight_red();
3228                 active_off = ansi_highlight_off();
3229         } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
3230                 active_on = ansi_highlight_green();
3231                 active_off = ansi_highlight_off();
3232         } else
3233                 active_on = active_off = "";
3234
3235         printf("%s%s%s %s", active_on, draw_special_char(DRAW_BLACK_CIRCLE), active_off, strna(i->id));
3236
3237         if (i->description && !streq_ptr(i->id, i->description))
3238                 printf(" - %s", i->description);
3239
3240         printf("\n");
3241
3242         if (i->following)
3243                 printf("   Follow: unit currently follows state of %s\n", i->following);
3244
3245         if (streq_ptr(i->load_state, "error")) {
3246                 on = ansi_highlight_red();
3247                 off = ansi_highlight_off();
3248         } else
3249                 on = off = "";
3250
3251         path = i->source_path ? i->source_path : i->fragment_path;
3252
3253         if (i->load_error)
3254                 printf("   Loaded: %s%s%s (Reason: %s)\n",
3255                        on, strna(i->load_state), off, i->load_error);
3256         else if (path && i->unit_file_state)
3257                 printf("   Loaded: %s%s%s (%s; %s)\n",
3258                        on, strna(i->load_state), off, path, i->unit_file_state);
3259         else if (path)
3260                 printf("   Loaded: %s%s%s (%s)\n",
3261                        on, strna(i->load_state), off, path);
3262         else
3263                 printf("   Loaded: %s%s%s\n",
3264                        on, strna(i->load_state), off);
3265
3266         if (!strv_isempty(i->dropin_paths)) {
3267                 _cleanup_free_ char *dir = NULL;
3268                 bool last = false;
3269                 char ** dropin;
3270
3271                 STRV_FOREACH(dropin, i->dropin_paths) {
3272                         if (! dir || last) {
3273                                 printf(dir ? "        " : "  Drop-In: ");
3274
3275                                 free(dir);
3276                                 dir = NULL;
3277
3278                                 if (path_get_parent(*dropin, &dir) < 0) {
3279                                         log_oom();
3280                                         return;
3281                                 }
3282
3283                                 printf("%s\n           %s", dir,
3284                                        draw_special_char(DRAW_TREE_RIGHT));
3285                         }
3286
3287                         last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
3288
3289                         printf("%s%s", basename(*dropin), last ? "\n" : ", ");
3290                 }
3291         }
3292
3293         ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
3294         if (ss)
3295                 printf("   Active: %s%s (%s)%s",
3296                        active_on, strna(i->active_state), ss, active_off);
3297         else
3298                 printf("   Active: %s%s%s",
3299                        active_on, strna(i->active_state), active_off);
3300
3301         if (!isempty(i->result) && !streq(i->result, "success"))
3302                 printf(" (Result: %s)", i->result);
3303
3304         timestamp = (streq_ptr(i->active_state, "active")      ||
3305                      streq_ptr(i->active_state, "reloading"))   ? i->active_enter_timestamp :
3306                     (streq_ptr(i->active_state, "inactive")    ||
3307                      streq_ptr(i->active_state, "failed"))      ? i->inactive_enter_timestamp :
3308                     streq_ptr(i->active_state, "activating")    ? i->inactive_exit_timestamp :
3309                                                                   i->active_exit_timestamp;
3310
3311         s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
3312         s2 = format_timestamp(since2, sizeof(since2), timestamp);
3313
3314         if (s1)
3315                 printf(" since %s; %s\n", s2, s1);
3316         else if (s2)
3317                 printf(" since %s\n", s2);
3318         else
3319                 printf("\n");
3320
3321         if (!i->condition_result && i->condition_timestamp > 0) {
3322                 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
3323                 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
3324
3325                 printf("           start condition failed at %s%s%s\n",
3326                        s2, s1 ? "; " : "", s1 ? s1 : "");
3327                 if (i->failed_condition_trigger)
3328                         printf("           none of the trigger conditions were met\n");
3329                 else if (i->failed_condition)
3330                         printf("           %s=%s%s was not met\n",
3331                                i->failed_condition,
3332                                i->failed_condition_negate ? "!" : "",
3333                                i->failed_condition_param);
3334         }
3335
3336         if (i->sysfs_path)
3337                 printf("   Device: %s\n", i->sysfs_path);
3338         if (i->where)
3339                 printf("    Where: %s\n", i->where);
3340         if (i->what)
3341                 printf("     What: %s\n", i->what);
3342
3343         STRV_FOREACH(t, i->documentation)
3344                 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
3345
3346         STRV_FOREACH_PAIR(t, t2, i->listen)
3347                 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
3348
3349         if (i->accept)
3350                 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
3351
3352         LIST_FOREACH(exec, p, i->exec) {
3353                 _cleanup_free_ char *argv = NULL;
3354                 bool good;
3355
3356                 /* Only show exited processes here */
3357                 if (p->code == 0)
3358                         continue;
3359
3360                 argv = strv_join(p->argv, " ");
3361                 printf("  Process: %u %s=%s ", p->pid, p->name, strna(argv));
3362
3363                 good = is_clean_exit_lsb(p->code, p->status, NULL);
3364                 if (!good) {
3365                         on = ansi_highlight_red();
3366                         off = ansi_highlight_off();
3367                 } else
3368                         on = off = "";
3369
3370                 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
3371
3372                 if (p->code == CLD_EXITED) {
3373                         const char *c;
3374
3375                         printf("status=%i", p->status);
3376
3377                         c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
3378                         if (c)
3379                                 printf("/%s", c);
3380
3381                 } else
3382                         printf("signal=%s", signal_to_string(p->status));
3383
3384                 printf(")%s\n", off);
3385
3386                 if (i->main_pid == p->pid &&
3387                     i->start_timestamp == p->start_timestamp &&
3388                     i->exit_timestamp == p->start_timestamp)
3389                         /* Let's not show this twice */
3390                         i->main_pid = 0;
3391
3392                 if (p->pid == i->control_pid)
3393                         i->control_pid = 0;
3394         }
3395
3396         if (i->main_pid > 0 || i->control_pid > 0) {
3397                 if (i->main_pid > 0) {
3398                         printf(" Main PID: %u", (unsigned) i->main_pid);
3399
3400                         if (i->running) {
3401                                 _cleanup_free_ char *comm = NULL;
3402                                 get_process_comm(i->main_pid, &comm);
3403                                 if (comm)
3404                                         printf(" (%s)", comm);
3405                         } else if (i->exit_code > 0) {
3406                                 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
3407
3408                                 if (i->exit_code == CLD_EXITED) {
3409                                         const char *c;
3410
3411                                         printf("status=%i", i->exit_status);
3412
3413                                         c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
3414                                         if (c)
3415                                                 printf("/%s", c);
3416
3417                                 } else
3418                                         printf("signal=%s", signal_to_string(i->exit_status));
3419                                 printf(")");
3420                         }
3421
3422                         if (i->control_pid > 0)
3423                                 printf(";");
3424                 }
3425
3426                 if (i->control_pid > 0) {
3427                         _cleanup_free_ char *c = NULL;
3428
3429                         printf(" %8s: %u", i->main_pid ? "" : " Control", (unsigned) i->control_pid);
3430
3431                         get_process_comm(i->control_pid, &c);
3432                         if (c)
3433                                 printf(" (%s)", c);
3434                 }
3435
3436                 printf("\n");
3437         }
3438
3439         if (i->status_text)
3440                 printf("   Status: \"%s\"\n", i->status_text);
3441
3442         if (i->control_group &&
3443             (i->main_pid > 0 || i->control_pid > 0 ||
3444              ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_CONTAINER) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) {
3445                 unsigned c;
3446
3447                 printf("   CGroup: %s\n", i->control_group);
3448
3449                 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
3450                         unsigned k = 0;
3451                         pid_t extra[2];
3452                         static const char prefix[] = "           ";
3453
3454                         c = columns();
3455                         if (c > sizeof(prefix) - 1)
3456                                 c -= sizeof(prefix) - 1;
3457                         else
3458                                 c = 0;
3459
3460                         if (i->main_pid > 0)
3461                                 extra[k++] = i->main_pid;
3462
3463                         if (i->control_pid > 0)
3464                                 extra[k++] = i->control_pid;
3465
3466                         show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, false, extra, k, flags);
3467                 }
3468         }
3469
3470         if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) {
3471                 show_journal_by_unit(stdout,
3472                                      i->id,
3473                                      arg_output,
3474                                      0,
3475                                      i->inactive_exit_timestamp_monotonic,
3476                                      arg_lines,
3477                                      getuid(),
3478                                      flags | OUTPUT_BEGIN_NEWLINE,
3479                                      arg_scope == UNIT_FILE_SYSTEM,
3480                                      ellipsized);
3481         }
3482
3483         if (i->need_daemon_reload)
3484                 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
3485                        ansi_highlight_red(),
3486                        ansi_highlight_off(),
3487                        arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
3488 }
3489
3490 static void show_unit_help(UnitStatusInfo *i) {
3491         char **p;
3492
3493         assert(i);
3494
3495         if (!i->documentation) {
3496                 log_info("Documentation for %s not known.", i->id);
3497                 return;
3498         }
3499
3500         STRV_FOREACH(p, i->documentation) {
3501
3502                 if (startswith(*p, "man:")) {
3503                         const char *args[4] = { "man", NULL, NULL, NULL };
3504                         _cleanup_free_ char *page = NULL, *section = NULL;
3505                         char *e = NULL;
3506                         pid_t pid;
3507                         size_t k;
3508
3509                         k = strlen(*p);
3510
3511                         if ((*p)[k-1] == ')')
3512                                 e = strrchr(*p, '(');
3513
3514                         if (e) {
3515                                 page = strndup((*p) + 4, e - *p - 4);
3516                                 section = strndup(e + 1, *p + k - e - 2);
3517                                 if (!page || !section) {
3518                                         log_oom();
3519                                         return;
3520                                 }
3521
3522                                 args[1] = section;
3523                                 args[2] = page;
3524                         } else
3525                                 args[1] = *p + 4;
3526
3527                         pid = fork();
3528                         if (pid < 0) {
3529                                 log_error("Failed to fork: %m");
3530                                 continue;
3531                         }
3532
3533                         if (pid == 0) {
3534                                 /* Child */
3535                                 execvp(args[0], (char**) args);
3536                                 log_error("Failed to execute man: %m");
3537                                 _exit(EXIT_FAILURE);
3538                         }
3539
3540                         wait_for_terminate(pid, NULL);
3541                 } else
3542                         log_info("Can't show: %s", *p);
3543         }
3544 }
3545
3546 static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) {
3547         int r;
3548
3549         assert(name);
3550         assert(m);
3551         assert(i);
3552
3553         switch (contents[0]) {
3554
3555         case SD_BUS_TYPE_STRING: {
3556                 const char *s;
3557
3558                 r = sd_bus_message_read(m, "s", &s);
3559                 if (r < 0)
3560                         return bus_log_parse_error(r);
3561
3562                 if (!isempty(s)) {
3563                         if (streq(name, "Id"))
3564                                 i->id = s;
3565                         else if (streq(name, "LoadState"))
3566                                 i->load_state = s;
3567                         else if (streq(name, "ActiveState"))
3568                                 i->active_state = s;
3569                         else if (streq(name, "SubState"))
3570                                 i->sub_state = s;
3571                         else if (streq(name, "Description"))
3572                                 i->description = s;
3573                         else if (streq(name, "FragmentPath"))
3574                                 i->fragment_path = s;
3575                         else if (streq(name, "SourcePath"))
3576                                 i->source_path = s;
3577 #ifndef NOLEGACY
3578                         else if (streq(name, "DefaultControlGroup")) {
3579                                 const char *e;
3580                                 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
3581                                 if (e)
3582                                         i->control_group = e;
3583                         }
3584 #endif
3585                         else if (streq(name, "ControlGroup"))
3586                                 i->control_group = s;
3587                         else if (streq(name, "StatusText"))
3588                                 i->status_text = s;
3589                         else if (streq(name, "PIDFile"))
3590                                 i->pid_file = s;
3591                         else if (streq(name, "SysFSPath"))
3592                                 i->sysfs_path = s;
3593                         else if (streq(name, "Where"))
3594                                 i->where = s;
3595                         else if (streq(name, "What"))
3596                                 i->what = s;
3597                         else if (streq(name, "Following"))
3598                                 i->following = s;
3599                         else if (streq(name, "UnitFileState"))
3600                                 i->unit_file_state = s;
3601                         else if (streq(name, "Result"))
3602                                 i->result = s;
3603                 }
3604
3605                 break;
3606         }
3607
3608         case SD_BUS_TYPE_BOOLEAN: {
3609                 int b;
3610
3611                 r = sd_bus_message_read(m, "b", &b);
3612                 if (r < 0)
3613                         return bus_log_parse_error(r);
3614
3615                 if (streq(name, "Accept"))
3616                         i->accept = b;
3617                 else if (streq(name, "NeedDaemonReload"))
3618                         i->need_daemon_reload = b;
3619                 else if (streq(name, "ConditionResult"))
3620                         i->condition_result = b;
3621
3622                 break;
3623         }
3624
3625         case SD_BUS_TYPE_UINT32: {
3626                 uint32_t u;
3627
3628                 r = sd_bus_message_read(m, "u", &u);
3629                 if (r < 0)
3630                         return bus_log_parse_error(r);
3631
3632                 if (streq(name, "MainPID")) {
3633                         if (u > 0) {
3634                                 i->main_pid = (pid_t) u;
3635                                 i->running = true;
3636                         }
3637                 } else if (streq(name, "ControlPID"))
3638                         i->control_pid = (pid_t) u;
3639                 else if (streq(name, "ExecMainPID")) {
3640                         if (u > 0)
3641                                 i->main_pid = (pid_t) u;
3642                 } else if (streq(name, "NAccepted"))
3643                         i->n_accepted = u;
3644                 else if (streq(name, "NConnections"))
3645                         i->n_connections = u;
3646
3647                 break;
3648         }
3649
3650         case SD_BUS_TYPE_INT32: {
3651                 int32_t j;
3652
3653                 r = sd_bus_message_read(m, "i", &j);
3654                 if (r < 0)
3655                         return bus_log_parse_error(r);
3656
3657                 if (streq(name, "ExecMainCode"))
3658                         i->exit_code = (int) j;
3659                 else if (streq(name, "ExecMainStatus"))
3660                         i->exit_status = (int) j;
3661
3662                 break;
3663         }
3664
3665         case SD_BUS_TYPE_UINT64: {
3666                 uint64_t u;
3667
3668                 r = sd_bus_message_read(m, "t", &u);
3669                 if (r < 0)
3670                         return bus_log_parse_error(r);
3671
3672                 if (streq(name, "ExecMainStartTimestamp"))
3673                         i->start_timestamp = (usec_t) u;
3674                 else if (streq(name, "ExecMainExitTimestamp"))
3675                         i->exit_timestamp = (usec_t) u;
3676                 else if (streq(name, "ActiveEnterTimestamp"))
3677                         i->active_enter_timestamp = (usec_t) u;
3678                 else if (streq(name, "InactiveEnterTimestamp"))
3679                         i->inactive_enter_timestamp = (usec_t) u;
3680                 else if (streq(name, "InactiveExitTimestamp"))
3681                         i->inactive_exit_timestamp = (usec_t) u;
3682                 else if (streq(name, "InactiveExitTimestampMonotonic"))
3683                         i->inactive_exit_timestamp_monotonic = (usec_t) u;
3684                 else if (streq(name, "ActiveExitTimestamp"))
3685                         i->active_exit_timestamp = (usec_t) u;
3686                 else if (streq(name, "ConditionTimestamp"))
3687                         i->condition_timestamp = (usec_t) u;
3688
3689                 break;
3690         }
3691
3692         case SD_BUS_TYPE_ARRAY:
3693
3694                 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3695                         _cleanup_free_ ExecStatusInfo *info = NULL;
3696
3697                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3698                         if (r < 0)
3699                                 return bus_log_parse_error(r);
3700
3701                         info = new0(ExecStatusInfo, 1);
3702                         if (!info)
3703                                 return log_oom();
3704
3705                         while ((r = exec_status_info_deserialize(m, info)) > 0) {
3706
3707                                 info->name = strdup(name);
3708                                 if (!info->name)
3709                                         log_oom();
3710
3711                                 LIST_PREPEND(exec, i->exec, info);
3712
3713                                 info = new0(ExecStatusInfo, 1);
3714                                 if (!info)
3715                                         log_oom();
3716                         }
3717
3718                         if (r < 0)
3719                                 return bus_log_parse_error(r);
3720
3721                         r = sd_bus_message_exit_container(m);
3722                         if (r < 0)
3723                                 return bus_log_parse_error(r);
3724
3725                         return 0;
3726
3727                 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3728                         const char *type, *path;
3729
3730                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3731                         if (r < 0)
3732                                 return bus_log_parse_error(r);
3733
3734                         while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
3735
3736                                 r = strv_extend(&i->listen, type);
3737                                 if (r < 0)
3738                                         return r;
3739
3740                                 r = strv_extend(&i->listen, path);
3741                                 if (r < 0)
3742                                         return r;
3743                         }
3744                         if (r < 0)
3745                                 return bus_log_parse_error(r);
3746
3747                         r = sd_bus_message_exit_container(m);
3748                         if (r < 0)
3749                                 return bus_log_parse_error(r);
3750
3751                         return 0;
3752
3753                 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "DropInPaths")) {
3754
3755                         r = sd_bus_message_read_strv(m, &i->dropin_paths);
3756                         if (r < 0)
3757                                 return bus_log_parse_error(r);
3758
3759                 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Documentation")) {
3760
3761                         r = sd_bus_message_read_strv(m, &i->documentation);
3762                         if (r < 0)
3763                                 return bus_log_parse_error(r);
3764
3765                 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Conditions")) {
3766                         const char *cond, *param;
3767                         int trigger, negate;
3768                         int32_t state;
3769
3770                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3771                         if (r < 0)
3772                                 return bus_log_parse_error(r);
3773
3774                         while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, &param, &state)) > 0) {
3775                                 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3776                                 if (state < 0 && (!trigger || !i->failed_condition)) {
3777                                         i->failed_condition = cond;
3778                                         i->failed_condition_trigger = trigger;
3779                                         i->failed_condition_negate = negate;
3780                                         i->failed_condition_param = param;
3781                                 }
3782                         }
3783                         if (r < 0)
3784                                 return bus_log_parse_error(r);
3785
3786                         r = sd_bus_message_exit_container(m);
3787                         if (r < 0)
3788                                 return bus_log_parse_error(r);
3789
3790                 } else
3791                         goto skip;
3792
3793                 break;
3794
3795         case SD_BUS_TYPE_STRUCT_BEGIN:
3796
3797                 if (streq(name, "LoadError")) {
3798                         const char *n, *message;
3799
3800                         r = sd_bus_message_read(m, "(ss)", &n, &message);
3801                         if (r < 0)
3802                                 return bus_log_parse_error(r);
3803
3804                         if (!isempty(message))
3805                                 i->load_error = message;
3806                 } else
3807                         goto skip;
3808
3809                 break;
3810
3811         default:
3812                 goto skip;
3813         }
3814
3815         return 0;
3816
3817 skip:
3818         r = sd_bus_message_skip(m, contents);
3819         if (r < 0)
3820                 return bus_log_parse_error(r);
3821
3822         return 0;
3823 }
3824
3825 static int print_property(const char *name, sd_bus_message *m, const char *contents) {
3826         int r;
3827
3828         assert(name);
3829         assert(m);
3830
3831         /* This is a low-level property printer, see
3832          * print_status_info() for the nicer output */
3833
3834         if (arg_properties && !strv_find(arg_properties, name)) {
3835                 /* skip what we didn't read */
3836                 r = sd_bus_message_skip(m, contents);
3837                 return r;
3838         }
3839
3840         switch (contents[0]) {
3841
3842         case SD_BUS_TYPE_STRUCT_BEGIN:
3843
3844                 if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
3845                         uint32_t u;
3846
3847                         r = sd_bus_message_read(m, "(uo)", &u, NULL);
3848                         if (r < 0)
3849                                 return bus_log_parse_error(r);
3850
3851                         if (u > 0)
3852                                 printf("%s=%u\n", name, (unsigned) u);
3853                         else if (arg_all)
3854                                 printf("%s=\n", name);
3855
3856                         return 0;
3857
3858                 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
3859                         const char *s;
3860
3861                         r = sd_bus_message_read(m, "(so)", &s, NULL);
3862                         if (r < 0)
3863                                 return bus_log_parse_error(r);
3864
3865                         if (arg_all || !isempty(s))
3866                                 printf("%s=%s\n", name, s);
3867
3868                         return 0;
3869
3870                 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
3871                         const char *a = NULL, *b = NULL;
3872
3873                         r = sd_bus_message_read(m, "(ss)", &a, &b);
3874                         if (r < 0)
3875                                 return bus_log_parse_error(r);
3876
3877                         if (arg_all || !isempty(a) || !isempty(b))
3878                                 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3879
3880                         return 0;
3881                 } else if (streq_ptr(name, "SystemCallFilter")) {
3882                         _cleanup_strv_free_ char **l = NULL;
3883                         int whitelist;
3884
3885                         r = sd_bus_message_enter_container(m, 'r', "bas");
3886                         if (r < 0)
3887                                 return bus_log_parse_error(r);
3888
3889                         r = sd_bus_message_read(m, "b", &whitelist);
3890                         if (r < 0)
3891                                 return bus_log_parse_error(r);
3892
3893                         r = sd_bus_message_read_strv(m, &l);
3894                         if (r < 0)
3895                                 return bus_log_parse_error(r);
3896
3897                         r = sd_bus_message_exit_container(m);
3898                         if (r < 0)
3899                                 return bus_log_parse_error(r);
3900
3901                         if (arg_all || whitelist || !strv_isempty(l)) {
3902                                 bool first = true;
3903                                 char **i;
3904
3905                                 fputs(name, stdout);
3906                                 fputc('=', stdout);
3907
3908                                 if (!whitelist)
3909                                         fputc('~', stdout);
3910
3911                                 STRV_FOREACH(i, l) {
3912                                         if (first)
3913                                                 first = false;
3914                                         else
3915                                                 fputc(' ', stdout);
3916
3917                                         fputs(*i, stdout);
3918                                 }
3919                                 fputc('\n', stdout);
3920                         }
3921
3922                         return 0;
3923                 }
3924
3925                 break;
3926
3927         case SD_BUS_TYPE_ARRAY:
3928
3929                 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
3930                         const char *path;
3931                         int ignore;
3932
3933                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)");
3934                         if (r < 0)
3935                                 return bus_log_parse_error(r);
3936
3937                         while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
3938                                 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3939
3940                         if (r < 0)
3941                                 return bus_log_parse_error(r);
3942
3943                         r = sd_bus_message_exit_container(m);
3944                         if (r < 0)
3945                                 return bus_log_parse_error(r);
3946
3947                         return 0;
3948
3949                 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
3950                         const char *type, *path;
3951
3952                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3953                         if (r < 0)
3954                                 return bus_log_parse_error(r);
3955
3956                         while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
3957                                 printf("%s=%s\n", type, path);
3958                         if (r < 0)
3959                                 return bus_log_parse_error(r);
3960
3961                         r = sd_bus_message_exit_container(m);
3962                         if (r < 0)
3963                                 return bus_log_parse_error(r);
3964
3965                         return 0;
3966
3967                 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3968                         const char *type, *path;
3969
3970                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3971                         if (r < 0)
3972                                 return bus_log_parse_error(r);
3973
3974                         while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
3975                                 printf("Listen%s=%s\n", type, path);
3976                         if (r < 0)
3977                                 return bus_log_parse_error(r);
3978
3979                         r = sd_bus_message_exit_container(m);
3980                         if (r < 0)
3981                                 return bus_log_parse_error(r);
3982
3983                         return 0;
3984
3985                 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Timers")) {
3986                         const char *base;
3987                         uint64_t value, next_elapse;
3988
3989                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
3990                         if (r < 0)
3991                                 return bus_log_parse_error(r);
3992
3993                         while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) {
3994                                 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3995
3996                                 printf("%s={ value=%s ; next_elapse=%s }\n",
3997                                        base,
3998                                        format_timespan(timespan1, sizeof(timespan1), value, 0),
3999                                        format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
4000                         }
4001                         if (r < 0)
4002                                 return bus_log_parse_error(r);
4003
4004                         r = sd_bus_message_exit_container(m);
4005                         if (r < 0)
4006                                 return bus_log_parse_error(r);
4007
4008                         return 0;
4009
4010                 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
4011                         ExecStatusInfo info = {};
4012
4013                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
4014                         if (r < 0)
4015                                 return bus_log_parse_error(r);
4016
4017                         while ((r = exec_status_info_deserialize(m, &info)) > 0) {
4018                                 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
4019                                 _cleanup_free_ char *tt;
4020
4021                                 tt = strv_join(info.argv, " ");
4022
4023                                 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
4024                                        name,
4025                                        strna(info.path),
4026                                        strna(tt),
4027                                        yes_no(info.ignore),
4028                                        strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
4029                                        strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
4030                                        (unsigned) info. pid,
4031                                        sigchld_code_to_string(info.code),
4032                                        info.status,
4033                                        info.code == CLD_EXITED ? "" : "/",
4034                                        strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
4035
4036                                 free(info.path);
4037                                 strv_free(info.argv);
4038                                 zero(info);
4039                         }
4040
4041                         r = sd_bus_message_exit_container(m);
4042                         if (r < 0)
4043                                 return bus_log_parse_error(r);
4044
4045                         return 0;
4046
4047                 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
4048                         const char *path, *rwm;
4049
4050                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4051                         if (r < 0)
4052                                 return bus_log_parse_error(r);
4053
4054                         while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
4055                                 printf("%s=%s %s\n", name, strna(path), strna(rwm));
4056                         if (r < 0)
4057                                 return bus_log_parse_error(r);
4058
4059                         r = sd_bus_message_exit_container(m);
4060                         if (r < 0)
4061                                 return bus_log_parse_error(r);
4062
4063                         return 0;
4064
4065                 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "BlockIODeviceWeight")) {
4066                         const char *path;
4067                         uint64_t weight;
4068
4069                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4070                         if (r < 0)
4071                                 return bus_log_parse_error(r);
4072
4073                         while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
4074                                 printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
4075                         if (r < 0)
4076                                 return bus_log_parse_error(r);
4077
4078                         r = sd_bus_message_exit_container(m);
4079                         if (r < 0)
4080                                 return bus_log_parse_error(r);
4081
4082                         return 0;
4083
4084                 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
4085                         const char *path;
4086                         uint64_t bandwidth;
4087
4088                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4089                         if (r < 0)
4090                                 return bus_log_parse_error(r);
4091
4092                         while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
4093                                 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
4094                         if (r < 0)
4095                                 return bus_log_parse_error(r);
4096
4097                         r = sd_bus_message_exit_container(m);
4098                         if (r < 0)
4099                                 return bus_log_parse_error(r);
4100
4101                         return 0;
4102                 }
4103
4104                 break;
4105         }
4106
4107         r = bus_print_property(name, m, arg_all);
4108         if (r < 0)
4109                 return bus_log_parse_error(r);
4110
4111         if (r == 0) {
4112                 r = sd_bus_message_skip(m, contents);
4113                 if (r < 0)
4114                         return bus_log_parse_error(r);
4115
4116                 if (arg_all)
4117                         printf("%s=[unprintable]\n", name);
4118         }
4119
4120         return 0;
4121 }
4122
4123 static int show_one(
4124                 const char *verb,
4125                 sd_bus *bus,
4126                 const char *path,
4127                 bool show_properties,
4128                 bool *new_line,
4129                 bool *ellipsized) {
4130
4131         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4132         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4133         UnitStatusInfo info = {};
4134         ExecStatusInfo *p;
4135         int r;
4136
4137         assert(path);
4138         assert(new_line);
4139
4140         log_debug("Showing one %s", path);
4141
4142         r = sd_bus_call_method(
4143                         bus,
4144                         "org.freedesktop.systemd1",
4145                         path,
4146                         "org.freedesktop.DBus.Properties",
4147                         "GetAll",
4148                         &error,
4149                         &reply,
4150                         "s", "");
4151         if (r < 0) {
4152                 log_error("Failed to get properties: %s", bus_error_message(&error, r));
4153                 return r;
4154         }
4155
4156         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
4157         if (r < 0)
4158                 return bus_log_parse_error(r);
4159
4160         if (*new_line)
4161                 printf("\n");
4162
4163         *new_line = true;
4164
4165         while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
4166                 const char *name, *contents;
4167
4168                 r = sd_bus_message_read(reply, "s", &name);
4169                 if (r < 0)
4170                         return bus_log_parse_error(r);
4171
4172                 r = sd_bus_message_peek_type(reply, NULL, &contents);
4173                 if (r < 0)
4174                         return bus_log_parse_error(r);
4175
4176                 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
4177                 if (r < 0)
4178                         return bus_log_parse_error(r);
4179
4180                 if (show_properties)
4181                         r = print_property(name, reply, contents);
4182                 else
4183                         r = status_property(name, reply, &info, contents);
4184                 if (r < 0)
4185                         return r;
4186
4187                 r = sd_bus_message_exit_container(reply);
4188                 if (r < 0)
4189                         return bus_log_parse_error(r);
4190
4191                 r = sd_bus_message_exit_container(reply);
4192                 if (r < 0)
4193                         return bus_log_parse_error(r);
4194         }
4195         if (r < 0)
4196                 return bus_log_parse_error(r);
4197
4198         r = sd_bus_message_exit_container(reply);
4199         if (r < 0)
4200                 return bus_log_parse_error(r);
4201
4202         r = 0;
4203
4204         if (!show_properties) {
4205                 if (streq(verb, "help"))
4206                         show_unit_help(&info);
4207                 else
4208                         print_status_info(&info, ellipsized);
4209         }
4210
4211         strv_free(info.documentation);
4212         strv_free(info.dropin_paths);
4213         strv_free(info.listen);
4214
4215         if (!streq_ptr(info.active_state, "active") &&
4216             !streq_ptr(info.active_state, "reloading") &&
4217             streq(verb, "status")) {
4218                 /* According to LSB: "program not running" */
4219                 /* 0: program is running or service is OK
4220                  * 1: program is dead and /run PID file exists
4221                  * 2: program is dead and /run/lock lock file exists
4222                  * 3: program is not running
4223                  * 4: program or service status is unknown
4224                  */
4225                 if (info.pid_file && access(info.pid_file, F_OK) == 0)
4226                         r = 1;
4227                 else
4228                         r = 3;
4229         }
4230
4231         while ((p = info.exec)) {
4232                 LIST_REMOVE(exec, info.exec, p);
4233                 exec_status_info_free(p);
4234         }
4235
4236         return r;
4237 }
4238
4239 static int get_unit_dbus_path_by_pid(
4240                 sd_bus *bus,
4241                 uint32_t pid,
4242                 char **unit) {
4243
4244         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4245         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4246         char *u;
4247         int r;
4248
4249         r = sd_bus_call_method(
4250                         bus,
4251                         "org.freedesktop.systemd1",
4252                         "/org/freedesktop/systemd1",
4253                         "org.freedesktop.systemd1.Manager",
4254                         "GetUnitByPID",
4255                         &error,
4256                         &reply,
4257                         "u", pid);
4258         if (r < 0) {
4259                 log_error("Failed to get unit for PID "PID_FMT": %s", pid, bus_error_message(&error, r));
4260                 return r;
4261         }
4262
4263         r = sd_bus_message_read(reply, "o", &u);
4264         if (r < 0)
4265                 return bus_log_parse_error(r);
4266
4267         u = strdup(u);
4268         if (!u)
4269                 return log_oom();
4270
4271         *unit = u;
4272         return 0;
4273 }
4274
4275 static int show_all(
4276                 const char* verb,
4277                 sd_bus *bus,
4278                 bool show_properties,
4279                 bool *new_line,
4280                 bool *ellipsized) {
4281
4282         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4283         _cleanup_free_ UnitInfo *unit_infos = NULL;
4284         const UnitInfo *u;
4285         unsigned c;
4286         int r, ret = 0;
4287
4288         r = get_unit_list(bus, NULL, NULL, &unit_infos, 0, &reply);
4289         if (r < 0)
4290                 return r;
4291
4292         pager_open_if_enabled();
4293
4294         c = (unsigned) r;
4295
4296         qsort_safe(unit_infos, c, sizeof(UnitInfo), compare_unit_info);
4297
4298         for (u = unit_infos; u < unit_infos + c; u++) {
4299                 _cleanup_free_ char *p = NULL;
4300
4301                 p = unit_dbus_path_from_name(u->id);
4302                 if (!p)
4303                         return log_oom();
4304
4305                 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
4306                 if (r < 0)
4307                         return r;
4308                 else if (r > 0 && ret == 0)
4309                         ret = r;
4310         }
4311
4312         return ret;
4313 }
4314
4315 static int show_system_status(sd_bus *bus) {
4316         char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
4317         _cleanup_free_ char *hn = NULL;
4318         struct machine_info mi = {};
4319         const char *on, *off;
4320         int r;
4321
4322         hn = gethostname_malloc();
4323         if (!hn)
4324                 return log_oom();
4325
4326         r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &mi);
4327         if (r < 0) {
4328                 log_error("Failed to read server status: %s", strerror(-r));
4329                 return r;
4330         }
4331
4332         if (streq_ptr(mi.state, "degraded")) {
4333                 on = ansi_highlight_red();
4334                 off = ansi_highlight_off();
4335         } else if (!streq_ptr(mi.state, "running")) {
4336                 on = ansi_highlight_yellow();
4337                 off = ansi_highlight_off();
4338         } else
4339                 on = off = "";
4340
4341         printf("%s%s%s %s\n", on, draw_special_char(DRAW_BLACK_CIRCLE), off, arg_host ? arg_host : hn);
4342
4343         printf("    State: %s%s%s\n",
4344                on, strna(mi.state), off);
4345
4346         printf("     Jobs: %u queued\n", mi.n_jobs);
4347         printf("   Failed: %u units\n", mi.n_failed_units);
4348
4349         printf("    Since: %s; %s\n",
4350                format_timestamp(since2, sizeof(since2), mi.timestamp),
4351                format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
4352
4353         printf("   CGroup: %s\n", mi.control_group ?: "/");
4354         if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
4355                 int flags =
4356                         arg_all * OUTPUT_SHOW_ALL |
4357                         (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
4358                         on_tty() * OUTPUT_COLOR |
4359                         !arg_quiet * OUTPUT_WARN_CUTOFF |
4360                         arg_full * OUTPUT_FULL_WIDTH;
4361
4362                 static const char prefix[] = "           ";
4363                 unsigned c;
4364
4365                 c = columns();
4366                 if (c > sizeof(prefix) - 1)
4367                         c -= sizeof(prefix) - 1;
4368                 else
4369                         c = 0;
4370
4371                 show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, flags);
4372         }
4373
4374         free(mi.state);
4375         free(mi.control_group);
4376
4377         return 0;
4378 }
4379
4380 static int show(sd_bus *bus, char **args) {
4381         bool show_properties, show_status, new_line = false;
4382         bool ellipsized = false;
4383         int r, ret = 0;
4384
4385         assert(bus);
4386         assert(args);
4387
4388         show_properties = streq(args[0], "show");
4389         show_status = streq(args[0], "status");
4390
4391         if (show_properties)
4392                 pager_open_if_enabled();
4393
4394         /* If no argument is specified inspect the manager itself */
4395
4396         if (show_properties && strv_length(args) <= 1)
4397                 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
4398
4399         if (show_status && strv_length(args) <= 1) {
4400
4401                 pager_open_if_enabled();
4402                 show_system_status(bus);
4403                 new_line = true;
4404
4405                 if (arg_all)
4406                         ret = show_all(args[0], bus, false, &new_line, &ellipsized);
4407         } else {
4408                 _cleanup_free_ char **patterns = NULL;
4409                 char **name;
4410
4411                 STRV_FOREACH(name, args + 1) {
4412                         _cleanup_free_ char *unit = NULL;
4413                         uint32_t id;
4414
4415                         if (safe_atou32(*name, &id) < 0) {
4416                                 if (strv_push(&patterns, *name) < 0)
4417                                         return log_oom();
4418
4419                                 continue;
4420                         } else if (show_properties) {
4421                                 /* Interpret as job id */
4422                                 if (asprintf(&unit, "/org/freedesktop/systemd1/job/%u", id) < 0)
4423                                         return log_oom();
4424
4425                         } else {
4426                                 /* Interpret as PID */
4427                                 r = get_unit_dbus_path_by_pid(bus, id, &unit);
4428                                 if (r < 0) {
4429                                         ret = r;
4430                                         continue;
4431                                 }
4432                         }
4433
4434                         r = show_one(args[0], bus, unit, show_properties,
4435                                      &new_line, &ellipsized);
4436                         if (r < 0)
4437                                 return r;
4438                         else if (r > 0 && ret == 0)
4439                                 ret = r;
4440                 }
4441
4442                 if (!strv_isempty(patterns)) {
4443                         _cleanup_strv_free_ char **names = NULL;
4444
4445                         r = expand_names(bus, patterns, NULL, &names);
4446                         if (r < 0)
4447                                 log_error("Failed to expand names: %s", strerror(-r));
4448
4449                         STRV_FOREACH(name, names) {
4450                                 _cleanup_free_ char *unit;
4451
4452                                 unit = unit_dbus_path_from_name(*name);
4453                                 if (!unit)
4454                                         return log_oom();
4455
4456                                 r = show_one(args[0], bus, unit, show_properties,
4457                                              &new_line, &ellipsized);
4458                                 if (r < 0)
4459                                         return r;
4460                                 else if (r > 0 && ret == 0)
4461                                         ret = r;
4462                         }
4463                 }
4464         }
4465
4466         if (ellipsized && !arg_quiet)
4467                 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4468
4469         return ret;
4470 }
4471
4472 static int cat(sd_bus *bus, char **args) {
4473         _cleanup_free_ char *unit = NULL;
4474         _cleanup_strv_free_ char **names = NULL;
4475         char **name;
4476         bool first = true;
4477         int r = 0;
4478
4479         assert(bus);
4480         assert(args);
4481
4482         r = expand_names(bus, args + 1, NULL, &names);
4483         if (r < 0)
4484                 log_error("Failed to expand names: %s", strerror(-r));
4485
4486         pager_open_if_enabled();
4487
4488         STRV_FOREACH(name, names) {
4489                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4490                 _cleanup_strv_free_ char **dropin_paths = NULL;
4491                 _cleanup_free_ char *fragment_path = NULL;
4492                 char **path;
4493
4494                 unit = unit_dbus_path_from_name(*name);
4495                 if (!unit)
4496                         return log_oom();
4497
4498                 if (need_daemon_reload(bus, *name) > 0)
4499                         log_warning("Unit file of %s changed on disk. Run 'systemctl%s daemon-reload'.",
4500                                     *name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
4501
4502                 r = sd_bus_get_property_string(
4503                                 bus,
4504                                 "org.freedesktop.systemd1",
4505                                 unit,
4506                                 "org.freedesktop.systemd1.Unit",
4507                                 "FragmentPath",
4508                                 &error,
4509                                 &fragment_path);
4510                 if (r < 0) {
4511                         log_warning("Failed to get FragmentPath: %s", bus_error_message(&error, r));
4512                         continue;
4513                 }
4514
4515                 r = sd_bus_get_property_strv(
4516                                 bus,
4517                                 "org.freedesktop.systemd1",
4518                                 unit,
4519                                 "org.freedesktop.systemd1.Unit",
4520                                 "DropInPaths",
4521                                 &error,
4522                                 &dropin_paths);
4523                 if (r < 0) {
4524                         log_warning("Failed to get DropInPaths: %s", bus_error_message(&error, r));
4525                         continue;
4526                 }
4527
4528                 if (first)
4529                         first = false;
4530                 else
4531                         puts("");
4532
4533                 if (!isempty(fragment_path)) {
4534                         printf("%s# %s%s\n",
4535                                ansi_highlight_blue(),
4536                                fragment_path,
4537                                ansi_highlight_off());
4538                         fflush(stdout);
4539
4540                         r = sendfile_full(STDOUT_FILENO, fragment_path);
4541                         if (r < 0) {
4542                                 log_warning("Failed to cat %s: %s", fragment_path, strerror(-r));
4543                                 continue;
4544                         }
4545                 }
4546
4547                 STRV_FOREACH(path, dropin_paths) {
4548                         printf("%s%s# %s%s\n",
4549                                isempty(fragment_path) && path == dropin_paths ? "" : "\n",
4550                                ansi_highlight_blue(),
4551                                *path,
4552                                ansi_highlight_off());
4553                         fflush(stdout);
4554
4555                         r = sendfile_full(STDOUT_FILENO, *path);
4556                         if (r < 0) {
4557                                 log_warning("Failed to cat %s: %s", *path, strerror(-r));
4558                                 continue;
4559                         }
4560                 }
4561         }
4562
4563         return r < 0 ? r : 0;
4564 }
4565
4566 static int set_property(sd_bus *bus, char **args) {
4567         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4568         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4569         _cleanup_free_ char *n = NULL;
4570         char **i;
4571         int r;
4572
4573         r = sd_bus_message_new_method_call(
4574                         bus,
4575                         &m,
4576                         "org.freedesktop.systemd1",
4577                         "/org/freedesktop/systemd1",
4578                         "org.freedesktop.systemd1.Manager",
4579                         "SetUnitProperties");
4580         if (r < 0)
4581                 return bus_log_create_error(r);
4582
4583         n = unit_name_mangle(args[1], MANGLE_NOGLOB);
4584         if (!n)
4585                 return log_oom();
4586
4587         r = sd_bus_message_append(m, "sb", n, arg_runtime);
4588         if (r < 0)
4589                 return bus_log_create_error(r);
4590
4591         r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)");
4592         if (r < 0)
4593                 return bus_log_create_error(r);
4594
4595         STRV_FOREACH(i, args + 2) {
4596                 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
4597                 if (r < 0)
4598                         return bus_log_create_error(r);
4599
4600                 r = bus_append_unit_property_assignment(m, *i);
4601                 if (r < 0)
4602                         return r;
4603
4604                 r = sd_bus_message_close_container(m);
4605                 if (r < 0)
4606                         return bus_log_create_error(r);
4607         }
4608
4609         r = sd_bus_message_close_container(m);
4610         if (r < 0)
4611                 return bus_log_create_error(r);
4612
4613         r = sd_bus_call(bus, m, 0, &error, NULL);
4614         if (r < 0) {
4615                 log_error("Failed to set unit properties on %s: %s", n, bus_error_message(&error, r));
4616                 return r;
4617         }
4618
4619         return 0;
4620 }
4621
4622 static int snapshot(sd_bus *bus, char **args) {
4623         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4624         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4625         _cleanup_free_ char *n = NULL, *id = NULL;
4626         const char *path;
4627         int r;
4628
4629         if (strv_length(args) > 1)
4630                 n = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".snapshot");
4631         else
4632                 n = strdup("");
4633         if (!n)
4634                 return log_oom();
4635
4636         r = sd_bus_call_method(
4637                         bus,
4638                         "org.freedesktop.systemd1",
4639                         "/org/freedesktop/systemd1",
4640                         "org.freedesktop.systemd1.Manager",
4641                         "CreateSnapshot",
4642                         &error,
4643                         &reply,
4644                         "sb", n, false);
4645         if (r < 0) {
4646                 log_error("Failed to create snapshot: %s", bus_error_message(&error, r));
4647                 return r;
4648         }
4649
4650         r = sd_bus_message_read(reply, "o", &path);
4651         if (r < 0)
4652                 return bus_log_parse_error(r);
4653
4654         r = sd_bus_get_property_string(
4655                         bus,
4656                         "org.freedesktop.systemd1",
4657                         path,
4658                         "org.freedesktop.systemd1.Unit",
4659                         "Id",
4660                         &error,
4661                         &id);
4662         if (r < 0) {
4663                 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error, r));
4664                 return r;
4665         }
4666
4667         if (!arg_quiet)
4668                 puts(id);
4669
4670         return 0;
4671 }
4672
4673 static int delete_snapshot(sd_bus *bus, char **args) {
4674         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4675         _cleanup_strv_free_ char **names = NULL;
4676         char **name;
4677         int r, q;
4678
4679         assert(args);
4680
4681         r = expand_names(bus, args + 1, ".snapshot", &names);
4682         if (r < 0)
4683                 log_error("Failed to expand names: %s", strerror(-r));
4684
4685         STRV_FOREACH(name, names) {
4686                 q = sd_bus_call_method(
4687                                 bus,
4688                                 "org.freedesktop.systemd1",
4689                                 "/org/freedesktop/systemd1",
4690                                 "org.freedesktop.systemd1.Manager",
4691                                 "RemoveSnapshot",
4692                                 &error,
4693                                 NULL,
4694                                 "s", *name);
4695                 if (q < 0) {
4696                         log_error("Failed to remove snapshot %s: %s",
4697                                   *name, bus_error_message(&error, r));
4698                         if (r == 0)
4699                                 r = q;
4700                 }
4701         }
4702
4703         return r;
4704 }
4705
4706 static int daemon_reload(sd_bus *bus, char **args) {
4707         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4708         const char *method;
4709         int r;
4710
4711         if (arg_action == ACTION_RELOAD)
4712                 method = "Reload";
4713         else if (arg_action == ACTION_REEXEC)
4714                 method = "Reexecute";
4715         else {
4716                 assert(arg_action == ACTION_SYSTEMCTL);
4717
4718                 method =
4719                         streq(args[0], "clear-jobs")    ||
4720                         streq(args[0], "cancel")        ? "ClearJobs" :
4721                         streq(args[0], "daemon-reexec") ? "Reexecute" :
4722                         streq(args[0], "reset-failed")  ? "ResetFailed" :
4723                         streq(args[0], "halt")          ? "Halt" :
4724                         streq(args[0], "poweroff")      ? "PowerOff" :
4725                         streq(args[0], "reboot")        ? "Reboot" :
4726                         streq(args[0], "kexec")         ? "KExec" :
4727                         streq(args[0], "exit")          ? "Exit" :
4728                                     /* "daemon-reload" */ "Reload";
4729         }
4730
4731         r = sd_bus_call_method(
4732                         bus,
4733                         "org.freedesktop.systemd1",
4734                         "/org/freedesktop/systemd1",
4735                         "org.freedesktop.systemd1.Manager",
4736                         method,
4737                         &error,
4738                         NULL,
4739                         NULL);
4740
4741         if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
4742                 /* There's always a fallback possible for
4743                  * legacy actions. */
4744                 r = -EADDRNOTAVAIL;
4745         else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
4746                 /* On reexecution, we expect a disconnect, not a
4747                  * reply */
4748                 r = 0;
4749         else if (r < 0)
4750                 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
4751
4752         return r < 0 ? r : 0;
4753 }
4754
4755 static int reset_failed(sd_bus *bus, char **args) {
4756         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4757         _cleanup_strv_free_ char **names = NULL;
4758         char **name;
4759         int r, q;
4760
4761         if (strv_length(args) <= 1)
4762                 return daemon_reload(bus, args);
4763
4764         r = expand_names(bus, args + 1, NULL, &names);
4765         if (r < 0)
4766                 log_error("Failed to expand names: %s", strerror(-r));
4767
4768         STRV_FOREACH(name, names) {
4769                 q = sd_bus_call_method(
4770                                 bus,
4771                                 "org.freedesktop.systemd1",
4772                                 "/org/freedesktop/systemd1",
4773                                 "org.freedesktop.systemd1.Manager",
4774                                 "ResetFailedUnit",
4775                                 &error,
4776                                 NULL,
4777                                 "s", *name);
4778                 if (q < 0) {
4779                         log_error("Failed to reset failed state of unit %s: %s",
4780                                   *name, bus_error_message(&error, r));
4781                         if (r == 0)
4782                                 r = q;
4783                 }
4784         }
4785
4786         return r;
4787 }
4788
4789 static int show_environment(sd_bus *bus, char **args) {
4790         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4791         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4792         const char *text;
4793         int r;
4794
4795         pager_open_if_enabled();
4796
4797         r = sd_bus_get_property(
4798                         bus,
4799                         "org.freedesktop.systemd1",
4800                         "/org/freedesktop/systemd1",
4801                         "org.freedesktop.systemd1.Manager",
4802                         "Environment",
4803                         &error,
4804                         &reply,
4805                         "as");
4806         if (r < 0) {
4807                 log_error("Failed to get environment: %s", bus_error_message(&error, r));
4808                 return r;
4809         }
4810
4811         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
4812         if (r < 0)
4813                 return bus_log_parse_error(r);
4814
4815         while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0)
4816                 puts(text);
4817         if (r < 0)
4818                 return bus_log_parse_error(r);
4819
4820         r = sd_bus_message_exit_container(reply);
4821         if (r < 0)
4822                 return bus_log_parse_error(r);
4823
4824         return 0;
4825 }
4826
4827 static int switch_root(sd_bus *bus, char **args) {
4828         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4829         _cleanup_free_ char *cmdline_init = NULL;
4830         const char *root, *init;
4831         unsigned l;
4832         int r;
4833
4834         l = strv_length(args);
4835         if (l < 2 || l > 3) {
4836                 log_error("Wrong number of arguments.");
4837                 return -EINVAL;
4838         }
4839
4840         root = args[1];
4841
4842         if (l >= 3)
4843                 init = args[2];
4844         else {
4845                 r = parse_env_file("/proc/cmdline", WHITESPACE,
4846                                    "init", &cmdline_init,
4847                                    NULL);
4848                 if (r < 0)
4849                         log_debug("Failed to parse /proc/cmdline: %s", strerror(-r));
4850
4851                 init = cmdline_init;
4852         }
4853
4854         if (isempty(init))
4855                 init = NULL;
4856
4857         if (init) {
4858                 const char *root_systemd_path = NULL, *root_init_path = NULL;
4859
4860                 root_systemd_path = strappenda(root, "/" SYSTEMD_BINARY_PATH);
4861                 root_init_path = strappenda3(root, "/", init);
4862
4863                 /* If the passed init is actually the same as the
4864                  * systemd binary, then let's suppress it. */
4865                 if (files_same(root_init_path, root_systemd_path) > 0)
4866                         init = NULL;
4867         }
4868
4869         log_debug("Switching root - root: %s; init: %s", root, strna(init));
4870
4871         r = sd_bus_call_method(
4872                         bus,
4873                         "org.freedesktop.systemd1",
4874                         "/org/freedesktop/systemd1",
4875                         "org.freedesktop.systemd1.Manager",
4876                         "SwitchRoot",
4877                         &error,
4878                         NULL,
4879                         "ss", root, init);
4880         if (r < 0) {
4881                 log_error("Failed to switch root: %s", bus_error_message(&error, r));
4882                 return r;
4883         }
4884
4885         return 0;
4886 }
4887
4888 static int set_environment(sd_bus *bus, char **args) {
4889         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4890         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4891         const char *method;
4892         int r;
4893
4894         assert(bus);
4895         assert(args);
4896
4897         method = streq(args[0], "set-environment")
4898                 ? "SetEnvironment"
4899                 : "UnsetEnvironment";
4900
4901         r = sd_bus_message_new_method_call(
4902                         bus,
4903                         &m,
4904                         "org.freedesktop.systemd1",
4905                         "/org/freedesktop/systemd1",
4906                         "org.freedesktop.systemd1.Manager",
4907                         method);
4908         if (r < 0)
4909                 return bus_log_create_error(r);
4910
4911         r = sd_bus_message_append_strv(m, args + 1);
4912         if (r < 0)
4913                 return bus_log_create_error(r);
4914
4915         r = sd_bus_call(bus, m, 0, &error, NULL);
4916         if (r < 0) {
4917                 log_error("Failed to set environment: %s", bus_error_message(&error, r));
4918                 return r;
4919         }
4920
4921         return 0;
4922 }
4923
4924 static int import_environment(sd_bus *bus, char **args) {
4925         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4926         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4927         int r;
4928
4929         assert(bus);
4930         assert(args);
4931
4932         r = sd_bus_message_new_method_call(
4933                         bus,
4934                         &m,
4935                         "org.freedesktop.systemd1",
4936                         "/org/freedesktop/systemd1",
4937                         "org.freedesktop.systemd1.Manager",
4938                         "SetEnvironment");
4939         if (r < 0)
4940                 return bus_log_create_error(r);
4941
4942         if (strv_isempty(args + 1))
4943                 r = sd_bus_message_append_strv(m, environ);
4944         else {
4945                 char **a, **b;
4946
4947                 r = sd_bus_message_open_container(m, 'a', "s");
4948                 if (r < 0)
4949                         return bus_log_create_error(r);
4950
4951                 STRV_FOREACH(a, args + 1) {
4952
4953                         if (!env_name_is_valid(*a)) {
4954                                 log_error("Not a valid environment variable name: %s", *a);
4955                                 return -EINVAL;
4956                         }
4957
4958                         STRV_FOREACH(b, environ) {
4959                                 const char *eq;
4960
4961                                 eq = startswith(*b, *a);
4962                                 if (eq && *eq == '=') {
4963
4964                                         r = sd_bus_message_append(m, "s", *b);
4965                                         if (r < 0)
4966                                                 return bus_log_create_error(r);
4967
4968                                         break;
4969                                 }
4970                         }
4971                 }
4972
4973                 r = sd_bus_message_close_container(m);
4974         }
4975         if (r < 0)
4976                 return bus_log_create_error(r);
4977
4978         r = sd_bus_call(bus, m, 0, &error, NULL);
4979         if (r < 0) {
4980                 log_error("Failed to import environment: %s", bus_error_message(&error, r));
4981                 return r;
4982         }
4983
4984         return 0;
4985 }
4986
4987 static int enable_sysv_units(const char *verb, char **args) {
4988         int r = 0;
4989
4990 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4991         unsigned f = 1, t = 1;
4992         _cleanup_lookup_paths_free_ LookupPaths paths = {};
4993
4994         if (arg_scope != UNIT_FILE_SYSTEM)
4995                 return 0;
4996
4997         if (!streq(verb, "enable") &&
4998             !streq(verb, "disable") &&
4999             !streq(verb, "is-enabled"))
5000                 return 0;
5001
5002         /* Processes all SysV units, and reshuffles the array so that
5003          * afterwards only the native units remain */
5004
5005         r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, arg_root, NULL, NULL, NULL);
5006         if (r < 0)
5007                 return r;
5008
5009         r = 0;
5010         for (f = 0; args[f]; f++) {
5011                 const char *name;
5012                 _cleanup_free_ char *p = NULL, *q = NULL;
5013                 bool found_native = false, found_sysv;
5014                 unsigned c = 1;
5015                 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
5016                 char **k, *l;
5017                 int j;
5018                 pid_t pid;
5019                 siginfo_t status;
5020
5021                 name = args[f];
5022
5023                 if (!endswith(name, ".service"))
5024                         continue;
5025
5026                 if (path_is_absolute(name))
5027                         continue;
5028
5029                 STRV_FOREACH(k, paths.unit_path) {
5030                         if (!isempty(arg_root))
5031                                 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
5032                         else
5033                                 asprintf(&p, "%s/%s", *k, name);
5034
5035                         if (!p) {
5036                                 r = log_oom();
5037                                 goto finish;
5038                         }
5039
5040                         found_native = access(p, F_OK) >= 0;
5041                         free(p);
5042                         p = NULL;
5043
5044                         if (found_native)
5045                                 break;
5046                 }
5047
5048                 if (found_native)
5049                         continue;
5050
5051                 if (!isempty(arg_root))
5052                         asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
5053                 else
5054                         asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
5055                 if (!p) {
5056                         r = log_oom();
5057                         goto finish;
5058                 }
5059
5060                 p[strlen(p) - sizeof(".service") + 1] = 0;
5061                 found_sysv = access(p, F_OK) >= 0;
5062
5063                 if (!found_sysv)
5064                         continue;
5065
5066                 /* Mark this entry, so that we don't try enabling it as native unit */
5067                 args[f] = (char*) "";
5068
5069                 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
5070
5071                 if (!isempty(arg_root))
5072                         argv[c++] = q = strappend("--root=", arg_root);
5073
5074                 argv[c++] = basename(p);
5075                 argv[c++] =
5076                         streq(verb, "enable") ? "on" :
5077                         streq(verb, "disable") ? "off" : "--level=5";
5078                 argv[c] = NULL;
5079
5080                 l = strv_join((char**)argv, " ");
5081                 if (!l) {
5082                         r = log_oom();
5083                         goto finish;
5084                 }
5085
5086                 log_info("Executing %s", l);
5087                 free(l);
5088
5089                 pid = fork();
5090                 if (pid < 0) {
5091                         log_error("Failed to fork: %m");
5092                         r = -errno;
5093                         goto finish;
5094                 } else if (pid == 0) {
5095                         /* Child */
5096
5097                         execv(argv[0], (char**) argv);
5098                         _exit(EXIT_FAILURE);
5099                 }
5100
5101                 j = wait_for_terminate(pid, &status);
5102                 if (j < 0) {
5103                         log_error("Failed to wait for child: %s", strerror(-r));
5104                         r = j;
5105                         goto finish;
5106                 }
5107
5108                 if (status.si_code == CLD_EXITED) {
5109                         if (streq(verb, "is-enabled")) {
5110                                 if (status.si_status == 0) {
5111                                         if (!arg_quiet)
5112                                                 puts("enabled");
5113                                         r = 1;
5114                                 } else {
5115                                         if (!arg_quiet)
5116                                                 puts("disabled");
5117                                 }
5118
5119                         } else if (status.si_status != 0) {
5120                                 r = -EINVAL;
5121                                 goto finish;
5122                         }
5123                 } else {
5124                         r = -EPROTO;
5125                         goto finish;
5126                 }
5127         }
5128
5129 finish:
5130         /* Drop all SysV units */
5131         for (f = 0, t = 0; args[f]; f++) {
5132
5133                 if (isempty(args[f]))
5134                         continue;
5135
5136                 args[t++] = args[f];
5137         }
5138
5139         args[t] = NULL;
5140
5141 #endif
5142         return r;
5143 }
5144
5145 static int mangle_names(char **original_names, char ***mangled_names) {
5146         char **i, **l, **name;
5147
5148         l = new(char*, strv_length(original_names) + 1);
5149         if (!l)
5150                 return log_oom();
5151
5152         i = l;
5153         STRV_FOREACH(name, original_names) {
5154
5155                 /* When enabling units qualified path names are OK,
5156                  * too, hence allow them explicitly. */
5157
5158                 if (is_path(*name))
5159                         *i = strdup(*name);
5160                 else
5161                         *i = unit_name_mangle(*name, MANGLE_NOGLOB);
5162
5163                 if (!*i) {
5164                         strv_free(l);
5165                         return log_oom();
5166                 }
5167
5168                 i++;
5169         }
5170
5171         *i = NULL;
5172         *mangled_names = l;
5173
5174         return 0;
5175 }
5176
5177 static int enable_unit(sd_bus *bus, char **args) {
5178         _cleanup_strv_free_ char **names = NULL;
5179         const char *verb = args[0];
5180         UnitFileChange *changes = NULL;
5181         unsigned n_changes = 0;
5182         int carries_install_info = -1;
5183         int r;
5184
5185         if (!args[1])
5186                 return 0;
5187
5188         r = mangle_names(args+1, &names);
5189         if (r < 0)
5190                 return r;
5191
5192         r = enable_sysv_units(verb, names);
5193         if (r < 0)
5194                 return r;
5195
5196         /* If the operation was fully executed by the SysV compat,
5197          * let's finish early */
5198         if (strv_isempty(names))
5199                 return 0;
5200
5201         if (!bus || avoid_bus()) {
5202                 if (streq(verb, "enable")) {
5203                         r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5204                         carries_install_info = r;
5205                 } else if (streq(verb, "disable"))
5206                         r = unit_file_disable(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5207                 else if (streq(verb, "reenable")) {
5208                         r = unit_file_reenable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5209                         carries_install_info = r;
5210                 } else if (streq(verb, "link"))
5211                         r = unit_file_link(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5212                 else if (streq(verb, "preset")) {
5213                         r = unit_file_preset(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5214                         carries_install_info = r;
5215                 } else if (streq(verb, "mask"))
5216                         r = unit_file_mask(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5217                 else if (streq(verb, "unmask"))
5218                         r = unit_file_unmask(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5219                 else
5220                         assert_not_reached("Unknown verb");
5221
5222                 if (r < 0) {
5223                         log_error("Operation failed: %s", strerror(-r));
5224                         goto finish;
5225                 }
5226
5227                 if (!arg_quiet)
5228                         dump_unit_file_changes(changes, n_changes);
5229
5230                 r = 0;
5231         } else {
5232                 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5233                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5234                 int expect_carries_install_info = false;
5235                 bool send_force = true;
5236                 const char *method;
5237
5238                 if (streq(verb, "enable")) {
5239                         method = "EnableUnitFiles";
5240                         expect_carries_install_info = true;
5241                 } else if (streq(verb, "disable")) {
5242                         method = "DisableUnitFiles";
5243                         send_force = false;
5244                 } else if (streq(verb, "reenable")) {
5245                         method = "ReenableUnitFiles";
5246                         expect_carries_install_info = true;
5247                 } else if (streq(verb, "link"))
5248                         method = "LinkUnitFiles";
5249                 else if (streq(verb, "preset")) {
5250                         method = "PresetUnitFiles";
5251                         expect_carries_install_info = true;
5252                 } else if (streq(verb, "mask"))
5253                         method = "MaskUnitFiles";
5254                 else if (streq(verb, "unmask")) {
5255                         method = "UnmaskUnitFiles";
5256                         send_force = false;
5257                 } else
5258                         assert_not_reached("Unknown verb");
5259
5260                 r = sd_bus_message_new_method_call(
5261                                 bus,
5262                                 &m,
5263                                 "org.freedesktop.systemd1",
5264                                 "/org/freedesktop/systemd1",
5265                                 "org.freedesktop.systemd1.Manager",
5266                                 method);
5267                 if (r < 0)
5268                         return bus_log_create_error(r);
5269
5270                 r = sd_bus_message_append_strv(m, names);
5271                 if (r < 0)
5272                         return bus_log_create_error(r);
5273
5274                 r = sd_bus_message_append(m, "b", arg_runtime);
5275                 if (r < 0)
5276                         return bus_log_create_error(r);
5277
5278                 if (send_force) {
5279                         r = sd_bus_message_append(m, "b", arg_force);
5280                         if (r < 0)
5281                                 return bus_log_create_error(r);
5282                 }
5283
5284                 r = sd_bus_call(bus, m, 0, &error, &reply);
5285                 if (r < 0) {
5286                         log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5287                         return r;
5288                 }
5289
5290                 if (expect_carries_install_info) {
5291                         r = sd_bus_message_read(reply, "b", &carries_install_info);
5292                         if (r < 0)
5293                                 return bus_log_parse_error(r);
5294                 }
5295
5296                 r = deserialize_and_dump_unit_file_changes(reply);
5297                 if (r < 0)
5298                         return r;
5299
5300                 /* Try to reload if enabled */
5301                 if (!arg_no_reload)
5302                         r = daemon_reload(bus, args);
5303                 else
5304                         r = 0;
5305         }
5306
5307         if (carries_install_info == 0)
5308                 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5309                             "using systemctl.\n"
5310                             "Possible reasons for having this kind of units are:\n"
5311                             "1) A unit may be statically enabled by being symlinked from another unit's\n"
5312                             "   .wants/ or .requires/ directory.\n"
5313                             "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5314                             "   a requirement dependency on it.\n"
5315                             "3) A unit may be started when needed via activation (socket, path, timer,\n"
5316                             "   D-Bus, udev, scripted systemctl call, ...).\n");
5317
5318 finish:
5319         unit_file_changes_free(changes, n_changes);
5320
5321         return r;
5322 }
5323
5324 static int unit_is_enabled(sd_bus *bus, char **args) {
5325
5326         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5327         _cleanup_strv_free_ char **names = NULL;
5328         bool enabled;
5329         char **name;
5330         int r;
5331
5332         r = mangle_names(args+1, &names);
5333         if (r < 0)
5334                 return r;
5335
5336         r = enable_sysv_units(args[0], names);
5337         if (r < 0)
5338                 return r;
5339
5340         enabled = r > 0;
5341
5342         if (!bus || avoid_bus()) {
5343
5344                 STRV_FOREACH(name, names) {
5345                         UnitFileState state;
5346
5347                         state = unit_file_get_state(arg_scope, arg_root, *name);
5348                         if (state < 0) {
5349                                 log_error("Failed to get unit file state for %s: %s", *name, strerror(-state));
5350                                 return state;
5351                         }
5352
5353                         if (state == UNIT_FILE_ENABLED ||
5354                             state == UNIT_FILE_ENABLED_RUNTIME ||
5355                             state == UNIT_FILE_STATIC)
5356                                 enabled = true;
5357
5358                         if (!arg_quiet)
5359                                 puts(unit_file_state_to_string(state));
5360                 }
5361
5362         } else {
5363                 STRV_FOREACH(name, names) {
5364                         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
5365                         const char *s;
5366
5367                         r = sd_bus_call_method(
5368                                         bus,
5369                                         "org.freedesktop.systemd1",
5370                                         "/org/freedesktop/systemd1",
5371                                         "org.freedesktop.systemd1.Manager",
5372                                         "GetUnitFileState",
5373                                         &error,
5374                                         &reply,
5375                                         "s", *name);
5376                         if (r < 0) {
5377                                 log_error("Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
5378                                 return r;
5379                         }
5380
5381                         r = sd_bus_message_read(reply, "s", &s);
5382                         if (r < 0)
5383                                 return bus_log_parse_error(r);
5384
5385                         if (streq(s, "enabled") ||
5386                             streq(s, "enabled-runtime") ||
5387                             streq(s, "static"))
5388                                 enabled = true;
5389
5390                         if (!arg_quiet)
5391                                 puts(s);
5392                 }
5393         }
5394
5395         return !enabled;
5396 }
5397
5398 static int systemctl_help(void) {
5399
5400         pager_open_if_enabled();
5401
5402         printf("%s [OPTIONS...] {COMMAND} ...\n\n"
5403                "Query or send control commands to the systemd manager.\n\n"
5404                "  -h --help           Show this help\n"
5405                "     --version        Show package version\n"
5406                "     --system         Connect to system manager\n"
5407                "     --user           Connect to user service manager\n"
5408                "  -H --host=[USER@]HOST\n"
5409                "                      Operate on remote host\n"
5410                "  -M --machine=CONTAINER\n"
5411                "                      Operate on local container\n"
5412                "  -t --type=TYPE      List only units of a particular type\n"
5413                "     --state=STATE    List only units with particular LOAD or SUB or ACTIVE state\n"
5414                "  -p --property=NAME  Show only properties by this name\n"
5415                "  -a --all            Show all loaded units/properties, including dead/empty\n"
5416                "                      ones. To list all units installed on the system, use\n"
5417                "                      the 'list-unit-files' command instead.\n"
5418                "  -l --full           Don't ellipsize unit names on output\n"
5419                "  -r --recursive      Show unit list of host and local containers\n"
5420                "     --reverse        Show reverse dependencies with 'list-dependencies'\n"
5421                "     --job-mode=MODE  Specify how to deal with already queued jobs, when\n"
5422                "                      queueing a new job\n"
5423                "     --show-types     When showing sockets, explicitly show their type\n"
5424                "  -i --ignore-inhibitors\n"
5425                "                      When shutting down or sleeping, ignore inhibitors\n"
5426                "     --kill-who=WHO   Who to send signal to\n"
5427                "  -s --signal=SIGNAL  Which signal to send\n"
5428                "  -q --quiet          Suppress output\n"
5429                "     --no-block       Do not wait until operation finished\n"
5430                "     --no-wall        Don't send wall message before halt/power-off/reboot\n"
5431                "     --no-reload      When enabling/disabling unit files, don't reload daemon\n"
5432                "                      configuration\n"
5433                "     --no-legend      Do not print a legend (column headers and hints)\n"
5434                "     --no-pager       Do not pipe output into a pager\n"
5435                "     --no-ask-password\n"
5436                "                      Do not ask for system passwords\n"
5437                "     --global         Enable/disable unit files globally\n"
5438                "     --runtime        Enable unit files only temporarily until next reboot\n"
5439                "  -f --force          When enabling unit files, override existing symlinks\n"
5440                "                      When shutting down, execute action immediately\n"
5441                "     --root=PATH      Enable unit files in the specified root directory\n"
5442                "  -n --lines=INTEGER  Number of journal entries to show\n"
5443                "  -o --output=STRING  Change journal output mode (short, short-monotonic,\n"
5444                "                      verbose, export, json, json-pretty, json-sse, cat)\n"
5445                "     --plain          Print unit dependencies as a list instead of a tree\n\n"
5446                "Unit Commands:\n"
5447                "  list-units [PATTERN...]         List loaded units\n"
5448                "  list-sockets [PATTERN...]       List loaded sockets ordered by address\n"
5449                "  list-timers [PATTERN...]        List loaded timers ordered by next elapse\n"
5450                "  start NAME...                   Start (activate) one or more units\n"
5451                "  stop NAME...                    Stop (deactivate) one or more units\n"
5452                "  reload NAME...                  Reload one or more units\n"
5453                "  restart NAME...                 Start or restart one or more units\n"
5454                "  try-restart NAME...             Restart one or more units if active\n"
5455                "  reload-or-restart NAME...       Reload one or more units if possible,\n"
5456                "                                  otherwise start or restart\n"
5457                "  reload-or-try-restart NAME...   Reload one or more units if possible,\n"
5458                "                                  otherwise restart if active\n"
5459                "  isolate NAME                    Start one unit and stop all others\n"
5460                "  kill NAME...                    Send signal to processes of a unit\n"
5461                "  is-active PATTERN...            Check whether units are active\n"
5462                "  is-failed PATTERN...            Check whether units are failed\n"
5463                "  status [PATTERN...|PID...]      Show runtime status of one or more units\n"
5464                "  show [PATTERN...|JOB...]        Show properties of one or more\n"
5465                "                                  units/jobs or the manager\n"
5466                "  cat PATTERN...                  Show files and drop-ins of one or more units\n"
5467                "  set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
5468                "  help PATTERN...|PID...          Show manual for one or more units\n"
5469                "  reset-failed [PATTERN...]       Reset failed state for all, one, or more\n"
5470                "                                  units\n"
5471                "  list-dependencies [NAME]        Recursively show units which are required\n"
5472                "                                  or wanted by this unit or by which this\n"
5473                "                                  unit is required or wanted\n\n"
5474                "Unit File Commands:\n"
5475                "  list-unit-files [PATTERN...]    List installed unit files\n"
5476                "  enable NAME...                  Enable one or more unit files\n"
5477                "  disable NAME...                 Disable one or more unit files\n"
5478                "  reenable NAME...                Reenable one or more unit files\n"
5479                "  preset NAME...                  Enable/disable one or more unit files\n"
5480                "                                  based on preset configuration\n"
5481                "  is-enabled NAME...              Check whether unit files are enabled\n\n"
5482                "  mask NAME...                    Mask one or more units\n"
5483                "  unmask NAME...                  Unmask one or more units\n"
5484                "  link PATH...                    Link one or more units files into\n"
5485                "                                  the search path\n"
5486                "  get-default                     Get the name of the default target\n"
5487                "  set-default NAME                Set the default target\n\n"
5488                "Machine Commands:\n"
5489                "  list-machines [PATTERN...]      List local containers and host\n\n"
5490                "Job Commands:\n"
5491                "  list-jobs [PATTERN...]          List jobs\n"
5492                "  cancel [JOB...]                 Cancel all, one, or more jobs\n\n"
5493                "Snapshot Commands:\n"
5494                "  snapshot [NAME]                 Create a snapshot\n"
5495                "  delete NAME...                  Remove one or more snapshots\n\n"
5496                "Environment Commands:\n"
5497                "  show-environment                Dump environment\n"
5498                "  set-environment NAME=VALUE...   Set one or more environment variables\n"
5499                "  unset-environment NAME...       Unset one or more environment variables\n"
5500                "  import-environment NAME...      Import all, one or more environment variables\n\n"
5501                "Manager Lifecycle Commands:\n"
5502                "  daemon-reload                   Reload systemd manager configuration\n"
5503                "  daemon-reexec                   Reexecute systemd manager\n\n"
5504                "System Commands:\n"
5505                "  default                         Enter system default mode\n"
5506                "  rescue                          Enter system rescue mode\n"
5507                "  emergency                       Enter system emergency mode\n"
5508                "  halt                            Shut down and halt the system\n"
5509                "  poweroff                        Shut down and power-off the system\n"
5510                "  reboot [ARG]                    Shut down and reboot the system\n"
5511                "  kexec                           Shut down and reboot the system with kexec\n"
5512                "  exit                            Request user instance exit\n"
5513                "  switch-root ROOT [INIT]         Change to a different root file system\n"
5514                "  suspend                         Suspend the system\n"
5515                "  hibernate                       Hibernate the system\n"
5516                "  hybrid-sleep                    Hibernate and suspend the system\n",
5517                program_invocation_short_name);
5518
5519         return 0;
5520 }
5521
5522 static int halt_help(void) {
5523
5524         printf("%s [OPTIONS...]%s\n\n"
5525                "%s the system.\n\n"
5526                "     --help      Show this help\n"
5527                "     --halt      Halt the machine\n"
5528                "  -p --poweroff  Switch off the machine\n"
5529                "     --reboot    Reboot the machine\n"
5530                "  -f --force     Force immediate halt/power-off/reboot\n"
5531                "  -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
5532                "  -d --no-wtmp   Don't write wtmp record\n"
5533                "     --no-wall   Don't send wall message before halt/power-off/reboot\n",
5534                program_invocation_short_name,
5535                arg_action == ACTION_REBOOT   ? " [ARG]" : "",
5536                arg_action == ACTION_REBOOT   ? "Reboot" :
5537                arg_action == ACTION_POWEROFF ? "Power off" :
5538                                                "Halt");
5539
5540         return 0;
5541 }
5542
5543 static int shutdown_help(void) {
5544
5545         printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
5546                "Shut down the system.\n\n"
5547                "     --help      Show this help\n"
5548                "  -H --halt      Halt the machine\n"
5549                "  -P --poweroff  Power-off the machine\n"
5550                "  -r --reboot    Reboot the machine\n"
5551                "  -h             Equivalent to --poweroff, overridden by --halt\n"
5552                "  -k             Don't halt/power-off/reboot, just send warnings\n"
5553                "     --no-wall   Don't send wall message before halt/power-off/reboot\n"
5554                "  -c             Cancel a pending shutdown\n",
5555                program_invocation_short_name);
5556
5557         return 0;
5558 }
5559
5560 static int telinit_help(void) {
5561
5562         printf("%s [OPTIONS...] {COMMAND}\n\n"
5563                "Send control commands to the init daemon.\n\n"
5564                "     --help      Show this help\n"
5565                "     --no-wall   Don't send wall message before halt/power-off/reboot\n\n"
5566                "Commands:\n"
5567                "  0              Power-off the machine\n"
5568                "  6              Reboot the machine\n"
5569                "  2, 3, 4, 5     Start runlevelX.target unit\n"
5570                "  1, s, S        Enter rescue mode\n"
5571                "  q, Q           Reload init daemon configuration\n"
5572                "  u, U           Reexecute init daemon\n",
5573                program_invocation_short_name);
5574
5575         return 0;
5576 }
5577
5578 static int runlevel_help(void) {
5579
5580         printf("%s [OPTIONS...]\n\n"
5581                "Prints the previous and current runlevel of the init system.\n\n"
5582                "     --help      Show this help\n",
5583                program_invocation_short_name);
5584
5585         return 0;
5586 }
5587
5588 static int help_types(void) {
5589         int i;
5590         const char *t;
5591
5592         puts("Available unit types:");
5593         for (i = 0; i < _UNIT_TYPE_MAX; i++) {
5594                 t = unit_type_to_string(i);
5595                 if (t)
5596                         puts(t);
5597         }
5598
5599         return 0;
5600 }
5601
5602 static int systemctl_parse_argv(int argc, char *argv[]) {
5603
5604         enum {
5605                 ARG_FAIL = 0x100,
5606                 ARG_REVERSE,
5607                 ARG_AFTER,
5608                 ARG_BEFORE,
5609                 ARG_SHOW_TYPES,
5610                 ARG_IRREVERSIBLE,
5611                 ARG_IGNORE_DEPENDENCIES,
5612                 ARG_VERSION,
5613                 ARG_USER,
5614                 ARG_SYSTEM,
5615                 ARG_GLOBAL,
5616                 ARG_NO_BLOCK,
5617                 ARG_NO_LEGEND,
5618                 ARG_NO_PAGER,
5619                 ARG_NO_WALL,
5620                 ARG_ROOT,
5621                 ARG_NO_RELOAD,
5622                 ARG_KILL_WHO,
5623                 ARG_NO_ASK_PASSWORD,
5624                 ARG_FAILED,
5625                 ARG_RUNTIME,
5626                 ARG_FORCE,
5627                 ARG_PLAIN,
5628                 ARG_STATE,
5629                 ARG_JOB_MODE
5630         };
5631
5632         static const struct option options[] = {
5633                 { "help",                no_argument,       NULL, 'h'                     },
5634                 { "version",             no_argument,       NULL, ARG_VERSION             },
5635                 { "type",                required_argument, NULL, 't'                     },
5636                 { "property",            required_argument, NULL, 'p'                     },
5637                 { "all",                 no_argument,       NULL, 'a'                     },
5638                 { "reverse",             no_argument,       NULL, ARG_REVERSE             },
5639                 { "after",               no_argument,       NULL, ARG_AFTER               },
5640                 { "before",              no_argument,       NULL, ARG_BEFORE              },
5641                 { "show-types",          no_argument,       NULL, ARG_SHOW_TYPES          },
5642                 { "failed",              no_argument,       NULL, ARG_FAILED              }, /* compatibility only */
5643                 { "full",                no_argument,       NULL, 'l'                     },
5644                 { "job-mode",            required_argument, NULL, ARG_JOB_MODE            },
5645                 { "fail",                no_argument,       NULL, ARG_FAIL                }, /* compatibility only */
5646                 { "irreversible",        no_argument,       NULL, ARG_IRREVERSIBLE        }, /* compatibility only */
5647                 { "ignore-dependencies", no_argument,       NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
5648                 { "ignore-inhibitors",   no_argument,       NULL, 'i'                     },
5649                 { "user",                no_argument,       NULL, ARG_USER                },
5650                 { "system",              no_argument,       NULL, ARG_SYSTEM              },
5651                 { "global",              no_argument,       NULL, ARG_GLOBAL              },
5652                 { "no-block",            no_argument,       NULL, ARG_NO_BLOCK            },
5653                 { "no-legend",           no_argument,       NULL, ARG_NO_LEGEND           },
5654                 { "no-pager",            no_argument,       NULL, ARG_NO_PAGER            },
5655                 { "no-wall",             no_argument,       NULL, ARG_NO_WALL             },
5656                 { "quiet",               no_argument,       NULL, 'q'                     },
5657                 { "root",                required_argument, NULL, ARG_ROOT                },
5658                 { "force",               no_argument,       NULL, ARG_FORCE               },
5659                 { "no-reload",           no_argument,       NULL, ARG_NO_RELOAD           },
5660                 { "kill-who",            required_argument, NULL, ARG_KILL_WHO            },
5661                 { "signal",              required_argument, NULL, 's'                     },
5662                 { "no-ask-password",     no_argument,       NULL, ARG_NO_ASK_PASSWORD     },
5663                 { "host",                required_argument, NULL, 'H'                     },
5664                 { "machine",             required_argument, NULL, 'M'                     },
5665                 { "runtime",             no_argument,       NULL, ARG_RUNTIME             },
5666                 { "lines",               required_argument, NULL, 'n'                     },
5667                 { "output",              required_argument, NULL, 'o'                     },
5668                 { "plain",               no_argument,       NULL, ARG_PLAIN               },
5669                 { "state",               required_argument, NULL, ARG_STATE               },
5670                 { "recursive",           no_argument,       NULL, 'r'                     },
5671                 {}
5672         };
5673
5674         int c;
5675
5676         assert(argc >= 0);
5677         assert(argv);
5678
5679         while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0) {
5680
5681                 switch (c) {
5682
5683                 case 'h':
5684                         return systemctl_help();
5685
5686                 case ARG_VERSION:
5687                         puts(PACKAGE_STRING);
5688                         puts(SYSTEMD_FEATURES);
5689                         return 0;
5690
5691                 case 't': {
5692                         char *word, *state;
5693                         size_t size;
5694
5695                         FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5696                                 _cleanup_free_ char *type;
5697
5698                                 type = strndup(word, size);
5699                                 if (!type)
5700                                         return -ENOMEM;
5701
5702                                 if (streq(type, "help")) {
5703                                         help_types();
5704                                         return 0;
5705                                 }
5706
5707                                 if (unit_type_from_string(type) >= 0) {
5708                                         if (strv_push(&arg_types, type))
5709                                                 return log_oom();
5710                                         type = NULL;
5711                                         continue;
5712                                 }
5713
5714                                 /* It's much nicer to use --state= for
5715                                  * load states, but let's support this
5716                                  * in --types= too for compatibility
5717                                  * with old versions */
5718                                 if (unit_load_state_from_string(optarg) >= 0) {
5719                                         if (strv_push(&arg_states, type) < 0)
5720                                                 return log_oom();
5721                                         type = NULL;
5722                                         continue;
5723                                 }
5724
5725                                 log_error("Unknown unit type or load state '%s'.", type);
5726                                 log_info("Use -t help to see a list of allowed values.");
5727                                 return -EINVAL;
5728                         }
5729
5730                         break;
5731                 }
5732
5733                 case 'p': {
5734                         /* Make sure that if the empty property list
5735                            was specified, we won't show any properties. */
5736                         if (isempty(optarg) && !arg_properties) {
5737                                 arg_properties = new0(char*, 1);
5738                                 if (!arg_properties)
5739                                         return log_oom();
5740                         } else {
5741                                 char *word, *state;
5742                                 size_t size;
5743
5744                                 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5745                                         char *prop;
5746
5747                                         prop = strndup(word, size);
5748                                         if (!prop)
5749                                                 return log_oom();
5750
5751                                         if (strv_consume(&arg_properties, prop) < 0)
5752                                                 return log_oom();
5753                                 }
5754                         }
5755
5756                         /* If the user asked for a particular
5757                          * property, show it to him, even if it is
5758                          * empty. */
5759                         arg_all = true;
5760
5761                         break;
5762                 }
5763
5764                 case 'a':
5765                         arg_all = true;
5766                         break;
5767
5768                 case ARG_REVERSE:
5769                         arg_dependency = DEPENDENCY_REVERSE;
5770                         break;
5771
5772                 case ARG_AFTER:
5773                         arg_dependency = DEPENDENCY_AFTER;
5774                         break;
5775
5776                 case ARG_BEFORE:
5777                         arg_dependency = DEPENDENCY_BEFORE;
5778                         break;
5779
5780                 case ARG_SHOW_TYPES:
5781                         arg_show_types = true;
5782                         break;
5783
5784                 case ARG_JOB_MODE:
5785                         arg_job_mode = optarg;
5786                         break;
5787
5788                 case ARG_FAIL:
5789                         arg_job_mode = "fail";
5790                         break;
5791
5792                 case ARG_IRREVERSIBLE:
5793                         arg_job_mode = "replace-irreversibly";
5794                         break;
5795
5796                 case ARG_IGNORE_DEPENDENCIES:
5797                         arg_job_mode = "ignore-dependencies";
5798                         break;
5799
5800                 case ARG_USER:
5801                         arg_scope = UNIT_FILE_USER;
5802                         break;
5803
5804                 case ARG_SYSTEM:
5805                         arg_scope = UNIT_FILE_SYSTEM;
5806                         break;
5807
5808                 case ARG_GLOBAL:
5809                         arg_scope = UNIT_FILE_GLOBAL;
5810                         break;
5811
5812                 case ARG_NO_BLOCK:
5813                         arg_no_block = true;
5814                         break;
5815
5816                 case ARG_NO_LEGEND:
5817                         arg_no_legend = true;
5818                         break;
5819
5820                 case ARG_NO_PAGER:
5821                         arg_no_pager = true;
5822                         break;
5823
5824                 case ARG_NO_WALL:
5825                         arg_no_wall = true;
5826                         break;
5827
5828                 case ARG_ROOT:
5829                         arg_root = optarg;
5830                         break;
5831
5832                 case 'l':
5833                         arg_full = true;
5834                         break;
5835
5836                 case ARG_FAILED:
5837                         if (strv_extend(&arg_states, "failed") < 0)
5838                                 return log_oom();
5839
5840                         break;
5841
5842                 case 'q':
5843                         arg_quiet = true;
5844                         break;
5845
5846                 case ARG_FORCE:
5847                         arg_force ++;
5848                         break;
5849
5850                 case 'f':
5851                         arg_force ++;
5852                         break;
5853
5854                 case ARG_NO_RELOAD:
5855                         arg_no_reload = true;
5856                         break;
5857
5858                 case ARG_KILL_WHO:
5859                         arg_kill_who = optarg;
5860                         break;
5861
5862                 case 's':
5863                         if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
5864                                 log_error("Failed to parse signal string %s.", optarg);
5865                                 return -EINVAL;
5866                         }
5867                         break;
5868
5869                 case ARG_NO_ASK_PASSWORD:
5870                         arg_ask_password = false;
5871                         break;
5872
5873                 case 'H':
5874                         arg_transport = BUS_TRANSPORT_REMOTE;
5875                         arg_host = optarg;
5876                         break;
5877
5878                 case 'M':
5879                         arg_transport = BUS_TRANSPORT_CONTAINER;
5880                         arg_host = optarg;
5881                         break;
5882
5883                 case ARG_RUNTIME:
5884                         arg_runtime = true;
5885                         break;
5886
5887                 case 'n':
5888                         if (safe_atou(optarg, &arg_lines) < 0) {
5889                                 log_error("Failed to parse lines '%s'", optarg);
5890                                 return -EINVAL;
5891                         }
5892                         break;
5893
5894                 case 'o':
5895                         arg_output = output_mode_from_string(optarg);
5896                         if (arg_output < 0) {
5897                                 log_error("Unknown output '%s'.", optarg);
5898                                 return -EINVAL;
5899                         }
5900                         break;
5901
5902                 case 'i':
5903                         arg_ignore_inhibitors = true;
5904                         break;
5905
5906                 case ARG_PLAIN:
5907                         arg_plain = true;
5908                         break;
5909
5910                 case ARG_STATE: {
5911                         char *word, *state;
5912                         size_t size;
5913
5914                         FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5915                                 char *s;
5916
5917                                 s = strndup(word, size);
5918                                 if (!s)
5919                                         return log_oom();
5920
5921                                 if (strv_consume(&arg_states, s) < 0)
5922                                         return log_oom();
5923                         }
5924                         break;
5925                 }
5926
5927                 case 'r':
5928                         if (geteuid() != 0) {
5929                                 log_error("--recursive requires root priviliges.");
5930                                 return -EPERM;
5931                         }
5932
5933                         arg_recursive = true;
5934                         break;
5935
5936                 case '?':
5937                         return -EINVAL;
5938
5939                 default:
5940                         assert_not_reached("Unhandled option");
5941                 }
5942         }
5943
5944         if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM) {
5945                 log_error("Cannot access user instance remotely.");
5946                 return -EINVAL;
5947         }
5948
5949         return 1;
5950 }
5951
5952 static int halt_parse_argv(int argc, char *argv[]) {
5953
5954         enum {
5955                 ARG_HELP = 0x100,
5956                 ARG_HALT,
5957                 ARG_REBOOT,
5958                 ARG_NO_WALL
5959         };
5960
5961         static const struct option options[] = {
5962                 { "help",      no_argument,       NULL, ARG_HELP    },
5963                 { "halt",      no_argument,       NULL, ARG_HALT    },
5964                 { "poweroff",  no_argument,       NULL, 'p'         },
5965                 { "reboot",    no_argument,       NULL, ARG_REBOOT  },
5966                 { "force",     no_argument,       NULL, 'f'         },
5967                 { "wtmp-only", no_argument,       NULL, 'w'         },
5968                 { "no-wtmp",   no_argument,       NULL, 'd'         },
5969                 { "no-wall",   no_argument,       NULL, ARG_NO_WALL },
5970                 {}
5971         };
5972
5973         int c, r, runlevel;
5974
5975         assert(argc >= 0);
5976         assert(argv);
5977
5978         if (utmp_get_runlevel(&runlevel, NULL) >= 0)
5979                 if (runlevel == '0' || runlevel == '6')
5980                         arg_force = 2;
5981
5982         while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
5983                 switch (c) {
5984
5985                 case ARG_HELP:
5986                         return halt_help();
5987
5988                 case ARG_HALT:
5989                         arg_action = ACTION_HALT;
5990                         break;
5991
5992                 case 'p':
5993                         if (arg_action != ACTION_REBOOT)
5994                                 arg_action = ACTION_POWEROFF;
5995                         break;
5996
5997                 case ARG_REBOOT:
5998                         arg_action = ACTION_REBOOT;
5999                         break;
6000
6001                 case 'f':
6002                         arg_force = 2;
6003                         break;
6004
6005                 case 'w':
6006                         arg_dry = true;
6007                         break;
6008
6009                 case 'd':
6010                         arg_no_wtmp = true;
6011                         break;
6012
6013                 case ARG_NO_WALL:
6014                         arg_no_wall = true;
6015                         break;
6016
6017                 case 'i':
6018                 case 'h':
6019                 case 'n':
6020                         /* Compatibility nops */
6021                         break;
6022
6023                 case '?':
6024                         return -EINVAL;
6025
6026                 default:
6027                         assert_not_reached("Unhandled option");
6028                 }
6029         }
6030
6031         if (arg_action == ACTION_REBOOT && (argc == optind || argc == optind + 1)) {
6032                 r = update_reboot_param_file(argc == optind + 1 ? argv[optind] : NULL);
6033                 if (r < 0)
6034                         return r;
6035         } else if (optind < argc) {
6036                 log_error("Too many arguments.");
6037                 return -EINVAL;
6038         }
6039
6040         return 1;
6041 }
6042
6043 static int parse_time_spec(const char *t, usec_t *_u) {
6044         assert(t);
6045         assert(_u);
6046
6047         if (streq(t, "now"))
6048                 *_u = 0;
6049         else if (!strchr(t, ':')) {
6050                 uint64_t u;
6051
6052                 if (safe_atou64(t, &u) < 0)
6053                         return -EINVAL;
6054
6055                 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
6056         } else {
6057                 char *e = NULL;
6058                 long hour, minute;
6059                 struct tm tm = {};
6060                 time_t s;
6061                 usec_t n;
6062
6063                 errno = 0;
6064                 hour = strtol(t, &e, 10);
6065                 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
6066                         return -EINVAL;
6067
6068                 minute = strtol(e+1, &e, 10);
6069                 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
6070                         return -EINVAL;
6071
6072                 n = now(CLOCK_REALTIME);
6073                 s = (time_t) (n / USEC_PER_SEC);
6074
6075                 assert_se(localtime_r(&s, &tm));
6076
6077                 tm.tm_hour = (int) hour;
6078                 tm.tm_min = (int) minute;
6079                 tm.tm_sec = 0;
6080
6081                 assert_se(s = mktime(&tm));
6082
6083                 *_u = (usec_t) s * USEC_PER_SEC;
6084
6085                 while (*_u <= n)
6086                         *_u += USEC_PER_DAY;
6087         }
6088
6089         return 0;
6090 }
6091
6092 static int shutdown_parse_argv(int argc, char *argv[]) {
6093
6094         enum {
6095                 ARG_HELP = 0x100,
6096                 ARG_NO_WALL
6097         };
6098
6099         static const struct option options[] = {
6100                 { "help",      no_argument,       NULL, ARG_HELP    },
6101                 { "halt",      no_argument,       NULL, 'H'         },
6102                 { "poweroff",  no_argument,       NULL, 'P'         },
6103                 { "reboot",    no_argument,       NULL, 'r'         },
6104                 { "kexec",     no_argument,       NULL, 'K'         }, /* not documented extension */
6105                 { "no-wall",   no_argument,       NULL, ARG_NO_WALL },
6106                 {}
6107         };
6108
6109         int c, r;
6110
6111         assert(argc >= 0);
6112         assert(argv);
6113
6114         while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
6115                 switch (c) {
6116
6117                 case ARG_HELP:
6118                         return shutdown_help();
6119
6120                 case 'H':
6121                         arg_action = ACTION_HALT;
6122                         break;
6123
6124                 case 'P':
6125                         arg_action = ACTION_POWEROFF;
6126                         break;
6127
6128                 case 'r':
6129                         if (kexec_loaded())
6130                                 arg_action = ACTION_KEXEC;
6131                         else
6132                                 arg_action = ACTION_REBOOT;
6133                         break;
6134
6135                 case 'K':
6136                         arg_action = ACTION_KEXEC;
6137                         break;
6138
6139                 case 'h':
6140                         if (arg_action != ACTION_HALT)
6141                                 arg_action = ACTION_POWEROFF;
6142                         break;
6143
6144                 case 'k':
6145                         arg_dry = true;
6146                         break;
6147
6148                 case ARG_NO_WALL:
6149                         arg_no_wall = true;
6150                         break;
6151
6152                 case 't':
6153                 case 'a':
6154                         /* Compatibility nops */
6155                         break;
6156
6157                 case 'c':
6158                         arg_action = ACTION_CANCEL_SHUTDOWN;
6159                         break;
6160
6161                 case '?':
6162                         return -EINVAL;
6163
6164                 default:
6165                         assert_not_reached("Unhandled option");
6166                 }
6167         }
6168
6169         if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
6170                 r = parse_time_spec(argv[optind], &arg_when);
6171                 if (r < 0) {
6172                         log_error("Failed to parse time specification: %s", argv[optind]);
6173                         return r;
6174                 }
6175         } else
6176                 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
6177
6178         if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
6179                 /* No time argument for shutdown cancel */
6180                 arg_wall = argv + optind;
6181         else if (argc > optind + 1)
6182                 /* We skip the time argument */
6183                 arg_wall = argv + optind + 1;
6184
6185         optind = argc;
6186
6187         return 1;
6188 }
6189
6190 static int telinit_parse_argv(int argc, char *argv[]) {
6191
6192         enum {
6193                 ARG_HELP = 0x100,
6194                 ARG_NO_WALL
6195         };
6196
6197         static const struct option options[] = {
6198                 { "help",      no_argument,       NULL, ARG_HELP    },
6199                 { "no-wall",   no_argument,       NULL, ARG_NO_WALL },
6200                 {}
6201         };
6202
6203         static const struct {
6204                 char from;
6205                 enum action to;
6206         } table[] = {
6207                 { '0', ACTION_POWEROFF },
6208                 { '6', ACTION_REBOOT },
6209                 { '1', ACTION_RESCUE },
6210                 { '2', ACTION_RUNLEVEL2 },
6211                 { '3', ACTION_RUNLEVEL3 },
6212                 { '4', ACTION_RUNLEVEL4 },
6213                 { '5', ACTION_RUNLEVEL5 },
6214                 { 's', ACTION_RESCUE },
6215                 { 'S', ACTION_RESCUE },
6216                 { 'q', ACTION_RELOAD },
6217                 { 'Q', ACTION_RELOAD },
6218                 { 'u', ACTION_REEXEC },
6219                 { 'U', ACTION_REEXEC }
6220         };
6221
6222         unsigned i;
6223         int c;
6224
6225         assert(argc >= 0);
6226         assert(argv);
6227
6228         while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
6229                 switch (c) {
6230
6231                 case ARG_HELP:
6232                         return telinit_help();
6233
6234                 case ARG_NO_WALL:
6235                         arg_no_wall = true;
6236                         break;
6237
6238                 case '?':
6239                         return -EINVAL;
6240
6241                 default:
6242                         assert_not_reached("Unhandled option");
6243                 }
6244         }
6245
6246         if (optind >= argc) {
6247                 telinit_help();
6248                 return -EINVAL;
6249         }
6250
6251         if (optind + 1 < argc) {
6252                 log_error("Too many arguments.");
6253                 return -EINVAL;
6254         }
6255
6256         if (strlen(argv[optind]) != 1) {
6257                 log_error("Expected single character argument.");
6258                 return -EINVAL;
6259         }
6260
6261         for (i = 0; i < ELEMENTSOF(table); i++)
6262                 if (table[i].from == argv[optind][0])
6263                         break;
6264
6265         if (i >= ELEMENTSOF(table)) {
6266                 log_error("Unknown command '%s'.", argv[optind]);
6267                 return -EINVAL;
6268         }
6269
6270         arg_action = table[i].to;
6271
6272         optind ++;
6273
6274         return 1;
6275 }
6276
6277 static int runlevel_parse_argv(int argc, char *argv[]) {
6278
6279         enum {
6280                 ARG_HELP = 0x100,
6281         };
6282
6283         static const struct option options[] = {
6284                 { "help",      no_argument,       NULL, ARG_HELP    },
6285                 {}
6286         };
6287
6288         int c;
6289
6290         assert(argc >= 0);
6291         assert(argv);
6292
6293         while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
6294                 switch (c) {
6295
6296                 case ARG_HELP:
6297                         return runlevel_help();
6298
6299                 case '?':
6300                         return -EINVAL;
6301
6302                 default:
6303                         assert_not_reached("Unhandled option");
6304                 }
6305         }
6306
6307         if (optind < argc) {
6308                 log_error("Too many arguments.");
6309                 return -EINVAL;
6310         }
6311
6312         return 1;
6313 }
6314
6315 static int parse_argv(int argc, char *argv[]) {
6316         assert(argc >= 0);
6317         assert(argv);
6318
6319         if (program_invocation_short_name) {
6320
6321                 if (strstr(program_invocation_short_name, "halt")) {
6322                         arg_action = ACTION_HALT;
6323                         return halt_parse_argv(argc, argv);
6324                 } else if (strstr(program_invocation_short_name, "poweroff")) {
6325                         arg_action = ACTION_POWEROFF;
6326                         return halt_parse_argv(argc, argv);
6327                 } else if (strstr(program_invocation_short_name, "reboot")) {
6328                         if (kexec_loaded())
6329                                 arg_action = ACTION_KEXEC;
6330                         else
6331                                 arg_action = ACTION_REBOOT;
6332                         return halt_parse_argv(argc, argv);
6333                 } else if (strstr(program_invocation_short_name, "shutdown")) {
6334                         arg_action = ACTION_POWEROFF;
6335                         return shutdown_parse_argv(argc, argv);
6336                 } else if (strstr(program_invocation_short_name, "init")) {
6337
6338                         if (sd_booted() > 0) {
6339                                 arg_action = _ACTION_INVALID;
6340                                 return telinit_parse_argv(argc, argv);
6341                         } else {
6342                                 /* Hmm, so some other init system is
6343                                  * running, we need to forward this
6344                                  * request to it. For now we simply
6345                                  * guess that it is Upstart. */
6346
6347                                 execv(TELINIT, argv);
6348
6349                                 log_error("Couldn't find an alternative telinit implementation to spawn.");
6350                                 return -EIO;
6351                         }
6352
6353                 } else if (strstr(program_invocation_short_name, "runlevel")) {
6354                         arg_action = ACTION_RUNLEVEL;
6355                         return runlevel_parse_argv(argc, argv);
6356                 }
6357         }
6358
6359         arg_action = ACTION_SYSTEMCTL;
6360         return systemctl_parse_argv(argc, argv);
6361 }
6362
6363 _pure_ static int action_to_runlevel(void) {
6364
6365         static const char table[_ACTION_MAX] = {
6366                 [ACTION_HALT] =      '0',
6367                 [ACTION_POWEROFF] =  '0',
6368                 [ACTION_REBOOT] =    '6',
6369                 [ACTION_RUNLEVEL2] = '2',
6370                 [ACTION_RUNLEVEL3] = '3',
6371                 [ACTION_RUNLEVEL4] = '4',
6372                 [ACTION_RUNLEVEL5] = '5',
6373                 [ACTION_RESCUE] =    '1'
6374         };
6375
6376         assert(arg_action < _ACTION_MAX);
6377
6378         return table[arg_action];
6379 }
6380
6381 static int talk_initctl(void) {
6382
6383         struct init_request request = {
6384                 .magic = INIT_MAGIC,
6385                 .sleeptime  = 0,
6386                 .cmd = INIT_CMD_RUNLVL
6387         };
6388
6389         _cleanup_close_ int fd = -1;
6390         char rl;
6391         int r;
6392
6393         rl = action_to_runlevel();
6394         if (!rl)
6395                 return 0;
6396
6397         request.runlevel = rl;
6398
6399         fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
6400         if (fd < 0) {
6401                 if (errno == ENOENT)
6402                         return 0;
6403
6404                 log_error("Failed to open "INIT_FIFO": %m");
6405                 return -errno;
6406         }
6407
6408         errno = 0;
6409         r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
6410         if (r) {
6411                 log_error("Failed to write to "INIT_FIFO": %m");
6412                 return errno > 0 ? -errno : -EIO;
6413         }
6414
6415         return 1;
6416 }
6417
6418 static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
6419
6420         static const struct {
6421                 const char* verb;
6422                 const enum {
6423                         MORE,
6424                         LESS,
6425                         EQUAL
6426                 } argc_cmp;
6427                 const int argc;
6428                 int (* const dispatch)(sd_bus *bus, char **args);
6429                 const enum {
6430                         NOBUS = 1,
6431                         FORCE,
6432                 } bus;
6433         } verbs[] = {
6434                 { "list-units",            MORE,  0, list_units        },
6435                 { "list-unit-files",       MORE,  1, list_unit_files,  NOBUS },
6436                 { "list-sockets",          MORE,  1, list_sockets      },
6437                 { "list-timers",           MORE,  1, list_timers       },
6438                 { "list-jobs",             MORE,  1, list_jobs         },
6439                 { "list-machines",         MORE,  1, list_machines     },
6440                 { "clear-jobs",            EQUAL, 1, daemon_reload     },
6441                 { "cancel",                MORE,  2, cancel_job        },
6442                 { "start",                 MORE,  2, start_unit        },
6443                 { "stop",                  MORE,  2, start_unit        },
6444                 { "condstop",              MORE,  2, start_unit        }, /* For compatibility with ALTLinux */
6445                 { "reload",                MORE,  2, start_unit        },
6446                 { "restart",               MORE,  2, start_unit        },
6447                 { "try-restart",           MORE,  2, start_unit        },
6448                 { "reload-or-restart",     MORE,  2, start_unit        },
6449                 { "reload-or-try-restart", MORE,  2, start_unit        },
6450                 { "force-reload",          MORE,  2, start_unit        }, /* For compatibility with SysV */
6451                 { "condreload",            MORE,  2, start_unit        }, /* For compatibility with ALTLinux */
6452                 { "condrestart",           MORE,  2, start_unit        }, /* For compatibility with RH */
6453                 { "isolate",               EQUAL, 2, start_unit        },
6454                 { "kill",                  MORE,  2, kill_unit         },
6455                 { "is-active",             MORE,  2, check_unit_active },
6456                 { "check",                 MORE,  2, check_unit_active },
6457                 { "is-failed",             MORE,  2, check_unit_failed },
6458                 { "show",                  MORE,  1, show              },
6459                 { "cat",                   MORE,  2, cat               },
6460                 { "status",                MORE,  1, show              },
6461                 { "help",                  MORE,  2, show              },
6462                 { "snapshot",              LESS,  2, snapshot          },
6463                 { "delete",                MORE,  2, delete_snapshot   },
6464                 { "daemon-reload",         EQUAL, 1, daemon_reload     },
6465                 { "daemon-reexec",         EQUAL, 1, daemon_reload     },
6466                 { "show-environment",      EQUAL, 1, show_environment  },
6467                 { "set-environment",       MORE,  2, set_environment   },
6468                 { "unset-environment",     MORE,  2, set_environment   },
6469                 { "import-environment",    MORE,  1, import_environment},
6470                 { "halt",                  EQUAL, 1, start_special,    FORCE },
6471                 { "poweroff",              EQUAL, 1, start_special,    FORCE },
6472                 { "reboot",                EQUAL, 1, start_special,    FORCE },
6473                 { "kexec",                 EQUAL, 1, start_special     },
6474                 { "suspend",               EQUAL, 1, start_special     },
6475                 { "hibernate",             EQUAL, 1, start_special     },
6476                 { "hybrid-sleep",          EQUAL, 1, start_special     },
6477                 { "default",               EQUAL, 1, start_special     },
6478                 { "rescue",                EQUAL, 1, start_special     },
6479                 { "emergency",             EQUAL, 1, start_special     },
6480                 { "exit",                  EQUAL, 1, start_special     },
6481                 { "reset-failed",          MORE,  1, reset_failed      },
6482                 { "enable",                MORE,  2, enable_unit,      NOBUS },
6483                 { "disable",               MORE,  2, enable_unit,      NOBUS },
6484                 { "is-enabled",            MORE,  2, unit_is_enabled,  NOBUS },
6485                 { "reenable",              MORE,  2, enable_unit,      NOBUS },
6486                 { "preset",                MORE,  2, enable_unit,      NOBUS },
6487                 { "mask",                  MORE,  2, enable_unit,      NOBUS },
6488                 { "unmask",                MORE,  2, enable_unit,      NOBUS },
6489                 { "link",                  MORE,  2, enable_unit,      NOBUS },
6490                 { "switch-root",           MORE,  2, switch_root       },
6491                 { "list-dependencies",     LESS,  2, list_dependencies },
6492                 { "set-default",           EQUAL, 2, set_default,      NOBUS },
6493                 { "get-default",           EQUAL, 1, get_default,      NOBUS },
6494                 { "set-property",          MORE,  3, set_property      },
6495                 {}
6496         }, *verb = verbs;
6497
6498         int left;
6499
6500         assert(argc >= 0);
6501         assert(argv);
6502
6503         left = argc - optind;
6504
6505         /* Special rule: no arguments (left == 0) means "list-units" */
6506         if (left > 0) {
6507                 if (streq(argv[optind], "help") && !argv[optind+1]) {
6508                         log_error("This command expects one or more "
6509                                   "unit names. Did you mean --help?");
6510                         return -EINVAL;
6511                 }
6512
6513                 for (; verb->verb; verb++)
6514                         if (streq(argv[optind], verb->verb))
6515                                 goto found;
6516
6517                 log_error("Unknown operation '%s'.", argv[optind]);
6518                 return -EINVAL;
6519         }
6520 found:
6521
6522         switch (verb->argc_cmp) {
6523
6524         case EQUAL:
6525                 if (left != verb->argc) {
6526                         log_error("Invalid number of arguments.");
6527                         return -EINVAL;
6528                 }
6529
6530                 break;
6531
6532         case MORE:
6533                 if (left < verb->argc) {
6534                         log_error("Too few arguments.");
6535                         return -EINVAL;
6536                 }
6537
6538                 break;
6539
6540         case LESS:
6541                 if (left > verb->argc) {
6542                         log_error("Too many arguments.");
6543                         return -EINVAL;
6544                 }
6545
6546                 break;
6547
6548         default:
6549                 assert_not_reached("Unknown comparison operator.");
6550         }
6551
6552         /* Require a bus connection for all operations but
6553          * enable/disable */
6554         if (verb->bus == NOBUS) {
6555                 if (!bus && !avoid_bus()) {
6556                         log_error("Failed to get D-Bus connection: %s", strerror(-bus_error));
6557                         return -EIO;
6558                 }
6559
6560         } else {
6561                 if (running_in_chroot() > 0) {
6562                         log_info("Running in chroot, ignoring request.");
6563                         return 0;
6564                 }
6565
6566                 if ((verb->bus != FORCE || arg_force <= 0) && !bus) {
6567                         log_error("Failed to get D-Bus connection: %s", strerror(-bus_error));
6568                         return -EIO;
6569                 }
6570         }
6571
6572         return verb->dispatch(bus, argv + optind);
6573 }
6574
6575 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
6576
6577         struct sd_shutdown_command c = {
6578                 .usec = t,
6579                 .mode = mode,
6580                 .dry_run = dry_run,
6581                 .warn_wall = warn,
6582         };
6583
6584         union sockaddr_union sockaddr = {
6585                 .un.sun_family = AF_UNIX,
6586                 .un.sun_path = "/run/systemd/shutdownd",
6587         };
6588
6589         struct iovec iovec[2] = {{
6590                  .iov_base = (char*) &c,
6591                  .iov_len = offsetof(struct sd_shutdown_command, wall_message),
6592         }};
6593
6594         struct msghdr msghdr = {
6595                 .msg_name = &sockaddr,
6596                 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
6597                                + strlen("/run/systemd/shutdownd"),
6598                 .msg_iov = iovec,
6599                 .msg_iovlen = 1,
6600         };
6601
6602         _cleanup_close_ int fd;
6603
6604         fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
6605         if (fd < 0)
6606                 return -errno;
6607
6608         if (!isempty(message)) {
6609                 iovec[1].iov_base = (char*) message;
6610                 iovec[1].iov_len = strlen(message);
6611                 msghdr.msg_iovlen++;
6612         }
6613
6614         if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
6615                 return -errno;
6616
6617         return 0;
6618 }
6619
6620 static int reload_with_fallback(sd_bus *bus) {
6621
6622         if (bus) {
6623                 /* First, try systemd via D-Bus. */
6624                 if (daemon_reload(bus, NULL) >= 0)
6625                         return 0;
6626         }
6627
6628         /* Nothing else worked, so let's try signals */
6629         assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
6630
6631         if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
6632                 log_error("kill() failed: %m");
6633                 return -errno;
6634         }
6635
6636         return 0;
6637 }
6638
6639 static int start_with_fallback(sd_bus *bus) {
6640
6641         if (bus) {
6642                 /* First, try systemd via D-Bus. */
6643                 if (start_unit(bus, NULL) >= 0)
6644                         goto done;
6645         }
6646
6647         /* Nothing else worked, so let's try
6648          * /dev/initctl */
6649         if (talk_initctl() > 0)
6650                 goto done;
6651
6652         log_error("Failed to talk to init daemon.");
6653         return -EIO;
6654
6655 done:
6656         warn_wall(arg_action);
6657         return 0;
6658 }
6659
6660 static int halt_now(enum action a) {
6661
6662 /* Make sure C-A-D is handled by the kernel from this
6663          * point on... */
6664         reboot(RB_ENABLE_CAD);
6665
6666         switch (a) {
6667
6668         case ACTION_HALT:
6669                 log_info("Halting.");
6670                 reboot(RB_HALT_SYSTEM);
6671                 return -errno;
6672
6673         case ACTION_POWEROFF:
6674                 log_info("Powering off.");
6675                 reboot(RB_POWER_OFF);
6676                 return -errno;
6677
6678         case ACTION_REBOOT: {
6679                 _cleanup_free_ char *param = NULL;
6680
6681                 if (read_one_line_file(REBOOT_PARAM_FILE, &param) >= 0) {
6682                         log_info("Rebooting with argument '%s'.", param);
6683                         syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
6684                                 LINUX_REBOOT_CMD_RESTART2, param);
6685                 }
6686
6687                 log_info("Rebooting.");
6688                 reboot(RB_AUTOBOOT);
6689                 return -errno;
6690         }
6691
6692         default:
6693                 assert_not_reached("Unknown action.");
6694         }
6695 }
6696
6697 static int halt_main(sd_bus *bus) {
6698         int r;
6699
6700         r = check_inhibitors(bus, arg_action);
6701         if (r < 0)
6702                 return r;
6703
6704         if (geteuid() != 0) {
6705                 /* Try logind if we are a normal user and no special
6706                  * mode applies. Maybe PolicyKit allows us to shutdown
6707                  * the machine. */
6708
6709                 if (arg_when <= 0 &&
6710                     !arg_dry &&
6711                     arg_force <= 0 &&
6712                     (arg_action == ACTION_POWEROFF ||
6713                      arg_action == ACTION_REBOOT)) {
6714                         r = reboot_with_logind(bus, arg_action);
6715                         if (r >= 0)
6716                                 return r;
6717                 }
6718
6719                 log_error("Must be root.");
6720                 return -EPERM;
6721         }
6722
6723         if (arg_when > 0) {
6724                 _cleanup_free_ char *m;
6725
6726                 m = strv_join(arg_wall, " ");
6727                 if (!m)
6728                         return log_oom();
6729
6730                 r = send_shutdownd(arg_when,
6731                                    arg_action == ACTION_HALT     ? 'H' :
6732                                    arg_action == ACTION_POWEROFF ? 'P' :
6733                                    arg_action == ACTION_KEXEC    ? 'K' :
6734                                                                    'r',
6735                                    arg_dry,
6736                                    !arg_no_wall,
6737                                    m);
6738
6739                 if (r < 0)
6740                         log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
6741                 else {
6742                         char date[FORMAT_TIMESTAMP_MAX];
6743
6744                         log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
6745                                  format_timestamp(date, sizeof(date), arg_when));
6746                         return 0;
6747                 }
6748         }
6749
6750         if (!arg_dry && !arg_force)
6751                 return start_with_fallback(bus);
6752
6753         if (!arg_no_wtmp) {
6754                 if (sd_booted() > 0)
6755                         log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
6756                 else {
6757                         r = utmp_put_shutdown();
6758                         if (r < 0)
6759                                 log_warning("Failed to write utmp record: %s", strerror(-r));
6760                 }
6761         }
6762
6763         if (arg_dry)
6764                 return 0;
6765
6766         r = halt_now(arg_action);
6767         log_error("Failed to reboot: %s", strerror(-r));
6768
6769         return r;
6770 }
6771
6772 static int runlevel_main(void) {
6773         int r, runlevel, previous;
6774
6775         r = utmp_get_runlevel(&runlevel, &previous);
6776         if (r < 0) {
6777                 puts("unknown");
6778                 return r;
6779         }
6780
6781         printf("%c %c\n",
6782                previous <= 0 ? 'N' : previous,
6783                runlevel <= 0 ? 'N' : runlevel);
6784
6785         return 0;
6786 }
6787
6788 int main(int argc, char*argv[]) {
6789         _cleanup_bus_unref_ sd_bus *bus = NULL;
6790         int r;
6791
6792         setlocale(LC_ALL, "");
6793         log_parse_environment();
6794         log_open();
6795
6796         /* Explicitly not on_tty() to avoid setting cached value.
6797          * This becomes relevant for piping output which might be
6798          * ellipsized. */
6799         original_stdout_is_tty = isatty(STDOUT_FILENO);
6800
6801         r = parse_argv(argc, argv);
6802         if (r <= 0)
6803                 goto finish;
6804
6805         /* /sbin/runlevel doesn't need to communicate via D-Bus, so
6806          * let's shortcut this */
6807         if (arg_action == ACTION_RUNLEVEL) {
6808                 r = runlevel_main();
6809                 goto finish;
6810         }
6811
6812         if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
6813                 log_info("Running in chroot, ignoring request.");
6814                 r = 0;
6815                 goto finish;
6816         }
6817
6818         if (!avoid_bus())
6819                 r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus);
6820
6821         /* systemctl_main() will print an error message for the bus
6822          * connection, but only if it needs to */
6823
6824         switch (arg_action) {
6825
6826         case ACTION_SYSTEMCTL:
6827                 r = systemctl_main(bus, argc, argv, r);
6828                 break;
6829
6830         case ACTION_HALT:
6831         case ACTION_POWEROFF:
6832         case ACTION_REBOOT:
6833         case ACTION_KEXEC:
6834                 r = halt_main(bus);
6835                 break;
6836
6837         case ACTION_RUNLEVEL2:
6838         case ACTION_RUNLEVEL3:
6839         case ACTION_RUNLEVEL4:
6840         case ACTION_RUNLEVEL5:
6841         case ACTION_RESCUE:
6842         case ACTION_EMERGENCY:
6843         case ACTION_DEFAULT:
6844                 r = start_with_fallback(bus);
6845                 break;
6846
6847         case ACTION_RELOAD:
6848         case ACTION_REEXEC:
6849                 r = reload_with_fallback(bus);
6850                 break;
6851
6852         case ACTION_CANCEL_SHUTDOWN: {
6853                 _cleanup_free_ char *m = NULL;
6854
6855                 if (arg_wall) {
6856                         m = strv_join(arg_wall, " ");
6857                         if (!m) {
6858                                 r = log_oom();
6859                                 goto finish;
6860                         }
6861                 }
6862
6863                 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
6864                 if (r < 0)
6865                         log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
6866                 break;
6867         }
6868
6869         case ACTION_RUNLEVEL:
6870         case _ACTION_INVALID:
6871         default:
6872                 assert_not_reached("Unknown action");
6873         }
6874
6875 finish:
6876         pager_close();
6877         ask_password_agent_close();
6878         polkit_agent_close();
6879
6880         strv_free(arg_types);
6881         strv_free(arg_states);
6882         strv_free(arg_properties);
6883
6884         return r < 0 ? EXIT_FAILURE : r;
6885 }