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