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