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