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