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