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