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