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