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