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