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