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