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