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