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