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