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