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