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