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