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