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