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