]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/systemctl/systemctl.c
Merge pull request #11975 from keszybz/fuzzer-fixes-n
[thirdparty/systemd.git] / src / systemctl / systemctl.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <errno.h>
4 #include <fcntl.h>
5 #include <getopt.h>
6 #include <locale.h>
7 #include <stdbool.h>
8 #include <stddef.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <sys/mount.h>
12 #include <sys/prctl.h>
13 #include <sys/reboot.h>
14 #include <sys/socket.h>
15 #include <unistd.h>
16
17 #include "sd-bus.h"
18 #include "sd-daemon.h"
19 #include "sd-event.h"
20 #include "sd-login.h"
21
22 #include "alloc-util.h"
23 #include "bootspec.h"
24 #include "bus-common-errors.h"
25 #include "bus-error.h"
26 #include "bus-message.h"
27 #include "bus-unit-procs.h"
28 #include "bus-unit-util.h"
29 #include "bus-util.h"
30 #include "bus-wait-for-jobs.h"
31 #include "cgroup-show.h"
32 #include "cgroup-util.h"
33 #include "copy.h"
34 #include "dropin.h"
35 #include "efivars.h"
36 #include "env-util.h"
37 #include "escape.h"
38 #include "exit-status.h"
39 #include "fd-util.h"
40 #include "format-util.h"
41 #include "fs-util.h"
42 #include "glob-util.h"
43 #include "hexdecoct.h"
44 #include "hostname-util.h"
45 #include "in-addr-util.h"
46 #include "initreq.h"
47 #include "install.h"
48 #include "io-util.h"
49 #include "journal-util.h"
50 #include "list.h"
51 #include "locale-util.h"
52 #include "log.h"
53 #include "logs-show.h"
54 #include "macro.h"
55 #include "main-func.h"
56 #include "memory-util.h"
57 #include "mkdir.h"
58 #include "pager.h"
59 #include "parse-util.h"
60 #include "path-lookup.h"
61 #include "path-util.h"
62 #include "pretty-print.h"
63 #include "proc-cmdline.h"
64 #include "process-util.h"
65 #include "reboot-util.h"
66 #include "rlimit-util.h"
67 #include "set.h"
68 #include "sigbus.h"
69 #include "signal-util.h"
70 #include "socket-util.h"
71 #include "sort-util.h"
72 #include "spawn-ask-password-agent.h"
73 #include "spawn-polkit-agent.h"
74 #include "special.h"
75 #include "stat-util.h"
76 #include "string-table.h"
77 #include "strv.h"
78 #include "terminal-util.h"
79 #include "tmpfile-util.h"
80 #include "unit-def.h"
81 #include "unit-name.h"
82 #include "user-util.h"
83 #include "utf8.h"
84 #include "utmp-wtmp.h"
85 #include "verbs.h"
86 #include "virt.h"
87
88 /* The init script exit status codes
89 0 program is running or service is OK
90 1 program is dead and /var/run pid file exists
91 2 program is dead and /var/lock lock file exists
92 3 program is not running
93 4 program or service status is unknown
94 5-99 reserved for future LSB use
95 100-149 reserved for distribution use
96 150-199 reserved for application use
97 200-254 reserved
98 */
99 enum {
100 EXIT_PROGRAM_RUNNING_OR_SERVICE_OK = 0,
101 EXIT_PROGRAM_DEAD_AND_PID_EXISTS = 1,
102 EXIT_PROGRAM_DEAD_AND_LOCK_FILE_EXISTS = 2,
103 EXIT_PROGRAM_NOT_RUNNING = 3,
104 EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN = 4,
105 };
106
107 static char **arg_types = NULL;
108 static char **arg_states = NULL;
109 static char **arg_properties = NULL;
110 static bool arg_all = false;
111 static enum dependency {
112 DEPENDENCY_FORWARD,
113 DEPENDENCY_REVERSE,
114 DEPENDENCY_AFTER,
115 DEPENDENCY_BEFORE,
116 _DEPENDENCY_MAX
117 } arg_dependency = DEPENDENCY_FORWARD;
118 static const char *arg_job_mode = "replace";
119 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
120 static bool arg_wait = false;
121 static bool arg_no_block = false;
122 static bool arg_no_legend = false;
123 static PagerFlags arg_pager_flags = 0;
124 static bool arg_no_wtmp = false;
125 static bool arg_no_sync = false;
126 static bool arg_no_wall = false;
127 static bool arg_no_reload = false;
128 static bool arg_value = false;
129 static bool arg_show_types = false;
130 static bool arg_ignore_inhibitors = false;
131 static bool arg_dry_run = false;
132 static bool arg_quiet = false;
133 static bool arg_full = false;
134 static bool arg_recursive = false;
135 static int arg_force = 0;
136 static bool arg_ask_password = false;
137 static bool arg_runtime = false;
138 static UnitFilePresetMode arg_preset_mode = UNIT_FILE_PRESET_FULL;
139 static char **arg_wall = NULL;
140 static const char *arg_kill_who = NULL;
141 static int arg_signal = SIGTERM;
142 static char *arg_root = NULL;
143 static usec_t arg_when = 0;
144 static char *argv_cmdline = NULL;
145 static enum action {
146 ACTION_SYSTEMCTL,
147 ACTION_HALT,
148 ACTION_POWEROFF,
149 ACTION_REBOOT,
150 ACTION_KEXEC,
151 ACTION_EXIT,
152 ACTION_SUSPEND,
153 ACTION_HIBERNATE,
154 ACTION_HYBRID_SLEEP,
155 ACTION_SUSPEND_THEN_HIBERNATE,
156 ACTION_RUNLEVEL2,
157 ACTION_RUNLEVEL3,
158 ACTION_RUNLEVEL4,
159 ACTION_RUNLEVEL5,
160 ACTION_RESCUE,
161 ACTION_EMERGENCY,
162 ACTION_DEFAULT,
163 ACTION_RELOAD,
164 ACTION_REEXEC,
165 ACTION_RUNLEVEL,
166 ACTION_CANCEL_SHUTDOWN,
167 _ACTION_MAX,
168 _ACTION_INVALID = -1
169 } arg_action = ACTION_SYSTEMCTL;
170 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
171 static const char *arg_host = NULL;
172 static unsigned arg_lines = 10;
173 static OutputMode arg_output = OUTPUT_SHORT;
174 static bool arg_plain = false;
175 static bool arg_firmware_setup = false;
176 static usec_t arg_boot_loader_menu = USEC_INFINITY;
177 static const char *arg_boot_loader_entry = NULL;
178 static bool arg_now = false;
179 static bool arg_jobs_before = false;
180 static bool arg_jobs_after = false;
181
182 static int daemon_reload(int argc, char *argv[], void* userdata);
183 static int trivial_method(int argc, char *argv[], void *userdata);
184 static int halt_now(enum action a);
185 static int get_state_one_unit(sd_bus *bus, const char *name, UnitActiveState *active_state);
186
187 static bool original_stdout_is_tty;
188
189 typedef enum BusFocus {
190 BUS_FULL, /* The full bus indicated via --system or --user */
191 BUS_MANAGER, /* The manager itself, possibly directly, possibly via the bus */
192 _BUS_FOCUS_MAX
193 } BusFocus;
194
195 static sd_bus *busses[_BUS_FOCUS_MAX] = {};
196
197 static UnitFileFlags args_to_flags(void) {
198 return (arg_runtime ? UNIT_FILE_RUNTIME : 0) |
199 (arg_force ? UNIT_FILE_FORCE : 0);
200 }
201
202 static int acquire_bus(BusFocus focus, sd_bus **ret) {
203 int r;
204
205 assert(focus < _BUS_FOCUS_MAX);
206 assert(ret);
207
208 /* We only go directly to the manager, if we are using a local transport */
209 if (arg_transport != BUS_TRANSPORT_LOCAL)
210 focus = BUS_FULL;
211
212 if (getenv_bool("SYSTEMCTL_FORCE_BUS") > 0)
213 focus = BUS_FULL;
214
215 if (!busses[focus]) {
216 bool user;
217
218 user = arg_scope != UNIT_FILE_SYSTEM;
219
220 if (focus == BUS_MANAGER)
221 r = bus_connect_transport_systemd(arg_transport, arg_host, user, &busses[focus]);
222 else
223 r = bus_connect_transport(arg_transport, arg_host, user, &busses[focus]);
224 if (r < 0)
225 return log_error_errno(r, "Failed to connect to bus: %m");
226
227 (void) sd_bus_set_allow_interactive_authorization(busses[focus], arg_ask_password);
228 }
229
230 *ret = busses[focus];
231 return 0;
232 }
233
234 static void release_busses(void) {
235 BusFocus w;
236
237 for (w = 0; w < _BUS_FOCUS_MAX; w++)
238 busses[w] = sd_bus_flush_close_unref(busses[w]);
239 }
240
241 static void ask_password_agent_open_if_enabled(void) {
242 /* Open the password agent as a child process if necessary */
243
244 if (arg_dry_run)
245 return;
246
247 if (!arg_ask_password)
248 return;
249
250 if (arg_scope != UNIT_FILE_SYSTEM)
251 return;
252
253 if (arg_transport != BUS_TRANSPORT_LOCAL)
254 return;
255
256 ask_password_agent_open();
257 }
258
259 static void polkit_agent_open_maybe(void) {
260 /* Open the polkit agent as a child process if necessary */
261
262 if (arg_scope != UNIT_FILE_SYSTEM)
263 return;
264
265 polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
266 }
267
268 static OutputFlags get_output_flags(void) {
269 return
270 arg_all * OUTPUT_SHOW_ALL |
271 (arg_full || !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
272 colors_enabled() * OUTPUT_COLOR |
273 !arg_quiet * OUTPUT_WARN_CUTOFF;
274 }
275
276 static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) {
277 assert(error);
278
279 if (!sd_bus_error_is_set(error))
280 return r;
281
282 if (sd_bus_error_has_name(error, SD_BUS_ERROR_ACCESS_DENIED) ||
283 sd_bus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
284 sd_bus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
285 sd_bus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
286 return EXIT_NOPERMISSION;
287
288 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
289 return EXIT_NOTINSTALLED;
290
291 if (sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
292 sd_bus_error_has_name(error, SD_BUS_ERROR_NOT_SUPPORTED))
293 return EXIT_NOTIMPLEMENTED;
294
295 if (sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
296 return EXIT_NOTCONFIGURED;
297
298 if (r != 0)
299 return r;
300
301 return EXIT_FAILURE;
302 }
303
304 static bool install_client_side(void) {
305 /* Decides when to execute enable/disable/... operations
306 * client-side rather than server-side. */
307
308 if (running_in_chroot_or_offline())
309 return true;
310
311 if (sd_booted() <= 0)
312 return true;
313
314 if (!isempty(arg_root))
315 return true;
316
317 if (arg_scope == UNIT_FILE_GLOBAL)
318 return true;
319
320 /* Unsupported environment variable, mostly for debugging purposes */
321 if (getenv_bool("SYSTEMCTL_INSTALL_CLIENT_SIDE") > 0)
322 return true;
323
324 return false;
325 }
326
327 static int compare_unit_info(const UnitInfo *a, const UnitInfo *b) {
328 const char *d1, *d2;
329 int r;
330
331 /* First, order by machine */
332 if (!a->machine && b->machine)
333 return -1;
334 if (a->machine && !b->machine)
335 return 1;
336 if (a->machine && b->machine) {
337 r = strcasecmp(a->machine, b->machine);
338 if (r != 0)
339 return r;
340 }
341
342 /* Second, order by unit type */
343 d1 = strrchr(a->id, '.');
344 d2 = strrchr(b->id, '.');
345 if (d1 && d2) {
346 r = strcasecmp(d1, d2);
347 if (r != 0)
348 return r;
349 }
350
351 /* Third, order by name */
352 return strcasecmp(a->id, b->id);
353 }
354
355 static const char* unit_type_suffix(const char *name) {
356 const char *dot;
357
358 dot = strrchr(name, '.');
359 if (!dot)
360 return "";
361
362 return dot + 1;
363 }
364
365 static bool output_show_unit(const UnitInfo *u, char **patterns) {
366 assert(u);
367
368 if (!strv_fnmatch_or_empty(patterns, u->id, FNM_NOESCAPE))
369 return false;
370
371 if (arg_types && !strv_find(arg_types, unit_type_suffix(u->id)))
372 return false;
373
374 if (arg_all)
375 return true;
376
377 /* Note that '--all' is not purely a state filter, but also a
378 * filter that hides units that "follow" other units (which is
379 * used for device units that appear under different names). */
380 if (!isempty(u->following))
381 return false;
382
383 if (!strv_isempty(arg_states))
384 return true;
385
386 /* By default show all units except the ones in inactive
387 * state and with no pending job */
388 if (u->job_id > 0)
389 return true;
390
391 if (streq(u->active_state, "inactive"))
392 return false;
393
394 return true;
395 }
396
397 static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
398 unsigned circle_len = 0, id_len, max_id_len, load_len, active_len, sub_len, job_len, desc_len, max_desc_len;
399 const UnitInfo *u;
400 unsigned n_shown = 0;
401 int job_count = 0;
402 bool full = arg_full || FLAGS_SET(arg_pager_flags, PAGER_DISABLE);
403
404 max_id_len = STRLEN("UNIT");
405 load_len = STRLEN("LOAD");
406 active_len = STRLEN("ACTIVE");
407 sub_len = STRLEN("SUB");
408 job_len = STRLEN("JOB");
409 max_desc_len = STRLEN("DESCRIPTION");
410
411 for (u = unit_infos; u < unit_infos + c; u++) {
412 max_id_len = MAX(max_id_len, strlen(u->id) + (u->machine ? strlen(u->machine)+1 : 0));
413 load_len = MAX(load_len, strlen(u->load_state));
414 active_len = MAX(active_len, strlen(u->active_state));
415 sub_len = MAX(sub_len, strlen(u->sub_state));
416 max_desc_len = MAX(max_desc_len, strlen(u->description));
417
418 if (u->job_id != 0) {
419 job_len = MAX(job_len, strlen(u->job_type));
420 job_count++;
421 }
422
423 if (!arg_no_legend &&
424 (streq(u->active_state, "failed") ||
425 STR_IN_SET(u->load_state, "error", "not-found", "bad-setting", "masked")))
426 circle_len = 2;
427 }
428
429 if (!arg_full && original_stdout_is_tty) {
430 unsigned basic_len;
431
432 id_len = MIN(max_id_len, 25u); /* as much as it needs, but at most 25 for now */
433 basic_len = circle_len + 1 + id_len + 1 + load_len + 1 + active_len + 1 + sub_len + 1;
434
435 if (job_count)
436 basic_len += job_len + 1;
437
438 if (basic_len < (unsigned) columns()) {
439 unsigned extra_len, incr;
440 extra_len = columns() - basic_len;
441
442 /* Either UNIT already got 25, or is fully satisfied.
443 * Grant up to 25 to DESC now. */
444 incr = MIN(extra_len, 25u);
445 desc_len = incr;
446 extra_len -= incr;
447
448 /* Of the remainder give as much as the ID needs to the ID, and give the rest to the
449 * description but not more than it needs. */
450 if (extra_len > 0) {
451 incr = MIN(max_id_len - id_len, extra_len);
452 id_len += incr;
453 desc_len += MIN(extra_len - incr, max_desc_len - desc_len);
454 }
455 } else
456 desc_len = 0;
457 } else {
458 id_len = max_id_len;
459 desc_len = max_desc_len;
460 }
461
462 for (u = unit_infos; u < unit_infos + c; u++) {
463 _cleanup_free_ char *e = NULL, *j = NULL;
464 const char *on_underline = "", *off_underline = "";
465 const char *on_loaded = "", *off_loaded = "";
466 const char *on_active = "", *off_active = "";
467 const char *on_circle = "", *off_circle = "";
468 const char *id;
469 bool circle = false, underline = false;
470
471 if (!n_shown && !arg_no_legend) {
472
473 if (circle_len > 0)
474 fputs(" ", stdout);
475
476 printf("%s%-*s %-*s %-*s %-*s ",
477 ansi_underline(),
478 id_len, "UNIT",
479 load_len, "LOAD",
480 active_len, "ACTIVE",
481 sub_len, "SUB");
482
483 if (job_count)
484 printf("%-*s ", job_len, "JOB");
485
486 printf("%-*.*s%s\n",
487 desc_len,
488 full ? -1 : (int) desc_len,
489 "DESCRIPTION",
490 ansi_normal());
491 }
492
493 n_shown++;
494
495 if (u + 1 < unit_infos + c &&
496 !streq(unit_type_suffix(u->id), unit_type_suffix((u + 1)->id))) {
497 on_underline = ansi_underline();
498 off_underline = ansi_normal();
499 underline = true;
500 }
501
502 if (STR_IN_SET(u->load_state, "error", "not-found", "bad-setting", "masked") && !arg_plain) {
503 on_circle = ansi_highlight_yellow();
504 off_circle = ansi_normal();
505 circle = true;
506 on_loaded = underline ? ansi_highlight_red_underline() : ansi_highlight_red();
507 off_loaded = underline ? on_underline : ansi_normal();
508 } else if (streq(u->active_state, "failed") && !arg_plain) {
509 on_circle = ansi_highlight_red();
510 off_circle = ansi_normal();
511 circle = true;
512 on_active = underline ? ansi_highlight_red_underline() : ansi_highlight_red();
513 off_active = underline ? on_underline : ansi_normal();
514 }
515
516 if (u->machine) {
517 j = strjoin(u->machine, ":", u->id);
518 if (!j)
519 return log_oom();
520
521 id = j;
522 } else
523 id = u->id;
524
525 if (arg_full) {
526 e = ellipsize(id, id_len, 33);
527 if (!e)
528 return log_oom();
529
530 id = e;
531 }
532
533 if (circle_len > 0)
534 printf("%s%s%s ", on_circle, circle ? special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE) : " ", off_circle);
535
536 printf("%s%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
537 on_underline,
538 on_active, id_len, id, off_active,
539 on_loaded, load_len, u->load_state, off_loaded,
540 on_active, active_len, u->active_state,
541 sub_len, u->sub_state, off_active,
542 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
543
544 printf("%-*.*s%s\n",
545 desc_len,
546 full ? -1 : (int) desc_len,
547 u->description,
548 off_underline);
549 }
550
551 if (!arg_no_legend) {
552 const char *on, *off;
553
554 if (n_shown) {
555 puts("\n"
556 "LOAD = Reflects whether the unit definition was properly loaded.\n"
557 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
558 "SUB = The low-level unit activation state, values depend on unit type.");
559 puts(job_count ? "JOB = Pending job for the unit.\n" : "");
560 on = ansi_highlight();
561 off = ansi_normal();
562 } else {
563 on = ansi_highlight_red();
564 off = ansi_normal();
565 }
566
567 if (arg_all)
568 printf("%s%u loaded units listed.%s\n"
569 "To show all installed unit files use 'systemctl list-unit-files'.\n",
570 on, n_shown, off);
571 else
572 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
573 "To show all installed unit files use 'systemctl list-unit-files'.\n",
574 on, n_shown, off);
575 }
576
577 return 0;
578 }
579
580 static int get_unit_list(
581 sd_bus *bus,
582 const char *machine,
583 char **patterns,
584 UnitInfo **unit_infos,
585 int c,
586 sd_bus_message **_reply) {
587
588 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
589 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
590 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
591 size_t size = c;
592 int r;
593 UnitInfo u;
594 bool fallback = false;
595
596 assert(bus);
597 assert(unit_infos);
598 assert(_reply);
599
600 r = sd_bus_message_new_method_call(
601 bus,
602 &m,
603 "org.freedesktop.systemd1",
604 "/org/freedesktop/systemd1",
605 "org.freedesktop.systemd1.Manager",
606 "ListUnitsByPatterns");
607 if (r < 0)
608 return bus_log_create_error(r);
609
610 r = sd_bus_message_append_strv(m, arg_states);
611 if (r < 0)
612 return bus_log_create_error(r);
613
614 r = sd_bus_message_append_strv(m, patterns);
615 if (r < 0)
616 return bus_log_create_error(r);
617
618 r = sd_bus_call(bus, m, 0, &error, &reply);
619 if (r < 0 && (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD) ||
620 sd_bus_error_has_name(&error, SD_BUS_ERROR_ACCESS_DENIED))) {
621 /* Fallback to legacy ListUnitsFiltered method */
622 fallback = true;
623 log_debug_errno(r, "Failed to list units: %s Falling back to ListUnitsFiltered method.", bus_error_message(&error, r));
624 m = sd_bus_message_unref(m);
625 sd_bus_error_free(&error);
626
627 r = sd_bus_message_new_method_call(
628 bus,
629 &m,
630 "org.freedesktop.systemd1",
631 "/org/freedesktop/systemd1",
632 "org.freedesktop.systemd1.Manager",
633 "ListUnitsFiltered");
634 if (r < 0)
635 return bus_log_create_error(r);
636
637 r = sd_bus_message_append_strv(m, arg_states);
638 if (r < 0)
639 return bus_log_create_error(r);
640
641 r = sd_bus_call(bus, m, 0, &error, &reply);
642 }
643 if (r < 0)
644 return log_error_errno(r, "Failed to list units: %s", bus_error_message(&error, r));
645
646 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
647 if (r < 0)
648 return bus_log_parse_error(r);
649
650 while ((r = bus_parse_unit_info(reply, &u)) > 0) {
651 u.machine = machine;
652
653 if (!output_show_unit(&u, fallback ? patterns : NULL))
654 continue;
655
656 if (!GREEDY_REALLOC(*unit_infos, size, c+1))
657 return log_oom();
658
659 (*unit_infos)[c++] = u;
660 }
661 if (r < 0)
662 return bus_log_parse_error(r);
663
664 r = sd_bus_message_exit_container(reply);
665 if (r < 0)
666 return bus_log_parse_error(r);
667
668 *_reply = TAKE_PTR(reply);
669
670 return c;
671 }
672
673 static void message_set_freep(Set **set) {
674 set_free_with_destructor(*set, sd_bus_message_unref);
675 }
676
677 static int get_unit_list_recursive(
678 sd_bus *bus,
679 char **patterns,
680 UnitInfo **_unit_infos,
681 Set **_replies,
682 char ***_machines) {
683
684 _cleanup_free_ UnitInfo *unit_infos = NULL;
685 _cleanup_(message_set_freep) Set *replies;
686 sd_bus_message *reply;
687 int c, r;
688
689 assert(bus);
690 assert(_replies);
691 assert(_unit_infos);
692 assert(_machines);
693
694 replies = set_new(NULL);
695 if (!replies)
696 return log_oom();
697
698 c = get_unit_list(bus, NULL, patterns, &unit_infos, 0, &reply);
699 if (c < 0)
700 return c;
701
702 r = set_put(replies, reply);
703 if (r < 0) {
704 sd_bus_message_unref(reply);
705 return log_oom();
706 }
707
708 if (arg_recursive) {
709 _cleanup_strv_free_ char **machines = NULL;
710 char **i;
711
712 r = sd_get_machine_names(&machines);
713 if (r < 0)
714 return log_error_errno(r, "Failed to get machine names: %m");
715
716 STRV_FOREACH(i, machines) {
717 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *container = NULL;
718 int k;
719
720 r = sd_bus_open_system_machine(&container, *i);
721 if (r < 0) {
722 log_warning_errno(r, "Failed to connect to container %s, ignoring: %m", *i);
723 continue;
724 }
725
726 k = get_unit_list(container, *i, patterns, &unit_infos, c, &reply);
727 if (k < 0)
728 return k;
729
730 c = k;
731
732 r = set_put(replies, reply);
733 if (r < 0) {
734 sd_bus_message_unref(reply);
735 return log_oom();
736 }
737 }
738
739 *_machines = TAKE_PTR(machines);
740 } else
741 *_machines = NULL;
742
743 *_unit_infos = TAKE_PTR(unit_infos);
744
745 *_replies = TAKE_PTR(replies);
746
747 return c;
748 }
749
750 static int list_units(int argc, char *argv[], void *userdata) {
751 _cleanup_free_ UnitInfo *unit_infos = NULL;
752 _cleanup_(message_set_freep) Set *replies = NULL;
753 _cleanup_strv_free_ char **machines = NULL;
754 sd_bus *bus;
755 int r;
756
757 r = acquire_bus(BUS_MANAGER, &bus);
758 if (r < 0)
759 return r;
760
761 (void) pager_open(arg_pager_flags);
762
763 r = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines);
764 if (r < 0)
765 return r;
766
767 typesafe_qsort(unit_infos, r, compare_unit_info);
768 return output_units_list(unit_infos, r);
769 }
770
771 static int get_triggered_units(
772 sd_bus *bus,
773 const char* path,
774 char*** ret) {
775
776 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
777 int r;
778
779 assert(bus);
780 assert(path);
781 assert(ret);
782
783 r = sd_bus_get_property_strv(
784 bus,
785 "org.freedesktop.systemd1",
786 path,
787 "org.freedesktop.systemd1.Unit",
788 "Triggers",
789 &error,
790 ret);
791 if (r < 0)
792 return log_error_errno(r, "Failed to determine triggers: %s", bus_error_message(&error, r));
793
794 return 0;
795 }
796
797 static int get_listening(
798 sd_bus *bus,
799 const char* unit_path,
800 char*** listening) {
801
802 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
803 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
804 const char *type, *path;
805 int r, n = 0;
806
807 r = sd_bus_get_property(
808 bus,
809 "org.freedesktop.systemd1",
810 unit_path,
811 "org.freedesktop.systemd1.Socket",
812 "Listen",
813 &error,
814 &reply,
815 "a(ss)");
816 if (r < 0)
817 return log_error_errno(r, "Failed to get list of listening sockets: %s", bus_error_message(&error, r));
818
819 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
820 if (r < 0)
821 return bus_log_parse_error(r);
822
823 while ((r = sd_bus_message_read(reply, "(ss)", &type, &path)) > 0) {
824
825 r = strv_extend(listening, type);
826 if (r < 0)
827 return log_oom();
828
829 r = strv_extend(listening, path);
830 if (r < 0)
831 return log_oom();
832
833 n++;
834 }
835 if (r < 0)
836 return bus_log_parse_error(r);
837
838 r = sd_bus_message_exit_container(reply);
839 if (r < 0)
840 return bus_log_parse_error(r);
841
842 return n;
843 }
844
845 struct socket_info {
846 const char *machine;
847 const char* id;
848
849 char* type;
850 char* path;
851
852 /* Note: triggered is a list here, although it almost certainly
853 * will always be one unit. Nevertheless, dbus API allows for multiple
854 * values, so let's follow that. */
855 char** triggered;
856
857 /* The strv above is shared. free is set only in the first one. */
858 bool own_triggered;
859 };
860
861 static int socket_info_compare(const struct socket_info *a, const struct socket_info *b) {
862 int r;
863
864 assert(a);
865 assert(b);
866
867 if (!a->machine && b->machine)
868 return -1;
869 if (a->machine && !b->machine)
870 return 1;
871 if (a->machine && b->machine) {
872 r = strcasecmp(a->machine, b->machine);
873 if (r != 0)
874 return r;
875 }
876
877 r = strcmp(a->path, b->path);
878 if (r == 0)
879 r = strcmp(a->type, b->type);
880
881 return r;
882 }
883
884 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
885 struct socket_info *s;
886 unsigned pathlen = STRLEN("LISTEN"),
887 typelen = STRLEN("TYPE") * arg_show_types,
888 socklen = STRLEN("UNIT"),
889 servlen = STRLEN("ACTIVATES");
890 const char *on, *off;
891
892 for (s = socket_infos; s < socket_infos + cs; s++) {
893 unsigned tmp = 0;
894 char **a;
895
896 socklen = MAX(socklen, strlen(s->id));
897 if (arg_show_types)
898 typelen = MAX(typelen, strlen(s->type));
899 pathlen = MAX(pathlen, strlen(s->path) + (s->machine ? strlen(s->machine)+1 : 0));
900
901 STRV_FOREACH(a, s->triggered)
902 tmp += strlen(*a) + 2*(a != s->triggered);
903 servlen = MAX(servlen, tmp);
904 }
905
906 if (cs) {
907 if (!arg_no_legend)
908 printf("%-*s %-*.*s%-*s %s\n",
909 pathlen, "LISTEN",
910 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
911 socklen, "UNIT",
912 "ACTIVATES");
913
914 for (s = socket_infos; s < socket_infos + cs; s++) {
915 _cleanup_free_ char *j = NULL;
916 const char *path;
917 char **a;
918
919 if (s->machine) {
920 j = strjoin(s->machine, ":", s->path);
921 if (!j)
922 return log_oom();
923 path = j;
924 } else
925 path = s->path;
926
927 if (arg_show_types)
928 printf("%-*s %-*s %-*s",
929 pathlen, path, typelen, s->type, socklen, s->id);
930 else
931 printf("%-*s %-*s",
932 pathlen, path, socklen, s->id);
933 STRV_FOREACH(a, s->triggered)
934 printf("%s %s",
935 a == s->triggered ? "" : ",", *a);
936 printf("\n");
937 }
938
939 on = ansi_highlight();
940 off = ansi_normal();
941 if (!arg_no_legend)
942 printf("\n");
943 } else {
944 on = ansi_highlight_red();
945 off = ansi_normal();
946 }
947
948 if (!arg_no_legend) {
949 printf("%s%u sockets listed.%s\n", on, cs, off);
950 if (!arg_all)
951 printf("Pass --all to see loaded but inactive sockets, too.\n");
952 }
953
954 return 0;
955 }
956
957 static int list_sockets(int argc, char *argv[], void *userdata) {
958 _cleanup_(message_set_freep) Set *replies = NULL;
959 _cleanup_strv_free_ char **machines = NULL;
960 _cleanup_free_ UnitInfo *unit_infos = NULL;
961 _cleanup_free_ struct socket_info *socket_infos = NULL;
962 const UnitInfo *u;
963 struct socket_info *s;
964 unsigned cs = 0;
965 size_t size = 0;
966 int r = 0, n;
967 sd_bus *bus;
968
969 r = acquire_bus(BUS_MANAGER, &bus);
970 if (r < 0)
971 return r;
972
973 (void) pager_open(arg_pager_flags);
974
975 n = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines);
976 if (n < 0)
977 return n;
978
979 for (u = unit_infos; u < unit_infos + n; u++) {
980 _cleanup_strv_free_ char **listening = NULL, **triggered = NULL;
981 int i, c;
982
983 if (!endswith(u->id, ".socket"))
984 continue;
985
986 r = get_triggered_units(bus, u->unit_path, &triggered);
987 if (r < 0)
988 goto cleanup;
989
990 c = get_listening(bus, u->unit_path, &listening);
991 if (c < 0) {
992 r = c;
993 goto cleanup;
994 }
995
996 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
997 r = log_oom();
998 goto cleanup;
999 }
1000
1001 for (i = 0; i < c; i++)
1002 socket_infos[cs + i] = (struct socket_info) {
1003 .machine = u->machine,
1004 .id = u->id,
1005 .type = listening[i*2],
1006 .path = listening[i*2 + 1],
1007 .triggered = triggered,
1008 .own_triggered = i==0,
1009 };
1010
1011 /* from this point on we will cleanup those socket_infos */
1012 cs += c;
1013 free(listening);
1014 listening = triggered = NULL; /* avoid cleanup */
1015 }
1016
1017 typesafe_qsort(socket_infos, cs, socket_info_compare);
1018
1019 output_sockets_list(socket_infos, cs);
1020
1021 cleanup:
1022 assert(cs == 0 || socket_infos);
1023 for (s = socket_infos; s < socket_infos + cs; s++) {
1024 free(s->type);
1025 free(s->path);
1026 if (s->own_triggered)
1027 strv_free(s->triggered);
1028 }
1029
1030 return r;
1031 }
1032
1033 static int get_next_elapse(
1034 sd_bus *bus,
1035 const char *path,
1036 dual_timestamp *next) {
1037
1038 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1039 dual_timestamp t;
1040 int r;
1041
1042 assert(bus);
1043 assert(path);
1044 assert(next);
1045
1046 r = sd_bus_get_property_trivial(
1047 bus,
1048 "org.freedesktop.systemd1",
1049 path,
1050 "org.freedesktop.systemd1.Timer",
1051 "NextElapseUSecMonotonic",
1052 &error,
1053 't',
1054 &t.monotonic);
1055 if (r < 0)
1056 return log_error_errno(r, "Failed to get next elapse time: %s", bus_error_message(&error, r));
1057
1058 r = sd_bus_get_property_trivial(
1059 bus,
1060 "org.freedesktop.systemd1",
1061 path,
1062 "org.freedesktop.systemd1.Timer",
1063 "NextElapseUSecRealtime",
1064 &error,
1065 't',
1066 &t.realtime);
1067 if (r < 0)
1068 return log_error_errno(r, "Failed to get next elapse time: %s", bus_error_message(&error, r));
1069
1070 *next = t;
1071 return 0;
1072 }
1073
1074 static int get_last_trigger(
1075 sd_bus *bus,
1076 const char *path,
1077 usec_t *last) {
1078
1079 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1080 int r;
1081
1082 assert(bus);
1083 assert(path);
1084 assert(last);
1085
1086 r = sd_bus_get_property_trivial(
1087 bus,
1088 "org.freedesktop.systemd1",
1089 path,
1090 "org.freedesktop.systemd1.Timer",
1091 "LastTriggerUSec",
1092 &error,
1093 't',
1094 last);
1095 if (r < 0)
1096 return log_error_errno(r, "Failed to get last trigger time: %s", bus_error_message(&error, r));
1097
1098 return 0;
1099 }
1100
1101 struct timer_info {
1102 const char* machine;
1103 const char* id;
1104 usec_t next_elapse;
1105 usec_t last_trigger;
1106 char** triggered;
1107 };
1108
1109 static int timer_info_compare(const struct timer_info *a, const struct timer_info *b) {
1110 int r;
1111
1112 assert(a);
1113 assert(b);
1114
1115 if (!a->machine && b->machine)
1116 return -1;
1117 if (a->machine && !b->machine)
1118 return 1;
1119 if (a->machine && b->machine) {
1120 r = strcasecmp(a->machine, b->machine);
1121 if (r != 0)
1122 return r;
1123 }
1124
1125 r = CMP(a->next_elapse, b->next_elapse);
1126 if (r != 0)
1127 return r;
1128
1129 return strcmp(a->id, b->id);
1130 }
1131
1132 static int output_timers_list(struct timer_info *timer_infos, unsigned n) {
1133 struct timer_info *t;
1134 unsigned
1135 nextlen = STRLEN("NEXT"),
1136 leftlen = STRLEN("LEFT"),
1137 lastlen = STRLEN("LAST"),
1138 passedlen = STRLEN("PASSED"),
1139 unitlen = STRLEN("UNIT"),
1140 activatelen = STRLEN("ACTIVATES");
1141
1142 const char *on, *off;
1143
1144 assert(timer_infos || n == 0);
1145
1146 for (t = timer_infos; t < timer_infos + n; t++) {
1147 unsigned ul = 0;
1148 char **a;
1149
1150 if (t->next_elapse > 0) {
1151 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1152
1153 format_timestamp(tstamp, sizeof(tstamp), t->next_elapse);
1154 nextlen = MAX(nextlen, strlen(tstamp) + 1);
1155
1156 format_timestamp_relative(trel, sizeof(trel), t->next_elapse);
1157 leftlen = MAX(leftlen, strlen(trel));
1158 }
1159
1160 if (t->last_trigger > 0) {
1161 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1162
1163 format_timestamp(tstamp, sizeof(tstamp), t->last_trigger);
1164 lastlen = MAX(lastlen, strlen(tstamp) + 1);
1165
1166 format_timestamp_relative(trel, sizeof(trel), t->last_trigger);
1167 passedlen = MAX(passedlen, strlen(trel));
1168 }
1169
1170 unitlen = MAX(unitlen, strlen(t->id) + (t->machine ? strlen(t->machine)+1 : 0));
1171
1172 STRV_FOREACH(a, t->triggered)
1173 ul += strlen(*a) + 2*(a != t->triggered);
1174
1175 activatelen = MAX(activatelen, ul);
1176 }
1177
1178 if (n > 0) {
1179 if (!arg_no_legend)
1180 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1181 nextlen, "NEXT",
1182 leftlen, "LEFT",
1183 lastlen, "LAST",
1184 passedlen, "PASSED",
1185 unitlen, "UNIT",
1186 "ACTIVATES");
1187
1188 for (t = timer_infos; t < timer_infos + n; t++) {
1189 _cleanup_free_ char *j = NULL;
1190 const char *unit;
1191 char tstamp1[FORMAT_TIMESTAMP_MAX] = "n/a", trel1[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1192 char tstamp2[FORMAT_TIMESTAMP_MAX] = "n/a", trel2[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1193 char **a;
1194
1195 format_timestamp(tstamp1, sizeof(tstamp1), t->next_elapse);
1196 format_timestamp_relative(trel1, sizeof(trel1), t->next_elapse);
1197
1198 format_timestamp(tstamp2, sizeof(tstamp2), t->last_trigger);
1199 format_timestamp_relative(trel2, sizeof(trel2), t->last_trigger);
1200
1201 if (t->machine) {
1202 j = strjoin(t->machine, ":", t->id);
1203 if (!j)
1204 return log_oom();
1205 unit = j;
1206 } else
1207 unit = t->id;
1208
1209 printf("%-*s %-*s %-*s %-*s %-*s",
1210 nextlen, tstamp1, leftlen, trel1, lastlen, tstamp2, passedlen, trel2, unitlen, unit);
1211
1212 STRV_FOREACH(a, t->triggered)
1213 printf("%s %s",
1214 a == t->triggered ? "" : ",", *a);
1215 printf("\n");
1216 }
1217
1218 on = ansi_highlight();
1219 off = ansi_normal();
1220 if (!arg_no_legend)
1221 printf("\n");
1222 } else {
1223 on = ansi_highlight_red();
1224 off = ansi_normal();
1225 }
1226
1227 if (!arg_no_legend) {
1228 printf("%s%u timers listed.%s\n", on, n, off);
1229 if (!arg_all)
1230 printf("Pass --all to see loaded but inactive timers, too.\n");
1231 }
1232
1233 return 0;
1234 }
1235
1236 static usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next) {
1237 usec_t next_elapse;
1238
1239 assert(nw);
1240 assert(next);
1241
1242 if (next->monotonic != USEC_INFINITY && next->monotonic > 0) {
1243 usec_t converted;
1244
1245 if (next->monotonic > nw->monotonic)
1246 converted = nw->realtime + (next->monotonic - nw->monotonic);
1247 else
1248 converted = nw->realtime - (nw->monotonic - next->monotonic);
1249
1250 if (next->realtime != USEC_INFINITY && next->realtime > 0)
1251 next_elapse = MIN(converted, next->realtime);
1252 else
1253 next_elapse = converted;
1254
1255 } else
1256 next_elapse = next->realtime;
1257
1258 return next_elapse;
1259 }
1260
1261 static int list_timers(int argc, char *argv[], void *userdata) {
1262 _cleanup_(message_set_freep) Set *replies = NULL;
1263 _cleanup_strv_free_ char **machines = NULL;
1264 _cleanup_free_ struct timer_info *timer_infos = NULL;
1265 _cleanup_free_ UnitInfo *unit_infos = NULL;
1266 struct timer_info *t;
1267 const UnitInfo *u;
1268 size_t size = 0;
1269 int n, c = 0;
1270 dual_timestamp nw;
1271 sd_bus *bus;
1272 int r = 0;
1273
1274 r = acquire_bus(BUS_MANAGER, &bus);
1275 if (r < 0)
1276 return r;
1277
1278 (void) pager_open(arg_pager_flags);
1279
1280 n = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines);
1281 if (n < 0)
1282 return n;
1283
1284 dual_timestamp_get(&nw);
1285
1286 for (u = unit_infos; u < unit_infos + n; u++) {
1287 _cleanup_strv_free_ char **triggered = NULL;
1288 dual_timestamp next = DUAL_TIMESTAMP_NULL;
1289 usec_t m, last = 0;
1290
1291 if (!endswith(u->id, ".timer"))
1292 continue;
1293
1294 r = get_triggered_units(bus, u->unit_path, &triggered);
1295 if (r < 0)
1296 goto cleanup;
1297
1298 r = get_next_elapse(bus, u->unit_path, &next);
1299 if (r < 0)
1300 goto cleanup;
1301
1302 get_last_trigger(bus, u->unit_path, &last);
1303
1304 if (!GREEDY_REALLOC(timer_infos, size, c+1)) {
1305 r = log_oom();
1306 goto cleanup;
1307 }
1308
1309 m = calc_next_elapse(&nw, &next);
1310
1311 timer_infos[c++] = (struct timer_info) {
1312 .machine = u->machine,
1313 .id = u->id,
1314 .next_elapse = m,
1315 .last_trigger = last,
1316 .triggered = TAKE_PTR(triggered),
1317 };
1318 }
1319
1320 typesafe_qsort(timer_infos, c, timer_info_compare);
1321
1322 output_timers_list(timer_infos, c);
1323
1324 cleanup:
1325 for (t = timer_infos; t < timer_infos + c; t++)
1326 strv_free(t->triggered);
1327
1328 return r;
1329 }
1330
1331 static int compare_unit_file_list(const UnitFileList *a, const UnitFileList *b) {
1332 const char *d1, *d2;
1333
1334 d1 = strrchr(a->path, '.');
1335 d2 = strrchr(b->path, '.');
1336
1337 if (d1 && d2) {
1338 int r;
1339
1340 r = strcasecmp(d1, d2);
1341 if (r != 0)
1342 return r;
1343 }
1344
1345 return strcasecmp(basename(a->path), basename(b->path));
1346 }
1347
1348 static bool output_show_unit_file(const UnitFileList *u, char **states, char **patterns) {
1349 assert(u);
1350
1351 if (!strv_fnmatch_or_empty(patterns, basename(u->path), FNM_NOESCAPE))
1352 return false;
1353
1354 if (!strv_isempty(arg_types)) {
1355 const char *dot;
1356
1357 dot = strrchr(u->path, '.');
1358 if (!dot)
1359 return false;
1360
1361 if (!strv_find(arg_types, dot+1))
1362 return false;
1363 }
1364
1365 if (!strv_isempty(states) &&
1366 !strv_find(states, unit_file_state_to_string(u->state)))
1367 return false;
1368
1369 return true;
1370 }
1371
1372 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
1373 unsigned max_id_len, id_cols, state_cols;
1374 const UnitFileList *u;
1375
1376 max_id_len = STRLEN("UNIT FILE");
1377 state_cols = STRLEN("STATE");
1378
1379 for (u = units; u < units + c; u++) {
1380 max_id_len = MAX(max_id_len, strlen(basename(u->path)));
1381 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
1382 }
1383
1384 if (!arg_full) {
1385 unsigned basic_cols;
1386
1387 id_cols = MIN(max_id_len, 25u);
1388 basic_cols = 1 + id_cols + state_cols;
1389 if (basic_cols < (unsigned) columns())
1390 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
1391 } else
1392 id_cols = max_id_len;
1393
1394 if (!arg_no_legend && c > 0)
1395 printf("%s%-*s %-*s%s\n",
1396 ansi_underline(),
1397 id_cols, "UNIT FILE",
1398 state_cols, "STATE",
1399 ansi_normal());
1400
1401 for (u = units; u < units + c; u++) {
1402 const char *on_underline = NULL, *on_color = NULL, *off = NULL, *id;
1403 _cleanup_free_ char *e = NULL;
1404 bool underline;
1405
1406 underline = u + 1 < units + c &&
1407 !streq(unit_type_suffix(u->path), unit_type_suffix((u + 1)->path));
1408
1409 if (underline)
1410 on_underline = ansi_underline();
1411
1412 if (IN_SET(u->state,
1413 UNIT_FILE_MASKED,
1414 UNIT_FILE_MASKED_RUNTIME,
1415 UNIT_FILE_DISABLED,
1416 UNIT_FILE_BAD))
1417 on_color = underline ? ansi_highlight_red_underline() : ansi_highlight_red();
1418 else if (u->state == UNIT_FILE_ENABLED)
1419 on_color = underline ? ansi_highlight_green_underline() : ansi_highlight_green();
1420
1421 if (on_underline || on_color)
1422 off = ansi_normal();
1423
1424 id = basename(u->path);
1425
1426 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
1427
1428 printf("%s%-*s %s%-*s%s\n",
1429 strempty(on_underline),
1430 id_cols, e ? e : id,
1431 strempty(on_color), state_cols, unit_file_state_to_string(u->state), strempty(off));
1432 }
1433
1434 if (!arg_no_legend)
1435 printf("\n%u unit files listed.\n", c);
1436 }
1437
1438 static int list_unit_files(int argc, char *argv[], void *userdata) {
1439 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1440 _cleanup_free_ UnitFileList *units = NULL;
1441 UnitFileList *unit;
1442 size_t size = 0;
1443 unsigned c = 0;
1444 const char *state;
1445 char *path;
1446 int r;
1447 bool fallback = false;
1448
1449 if (install_client_side()) {
1450 Hashmap *h;
1451 UnitFileList *u;
1452 Iterator i;
1453 unsigned n_units;
1454
1455 h = hashmap_new(&string_hash_ops);
1456 if (!h)
1457 return log_oom();
1458
1459 r = unit_file_get_list(arg_scope, arg_root, h, arg_states, strv_skip(argv, 1));
1460 if (r < 0) {
1461 unit_file_list_free(h);
1462 return log_error_errno(r, "Failed to get unit file list: %m");
1463 }
1464
1465 n_units = hashmap_size(h);
1466
1467 units = new(UnitFileList, n_units ?: 1); /* avoid malloc(0) */
1468 if (!units) {
1469 unit_file_list_free(h);
1470 return log_oom();
1471 }
1472
1473 HASHMAP_FOREACH(u, h, i) {
1474 if (!output_show_unit_file(u, NULL, NULL))
1475 continue;
1476
1477 units[c++] = *u;
1478 free(u);
1479 }
1480
1481 assert(c <= n_units);
1482 hashmap_free(h);
1483
1484 r = 0;
1485 } else {
1486 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
1487 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1488 sd_bus *bus;
1489
1490 r = acquire_bus(BUS_MANAGER, &bus);
1491 if (r < 0)
1492 return r;
1493
1494 r = sd_bus_message_new_method_call(
1495 bus,
1496 &m,
1497 "org.freedesktop.systemd1",
1498 "/org/freedesktop/systemd1",
1499 "org.freedesktop.systemd1.Manager",
1500 "ListUnitFilesByPatterns");
1501 if (r < 0)
1502 return bus_log_create_error(r);
1503
1504 r = sd_bus_message_append_strv(m, arg_states);
1505 if (r < 0)
1506 return bus_log_create_error(r);
1507
1508 r = sd_bus_message_append_strv(m, strv_skip(argv, 1));
1509 if (r < 0)
1510 return bus_log_create_error(r);
1511
1512 r = sd_bus_call(bus, m, 0, &error, &reply);
1513 if (r < 0 && sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD)) {
1514 /* Fallback to legacy ListUnitFiles method */
1515 fallback = true;
1516 log_debug_errno(r, "Failed to list unit files: %s Falling back to ListUnitsFiles method.", bus_error_message(&error, r));
1517 m = sd_bus_message_unref(m);
1518 sd_bus_error_free(&error);
1519
1520 r = sd_bus_message_new_method_call(
1521 bus,
1522 &m,
1523 "org.freedesktop.systemd1",
1524 "/org/freedesktop/systemd1",
1525 "org.freedesktop.systemd1.Manager",
1526 "ListUnitFiles");
1527 if (r < 0)
1528 return bus_log_create_error(r);
1529
1530 r = sd_bus_call(bus, m, 0, &error, &reply);
1531 }
1532 if (r < 0)
1533 return log_error_errno(r, "Failed to list unit files: %s", bus_error_message(&error, r));
1534
1535 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
1536 if (r < 0)
1537 return bus_log_parse_error(r);
1538
1539 while ((r = sd_bus_message_read(reply, "(ss)", &path, &state)) > 0) {
1540
1541 if (!GREEDY_REALLOC(units, size, c + 1))
1542 return log_oom();
1543
1544 units[c] = (struct UnitFileList) {
1545 path,
1546 unit_file_state_from_string(state)
1547 };
1548
1549 if (output_show_unit_file(&units[c],
1550 fallback ? arg_states : NULL,
1551 fallback ? strv_skip(argv, 1) : NULL))
1552 c++;
1553
1554 }
1555 if (r < 0)
1556 return bus_log_parse_error(r);
1557
1558 r = sd_bus_message_exit_container(reply);
1559 if (r < 0)
1560 return bus_log_parse_error(r);
1561 }
1562
1563 (void) pager_open(arg_pager_flags);
1564
1565 typesafe_qsort(units, c, compare_unit_file_list);
1566 output_unit_file_list(units, c);
1567
1568 if (install_client_side())
1569 for (unit = units; unit < units + c; unit++)
1570 free(unit->path);
1571
1572 return 0;
1573 }
1574
1575 static int list_dependencies_print(const char *name, int level, unsigned branches, bool last) {
1576 _cleanup_free_ char *n = NULL;
1577 size_t max_len = MAX(columns(),20u);
1578 size_t len = 0;
1579 int i;
1580
1581 if (!arg_plain) {
1582
1583 for (i = level - 1; i >= 0; i--) {
1584 len += 2;
1585 if (len > max_len - 3 && !arg_full) {
1586 printf("%s...\n",max_len % 2 ? "" : " ");
1587 return 0;
1588 }
1589 printf("%s", special_glyph(branches & (1 << i) ? SPECIAL_GLYPH_TREE_VERTICAL : SPECIAL_GLYPH_TREE_SPACE));
1590 }
1591 len += 2;
1592
1593 if (len > max_len - 3 && !arg_full) {
1594 printf("%s...\n",max_len % 2 ? "" : " ");
1595 return 0;
1596 }
1597
1598 printf("%s", special_glyph(last ? SPECIAL_GLYPH_TREE_RIGHT : SPECIAL_GLYPH_TREE_BRANCH));
1599 }
1600
1601 if (arg_full) {
1602 printf("%s\n", name);
1603 return 0;
1604 }
1605
1606 n = ellipsize(name, max_len-len, 100);
1607 if (!n)
1608 return log_oom();
1609
1610 printf("%s\n", n);
1611 return 0;
1612 }
1613
1614 static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) {
1615 struct DependencyStatusInfo {
1616 char **dep[5];
1617 } info = {};
1618
1619 static const struct bus_properties_map map[_DEPENDENCY_MAX][6] = {
1620 [DEPENDENCY_FORWARD] = {
1621 { "Requires", "as", NULL, offsetof(struct DependencyStatusInfo, dep[0]) },
1622 { "Requisite", "as", NULL, offsetof(struct DependencyStatusInfo, dep[1]) },
1623 { "Wants", "as", NULL, offsetof(struct DependencyStatusInfo, dep[2]) },
1624 { "ConsistsOf", "as", NULL, offsetof(struct DependencyStatusInfo, dep[3]) },
1625 { "BindsTo", "as", NULL, offsetof(struct DependencyStatusInfo, dep[4]) },
1626 {}
1627 },
1628 [DEPENDENCY_REVERSE] = {
1629 { "RequiredBy", "as", NULL, offsetof(struct DependencyStatusInfo, dep[0]) },
1630 { "RequisiteOf", "as", NULL, offsetof(struct DependencyStatusInfo, dep[1]) },
1631 { "WantedBy", "as", NULL, offsetof(struct DependencyStatusInfo, dep[2]) },
1632 { "PartOf", "as", NULL, offsetof(struct DependencyStatusInfo, dep[3]) },
1633 { "BoundBy", "as", NULL, offsetof(struct DependencyStatusInfo, dep[4]) },
1634 {}
1635 },
1636 [DEPENDENCY_AFTER] = {
1637 { "After", "as", NULL, offsetof(struct DependencyStatusInfo, dep[0]) },
1638 {}
1639 },
1640 [DEPENDENCY_BEFORE] = {
1641 { "Before", "as", NULL, offsetof(struct DependencyStatusInfo, dep[0]) },
1642 {}
1643 },
1644 };
1645
1646 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1647 _cleanup_strv_free_ char **ret = NULL;
1648 _cleanup_free_ char *path = NULL;
1649 int i, r;
1650
1651 assert(bus);
1652 assert(name);
1653 assert(deps);
1654
1655 path = unit_dbus_path_from_name(name);
1656 if (!path)
1657 return log_oom();
1658
1659 r = bus_map_all_properties(bus,
1660 "org.freedesktop.systemd1",
1661 path,
1662 map[arg_dependency],
1663 BUS_MAP_STRDUP,
1664 &error,
1665 NULL,
1666 &info);
1667 if (r < 0)
1668 return log_error_errno(r, "Failed to get properties of %s: %s", name, bus_error_message(&error, r));
1669
1670 if (IN_SET(arg_dependency, DEPENDENCY_AFTER, DEPENDENCY_BEFORE)) {
1671 *deps = info.dep[0];
1672 return 0;
1673 }
1674
1675 for (i = 0; i < 5; i++) {
1676 r = strv_extend_strv(&ret, info.dep[i], true);
1677 if (r < 0)
1678 return log_oom();
1679 info.dep[i] = strv_free(info.dep[i]);
1680 }
1681
1682 *deps = TAKE_PTR(ret);
1683
1684 return 0;
1685 }
1686
1687 static int list_dependencies_compare(char * const *a, char * const *b) {
1688 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1689 return 1;
1690 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1691 return -1;
1692
1693 return strcasecmp(*a, *b);
1694 }
1695
1696 static int list_dependencies_one(
1697 sd_bus *bus,
1698 const char *name,
1699 int level,
1700 char ***units,
1701 unsigned branches) {
1702
1703 _cleanup_strv_free_ char **deps = NULL;
1704 char **c;
1705 int r = 0;
1706
1707 assert(bus);
1708 assert(name);
1709 assert(units);
1710
1711 r = strv_extend(units, name);
1712 if (r < 0)
1713 return log_oom();
1714
1715 r = list_dependencies_get_dependencies(bus, name, &deps);
1716 if (r < 0)
1717 return r;
1718
1719 typesafe_qsort(deps, strv_length(deps), list_dependencies_compare);
1720
1721 STRV_FOREACH(c, deps) {
1722 if (strv_contains(*units, *c)) {
1723 if (!arg_plain) {
1724 printf(" ");
1725 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1726 if (r < 0)
1727 return r;
1728 }
1729 continue;
1730 }
1731
1732 if (arg_plain)
1733 printf(" ");
1734 else {
1735 UnitActiveState active_state = _UNIT_ACTIVE_STATE_INVALID;
1736 const char *on;
1737
1738 (void) get_state_one_unit(bus, *c, &active_state);
1739
1740 switch (active_state) {
1741 case UNIT_ACTIVE:
1742 case UNIT_RELOADING:
1743 case UNIT_ACTIVATING:
1744 on = ansi_highlight_green();
1745 break;
1746
1747 case UNIT_INACTIVE:
1748 case UNIT_DEACTIVATING:
1749 on = ansi_normal();
1750 break;
1751
1752 default:
1753 on = ansi_highlight_red();
1754 break;
1755 }
1756
1757 printf("%s%s%s ", on, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE), ansi_normal());
1758 }
1759
1760 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1761 if (r < 0)
1762 return r;
1763
1764 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1765 r = list_dependencies_one(bus, *c, level + 1, units, (branches << 1) | (c[1] == NULL ? 0 : 1));
1766 if (r < 0)
1767 return r;
1768 }
1769 }
1770
1771 if (!arg_plain)
1772 strv_remove(*units, name);
1773
1774 return 0;
1775 }
1776
1777 static int list_dependencies(int argc, char *argv[], void *userdata) {
1778 _cleanup_strv_free_ char **units = NULL;
1779 _cleanup_free_ char *unit = NULL;
1780 const char *u;
1781 sd_bus *bus;
1782 int r;
1783
1784 if (argv[1]) {
1785 r = unit_name_mangle(argv[1], arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN, &unit);
1786 if (r < 0)
1787 return log_error_errno(r, "Failed to mangle unit name: %m");
1788
1789 u = unit;
1790 } else
1791 u = SPECIAL_DEFAULT_TARGET;
1792
1793 r = acquire_bus(BUS_MANAGER, &bus);
1794 if (r < 0)
1795 return r;
1796
1797 (void) pager_open(arg_pager_flags);
1798
1799 puts(u);
1800
1801 return list_dependencies_one(bus, u, 0, &units, 0);
1802 }
1803
1804 struct machine_info {
1805 bool is_host;
1806 char *name;
1807 char *state;
1808 char *control_group;
1809 uint32_t n_failed_units;
1810 uint32_t n_jobs;
1811 usec_t timestamp;
1812 };
1813
1814 static const struct bus_properties_map machine_info_property_map[] = {
1815 { "SystemState", "s", NULL, offsetof(struct machine_info, state) },
1816 { "NJobs", "u", NULL, offsetof(struct machine_info, n_jobs) },
1817 { "NFailedUnits", "u", NULL, offsetof(struct machine_info, n_failed_units) },
1818 { "ControlGroup", "s", NULL, offsetof(struct machine_info, control_group) },
1819 { "UserspaceTimestamp", "t", NULL, offsetof(struct machine_info, timestamp) },
1820 {}
1821 };
1822
1823 static void machine_info_clear(struct machine_info *info) {
1824 assert(info);
1825
1826 free(info->name);
1827 free(info->state);
1828 free(info->control_group);
1829 zero(*info);
1830 }
1831
1832 static void free_machines_list(struct machine_info *machine_infos, int n) {
1833 int i;
1834
1835 if (!machine_infos)
1836 return;
1837
1838 for (i = 0; i < n; i++)
1839 machine_info_clear(&machine_infos[i]);
1840
1841 free(machine_infos);
1842 }
1843
1844 static int compare_machine_info(const struct machine_info *a, const struct machine_info *b) {
1845 int r;
1846
1847 r = CMP(b->is_host, a->is_host);
1848 if (r != 0)
1849 return r;
1850
1851 return strcasecmp(a->name, b->name);
1852 }
1853
1854 static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
1855 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *container = NULL;
1856 int r;
1857
1858 assert(mi);
1859
1860 if (!bus) {
1861 r = sd_bus_open_system_machine(&container, mi->name);
1862 if (r < 0)
1863 return r;
1864
1865 bus = container;
1866 }
1867
1868 r = bus_map_all_properties(
1869 bus,
1870 "org.freedesktop.systemd1",
1871 "/org/freedesktop/systemd1",
1872 machine_info_property_map,
1873 BUS_MAP_STRDUP,
1874 NULL,
1875 NULL,
1876 mi);
1877 if (r < 0)
1878 return r;
1879
1880 return 0;
1881 }
1882
1883 static bool output_show_machine(const char *name, char **patterns) {
1884 return strv_fnmatch_or_empty(patterns, name, FNM_NOESCAPE);
1885 }
1886
1887 static int get_machine_list(
1888 sd_bus *bus,
1889 struct machine_info **_machine_infos,
1890 char **patterns) {
1891
1892 struct machine_info *machine_infos = NULL;
1893 _cleanup_strv_free_ char **m = NULL;
1894 _cleanup_free_ char *hn = NULL;
1895 size_t sz = 0;
1896 char **i;
1897 int c = 0, r;
1898
1899 hn = gethostname_malloc();
1900 if (!hn)
1901 return log_oom();
1902
1903 if (output_show_machine(hn, patterns)) {
1904 if (!GREEDY_REALLOC0(machine_infos, sz, c+1))
1905 return log_oom();
1906
1907 machine_infos[c].is_host = true;
1908 machine_infos[c].name = TAKE_PTR(hn);
1909
1910 (void) get_machine_properties(bus, &machine_infos[c]);
1911 c++;
1912 }
1913
1914 r = sd_get_machine_names(&m);
1915 if (r < 0)
1916 return log_error_errno(r, "Failed to get machine list: %m");
1917
1918 STRV_FOREACH(i, m) {
1919 _cleanup_free_ char *class = NULL;
1920
1921 if (!output_show_machine(*i, patterns))
1922 continue;
1923
1924 sd_machine_get_class(*i, &class);
1925 if (!streq_ptr(class, "container"))
1926 continue;
1927
1928 if (!GREEDY_REALLOC0(machine_infos, sz, c+1)) {
1929 free_machines_list(machine_infos, c);
1930 return log_oom();
1931 }
1932
1933 machine_infos[c].is_host = false;
1934 machine_infos[c].name = strdup(*i);
1935 if (!machine_infos[c].name) {
1936 free_machines_list(machine_infos, c);
1937 return log_oom();
1938 }
1939
1940 (void) get_machine_properties(NULL, &machine_infos[c]);
1941 c++;
1942 }
1943
1944 *_machine_infos = machine_infos;
1945 return c;
1946 }
1947
1948 static void output_machines_list(struct machine_info *machine_infos, unsigned n) {
1949 struct machine_info *m;
1950 unsigned
1951 circle_len = 0,
1952 namelen = STRLEN("NAME"),
1953 statelen = STRLEN("STATE"),
1954 failedlen = STRLEN("FAILED"),
1955 jobslen = STRLEN("JOBS");
1956
1957 assert(machine_infos || n == 0);
1958
1959 for (m = machine_infos; m < machine_infos + n; m++) {
1960 namelen = MAX(namelen,
1961 strlen(m->name) + (m->is_host ? STRLEN(" (host)") : 0));
1962 statelen = MAX(statelen, strlen_ptr(m->state));
1963 failedlen = MAX(failedlen, DECIMAL_STR_WIDTH(m->n_failed_units));
1964 jobslen = MAX(jobslen, DECIMAL_STR_WIDTH(m->n_jobs));
1965
1966 if (!arg_plain && !streq_ptr(m->state, "running"))
1967 circle_len = 2;
1968 }
1969
1970 if (!arg_no_legend) {
1971 if (circle_len > 0)
1972 fputs(" ", stdout);
1973
1974 printf("%-*s %-*s %-*s %-*s\n",
1975 namelen, "NAME",
1976 statelen, "STATE",
1977 failedlen, "FAILED",
1978 jobslen, "JOBS");
1979 }
1980
1981 for (m = machine_infos; m < machine_infos + n; m++) {
1982 const char *on_state = "", *off_state = "";
1983 const char *on_failed = "", *off_failed = "";
1984 bool circle = false;
1985
1986 if (streq_ptr(m->state, "degraded")) {
1987 on_state = ansi_highlight_red();
1988 off_state = ansi_normal();
1989 circle = true;
1990 } else if (!streq_ptr(m->state, "running")) {
1991 on_state = ansi_highlight_yellow();
1992 off_state = ansi_normal();
1993 circle = true;
1994 }
1995
1996 if (m->n_failed_units > 0) {
1997 on_failed = ansi_highlight_red();
1998 off_failed = ansi_normal();
1999 } else
2000 on_failed = off_failed = "";
2001
2002 if (circle_len > 0)
2003 printf("%s%s%s ", on_state, circle ? special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE) : " ", off_state);
2004
2005 if (m->is_host)
2006 printf("%-*s (host) %s%-*s%s %s%*" PRIu32 "%s %*" PRIu32 "\n",
2007 (int) (namelen - (STRLEN(" (host)"))),
2008 strna(m->name),
2009 on_state, statelen, strna(m->state), off_state,
2010 on_failed, failedlen, m->n_failed_units, off_failed,
2011 jobslen, m->n_jobs);
2012 else
2013 printf("%-*s %s%-*s%s %s%*" PRIu32 "%s %*" PRIu32 "\n",
2014 namelen, strna(m->name),
2015 on_state, statelen, strna(m->state), off_state,
2016 on_failed, failedlen, m->n_failed_units, off_failed,
2017 jobslen, m->n_jobs);
2018 }
2019
2020 if (!arg_no_legend)
2021 printf("\n%u machines listed.\n", n);
2022 }
2023
2024 static int list_machines(int argc, char *argv[], void *userdata) {
2025 struct machine_info *machine_infos = NULL;
2026 sd_bus *bus;
2027 int r;
2028
2029 r = acquire_bus(BUS_MANAGER, &bus);
2030 if (r < 0)
2031 return r;
2032
2033 r = get_machine_list(bus, &machine_infos, strv_skip(argv, 1));
2034 if (r < 0)
2035 return r;
2036
2037 (void) pager_open(arg_pager_flags);
2038
2039 typesafe_qsort(machine_infos, r, compare_machine_info);
2040 output_machines_list(machine_infos, r);
2041 free_machines_list(machine_infos, r);
2042
2043 return 0;
2044 }
2045
2046 static int get_default(int argc, char *argv[], void *userdata) {
2047 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
2048 _cleanup_free_ char *_path = NULL;
2049 const char *path;
2050 int r;
2051
2052 if (install_client_side()) {
2053 r = unit_file_get_default(arg_scope, arg_root, &_path);
2054 if (r < 0)
2055 return log_error_errno(r, "Failed to get default target: %m");
2056 path = _path;
2057
2058 r = 0;
2059 } else {
2060 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2061 sd_bus *bus;
2062
2063 r = acquire_bus(BUS_MANAGER, &bus);
2064 if (r < 0)
2065 return r;
2066
2067 r = sd_bus_call_method(
2068 bus,
2069 "org.freedesktop.systemd1",
2070 "/org/freedesktop/systemd1",
2071 "org.freedesktop.systemd1.Manager",
2072 "GetDefaultTarget",
2073 &error,
2074 &reply,
2075 NULL);
2076 if (r < 0)
2077 return log_error_errno(r, "Failed to get default target: %s", bus_error_message(&error, r));
2078
2079 r = sd_bus_message_read(reply, "s", &path);
2080 if (r < 0)
2081 return bus_log_parse_error(r);
2082 }
2083
2084 if (path)
2085 printf("%s\n", path);
2086
2087 return 0;
2088 }
2089
2090 static int set_default(int argc, char *argv[], void *userdata) {
2091 _cleanup_free_ char *unit = NULL;
2092 UnitFileChange *changes = NULL;
2093 size_t n_changes = 0;
2094 int r;
2095
2096 assert(argc >= 2);
2097 assert(argv);
2098
2099 r = unit_name_mangle_with_suffix(argv[1], arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN, ".target", &unit);
2100 if (r < 0)
2101 return log_error_errno(r, "Failed to mangle unit name: %m");
2102
2103 if (install_client_side()) {
2104 r = unit_file_set_default(arg_scope, UNIT_FILE_FORCE, arg_root, unit, &changes, &n_changes);
2105 unit_file_dump_changes(r, "set default", changes, n_changes, arg_quiet);
2106
2107 if (r > 0)
2108 r = 0;
2109 } else {
2110 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2111 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
2112 sd_bus *bus;
2113
2114 polkit_agent_open_maybe();
2115
2116 r = acquire_bus(BUS_MANAGER, &bus);
2117 if (r < 0)
2118 return r;
2119
2120 r = sd_bus_call_method(
2121 bus,
2122 "org.freedesktop.systemd1",
2123 "/org/freedesktop/systemd1",
2124 "org.freedesktop.systemd1.Manager",
2125 "SetDefaultTarget",
2126 &error,
2127 &reply,
2128 "sb", unit, 1);
2129 if (r < 0)
2130 return log_error_errno(r, "Failed to set default target: %s", bus_error_message(&error, r));
2131
2132 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, &changes, &n_changes);
2133 if (r < 0)
2134 goto finish;
2135
2136 /* Try to reload if enabled */
2137 if (!arg_no_reload)
2138 r = daemon_reload(argc, argv, userdata);
2139 else
2140 r = 0;
2141 }
2142
2143 finish:
2144 unit_file_changes_free(changes, n_changes);
2145
2146 return r;
2147 }
2148
2149 static int output_waiting_jobs(sd_bus *bus, uint32_t id, const char *method, const char *prefix) {
2150 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2151 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
2152 const char *name, *type;
2153 uint32_t other_id;
2154 int r;
2155
2156 assert(bus);
2157
2158 r = sd_bus_call_method(
2159 bus,
2160 "org.freedesktop.systemd1",
2161 "/org/freedesktop/systemd1",
2162 "org.freedesktop.systemd1.Manager",
2163 method,
2164 &error,
2165 &reply,
2166 "u", id);
2167 if (r < 0)
2168 return log_debug_errno(r, "Failed to get waiting jobs for job %" PRIu32, id);
2169
2170 r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
2171 if (r < 0)
2172 return bus_log_parse_error(r);
2173
2174 while ((r = sd_bus_message_read(reply, "(usssoo)", &other_id, &name, &type, NULL, NULL, NULL)) > 0)
2175 printf("%s %u (%s/%s)\n", prefix, other_id, name, type);
2176 if (r < 0)
2177 return bus_log_parse_error(r);
2178
2179 r = sd_bus_message_exit_container(reply);
2180 if (r < 0)
2181 return bus_log_parse_error(r);
2182
2183 return 0;
2184 }
2185
2186 struct job_info {
2187 uint32_t id;
2188 const char *name, *type, *state;
2189 };
2190
2191 static void output_jobs_list(sd_bus *bus, const struct job_info* jobs, unsigned n, bool skipped) {
2192 unsigned id_len, unit_len, type_len, state_len;
2193 const struct job_info *j;
2194 const char *on, *off;
2195 bool shorten = false;
2196
2197 assert(n == 0 || jobs);
2198
2199 if (n == 0) {
2200 if (!arg_no_legend) {
2201 on = ansi_highlight_green();
2202 off = ansi_normal();
2203
2204 printf("%sNo jobs %s.%s\n", on, skipped ? "listed" : "running", off);
2205 }
2206 return;
2207 }
2208
2209 (void) pager_open(arg_pager_flags);
2210
2211 id_len = STRLEN("JOB");
2212 unit_len = STRLEN("UNIT");
2213 type_len = STRLEN("TYPE");
2214 state_len = STRLEN("STATE");
2215
2216 for (j = jobs; j < jobs + n; j++) {
2217 uint32_t id = j->id;
2218 assert(j->name && j->type && j->state);
2219
2220 id_len = MAX(id_len, DECIMAL_STR_WIDTH(id));
2221 unit_len = MAX(unit_len, strlen(j->name));
2222 type_len = MAX(type_len, strlen(j->type));
2223 state_len = MAX(state_len, strlen(j->state));
2224 }
2225
2226 if (!arg_full && id_len + 1 + unit_len + type_len + 1 + state_len > columns()) {
2227 unit_len = MAX(33u, columns() - id_len - type_len - state_len - 3);
2228 shorten = true;
2229 }
2230
2231 if (!arg_no_legend)
2232 printf("%*s %-*s %-*s %-*s\n",
2233 id_len, "JOB",
2234 unit_len, "UNIT",
2235 type_len, "TYPE",
2236 state_len, "STATE");
2237
2238 for (j = jobs; j < jobs + n; j++) {
2239 _cleanup_free_ char *e = NULL;
2240
2241 if (streq(j->state, "running")) {
2242 on = ansi_highlight();
2243 off = ansi_normal();
2244 } else
2245 on = off = "";
2246
2247 e = shorten ? ellipsize(j->name, unit_len, 33) : NULL;
2248 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2249 id_len, j->id,
2250 on, unit_len, e ? e : j->name, off,
2251 type_len, j->type,
2252 on, state_len, j->state, off);
2253
2254 if (arg_jobs_after)
2255 output_waiting_jobs(bus, j->id, "GetJobAfter", "\twaiting for job");
2256 if (arg_jobs_before)
2257 output_waiting_jobs(bus, j->id, "GetJobBefore", "\tblocking job");
2258 }
2259
2260 if (!arg_no_legend) {
2261 on = ansi_highlight();
2262 off = ansi_normal();
2263
2264 printf("\n%s%u jobs listed%s.\n", on, n, off);
2265 }
2266 }
2267
2268 static bool output_show_job(struct job_info *job, char **patterns) {
2269 return strv_fnmatch_or_empty(patterns, job->name, FNM_NOESCAPE);
2270 }
2271
2272 static int list_jobs(int argc, char *argv[], void *userdata) {
2273 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2274 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
2275 _cleanup_free_ struct job_info *jobs = NULL;
2276 const char *name, *type, *state;
2277 bool skipped = false;
2278 size_t size = 0;
2279 unsigned c = 0;
2280 sd_bus *bus;
2281 uint32_t id;
2282 int r;
2283
2284 r = acquire_bus(BUS_MANAGER, &bus);
2285 if (r < 0)
2286 return r;
2287
2288 r = sd_bus_call_method(
2289 bus,
2290 "org.freedesktop.systemd1",
2291 "/org/freedesktop/systemd1",
2292 "org.freedesktop.systemd1.Manager",
2293 "ListJobs",
2294 &error,
2295 &reply,
2296 NULL);
2297 if (r < 0)
2298 return log_error_errno(r, "Failed to list jobs: %s", bus_error_message(&error, r));
2299
2300 r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
2301 if (r < 0)
2302 return bus_log_parse_error(r);
2303
2304 while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, NULL, NULL)) > 0) {
2305 struct job_info job = { id, name, type, state };
2306
2307 if (!output_show_job(&job, strv_skip(argv, 1))) {
2308 skipped = true;
2309 continue;
2310 }
2311
2312 if (!GREEDY_REALLOC(jobs, size, c + 1))
2313 return log_oom();
2314
2315 jobs[c++] = job;
2316 }
2317 if (r < 0)
2318 return bus_log_parse_error(r);
2319
2320 r = sd_bus_message_exit_container(reply);
2321 if (r < 0)
2322 return bus_log_parse_error(r);
2323
2324 (void) pager_open(arg_pager_flags);
2325
2326 output_jobs_list(bus, jobs, c, skipped);
2327 return 0;
2328 }
2329
2330 static int cancel_job(int argc, char *argv[], void *userdata) {
2331 sd_bus *bus;
2332 char **name;
2333 int r = 0;
2334
2335 if (argc <= 1)
2336 return trivial_method(argc, argv, userdata);
2337
2338 r = acquire_bus(BUS_MANAGER, &bus);
2339 if (r < 0)
2340 return r;
2341
2342 polkit_agent_open_maybe();
2343
2344 STRV_FOREACH(name, strv_skip(argv, 1)) {
2345 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2346 uint32_t id;
2347 int q;
2348
2349 q = safe_atou32(*name, &id);
2350 if (q < 0)
2351 return log_error_errno(q, "Failed to parse job id \"%s\": %m", *name);
2352
2353 q = sd_bus_call_method(
2354 bus,
2355 "org.freedesktop.systemd1",
2356 "/org/freedesktop/systemd1",
2357 "org.freedesktop.systemd1.Manager",
2358 "CancelJob",
2359 &error,
2360 NULL,
2361 "u", id);
2362 if (q < 0) {
2363 log_error_errno(q, "Failed to cancel job %"PRIu32": %s", id, bus_error_message(&error, q));
2364 if (r == 0)
2365 r = q;
2366 }
2367 }
2368
2369 return r;
2370 }
2371
2372 static int need_daemon_reload(sd_bus *bus, const char *unit) {
2373 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
2374 const char *path;
2375 int b, r;
2376
2377 /* We ignore all errors here, since this is used to show a
2378 * warning only */
2379
2380 /* We don't use unit_dbus_path_from_name() directly since we
2381 * don't want to load the unit if it isn't loaded. */
2382
2383 r = sd_bus_call_method(
2384 bus,
2385 "org.freedesktop.systemd1",
2386 "/org/freedesktop/systemd1",
2387 "org.freedesktop.systemd1.Manager",
2388 "GetUnit",
2389 NULL,
2390 &reply,
2391 "s", unit);
2392 if (r < 0)
2393 return r;
2394
2395 r = sd_bus_message_read(reply, "o", &path);
2396 if (r < 0)
2397 return r;
2398
2399 r = sd_bus_get_property_trivial(
2400 bus,
2401 "org.freedesktop.systemd1",
2402 path,
2403 "org.freedesktop.systemd1.Unit",
2404 "NeedDaemonReload",
2405 NULL,
2406 'b', &b);
2407 if (r < 0)
2408 return r;
2409
2410 return b;
2411 }
2412
2413 static void warn_unit_file_changed(const char *name) {
2414 assert(name);
2415
2416 log_warning("%sWarning:%s The unit file, source configuration file or drop-ins of %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
2417 ansi_highlight_red(),
2418 ansi_normal(),
2419 name,
2420 arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
2421 }
2422
2423 static int unit_file_find_path(LookupPaths *lp, const char *unit_name, char **ret_unit_path) {
2424 char **p;
2425
2426 assert(lp);
2427 assert(unit_name);
2428
2429 STRV_FOREACH(p, lp->search_path) {
2430 _cleanup_free_ char *path = NULL, *lpath = NULL;
2431 int r;
2432
2433 path = path_join(*p, unit_name);
2434 if (!path)
2435 return log_oom();
2436
2437 r = chase_symlinks(path, arg_root, 0, &lpath);
2438 if (r == -ENOENT)
2439 continue;
2440 if (r == -ENOMEM)
2441 return log_oom();
2442 if (r < 0)
2443 return log_error_errno(r, "Failed to access path \"%s\": %m", path);
2444
2445 if (ret_unit_path)
2446 *ret_unit_path = TAKE_PTR(lpath);
2447
2448 return 1;
2449 }
2450
2451 if (ret_unit_path)
2452 *ret_unit_path = NULL;
2453
2454 return 0;
2455 }
2456
2457 static int unit_find_template_path(
2458 const char *unit_name,
2459 LookupPaths *lp,
2460 char **ret_fragment_path,
2461 char **ret_template) {
2462
2463 _cleanup_free_ char *t = NULL, *f = NULL;
2464 int r;
2465
2466 /* Returns 1 if a fragment was found, 0 if not found, negative on error. */
2467
2468 r = unit_file_find_path(lp, unit_name, &f);
2469 if (r < 0)
2470 return r;
2471 if (r > 0) {
2472 if (ret_fragment_path)
2473 *ret_fragment_path = TAKE_PTR(f);
2474 if (ret_template)
2475 *ret_template = NULL;
2476 return r; /* found a real unit */
2477 }
2478
2479 r = unit_name_template(unit_name, &t);
2480 if (r == -EINVAL) {
2481 if (ret_fragment_path)
2482 *ret_fragment_path = NULL;
2483 if (ret_template)
2484 *ret_template = NULL;
2485
2486 return 0; /* not a template, does not exist */
2487 }
2488 if (r < 0)
2489 return log_error_errno(r, "Failed to determine template name: %m");
2490
2491 r = unit_file_find_path(lp, t, ret_fragment_path);
2492 if (r < 0)
2493 return r;
2494
2495 if (ret_template)
2496 *ret_template = r > 0 ? TAKE_PTR(t) : NULL;
2497
2498 return r;
2499 }
2500
2501 static int unit_find_paths(
2502 sd_bus *bus,
2503 const char *unit_name,
2504 LookupPaths *lp,
2505 bool force_client_side,
2506 char **ret_fragment_path,
2507 char ***ret_dropin_paths) {
2508
2509 _cleanup_strv_free_ char **dropins = NULL;
2510 _cleanup_free_ char *path = NULL;
2511 int r;
2512
2513 /**
2514 * Finds where the unit is defined on disk. Returns 0 if the unit is not found. Returns 1 if it is found, and
2515 * sets:
2516 * - the path to the unit in *ret_frament_path, if it exists on disk,
2517 * - and a strv of existing drop-ins in *ret_dropin_paths, if the arg is not NULL and any dropins were found.
2518 *
2519 * Returns -ERFKILL if the unit is masked, and -EKEYREJECTED if the unit file could not be loaded for some
2520 * reason (the latter only applies if we are going through the service manager)
2521 */
2522
2523 assert(unit_name);
2524 assert(ret_fragment_path);
2525 assert(lp);
2526
2527 /* Go via the bus to acquire the path, unless we are explicitly told not to, or when the unit name is a template */
2528 if (!force_client_side &&
2529 !install_client_side() &&
2530 !unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE)) {
2531 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2532 _cleanup_free_ char *load_state = NULL, *unit = NULL;
2533
2534 unit = unit_dbus_path_from_name(unit_name);
2535 if (!unit)
2536 return log_oom();
2537
2538 r = sd_bus_get_property_string(
2539 bus,
2540 "org.freedesktop.systemd1",
2541 unit,
2542 "org.freedesktop.systemd1.Unit",
2543 "LoadState",
2544 &error,
2545 &load_state);
2546 if (r < 0)
2547 return log_error_errno(r, "Failed to get LoadState: %s", bus_error_message(&error, r));
2548
2549 if (streq(load_state, "masked"))
2550 return -ERFKILL;
2551 if (streq(load_state, "not-found")) {
2552 r = 0;
2553 goto not_found;
2554 }
2555 if (!streq(load_state, "loaded"))
2556 return -EKEYREJECTED;
2557
2558 r = sd_bus_get_property_string(
2559 bus,
2560 "org.freedesktop.systemd1",
2561 unit,
2562 "org.freedesktop.systemd1.Unit",
2563 "FragmentPath",
2564 &error,
2565 &path);
2566 if (r < 0)
2567 return log_error_errno(r, "Failed to get FragmentPath: %s", bus_error_message(&error, r));
2568
2569 if (ret_dropin_paths) {
2570 r = sd_bus_get_property_strv(
2571 bus,
2572 "org.freedesktop.systemd1",
2573 unit,
2574 "org.freedesktop.systemd1.Unit",
2575 "DropInPaths",
2576 &error,
2577 &dropins);
2578 if (r < 0)
2579 return log_error_errno(r, "Failed to get DropInPaths: %s", bus_error_message(&error, r));
2580 }
2581 } else {
2582 _cleanup_set_free_ Set *names = NULL;
2583 _cleanup_free_ char *template = NULL;
2584
2585 names = set_new(NULL);
2586 if (!names)
2587 return log_oom();
2588
2589 r = unit_find_template_path(unit_name, lp, &path, &template);
2590 if (r < 0)
2591 return r;
2592 if (r > 0) {
2593 if (null_or_empty_path(path))
2594 /* The template is masked. Let's cut the process short. */
2595 return -ERFKILL;
2596
2597 /* We found the unit file. If we followed symlinks, this name might be
2598 * different then the unit_name with started with. Look for dropins matching
2599 * that "final" name. */
2600 r = set_put(names, basename(path));
2601 } else if (!template)
2602 /* No unit file, let's look for dropins matching the original name.
2603 * systemd has fairly complicated rules (based on unit type and provenience),
2604 * which units are allowed not to have the main unit file. We err on the
2605 * side of including too many files, and always try to load dropins. */
2606 r = set_put(names, unit_name);
2607 else
2608 /* The cases where we allow a unit to exist without the main file are
2609 * never valid for templates. Don't try to load dropins in this case. */
2610 goto not_found;
2611
2612 if (r < 0)
2613 return log_error_errno(r, "Failed to add unit name: %m");
2614
2615 if (ret_dropin_paths) {
2616 r = unit_file_find_dropin_conf_paths(arg_root, lp->search_path, NULL, names, &dropins);
2617 if (r < 0)
2618 return r;
2619 }
2620 }
2621
2622 r = 0;
2623
2624 if (!isempty(path)) {
2625 *ret_fragment_path = TAKE_PTR(path);
2626 r = 1;
2627 } else
2628 *ret_fragment_path = NULL;
2629
2630 if (ret_dropin_paths) {
2631 if (!strv_isempty(dropins)) {
2632 *ret_dropin_paths = TAKE_PTR(dropins);
2633 r = 1;
2634 } else
2635 *ret_dropin_paths = NULL;
2636 }
2637
2638 not_found:
2639 if (r == 0 && !arg_force)
2640 log_error("No files found for %s.", unit_name);
2641
2642 return r;
2643 }
2644
2645 static int get_state_one_unit(sd_bus *bus, const char *name, UnitActiveState *active_state) {
2646 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2647 _cleanup_free_ char *buf = NULL, *path = NULL;
2648 UnitActiveState state;
2649 int r;
2650
2651 assert(name);
2652 assert(active_state);
2653
2654 path = unit_dbus_path_from_name(name);
2655 if (!path)
2656 return log_oom();
2657
2658 r = sd_bus_get_property_string(
2659 bus,
2660 "org.freedesktop.systemd1",
2661 path,
2662 "org.freedesktop.systemd1.Unit",
2663 "ActiveState",
2664 &error,
2665 &buf);
2666 if (r < 0)
2667 return log_error_errno(r, "Failed to retrieve unit state: %s", bus_error_message(&error, r));
2668
2669 state = unit_active_state_from_string(buf);
2670 if (state == _UNIT_ACTIVE_STATE_INVALID) {
2671 log_error("Invalid unit state '%s' for: %s", buf, name);
2672 return -EINVAL;
2673 }
2674
2675 *active_state = state;
2676 return 0;
2677 }
2678
2679 static int unit_is_masked(sd_bus *bus, LookupPaths *lp, const char *name) {
2680 _cleanup_free_ char *load_state = NULL;
2681 int r;
2682
2683 if (unit_name_is_valid(name, UNIT_NAME_TEMPLATE)) {
2684 _cleanup_free_ char *path = NULL;
2685
2686 /* A template cannot be loaded, but it can be still masked, so
2687 * we need to use a different method. */
2688
2689 r = unit_file_find_path(lp, name, &path);
2690 if (r < 0)
2691 return r;
2692 if (r == 0)
2693 return false;
2694 return null_or_empty_path(path);
2695 }
2696
2697 r = unit_load_state(bus, name, &load_state);
2698 if (r < 0)
2699 return r;
2700
2701 return streq(load_state, "masked");
2702 }
2703
2704 static int check_triggering_units(sd_bus *bus, const char *name) {
2705 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2706 _cleanup_free_ char *n = NULL, *path = NULL, *load_state = NULL;
2707 _cleanup_strv_free_ char **triggered_by = NULL;
2708 bool print_warning_label = true;
2709 UnitActiveState active_state;
2710 char **i;
2711 int r;
2712
2713 r = unit_name_mangle(name, 0, &n);
2714 if (r < 0)
2715 return log_error_errno(r, "Failed to mangle unit name: %m");
2716
2717 r = unit_load_state(bus, name, &load_state);
2718 if (r < 0)
2719 return r;
2720
2721 if (streq(load_state, "masked"))
2722 return 0;
2723
2724 path = unit_dbus_path_from_name(n);
2725 if (!path)
2726 return log_oom();
2727
2728 r = sd_bus_get_property_strv(
2729 bus,
2730 "org.freedesktop.systemd1",
2731 path,
2732 "org.freedesktop.systemd1.Unit",
2733 "TriggeredBy",
2734 &error,
2735 &triggered_by);
2736 if (r < 0)
2737 return log_error_errno(r, "Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
2738
2739 STRV_FOREACH(i, triggered_by) {
2740 r = get_state_one_unit(bus, *i, &active_state);
2741 if (r < 0)
2742 return r;
2743
2744 if (!IN_SET(active_state, UNIT_ACTIVE, UNIT_RELOADING))
2745 continue;
2746
2747 if (print_warning_label) {
2748 log_warning("Warning: Stopping %s, but it can still be activated by:", n);
2749 print_warning_label = false;
2750 }
2751
2752 log_warning(" %s", *i);
2753 }
2754
2755 return 0;
2756 }
2757
2758 static const struct {
2759 const char *verb;
2760 const char *method;
2761 } unit_actions[] = {
2762 { "start", "StartUnit" },
2763 { "stop", "StopUnit" },
2764 { "condstop", "StopUnit" },
2765 { "reload", "ReloadUnit" },
2766 { "restart", "RestartUnit" },
2767 { "try-restart", "TryRestartUnit" },
2768 { "condrestart", "TryRestartUnit" },
2769 { "reload-or-restart", "ReloadOrRestartUnit" },
2770 { "try-reload-or-restart", "ReloadOrTryRestartUnit" },
2771 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2772 { "condreload", "ReloadOrTryRestartUnit" },
2773 { "force-reload", "ReloadOrTryRestartUnit" }
2774 };
2775
2776 static const char *verb_to_method(const char *verb) {
2777 uint i;
2778
2779 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2780 if (streq_ptr(unit_actions[i].verb, verb))
2781 return unit_actions[i].method;
2782
2783 return "StartUnit";
2784 }
2785
2786 static const char *method_to_verb(const char *method) {
2787 uint i;
2788
2789 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2790 if (streq_ptr(unit_actions[i].method, method))
2791 return unit_actions[i].verb;
2792
2793 return "n/a";
2794 }
2795
2796 typedef struct {
2797 sd_bus_slot *match;
2798 sd_event *event;
2799 Set *unit_paths;
2800 bool any_failed;
2801 } WaitContext;
2802
2803 static void wait_context_free(WaitContext *c) {
2804 c->match = sd_bus_slot_unref(c->match);
2805 c->event = sd_event_unref(c->event);
2806 c->unit_paths = set_free_free(c->unit_paths);
2807 }
2808
2809 static int on_properties_changed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
2810 const char *path, *interface, *active_state = NULL, *job_path = NULL;
2811 WaitContext *c = userdata;
2812 bool is_failed;
2813 int r;
2814
2815 /* Called whenever we get a PropertiesChanged signal. Checks if ActiveState changed to inactive/failed.
2816 *
2817 * Signal parameters: (s interface, a{sv} changed_properties, as invalidated_properties) */
2818
2819 path = sd_bus_message_get_path(m);
2820 if (!set_contains(c->unit_paths, path))
2821 return 0;
2822
2823 r = sd_bus_message_read(m, "s", &interface);
2824 if (r < 0)
2825 return bus_log_parse_error(r);
2826
2827 if (!streq(interface, "org.freedesktop.systemd1.Unit")) /* ActiveState is on the Unit interface */
2828 return 0;
2829
2830 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
2831 if (r < 0)
2832 return bus_log_parse_error(r);
2833
2834 for (;;) {
2835 const char *s;
2836
2837 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv");
2838 if (r < 0)
2839 return bus_log_parse_error(r);
2840 if (r == 0) /* end of array */
2841 break;
2842
2843 r = sd_bus_message_read(m, "s", &s); /* Property name */
2844 if (r < 0)
2845 return bus_log_parse_error(r);
2846
2847 if (streq(s, "ActiveState")) {
2848 r = sd_bus_message_read(m, "v", "s", &active_state);
2849 if (r < 0)
2850 return bus_log_parse_error(r);
2851
2852 if (job_path) /* Found everything we need */
2853 break;
2854
2855 } else if (streq(s, "Job")) {
2856 uint32_t job_id;
2857
2858 r = sd_bus_message_read(m, "v", "(uo)", &job_id, &job_path);
2859 if (r < 0)
2860 return bus_log_parse_error(r);
2861
2862 /* There's still a job pending for this unit, let's ignore this for now, and return right-away. */
2863 if (job_id != 0)
2864 return 0;
2865
2866 if (active_state) /* Found everything we need */
2867 break;
2868
2869 } else {
2870 r = sd_bus_message_skip(m, "v"); /* Other property */
2871 if (r < 0)
2872 return bus_log_parse_error(r);
2873 }
2874
2875 r = sd_bus_message_exit_container(m);
2876 if (r < 0)
2877 return bus_log_parse_error(r);
2878 }
2879
2880 /* If this didn't contain the ActiveState property we can't do anything */
2881 if (!active_state)
2882 return 0;
2883
2884 is_failed = streq(active_state, "failed");
2885 if (streq(active_state, "inactive") || is_failed) {
2886 log_debug("%s became %s, dropping from --wait tracking", path, active_state);
2887 free(set_remove(c->unit_paths, path));
2888 c->any_failed = c->any_failed || is_failed;
2889 } else
2890 log_debug("ActiveState on %s changed to %s", path, active_state);
2891
2892 if (set_isempty(c->unit_paths))
2893 sd_event_exit(c->event, EXIT_SUCCESS);
2894
2895 return 0;
2896 }
2897
2898 static int wait_context_watch(
2899 WaitContext *wait_context,
2900 sd_bus *bus,
2901 const char *name) {
2902
2903 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2904 _cleanup_free_ char *unit_path = NULL;
2905 int r;
2906
2907 assert(wait_context);
2908 assert(name);
2909
2910 log_debug("Watching for property changes of %s", name);
2911 r = sd_bus_call_method(
2912 bus,
2913 "org.freedesktop.systemd1",
2914 "/org/freedesktop/systemd1",
2915 "org.freedesktop.systemd1.Manager",
2916 "RefUnit",
2917 &error,
2918 NULL,
2919 "s", name);
2920 if (r < 0)
2921 return log_error_errno(r, "Failed to add reference to unit %s: %s", name, bus_error_message(&error, r));
2922
2923 unit_path = unit_dbus_path_from_name(name);
2924 if (!unit_path)
2925 return log_oom();
2926
2927 r = set_ensure_allocated(&wait_context->unit_paths, &string_hash_ops);
2928 if (r < 0)
2929 return log_oom();
2930
2931 r = set_put_strdup(wait_context->unit_paths, unit_path);
2932 if (r < 0)
2933 return log_error_errno(r, "Failed to add unit path %s to set: %m", unit_path);
2934
2935 r = sd_bus_match_signal_async(bus,
2936 &wait_context->match,
2937 NULL,
2938 unit_path,
2939 "org.freedesktop.DBus.Properties",
2940 "PropertiesChanged",
2941 on_properties_changed, NULL, wait_context);
2942 if (r < 0)
2943 return log_error_errno(r, "Failed to request match for PropertiesChanged signal: %m");
2944
2945 return 0;
2946 }
2947
2948 static int start_unit_one(
2949 sd_bus *bus,
2950 const char *method,
2951 const char *name,
2952 const char *mode,
2953 sd_bus_error *error,
2954 BusWaitForJobs *w,
2955 WaitContext *wait_context) {
2956
2957 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
2958 const char *path;
2959 int r;
2960
2961 assert(method);
2962 assert(name);
2963 assert(mode);
2964 assert(error);
2965
2966 if (wait_context) {
2967 r = wait_context_watch(wait_context, bus, name);
2968 if (r < 0)
2969 return r;
2970 }
2971
2972 log_debug("%s dbus call org.freedesktop.systemd1.Manager %s(%s, %s)",
2973 arg_dry_run ? "Would execute" : "Executing",
2974 method, name, mode);
2975 if (arg_dry_run)
2976 return 0;
2977
2978 r = sd_bus_call_method(
2979 bus,
2980 "org.freedesktop.systemd1",
2981 "/org/freedesktop/systemd1",
2982 "org.freedesktop.systemd1.Manager",
2983 method,
2984 error,
2985 &reply,
2986 "ss", name, mode);
2987 if (r < 0) {
2988 const char *verb;
2989
2990 /* There's always a fallback possible for legacy actions. */
2991 if (arg_action != ACTION_SYSTEMCTL)
2992 return r;
2993
2994 verb = method_to_verb(method);
2995
2996 log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r));
2997
2998 if (!sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) &&
2999 !sd_bus_error_has_name(error, BUS_ERROR_UNIT_MASKED) &&
3000 !sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE))
3001 log_error("See %s logs and 'systemctl%s status%s %s' for details.",
3002 arg_scope == UNIT_FILE_SYSTEM ? "system" : "user",
3003 arg_scope == UNIT_FILE_SYSTEM ? "" : " --user",
3004 name[0] == '-' ? " --" : "",
3005 name);
3006
3007 return r;
3008 }
3009
3010 r = sd_bus_message_read(reply, "o", &path);
3011 if (r < 0)
3012 return bus_log_parse_error(r);
3013
3014 if (need_daemon_reload(bus, name) > 0)
3015 warn_unit_file_changed(name);
3016
3017 if (w) {
3018 log_debug("Adding %s to the set", path);
3019 r = bus_wait_for_jobs_add(w, path);
3020 if (r < 0)
3021 return log_oom();
3022 }
3023
3024 return 0;
3025 }
3026
3027 static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret) {
3028 _cleanup_strv_free_ char **mangled = NULL, **globs = NULL;
3029 char **name;
3030 int r, i;
3031
3032 assert(bus);
3033 assert(ret);
3034
3035 STRV_FOREACH(name, names) {
3036 char *t;
3037 UnitNameMangle options = UNIT_NAME_MANGLE_GLOB | (arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN);
3038
3039 if (suffix)
3040 r = unit_name_mangle_with_suffix(*name, options, suffix, &t);
3041 else
3042 r = unit_name_mangle(*name, options, &t);
3043 if (r < 0)
3044 return log_error_errno(r, "Failed to mangle name: %m");
3045
3046 if (string_is_glob(t))
3047 r = strv_consume(&globs, t);
3048 else
3049 r = strv_consume(&mangled, t);
3050 if (r < 0)
3051 return log_oom();
3052 }
3053
3054 /* Query the manager only if any of the names are a glob, since
3055 * this is fairly expensive */
3056 if (!strv_isempty(globs)) {
3057 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3058 _cleanup_free_ UnitInfo *unit_infos = NULL;
3059 size_t allocated, n;
3060
3061 r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
3062 if (r < 0)
3063 return r;
3064
3065 n = strv_length(mangled);
3066 allocated = n + 1;
3067
3068 for (i = 0; i < r; i++) {
3069 if (!GREEDY_REALLOC(mangled, allocated, n+2))
3070 return log_oom();
3071
3072 mangled[n] = strdup(unit_infos[i].id);
3073 if (!mangled[n])
3074 return log_oom();
3075
3076 mangled[++n] = NULL;
3077 }
3078 }
3079
3080 *ret = TAKE_PTR(mangled);
3081
3082 return 0;
3083 }
3084
3085 static const struct {
3086 const char *target;
3087 const char *verb;
3088 const char *mode;
3089 } action_table[_ACTION_MAX] = {
3090 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
3091 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
3092 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
3093 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
3094 [ACTION_RUNLEVEL2] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" },
3095 [ACTION_RUNLEVEL3] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" },
3096 [ACTION_RUNLEVEL4] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" },
3097 [ACTION_RUNLEVEL5] = { SPECIAL_GRAPHICAL_TARGET, NULL, "isolate" },
3098 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
3099 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
3100 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
3101 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
3102 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
3103 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
3104 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
3105 [ACTION_SUSPEND_THEN_HIBERNATE] = { SPECIAL_SUSPEND_THEN_HIBERNATE_TARGET, "suspend-then-hibernate", "replace-irreversibly" },
3106 };
3107
3108 static enum action verb_to_action(const char *verb) {
3109 enum action i;
3110
3111 for (i = 0; i < _ACTION_MAX; i++)
3112 if (streq_ptr(action_table[i].verb, verb))
3113 return i;
3114
3115 return _ACTION_INVALID;
3116 }
3117
3118 static int start_unit(int argc, char *argv[], void *userdata) {
3119 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
3120 _cleanup_(wait_context_free) WaitContext wait_context = {};
3121 const char *method, *mode, *one_name, *suffix = NULL;
3122 _cleanup_free_ char **stopped_units = NULL; /* Do not use _cleanup_strv_free_ */
3123 _cleanup_strv_free_ char **names = NULL;
3124 int r, ret = EXIT_SUCCESS;
3125 sd_bus *bus;
3126 char **name;
3127
3128 if (arg_wait && !STR_IN_SET(argv[0], "start", "restart")) {
3129 log_error("--wait may only be used with the 'start' or 'restart' commands.");
3130 return -EINVAL;
3131 }
3132
3133 /* we cannot do sender tracking on the private bus, so we need the full
3134 * one for RefUnit to implement --wait */
3135 r = acquire_bus(arg_wait ? BUS_FULL : BUS_MANAGER, &bus);
3136 if (r < 0)
3137 return r;
3138
3139 ask_password_agent_open_if_enabled();
3140 polkit_agent_open_maybe();
3141
3142 if (arg_action == ACTION_SYSTEMCTL) {
3143 enum action action;
3144
3145 action = verb_to_action(argv[0]);
3146
3147 if (action != _ACTION_INVALID) {
3148 method = "StartUnit";
3149 mode = action_table[action].mode;
3150 one_name = action_table[action].target;
3151 } else {
3152 if (streq(argv[0], "isolate")) {
3153 method = "StartUnit";
3154 mode = "isolate";
3155
3156 suffix = ".target";
3157 } else {
3158 method = verb_to_method(argv[0]);
3159 mode = arg_job_mode;
3160 }
3161 one_name = NULL;
3162 }
3163 } else {
3164 assert(arg_action >= 0 && arg_action < _ACTION_MAX);
3165 assert(action_table[arg_action].target);
3166 assert(action_table[arg_action].mode);
3167
3168 method = "StartUnit";
3169 mode = action_table[arg_action].mode;
3170 one_name = action_table[arg_action].target;
3171 }
3172
3173 if (one_name) {
3174 names = strv_new(one_name);
3175 if (!names)
3176 return log_oom();
3177 } else {
3178 r = expand_names(bus, strv_skip(argv, 1), suffix, &names);
3179 if (r < 0)
3180 return log_error_errno(r, "Failed to expand names: %m");
3181 }
3182
3183 if (!arg_no_block) {
3184 r = bus_wait_for_jobs_new(bus, &w);
3185 if (r < 0)
3186 return log_error_errno(r, "Could not watch jobs: %m");
3187 }
3188
3189 if (arg_wait) {
3190 r = sd_bus_call_method_async(
3191 bus,
3192 NULL,
3193 "org.freedesktop.systemd1",
3194 "/org/freedesktop/systemd1",
3195 "org.freedesktop.systemd1.Manager",
3196 "Subscribe",
3197 NULL, NULL,
3198 NULL);
3199 if (r < 0)
3200 return log_error_errno(r, "Failed to enable subscription: %m");
3201 r = sd_event_default(&wait_context.event);
3202 if (r < 0)
3203 return log_error_errno(r, "Failed to allocate event loop: %m");
3204 r = sd_bus_attach_event(bus, wait_context.event, 0);
3205 if (r < 0)
3206 return log_error_errno(r, "Failed to attach bus to event loop: %m");
3207 }
3208
3209 STRV_FOREACH(name, names) {
3210 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3211
3212 r = start_unit_one(bus, method, *name, mode, &error, w, arg_wait ? &wait_context : NULL);
3213 if (ret == EXIT_SUCCESS && r < 0)
3214 ret = translate_bus_error_to_exit_status(r, &error);
3215
3216 if (r >= 0 && streq(method, "StopUnit")) {
3217 r = strv_push(&stopped_units, *name);
3218 if (r < 0)
3219 return log_oom();
3220 }
3221 }
3222
3223 if (!arg_no_block) {
3224 const char* extra_args[4] = {};
3225 int arg_count = 0;
3226
3227 if (arg_scope != UNIT_FILE_SYSTEM)
3228 extra_args[arg_count++] = "--user";
3229
3230 assert(IN_SET(arg_transport, BUS_TRANSPORT_LOCAL, BUS_TRANSPORT_REMOTE, BUS_TRANSPORT_MACHINE));
3231 if (arg_transport == BUS_TRANSPORT_REMOTE) {
3232 extra_args[arg_count++] = "-H";
3233 extra_args[arg_count++] = arg_host;
3234 } else if (arg_transport == BUS_TRANSPORT_MACHINE) {
3235 extra_args[arg_count++] = "-M";
3236 extra_args[arg_count++] = arg_host;
3237 }
3238
3239 r = bus_wait_for_jobs(w, arg_quiet, extra_args);
3240 if (r < 0)
3241 return r;
3242
3243 /* When stopping units, warn if they can still be triggered by
3244 * another active unit (socket, path, timer) */
3245 if (!arg_quiet)
3246 STRV_FOREACH(name, stopped_units)
3247 (void) check_triggering_units(bus, *name);
3248 }
3249
3250 if (ret == EXIT_SUCCESS && arg_wait && !set_isempty(wait_context.unit_paths)) {
3251 r = sd_event_loop(wait_context.event);
3252 if (r < 0)
3253 return log_error_errno(r, "Failed to run event loop: %m");
3254 if (wait_context.any_failed)
3255 ret = EXIT_FAILURE;
3256 }
3257
3258 return ret;
3259 }
3260
3261 #if ENABLE_LOGIND
3262 static int logind_set_wall_message(void) {
3263 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3264 sd_bus *bus;
3265 _cleanup_free_ char *m = NULL;
3266 int r;
3267
3268 r = acquire_bus(BUS_FULL, &bus);
3269 if (r < 0)
3270 return r;
3271
3272 m = strv_join(arg_wall, " ");
3273 if (!m)
3274 return log_oom();
3275
3276 log_debug("%s wall message \"%s\".", arg_dry_run ? "Would set" : "Setting", m);
3277 if (arg_dry_run)
3278 return 0;
3279
3280 r = sd_bus_call_method(
3281 bus,
3282 "org.freedesktop.login1",
3283 "/org/freedesktop/login1",
3284 "org.freedesktop.login1.Manager",
3285 "SetWallMessage",
3286 &error,
3287 NULL,
3288 "sb",
3289 m,
3290 !arg_no_wall);
3291
3292 if (r < 0)
3293 return log_warning_errno(r, "Failed to set wall message, ignoring: %s", bus_error_message(&error, r));
3294 return 0;
3295 }
3296 #endif
3297
3298 /* Ask systemd-logind, which might grant access to unprivileged users
3299 * through polkit */
3300 static int logind_reboot(enum action a) {
3301 #if ENABLE_LOGIND
3302 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3303 const char *method, *description;
3304 sd_bus *bus;
3305 int r;
3306
3307 r = acquire_bus(BUS_FULL, &bus);
3308 if (r < 0)
3309 return r;
3310
3311 switch (a) {
3312
3313 case ACTION_POWEROFF:
3314 method = "PowerOff";
3315 description = "power off system";
3316 break;
3317
3318 case ACTION_REBOOT:
3319 method = "Reboot";
3320 description = "reboot system";
3321 break;
3322
3323 case ACTION_HALT:
3324 method = "Halt";
3325 description = "halt system";
3326 break;
3327
3328 case ACTION_SUSPEND:
3329 method = "Suspend";
3330 description = "suspend system";
3331 break;
3332
3333 case ACTION_HIBERNATE:
3334 method = "Hibernate";
3335 description = "hibernate system";
3336 break;
3337
3338 case ACTION_HYBRID_SLEEP:
3339 method = "HybridSleep";
3340 description = "put system into hybrid sleep";
3341 break;
3342
3343 case ACTION_SUSPEND_THEN_HIBERNATE:
3344 method = "SuspendThenHibernate";
3345 description = "put system into suspend followed by hibernate";
3346 break;
3347
3348 default:
3349 return -EINVAL;
3350 }
3351
3352 polkit_agent_open_maybe();
3353 (void) logind_set_wall_message();
3354
3355 log_debug("%s org.freedesktop.login1.Manager %s dbus call.", arg_dry_run ? "Would execute" : "Executing", method);
3356 if (arg_dry_run)
3357 return 0;
3358
3359 r = sd_bus_call_method(
3360 bus,
3361 "org.freedesktop.login1",
3362 "/org/freedesktop/login1",
3363 "org.freedesktop.login1.Manager",
3364 method,
3365 &error,
3366 NULL,
3367 "b", arg_ask_password);
3368 if (r < 0)
3369 return log_error_errno(r, "Failed to %s via logind: %s", description, bus_error_message(&error, r));
3370
3371 return 0;
3372 #else
3373 return -ENOSYS;
3374 #endif
3375 }
3376
3377 static int logind_check_inhibitors(enum action a) {
3378 #if ENABLE_LOGIND
3379 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3380 _cleanup_strv_free_ char **sessions = NULL;
3381 const char *what, *who, *why, *mode;
3382 uint32_t uid, pid;
3383 sd_bus *bus;
3384 unsigned c = 0;
3385 char **s;
3386 int r;
3387
3388 if (arg_ignore_inhibitors || arg_force > 0)
3389 return 0;
3390
3391 if (arg_when > 0)
3392 return 0;
3393
3394 if (geteuid() == 0)
3395 return 0;
3396
3397 if (!on_tty())
3398 return 0;
3399
3400 if (arg_transport != BUS_TRANSPORT_LOCAL)
3401 return 0;
3402
3403 r = acquire_bus(BUS_FULL, &bus);
3404 if (r < 0)
3405 return r;
3406
3407 r = sd_bus_call_method(
3408 bus,
3409 "org.freedesktop.login1",
3410 "/org/freedesktop/login1",
3411 "org.freedesktop.login1.Manager",
3412 "ListInhibitors",
3413 NULL,
3414 &reply,
3415 NULL);
3416 if (r < 0)
3417 /* If logind is not around, then there are no inhibitors... */
3418 return 0;
3419
3420 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
3421 if (r < 0)
3422 return bus_log_parse_error(r);
3423
3424 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
3425 _cleanup_free_ char *comm = NULL, *user = NULL;
3426 _cleanup_strv_free_ char **sv = NULL;
3427
3428 if (!streq(mode, "block"))
3429 continue;
3430
3431 sv = strv_split(what, ":");
3432 if (!sv)
3433 return log_oom();
3434
3435 if (!pid_is_valid((pid_t) pid)) {
3436 log_error("Invalid PID "PID_FMT".", (pid_t) pid);
3437 return -ERANGE;
3438 }
3439
3440 if (!strv_contains(sv,
3441 IN_SET(a,
3442 ACTION_HALT,
3443 ACTION_POWEROFF,
3444 ACTION_REBOOT,
3445 ACTION_KEXEC) ? "shutdown" : "sleep"))
3446 continue;
3447
3448 get_process_comm(pid, &comm);
3449 user = uid_to_name(uid);
3450
3451 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
3452 who, (pid_t) pid, strna(comm), strna(user), why);
3453
3454 c++;
3455 }
3456 if (r < 0)
3457 return bus_log_parse_error(r);
3458
3459 r = sd_bus_message_exit_container(reply);
3460 if (r < 0)
3461 return bus_log_parse_error(r);
3462
3463 /* Check for current sessions */
3464 sd_get_sessions(&sessions);
3465 STRV_FOREACH(s, sessions) {
3466 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
3467
3468 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
3469 continue;
3470
3471 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
3472 continue;
3473
3474 if (sd_session_get_type(*s, &type) < 0 || !STR_IN_SET(type, "x11", "wayland", "tty", "mir"))
3475 continue;
3476
3477 sd_session_get_tty(*s, &tty);
3478 sd_session_get_seat(*s, &seat);
3479 sd_session_get_service(*s, &service);
3480 user = uid_to_name(uid);
3481
3482 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
3483 c++;
3484 }
3485
3486 if (c <= 0)
3487 return 0;
3488
3489 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
3490 action_table[a].verb);
3491
3492 return -EPERM;
3493 #else
3494 return 0;
3495 #endif
3496 }
3497
3498 static int prepare_firmware_setup(void) {
3499
3500 if (!arg_firmware_setup)
3501 return 0;
3502
3503 #if ENABLE_LOGIND
3504 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3505 sd_bus *bus;
3506 int r;
3507
3508 r = acquire_bus(BUS_FULL, &bus);
3509 if (r < 0)
3510 return r;
3511
3512 r = sd_bus_call_method(
3513 bus,
3514 "org.freedesktop.login1",
3515 "/org/freedesktop/login1",
3516 "org.freedesktop.login1.Manager",
3517 "SetRebootToFirmwareSetup",
3518 &error,
3519 NULL,
3520 "b", true);
3521 if (r < 0)
3522 return log_error_errno(r, "Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error, r));
3523
3524 return 0;
3525 #else
3526 log_error("Booting into firmware setup not supported.");
3527 return -ENOSYS;
3528 #endif
3529 }
3530
3531 static int prepare_boot_loader_menu(void) {
3532
3533 if (arg_boot_loader_menu == USEC_INFINITY)
3534 return 0;
3535
3536 #if ENABLE_LOGIND
3537 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3538 sd_bus *bus;
3539 int r;
3540
3541 r = acquire_bus(BUS_FULL, &bus);
3542 if (r < 0)
3543 return r;
3544
3545 r = sd_bus_call_method(
3546 bus,
3547 "org.freedesktop.login1",
3548 "/org/freedesktop/login1",
3549 "org.freedesktop.login1.Manager",
3550 "SetRebootToBootLoaderMenu",
3551 &error,
3552 NULL,
3553 "t", arg_boot_loader_menu);
3554 if (r < 0)
3555 return log_error_errno(r, "Cannot indicate to boot loader to enter boot loader entry menu: %s", bus_error_message(&error, r));
3556
3557 return 0;
3558 #else
3559 log_error("Booting into boot loader menu not supported.");
3560 return -ENOSYS;
3561 #endif
3562 }
3563
3564 static int prepare_boot_loader_entry(void) {
3565
3566 if (!arg_boot_loader_entry)
3567 return 0;
3568
3569 #if ENABLE_LOGIND
3570 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3571 sd_bus *bus;
3572 int r;
3573
3574 r = acquire_bus(BUS_FULL, &bus);
3575 if (r < 0)
3576 return r;
3577
3578 r = sd_bus_call_method(
3579 bus,
3580 "org.freedesktop.login1",
3581 "/org/freedesktop/login1",
3582 "org.freedesktop.login1.Manager",
3583 "SetRebootToBootLoaderEntry",
3584 &error,
3585 NULL,
3586 "s", arg_boot_loader_entry);
3587 if (r < 0)
3588 return log_error_errno(r, "Cannot set boot into loader entry '%s': %s", arg_boot_loader_entry, bus_error_message(&error, r));
3589
3590 return 0;
3591 #else
3592 log_error("Booting into boot loader entry not supported.");
3593 return -ENOSYS;
3594 #endif
3595 }
3596
3597 static int load_kexec_kernel(void) {
3598 _cleanup_(boot_config_free) BootConfig config = {};
3599 _cleanup_free_ char *kernel = NULL, *initrd = NULL, *options = NULL;
3600 const BootEntry *e;
3601 pid_t pid;
3602 int r;
3603
3604 if (kexec_loaded()) {
3605 log_debug("Kexec kernel already loaded.");
3606 return 0;
3607 }
3608
3609 if (access(KEXEC, X_OK) < 0)
3610 return log_error_errno(errno, KEXEC" is not available: %m");
3611
3612 r = boot_entries_load_config_auto(NULL, NULL, &config);
3613 if (r == -ENOKEY) /* The call doesn't log about ENOKEY, let's do so here. */
3614 return log_error_errno(r, "Cannot find the ESP partition mount point.");
3615 if (r < 0)
3616 return r;
3617
3618 e = boot_config_default_entry(&config);
3619 if (!e)
3620 return log_error_errno(SYNTHETIC_ERRNO(ENOENT),
3621 "No boot loader entry suitable as default, refusing to guess.");
3622
3623 log_debug("Found default boot loader entry in file \"%s\"", e->path);
3624
3625 if (!e->kernel)
3626 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
3627 "Boot entry does not refer to Linux kernel, which is not supported currently.");
3628 if (strv_length(e->initrd) > 1)
3629 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
3630 "Boot entry specifies multiple initrds, which is not supported currently.");
3631
3632 kernel = path_join(e->root, e->kernel);
3633 if (!kernel)
3634 return log_oom();
3635
3636 if (!strv_isempty(e->initrd)) {
3637 initrd = path_join(e->root, e->initrd[0]);
3638 if (!initrd)
3639 return log_oom();
3640 }
3641
3642 options = strv_join(e->options, " ");
3643 if (!options)
3644 return log_oom();
3645
3646 log_full(arg_quiet ? LOG_DEBUG : LOG_INFO,
3647 "%s "KEXEC" --load \"%s\" --append \"%s\"%s%s%s",
3648 arg_dry_run ? "Would run" : "Running",
3649 kernel,
3650 options,
3651 initrd ? " --initrd \"" : NULL, strempty(initrd), initrd ? "\"" : "");
3652 if (arg_dry_run)
3653 return 0;
3654
3655 r = safe_fork("(kexec)", FORK_WAIT|FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
3656 if (r < 0)
3657 return r;
3658 if (r == 0) {
3659 const char* const args[] = {
3660 KEXEC,
3661 "--load", kernel,
3662 "--append", options,
3663 initrd ? "--initrd" : NULL, initrd,
3664 NULL
3665 };
3666
3667 /* Child */
3668 execv(args[0], (char * const *) args);
3669 _exit(EXIT_FAILURE);
3670 }
3671
3672 return 0;
3673 }
3674
3675 static int set_exit_code(uint8_t code) {
3676 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3677 sd_bus *bus;
3678 int r;
3679
3680 r = acquire_bus(BUS_MANAGER, &bus);
3681 if (r < 0)
3682 return r;
3683
3684 r = sd_bus_call_method(
3685 bus,
3686 "org.freedesktop.systemd1",
3687 "/org/freedesktop/systemd1",
3688 "org.freedesktop.systemd1.Manager",
3689 "SetExitCode",
3690 &error,
3691 NULL,
3692 "y", code);
3693 if (r < 0)
3694 return log_error_errno(r, "Failed to set exit code: %s", bus_error_message(&error, r));
3695
3696 return 0;
3697 }
3698
3699 static int start_special(int argc, char *argv[], void *userdata) {
3700 enum action a;
3701 int r;
3702 bool termination_action; /* an action that terminates the manager,
3703 * can be performed also by signal. */
3704
3705 assert(argv);
3706
3707 a = verb_to_action(argv[0]);
3708
3709 r = logind_check_inhibitors(a);
3710 if (r < 0)
3711 return r;
3712
3713 if (arg_force >= 2) {
3714 r = must_be_root();
3715 if (r < 0)
3716 return r;
3717 }
3718
3719 r = prepare_firmware_setup();
3720 if (r < 0)
3721 return r;
3722
3723 r = prepare_boot_loader_menu();
3724 if (r < 0)
3725 return r;
3726
3727 r = prepare_boot_loader_entry();
3728 if (r < 0)
3729 return r;
3730
3731 if (a == ACTION_REBOOT && argc > 1) {
3732 r = update_reboot_parameter_and_warn(argv[1]);
3733 if (r < 0)
3734 return r;
3735
3736 } else if (a == ACTION_KEXEC) {
3737 r = load_kexec_kernel();
3738 if (r < 0 && arg_force >= 1)
3739 log_notice("Failed to load kexec kernel, continuing without.");
3740 else if (r < 0)
3741 return r;
3742
3743 } else if (a == ACTION_EXIT && argc > 1) {
3744 uint8_t code;
3745
3746 /* If the exit code is not given on the command line,
3747 * don't reset it to zero: just keep it as it might
3748 * have been set previously. */
3749
3750 r = safe_atou8(argv[1], &code);
3751 if (r < 0)
3752 return log_error_errno(r, "Invalid exit code.");
3753
3754 r = set_exit_code(code);
3755 if (r < 0)
3756 return r;
3757 }
3758
3759 termination_action = IN_SET(a,
3760 ACTION_HALT,
3761 ACTION_POWEROFF,
3762 ACTION_REBOOT);
3763 if (termination_action && arg_force >= 2)
3764 return halt_now(a);
3765
3766 if (arg_force >= 1 &&
3767 (termination_action || IN_SET(a, ACTION_KEXEC, ACTION_EXIT)))
3768 r = trivial_method(argc, argv, userdata);
3769 else {
3770 /* First try logind, to allow authentication with polkit */
3771 if (IN_SET(a,
3772 ACTION_POWEROFF,
3773 ACTION_REBOOT,
3774 ACTION_HALT,
3775 ACTION_SUSPEND,
3776 ACTION_HIBERNATE,
3777 ACTION_HYBRID_SLEEP,
3778 ACTION_SUSPEND_THEN_HIBERNATE)) {
3779
3780 r = logind_reboot(a);
3781 if (r >= 0)
3782 return r;
3783 if (IN_SET(r, -EOPNOTSUPP, -EINPROGRESS))
3784 /* requested operation is not supported or already in progress */
3785 return r;
3786
3787 /* On all other errors, try low-level operation. In order to minimize the difference between
3788 * operation with and without logind, we explicitly enable non-blocking mode for this, as
3789 * logind's shutdown operations are always non-blocking. */
3790
3791 arg_no_block = true;
3792
3793 } else if (IN_SET(a, ACTION_EXIT, ACTION_KEXEC))
3794 /* Since exit/kexec are so close in behaviour to power-off/reboot, let's also make them
3795 * asynchronous, in order to not confuse the user needlessly with unexpected behaviour. */
3796 arg_no_block = true;
3797
3798 r = start_unit(argc, argv, userdata);
3799 }
3800
3801 if (termination_action && arg_force < 2 &&
3802 IN_SET(r, -ENOENT, -ETIMEDOUT))
3803 log_notice("It is possible to perform action directly, see discussion of --force --force in man:systemctl(1).");
3804
3805 return r;
3806 }
3807
3808 static int start_system_special(int argc, char *argv[], void *userdata) {
3809 /* Like start_special above, but raises an error when running in user mode */
3810
3811 if (arg_scope != UNIT_FILE_SYSTEM)
3812 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
3813 "Bad action for %s mode.",
3814 arg_scope == UNIT_FILE_GLOBAL ? "--global" : "--user");
3815
3816 return start_special(argc, argv, userdata);
3817 }
3818
3819 static int check_unit_generic(int code, const UnitActiveState good_states[], int nb_states, char **args) {
3820 _cleanup_strv_free_ char **names = NULL;
3821 UnitActiveState active_state;
3822 sd_bus *bus;
3823 char **name;
3824 int r, i;
3825 bool found = false;
3826
3827 r = acquire_bus(BUS_MANAGER, &bus);
3828 if (r < 0)
3829 return r;
3830
3831 r = expand_names(bus, args, NULL, &names);
3832 if (r < 0)
3833 return log_error_errno(r, "Failed to expand names: %m");
3834
3835 STRV_FOREACH(name, names) {
3836 r = get_state_one_unit(bus, *name, &active_state);
3837 if (r < 0)
3838 return r;
3839
3840 if (!arg_quiet)
3841 puts(unit_active_state_to_string(active_state));
3842
3843 for (i = 0; i < nb_states; ++i)
3844 if (good_states[i] == active_state)
3845 found = true;
3846 }
3847
3848 /* use the given return code for the case that we won't find
3849 * any unit which matches the list */
3850 return found ? 0 : code;
3851 }
3852
3853 static int check_unit_active(int argc, char *argv[], void *userdata) {
3854 static const UnitActiveState states[] = {
3855 UNIT_ACTIVE,
3856 UNIT_RELOADING,
3857 };
3858
3859 /* According to LSB: 3, "program is not running" */
3860 return check_unit_generic(EXIT_PROGRAM_NOT_RUNNING, states, ELEMENTSOF(states), strv_skip(argv, 1));
3861 }
3862
3863 static int check_unit_failed(int argc, char *argv[], void *userdata) {
3864 static const UnitActiveState states[] = {
3865 UNIT_FAILED,
3866 };
3867
3868 return check_unit_generic(EXIT_PROGRAM_DEAD_AND_PID_EXISTS, states, ELEMENTSOF(states), strv_skip(argv, 1));
3869 }
3870
3871 static int kill_unit(int argc, char *argv[], void *userdata) {
3872 _cleanup_strv_free_ char **names = NULL;
3873 char *kill_who = NULL, **name;
3874 sd_bus *bus;
3875 int r, q;
3876
3877 r = acquire_bus(BUS_MANAGER, &bus);
3878 if (r < 0)
3879 return r;
3880
3881 polkit_agent_open_maybe();
3882
3883 if (!arg_kill_who)
3884 arg_kill_who = "all";
3885
3886 /* --fail was specified */
3887 if (streq(arg_job_mode, "fail"))
3888 kill_who = strjoina(arg_kill_who, "-fail");
3889
3890 r = expand_names(bus, strv_skip(argv, 1), NULL, &names);
3891 if (r < 0)
3892 return log_error_errno(r, "Failed to expand names: %m");
3893
3894 STRV_FOREACH(name, names) {
3895 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3896
3897 q = sd_bus_call_method(
3898 bus,
3899 "org.freedesktop.systemd1",
3900 "/org/freedesktop/systemd1",
3901 "org.freedesktop.systemd1.Manager",
3902 "KillUnit",
3903 &error,
3904 NULL,
3905 "ssi", *name, kill_who ? kill_who : arg_kill_who, arg_signal);
3906 if (q < 0) {
3907 log_error_errno(q, "Failed to kill unit %s: %s", *name, bus_error_message(&error, q));
3908 if (r == 0)
3909 r = q;
3910 }
3911 }
3912
3913 return r;
3914 }
3915
3916 typedef struct ExecStatusInfo {
3917 char *name;
3918
3919 char *path;
3920 char **argv;
3921
3922 bool ignore;
3923
3924 usec_t start_timestamp;
3925 usec_t exit_timestamp;
3926 pid_t pid;
3927 int code;
3928 int status;
3929
3930 LIST_FIELDS(struct ExecStatusInfo, exec);
3931 } ExecStatusInfo;
3932
3933 static void exec_status_info_free(ExecStatusInfo *i) {
3934 assert(i);
3935
3936 free(i->name);
3937 free(i->path);
3938 strv_free(i->argv);
3939 free(i);
3940 }
3941
3942 static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
3943 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
3944 const char *path;
3945 uint32_t pid;
3946 int32_t code, status;
3947 int ignore, r;
3948
3949 assert(m);
3950 assert(i);
3951
3952 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii");
3953 if (r < 0)
3954 return bus_log_parse_error(r);
3955 else if (r == 0)
3956 return 0;
3957
3958 r = sd_bus_message_read(m, "s", &path);
3959 if (r < 0)
3960 return bus_log_parse_error(r);
3961
3962 i->path = strdup(path);
3963 if (!i->path)
3964 return log_oom();
3965
3966 r = sd_bus_message_read_strv(m, &i->argv);
3967 if (r < 0)
3968 return bus_log_parse_error(r);
3969
3970 r = sd_bus_message_read(m,
3971 "bttttuii",
3972 &ignore,
3973 &start_timestamp, &start_timestamp_monotonic,
3974 &exit_timestamp, &exit_timestamp_monotonic,
3975 &pid,
3976 &code, &status);
3977 if (r < 0)
3978 return bus_log_parse_error(r);
3979
3980 i->ignore = ignore;
3981 i->start_timestamp = (usec_t) start_timestamp;
3982 i->exit_timestamp = (usec_t) exit_timestamp;
3983 i->pid = (pid_t) pid;
3984 i->code = code;
3985 i->status = status;
3986
3987 r = sd_bus_message_exit_container(m);
3988 if (r < 0)
3989 return bus_log_parse_error(r);
3990
3991 return 1;
3992 }
3993
3994 typedef struct UnitCondition {
3995 char *name;
3996 char *param;
3997 bool trigger;
3998 bool negate;
3999 int tristate;
4000
4001 LIST_FIELDS(struct UnitCondition, conditions);
4002 } UnitCondition;
4003
4004 static void unit_condition_free(UnitCondition *c) {
4005 if (!c)
4006 return;
4007
4008 free(c->name);
4009 free(c->param);
4010 free(c);
4011 }
4012
4013 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitCondition*, unit_condition_free);
4014
4015 typedef struct UnitStatusInfo {
4016 const char *id;
4017 const char *load_state;
4018 const char *active_state;
4019 const char *sub_state;
4020 const char *unit_file_state;
4021 const char *unit_file_preset;
4022
4023 const char *description;
4024 const char *following;
4025
4026 char **documentation;
4027
4028 const char *fragment_path;
4029 const char *source_path;
4030 const char *control_group;
4031
4032 char **dropin_paths;
4033
4034 const char *load_error;
4035 const char *result;
4036
4037 usec_t inactive_exit_timestamp;
4038 usec_t inactive_exit_timestamp_monotonic;
4039 usec_t active_enter_timestamp;
4040 usec_t active_exit_timestamp;
4041 usec_t inactive_enter_timestamp;
4042
4043 bool need_daemon_reload;
4044 bool transient;
4045
4046 /* Service */
4047 pid_t main_pid;
4048 pid_t control_pid;
4049 const char *status_text;
4050 const char *pid_file;
4051 bool running:1;
4052 int status_errno;
4053
4054 usec_t start_timestamp;
4055 usec_t exit_timestamp;
4056
4057 int exit_code, exit_status;
4058
4059 usec_t condition_timestamp;
4060 bool condition_result;
4061 LIST_HEAD(UnitCondition, conditions);
4062
4063 usec_t assert_timestamp;
4064 bool assert_result;
4065 bool failed_assert_trigger;
4066 bool failed_assert_negate;
4067 const char *failed_assert;
4068 const char *failed_assert_parameter;
4069 usec_t next_elapse_real;
4070 usec_t next_elapse_monotonic;
4071
4072 /* Socket */
4073 unsigned n_accepted;
4074 unsigned n_connections;
4075 unsigned n_refused;
4076 bool accept;
4077
4078 /* Pairs of type, path */
4079 char **listen;
4080
4081 /* Device */
4082 const char *sysfs_path;
4083
4084 /* Mount, Automount */
4085 const char *where;
4086
4087 /* Swap */
4088 const char *what;
4089
4090 /* CGroup */
4091 uint64_t memory_current;
4092 uint64_t memory_min;
4093 uint64_t memory_low;
4094 uint64_t memory_high;
4095 uint64_t memory_max;
4096 uint64_t memory_swap_max;
4097 uint64_t memory_limit;
4098 uint64_t cpu_usage_nsec;
4099 uint64_t tasks_current;
4100 uint64_t tasks_max;
4101
4102 uint64_t ip_ingress_bytes;
4103 uint64_t ip_egress_bytes;
4104
4105 LIST_HEAD(ExecStatusInfo, exec);
4106 } UnitStatusInfo;
4107
4108 static void unit_status_info_free(UnitStatusInfo *info) {
4109 ExecStatusInfo *p;
4110 UnitCondition *c;
4111
4112 strv_free(info->documentation);
4113 strv_free(info->dropin_paths);
4114 strv_free(info->listen);
4115
4116 while ((c = info->conditions)) {
4117 LIST_REMOVE(conditions, info->conditions, c);
4118 unit_condition_free(c);
4119 }
4120
4121 while ((p = info->exec)) {
4122 LIST_REMOVE(exec, info->exec, p);
4123 exec_status_info_free(p);
4124 }
4125 }
4126
4127 static void print_status_info(
4128 sd_bus *bus,
4129 UnitStatusInfo *i,
4130 bool *ellipsized) {
4131
4132 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
4133 const char *s1, *s2, *active_on, *active_off, *on, *off, *ss;
4134 _cleanup_free_ char *formatted_path = NULL;
4135 ExecStatusInfo *p;
4136 usec_t timestamp;
4137 const char *path;
4138 char **t, **t2;
4139 int r;
4140
4141 assert(i);
4142
4143 /* This shows pretty information about a unit. See
4144 * print_property() for a low-level property printer */
4145
4146 if (streq_ptr(i->active_state, "failed")) {
4147 active_on = ansi_highlight_red();
4148 active_off = ansi_normal();
4149 } else if (STRPTR_IN_SET(i->active_state, "active", "reloading")) {
4150 active_on = ansi_highlight_green();
4151 active_off = ansi_normal();
4152 } else
4153 active_on = active_off = "";
4154
4155 printf("%s%s%s %s", active_on, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE), active_off, strna(i->id));
4156
4157 if (i->description && !streq_ptr(i->id, i->description))
4158 printf(" - %s", i->description);
4159
4160 printf("\n");
4161
4162 if (i->following)
4163 printf(" Follow: unit currently follows state of %s\n", i->following);
4164
4165 if (STRPTR_IN_SET(i->load_state, "error", "not-found", "bad-setting")) {
4166 on = ansi_highlight_red();
4167 off = ansi_normal();
4168 } else
4169 on = off = "";
4170
4171 path = i->source_path ?: i->fragment_path;
4172 if (path && terminal_urlify_path(path, NULL, &formatted_path) >= 0)
4173 path = formatted_path;
4174
4175 if (!isempty(i->load_error))
4176 printf(" Loaded: %s%s%s (Reason: %s)\n",
4177 on, strna(i->load_state), off, i->load_error);
4178 else if (path && !isempty(i->unit_file_state) && !isempty(i->unit_file_preset) &&
4179 !STR_IN_SET(i->unit_file_state, "generated", "transient"))
4180 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
4181 on, strna(i->load_state), off, path, i->unit_file_state, i->unit_file_preset);
4182 else if (path && !isempty(i->unit_file_state))
4183 printf(" Loaded: %s%s%s (%s; %s)\n",
4184 on, strna(i->load_state), off, path, i->unit_file_state);
4185 else if (path)
4186 printf(" Loaded: %s%s%s (%s)\n",
4187 on, strna(i->load_state), off, path);
4188 else
4189 printf(" Loaded: %s%s%s\n",
4190 on, strna(i->load_state), off);
4191
4192 if (i->transient)
4193 printf("Transient: yes\n");
4194
4195 if (!strv_isempty(i->dropin_paths)) {
4196 _cleanup_free_ char *dir = NULL;
4197 bool last = false;
4198 char ** dropin;
4199
4200 STRV_FOREACH(dropin, i->dropin_paths) {
4201 _cleanup_free_ char *dropin_formatted = NULL;
4202 const char *df;
4203
4204 if (!dir || last) {
4205 printf(dir ? " " :
4206 " Drop-In: ");
4207
4208 dir = mfree(dir);
4209
4210 dir = dirname_malloc(*dropin);
4211 if (!dir) {
4212 log_oom();
4213 return;
4214 }
4215
4216 printf("%s\n"
4217 " %s", dir,
4218 special_glyph(SPECIAL_GLYPH_TREE_RIGHT));
4219 }
4220
4221 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
4222
4223 if (terminal_urlify_path(*dropin, basename(*dropin), &dropin_formatted) >= 0)
4224 df = dropin_formatted;
4225 else
4226 df = *dropin;
4227
4228 printf("%s%s", df, last ? "\n" : ", ");
4229 }
4230 }
4231
4232 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
4233 if (ss)
4234 printf(" Active: %s%s (%s)%s",
4235 active_on, strna(i->active_state), ss, active_off);
4236 else
4237 printf(" Active: %s%s%s",
4238 active_on, strna(i->active_state), active_off);
4239
4240 if (!isempty(i->result) && !streq(i->result, "success"))
4241 printf(" (Result: %s)", i->result);
4242
4243 timestamp = STRPTR_IN_SET(i->active_state, "active", "reloading") ? i->active_enter_timestamp :
4244 STRPTR_IN_SET(i->active_state, "inactive", "failed") ? i->inactive_enter_timestamp :
4245 STRPTR_IN_SET(i->active_state, "activating") ? i->inactive_exit_timestamp :
4246 i->active_exit_timestamp;
4247
4248 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
4249 s2 = format_timestamp(since2, sizeof(since2), timestamp);
4250
4251 if (s1)
4252 printf(" since %s; %s\n", s2, s1);
4253 else if (s2)
4254 printf(" since %s\n", s2);
4255 else
4256 printf("\n");
4257
4258 if (endswith(i->id, ".timer")) {
4259 char tstamp1[FORMAT_TIMESTAMP_RELATIVE_MAX],
4260 tstamp2[FORMAT_TIMESTAMP_MAX];
4261 const char *next_rel_time, *next_time;
4262 dual_timestamp nw, next = {i->next_elapse_real,
4263 i->next_elapse_monotonic};
4264 usec_t next_elapse;
4265
4266 printf(" Trigger: ");
4267
4268 dual_timestamp_get(&nw);
4269 next_elapse = calc_next_elapse(&nw, &next);
4270 next_rel_time = format_timestamp_relative(tstamp1, sizeof tstamp1, next_elapse);
4271 next_time = format_timestamp(tstamp2, sizeof tstamp2, next_elapse);
4272
4273 if (next_time && next_rel_time)
4274 printf("%s; %s\n", next_time, next_rel_time);
4275 else
4276 printf("n/a\n");
4277 }
4278
4279 if (!i->condition_result && i->condition_timestamp > 0) {
4280 UnitCondition *c;
4281 int n = 0;
4282
4283 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
4284 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
4285
4286 printf("Condition: start %scondition failed%s at %s%s%s\n",
4287 ansi_highlight_yellow(), ansi_normal(),
4288 s2, s1 ? "; " : "", strempty(s1));
4289
4290 LIST_FOREACH(conditions, c, i->conditions)
4291 if (c->tristate < 0)
4292 n++;
4293
4294 LIST_FOREACH(conditions, c, i->conditions)
4295 if (c->tristate < 0)
4296 printf(" %s %s=%s%s%s was not met\n",
4297 --n ? special_glyph(SPECIAL_GLYPH_TREE_BRANCH) : special_glyph(SPECIAL_GLYPH_TREE_RIGHT),
4298 c->name,
4299 c->trigger ? "|" : "",
4300 c->negate ? "!" : "",
4301 c->param);
4302 }
4303
4304 if (!i->assert_result && i->assert_timestamp > 0) {
4305 s1 = format_timestamp_relative(since1, sizeof(since1), i->assert_timestamp);
4306 s2 = format_timestamp(since2, sizeof(since2), i->assert_timestamp);
4307
4308 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
4309 ansi_highlight_red(), ansi_normal(),
4310 s2, s1 ? "; " : "", strempty(s1));
4311 if (i->failed_assert_trigger)
4312 printf(" none of the trigger assertions were met\n");
4313 else if (i->failed_assert)
4314 printf(" %s=%s%s was not met\n",
4315 i->failed_assert,
4316 i->failed_assert_negate ? "!" : "",
4317 i->failed_assert_parameter);
4318 }
4319
4320 if (i->sysfs_path)
4321 printf(" Device: %s\n", i->sysfs_path);
4322 if (i->where)
4323 printf(" Where: %s\n", i->where);
4324 if (i->what)
4325 printf(" What: %s\n", i->what);
4326
4327 STRV_FOREACH(t, i->documentation) {
4328 _cleanup_free_ char *formatted = NULL;
4329 const char *q;
4330
4331 if (terminal_urlify(*t, NULL, &formatted) >= 0)
4332 q = formatted;
4333 else
4334 q = *t;
4335
4336 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", q);
4337 }
4338
4339 STRV_FOREACH_PAIR(t, t2, i->listen)
4340 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
4341
4342 if (i->accept) {
4343 printf(" Accepted: %u; Connected: %u;", i->n_accepted, i->n_connections);
4344 if (i->n_refused)
4345 printf(" Refused: %u", i->n_refused);
4346 printf("\n");
4347 }
4348
4349 LIST_FOREACH(exec, p, i->exec) {
4350 _cleanup_free_ char *argv = NULL;
4351 bool good;
4352
4353 /* Only show exited processes here */
4354 if (p->code == 0)
4355 continue;
4356
4357 argv = strv_join(p->argv, " ");
4358 printf(" Process: "PID_FMT" %s=%s ", p->pid, p->name, strna(argv));
4359
4360 good = is_clean_exit(p->code, p->status, EXIT_CLEAN_DAEMON, NULL);
4361 if (!good) {
4362 on = ansi_highlight_red();
4363 off = ansi_normal();
4364 } else
4365 on = off = "";
4366
4367 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
4368
4369 if (p->code == CLD_EXITED) {
4370 const char *c;
4371
4372 printf("status=%i", p->status);
4373
4374 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
4375 if (c)
4376 printf("/%s", c);
4377
4378 } else
4379 printf("signal=%s", signal_to_string(p->status));
4380
4381 printf(")%s\n", off);
4382
4383 if (i->main_pid == p->pid &&
4384 i->start_timestamp == p->start_timestamp &&
4385 i->exit_timestamp == p->start_timestamp)
4386 /* Let's not show this twice */
4387 i->main_pid = 0;
4388
4389 if (p->pid == i->control_pid)
4390 i->control_pid = 0;
4391 }
4392
4393 if (i->main_pid > 0 || i->control_pid > 0) {
4394 if (i->main_pid > 0) {
4395 printf(" Main PID: "PID_FMT, i->main_pid);
4396
4397 if (i->running) {
4398
4399 if (arg_transport == BUS_TRANSPORT_LOCAL) {
4400 _cleanup_free_ char *comm = NULL;
4401
4402 (void) get_process_comm(i->main_pid, &comm);
4403 if (comm)
4404 printf(" (%s)", comm);
4405 }
4406
4407 } else if (i->exit_code > 0) {
4408 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
4409
4410 if (i->exit_code == CLD_EXITED) {
4411 const char *c;
4412
4413 printf("status=%i", i->exit_status);
4414
4415 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
4416 if (c)
4417 printf("/%s", c);
4418
4419 } else
4420 printf("signal=%s", signal_to_string(i->exit_status));
4421 printf(")");
4422 }
4423 }
4424
4425 if (i->control_pid > 0) {
4426 _cleanup_free_ char *c = NULL;
4427
4428 if (i->main_pid > 0)
4429 fputs("; Control PID: ", stdout);
4430 else
4431 fputs("Cntrl PID: ", stdout); /* if first in column, abbreviated so it fits alignment */
4432
4433 printf(PID_FMT, i->control_pid);
4434
4435 if (arg_transport == BUS_TRANSPORT_LOCAL) {
4436 (void) get_process_comm(i->control_pid, &c);
4437 if (c)
4438 printf(" (%s)", c);
4439 }
4440 }
4441
4442 printf("\n");
4443 }
4444
4445 if (i->status_text)
4446 printf(" Status: \"%s\"\n", i->status_text);
4447 if (i->status_errno > 0)
4448 printf(" Error: %i (%s)\n", i->status_errno, strerror(i->status_errno));
4449
4450 if (i->ip_ingress_bytes != (uint64_t) -1 && i->ip_egress_bytes != (uint64_t) -1) {
4451 char buf_in[FORMAT_BYTES_MAX], buf_out[FORMAT_BYTES_MAX];
4452
4453 printf(" IP: %s in, %s out\n",
4454 format_bytes(buf_in, sizeof(buf_in), i->ip_ingress_bytes),
4455 format_bytes(buf_out, sizeof(buf_out), i->ip_egress_bytes));
4456 }
4457
4458 if (i->tasks_current != (uint64_t) -1) {
4459 printf(" Tasks: %" PRIu64, i->tasks_current);
4460
4461 if (i->tasks_max != (uint64_t) -1)
4462 printf(" (limit: %" PRIu64 ")\n", i->tasks_max);
4463 else
4464 printf("\n");
4465 }
4466
4467 if (i->memory_current != (uint64_t) -1) {
4468 char buf[FORMAT_BYTES_MAX];
4469
4470 printf(" Memory: %s", format_bytes(buf, sizeof(buf), i->memory_current));
4471
4472 if (i->memory_min > 0 || i->memory_low > 0 ||
4473 i->memory_high != CGROUP_LIMIT_MAX || i->memory_max != CGROUP_LIMIT_MAX ||
4474 i->memory_swap_max != CGROUP_LIMIT_MAX ||
4475 i->memory_limit != CGROUP_LIMIT_MAX) {
4476 const char *prefix = "";
4477
4478 printf(" (");
4479 if (i->memory_min > 0) {
4480 printf("%smin: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_min));
4481 prefix = " ";
4482 }
4483 if (i->memory_low > 0) {
4484 printf("%slow: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_low));
4485 prefix = " ";
4486 }
4487 if (i->memory_high != CGROUP_LIMIT_MAX) {
4488 printf("%shigh: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_high));
4489 prefix = " ";
4490 }
4491 if (i->memory_max != CGROUP_LIMIT_MAX) {
4492 printf("%smax: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_max));
4493 prefix = " ";
4494 }
4495 if (i->memory_swap_max != CGROUP_LIMIT_MAX) {
4496 printf("%sswap max: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_swap_max));
4497 prefix = " ";
4498 }
4499 if (i->memory_limit != CGROUP_LIMIT_MAX) {
4500 printf("%slimit: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_limit));
4501 prefix = " ";
4502 }
4503 printf(")");
4504 }
4505 printf("\n");
4506 }
4507
4508 if (i->cpu_usage_nsec != (uint64_t) -1) {
4509 char buf[FORMAT_TIMESPAN_MAX];
4510 printf(" CPU: %s\n", format_timespan(buf, sizeof(buf), i->cpu_usage_nsec / NSEC_PER_USEC, USEC_PER_MSEC));
4511 }
4512
4513 if (i->control_group) {
4514 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
4515 static const char prefix[] = " ";
4516 unsigned c;
4517
4518 printf(" CGroup: %s\n", i->control_group);
4519
4520 c = columns();
4521 if (c > sizeof(prefix) - 1)
4522 c -= sizeof(prefix) - 1;
4523 else
4524 c = 0;
4525
4526 r = unit_show_processes(bus, i->id, i->control_group, prefix, c, get_output_flags(), &error);
4527 if (r == -EBADR) {
4528 unsigned k = 0;
4529 pid_t extra[2];
4530
4531 /* Fallback for older systemd versions where the GetUnitProcesses() call is not yet available */
4532
4533 if (i->main_pid > 0)
4534 extra[k++] = i->main_pid;
4535
4536 if (i->control_pid > 0)
4537 extra[k++] = i->control_pid;
4538
4539 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, extra, k, get_output_flags());
4540 } else if (r < 0)
4541 log_warning_errno(r, "Failed to dump process list for '%s', ignoring: %s", i->id, bus_error_message(&error, r));
4542 }
4543
4544 if (i->id && arg_transport == BUS_TRANSPORT_LOCAL)
4545 show_journal_by_unit(
4546 stdout,
4547 i->id,
4548 arg_output,
4549 0,
4550 i->inactive_exit_timestamp_monotonic,
4551 arg_lines,
4552 getuid(),
4553 get_output_flags() | OUTPUT_BEGIN_NEWLINE,
4554 SD_JOURNAL_LOCAL_ONLY,
4555 arg_scope == UNIT_FILE_SYSTEM,
4556 ellipsized);
4557
4558 if (i->need_daemon_reload)
4559 warn_unit_file_changed(i->id);
4560 }
4561
4562 static void show_unit_help(UnitStatusInfo *i) {
4563 char **p;
4564
4565 assert(i);
4566
4567 if (!i->documentation) {
4568 log_info("Documentation for %s not known.", i->id);
4569 return;
4570 }
4571
4572 STRV_FOREACH(p, i->documentation)
4573 if (startswith(*p, "man:"))
4574 show_man_page(*p + 4, false);
4575 else
4576 log_info("Can't show: %s", *p);
4577 }
4578
4579 static int map_main_pid(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
4580 UnitStatusInfo *i = userdata;
4581 uint32_t u;
4582 int r;
4583
4584 r = sd_bus_message_read(m, "u", &u);
4585 if (r < 0)
4586 return r;
4587
4588 i->main_pid = (pid_t) u;
4589 i->running = u > 0;
4590
4591 return 0;
4592 }
4593
4594 static int map_load_error(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
4595 const char *message, **p = userdata;
4596 int r;
4597
4598 r = sd_bus_message_read(m, "(ss)", NULL, &message);
4599 if (r < 0)
4600 return r;
4601
4602 if (!isempty(message))
4603 *p = message;
4604
4605 return 0;
4606 }
4607
4608 static int map_listen(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
4609 const char *type, *path;
4610 char ***p = userdata;
4611 int r;
4612
4613 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4614 if (r < 0)
4615 return r;
4616
4617 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
4618
4619 r = strv_extend(p, type);
4620 if (r < 0)
4621 return r;
4622
4623 r = strv_extend(p, path);
4624 if (r < 0)
4625 return r;
4626 }
4627 if (r < 0)
4628 return r;
4629
4630 r = sd_bus_message_exit_container(m);
4631 if (r < 0)
4632 return r;
4633
4634 return 0;
4635 }
4636
4637 static int map_conditions(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
4638 UnitStatusInfo *i = userdata;
4639 const char *cond, *param;
4640 int trigger, negate;
4641 int32_t state;
4642 int r;
4643
4644 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
4645 if (r < 0)
4646 return r;
4647
4648 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, &param, &state)) > 0) {
4649 _cleanup_(unit_condition_freep) UnitCondition *c = NULL;
4650
4651 c = new0(UnitCondition, 1);
4652 if (!c)
4653 return -ENOMEM;
4654
4655 c->name = strdup(cond);
4656 c->param = strdup(param);
4657 if (!c->name || !c->param)
4658 return -ENOMEM;
4659
4660 c->trigger = trigger;
4661 c->negate = negate;
4662 c->tristate = state;
4663
4664 LIST_PREPEND(conditions, i->conditions, c);
4665 c = NULL;
4666 }
4667 if (r < 0)
4668 return r;
4669
4670 r = sd_bus_message_exit_container(m);
4671 if (r < 0)
4672 return r;
4673
4674 return 0;
4675 }
4676
4677 static int map_asserts(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
4678 UnitStatusInfo *i = userdata;
4679 const char *cond, *param;
4680 int trigger, negate;
4681 int32_t state;
4682 int r;
4683
4684 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
4685 if (r < 0)
4686 return r;
4687
4688 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, &param, &state)) > 0) {
4689 if (state < 0 && (!trigger || !i->failed_assert)) {
4690 i->failed_assert = cond;
4691 i->failed_assert_trigger = trigger;
4692 i->failed_assert_negate = negate;
4693 i->failed_assert_parameter = param;
4694 }
4695 }
4696 if (r < 0)
4697 return r;
4698
4699 r = sd_bus_message_exit_container(m);
4700 if (r < 0)
4701 return r;
4702
4703 return 0;
4704 }
4705
4706 static int map_exec(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
4707 _cleanup_free_ ExecStatusInfo *info = NULL;
4708 ExecStatusInfo *last;
4709 UnitStatusInfo *i = userdata;
4710 int r;
4711
4712 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
4713 if (r < 0)
4714 return r;
4715
4716 info = new0(ExecStatusInfo, 1);
4717 if (!info)
4718 return -ENOMEM;
4719
4720 LIST_FIND_TAIL(exec, i->exec, last);
4721
4722 while ((r = exec_status_info_deserialize(m, info)) > 0) {
4723
4724 info->name = strdup(member);
4725 if (!info->name)
4726 return -ENOMEM;
4727
4728 LIST_INSERT_AFTER(exec, i->exec, last, info);
4729 last = info;
4730
4731 info = new0(ExecStatusInfo, 1);
4732 if (!info)
4733 return -ENOMEM;
4734 }
4735 if (r < 0)
4736 return r;
4737
4738 r = sd_bus_message_exit_container(m);
4739 if (r < 0)
4740 return r;
4741
4742 return 0;
4743 }
4744
4745 static int print_property(const char *name, const char *expected_value, sd_bus_message *m, bool value, bool all) {
4746 char bus_type;
4747 const char *contents;
4748 int r;
4749
4750 assert(name);
4751 assert(m);
4752
4753 /* This is a low-level property printer, see
4754 * print_status_info() for the nicer output */
4755
4756 r = sd_bus_message_peek_type(m, &bus_type, &contents);
4757 if (r < 0)
4758 return r;
4759
4760 switch (bus_type) {
4761
4762 case SD_BUS_TYPE_INT32:
4763 if (endswith(name, "ActionExitStatus")) {
4764 int32_t i;
4765
4766 r = sd_bus_message_read_basic(m, bus_type, &i);
4767 if (r < 0)
4768 return r;
4769
4770 if (i >= 0 && i <= 255)
4771 bus_print_property_valuef(name, expected_value, value, "%"PRIi32, i);
4772 else if (all)
4773 bus_print_property_value(name, expected_value, value, "[not set]");
4774
4775 return 1;
4776 }
4777 break;
4778
4779 case SD_BUS_TYPE_STRUCT:
4780
4781 if (contents[0] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
4782 uint32_t u;
4783
4784 r = sd_bus_message_read(m, "(uo)", &u, NULL);
4785 if (r < 0)
4786 return bus_log_parse_error(r);
4787
4788 if (u > 0)
4789 bus_print_property_valuef(name, expected_value, value, "%"PRIu32, u);
4790 else if (all)
4791 bus_print_property_value(name, expected_value, value, "");
4792
4793 return 1;
4794
4795 } else if (contents[0] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
4796 const char *s;
4797
4798 r = sd_bus_message_read(m, "(so)", &s, NULL);
4799 if (r < 0)
4800 return bus_log_parse_error(r);
4801
4802 if (all || !isempty(s))
4803 bus_print_property_value(name, expected_value, value, s);
4804
4805 return 1;
4806
4807 } else if (contents[0] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
4808 const char *a = NULL, *b = NULL;
4809
4810 r = sd_bus_message_read(m, "(ss)", &a, &b);
4811 if (r < 0)
4812 return bus_log_parse_error(r);
4813
4814 if (!isempty(a) || !isempty(b))
4815 bus_print_property_valuef(name, expected_value, value, "%s \"%s\"", strempty(a), strempty(b));
4816 else if (all)
4817 bus_print_property_value(name, expected_value, value, "");
4818
4819 return 1;
4820
4821 } else if (STR_IN_SET(name, "SystemCallFilter", "RestrictAddressFamilies")) {
4822 _cleanup_strv_free_ char **l = NULL;
4823 int whitelist;
4824
4825 r = sd_bus_message_enter_container(m, 'r', "bas");
4826 if (r < 0)
4827 return bus_log_parse_error(r);
4828
4829 r = sd_bus_message_read(m, "b", &whitelist);
4830 if (r < 0)
4831 return bus_log_parse_error(r);
4832
4833 r = sd_bus_message_read_strv(m, &l);
4834 if (r < 0)
4835 return bus_log_parse_error(r);
4836
4837 r = sd_bus_message_exit_container(m);
4838 if (r < 0)
4839 return bus_log_parse_error(r);
4840
4841 if (all || whitelist || !strv_isempty(l)) {
4842 bool first = true;
4843 char **i;
4844
4845 if (!value) {
4846 fputs(name, stdout);
4847 fputc('=', stdout);
4848 }
4849
4850 if (!whitelist)
4851 fputc('~', stdout);
4852
4853 STRV_FOREACH(i, l) {
4854 if (first)
4855 first = false;
4856 else
4857 fputc(' ', stdout);
4858
4859 fputs(*i, stdout);
4860 }
4861 fputc('\n', stdout);
4862 }
4863
4864 return 1;
4865
4866 } else if (STR_IN_SET(name, "SELinuxContext", "AppArmorProfile", "SmackProcessLabel")) {
4867 int ignore;
4868 const char *s;
4869
4870 r = sd_bus_message_read(m, "(bs)", &ignore, &s);
4871 if (r < 0)
4872 return bus_log_parse_error(r);
4873
4874 if (!isempty(s))
4875 bus_print_property_valuef(name, expected_value, value, "%s%s", ignore ? "-" : "", s);
4876 else if (all)
4877 bus_print_property_value(name, expected_value, value, "");
4878
4879 return 1;
4880
4881 } else if (endswith(name, "ExitStatus") && streq(contents, "aiai")) {
4882 const int32_t *status, *signal;
4883 size_t sz_status, sz_signal, i;
4884
4885 r = sd_bus_message_enter_container(m, 'r', "aiai");
4886 if (r < 0)
4887 return bus_log_parse_error(r);
4888
4889 r = sd_bus_message_read_array(m, 'i', (const void **) &status, &sz_status);
4890 if (r < 0)
4891 return bus_log_parse_error(r);
4892
4893 r = sd_bus_message_read_array(m, 'i', (const void **) &signal, &sz_signal);
4894 if (r < 0)
4895 return bus_log_parse_error(r);
4896
4897 r = sd_bus_message_exit_container(m);
4898 if (r < 0)
4899 return bus_log_parse_error(r);
4900
4901 sz_status /= sizeof(int32_t);
4902 sz_signal /= sizeof(int32_t);
4903
4904 if (all || sz_status > 0 || sz_signal > 0) {
4905 bool first = true;
4906
4907 if (!value) {
4908 fputs(name, stdout);
4909 fputc('=', stdout);
4910 }
4911
4912 for (i = 0; i < sz_status; i++) {
4913 if (status[i] < 0 || status[i] > 255)
4914 continue;
4915
4916 if (first)
4917 first = false;
4918 else
4919 fputc(' ', stdout);
4920
4921 printf("%"PRIi32, status[i]);
4922 }
4923
4924 for (i = 0; i < sz_signal; i++) {
4925 const char *str;
4926
4927 str = signal_to_string((int) signal[i]);
4928 if (!str)
4929 continue;
4930
4931 if (first)
4932 first = false;
4933 else
4934 fputc(' ', stdout);
4935
4936 fputs(str, stdout);
4937 }
4938
4939 fputc('\n', stdout);
4940 }
4941 return 1;
4942 }
4943
4944 break;
4945
4946 case SD_BUS_TYPE_ARRAY:
4947
4948 if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
4949 const char *path;
4950 int ignore;
4951
4952 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)");
4953 if (r < 0)
4954 return bus_log_parse_error(r);
4955
4956 while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
4957 bus_print_property_valuef(name, expected_value, value, "%s (ignore_errors=%s)", path, yes_no(ignore));
4958
4959 if (r < 0)
4960 return bus_log_parse_error(r);
4961
4962 r = sd_bus_message_exit_container(m);
4963 if (r < 0)
4964 return bus_log_parse_error(r);
4965
4966 return 1;
4967
4968 } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
4969 const char *type, *path;
4970
4971 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4972 if (r < 0)
4973 return bus_log_parse_error(r);
4974
4975 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
4976 bus_print_property_valuef(name, expected_value, value, "%s (%s)", path, type);
4977 if (r < 0)
4978 return bus_log_parse_error(r);
4979
4980 r = sd_bus_message_exit_container(m);
4981 if (r < 0)
4982 return bus_log_parse_error(r);
4983
4984 return 1;
4985
4986 } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
4987 const char *type, *path;
4988
4989 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4990 if (r < 0)
4991 return bus_log_parse_error(r);
4992
4993 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
4994 bus_print_property_valuef(name, expected_value, value, "%s (%s)", path, type);
4995 if (r < 0)
4996 return bus_log_parse_error(r);
4997
4998 r = sd_bus_message_exit_container(m);
4999 if (r < 0)
5000 return bus_log_parse_error(r);
5001
5002 return 1;
5003
5004 } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "TimersMonotonic")) {
5005 const char *base;
5006 uint64_t v, next_elapse;
5007
5008 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
5009 if (r < 0)
5010 return bus_log_parse_error(r);
5011
5012 while ((r = sd_bus_message_read(m, "(stt)", &base, &v, &next_elapse)) > 0) {
5013 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
5014
5015 bus_print_property_valuef(name, expected_value, value, "{ %s=%s ; next_elapse=%s }", base,
5016 format_timespan(timespan1, sizeof(timespan1), v, 0),
5017 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
5018 }
5019 if (r < 0)
5020 return bus_log_parse_error(r);
5021
5022 r = sd_bus_message_exit_container(m);
5023 if (r < 0)
5024 return bus_log_parse_error(r);
5025
5026 return 1;
5027
5028 } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "TimersCalendar")) {
5029 const char *base, *spec;
5030 uint64_t next_elapse;
5031
5032 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sst)");
5033 if (r < 0)
5034 return bus_log_parse_error(r);
5035
5036 while ((r = sd_bus_message_read(m, "(sst)", &base, &spec, &next_elapse)) > 0) {
5037 char timestamp[FORMAT_TIMESTAMP_MAX];
5038
5039 bus_print_property_valuef(name, expected_value, value, "{ %s=%s ; next_elapse=%s }", base, spec,
5040 format_timestamp(timestamp, sizeof(timestamp), next_elapse));
5041 }
5042 if (r < 0)
5043 return bus_log_parse_error(r);
5044
5045 r = sd_bus_message_exit_container(m);
5046 if (r < 0)
5047 return bus_log_parse_error(r);
5048
5049 return 1;
5050
5051 } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
5052 ExecStatusInfo info = {};
5053
5054 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
5055 if (r < 0)
5056 return bus_log_parse_error(r);
5057
5058 while ((r = exec_status_info_deserialize(m, &info)) > 0) {
5059 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
5060 _cleanup_free_ char *tt;
5061
5062 tt = strv_join(info.argv, " ");
5063
5064 bus_print_property_valuef(name, expected_value, value,
5065 "{ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT" ; code=%s ; status=%i%s%s }",
5066 strna(info.path),
5067 strna(tt),
5068 yes_no(info.ignore),
5069 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
5070 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
5071 info.pid,
5072 sigchld_code_to_string(info.code),
5073 info.status,
5074 info.code == CLD_EXITED ? "" : "/",
5075 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
5076
5077 free(info.path);
5078 strv_free(info.argv);
5079 zero(info);
5080 }
5081
5082 r = sd_bus_message_exit_container(m);
5083 if (r < 0)
5084 return bus_log_parse_error(r);
5085
5086 return 1;
5087
5088 } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
5089 const char *path, *rwm;
5090
5091 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
5092 if (r < 0)
5093 return bus_log_parse_error(r);
5094
5095 while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
5096 bus_print_property_valuef(name, expected_value, value, "%s %s", strna(path), strna(rwm));
5097 if (r < 0)
5098 return bus_log_parse_error(r);
5099
5100 r = sd_bus_message_exit_container(m);
5101 if (r < 0)
5102 return bus_log_parse_error(r);
5103
5104 return 1;
5105
5106 } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN &&
5107 STR_IN_SET(name, "IODeviceWeight", "BlockIODeviceWeight")) {
5108 const char *path;
5109 uint64_t weight;
5110
5111 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
5112 if (r < 0)
5113 return bus_log_parse_error(r);
5114
5115 while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
5116 bus_print_property_valuef(name, expected_value, value, "%s %"PRIu64, strna(path), weight);
5117 if (r < 0)
5118 return bus_log_parse_error(r);
5119
5120 r = sd_bus_message_exit_container(m);
5121 if (r < 0)
5122 return bus_log_parse_error(r);
5123
5124 return 1;
5125
5126 } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN &&
5127 (cgroup_io_limit_type_from_string(name) >= 0 ||
5128 STR_IN_SET(name, "BlockIOReadBandwidth", "BlockIOWriteBandwidth"))) {
5129 const char *path;
5130 uint64_t bandwidth;
5131
5132 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
5133 if (r < 0)
5134 return bus_log_parse_error(r);
5135
5136 while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
5137 bus_print_property_valuef(name, expected_value, value, "%s %"PRIu64, strna(path), bandwidth);
5138 if (r < 0)
5139 return bus_log_parse_error(r);
5140
5141 r = sd_bus_message_exit_container(m);
5142 if (r < 0)
5143 return bus_log_parse_error(r);
5144
5145 return 1;
5146
5147 } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN &&
5148 streq(name, "IODeviceLatencyTargetUSec")) {
5149 char ts[FORMAT_TIMESPAN_MAX];
5150 const char *path;
5151 uint64_t target;
5152
5153 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
5154 if (r < 0)
5155 return bus_log_parse_error(r);
5156
5157 while ((r = sd_bus_message_read(m, "(st)", &path, &target)) > 0)
5158 bus_print_property_valuef(name, expected_value, value, "%s %s", strna(path),
5159 format_timespan(ts, sizeof(ts), target, 1));
5160 if (r < 0)
5161 return bus_log_parse_error(r);
5162
5163 r = sd_bus_message_exit_container(m);
5164 if (r < 0)
5165 return bus_log_parse_error(r);
5166
5167 return 1;
5168
5169 } else if (contents[0] == SD_BUS_TYPE_BYTE && streq(name, "StandardInputData")) {
5170 _cleanup_free_ char *h = NULL;
5171 const void *p;
5172 size_t sz;
5173 ssize_t n;
5174
5175 r = sd_bus_message_read_array(m, 'y', &p, &sz);
5176 if (r < 0)
5177 return bus_log_parse_error(r);
5178
5179 n = base64mem(p, sz, &h);
5180 if (n < 0)
5181 return log_oom();
5182
5183 bus_print_property_value(name, expected_value, value, h);
5184
5185 return 1;
5186
5187 } else if (STR_IN_SET(name, "IPAddressAllow", "IPAddressDeny")) {
5188 _cleanup_free_ char *addresses = NULL;
5189
5190 r = sd_bus_message_enter_container(m, 'a', "(iayu)");
5191 if (r < 0)
5192 return bus_log_parse_error(r);
5193
5194 for (;;) {
5195 _cleanup_free_ char *str = NULL;
5196 uint32_t prefixlen;
5197 int32_t family;
5198 const void *ap;
5199 size_t an;
5200
5201 r = sd_bus_message_enter_container(m, 'r', "iayu");
5202 if (r < 0)
5203 return bus_log_parse_error(r);
5204 if (r == 0)
5205 break;
5206
5207 r = sd_bus_message_read(m, "i", &family);
5208 if (r < 0)
5209 return bus_log_parse_error(r);
5210
5211 r = sd_bus_message_read_array(m, 'y', &ap, &an);
5212 if (r < 0)
5213 return bus_log_parse_error(r);
5214
5215 r = sd_bus_message_read(m, "u", &prefixlen);
5216 if (r < 0)
5217 return bus_log_parse_error(r);
5218
5219 r = sd_bus_message_exit_container(m);
5220 if (r < 0)
5221 return bus_log_parse_error(r);
5222
5223 if (!IN_SET(family, AF_INET, AF_INET6))
5224 continue;
5225
5226 if (an != FAMILY_ADDRESS_SIZE(family))
5227 continue;
5228
5229 if (prefixlen > FAMILY_ADDRESS_SIZE(family) * 8)
5230 continue;
5231
5232 if (in_addr_prefix_to_string(family, (union in_addr_union *) ap, prefixlen, &str) < 0)
5233 continue;
5234
5235 if (!strextend_with_separator(&addresses, " ", str, NULL))
5236 return log_oom();
5237 }
5238
5239 r = sd_bus_message_exit_container(m);
5240 if (r < 0)
5241 return bus_log_parse_error(r);
5242
5243 if (all || !isempty(addresses))
5244 bus_print_property_value(name, expected_value, value, strempty(addresses));
5245
5246 return 1;
5247
5248 } else if (STR_IN_SET(name, "BindPaths", "BindReadOnlyPaths")) {
5249 _cleanup_free_ char *paths = NULL;
5250 const char *source, *dest;
5251 int ignore_enoent;
5252 uint64_t rbind;
5253
5254 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ssbt)");
5255 if (r < 0)
5256 return bus_log_parse_error(r);
5257
5258 while ((r = sd_bus_message_read(m, "(ssbt)", &source, &dest, &ignore_enoent, &rbind)) > 0) {
5259 _cleanup_free_ char *str = NULL;
5260
5261 if (isempty(source))
5262 continue;
5263
5264 if (asprintf(&str, "%s%s%s%s%s",
5265 ignore_enoent ? "-" : "",
5266 source,
5267 isempty(dest) ? "" : ":",
5268 strempty(dest),
5269 rbind == MS_REC ? ":rbind" : "") < 0)
5270 return log_oom();
5271
5272 if (!strextend_with_separator(&paths, " ", str, NULL))
5273 return log_oom();
5274 }
5275 if (r < 0)
5276 return bus_log_parse_error(r);
5277
5278 r = sd_bus_message_exit_container(m);
5279 if (r < 0)
5280 return bus_log_parse_error(r);
5281
5282 if (all || !isempty(paths))
5283 bus_print_property_value(name, expected_value, value, strempty(paths));
5284
5285 return 1;
5286
5287 } else if (streq(name, "TemporaryFileSystem")) {
5288 _cleanup_free_ char *paths = NULL;
5289 const char *target, *option;
5290
5291 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
5292 if (r < 0)
5293 return bus_log_parse_error(r);
5294
5295 while ((r = sd_bus_message_read(m, "(ss)", &target, &option)) > 0) {
5296 _cleanup_free_ char *str = NULL;
5297
5298 if (isempty(target))
5299 continue;
5300
5301 if (asprintf(&str, "%s%s%s", target, isempty(option) ? "" : ":", strempty(option)) < 0)
5302 return log_oom();
5303
5304 if (!strextend_with_separator(&paths, " ", str, NULL))
5305 return log_oom();
5306 }
5307 if (r < 0)
5308 return bus_log_parse_error(r);
5309
5310 r = sd_bus_message_exit_container(m);
5311 if (r < 0)
5312 return bus_log_parse_error(r);
5313
5314 if (all || !isempty(paths))
5315 bus_print_property_value(name, expected_value, value, strempty(paths));
5316
5317 return 1;
5318
5319 } else if (streq(name, "LogExtraFields")) {
5320 _cleanup_free_ char *fields = NULL;
5321 const void *p;
5322 size_t sz;
5323
5324 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "ay");
5325 if (r < 0)
5326 return bus_log_parse_error(r);
5327
5328 while ((r = sd_bus_message_read_array(m, 'y', &p, &sz)) > 0) {
5329 _cleanup_free_ char *str = NULL;
5330 const char *eq;
5331
5332 if (memchr(p, 0, sz))
5333 continue;
5334
5335 eq = memchr(p, '=', sz);
5336 if (!eq)
5337 continue;
5338
5339 if (!journal_field_valid(p, eq - (const char*) p, false))
5340 continue;
5341
5342 str = malloc(sz + 1);
5343 if (!str)
5344 return log_oom();
5345
5346 memcpy(str, p, sz);
5347 str[sz] = '\0';
5348
5349 if (!utf8_is_valid(str))
5350 continue;
5351
5352 if (!strextend_with_separator(&fields, " ", str, NULL))
5353 return log_oom();
5354 }
5355 if (r < 0)
5356 return bus_log_parse_error(r);
5357
5358 r = sd_bus_message_exit_container(m);
5359 if (r < 0)
5360 return bus_log_parse_error(r);
5361
5362 if (all || !isempty(fields))
5363 bus_print_property_value(name, expected_value, value, strempty(fields));
5364
5365 return 1;
5366 }
5367
5368 break;
5369 }
5370
5371 return 0;
5372 }
5373
5374 typedef enum SystemctlShowMode{
5375 SYSTEMCTL_SHOW_PROPERTIES,
5376 SYSTEMCTL_SHOW_STATUS,
5377 SYSTEMCTL_SHOW_HELP,
5378 _SYSTEMCTL_SHOW_MODE_MAX,
5379 _SYSTEMCTL_SHOW_MODE_INVALID = -1,
5380 } SystemctlShowMode;
5381
5382 static const char* const systemctl_show_mode_table[_SYSTEMCTL_SHOW_MODE_MAX] = {
5383 [SYSTEMCTL_SHOW_PROPERTIES] = "show",
5384 [SYSTEMCTL_SHOW_STATUS] = "status",
5385 [SYSTEMCTL_SHOW_HELP] = "help",
5386 };
5387
5388 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(systemctl_show_mode, SystemctlShowMode);
5389
5390 static int show_one(
5391 sd_bus *bus,
5392 const char *path,
5393 const char *unit,
5394 SystemctlShowMode show_mode,
5395 bool *new_line,
5396 bool *ellipsized) {
5397
5398 static const struct bus_properties_map property_map[] = {
5399 { "LoadState", "s", NULL, offsetof(UnitStatusInfo, load_state) },
5400 { "ActiveState", "s", NULL, offsetof(UnitStatusInfo, active_state) },
5401 { "Documentation", "as", NULL, offsetof(UnitStatusInfo, documentation) },
5402 {}
5403 }, status_map[] = {
5404 { "Id", "s", NULL, offsetof(UnitStatusInfo, id) },
5405 { "LoadState", "s", NULL, offsetof(UnitStatusInfo, load_state) },
5406 { "ActiveState", "s", NULL, offsetof(UnitStatusInfo, active_state) },
5407 { "SubState", "s", NULL, offsetof(UnitStatusInfo, sub_state) },
5408 { "UnitFileState", "s", NULL, offsetof(UnitStatusInfo, unit_file_state) },
5409 { "UnitFilePreset", "s", NULL, offsetof(UnitStatusInfo, unit_file_preset) },
5410 { "Description", "s", NULL, offsetof(UnitStatusInfo, description) },
5411 { "Following", "s", NULL, offsetof(UnitStatusInfo, following) },
5412 { "Documentation", "as", NULL, offsetof(UnitStatusInfo, documentation) },
5413 { "FragmentPath", "s", NULL, offsetof(UnitStatusInfo, fragment_path) },
5414 { "SourcePath", "s", NULL, offsetof(UnitStatusInfo, source_path) },
5415 { "ControlGroup", "s", NULL, offsetof(UnitStatusInfo, control_group) },
5416 { "DropInPaths", "as", NULL, offsetof(UnitStatusInfo, dropin_paths) },
5417 { "LoadError", "(ss)", map_load_error, offsetof(UnitStatusInfo, load_error) },
5418 { "Result", "s", NULL, offsetof(UnitStatusInfo, result) },
5419 { "InactiveExitTimestamp", "t", NULL, offsetof(UnitStatusInfo, inactive_exit_timestamp) },
5420 { "InactiveExitTimestampMonotonic", "t", NULL, offsetof(UnitStatusInfo, inactive_exit_timestamp_monotonic) },
5421 { "ActiveEnterTimestamp", "t", NULL, offsetof(UnitStatusInfo, active_enter_timestamp) },
5422 { "ActiveExitTimestamp", "t", NULL, offsetof(UnitStatusInfo, active_exit_timestamp) },
5423 { "InactiveEnterTimestamp", "t", NULL, offsetof(UnitStatusInfo, inactive_enter_timestamp) },
5424 { "NeedDaemonReload", "b", NULL, offsetof(UnitStatusInfo, need_daemon_reload) },
5425 { "Transient", "b", NULL, offsetof(UnitStatusInfo, transient) },
5426 { "ExecMainPID", "u", NULL, offsetof(UnitStatusInfo, main_pid) },
5427 { "MainPID", "u", map_main_pid, 0 },
5428 { "ControlPID", "u", NULL, offsetof(UnitStatusInfo, control_pid) },
5429 { "StatusText", "s", NULL, offsetof(UnitStatusInfo, status_text) },
5430 { "PIDFile", "s", NULL, offsetof(UnitStatusInfo, pid_file) },
5431 { "StatusErrno", "i", NULL, offsetof(UnitStatusInfo, status_errno) },
5432 { "ExecMainStartTimestamp", "t", NULL, offsetof(UnitStatusInfo, start_timestamp) },
5433 { "ExecMainExitTimestamp", "t", NULL, offsetof(UnitStatusInfo, exit_timestamp) },
5434 { "ExecMainCode", "i", NULL, offsetof(UnitStatusInfo, exit_code) },
5435 { "ExecMainStatus", "i", NULL, offsetof(UnitStatusInfo, exit_status) },
5436 { "ConditionTimestamp", "t", NULL, offsetof(UnitStatusInfo, condition_timestamp) },
5437 { "ConditionResult", "b", NULL, offsetof(UnitStatusInfo, condition_result) },
5438 { "Conditions", "a(sbbsi)", map_conditions, 0 },
5439 { "AssertTimestamp", "t", NULL, offsetof(UnitStatusInfo, assert_timestamp) },
5440 { "AssertResult", "b", NULL, offsetof(UnitStatusInfo, assert_result) },
5441 { "Asserts", "a(sbbsi)", map_asserts, 0 },
5442 { "NextElapseUSecRealtime", "t", NULL, offsetof(UnitStatusInfo, next_elapse_real) },
5443 { "NextElapseUSecMonotonic", "t", NULL, offsetof(UnitStatusInfo, next_elapse_monotonic) },
5444 { "NAccepted", "u", NULL, offsetof(UnitStatusInfo, n_accepted) },
5445 { "NConnections", "u", NULL, offsetof(UnitStatusInfo, n_connections) },
5446 { "NRefused", "u", NULL, offsetof(UnitStatusInfo, n_refused) },
5447 { "Accept", "b", NULL, offsetof(UnitStatusInfo, accept) },
5448 { "Listen", "a(ss)", map_listen, offsetof(UnitStatusInfo, listen) },
5449 { "SysFSPath", "s", NULL, offsetof(UnitStatusInfo, sysfs_path) },
5450 { "Where", "s", NULL, offsetof(UnitStatusInfo, where) },
5451 { "What", "s", NULL, offsetof(UnitStatusInfo, what) },
5452 { "MemoryCurrent", "t", NULL, offsetof(UnitStatusInfo, memory_current) },
5453 { "MemoryMin", "t", NULL, offsetof(UnitStatusInfo, memory_min) },
5454 { "MemoryLow", "t", NULL, offsetof(UnitStatusInfo, memory_low) },
5455 { "MemoryHigh", "t", NULL, offsetof(UnitStatusInfo, memory_high) },
5456 { "MemoryMax", "t", NULL, offsetof(UnitStatusInfo, memory_max) },
5457 { "MemorySwapMax", "t", NULL, offsetof(UnitStatusInfo, memory_swap_max) },
5458 { "MemoryLimit", "t", NULL, offsetof(UnitStatusInfo, memory_limit) },
5459 { "CPUUsageNSec", "t", NULL, offsetof(UnitStatusInfo, cpu_usage_nsec) },
5460 { "TasksCurrent", "t", NULL, offsetof(UnitStatusInfo, tasks_current) },
5461 { "TasksMax", "t", NULL, offsetof(UnitStatusInfo, tasks_max) },
5462 { "IPIngressBytes", "t", NULL, offsetof(UnitStatusInfo, ip_ingress_bytes) },
5463 { "IPEgressBytes", "t", NULL, offsetof(UnitStatusInfo, ip_egress_bytes) },
5464 { "ExecStartPre", "a(sasbttttuii)", map_exec, 0 },
5465 { "ExecStart", "a(sasbttttuii)", map_exec, 0 },
5466 { "ExecStartPost", "a(sasbttttuii)", map_exec, 0 },
5467 { "ExecReload", "a(sasbttttuii)", map_exec, 0 },
5468 { "ExecStopPre", "a(sasbttttuii)", map_exec, 0 },
5469 { "ExecStop", "a(sasbttttuii)", map_exec, 0 },
5470 { "ExecStopPost", "a(sasbttttuii)", map_exec, 0 },
5471 {}
5472 };
5473
5474 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
5475 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
5476 _cleanup_set_free_ Set *found_properties = NULL;
5477 _cleanup_(unit_status_info_free) UnitStatusInfo info = {
5478 .memory_current = (uint64_t) -1,
5479 .memory_high = CGROUP_LIMIT_MAX,
5480 .memory_max = CGROUP_LIMIT_MAX,
5481 .memory_swap_max = CGROUP_LIMIT_MAX,
5482 .memory_limit = (uint64_t) -1,
5483 .cpu_usage_nsec = (uint64_t) -1,
5484 .tasks_current = (uint64_t) -1,
5485 .tasks_max = (uint64_t) -1,
5486 .ip_ingress_bytes = (uint64_t) -1,
5487 .ip_egress_bytes = (uint64_t) -1,
5488 };
5489 char **pp;
5490 int r;
5491
5492 assert(path);
5493 assert(new_line);
5494
5495 log_debug("Showing one %s", path);
5496
5497 r = bus_map_all_properties(
5498 bus,
5499 "org.freedesktop.systemd1",
5500 path,
5501 show_mode == SYSTEMCTL_SHOW_STATUS ? status_map : property_map,
5502 BUS_MAP_BOOLEAN_AS_BOOL,
5503 &error,
5504 &reply,
5505 &info);
5506 if (r < 0)
5507 return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r));
5508
5509 if (unit && streq_ptr(info.load_state, "not-found") && streq_ptr(info.active_state, "inactive")) {
5510 log_full(show_mode == SYSTEMCTL_SHOW_STATUS ? LOG_ERR : LOG_DEBUG,
5511 "Unit %s could not be found.", unit);
5512
5513 if (show_mode == SYSTEMCTL_SHOW_STATUS)
5514 return EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN;
5515 else if (show_mode == SYSTEMCTL_SHOW_HELP)
5516 return -ENOENT;
5517 }
5518
5519 if (*new_line)
5520 printf("\n");
5521
5522 *new_line = true;
5523
5524 if (show_mode == SYSTEMCTL_SHOW_STATUS) {
5525 print_status_info(bus, &info, ellipsized);
5526
5527 if (info.active_state && !STR_IN_SET(info.active_state, "active", "reloading"))
5528 return EXIT_PROGRAM_NOT_RUNNING;
5529
5530 return EXIT_PROGRAM_RUNNING_OR_SERVICE_OK;
5531
5532 } else if (show_mode == SYSTEMCTL_SHOW_HELP) {
5533 show_unit_help(&info);
5534 return 0;
5535 }
5536
5537 r = sd_bus_message_rewind(reply, true);
5538 if (r < 0)
5539 return log_error_errno(r, "Failed to rewind: %s", bus_error_message(&error, r));
5540
5541 r = bus_message_print_all_properties(reply, print_property, arg_properties, arg_value, arg_all, &found_properties);
5542 if (r < 0)
5543 return bus_log_parse_error(r);
5544
5545 STRV_FOREACH(pp, arg_properties)
5546 if (!set_contains(found_properties, *pp))
5547 log_debug("Property %s does not exist.", *pp);
5548
5549 return 0;
5550 }
5551
5552 static int get_unit_dbus_path_by_pid(
5553 sd_bus *bus,
5554 uint32_t pid,
5555 char **unit) {
5556
5557 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
5558 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
5559 char *u;
5560 int r;
5561
5562 r = sd_bus_call_method(
5563 bus,
5564 "org.freedesktop.systemd1",
5565 "/org/freedesktop/systemd1",
5566 "org.freedesktop.systemd1.Manager",
5567 "GetUnitByPID",
5568 &error,
5569 &reply,
5570 "u", pid);
5571 if (r < 0)
5572 return log_error_errno(r, "Failed to get unit for PID %"PRIu32": %s", pid, bus_error_message(&error, r));
5573
5574 r = sd_bus_message_read(reply, "o", &u);
5575 if (r < 0)
5576 return bus_log_parse_error(r);
5577
5578 u = strdup(u);
5579 if (!u)
5580 return log_oom();
5581
5582 *unit = u;
5583 return 0;
5584 }
5585
5586 static int show_all(
5587 sd_bus *bus,
5588 bool *new_line,
5589 bool *ellipsized) {
5590
5591 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
5592 _cleanup_free_ UnitInfo *unit_infos = NULL;
5593 const UnitInfo *u;
5594 unsigned c;
5595 int r, ret = 0;
5596
5597 r = get_unit_list(bus, NULL, NULL, &unit_infos, 0, &reply);
5598 if (r < 0)
5599 return r;
5600
5601 (void) pager_open(arg_pager_flags);
5602
5603 c = (unsigned) r;
5604
5605 typesafe_qsort(unit_infos, c, compare_unit_info);
5606
5607 for (u = unit_infos; u < unit_infos + c; u++) {
5608 _cleanup_free_ char *p = NULL;
5609
5610 p = unit_dbus_path_from_name(u->id);
5611 if (!p)
5612 return log_oom();
5613
5614 r = show_one(bus, p, u->id, SYSTEMCTL_SHOW_STATUS, new_line, ellipsized);
5615 if (r < 0)
5616 return r;
5617 else if (r > 0 && ret == 0)
5618 ret = r;
5619 }
5620
5621 return ret;
5622 }
5623
5624 static int show_system_status(sd_bus *bus) {
5625 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
5626 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
5627 _cleanup_(machine_info_clear) struct machine_info mi = {};
5628 _cleanup_free_ char *hn = NULL;
5629 const char *on, *off;
5630 int r;
5631
5632 hn = gethostname_malloc();
5633 if (!hn)
5634 return log_oom();
5635
5636 r = bus_map_all_properties(
5637 bus,
5638 "org.freedesktop.systemd1",
5639 "/org/freedesktop/systemd1",
5640 machine_info_property_map,
5641 BUS_MAP_STRDUP,
5642 &error,
5643 NULL,
5644 &mi);
5645 if (r < 0)
5646 return log_error_errno(r, "Failed to read server status: %s", bus_error_message(&error, r));
5647
5648 if (streq_ptr(mi.state, "degraded")) {
5649 on = ansi_highlight_red();
5650 off = ansi_normal();
5651 } else if (streq_ptr(mi.state, "running")) {
5652 on = ansi_highlight_green();
5653 off = ansi_normal();
5654 } else {
5655 on = ansi_highlight_yellow();
5656 off = ansi_normal();
5657 }
5658
5659 printf("%s%s%s %s\n", on, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE), off, arg_host ? arg_host : hn);
5660
5661 printf(" State: %s%s%s\n",
5662 on, strna(mi.state), off);
5663
5664 printf(" Jobs: %" PRIu32 " queued\n", mi.n_jobs);
5665 printf(" Failed: %" PRIu32 " units\n", mi.n_failed_units);
5666
5667 printf(" Since: %s; %s\n",
5668 format_timestamp(since2, sizeof(since2), mi.timestamp),
5669 format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
5670
5671 printf(" CGroup: %s\n", mi.control_group ?: "/");
5672 if (IN_SET(arg_transport,
5673 BUS_TRANSPORT_LOCAL,
5674 BUS_TRANSPORT_MACHINE)) {
5675 static const char prefix[] = " ";
5676 unsigned c;
5677
5678 c = columns();
5679 if (c > sizeof(prefix) - 1)
5680 c -= sizeof(prefix) - 1;
5681 else
5682 c = 0;
5683
5684 show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, get_output_flags());
5685 }
5686
5687 return 0;
5688 }
5689
5690 static int show(int argc, char *argv[], void *userdata) {
5691 bool new_line = false, ellipsized = false;
5692 SystemctlShowMode show_mode;
5693 int r, ret = 0;
5694 sd_bus *bus;
5695
5696 assert(argv);
5697
5698 show_mode = systemctl_show_mode_from_string(argv[0]);
5699 if (show_mode < 0)
5700 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
5701 "Invalid argument.");
5702
5703 if (show_mode == SYSTEMCTL_SHOW_HELP && argc <= 1)
5704 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
5705 "This command expects one or more unit names. Did you mean --help?");
5706
5707 r = acquire_bus(BUS_MANAGER, &bus);
5708 if (r < 0)
5709 return r;
5710
5711 (void) pager_open(arg_pager_flags);
5712
5713 /* If no argument is specified inspect the manager itself */
5714 if (show_mode == SYSTEMCTL_SHOW_PROPERTIES && argc <= 1)
5715 return show_one(bus, "/org/freedesktop/systemd1", NULL, show_mode, &new_line, &ellipsized);
5716
5717 if (show_mode == SYSTEMCTL_SHOW_STATUS && argc <= 1) {
5718
5719 show_system_status(bus);
5720 new_line = true;
5721
5722 if (arg_all)
5723 ret = show_all(bus, &new_line, &ellipsized);
5724 } else {
5725 _cleanup_free_ char **patterns = NULL;
5726 char **name;
5727
5728 STRV_FOREACH(name, strv_skip(argv, 1)) {
5729 _cleanup_free_ char *path = NULL, *unit = NULL;
5730 uint32_t id;
5731
5732 if (safe_atou32(*name, &id) < 0) {
5733 if (strv_push(&patterns, *name) < 0)
5734 return log_oom();
5735
5736 continue;
5737 } else if (show_mode == SYSTEMCTL_SHOW_PROPERTIES) {
5738 /* Interpret as job id */
5739 if (asprintf(&path, "/org/freedesktop/systemd1/job/%u", id) < 0)
5740 return log_oom();
5741
5742 } else {
5743 /* Interpret as PID */
5744 r = get_unit_dbus_path_by_pid(bus, id, &path);
5745 if (r < 0) {
5746 ret = r;
5747 continue;
5748 }
5749
5750 r = unit_name_from_dbus_path(path, &unit);
5751 if (r < 0)
5752 return log_oom();
5753 }
5754
5755 r = show_one(bus, path, unit, show_mode, &new_line, &ellipsized);
5756 if (r < 0)
5757 return r;
5758 else if (r > 0 && ret == 0)
5759 ret = r;
5760 }
5761
5762 if (!strv_isempty(patterns)) {
5763 _cleanup_strv_free_ char **names = NULL;
5764
5765 r = expand_names(bus, patterns, NULL, &names);
5766 if (r < 0)
5767 return log_error_errno(r, "Failed to expand names: %m");
5768
5769 STRV_FOREACH(name, names) {
5770 _cleanup_free_ char *path;
5771
5772 path = unit_dbus_path_from_name(*name);
5773 if (!path)
5774 return log_oom();
5775
5776 r = show_one(bus, path, *name, show_mode, &new_line, &ellipsized);
5777 if (r < 0)
5778 return r;
5779 if (r > 0 && ret == 0)
5780 ret = r;
5781 }
5782 }
5783 }
5784
5785 if (ellipsized && !arg_quiet)
5786 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
5787
5788 return ret;
5789 }
5790
5791 static int cat(int argc, char *argv[], void *userdata) {
5792 _cleanup_(lookup_paths_free) LookupPaths lp = {};
5793 _cleanup_strv_free_ char **names = NULL;
5794 char **name;
5795 sd_bus *bus;
5796 bool first = true;
5797 int r;
5798
5799 if (arg_transport != BUS_TRANSPORT_LOCAL) {
5800 log_error("Cannot remotely cat units.");
5801 return -EINVAL;
5802 }
5803
5804 r = lookup_paths_init(&lp, arg_scope, 0, arg_root);
5805 if (r < 0)
5806 return log_error_errno(r, "Failed to determine unit paths: %m");
5807
5808 r = acquire_bus(BUS_MANAGER, &bus);
5809 if (r < 0)
5810 return r;
5811
5812 r = expand_names(bus, strv_skip(argv, 1), NULL, &names);
5813 if (r < 0)
5814 return log_error_errno(r, "Failed to expand names: %m");
5815
5816 (void) pager_open(arg_pager_flags);
5817
5818 STRV_FOREACH(name, names) {
5819 _cleanup_free_ char *fragment_path = NULL;
5820 _cleanup_strv_free_ char **dropin_paths = NULL;
5821
5822 r = unit_find_paths(bus, *name, &lp, false, &fragment_path, &dropin_paths);
5823 if (r == -ERFKILL) {
5824 printf("%s# Unit %s is masked%s.\n",
5825 ansi_highlight_magenta(),
5826 *name,
5827 ansi_normal());
5828 continue;
5829 }
5830 if (r == -EKEYREJECTED) {
5831 printf("%s# Unit %s could not be loaded.%s\n",
5832 ansi_highlight_magenta(),
5833 *name,
5834 ansi_normal());
5835 continue;
5836 }
5837 if (r < 0)
5838 return r;
5839 if (r == 0)
5840 return -ENOENT;
5841
5842 if (first)
5843 first = false;
5844 else
5845 puts("");
5846
5847 if (need_daemon_reload(bus, *name) > 0) /* ignore errors (<0), this is informational output */
5848 fprintf(stderr,
5849 "%s# Warning: %s changed on disk, the version systemd has loaded is outdated.\n"
5850 "%s# This output shows the current version of the unit's original fragment and drop-in files.\n"
5851 "%s# If fragments or drop-ins were added or removed, they are not properly reflected in this output.\n"
5852 "%s# Run 'systemctl%s daemon-reload' to reload units.%s\n",
5853 ansi_highlight_red(),
5854 *name,
5855 ansi_highlight_red(),
5856 ansi_highlight_red(),
5857 ansi_highlight_red(),
5858 arg_scope == UNIT_FILE_SYSTEM ? "" : " --user",
5859 ansi_normal());
5860
5861 r = cat_files(fragment_path, dropin_paths, 0);
5862 if (r < 0)
5863 return r;
5864 }
5865
5866 return 0;
5867 }
5868
5869 static int set_property(int argc, char *argv[], void *userdata) {
5870 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
5871 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
5872 _cleanup_free_ char *n = NULL;
5873 UnitType t;
5874 sd_bus *bus;
5875 int r;
5876
5877 r = acquire_bus(BUS_MANAGER, &bus);
5878 if (r < 0)
5879 return r;
5880
5881 polkit_agent_open_maybe();
5882
5883 r = sd_bus_message_new_method_call(
5884 bus,
5885 &m,
5886 "org.freedesktop.systemd1",
5887 "/org/freedesktop/systemd1",
5888 "org.freedesktop.systemd1.Manager",
5889 "SetUnitProperties");
5890 if (r < 0)
5891 return bus_log_create_error(r);
5892
5893 r = unit_name_mangle(argv[1], arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN, &n);
5894 if (r < 0)
5895 return log_error_errno(r, "Failed to mangle unit name: %m");
5896
5897 t = unit_name_to_type(n);
5898 if (t < 0) {
5899 log_error("Invalid unit type: %s", n);
5900 return -EINVAL;
5901 }
5902
5903 r = sd_bus_message_append(m, "sb", n, arg_runtime);
5904 if (r < 0)
5905 return bus_log_create_error(r);
5906
5907 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)");
5908 if (r < 0)
5909 return bus_log_create_error(r);
5910
5911 r = bus_append_unit_property_assignment_many(m, t, strv_skip(argv, 2));
5912 if (r < 0)
5913 return r;
5914
5915 r = sd_bus_message_close_container(m);
5916 if (r < 0)
5917 return bus_log_create_error(r);
5918
5919 r = sd_bus_call(bus, m, 0, &error, NULL);
5920 if (r < 0)
5921 return log_error_errno(r, "Failed to set unit properties on %s: %s", n, bus_error_message(&error, r));
5922
5923 return 0;
5924 }
5925
5926 static int daemon_reload(int argc, char *argv[], void *userdata) {
5927 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
5928 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
5929 const char *method;
5930 sd_bus *bus;
5931 int r;
5932
5933 r = acquire_bus(BUS_MANAGER, &bus);
5934 if (r < 0)
5935 return r;
5936
5937 polkit_agent_open_maybe();
5938
5939 switch (arg_action) {
5940
5941 case ACTION_RELOAD:
5942 method = "Reload";
5943 break;
5944
5945 case ACTION_REEXEC:
5946 method = "Reexecute";
5947 break;
5948
5949 case ACTION_SYSTEMCTL:
5950 method = streq(argv[0], "daemon-reexec") ? "Reexecute" :
5951 /* "daemon-reload" */ "Reload";
5952 break;
5953
5954 default:
5955 assert_not_reached("Unexpected action");
5956 }
5957
5958 r = sd_bus_message_new_method_call(
5959 bus,
5960 &m,
5961 "org.freedesktop.systemd1",
5962 "/org/freedesktop/systemd1",
5963 "org.freedesktop.systemd1.Manager",
5964 method);
5965 if (r < 0)
5966 return bus_log_create_error(r);
5967
5968 /* Note we use an extra-long timeout here. This is because a reload or reexec means generators are rerun which
5969 * are timed out after DEFAULT_TIMEOUT_USEC. Let's use twice that time here, so that the generators can have
5970 * their timeout, and for everything else there's the same time budget in place. */
5971
5972 r = sd_bus_call(bus, m, DEFAULT_TIMEOUT_USEC * 2, &error, NULL);
5973
5974 /* On reexecution, we expect a disconnect, not a reply */
5975 if (IN_SET(r, -ETIMEDOUT, -ECONNRESET) && streq(method, "Reexecute"))
5976 r = 0;
5977
5978 if (r < 0 && arg_action == ACTION_SYSTEMCTL)
5979 return log_error_errno(r, "Failed to reload daemon: %s", bus_error_message(&error, r));
5980
5981 /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
5982 * old ways of doing things, hence don't log any error in that case here. */
5983
5984 return r < 0 ? r : 0;
5985 }
5986
5987 static int trivial_method(int argc, char *argv[], void *userdata) {
5988 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
5989 const char *method;
5990 sd_bus *bus;
5991 int r;
5992
5993 if (arg_dry_run)
5994 return 0;
5995
5996 r = acquire_bus(BUS_MANAGER, &bus);
5997 if (r < 0)
5998 return r;
5999
6000 polkit_agent_open_maybe();
6001
6002 method =
6003 streq(argv[0], "clear-jobs") ||
6004 streq(argv[0], "cancel") ? "ClearJobs" :
6005 streq(argv[0], "reset-failed") ? "ResetFailed" :
6006 streq(argv[0], "halt") ? "Halt" :
6007 streq(argv[0], "reboot") ? "Reboot" :
6008 streq(argv[0], "kexec") ? "KExec" :
6009 streq(argv[0], "exit") ? "Exit" :
6010 /* poweroff */ "PowerOff";
6011
6012 r = sd_bus_call_method(
6013 bus,
6014 "org.freedesktop.systemd1",
6015 "/org/freedesktop/systemd1",
6016 "org.freedesktop.systemd1.Manager",
6017 method,
6018 &error,
6019 NULL,
6020 NULL);
6021 if (r < 0 && arg_action == ACTION_SYSTEMCTL)
6022 return log_error_errno(r, "Failed to execute operation: %s", bus_error_message(&error, r));
6023
6024 /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
6025 * old ways of doing things, hence don't log any error in that case here. */
6026
6027 return r < 0 ? r : 0;
6028 }
6029
6030 static int reset_failed(int argc, char *argv[], void *userdata) {
6031 _cleanup_strv_free_ char **names = NULL;
6032 sd_bus *bus;
6033 char **name;
6034 int r, q;
6035
6036 if (argc <= 1)
6037 return trivial_method(argc, argv, userdata);
6038
6039 r = acquire_bus(BUS_MANAGER, &bus);
6040 if (r < 0)
6041 return r;
6042
6043 polkit_agent_open_maybe();
6044
6045 r = expand_names(bus, strv_skip(argv, 1), NULL, &names);
6046 if (r < 0)
6047 return log_error_errno(r, "Failed to expand names: %m");
6048
6049 STRV_FOREACH(name, names) {
6050 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
6051
6052 q = sd_bus_call_method(
6053 bus,
6054 "org.freedesktop.systemd1",
6055 "/org/freedesktop/systemd1",
6056 "org.freedesktop.systemd1.Manager",
6057 "ResetFailedUnit",
6058 &error,
6059 NULL,
6060 "s", *name);
6061 if (q < 0) {
6062 log_error_errno(q, "Failed to reset failed state of unit %s: %s", *name, bus_error_message(&error, q));
6063 if (r == 0)
6064 r = q;
6065 }
6066 }
6067
6068 return r;
6069 }
6070
6071 static int print_variable(const char *s) {
6072 const char *sep;
6073 _cleanup_free_ char *esc = NULL;
6074
6075 sep = strchr(s, '=');
6076 if (!sep)
6077 return log_error_errno(SYNTHETIC_ERRNO(EUCLEAN),
6078 "Invalid environment block");
6079
6080 esc = shell_maybe_quote(sep + 1, ESCAPE_POSIX);
6081 if (!esc)
6082 return log_oom();
6083
6084 printf("%.*s=%s\n", (int)(sep-s), s, esc);
6085 return 0;
6086 }
6087
6088 static int show_environment(int argc, char *argv[], void *userdata) {
6089 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
6090 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
6091 const char *text;
6092 sd_bus *bus;
6093 int r;
6094
6095 r = acquire_bus(BUS_MANAGER, &bus);
6096 if (r < 0)
6097 return r;
6098
6099 (void) pager_open(arg_pager_flags);
6100
6101 r = sd_bus_get_property(
6102 bus,
6103 "org.freedesktop.systemd1",
6104 "/org/freedesktop/systemd1",
6105 "org.freedesktop.systemd1.Manager",
6106 "Environment",
6107 &error,
6108 &reply,
6109 "as");
6110 if (r < 0)
6111 return log_error_errno(r, "Failed to get environment: %s", bus_error_message(&error, r));
6112
6113 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
6114 if (r < 0)
6115 return bus_log_parse_error(r);
6116
6117 while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0) {
6118 r = print_variable(text);
6119 if (r < 0)
6120 return r;
6121 }
6122 if (r < 0)
6123 return bus_log_parse_error(r);
6124
6125 r = sd_bus_message_exit_container(reply);
6126 if (r < 0)
6127 return bus_log_parse_error(r);
6128
6129 return 0;
6130 }
6131
6132 static int switch_root(int argc, char *argv[], void *userdata) {
6133 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
6134 _cleanup_free_ char *cmdline_init = NULL;
6135 const char *root, *init;
6136 sd_bus *bus;
6137 int r;
6138
6139 if (arg_transport != BUS_TRANSPORT_LOCAL) {
6140 log_error("Cannot switch root remotely.");
6141 return -EINVAL;
6142 }
6143
6144 if (argc < 2 || argc > 3) {
6145 log_error("Wrong number of arguments.");
6146 return -EINVAL;
6147 }
6148
6149 root = argv[1];
6150
6151 if (argc >= 3)
6152 init = argv[2];
6153 else {
6154 r = proc_cmdline_get_key("init", 0, &cmdline_init);
6155 if (r < 0)
6156 log_debug_errno(r, "Failed to parse /proc/cmdline: %m");
6157
6158 init = cmdline_init;
6159 }
6160
6161 init = empty_to_null(init);
6162 if (init) {
6163 const char *root_systemd_path = NULL, *root_init_path = NULL;
6164
6165 root_systemd_path = strjoina(root, "/" SYSTEMD_BINARY_PATH);
6166 root_init_path = strjoina(root, "/", init);
6167
6168 /* If the passed init is actually the same as the
6169 * systemd binary, then let's suppress it. */
6170 if (files_same(root_init_path, root_systemd_path, 0) > 0)
6171 init = NULL;
6172 }
6173
6174 /* Instruct PID1 to exclude us from its killing spree applied during
6175 * the transition. Otherwise we would exit with a failure status even
6176 * though the switch to the new root has succeed. */
6177 argv_cmdline[0] = '@';
6178
6179 r = acquire_bus(BUS_MANAGER, &bus);
6180 if (r < 0)
6181 return r;
6182
6183 /* If we are slow to exit after the root switch, the new systemd instance
6184 * will send us a signal to terminate. Just ignore it and exit normally.
6185 * This way the unit does not end up as failed.
6186 */
6187 r = ignore_signals(SIGTERM, -1);
6188 if (r < 0)
6189 log_warning_errno(r, "Failed to change disposition of SIGTERM to ignore: %m");
6190
6191 log_debug("Switching root - root: %s; init: %s", root, strna(init));
6192
6193 r = sd_bus_call_method(
6194 bus,
6195 "org.freedesktop.systemd1",
6196 "/org/freedesktop/systemd1",
6197 "org.freedesktop.systemd1.Manager",
6198 "SwitchRoot",
6199 &error,
6200 NULL,
6201 "ss", root, init);
6202 if (r < 0) {
6203 (void) default_signals(SIGTERM, -1);
6204
6205 return log_error_errno(r, "Failed to switch root: %s", bus_error_message(&error, r));
6206 }
6207
6208 return 0;
6209 }
6210
6211 static int set_environment(int argc, char *argv[], void *userdata) {
6212 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
6213 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
6214 const char *method;
6215 sd_bus *bus;
6216 int r;
6217
6218 assert(argc > 1);
6219 assert(argv);
6220
6221 r = acquire_bus(BUS_MANAGER, &bus);
6222 if (r < 0)
6223 return r;
6224
6225 polkit_agent_open_maybe();
6226
6227 method = streq(argv[0], "set-environment")
6228 ? "SetEnvironment"
6229 : "UnsetEnvironment";
6230
6231 r = sd_bus_message_new_method_call(
6232 bus,
6233 &m,
6234 "org.freedesktop.systemd1",
6235 "/org/freedesktop/systemd1",
6236 "org.freedesktop.systemd1.Manager",
6237 method);
6238 if (r < 0)
6239 return bus_log_create_error(r);
6240
6241 r = sd_bus_message_append_strv(m, strv_skip(argv, 1));
6242 if (r < 0)
6243 return bus_log_create_error(r);
6244
6245 r = sd_bus_call(bus, m, 0, &error, NULL);
6246 if (r < 0)
6247 return log_error_errno(r, "Failed to set environment: %s", bus_error_message(&error, r));
6248
6249 return 0;
6250 }
6251
6252 static int import_environment(int argc, char *argv[], void *userdata) {
6253 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
6254 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
6255 sd_bus *bus;
6256 int r;
6257
6258 r = acquire_bus(BUS_MANAGER, &bus);
6259 if (r < 0)
6260 return r;
6261
6262 polkit_agent_open_maybe();
6263
6264 r = sd_bus_message_new_method_call(
6265 bus,
6266 &m,
6267 "org.freedesktop.systemd1",
6268 "/org/freedesktop/systemd1",
6269 "org.freedesktop.systemd1.Manager",
6270 "SetEnvironment");
6271 if (r < 0)
6272 return bus_log_create_error(r);
6273
6274 if (argc < 2)
6275 r = sd_bus_message_append_strv(m, environ);
6276 else {
6277 char **a, **b;
6278
6279 r = sd_bus_message_open_container(m, 'a', "s");
6280 if (r < 0)
6281 return bus_log_create_error(r);
6282
6283 STRV_FOREACH(a, strv_skip(argv, 1)) {
6284
6285 if (!env_name_is_valid(*a)) {
6286 log_error("Not a valid environment variable name: %s", *a);
6287 return -EINVAL;
6288 }
6289
6290 STRV_FOREACH(b, environ) {
6291 const char *eq;
6292
6293 eq = startswith(*b, *a);
6294 if (eq && *eq == '=') {
6295
6296 r = sd_bus_message_append(m, "s", *b);
6297 if (r < 0)
6298 return bus_log_create_error(r);
6299
6300 break;
6301 }
6302 }
6303 }
6304
6305 r = sd_bus_message_close_container(m);
6306 }
6307 if (r < 0)
6308 return bus_log_create_error(r);
6309
6310 r = sd_bus_call(bus, m, 0, &error, NULL);
6311 if (r < 0)
6312 return log_error_errno(r, "Failed to import environment: %s", bus_error_message(&error, r));
6313
6314 return 0;
6315 }
6316
6317 static int enable_sysv_units(const char *verb, char **args) {
6318 int r = 0;
6319
6320 #if HAVE_SYSV_COMPAT
6321 _cleanup_(lookup_paths_free) LookupPaths paths = {};
6322 unsigned f = 0;
6323
6324 /* Processes all SysV units, and reshuffles the array so that afterwards only the native units remain */
6325
6326 if (arg_scope != UNIT_FILE_SYSTEM)
6327 return 0;
6328
6329 if (getenv_bool("SYSTEMCTL_SKIP_SYSV") > 0)
6330 return 0;
6331
6332 if (!STR_IN_SET(verb,
6333 "enable",
6334 "disable",
6335 "is-enabled"))
6336 return 0;
6337
6338 r = lookup_paths_init(&paths, arg_scope, LOOKUP_PATHS_EXCLUDE_GENERATED, arg_root);
6339 if (r < 0)
6340 return r;
6341
6342 r = 0;
6343 while (args[f]) {
6344
6345 const char *argv[] = {
6346 ROOTLIBEXECDIR "/systemd-sysv-install",
6347 NULL,
6348 NULL,
6349 NULL,
6350 NULL,
6351 };
6352
6353 _cleanup_free_ char *p = NULL, *q = NULL, *l = NULL;
6354 bool found_native = false, found_sysv;
6355 const char *name;
6356 unsigned c = 1;
6357 pid_t pid;
6358 int j;
6359
6360 name = args[f++];
6361
6362 if (!endswith(name, ".service"))
6363 continue;
6364
6365 if (path_is_absolute(name))
6366 continue;
6367
6368 j = unit_file_exists(arg_scope, &paths, name);
6369 if (j < 0 && !IN_SET(j, -ELOOP, -ERFKILL, -EADDRNOTAVAIL))
6370 return log_error_errno(j, "Failed to lookup unit file state: %m");
6371 found_native = j != 0;
6372
6373 /* If we have both a native unit and a SysV script, enable/disable them both (below); for is-enabled,
6374 * prefer the native unit */
6375 if (found_native && streq(verb, "is-enabled"))
6376 continue;
6377
6378 p = path_join(arg_root, SYSTEM_SYSVINIT_PATH, name);
6379 if (!p)
6380 return log_oom();
6381
6382 p[strlen(p) - STRLEN(".service")] = 0;
6383 found_sysv = access(p, F_OK) >= 0;
6384 if (!found_sysv)
6385 continue;
6386
6387 if (!arg_quiet) {
6388 if (found_native)
6389 log_info("Synchronizing state of %s with SysV service script with %s.", name, argv[0]);
6390 else
6391 log_info("%s is not a native service, redirecting to systemd-sysv-install.", name);
6392 }
6393
6394 if (!isempty(arg_root))
6395 argv[c++] = q = strappend("--root=", arg_root);
6396
6397 argv[c++] = verb;
6398 argv[c++] = basename(p);
6399 argv[c] = NULL;
6400
6401 l = strv_join((char**)argv, " ");
6402 if (!l)
6403 return log_oom();
6404
6405 if (!arg_quiet)
6406 log_info("Executing: %s", l);
6407
6408 j = safe_fork("(sysv-install)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
6409 if (j < 0)
6410 return j;
6411 if (j == 0) {
6412 /* Child */
6413 execv(argv[0], (char**) argv);
6414 log_error_errno(errno, "Failed to execute %s: %m", argv[0]);
6415 _exit(EXIT_FAILURE);
6416 }
6417
6418 j = wait_for_terminate_and_check("sysv-install", pid, WAIT_LOG_ABNORMAL);
6419 if (j < 0)
6420 return j;
6421 if (streq(verb, "is-enabled")) {
6422 if (j == EXIT_SUCCESS) {
6423 if (!arg_quiet)
6424 puts("enabled");
6425 r = 1;
6426 } else {
6427 if (!arg_quiet)
6428 puts("disabled");
6429 }
6430
6431 } else if (j != EXIT_SUCCESS)
6432 return -EBADE; /* We don't warn here, under the assumption the script already showed an explanation */
6433
6434 if (found_native)
6435 continue;
6436
6437 /* Remove this entry, so that we don't try enabling it as native unit */
6438 assert(f > 0);
6439 f--;
6440 assert(args[f] == name);
6441 strv_remove(args, name);
6442 }
6443
6444 #endif
6445 return r;
6446 }
6447
6448 static int mangle_names(char **original_names, char ***mangled_names) {
6449 char **i, **l, **name;
6450 int r;
6451
6452 l = i = new(char*, strv_length(original_names) + 1);
6453 if (!l)
6454 return log_oom();
6455
6456 STRV_FOREACH(name, original_names) {
6457
6458 /* When enabling units qualified path names are OK,
6459 * too, hence allow them explicitly. */
6460
6461 if (is_path(*name)) {
6462 *i = strdup(*name);
6463 if (!*i) {
6464 strv_free(l);
6465 return log_oom();
6466 }
6467 } else {
6468 r = unit_name_mangle(*name, arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN, i);
6469 if (r < 0) {
6470 *i = NULL;
6471 strv_free(l);
6472 return log_error_errno(r, "Failed to mangle unit name: %m");
6473 }
6474 }
6475
6476 i++;
6477 }
6478
6479 *i = NULL;
6480 *mangled_names = l;
6481
6482 return 0;
6483 }
6484
6485 static int normalize_filenames(char **names) {
6486 char **u;
6487 int r;
6488
6489 STRV_FOREACH(u, names)
6490 if (!path_is_absolute(*u)) {
6491 char* normalized_path;
6492
6493 if (!isempty(arg_root))
6494 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
6495 "Non-absolute paths are not allowed when --root is used: %s",
6496 *u);
6497
6498 if (!strchr(*u,'/'))
6499 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
6500 "Link argument does contain at least one directory separator: %s",
6501 *u);
6502
6503 r = path_make_absolute_cwd(*u, &normalized_path);
6504 if (r < 0)
6505 return r;
6506
6507 free_and_replace(*u, normalized_path);
6508 }
6509
6510 return 0;
6511 }
6512
6513 static int normalize_names(char **names, bool warn_if_path) {
6514 char **u;
6515 bool was_path = false;
6516
6517 STRV_FOREACH(u, names) {
6518 int r;
6519
6520 if (!is_path(*u))
6521 continue;
6522
6523 r = free_and_strdup(u, basename(*u));
6524 if (r < 0)
6525 return log_error_errno(r, "Failed to normalize unit file path: %m");
6526
6527 was_path = true;
6528 }
6529
6530 if (warn_if_path && was_path)
6531 log_warning("Warning: Can't execute disable on the unit file path. Proceeding with the unit name.");
6532
6533 return 0;
6534 }
6535
6536 static int unit_exists(LookupPaths *lp, const char *unit) {
6537 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
6538 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
6539 _cleanup_free_ char *path = NULL;
6540 static const struct bus_properties_map property_map[] = {
6541 { "LoadState", "s", NULL, offsetof(UnitStatusInfo, load_state) },
6542 { "ActiveState", "s", NULL, offsetof(UnitStatusInfo, active_state)},
6543 {},
6544 };
6545 UnitStatusInfo info = {};
6546 sd_bus *bus;
6547 int r;
6548
6549 if (unit_name_is_valid(unit, UNIT_NAME_TEMPLATE))
6550 return unit_find_template_path(unit, lp, NULL, NULL);
6551
6552 path = unit_dbus_path_from_name(unit);
6553 if (!path)
6554 return log_oom();
6555
6556 r = acquire_bus(BUS_MANAGER, &bus);
6557 if (r < 0)
6558 return r;
6559
6560 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", path, property_map, 0, &error, &m, &info);
6561 if (r < 0)
6562 return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r));
6563
6564 return !streq_ptr(info.load_state, "not-found") || !streq_ptr(info.active_state, "inactive");
6565 }
6566
6567 static int enable_unit(int argc, char *argv[], void *userdata) {
6568 _cleanup_strv_free_ char **names = NULL;
6569 const char *verb = argv[0];
6570 UnitFileChange *changes = NULL;
6571 size_t n_changes = 0;
6572 int carries_install_info = -1;
6573 bool ignore_carries_install_info = arg_quiet;
6574 int r;
6575
6576 if (!argv[1])
6577 return 0;
6578
6579 r = mangle_names(strv_skip(argv, 1), &names);
6580 if (r < 0)
6581 return r;
6582
6583 r = enable_sysv_units(verb, names);
6584 if (r < 0)
6585 return r;
6586
6587 /* If the operation was fully executed by the SysV compat, let's finish early */
6588 if (strv_isempty(names)) {
6589 if (arg_no_reload || install_client_side())
6590 return 0;
6591 return daemon_reload(argc, argv, userdata);
6592 }
6593
6594 if (streq(verb, "disable")) {
6595 r = normalize_names(names, true);
6596 if (r < 0)
6597 return r;
6598 }
6599
6600 if (streq(verb, "link")) {
6601 r = normalize_filenames(names);
6602 if (r < 0)
6603 return r;
6604 }
6605
6606 if (install_client_side()) {
6607 UnitFileFlags flags;
6608
6609 flags = args_to_flags();
6610 if (streq(verb, "enable")) {
6611 r = unit_file_enable(arg_scope, flags, arg_root, names, &changes, &n_changes);
6612 carries_install_info = r;
6613 } else if (streq(verb, "disable"))
6614 r = unit_file_disable(arg_scope, flags, arg_root, names, &changes, &n_changes);
6615 else if (streq(verb, "reenable")) {
6616 r = unit_file_reenable(arg_scope, flags, arg_root, names, &changes, &n_changes);
6617 carries_install_info = r;
6618 } else if (streq(verb, "link"))
6619 r = unit_file_link(arg_scope, flags, arg_root, names, &changes, &n_changes);
6620 else if (streq(verb, "preset")) {
6621 r = unit_file_preset(arg_scope, flags, arg_root, names, arg_preset_mode, &changes, &n_changes);
6622 } else if (streq(verb, "mask"))
6623 r = unit_file_mask(arg_scope, flags, arg_root, names, &changes, &n_changes);
6624 else if (streq(verb, "unmask"))
6625 r = unit_file_unmask(arg_scope, flags, arg_root, names, &changes, &n_changes);
6626 else if (streq(verb, "revert"))
6627 r = unit_file_revert(arg_scope, arg_root, names, &changes, &n_changes);
6628 else
6629 assert_not_reached("Unknown verb");
6630
6631 unit_file_dump_changes(r, verb, changes, n_changes, arg_quiet);
6632 if (r < 0)
6633 goto finish;
6634 r = 0;
6635 } else {
6636 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
6637 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
6638 bool expect_carries_install_info = false;
6639 bool send_runtime = true, send_force = true, send_preset_mode = false;
6640 const char *method;
6641 sd_bus *bus;
6642
6643 if (STR_IN_SET(verb, "mask", "unmask")) {
6644 char **name;
6645 _cleanup_(lookup_paths_free) LookupPaths lp = {};
6646
6647 r = lookup_paths_init(&lp, arg_scope, 0, arg_root);
6648 if (r < 0)
6649 return r;
6650
6651 STRV_FOREACH(name, names) {
6652 r = unit_exists(&lp, *name);
6653 if (r < 0)
6654 return r;
6655 if (r == 0)
6656 log_notice("Unit %s does not exist, proceeding anyway.", *name);
6657 }
6658 }
6659
6660 r = acquire_bus(BUS_MANAGER, &bus);
6661 if (r < 0)
6662 return r;
6663
6664 polkit_agent_open_maybe();
6665
6666 if (streq(verb, "enable")) {
6667 method = "EnableUnitFiles";
6668 expect_carries_install_info = true;
6669 } else if (streq(verb, "disable")) {
6670 method = "DisableUnitFiles";
6671 send_force = false;
6672 } else if (streq(verb, "reenable")) {
6673 method = "ReenableUnitFiles";
6674 expect_carries_install_info = true;
6675 } else if (streq(verb, "link"))
6676 method = "LinkUnitFiles";
6677 else if (streq(verb, "preset")) {
6678
6679 if (arg_preset_mode != UNIT_FILE_PRESET_FULL) {
6680 method = "PresetUnitFilesWithMode";
6681 send_preset_mode = true;
6682 } else
6683 method = "PresetUnitFiles";
6684
6685 expect_carries_install_info = true;
6686 ignore_carries_install_info = true;
6687 } else if (streq(verb, "mask"))
6688 method = "MaskUnitFiles";
6689 else if (streq(verb, "unmask")) {
6690 method = "UnmaskUnitFiles";
6691 send_force = false;
6692 } else if (streq(verb, "revert")) {
6693 method = "RevertUnitFiles";
6694 send_runtime = send_force = false;
6695 } else
6696 assert_not_reached("Unknown verb");
6697
6698 r = sd_bus_message_new_method_call(
6699 bus,
6700 &m,
6701 "org.freedesktop.systemd1",
6702 "/org/freedesktop/systemd1",
6703 "org.freedesktop.systemd1.Manager",
6704 method);
6705 if (r < 0)
6706 return bus_log_create_error(r);
6707
6708 r = sd_bus_message_append_strv(m, names);
6709 if (r < 0)
6710 return bus_log_create_error(r);
6711
6712 if (send_preset_mode) {
6713 r = sd_bus_message_append(m, "s", unit_file_preset_mode_to_string(arg_preset_mode));
6714 if (r < 0)
6715 return bus_log_create_error(r);
6716 }
6717
6718 if (send_runtime) {
6719 r = sd_bus_message_append(m, "b", arg_runtime);
6720 if (r < 0)
6721 return bus_log_create_error(r);
6722 }
6723
6724 if (send_force) {
6725 r = sd_bus_message_append(m, "b", arg_force);
6726 if (r < 0)
6727 return bus_log_create_error(r);
6728 }
6729
6730 r = sd_bus_call(bus, m, 0, &error, &reply);
6731 if (r < 0)
6732 return log_error_errno(r, "Failed to %s unit: %s", verb, bus_error_message(&error, r));
6733
6734 if (expect_carries_install_info) {
6735 r = sd_bus_message_read(reply, "b", &carries_install_info);
6736 if (r < 0)
6737 return bus_log_parse_error(r);
6738 }
6739
6740 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, &changes, &n_changes);
6741 if (r < 0)
6742 goto finish;
6743
6744 /* Try to reload if enabled */
6745 if (!arg_no_reload)
6746 r = daemon_reload(argc, argv, userdata);
6747 else
6748 r = 0;
6749 }
6750
6751 if (carries_install_info == 0 && !ignore_carries_install_info)
6752 log_notice("The unit files have no installation config (WantedBy=, RequiredBy=, Also=,\n"
6753 "Alias= settings in the [Install] section, and DefaultInstance= for template\n"
6754 "units). This means they are not meant to be enabled using systemctl.\n"
6755 " \n" /* trick: the space is needed so that the line does not get stripped from output */
6756 "Possible reasons for having this kind of units are:\n"
6757 "%1$s A unit may be statically enabled by being symlinked from another unit's\n"
6758 " .wants/ or .requires/ directory.\n"
6759 "%1$s A unit's purpose may be to act as a helper for some other unit which has\n"
6760 " a requirement dependency on it.\n"
6761 "%1$s A unit may be started when needed via activation (socket, path, timer,\n"
6762 " D-Bus, udev, scripted systemctl call, ...).\n"
6763 "%1$s In case of template units, the unit is meant to be enabled with some\n"
6764 " instance name specified.",
6765 special_glyph(SPECIAL_GLYPH_BULLET));
6766
6767 if (arg_now && STR_IN_SET(argv[0], "enable", "disable", "mask")) {
6768 sd_bus *bus;
6769 size_t len, i;
6770
6771 r = acquire_bus(BUS_MANAGER, &bus);
6772 if (r < 0)
6773 goto finish;
6774
6775 len = strv_length(names);
6776 {
6777 char *new_args[len + 2];
6778
6779 new_args[0] = (char*) (streq(argv[0], "enable") ? "start" : "stop");
6780 for (i = 0; i < len; i++)
6781 new_args[i + 1] = basename(names[i]);
6782 new_args[i + 1] = NULL;
6783
6784 r = start_unit(len + 1, new_args, userdata);
6785 }
6786 }
6787
6788 finish:
6789 unit_file_changes_free(changes, n_changes);
6790
6791 return r;
6792 }
6793
6794 static int add_dependency(int argc, char *argv[], void *userdata) {
6795 _cleanup_strv_free_ char **names = NULL;
6796 _cleanup_free_ char *target = NULL;
6797 const char *verb = argv[0];
6798 UnitFileChange *changes = NULL;
6799 size_t n_changes = 0;
6800 UnitDependency dep;
6801 int r = 0;
6802
6803 if (!argv[1])
6804 return 0;
6805
6806 r = unit_name_mangle_with_suffix(argv[1], arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN, ".target", &target);
6807 if (r < 0)
6808 return log_error_errno(r, "Failed to mangle unit name: %m");
6809
6810 r = mangle_names(strv_skip(argv, 2), &names);
6811 if (r < 0)
6812 return r;
6813
6814 if (streq(verb, "add-wants"))
6815 dep = UNIT_WANTS;
6816 else if (streq(verb, "add-requires"))
6817 dep = UNIT_REQUIRES;
6818 else
6819 assert_not_reached("Unknown verb");
6820
6821 if (install_client_side()) {
6822 r = unit_file_add_dependency(arg_scope, args_to_flags(), arg_root, names, target, dep, &changes, &n_changes);
6823 unit_file_dump_changes(r, "add dependency on", changes, n_changes, arg_quiet);
6824
6825 if (r > 0)
6826 r = 0;
6827 } else {
6828 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
6829 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
6830 sd_bus *bus;
6831
6832 r = acquire_bus(BUS_MANAGER, &bus);
6833 if (r < 0)
6834 return r;
6835
6836 polkit_agent_open_maybe();
6837
6838 r = sd_bus_message_new_method_call(
6839 bus,
6840 &m,
6841 "org.freedesktop.systemd1",
6842 "/org/freedesktop/systemd1",
6843 "org.freedesktop.systemd1.Manager",
6844 "AddDependencyUnitFiles");
6845 if (r < 0)
6846 return bus_log_create_error(r);
6847
6848 r = sd_bus_message_append_strv(m, names);
6849 if (r < 0)
6850 return bus_log_create_error(r);
6851
6852 r = sd_bus_message_append(m, "ssbb", target, unit_dependency_to_string(dep), arg_runtime, arg_force);
6853 if (r < 0)
6854 return bus_log_create_error(r);
6855
6856 r = sd_bus_call(bus, m, 0, &error, &reply);
6857 if (r < 0)
6858 return log_error_errno(r, "Failed to add dependency: %s", bus_error_message(&error, r));
6859
6860 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, &changes, &n_changes);
6861 if (r < 0)
6862 goto finish;
6863
6864 if (arg_no_reload) {
6865 r = 0;
6866 goto finish;
6867 }
6868
6869 r = daemon_reload(argc, argv, userdata);
6870 }
6871
6872 finish:
6873 unit_file_changes_free(changes, n_changes);
6874
6875 return r;
6876 }
6877
6878 static int preset_all(int argc, char *argv[], void *userdata) {
6879 UnitFileChange *changes = NULL;
6880 size_t n_changes = 0;
6881 int r;
6882
6883 if (install_client_side()) {
6884 r = unit_file_preset_all(arg_scope, args_to_flags(), arg_root, arg_preset_mode, &changes, &n_changes);
6885 unit_file_dump_changes(r, "preset", changes, n_changes, arg_quiet);
6886
6887 if (r > 0)
6888 r = 0;
6889 } else {
6890 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
6891 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
6892 sd_bus *bus;
6893
6894 r = acquire_bus(BUS_MANAGER, &bus);
6895 if (r < 0)
6896 return r;
6897
6898 polkit_agent_open_maybe();
6899
6900 r = sd_bus_call_method(
6901 bus,
6902 "org.freedesktop.systemd1",
6903 "/org/freedesktop/systemd1",
6904 "org.freedesktop.systemd1.Manager",
6905 "PresetAllUnitFiles",
6906 &error,
6907 &reply,
6908 "sbb",
6909 unit_file_preset_mode_to_string(arg_preset_mode),
6910 arg_runtime,
6911 arg_force);
6912 if (r < 0)
6913 return log_error_errno(r, "Failed to preset all units: %s", bus_error_message(&error, r));
6914
6915 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, &changes, &n_changes);
6916 if (r < 0)
6917 goto finish;
6918
6919 if (arg_no_reload) {
6920 r = 0;
6921 goto finish;
6922 }
6923
6924 r = daemon_reload(argc, argv, userdata);
6925 }
6926
6927 finish:
6928 unit_file_changes_free(changes, n_changes);
6929
6930 return r;
6931 }
6932
6933 static int show_installation_targets_client_side(const char *name) {
6934 UnitFileChange *changes = NULL;
6935 size_t n_changes = 0, i;
6936 UnitFileFlags flags;
6937 char **p;
6938 int r;
6939
6940 p = STRV_MAKE(name);
6941 flags = UNIT_FILE_DRY_RUN |
6942 (arg_runtime ? UNIT_FILE_RUNTIME : 0);
6943
6944 r = unit_file_disable(UNIT_FILE_SYSTEM, flags, NULL, p, &changes, &n_changes);
6945 if (r < 0)
6946 return log_error_errno(r, "Failed to get file links for %s: %m", name);
6947
6948 for (i = 0; i < n_changes; i++)
6949 if (changes[i].type == UNIT_FILE_UNLINK)
6950 printf(" %s\n", changes[i].path);
6951
6952 return 0;
6953 }
6954
6955 static int show_installation_targets(sd_bus *bus, const char *name) {
6956 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
6957 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
6958 const char *link;
6959 int r;
6960
6961 r = sd_bus_call_method(
6962 bus,
6963 "org.freedesktop.systemd1",
6964 "/org/freedesktop/systemd1",
6965 "org.freedesktop.systemd1.Manager",
6966 "GetUnitFileLinks",
6967 &error,
6968 &reply,
6969 "sb", name, arg_runtime);
6970 if (r < 0)
6971 return log_error_errno(r, "Failed to get unit file links for %s: %s", name, bus_error_message(&error, r));
6972
6973 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
6974 if (r < 0)
6975 return bus_log_parse_error(r);
6976
6977 while ((r = sd_bus_message_read(reply, "s", &link)) > 0)
6978 printf(" %s\n", link);
6979
6980 if (r < 0)
6981 return bus_log_parse_error(r);
6982
6983 r = sd_bus_message_exit_container(reply);
6984 if (r < 0)
6985 return bus_log_parse_error(r);
6986
6987 return 0;
6988 }
6989
6990 static int unit_is_enabled(int argc, char *argv[], void *userdata) {
6991 _cleanup_strv_free_ char **names = NULL;
6992 bool enabled;
6993 char **name;
6994 int r;
6995
6996 r = mangle_names(strv_skip(argv, 1), &names);
6997 if (r < 0)
6998 return r;
6999
7000 r = enable_sysv_units(argv[0], names);
7001 if (r < 0)
7002 return r;
7003
7004 enabled = r > 0;
7005
7006 if (install_client_side()) {
7007 STRV_FOREACH(name, names) {
7008 UnitFileState state;
7009
7010 r = unit_file_get_state(arg_scope, arg_root, *name, &state);
7011 if (r < 0)
7012 return log_error_errno(r, "Failed to get unit file state for %s: %m", *name);
7013
7014 if (IN_SET(state,
7015 UNIT_FILE_ENABLED,
7016 UNIT_FILE_ENABLED_RUNTIME,
7017 UNIT_FILE_STATIC,
7018 UNIT_FILE_INDIRECT,
7019 UNIT_FILE_GENERATED))
7020 enabled = true;
7021
7022 if (!arg_quiet) {
7023 puts(unit_file_state_to_string(state));
7024 if (arg_full) {
7025 r = show_installation_targets_client_side(*name);
7026 if (r < 0)
7027 return r;
7028 }
7029 }
7030 }
7031
7032 r = 0;
7033 } else {
7034 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
7035 sd_bus *bus;
7036
7037 r = acquire_bus(BUS_MANAGER, &bus);
7038 if (r < 0)
7039 return r;
7040
7041 STRV_FOREACH(name, names) {
7042 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
7043 const char *s;
7044
7045 r = sd_bus_call_method(
7046 bus,
7047 "org.freedesktop.systemd1",
7048 "/org/freedesktop/systemd1",
7049 "org.freedesktop.systemd1.Manager",
7050 "GetUnitFileState",
7051 &error,
7052 &reply,
7053 "s", *name);
7054 if (r < 0)
7055 return log_error_errno(r, "Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
7056
7057 r = sd_bus_message_read(reply, "s", &s);
7058 if (r < 0)
7059 return bus_log_parse_error(r);
7060
7061 if (STR_IN_SET(s, "enabled", "enabled-runtime", "static", "indirect", "generated"))
7062 enabled = true;
7063
7064 if (!arg_quiet) {
7065 puts(s);
7066 if (arg_full) {
7067 r = show_installation_targets(bus, *name);
7068 if (r < 0)
7069 return r;
7070 }
7071 }
7072 }
7073 }
7074
7075 return enabled ? EXIT_SUCCESS : EXIT_FAILURE;
7076 }
7077
7078 static int match_startup_finished(sd_bus_message *m, void *userdata, sd_bus_error *error) {
7079 char **state = userdata;
7080 int r;
7081
7082 assert(state);
7083
7084 r = sd_bus_get_property_string(
7085 sd_bus_message_get_bus(m),
7086 "org.freedesktop.systemd1",
7087 "/org/freedesktop/systemd1",
7088 "org.freedesktop.systemd1.Manager",
7089 "SystemState",
7090 NULL,
7091 state);
7092
7093 sd_event_exit(sd_bus_get_event(sd_bus_message_get_bus(m)), r);
7094 return 0;
7095 }
7096
7097 static int is_system_running(int argc, char *argv[], void *userdata) {
7098 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
7099 _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot_startup_finished = NULL;
7100 _cleanup_(sd_event_unrefp) sd_event* event = NULL;
7101 _cleanup_free_ char *state = NULL;
7102 sd_bus *bus;
7103 int r;
7104
7105 if (running_in_chroot() > 0 || (arg_transport == BUS_TRANSPORT_LOCAL && !sd_booted())) {
7106 if (!arg_quiet)
7107 puts("offline");
7108 return EXIT_FAILURE;
7109 }
7110
7111 r = acquire_bus(BUS_MANAGER, &bus);
7112 if (r < 0)
7113 return r;
7114
7115 if (arg_wait) {
7116 r = sd_event_default(&event);
7117 if (r >= 0)
7118 r = sd_bus_attach_event(bus, event, 0);
7119 if (r >= 0)
7120 r = sd_bus_match_signal_async(
7121 bus,
7122 &slot_startup_finished,
7123 "org.freedesktop.systemd1",
7124 "/org/freedesktop/systemd1",
7125 "org.freedesktop.systemd1.Manager",
7126 "StartupFinished",
7127 match_startup_finished, NULL, &state);
7128 if (r < 0) {
7129 log_warning_errno(r, "Failed to request match for StartupFinished: %m");
7130 arg_wait = false;
7131 }
7132 }
7133
7134 r = sd_bus_get_property_string(
7135 bus,
7136 "org.freedesktop.systemd1",
7137 "/org/freedesktop/systemd1",
7138 "org.freedesktop.systemd1.Manager",
7139 "SystemState",
7140 &error,
7141 &state);
7142 if (r < 0) {
7143 log_warning_errno(r, "Failed to query system state: %s", bus_error_message(&error, r));
7144
7145 if (!arg_quiet)
7146 puts("unknown");
7147 return EXIT_FAILURE;
7148 }
7149
7150 if (arg_wait && STR_IN_SET(state, "initializing", "starting")) {
7151 r = sd_event_loop(event);
7152 if (r < 0) {
7153 log_warning_errno(r, "Failed to get property from event loop: %m");
7154 if (!arg_quiet)
7155 puts("unknown");
7156 return EXIT_FAILURE;
7157 }
7158 }
7159
7160 if (!arg_quiet)
7161 puts(state);
7162
7163 return streq(state, "running") ? EXIT_SUCCESS : EXIT_FAILURE;
7164 }
7165
7166 static int create_edit_temp_file(const char *new_path, const char *original_path, char **ret_tmp_fn) {
7167 _cleanup_free_ char *t = NULL;
7168 int r;
7169
7170 assert(new_path);
7171 assert(original_path);
7172 assert(ret_tmp_fn);
7173
7174 r = tempfn_random(new_path, NULL, &t);
7175 if (r < 0)
7176 return log_error_errno(r, "Failed to determine temporary filename for \"%s\": %m", new_path);
7177
7178 r = mkdir_parents(new_path, 0755);
7179 if (r < 0)
7180 return log_error_errno(r, "Failed to create directories for \"%s\": %m", new_path);
7181
7182 r = copy_file(original_path, t, 0, 0644, 0, COPY_REFLINK);
7183 if (r == -ENOENT) {
7184
7185 r = touch(t);
7186 if (r < 0)
7187 return log_error_errno(r, "Failed to create temporary file \"%s\": %m", t);
7188
7189 } else if (r < 0)
7190 return log_error_errno(r, "Failed to create temporary file for \"%s\": %m", new_path);
7191
7192 *ret_tmp_fn = TAKE_PTR(t);
7193
7194 return 0;
7195 }
7196
7197 static int get_file_to_edit(
7198 const LookupPaths *paths,
7199 const char *name,
7200 char **ret_path) {
7201
7202 _cleanup_free_ char *path = NULL, *run = NULL;
7203
7204 assert(name);
7205 assert(ret_path);
7206
7207 path = strjoin(paths->persistent_config, "/", name);
7208 if (!path)
7209 return log_oom();
7210
7211 if (arg_runtime) {
7212 run = strjoin(paths->runtime_config, "/", name);
7213 if (!run)
7214 return log_oom();
7215 }
7216
7217 if (arg_runtime) {
7218 if (access(path, F_OK) >= 0)
7219 return log_error_errno(SYNTHETIC_ERRNO(EEXIST),
7220 "Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.",
7221 run, path);
7222
7223 *ret_path = TAKE_PTR(run);
7224 } else
7225 *ret_path = TAKE_PTR(path);
7226
7227 return 0;
7228 }
7229
7230 static int unit_file_create_new(
7231 const LookupPaths *paths,
7232 const char *unit_name,
7233 const char *suffix,
7234 char **ret_new_path,
7235 char **ret_tmp_path) {
7236
7237 _cleanup_free_ char *new_path = NULL, *tmp_path = NULL;
7238 const char *ending;
7239 int r;
7240
7241 assert(unit_name);
7242 assert(ret_new_path);
7243 assert(ret_tmp_path);
7244
7245 ending = strjoina(unit_name, suffix);
7246 r = get_file_to_edit(paths, ending, &new_path);
7247 if (r < 0)
7248 return r;
7249
7250 r = create_edit_temp_file(new_path, new_path, &tmp_path);
7251 if (r < 0)
7252 return r;
7253
7254 *ret_new_path = TAKE_PTR(new_path);
7255 *ret_tmp_path = TAKE_PTR(tmp_path);
7256
7257 return 0;
7258 }
7259
7260 static int unit_file_create_copy(
7261 const LookupPaths *paths,
7262 const char *unit_name,
7263 const char *fragment_path,
7264 char **ret_new_path,
7265 char **ret_tmp_path) {
7266
7267 _cleanup_free_ char *new_path = NULL, *tmp_path = NULL;
7268 int r;
7269
7270 assert(fragment_path);
7271 assert(unit_name);
7272 assert(ret_new_path);
7273 assert(ret_tmp_path);
7274
7275 r = get_file_to_edit(paths, unit_name, &new_path);
7276 if (r < 0)
7277 return r;
7278
7279 if (!path_equal(fragment_path, new_path) && access(new_path, F_OK) >= 0) {
7280 char response;
7281
7282 r = ask_char(&response, "yn", "\"%s\" already exists. Overwrite with \"%s\"? [(y)es, (n)o] ", new_path, fragment_path);
7283 if (r < 0)
7284 return r;
7285 if (response != 'y')
7286 return log_warning_errno(SYNTHETIC_ERRNO(EKEYREJECTED), "%s skipped.", unit_name);
7287 }
7288
7289 r = create_edit_temp_file(new_path, fragment_path, &tmp_path);
7290 if (r < 0)
7291 return r;
7292
7293 *ret_new_path = TAKE_PTR(new_path);
7294 *ret_tmp_path = TAKE_PTR(tmp_path);
7295
7296 return 0;
7297 }
7298
7299 static int run_editor(char **paths) {
7300 int r;
7301
7302 assert(paths);
7303
7304 r = safe_fork("(editor)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG|FORK_WAIT, NULL);
7305 if (r < 0)
7306 return r;
7307 if (r == 0) {
7308 char **editor_args = NULL, **tmp_path, **original_path;
7309 size_t n_editor_args = 0, i = 1, argc;
7310 const char **args, *editor, *p;
7311
7312 argc = strv_length(paths)/2 + 1;
7313
7314 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
7315 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
7316 * we try to execute well known editors
7317 */
7318 editor = getenv("SYSTEMD_EDITOR");
7319 if (!editor)
7320 editor = getenv("EDITOR");
7321 if (!editor)
7322 editor = getenv("VISUAL");
7323
7324 if (!isempty(editor)) {
7325 editor_args = strv_split(editor, WHITESPACE);
7326 if (!editor_args) {
7327 (void) log_oom();
7328 _exit(EXIT_FAILURE);
7329 }
7330 n_editor_args = strv_length(editor_args);
7331 argc += n_editor_args - 1;
7332 }
7333
7334 args = newa(const char*, argc + 1);
7335
7336 if (n_editor_args > 0) {
7337 args[0] = editor_args[0];
7338 for (; i < n_editor_args; i++)
7339 args[i] = editor_args[i];
7340 }
7341
7342 STRV_FOREACH_PAIR(original_path, tmp_path, paths)
7343 args[i++] = *tmp_path;
7344 args[i] = NULL;
7345
7346 if (n_editor_args > 0)
7347 execvp(args[0], (char* const*) args);
7348
7349 FOREACH_STRING(p, "editor", "nano", "vim", "vi") {
7350 args[0] = p;
7351 execvp(p, (char* const*) args);
7352 /* We do not fail if the editor doesn't exist
7353 * because we want to try each one of them before
7354 * failing.
7355 */
7356 if (errno != ENOENT) {
7357 log_error_errno(errno, "Failed to execute %s: %m", editor);
7358 _exit(EXIT_FAILURE);
7359 }
7360 }
7361
7362 log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR, $EDITOR or $VISUAL.");
7363 _exit(EXIT_FAILURE);
7364 }
7365
7366 return 0;
7367 }
7368
7369 static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) {
7370 _cleanup_(lookup_paths_free) LookupPaths lp = {};
7371 char **name;
7372 int r;
7373
7374 assert(names);
7375 assert(paths);
7376
7377 r = lookup_paths_init(&lp, arg_scope, 0, arg_root);
7378 if (r < 0)
7379 return r;
7380
7381 STRV_FOREACH(name, names) {
7382 _cleanup_free_ char *path = NULL, *new_path = NULL, *tmp_path = NULL, *tmp_name = NULL;
7383 const char *unit_name;
7384
7385 r = unit_find_paths(bus, *name, &lp, false, &path, NULL);
7386 if (r == -EKEYREJECTED) {
7387 /* If loading of the unit failed server side complete, then the server won't tell us the unit
7388 * file path. In that case, find the file client side. */
7389 log_debug_errno(r, "Unit '%s' was not loaded correctly, retrying client-side.", *name);
7390 r = unit_find_paths(bus, *name, &lp, true, &path, NULL);
7391 }
7392 if (r == -ERFKILL)
7393 return log_error_errno(r, "Unit '%s' masked, cannot edit.", *name);
7394 if (r < 0)
7395 return r;
7396
7397 if (r == 0) {
7398 assert(!path);
7399
7400 if (!arg_force) {
7401 log_info("Run 'systemctl edit%s --force --full %s' to create a new unit.",
7402 arg_scope == UNIT_FILE_GLOBAL ? " --global" :
7403 arg_scope == UNIT_FILE_USER ? " --user" : "",
7404 *name);
7405 return -ENOENT;
7406 }
7407
7408 /* Create a new unit from scratch */
7409 unit_name = *name;
7410 r = unit_file_create_new(&lp, unit_name,
7411 arg_full ? NULL : ".d/override.conf",
7412 &new_path, &tmp_path);
7413 } else {
7414 assert(path);
7415
7416 unit_name = basename(path);
7417 /* We follow unit aliases, but we need to propagate the instance */
7418 if (unit_name_is_valid(*name, UNIT_NAME_INSTANCE) &&
7419 unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE)) {
7420 _cleanup_free_ char *instance = NULL;
7421
7422 r = unit_name_to_instance(*name, &instance);
7423 if (r < 0)
7424 return r;
7425
7426 r = unit_name_replace_instance(unit_name, instance, &tmp_name);
7427 if (r < 0)
7428 return r;
7429
7430 unit_name = tmp_name;
7431 }
7432
7433 if (arg_full)
7434 r = unit_file_create_copy(&lp, unit_name, path, &new_path, &tmp_path);
7435 else
7436 r = unit_file_create_new(&lp, unit_name, ".d/override.conf", &new_path, &tmp_path);
7437 }
7438 if (r < 0)
7439 return r;
7440
7441 r = strv_push_pair(paths, new_path, tmp_path);
7442 if (r < 0)
7443 return log_oom();
7444
7445 new_path = tmp_path = NULL;
7446 }
7447
7448 return 0;
7449 }
7450
7451 static int edit(int argc, char *argv[], void *userdata) {
7452 _cleanup_(lookup_paths_free) LookupPaths lp = {};
7453 _cleanup_strv_free_ char **names = NULL;
7454 _cleanup_strv_free_ char **paths = NULL;
7455 char **original, **tmp;
7456 sd_bus *bus;
7457 int r;
7458
7459 if (!on_tty()) {
7460 log_error("Cannot edit units if not on a tty.");
7461 return -EINVAL;
7462 }
7463
7464 if (arg_transport != BUS_TRANSPORT_LOCAL) {
7465 log_error("Cannot edit units remotely.");
7466 return -EINVAL;
7467 }
7468
7469 r = lookup_paths_init(&lp, arg_scope, 0, arg_root);
7470 if (r < 0)
7471 return log_error_errno(r, "Failed to determine unit paths: %m");
7472
7473 r = acquire_bus(BUS_MANAGER, &bus);
7474 if (r < 0)
7475 return r;
7476
7477 r = expand_names(bus, strv_skip(argv, 1), NULL, &names);
7478 if (r < 0)
7479 return log_error_errno(r, "Failed to expand names: %m");
7480
7481 STRV_FOREACH(tmp, names) {
7482 r = unit_is_masked(bus, &lp, *tmp);
7483 if (r < 0)
7484 return r;
7485 if (r > 0) {
7486 log_error("Cannot edit %s: unit is masked.", *tmp);
7487 return -EINVAL;
7488 }
7489 }
7490
7491 r = find_paths_to_edit(bus, names, &paths);
7492 if (r < 0)
7493 return r;
7494
7495 if (strv_isempty(paths))
7496 return -ENOENT;
7497
7498 r = run_editor(paths);
7499 if (r < 0)
7500 goto end;
7501
7502 STRV_FOREACH_PAIR(original, tmp, paths) {
7503 /* If the temporary file is empty we ignore it.
7504 * This allows the user to cancel the modification.
7505 */
7506 if (null_or_empty_path(*tmp)) {
7507 log_warning("Editing \"%s\" canceled: temporary file is empty.", *original);
7508 continue;
7509 }
7510
7511 r = rename(*tmp, *original);
7512 if (r < 0) {
7513 r = log_error_errno(errno, "Failed to rename \"%s\" to \"%s\": %m", *tmp, *original);
7514 goto end;
7515 }
7516 }
7517
7518 r = 0;
7519
7520 if (!arg_no_reload && !install_client_side())
7521 r = daemon_reload(argc, argv, userdata);
7522
7523 end:
7524 STRV_FOREACH_PAIR(original, tmp, paths) {
7525 (void) unlink(*tmp);
7526
7527 /* Removing empty dropin dirs */
7528 if (!arg_full) {
7529 _cleanup_free_ char *dir;
7530
7531 dir = dirname_malloc(*original);
7532 if (!dir)
7533 return log_oom();
7534
7535 /* no need to check if the dir is empty, rmdir
7536 * does nothing if it is not the case.
7537 */
7538 (void) rmdir(dir);
7539 }
7540 }
7541
7542 return r;
7543 }
7544
7545 static int systemctl_help(void) {
7546 _cleanup_free_ char *link = NULL;
7547 int r;
7548
7549 (void) pager_open(arg_pager_flags);
7550
7551 r = terminal_urlify_man("systemctl", "1", &link);
7552 if (r < 0)
7553 return log_oom();
7554
7555 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
7556 "Query or send control commands to the systemd manager.\n\n"
7557 " -h --help Show this help\n"
7558 " --version Show package version\n"
7559 " --system Connect to system manager\n"
7560 " --user Connect to user service manager\n"
7561 " -H --host=[USER@]HOST\n"
7562 " Operate on remote host\n"
7563 " -M --machine=CONTAINER\n"
7564 " Operate on local container\n"
7565 " -t --type=TYPE List units of a particular type\n"
7566 " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n"
7567 " -p --property=NAME Show only properties by this name\n"
7568 " -a --all Show all properties/all units currently in memory,\n"
7569 " including dead/empty ones. To list all units installed on\n"
7570 " the system, use the 'list-unit-files' command instead.\n"
7571 " --failed Same as --state=failed\n"
7572 " -l --full Don't ellipsize unit names on output\n"
7573 " -r --recursive Show unit list of host and local containers\n"
7574 " --reverse Show reverse dependencies with 'list-dependencies'\n"
7575 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
7576 " queueing a new job\n"
7577 " --show-types When showing sockets, explicitly show their type\n"
7578 " --value When showing properties, only print the value\n"
7579 " -i --ignore-inhibitors\n"
7580 " When shutting down or sleeping, ignore inhibitors\n"
7581 " --kill-who=WHO Who to send signal to\n"
7582 " -s --signal=SIGNAL Which signal to send\n"
7583 " --now Start or stop unit in addition to enabling or disabling it\n"
7584 " --dry-run Only print what would be done\n"
7585 " -q --quiet Suppress output\n"
7586 " --wait For (re)start, wait until service stopped again\n"
7587 " For is-system-running, wait until startup is completed\n"
7588 " --no-block Do not wait until operation finished\n"
7589 " --no-wall Don't send wall message before halt/power-off/reboot\n"
7590 " --no-reload Don't reload daemon after en-/dis-abling unit files\n"
7591 " --no-legend Do not print a legend (column headers and hints)\n"
7592 " --no-pager Do not pipe output into a pager\n"
7593 " --no-ask-password\n"
7594 " Do not ask for system passwords\n"
7595 " --global Enable/disable/mask unit files globally\n"
7596 " --runtime Enable/disable/mask unit files temporarily until next\n"
7597 " reboot\n"
7598 " -f --force When enabling unit files, override existing symlinks\n"
7599 " When shutting down, execute action immediately\n"
7600 " --preset-mode= Apply only enable, only disable, or all presets\n"
7601 " --root=PATH Enable/disable/mask unit files in the specified root\n"
7602 " directory\n"
7603 " -n --lines=INTEGER Number of journal entries to show\n"
7604 " -o --output=STRING Change journal output mode (short, short-precise,\n"
7605 " short-iso, short-iso-precise, short-full,\n"
7606 " short-monotonic, short-unix,\n"
7607 " verbose, export, json, json-pretty, json-sse, cat)\n"
7608 " --firmware-setup Tell the firmware to show the setup menu on next boot\n"
7609 " --boot-loader-menu=TIME\n"
7610 " Boot into boot loader menu on next boot\n"
7611 " --boot-loader-entry=NAME\n"
7612 " Boot into a specific boot loader entry on next boot\n"
7613 " --plain Print unit dependencies as a list instead of a tree\n\n"
7614 "Unit Commands:\n"
7615 " list-units [PATTERN...] List units currently in memory\n"
7616 " list-sockets [PATTERN...] List socket units currently in memory,\n"
7617 " ordered by address\n"
7618 " list-timers [PATTERN...] List timer units currently in memory,\n"
7619 " ordered by next elapse\n"
7620 " start UNIT... Start (activate) one or more units\n"
7621 " stop UNIT... Stop (deactivate) one or more units\n"
7622 " reload UNIT... Reload one or more units\n"
7623 " restart UNIT... Start or restart one or more units\n"
7624 " try-restart UNIT... Restart one or more units if active\n"
7625 " reload-or-restart UNIT... Reload one or more units if possible,\n"
7626 " otherwise start or restart\n"
7627 " try-reload-or-restart UNIT... If active, reload one or more units,\n"
7628 " if supported, otherwise restart\n"
7629 " isolate UNIT Start one unit and stop all others\n"
7630 " kill UNIT... Send signal to processes of a unit\n"
7631 " is-active PATTERN... Check whether units are active\n"
7632 " is-failed PATTERN... Check whether units are failed\n"
7633 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
7634 " show [PATTERN...|JOB...] Show properties of one or more\n"
7635 " units/jobs or the manager\n"
7636 " cat PATTERN... Show files and drop-ins of specified units\n"
7637 " set-property UNIT PROPERTY=VALUE... Sets one or more properties of a unit\n"
7638 " help PATTERN...|PID... Show manual for one or more units\n"
7639 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
7640 " units\n"
7641 " list-dependencies [UNIT] Recursively show units which are required\n"
7642 " or wanted by this unit or by which this\n"
7643 " unit is required or wanted\n\n"
7644 "Unit File Commands:\n"
7645 " list-unit-files [PATTERN...] List installed unit files\n"
7646 " enable [UNIT...|PATH...] Enable one or more unit files\n"
7647 " disable UNIT... Disable one or more unit files\n"
7648 " reenable UNIT... Reenable one or more unit files\n"
7649 " preset UNIT... Enable/disable one or more unit files\n"
7650 " based on preset configuration\n"
7651 " preset-all Enable/disable all unit files based on\n"
7652 " preset configuration\n"
7653 " is-enabled UNIT... Check whether unit files are enabled\n"
7654 " mask UNIT... Mask one or more units\n"
7655 " unmask UNIT... Unmask one or more units\n"
7656 " link PATH... Link one or more units files into\n"
7657 " the search path\n"
7658 " revert UNIT... Revert one or more unit files to vendor\n"
7659 " version\n"
7660 " add-wants TARGET UNIT... Add 'Wants' dependency for the target\n"
7661 " on specified one or more units\n"
7662 " add-requires TARGET UNIT... Add 'Requires' dependency for the target\n"
7663 " on specified one or more units\n"
7664 " edit UNIT... Edit one or more unit files\n"
7665 " get-default Get the name of the default target\n"
7666 " set-default TARGET Set the default target\n\n"
7667 "Machine Commands:\n"
7668 " list-machines [PATTERN...] List local containers and host\n\n"
7669 "Job Commands:\n"
7670 " list-jobs [PATTERN...] List jobs\n"
7671 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
7672 "Environment Commands:\n"
7673 " show-environment Dump environment\n"
7674 " set-environment VARIABLE=VALUE... Set one or more environment variables\n"
7675 " unset-environment VARIABLE... Unset one or more environment variables\n"
7676 " import-environment [VARIABLE...] Import all or some environment variables\n\n"
7677 "Manager Lifecycle Commands:\n"
7678 " daemon-reload Reload systemd manager configuration\n"
7679 " daemon-reexec Reexecute systemd manager\n\n"
7680 "System Commands:\n"
7681 " is-system-running Check whether system is fully running\n"
7682 " default Enter system default mode\n"
7683 " rescue Enter system rescue mode\n"
7684 " emergency Enter system emergency mode\n"
7685 " halt Shut down and halt the system\n"
7686 " poweroff Shut down and power-off the system\n"
7687 " reboot [ARG] Shut down and reboot the system\n"
7688 " kexec Shut down and reboot the system with kexec\n"
7689 " exit [EXIT_CODE] Request user instance or container exit\n"
7690 " switch-root ROOT [INIT] Change to a different root file system\n"
7691 " suspend Suspend the system\n"
7692 " hibernate Hibernate the system\n"
7693 " hybrid-sleep Hibernate and suspend the system\n"
7694 " suspend-then-hibernate Suspend the system, wake after a period of\n"
7695 " time and put it into hibernate\n"
7696 "\nSee the %s for details.\n"
7697 , program_invocation_short_name
7698 , link
7699 );
7700
7701 return 0;
7702 }
7703
7704 static int halt_help(void) {
7705 _cleanup_free_ char *link = NULL;
7706 int r;
7707
7708 r = terminal_urlify_man("halt", "8", &link);
7709 if (r < 0)
7710 return log_oom();
7711
7712 printf("%s [OPTIONS...]%s\n\n"
7713 "%s the system.\n\n"
7714 " --help Show this help\n"
7715 " --halt Halt the machine\n"
7716 " -p --poweroff Switch off the machine\n"
7717 " --reboot Reboot the machine\n"
7718 " -f --force Force immediate halt/power-off/reboot\n"
7719 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
7720 " -d --no-wtmp Don't write wtmp record\n"
7721 " --no-wall Don't send wall message before halt/power-off/reboot\n"
7722 "\nSee the %s for details.\n"
7723 , program_invocation_short_name
7724 , arg_action == ACTION_REBOOT ? " [ARG]" : "",
7725 arg_action == ACTION_REBOOT ? "Reboot" :
7726 arg_action == ACTION_POWEROFF ? "Power off" :
7727 "Halt"
7728 , link
7729 );
7730
7731 return 0;
7732 }
7733
7734 static int shutdown_help(void) {
7735 _cleanup_free_ char *link = NULL;
7736 int r;
7737
7738 r = terminal_urlify_man("shutdown", "8", &link);
7739 if (r < 0)
7740 return log_oom();
7741
7742 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
7743 "Shut down the system.\n\n"
7744 " --help Show this help\n"
7745 " -H --halt Halt the machine\n"
7746 " -P --poweroff Power-off the machine\n"
7747 " -r --reboot Reboot the machine\n"
7748 " -h Equivalent to --poweroff, overridden by --halt\n"
7749 " -k Don't halt/power-off/reboot, just send warnings\n"
7750 " --no-wall Don't send wall message before halt/power-off/reboot\n"
7751 " -c Cancel a pending shutdown\n"
7752 "\nSee the %s for details.\n"
7753 , program_invocation_short_name
7754 , link
7755 );
7756
7757 return 0;
7758 }
7759
7760 static int telinit_help(void) {
7761 _cleanup_free_ char *link = NULL;
7762 int r;
7763
7764 r = terminal_urlify_man("telinit", "8", &link);
7765 if (r < 0)
7766 return log_oom();
7767
7768 printf("%s [OPTIONS...] {COMMAND}\n\n"
7769 "Send control commands to the init daemon.\n\n"
7770 " --help Show this help\n"
7771 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
7772 "Commands:\n"
7773 " 0 Power-off the machine\n"
7774 " 6 Reboot the machine\n"
7775 " 2, 3, 4, 5 Start runlevelX.target unit\n"
7776 " 1, s, S Enter rescue mode\n"
7777 " q, Q Reload init daemon configuration\n"
7778 " u, U Reexecute init daemon\n"
7779 "\nSee the %s for details.\n"
7780 , program_invocation_short_name
7781 , link
7782 );
7783
7784 return 0;
7785 }
7786
7787 static int runlevel_help(void) {
7788 _cleanup_free_ char *link = NULL;
7789 int r;
7790
7791 r = terminal_urlify_man("runlevel", "8", &link);
7792 if (r < 0)
7793 return log_oom();
7794
7795 printf("%s [OPTIONS...]\n\n"
7796 "Prints the previous and current runlevel of the init system.\n\n"
7797 " --help Show this help\n"
7798 "\nSee the %s for details.\n"
7799 , program_invocation_short_name
7800 , link
7801 );
7802
7803 return 0;
7804 }
7805
7806 static void help_types(void) {
7807 if (!arg_no_legend)
7808 puts("Available unit types:");
7809
7810 DUMP_STRING_TABLE(unit_type, UnitType, _UNIT_TYPE_MAX);
7811 }
7812
7813 static void help_states(void) {
7814 if (!arg_no_legend)
7815 puts("Available unit load states:");
7816 DUMP_STRING_TABLE(unit_load_state, UnitLoadState, _UNIT_LOAD_STATE_MAX);
7817
7818 if (!arg_no_legend)
7819 puts("\nAvailable unit active states:");
7820 DUMP_STRING_TABLE(unit_active_state, UnitActiveState, _UNIT_ACTIVE_STATE_MAX);
7821
7822 if (!arg_no_legend)
7823 puts("\nAvailable automount unit substates:");
7824 DUMP_STRING_TABLE(automount_state, AutomountState, _AUTOMOUNT_STATE_MAX);
7825
7826 if (!arg_no_legend)
7827 puts("\nAvailable device unit substates:");
7828 DUMP_STRING_TABLE(device_state, DeviceState, _DEVICE_STATE_MAX);
7829
7830 if (!arg_no_legend)
7831 puts("\nAvailable mount unit substates:");
7832 DUMP_STRING_TABLE(mount_state, MountState, _MOUNT_STATE_MAX);
7833
7834 if (!arg_no_legend)
7835 puts("\nAvailable path unit substates:");
7836 DUMP_STRING_TABLE(path_state, PathState, _PATH_STATE_MAX);
7837
7838 if (!arg_no_legend)
7839 puts("\nAvailable scope unit substates:");
7840 DUMP_STRING_TABLE(scope_state, ScopeState, _SCOPE_STATE_MAX);
7841
7842 if (!arg_no_legend)
7843 puts("\nAvailable service unit substates:");
7844 DUMP_STRING_TABLE(service_state, ServiceState, _SERVICE_STATE_MAX);
7845
7846 if (!arg_no_legend)
7847 puts("\nAvailable slice unit substates:");
7848 DUMP_STRING_TABLE(slice_state, SliceState, _SLICE_STATE_MAX);
7849
7850 if (!arg_no_legend)
7851 puts("\nAvailable socket unit substates:");
7852 DUMP_STRING_TABLE(socket_state, SocketState, _SOCKET_STATE_MAX);
7853
7854 if (!arg_no_legend)
7855 puts("\nAvailable swap unit substates:");
7856 DUMP_STRING_TABLE(swap_state, SwapState, _SWAP_STATE_MAX);
7857
7858 if (!arg_no_legend)
7859 puts("\nAvailable target unit substates:");
7860 DUMP_STRING_TABLE(target_state, TargetState, _TARGET_STATE_MAX);
7861
7862 if (!arg_no_legend)
7863 puts("\nAvailable timer unit substates:");
7864 DUMP_STRING_TABLE(timer_state, TimerState, _TIMER_STATE_MAX);
7865 }
7866
7867 static int help_boot_loader_entry(void) {
7868 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
7869 _cleanup_free_ char **l = NULL;
7870 sd_bus *bus;
7871 char **i;
7872 int r;
7873
7874 r = acquire_bus(BUS_FULL, &bus);
7875 if (r < 0)
7876 return r;
7877
7878 r = sd_bus_get_property_strv(
7879 bus,
7880 "org.freedesktop.login1",
7881 "/org/freedesktop/login1",
7882 "org.freedesktop.login1.Manager",
7883 "BootLoaderEntries",
7884 &error,
7885 &l);
7886 if (r < 0)
7887 return log_error_errno(r, "Failed to enumerate boot loader entries: %s", bus_error_message(&error, r));
7888
7889 if (strv_isempty(l)) {
7890 log_error("No boot loader entries discovered.");
7891 return -ENODATA;
7892 }
7893
7894 STRV_FOREACH(i, l)
7895 puts(*i);
7896
7897 return 0;
7898 }
7899
7900 static int systemctl_parse_argv(int argc, char *argv[]) {
7901 enum {
7902 ARG_FAIL = 0x100,
7903 ARG_REVERSE,
7904 ARG_AFTER,
7905 ARG_BEFORE,
7906 ARG_DRY_RUN,
7907 ARG_SHOW_TYPES,
7908 ARG_IRREVERSIBLE,
7909 ARG_IGNORE_DEPENDENCIES,
7910 ARG_VALUE,
7911 ARG_VERSION,
7912 ARG_USER,
7913 ARG_SYSTEM,
7914 ARG_GLOBAL,
7915 ARG_NO_BLOCK,
7916 ARG_NO_LEGEND,
7917 ARG_NO_PAGER,
7918 ARG_NO_WALL,
7919 ARG_ROOT,
7920 ARG_NO_RELOAD,
7921 ARG_KILL_WHO,
7922 ARG_NO_ASK_PASSWORD,
7923 ARG_FAILED,
7924 ARG_RUNTIME,
7925 ARG_PLAIN,
7926 ARG_STATE,
7927 ARG_JOB_MODE,
7928 ARG_PRESET_MODE,
7929 ARG_FIRMWARE_SETUP,
7930 ARG_BOOT_LOADER_MENU,
7931 ARG_BOOT_LOADER_ENTRY,
7932 ARG_NOW,
7933 ARG_MESSAGE,
7934 ARG_WAIT,
7935 };
7936
7937 static const struct option options[] = {
7938 { "help", no_argument, NULL, 'h' },
7939 { "version", no_argument, NULL, ARG_VERSION },
7940 { "type", required_argument, NULL, 't' },
7941 { "property", required_argument, NULL, 'p' },
7942 { "all", no_argument, NULL, 'a' },
7943 { "reverse", no_argument, NULL, ARG_REVERSE },
7944 { "after", no_argument, NULL, ARG_AFTER },
7945 { "before", no_argument, NULL, ARG_BEFORE },
7946 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
7947 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
7948 { "full", no_argument, NULL, 'l' },
7949 { "job-mode", required_argument, NULL, ARG_JOB_MODE },
7950 { "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */
7951 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */
7952 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
7953 { "ignore-inhibitors", no_argument, NULL, 'i' },
7954 { "value", no_argument, NULL, ARG_VALUE },
7955 { "user", no_argument, NULL, ARG_USER },
7956 { "system", no_argument, NULL, ARG_SYSTEM },
7957 { "global", no_argument, NULL, ARG_GLOBAL },
7958 { "wait", no_argument, NULL, ARG_WAIT },
7959 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
7960 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
7961 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
7962 { "no-wall", no_argument, NULL, ARG_NO_WALL },
7963 { "dry-run", no_argument, NULL, ARG_DRY_RUN },
7964 { "quiet", no_argument, NULL, 'q' },
7965 { "root", required_argument, NULL, ARG_ROOT },
7966 { "force", no_argument, NULL, 'f' },
7967 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
7968 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
7969 { "signal", required_argument, NULL, 's' },
7970 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
7971 { "host", required_argument, NULL, 'H' },
7972 { "machine", required_argument, NULL, 'M' },
7973 { "runtime", no_argument, NULL, ARG_RUNTIME },
7974 { "lines", required_argument, NULL, 'n' },
7975 { "output", required_argument, NULL, 'o' },
7976 { "plain", no_argument, NULL, ARG_PLAIN },
7977 { "state", required_argument, NULL, ARG_STATE },
7978 { "recursive", no_argument, NULL, 'r' },
7979 { "preset-mode", required_argument, NULL, ARG_PRESET_MODE },
7980 { "firmware-setup", no_argument, NULL, ARG_FIRMWARE_SETUP },
7981 { "boot-loader-menu", required_argument, NULL, ARG_BOOT_LOADER_MENU },
7982 { "boot-loader-entry", required_argument, NULL, ARG_BOOT_LOADER_ENTRY },
7983 { "now", no_argument, NULL, ARG_NOW },
7984 { "message", required_argument, NULL, ARG_MESSAGE },
7985 {}
7986 };
7987
7988 int c, r;
7989
7990 assert(argc >= 0);
7991 assert(argv);
7992
7993 /* we default to allowing interactive authorization only in systemctl (not in the legacy commands) */
7994 arg_ask_password = true;
7995
7996 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir.::", options, NULL)) >= 0)
7997
7998 switch (c) {
7999
8000 case 'h':
8001 return systemctl_help();
8002
8003 case ARG_VERSION:
8004 return version();
8005
8006 case 't': {
8007 const char *p;
8008
8009 if (isempty(optarg))
8010 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
8011 "--type= requires arguments.");
8012
8013 for (p = optarg;;) {
8014 _cleanup_free_ char *type = NULL;
8015
8016 r = extract_first_word(&p, &type, ",", 0);
8017 if (r < 0)
8018 return log_error_errno(r, "Failed to parse type: %s", optarg);
8019 if (r == 0)
8020 break;
8021
8022 if (streq(type, "help")) {
8023 help_types();
8024 return 0;
8025 }
8026
8027 if (unit_type_from_string(type) >= 0) {
8028 if (strv_consume(&arg_types, TAKE_PTR(type)) < 0)
8029 return log_oom();
8030 continue;
8031 }
8032
8033 /* It's much nicer to use --state= for
8034 * load states, but let's support this
8035 * in --types= too for compatibility
8036 * with old versions */
8037 if (unit_load_state_from_string(type) >= 0) {
8038 if (strv_consume(&arg_states, TAKE_PTR(type)) < 0)
8039 return log_oom();
8040 continue;
8041 }
8042
8043 log_error("Unknown unit type or load state '%s'.", type);
8044 return log_info_errno(SYNTHETIC_ERRNO(EINVAL),
8045 "Use -t help to see a list of allowed values.");
8046 }
8047
8048 break;
8049 }
8050
8051 case 'p':
8052 /* Make sure that if the empty property list was specified, we won't show any
8053 properties. */
8054 if (isempty(optarg) && !arg_properties) {
8055 arg_properties = new0(char*, 1);
8056 if (!arg_properties)
8057 return log_oom();
8058 } else {
8059 const char *p;
8060
8061 for (p = optarg;;) {
8062 _cleanup_free_ char *prop = NULL;
8063
8064 r = extract_first_word(&p, &prop, ",", 0);
8065 if (r < 0)
8066 return log_error_errno(r, "Failed to parse property: %s", optarg);
8067 if (r == 0)
8068 break;
8069
8070 if (strv_push(&arg_properties, prop) < 0)
8071 return log_oom();
8072
8073 prop = NULL;
8074 }
8075 }
8076
8077 /* If the user asked for a particular
8078 * property, show it to him, even if it is
8079 * empty. */
8080 arg_all = true;
8081
8082 break;
8083
8084 case 'a':
8085 arg_all = true;
8086 break;
8087
8088 case ARG_REVERSE:
8089 arg_dependency = DEPENDENCY_REVERSE;
8090 break;
8091
8092 case ARG_AFTER:
8093 arg_dependency = DEPENDENCY_AFTER;
8094 arg_jobs_after = true;
8095 break;
8096
8097 case ARG_BEFORE:
8098 arg_dependency = DEPENDENCY_BEFORE;
8099 arg_jobs_before = true;
8100 break;
8101
8102 case ARG_SHOW_TYPES:
8103 arg_show_types = true;
8104 break;
8105
8106 case ARG_VALUE:
8107 arg_value = true;
8108 break;
8109
8110 case ARG_JOB_MODE:
8111 arg_job_mode = optarg;
8112 break;
8113
8114 case ARG_FAIL:
8115 arg_job_mode = "fail";
8116 break;
8117
8118 case ARG_IRREVERSIBLE:
8119 arg_job_mode = "replace-irreversibly";
8120 break;
8121
8122 case ARG_IGNORE_DEPENDENCIES:
8123 arg_job_mode = "ignore-dependencies";
8124 break;
8125
8126 case ARG_USER:
8127 arg_scope = UNIT_FILE_USER;
8128 break;
8129
8130 case ARG_SYSTEM:
8131 arg_scope = UNIT_FILE_SYSTEM;
8132 break;
8133
8134 case ARG_GLOBAL:
8135 arg_scope = UNIT_FILE_GLOBAL;
8136 break;
8137
8138 case ARG_WAIT:
8139 arg_wait = true;
8140 break;
8141
8142 case ARG_NO_BLOCK:
8143 arg_no_block = true;
8144 break;
8145
8146 case ARG_NO_LEGEND:
8147 arg_no_legend = true;
8148 break;
8149
8150 case ARG_NO_PAGER:
8151 arg_pager_flags |= PAGER_DISABLE;
8152 break;
8153
8154 case ARG_NO_WALL:
8155 arg_no_wall = true;
8156 break;
8157
8158 case ARG_ROOT:
8159 r = parse_path_argument_and_warn(optarg, false, &arg_root);
8160 if (r < 0)
8161 return r;
8162 break;
8163
8164 case 'l':
8165 arg_full = true;
8166 break;
8167
8168 case ARG_FAILED:
8169 if (strv_extend(&arg_states, "failed") < 0)
8170 return log_oom();
8171
8172 break;
8173
8174 case ARG_DRY_RUN:
8175 arg_dry_run = true;
8176 break;
8177
8178 case 'q':
8179 arg_quiet = true;
8180 break;
8181
8182 case 'f':
8183 arg_force++;
8184 break;
8185
8186 case ARG_NO_RELOAD:
8187 arg_no_reload = true;
8188 break;
8189
8190 case ARG_KILL_WHO:
8191 arg_kill_who = optarg;
8192 break;
8193
8194 case 's':
8195 if (streq(optarg, "help")) {
8196 DUMP_STRING_TABLE(signal, int, _NSIG);
8197 return 0;
8198 }
8199
8200 arg_signal = signal_from_string(optarg);
8201 if (arg_signal < 0)
8202 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
8203 "Failed to parse signal string %s.",
8204 optarg);
8205 break;
8206
8207 case ARG_NO_ASK_PASSWORD:
8208 arg_ask_password = false;
8209 break;
8210
8211 case 'H':
8212 arg_transport = BUS_TRANSPORT_REMOTE;
8213 arg_host = optarg;
8214 break;
8215
8216 case 'M':
8217 arg_transport = BUS_TRANSPORT_MACHINE;
8218 arg_host = optarg;
8219 break;
8220
8221 case ARG_RUNTIME:
8222 arg_runtime = true;
8223 break;
8224
8225 case 'n':
8226 if (safe_atou(optarg, &arg_lines) < 0)
8227 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
8228 "Failed to parse lines '%s'",
8229 optarg);
8230 break;
8231
8232 case 'o':
8233 if (streq(optarg, "help")) {
8234 DUMP_STRING_TABLE(output_mode, OutputMode, _OUTPUT_MODE_MAX);
8235 return 0;
8236 }
8237
8238 arg_output = output_mode_from_string(optarg);
8239 if (arg_output < 0)
8240 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
8241 "Unknown output '%s'.",
8242 optarg);
8243 break;
8244
8245 case 'i':
8246 arg_ignore_inhibitors = true;
8247 break;
8248
8249 case ARG_PLAIN:
8250 arg_plain = true;
8251 break;
8252
8253 case ARG_FIRMWARE_SETUP:
8254 arg_firmware_setup = true;
8255 break;
8256
8257 case ARG_BOOT_LOADER_MENU:
8258
8259 r = parse_sec(optarg, &arg_boot_loader_menu);
8260 if (r < 0)
8261 return log_error_errno(r, "Failed to parse --boot-loader-menu= argument '%s': %m", optarg);
8262
8263 break;
8264
8265 case ARG_BOOT_LOADER_ENTRY:
8266
8267 if (streq(optarg, "help")) { /* Yes, this means, "help" is not a valid boot loader entry name we can deal with */
8268 r = help_boot_loader_entry();
8269 if (r < 0)
8270 return r;
8271
8272 return 0;
8273 }
8274
8275 arg_boot_loader_entry = empty_to_null(optarg);
8276 break;
8277
8278 case ARG_STATE: {
8279 const char *p;
8280
8281 if (isempty(optarg))
8282 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
8283 "--state= requires arguments.");
8284
8285 for (p = optarg;;) {
8286 _cleanup_free_ char *s = NULL;
8287
8288 r = extract_first_word(&p, &s, ",", 0);
8289 if (r < 0)
8290 return log_error_errno(r, "Failed to parse state: %s", optarg);
8291 if (r == 0)
8292 break;
8293
8294 if (streq(s, "help")) {
8295 help_states();
8296 return 0;
8297 }
8298
8299 if (strv_push(&arg_states, s) < 0)
8300 return log_oom();
8301
8302 s = NULL;
8303 }
8304 break;
8305 }
8306
8307 case 'r':
8308 if (geteuid() != 0)
8309 return log_error_errno(SYNTHETIC_ERRNO(EPERM),
8310 "--recursive requires root privileges.");
8311
8312 arg_recursive = true;
8313 break;
8314
8315 case ARG_PRESET_MODE:
8316 if (streq(optarg, "help")) {
8317 DUMP_STRING_TABLE(unit_file_preset_mode, UnitFilePresetMode, _UNIT_FILE_PRESET_MAX);
8318 return 0;
8319 }
8320
8321 arg_preset_mode = unit_file_preset_mode_from_string(optarg);
8322 if (arg_preset_mode < 0)
8323 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
8324 "Failed to parse preset mode: %s.", optarg);
8325
8326 break;
8327
8328 case ARG_NOW:
8329 arg_now = true;
8330 break;
8331
8332 case ARG_MESSAGE:
8333 if (strv_extend(&arg_wall, optarg) < 0)
8334 return log_oom();
8335 break;
8336
8337 case '.':
8338 /* Output an error mimicking getopt, and print a hint afterwards */
8339 log_error("%s: invalid option -- '.'", program_invocation_name);
8340 log_notice("Hint: to specify units starting with a dash, use \"--\":\n"
8341 " %s [OPTIONS...] {COMMAND} -- -.%s ...",
8342 program_invocation_name, optarg ?: "mount");
8343 _fallthrough_;
8344
8345 case '?':
8346 return -EINVAL;
8347
8348 default:
8349 assert_not_reached("Unhandled option");
8350 }
8351
8352 if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM)
8353 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
8354 "Cannot access user instance remotely.");
8355
8356 if (arg_wait && arg_no_block)
8357 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
8358 "--wait may not be combined with --no-block.");
8359
8360 return 1;
8361 }
8362
8363 static int halt_parse_argv(int argc, char *argv[]) {
8364 enum {
8365 ARG_HELP = 0x100,
8366 ARG_HALT,
8367 ARG_REBOOT,
8368 ARG_NO_WALL
8369 };
8370
8371 static const struct option options[] = {
8372 { "help", no_argument, NULL, ARG_HELP },
8373 { "halt", no_argument, NULL, ARG_HALT },
8374 { "poweroff", no_argument, NULL, 'p' },
8375 { "reboot", no_argument, NULL, ARG_REBOOT },
8376 { "force", no_argument, NULL, 'f' },
8377 { "wtmp-only", no_argument, NULL, 'w' },
8378 { "no-wtmp", no_argument, NULL, 'd' },
8379 { "no-sync", no_argument, NULL, 'n' },
8380 { "no-wall", no_argument, NULL, ARG_NO_WALL },
8381 {}
8382 };
8383
8384 int c, r, runlevel;
8385
8386 assert(argc >= 0);
8387 assert(argv);
8388
8389 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
8390 if (IN_SET(runlevel, '0', '6'))
8391 arg_force = 2;
8392
8393 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0)
8394 switch (c) {
8395
8396 case ARG_HELP:
8397 return halt_help();
8398
8399 case ARG_HALT:
8400 arg_action = ACTION_HALT;
8401 break;
8402
8403 case 'p':
8404 if (arg_action != ACTION_REBOOT)
8405 arg_action = ACTION_POWEROFF;
8406 break;
8407
8408 case ARG_REBOOT:
8409 arg_action = ACTION_REBOOT;
8410 break;
8411
8412 case 'f':
8413 arg_force = 2;
8414 break;
8415
8416 case 'w':
8417 arg_dry_run = true;
8418 break;
8419
8420 case 'd':
8421 arg_no_wtmp = true;
8422 break;
8423
8424 case 'n':
8425 arg_no_sync = true;
8426 break;
8427
8428 case ARG_NO_WALL:
8429 arg_no_wall = true;
8430 break;
8431
8432 case 'i':
8433 case 'h':
8434 /* Compatibility nops */
8435 break;
8436
8437 case '?':
8438 return -EINVAL;
8439
8440 default:
8441 assert_not_reached("Unhandled option");
8442 }
8443
8444 if (arg_action == ACTION_REBOOT && (argc == optind || argc == optind + 1)) {
8445 r = update_reboot_parameter_and_warn(argc == optind + 1 ? argv[optind] : NULL);
8446 if (r < 0)
8447 return r;
8448 } else if (optind < argc)
8449 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
8450 "Too many arguments.");
8451
8452 return 1;
8453 }
8454
8455 static int parse_shutdown_time_spec(const char *t, usec_t *_u) {
8456 assert(t);
8457 assert(_u);
8458
8459 if (streq(t, "now"))
8460 *_u = 0;
8461 else if (!strchr(t, ':')) {
8462 uint64_t u;
8463
8464 if (safe_atou64(t, &u) < 0)
8465 return -EINVAL;
8466
8467 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
8468 } else {
8469 char *e = NULL;
8470 long hour, minute;
8471 struct tm tm = {};
8472 time_t s;
8473 usec_t n;
8474
8475 errno = 0;
8476 hour = strtol(t, &e, 10);
8477 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
8478 return -EINVAL;
8479
8480 minute = strtol(e+1, &e, 10);
8481 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
8482 return -EINVAL;
8483
8484 n = now(CLOCK_REALTIME);
8485 s = (time_t) (n / USEC_PER_SEC);
8486
8487 assert_se(localtime_r(&s, &tm));
8488
8489 tm.tm_hour = (int) hour;
8490 tm.tm_min = (int) minute;
8491 tm.tm_sec = 0;
8492
8493 s = mktime(&tm);
8494 assert(s >= 0);
8495
8496 *_u = (usec_t) s * USEC_PER_SEC;
8497
8498 while (*_u <= n)
8499 *_u += USEC_PER_DAY;
8500 }
8501
8502 return 0;
8503 }
8504
8505 static int shutdown_parse_argv(int argc, char *argv[]) {
8506 enum {
8507 ARG_HELP = 0x100,
8508 ARG_NO_WALL
8509 };
8510
8511 static const struct option options[] = {
8512 { "help", no_argument, NULL, ARG_HELP },
8513 { "halt", no_argument, NULL, 'H' },
8514 { "poweroff", no_argument, NULL, 'P' },
8515 { "reboot", no_argument, NULL, 'r' },
8516 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
8517 { "no-wall", no_argument, NULL, ARG_NO_WALL },
8518 {}
8519 };
8520
8521 char **wall = NULL;
8522 int c, r;
8523
8524 assert(argc >= 0);
8525 assert(argv);
8526
8527 while ((c = getopt_long(argc, argv, "HPrhkKat:fFc", options, NULL)) >= 0)
8528 switch (c) {
8529
8530 case ARG_HELP:
8531 return shutdown_help();
8532
8533 case 'H':
8534 arg_action = ACTION_HALT;
8535 break;
8536
8537 case 'P':
8538 arg_action = ACTION_POWEROFF;
8539 break;
8540
8541 case 'r':
8542 if (kexec_loaded())
8543 arg_action = ACTION_KEXEC;
8544 else
8545 arg_action = ACTION_REBOOT;
8546 break;
8547
8548 case 'K':
8549 arg_action = ACTION_KEXEC;
8550 break;
8551
8552 case 'h':
8553 if (arg_action != ACTION_HALT)
8554 arg_action = ACTION_POWEROFF;
8555 break;
8556
8557 case 'k':
8558 arg_dry_run = true;
8559 break;
8560
8561 case ARG_NO_WALL:
8562 arg_no_wall = true;
8563 break;
8564
8565 case 'a':
8566 case 't': /* Note that we also ignore any passed argument to -t, not just the -t itself */
8567 case 'f':
8568 case 'F':
8569 /* Compatibility nops */
8570 break;
8571
8572 case 'c':
8573 arg_action = ACTION_CANCEL_SHUTDOWN;
8574 break;
8575
8576 case '?':
8577 return -EINVAL;
8578
8579 default:
8580 assert_not_reached("Unhandled option");
8581 }
8582
8583 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
8584 r = parse_shutdown_time_spec(argv[optind], &arg_when);
8585 if (r < 0) {
8586 log_error("Failed to parse time specification: %s", argv[optind]);
8587 return r;
8588 }
8589 } else
8590 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
8591
8592 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
8593 /* No time argument for shutdown cancel */
8594 wall = argv + optind;
8595 else if (argc > optind + 1)
8596 /* We skip the time argument */
8597 wall = argv + optind + 1;
8598
8599 if (wall) {
8600 arg_wall = strv_copy(wall);
8601 if (!arg_wall)
8602 return log_oom();
8603 }
8604
8605 optind = argc;
8606
8607 return 1;
8608 }
8609
8610 static int telinit_parse_argv(int argc, char *argv[]) {
8611 enum {
8612 ARG_HELP = 0x100,
8613 ARG_NO_WALL
8614 };
8615
8616 static const struct option options[] = {
8617 { "help", no_argument, NULL, ARG_HELP },
8618 { "no-wall", no_argument, NULL, ARG_NO_WALL },
8619 {}
8620 };
8621
8622 static const struct {
8623 char from;
8624 enum action to;
8625 } table[] = {
8626 { '0', ACTION_POWEROFF },
8627 { '6', ACTION_REBOOT },
8628 { '1', ACTION_RESCUE },
8629 { '2', ACTION_RUNLEVEL2 },
8630 { '3', ACTION_RUNLEVEL3 },
8631 { '4', ACTION_RUNLEVEL4 },
8632 { '5', ACTION_RUNLEVEL5 },
8633 { 's', ACTION_RESCUE },
8634 { 'S', ACTION_RESCUE },
8635 { 'q', ACTION_RELOAD },
8636 { 'Q', ACTION_RELOAD },
8637 { 'u', ACTION_REEXEC },
8638 { 'U', ACTION_REEXEC }
8639 };
8640
8641 unsigned i;
8642 int c;
8643
8644 assert(argc >= 0);
8645 assert(argv);
8646
8647 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
8648 switch (c) {
8649
8650 case ARG_HELP:
8651 return telinit_help();
8652
8653 case ARG_NO_WALL:
8654 arg_no_wall = true;
8655 break;
8656
8657 case '?':
8658 return -EINVAL;
8659
8660 default:
8661 assert_not_reached("Unhandled option");
8662 }
8663
8664 if (optind >= argc)
8665 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
8666 "%s: required argument missing.",
8667 program_invocation_short_name);
8668
8669 if (optind + 1 < argc)
8670 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
8671 "Too many arguments.");
8672
8673 if (strlen(argv[optind]) != 1)
8674 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
8675 "Expected single character argument.");
8676
8677 for (i = 0; i < ELEMENTSOF(table); i++)
8678 if (table[i].from == argv[optind][0])
8679 break;
8680
8681 if (i >= ELEMENTSOF(table))
8682 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
8683 "Unknown command '%s'.", argv[optind]);
8684
8685 arg_action = table[i].to;
8686
8687 optind++;
8688
8689 return 1;
8690 }
8691
8692 static int runlevel_parse_argv(int argc, char *argv[]) {
8693 enum {
8694 ARG_HELP = 0x100,
8695 };
8696
8697 static const struct option options[] = {
8698 { "help", no_argument, NULL, ARG_HELP },
8699 {}
8700 };
8701
8702 int c;
8703
8704 assert(argc >= 0);
8705 assert(argv);
8706
8707 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
8708 switch (c) {
8709
8710 case ARG_HELP:
8711 return runlevel_help();
8712
8713 case '?':
8714 return -EINVAL;
8715
8716 default:
8717 assert_not_reached("Unhandled option");
8718 }
8719
8720 if (optind < argc)
8721 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
8722 "Too many arguments.");
8723
8724 return 1;
8725 }
8726
8727 static int parse_argv(int argc, char *argv[]) {
8728 assert(argc >= 0);
8729 assert(argv);
8730
8731 if (program_invocation_short_name) {
8732
8733 if (strstr(program_invocation_short_name, "halt")) {
8734 arg_action = ACTION_HALT;
8735 return halt_parse_argv(argc, argv);
8736
8737 } else if (strstr(program_invocation_short_name, "poweroff")) {
8738 arg_action = ACTION_POWEROFF;
8739 return halt_parse_argv(argc, argv);
8740
8741 } else if (strstr(program_invocation_short_name, "reboot")) {
8742 if (kexec_loaded())
8743 arg_action = ACTION_KEXEC;
8744 else
8745 arg_action = ACTION_REBOOT;
8746 return halt_parse_argv(argc, argv);
8747
8748 } else if (strstr(program_invocation_short_name, "shutdown")) {
8749 arg_action = ACTION_POWEROFF;
8750 return shutdown_parse_argv(argc, argv);
8751
8752 } else if (strstr(program_invocation_short_name, "init")) {
8753
8754 /* Matches invocations as "init" as well as "telinit", which are synonymous when run as PID !=
8755 * 1 on SysV.
8756 *
8757 * On SysV "telinit" was the official command to communicate with PID 1, but "init" would
8758 * redirect itself to "telinit" if called with PID != 1. We follow the same logic here still,
8759 * though we add one level of indirection, as we implement "telinit" in "systemctl". Hence, for
8760 * us if you invoke "init" you get "systemd", but it will execve() "systemctl" immediately with
8761 * argv[] unmodified if PID is != 1. If you invoke "telinit" you directly get "systemctl". In
8762 * both cases we shall do the same thing, which is why we do strstr(p_i_s_n, "init") here, as a
8763 * quick way to match both.
8764 *
8765 * Also see redirect_telinit() in src/core/main.c. */
8766
8767 if (sd_booted() > 0) {
8768 arg_action = _ACTION_INVALID;
8769 return telinit_parse_argv(argc, argv);
8770 } else {
8771 /* Hmm, so some other init system is running, we need to forward this request to
8772 * it. For now we simply guess that it is Upstart. */
8773
8774 (void) rlimit_nofile_safe();
8775 execv(TELINIT, argv);
8776
8777 return log_error_errno(SYNTHETIC_ERRNO(EIO),
8778 "Couldn't find an alternative telinit implementation to spawn.");
8779 }
8780
8781 } else if (strstr(program_invocation_short_name, "runlevel")) {
8782 arg_action = ACTION_RUNLEVEL;
8783 return runlevel_parse_argv(argc, argv);
8784 }
8785 }
8786
8787 arg_action = ACTION_SYSTEMCTL;
8788 return systemctl_parse_argv(argc, argv);
8789 }
8790
8791 #if HAVE_SYSV_COMPAT
8792 _pure_ static int action_to_runlevel(void) {
8793 static const char table[_ACTION_MAX] = {
8794 [ACTION_HALT] = '0',
8795 [ACTION_POWEROFF] = '0',
8796 [ACTION_REBOOT] = '6',
8797 [ACTION_RUNLEVEL2] = '2',
8798 [ACTION_RUNLEVEL3] = '3',
8799 [ACTION_RUNLEVEL4] = '4',
8800 [ACTION_RUNLEVEL5] = '5',
8801 [ACTION_RESCUE] = '1'
8802 };
8803
8804 assert(arg_action >= 0 && arg_action < _ACTION_MAX);
8805
8806 return table[arg_action];
8807 }
8808 #endif
8809
8810 static int talk_initctl(void) {
8811 #if HAVE_SYSV_COMPAT
8812 struct init_request request = {
8813 .magic = INIT_MAGIC,
8814 .sleeptime = 0,
8815 .cmd = INIT_CMD_RUNLVL
8816 };
8817
8818 _cleanup_close_ int fd = -1;
8819 char rl;
8820 int r;
8821 const char *p;
8822
8823 rl = action_to_runlevel();
8824 if (!rl)
8825 return 0;
8826
8827 request.runlevel = rl;
8828
8829 FOREACH_STRING(p, "/run/initctl", "/dev/initctl") {
8830 fd = open(p, O_WRONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY);
8831 if (fd >= 0 || errno != ENOENT)
8832 break;
8833 }
8834 if (fd < 0) {
8835 if (errno == ENOENT)
8836 return 0;
8837
8838 return log_error_errno(errno, "Failed to open initctl fifo: %m");
8839 }
8840
8841 r = loop_write(fd, &request, sizeof(request), false);
8842 if (r < 0)
8843 return log_error_errno(r, "Failed to write to %s: %m", p);
8844
8845 return 1;
8846 #else
8847 return 0;
8848 #endif
8849 }
8850
8851 static int systemctl_main(int argc, char *argv[]) {
8852 static const Verb verbs[] = {
8853 { "list-units", VERB_ANY, VERB_ANY, VERB_DEFAULT|VERB_ONLINE_ONLY, list_units },
8854 { "list-unit-files", VERB_ANY, VERB_ANY, 0, list_unit_files },
8855 { "list-sockets", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, list_sockets },
8856 { "list-timers", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, list_timers },
8857 { "list-jobs", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, list_jobs },
8858 { "list-machines", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY|VERB_MUST_BE_ROOT, list_machines },
8859 { "clear-jobs", VERB_ANY, 1, VERB_ONLINE_ONLY, trivial_method },
8860 { "cancel", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, cancel_job },
8861 { "start", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit },
8862 { "stop", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit },
8863 { "condstop", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, /* For compatibility with ALTLinux */
8864 { "reload", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit },
8865 { "restart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit },
8866 { "try-restart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit },
8867 { "reload-or-restart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit },
8868 { "reload-or-try-restart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, /* For compatbility with old systemctl <= 228 */
8869 { "try-reload-or-restart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit },
8870 { "force-reload", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, /* For compatibility with SysV */
8871 { "condreload", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, /* For compatibility with ALTLinux */
8872 { "condrestart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, /* For compatibility with RH */
8873 { "isolate", 2, 2, VERB_ONLINE_ONLY, start_unit },
8874 { "kill", 2, VERB_ANY, VERB_ONLINE_ONLY, kill_unit },
8875 { "is-active", 2, VERB_ANY, VERB_ONLINE_ONLY, check_unit_active },
8876 { "check", 2, VERB_ANY, VERB_ONLINE_ONLY, check_unit_active }, /* deprecated alias of is-active */
8877 { "is-failed", 2, VERB_ANY, VERB_ONLINE_ONLY, check_unit_failed },
8878 { "show", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, show },
8879 { "cat", 2, VERB_ANY, VERB_ONLINE_ONLY, cat },
8880 { "status", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, show },
8881 { "help", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, show },
8882 { "daemon-reload", VERB_ANY, 1, VERB_ONLINE_ONLY, daemon_reload },
8883 { "daemon-reexec", VERB_ANY, 1, VERB_ONLINE_ONLY, daemon_reload },
8884 { "show-environment", VERB_ANY, 1, VERB_ONLINE_ONLY, show_environment },
8885 { "set-environment", 2, VERB_ANY, VERB_ONLINE_ONLY, set_environment },
8886 { "unset-environment", 2, VERB_ANY, VERB_ONLINE_ONLY, set_environment },
8887 { "import-environment", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, import_environment },
8888 { "halt", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special },
8889 { "poweroff", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special },
8890 { "reboot", VERB_ANY, 2, VERB_ONLINE_ONLY, start_system_special },
8891 { "kexec", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special },
8892 { "suspend", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special },
8893 { "hibernate", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special },
8894 { "hybrid-sleep", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special },
8895 { "suspend-then-hibernate",VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special },
8896 { "default", VERB_ANY, 1, VERB_ONLINE_ONLY, start_special },
8897 { "rescue", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special },
8898 { "emergency", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special },
8899 { "exit", VERB_ANY, 2, VERB_ONLINE_ONLY, start_special },
8900 { "reset-failed", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, reset_failed },
8901 { "enable", 2, VERB_ANY, 0, enable_unit },
8902 { "disable", 2, VERB_ANY, 0, enable_unit },
8903 { "is-enabled", 2, VERB_ANY, 0, unit_is_enabled },
8904 { "reenable", 2, VERB_ANY, 0, enable_unit },
8905 { "preset", 2, VERB_ANY, 0, enable_unit },
8906 { "preset-all", VERB_ANY, 1, 0, preset_all },
8907 { "mask", 2, VERB_ANY, 0, enable_unit },
8908 { "unmask", 2, VERB_ANY, 0, enable_unit },
8909 { "link", 2, VERB_ANY, 0, enable_unit },
8910 { "revert", 2, VERB_ANY, 0, enable_unit },
8911 { "switch-root", 2, VERB_ANY, VERB_ONLINE_ONLY, switch_root },
8912 { "list-dependencies", VERB_ANY, 2, VERB_ONLINE_ONLY, list_dependencies },
8913 { "set-default", 2, 2, 0, set_default },
8914 { "get-default", VERB_ANY, 1, 0, get_default },
8915 { "set-property", 3, VERB_ANY, VERB_ONLINE_ONLY, set_property },
8916 { "is-system-running", VERB_ANY, 1, 0, is_system_running },
8917 { "add-wants", 3, VERB_ANY, 0, add_dependency },
8918 { "add-requires", 3, VERB_ANY, 0, add_dependency },
8919 { "edit", 2, VERB_ANY, VERB_ONLINE_ONLY, edit },
8920 {}
8921 };
8922
8923 return dispatch_verb(argc, argv, verbs, NULL);
8924 }
8925
8926 static int reload_with_fallback(void) {
8927 /* First, try systemd via D-Bus. */
8928 if (daemon_reload(0, NULL, NULL) >= 0)
8929 return 0;
8930
8931 /* Nothing else worked, so let's try signals */
8932 assert(IN_SET(arg_action, ACTION_RELOAD, ACTION_REEXEC));
8933
8934 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0)
8935 return log_error_errno(errno, "kill() failed: %m");
8936
8937 return 0;
8938 }
8939
8940 static int start_with_fallback(void) {
8941 /* First, try systemd via D-Bus. */
8942 if (start_unit(0, NULL, NULL) >= 0)
8943 return 0;
8944
8945 /* Nothing else worked, so let's try /dev/initctl */
8946 if (talk_initctl() > 0)
8947 return 0;
8948
8949 return log_error_errno(SYNTHETIC_ERRNO(EIO),
8950 "Failed to talk to init daemon.");
8951 }
8952
8953 static int halt_now(enum action a) {
8954 /* The kernel will automatically flush ATA disks and suchlike on reboot(), but the file systems need to be
8955 * synced explicitly in advance. */
8956 if (!arg_no_sync && !arg_dry_run)
8957 (void) sync();
8958
8959 /* Make sure C-A-D is handled by the kernel from this point on... */
8960 if (!arg_dry_run)
8961 (void) reboot(RB_ENABLE_CAD);
8962
8963 switch (a) {
8964
8965 case ACTION_HALT:
8966 if (!arg_quiet)
8967 log_info("Halting.");
8968 if (arg_dry_run)
8969 return 0;
8970 (void) reboot(RB_HALT_SYSTEM);
8971 return -errno;
8972
8973 case ACTION_POWEROFF:
8974 if (!arg_quiet)
8975 log_info("Powering off.");
8976 if (arg_dry_run)
8977 return 0;
8978 (void) reboot(RB_POWER_OFF);
8979 return -errno;
8980
8981 case ACTION_KEXEC:
8982 case ACTION_REBOOT:
8983 return reboot_with_parameter(REBOOT_FALLBACK |
8984 (arg_quiet ? 0 : REBOOT_LOG) |
8985 (arg_dry_run ? REBOOT_DRY_RUN : 0));
8986
8987 default:
8988 assert_not_reached("Unknown action.");
8989 }
8990 }
8991
8992 static int logind_schedule_shutdown(void) {
8993
8994 #if ENABLE_LOGIND
8995 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
8996 char date[FORMAT_TIMESTAMP_MAX];
8997 const char *action;
8998 sd_bus *bus;
8999 int r;
9000
9001 r = acquire_bus(BUS_FULL, &bus);
9002 if (r < 0)
9003 return r;
9004
9005 switch (arg_action) {
9006 case ACTION_HALT:
9007 action = "halt";
9008 break;
9009 case ACTION_POWEROFF:
9010 action = "poweroff";
9011 break;
9012 case ACTION_KEXEC:
9013 action = "kexec";
9014 break;
9015 case ACTION_EXIT:
9016 action = "exit";
9017 break;
9018 case ACTION_REBOOT:
9019 default:
9020 action = "reboot";
9021 break;
9022 }
9023
9024 if (arg_dry_run)
9025 action = strjoina("dry-", action);
9026
9027 (void) logind_set_wall_message();
9028
9029 r = sd_bus_call_method(
9030 bus,
9031 "org.freedesktop.login1",
9032 "/org/freedesktop/login1",
9033 "org.freedesktop.login1.Manager",
9034 "ScheduleShutdown",
9035 &error,
9036 NULL,
9037 "st",
9038 action,
9039 arg_when);
9040 if (r < 0)
9041 return log_warning_errno(r, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s", bus_error_message(&error, r));
9042
9043 if (!arg_quiet)
9044 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.", format_timestamp(date, sizeof(date), arg_when));
9045 return 0;
9046 #else
9047 log_error("Cannot schedule shutdown without logind support, proceeding with immediate shutdown.");
9048 return -ENOSYS;
9049 #endif
9050 }
9051
9052 static int halt_main(void) {
9053 int r;
9054
9055 r = logind_check_inhibitors(arg_action);
9056 if (r < 0)
9057 return r;
9058
9059 /* Delayed shutdown requested, and was successful */
9060 if (arg_when > 0 && logind_schedule_shutdown() == 0)
9061 return 0;
9062 /* no delay, or logind failed or is not at all available */
9063
9064 if (geteuid() != 0) {
9065 if (arg_dry_run || arg_force > 0) {
9066 (void) must_be_root();
9067 return -EPERM;
9068 }
9069
9070 /* Try logind if we are a normal user and no special
9071 * mode applies. Maybe polkit allows us to shutdown
9072 * the machine. */
9073 if (IN_SET(arg_action, ACTION_POWEROFF, ACTION_REBOOT, ACTION_HALT)) {
9074 r = logind_reboot(arg_action);
9075 if (r >= 0)
9076 return r;
9077 if (IN_SET(r, -EOPNOTSUPP, -EINPROGRESS))
9078 /* requested operation is not
9079 * supported on the local system or
9080 * already in progress */
9081 return r;
9082 /* on all other errors, try low-level operation */
9083 }
9084 }
9085
9086 /* In order to minimize the difference between operation with and
9087 * without logind, we explicitly enable non-blocking mode for this,
9088 * as logind's shutdown operations are always non-blocking. */
9089 arg_no_block = true;
9090
9091 if (!arg_dry_run && !arg_force)
9092 return start_with_fallback();
9093
9094 assert(geteuid() == 0);
9095
9096 if (!arg_no_wtmp) {
9097 if (sd_booted() > 0)
9098 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
9099 else {
9100 r = utmp_put_shutdown();
9101 if (r < 0)
9102 log_warning_errno(r, "Failed to write utmp record: %m");
9103 }
9104 }
9105
9106 if (arg_dry_run)
9107 return 0;
9108
9109 r = halt_now(arg_action);
9110 return log_error_errno(r, "Failed to reboot: %m");
9111 }
9112
9113 static int runlevel_main(void) {
9114 int r, runlevel, previous;
9115
9116 r = utmp_get_runlevel(&runlevel, &previous);
9117 if (r < 0) {
9118 puts("unknown");
9119 return r;
9120 }
9121
9122 printf("%c %c\n",
9123 previous <= 0 ? 'N' : previous,
9124 runlevel <= 0 ? 'N' : runlevel);
9125
9126 return 0;
9127 }
9128
9129 static int logind_cancel_shutdown(void) {
9130 #if ENABLE_LOGIND
9131 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
9132 sd_bus *bus;
9133 int r;
9134
9135 r = acquire_bus(BUS_FULL, &bus);
9136 if (r < 0)
9137 return r;
9138
9139 (void) logind_set_wall_message();
9140
9141 r = sd_bus_call_method(
9142 bus,
9143 "org.freedesktop.login1",
9144 "/org/freedesktop/login1",
9145 "org.freedesktop.login1.Manager",
9146 "CancelScheduledShutdown",
9147 &error,
9148 NULL, NULL);
9149 if (r < 0)
9150 return log_warning_errno(r, "Failed to talk to logind, shutdown hasn't been cancelled: %s", bus_error_message(&error, r));
9151
9152 return 0;
9153 #else
9154 log_error("Not compiled with logind support, cannot cancel scheduled shutdowns.");
9155 return -ENOSYS;
9156 #endif
9157 }
9158
9159 static int run(int argc, char *argv[]) {
9160 int r;
9161
9162 argv_cmdline = argv[0];
9163
9164 setlocale(LC_ALL, "");
9165 log_parse_environment();
9166 log_open();
9167
9168 /* The journal merging logic potentially needs a lot of fds. */
9169 (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE);
9170
9171 sigbus_install();
9172
9173 /* Explicitly not on_tty() to avoid setting cached value.
9174 * This becomes relevant for piping output which might be
9175 * ellipsized. */
9176 original_stdout_is_tty = isatty(STDOUT_FILENO);
9177
9178 r = parse_argv(argc, argv);
9179 if (r <= 0)
9180 goto finish;
9181
9182 if (arg_action != ACTION_SYSTEMCTL && running_in_chroot() > 0) {
9183 if (!arg_quiet)
9184 log_info("Running in chroot, ignoring request.");
9185 r = 0;
9186 goto finish;
9187 }
9188
9189 /* systemctl_main() will print an error message for the bus
9190 * connection, but only if it needs to */
9191
9192 switch (arg_action) {
9193
9194 case ACTION_SYSTEMCTL:
9195 r = systemctl_main(argc, argv);
9196 break;
9197
9198 /* Legacy command aliases set arg_action. They provide some fallbacks,
9199 * e.g. to tell sysvinit to reboot after you have installed systemd
9200 * binaries. */
9201
9202 case ACTION_HALT:
9203 case ACTION_POWEROFF:
9204 case ACTION_REBOOT:
9205 case ACTION_KEXEC:
9206 r = halt_main();
9207 break;
9208
9209 case ACTION_RUNLEVEL2:
9210 case ACTION_RUNLEVEL3:
9211 case ACTION_RUNLEVEL4:
9212 case ACTION_RUNLEVEL5:
9213 case ACTION_RESCUE:
9214 r = start_with_fallback();
9215 break;
9216
9217 case ACTION_RELOAD:
9218 case ACTION_REEXEC:
9219 r = reload_with_fallback();
9220 break;
9221
9222 case ACTION_CANCEL_SHUTDOWN:
9223 r = logind_cancel_shutdown();
9224 break;
9225
9226 case ACTION_RUNLEVEL:
9227 r = runlevel_main();
9228 break;
9229
9230 case ACTION_EXIT:
9231 case ACTION_SUSPEND:
9232 case ACTION_HIBERNATE:
9233 case ACTION_HYBRID_SLEEP:
9234 case ACTION_SUSPEND_THEN_HIBERNATE:
9235 case ACTION_EMERGENCY:
9236 case ACTION_DEFAULT:
9237 /* systemctl verbs with no equivalent in the legacy commands.
9238 * These cannot appear in arg_action. Fall through. */
9239
9240 case _ACTION_INVALID:
9241 default:
9242 assert_not_reached("Unknown action");
9243 }
9244
9245 finish:
9246 release_busses();
9247
9248 strv_free(arg_types);
9249 strv_free(arg_states);
9250 strv_free(arg_properties);
9251
9252 strv_free(arg_wall);
9253 free(arg_root);
9254
9255 /* Note that we return r here, not 0, so that we can implement the LSB-like return codes */
9256 return r;
9257 }
9258
9259 DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run);