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