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