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