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