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