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