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