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