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