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