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