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