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