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