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