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