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