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