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