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