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