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