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