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