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