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