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