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