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