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