]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/systemctl/systemctl.c
systemctl: suggest -xe not -xn
[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);
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_close_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_INFINITY && 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_INFINITY && 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_ops);
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
1354 units = new(UnitFileList, n_units);
1355 if (!units && n_units > 0) {
1356 unit_file_list_free(h);
1357 return log_oom();
1358 }
1359
1360 HASHMAP_FOREACH(u, h, i) {
1361 if (!output_show_unit_file(u, strv_skip_first(args)))
1362 continue;
1363
1364 units[c++] = *u;
1365 free(u);
1366 }
1367
1368 assert(c <= n_units);
1369 hashmap_free(h);
1370 } else {
1371 r = sd_bus_call_method(
1372 bus,
1373 "org.freedesktop.systemd1",
1374 "/org/freedesktop/systemd1",
1375 "org.freedesktop.systemd1.Manager",
1376 "ListUnitFiles",
1377 &error,
1378 &reply,
1379 NULL);
1380 if (r < 0) {
1381 log_error("Failed to list unit files: %s", bus_error_message(&error, r));
1382 return r;
1383 }
1384
1385 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
1386 if (r < 0)
1387 return bus_log_parse_error(r);
1388
1389 while ((r = sd_bus_message_read(reply, "(ss)", &path, &state)) > 0) {
1390
1391 if (!GREEDY_REALLOC(units, size, c + 1))
1392 return log_oom();
1393
1394 units[c] = (struct UnitFileList) {
1395 path,
1396 unit_file_state_from_string(state)
1397 };
1398
1399 if (output_show_unit_file(&units[c], strv_skip_first(args)))
1400 c ++;
1401
1402 }
1403 if (r < 0)
1404 return bus_log_parse_error(r);
1405
1406 r = sd_bus_message_exit_container(reply);
1407 if (r < 0)
1408 return bus_log_parse_error(r);
1409 }
1410
1411 qsort_safe(units, c, sizeof(UnitFileList), compare_unit_file_list);
1412 output_unit_file_list(units, c);
1413
1414 if (avoid_bus()) {
1415 for (unit = units; unit < units + c; unit++)
1416 free(unit->path);
1417 }
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_close_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 -xe' for details.", strna(d->name));
2354 else if (!streq(d->result, "done") && !streq(d->result, "skipped")) {
2355 if (d->name) {
2356 bool quotes;
2357
2358 quotes = chars_intersect(d->name, SHELL_NEED_QUOTES);
2359
2360 log_error("Job for %s failed. See \"systemctl status %s%s%s\" and \"journalctl -xe\" for details.",
2361 d->name,
2362 quotes ? "'" : "", d->name, quotes ? "'" : "");
2363 } else
2364 log_error("Job failed. See \"journalctl -xe\" for details.");
2365 }
2366 }
2367
2368 if (streq(d->result, "timeout"))
2369 r = -ETIME;
2370 else if (streq(d->result, "canceled"))
2371 r = -ECANCELED;
2372 else if (streq(d->result, "dependency"))
2373 r = -EIO;
2374 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
2375 r = -EIO;
2376
2377 return r;
2378 }
2379
2380 static int wait_for_jobs(sd_bus *bus, Set *s) {
2381 _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL;
2382 WaitData d = { .set = s };
2383 int r = 0, q;
2384
2385 assert(bus);
2386 assert(s);
2387
2388 q = sd_bus_add_filter(bus, &slot, wait_filter, &d);
2389 if (q < 0)
2390 return log_oom();
2391
2392 while (!set_isempty(s)) {
2393 q = bus_process_wait(bus);
2394 if (q < 0) {
2395 log_error("Failed to wait for response: %s", strerror(-q));
2396 return q;
2397 }
2398
2399 if (d.result) {
2400 q = check_wait_response(&d);
2401 /* Return the first error as it is most likely to be
2402 * meaningful. */
2403 if (q < 0 && r == 0)
2404 r = q;
2405 log_debug("Got result %s/%s for job %s",
2406 strna(d.result), strerror(-q), strna(d.name));
2407 }
2408
2409 free(d.name);
2410 d.name = NULL;
2411
2412 free(d.result);
2413 d.result = NULL;
2414 }
2415
2416 return r;
2417 }
2418
2419 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
2420 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2421 _cleanup_free_ char *n = NULL, *state = NULL;
2422 const char *path;
2423 int r;
2424
2425 assert(name);
2426
2427 n = unit_name_mangle(name, MANGLE_NOGLOB);
2428 if (!n)
2429 return log_oom();
2430
2431 /* We don't use unit_dbus_path_from_name() directly since we
2432 * don't want to load the unit if it isn't loaded. */
2433
2434 r = sd_bus_call_method(
2435 bus,
2436 "org.freedesktop.systemd1",
2437 "/org/freedesktop/systemd1",
2438 "org.freedesktop.systemd1.Manager",
2439 "GetUnit",
2440 NULL,
2441 &reply,
2442 "s", n);
2443 if (r < 0) {
2444 if (!quiet)
2445 puts("unknown");
2446 return 0;
2447 }
2448
2449 r = sd_bus_message_read(reply, "o", &path);
2450 if (r < 0)
2451 return bus_log_parse_error(r);
2452
2453 r = sd_bus_get_property_string(
2454 bus,
2455 "org.freedesktop.systemd1",
2456 path,
2457 "org.freedesktop.systemd1.Unit",
2458 "ActiveState",
2459 NULL,
2460 &state);
2461 if (r < 0) {
2462 if (!quiet)
2463 puts("unknown");
2464 return 0;
2465 }
2466
2467 if (!quiet)
2468 puts(state);
2469
2470 return nulstr_contains(good_states, state);
2471 }
2472
2473 static int check_triggering_units(
2474 sd_bus *bus,
2475 const char *name) {
2476
2477 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2478 _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
2479 _cleanup_strv_free_ char **triggered_by = NULL;
2480 bool print_warning_label = true;
2481 char **i;
2482 int r;
2483
2484 n = unit_name_mangle(name, MANGLE_NOGLOB);
2485 if (!n)
2486 return log_oom();
2487
2488 path = unit_dbus_path_from_name(n);
2489 if (!path)
2490 return log_oom();
2491
2492 r = sd_bus_get_property_string(
2493 bus,
2494 "org.freedesktop.systemd1",
2495 path,
2496 "org.freedesktop.systemd1.Unit",
2497 "LoadState",
2498 &error,
2499 &state);
2500 if (r < 0) {
2501 log_error("Failed to get load state of %s: %s", n, bus_error_message(&error, r));
2502 return r;
2503 }
2504
2505 if (streq(state, "masked"))
2506 return 0;
2507
2508 r = sd_bus_get_property_strv(
2509 bus,
2510 "org.freedesktop.systemd1",
2511 path,
2512 "org.freedesktop.systemd1.Unit",
2513 "TriggeredBy",
2514 &error,
2515 &triggered_by);
2516 if (r < 0) {
2517 log_error("Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
2518 return r;
2519 }
2520
2521 STRV_FOREACH(i, triggered_by) {
2522 r = check_one_unit(bus, *i, "active\0reloading\0", true);
2523 if (r < 0) {
2524 log_error("Failed to check unit: %s", strerror(-r));
2525 return r;
2526 }
2527
2528 if (r == 0)
2529 continue;
2530
2531 if (print_warning_label) {
2532 log_warning("Warning: Stopping %s, but it can still be activated by:", n);
2533 print_warning_label = false;
2534 }
2535
2536 log_warning(" %s", *i);
2537 }
2538
2539 return 0;
2540 }
2541
2542 static const char *verb_to_method(const char *verb) {
2543 uint i;
2544
2545 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2546 if (streq_ptr(unit_actions[i].verb, verb))
2547 return unit_actions[i].method;
2548
2549 return "StartUnit";
2550 }
2551
2552 static const char *method_to_verb(const char *method) {
2553 uint i;
2554
2555 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2556 if (streq_ptr(unit_actions[i].method, method))
2557 return unit_actions[i].verb;
2558
2559 return "n/a";
2560 }
2561
2562 static int start_unit_one(
2563 sd_bus *bus,
2564 const char *method,
2565 const char *name,
2566 const char *mode,
2567 sd_bus_error *error,
2568 Set *s) {
2569
2570 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2571 const char *path;
2572 int r;
2573
2574 assert(method);
2575 assert(name);
2576 assert(mode);
2577 assert(error);
2578
2579 log_debug("Calling manager for %s on %s, %s", method, name, mode);
2580 r = sd_bus_call_method(
2581 bus,
2582 "org.freedesktop.systemd1",
2583 "/org/freedesktop/systemd1",
2584 "org.freedesktop.systemd1.Manager",
2585 method,
2586 error,
2587 &reply,
2588 "ss", name, mode);
2589 if (r < 0) {
2590 const char *verb;
2591
2592 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
2593 /* There's always a fallback possible for
2594 * legacy actions. */
2595 return -EADDRNOTAVAIL;
2596
2597 verb = method_to_verb(method);
2598
2599 log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r));
2600 return r;
2601 }
2602
2603 r = sd_bus_message_read(reply, "o", &path);
2604 if (r < 0)
2605 return bus_log_parse_error(r);
2606
2607 if (need_daemon_reload(bus, name) > 0)
2608 log_warning("Warning: Unit file of %s changed on disk, 'systemctl%s daemon-reload' recommended.",
2609 name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
2610
2611 if (s) {
2612 char *p;
2613
2614 p = strdup(path);
2615 if (!p)
2616 return log_oom();
2617
2618 log_debug("Adding %s to the set", p);
2619 r = set_consume(s, p);
2620 if (r < 0)
2621 return log_oom();
2622 }
2623
2624 return 0;
2625 }
2626
2627 static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret) {
2628
2629 _cleanup_strv_free_ char **mangled = NULL, **globs = NULL;
2630 char **name;
2631 int r = 0, i;
2632
2633 STRV_FOREACH(name, names) {
2634 char *t;
2635
2636 if (suffix)
2637 t = unit_name_mangle_with_suffix(*name, MANGLE_GLOB, suffix);
2638 else
2639 t = unit_name_mangle(*name, MANGLE_GLOB);
2640 if (!t)
2641 return log_oom();
2642
2643 if (string_is_glob(t))
2644 r = strv_consume(&globs, t);
2645 else
2646 r = strv_consume(&mangled, t);
2647 if (r < 0)
2648 return log_oom();
2649 }
2650
2651 /* Query the manager only if any of the names are a glob, since
2652 * this is fairly expensive */
2653 if (!strv_isempty(globs)) {
2654 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2655 _cleanup_free_ UnitInfo *unit_infos = NULL;
2656
2657 r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
2658 if (r < 0)
2659 return r;
2660
2661 for (i = 0; i < r; i++)
2662 if (strv_extend(&mangled, unit_infos[i].id) < 0)
2663 return log_oom();
2664 }
2665
2666 *ret = mangled;
2667 mangled = NULL; /* do not free */
2668
2669 return 0;
2670 }
2671
2672 static const struct {
2673 const char *target;
2674 const char *verb;
2675 const char *mode;
2676 } action_table[_ACTION_MAX] = {
2677 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
2678 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
2679 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
2680 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
2681 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
2682 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
2683 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
2684 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
2685 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
2686 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
2687 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
2688 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
2689 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
2690 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
2691 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
2692 };
2693
2694 static enum action verb_to_action(const char *verb) {
2695 enum action i;
2696
2697 for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
2698 if (streq_ptr(action_table[i].verb, verb))
2699 return i;
2700
2701 return _ACTION_INVALID;
2702 }
2703
2704 static int start_unit(sd_bus *bus, char **args) {
2705 _cleanup_set_free_free_ Set *s = NULL;
2706 _cleanup_strv_free_ char **names = NULL;
2707 const char *method, *mode, *one_name;
2708 char **name;
2709 int r = 0;
2710
2711 assert(bus);
2712
2713 ask_password_agent_open_if_enabled();
2714
2715 if (arg_action == ACTION_SYSTEMCTL) {
2716 enum action action;
2717 method = verb_to_method(args[0]);
2718 action = verb_to_action(args[0]);
2719
2720 mode = streq(args[0], "isolate") ? "isolate" :
2721 action_table[action].mode ?: arg_job_mode;
2722
2723 one_name = action_table[action].target;
2724 } else {
2725 assert(arg_action < ELEMENTSOF(action_table));
2726 assert(action_table[arg_action].target);
2727
2728 method = "StartUnit";
2729
2730 mode = action_table[arg_action].mode;
2731 one_name = action_table[arg_action].target;
2732 }
2733
2734 if (one_name)
2735 names = strv_new(one_name, NULL);
2736 else {
2737 r = expand_names(bus, args + 1, NULL, &names);
2738 if (r < 0)
2739 log_error("Failed to expand names: %s", strerror(-r));
2740 }
2741
2742 if (!arg_no_block) {
2743 r = enable_wait_for_jobs(bus);
2744 if (r < 0) {
2745 log_error("Could not watch jobs: %s", strerror(-r));
2746 return r;
2747 }
2748
2749 s = set_new(&string_hash_ops);
2750 if (!s)
2751 return log_oom();
2752 }
2753
2754 STRV_FOREACH(name, names) {
2755 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2756 int q;
2757
2758 q = start_unit_one(bus, method, *name, mode, &error, s);
2759 if (r >= 0 && q < 0)
2760 r = translate_bus_error_to_exit_status(q, &error);
2761 }
2762
2763 if (!arg_no_block) {
2764 int q;
2765
2766 q = wait_for_jobs(bus, s);
2767 if (q < 0)
2768 return q;
2769
2770 /* When stopping units, warn if they can still be triggered by
2771 * another active unit (socket, path, timer) */
2772 if (!arg_quiet && streq(method, "StopUnit"))
2773 STRV_FOREACH(name, names)
2774 check_triggering_units(bus, *name);
2775 }
2776
2777 return r;
2778 }
2779
2780 /* Ask systemd-logind, which might grant access to unprivileged users
2781 * through PolicyKit */
2782 static int reboot_with_logind(sd_bus *bus, enum action a) {
2783 #ifdef HAVE_LOGIND
2784 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2785 const char *method;
2786 int r;
2787
2788 if (!bus)
2789 return -EIO;
2790
2791 polkit_agent_open_if_enabled();
2792
2793 switch (a) {
2794
2795 case ACTION_REBOOT:
2796 method = "Reboot";
2797 break;
2798
2799 case ACTION_POWEROFF:
2800 method = "PowerOff";
2801 break;
2802
2803 case ACTION_SUSPEND:
2804 method = "Suspend";
2805 break;
2806
2807 case ACTION_HIBERNATE:
2808 method = "Hibernate";
2809 break;
2810
2811 case ACTION_HYBRID_SLEEP:
2812 method = "HybridSleep";
2813 break;
2814
2815 default:
2816 return -EINVAL;
2817 }
2818
2819 r = sd_bus_call_method(
2820 bus,
2821 "org.freedesktop.login1",
2822 "/org/freedesktop/login1",
2823 "org.freedesktop.login1.Manager",
2824 method,
2825 &error,
2826 NULL,
2827 "b", true);
2828 if (r < 0)
2829 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
2830
2831 return r;
2832 #else
2833 return -ENOSYS;
2834 #endif
2835 }
2836
2837 static int check_inhibitors(sd_bus *bus, enum action a) {
2838 #ifdef HAVE_LOGIND
2839 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2840 _cleanup_strv_free_ char **sessions = NULL;
2841 const char *what, *who, *why, *mode;
2842 uint32_t uid, pid;
2843 unsigned c = 0;
2844 char **s;
2845 int r;
2846
2847 if (!bus)
2848 return 0;
2849
2850 if (arg_ignore_inhibitors || arg_force > 0)
2851 return 0;
2852
2853 if (arg_when > 0)
2854 return 0;
2855
2856 if (geteuid() == 0)
2857 return 0;
2858
2859 if (!on_tty())
2860 return 0;
2861
2862 r = sd_bus_call_method(
2863 bus,
2864 "org.freedesktop.login1",
2865 "/org/freedesktop/login1",
2866 "org.freedesktop.login1.Manager",
2867 "ListInhibitors",
2868 NULL,
2869 &reply,
2870 NULL);
2871 if (r < 0)
2872 /* If logind is not around, then there are no inhibitors... */
2873 return 0;
2874
2875 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
2876 if (r < 0)
2877 return bus_log_parse_error(r);
2878
2879 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
2880 _cleanup_free_ char *comm = NULL, *user = NULL;
2881 _cleanup_strv_free_ char **sv = NULL;
2882
2883 if (!streq(mode, "block"))
2884 continue;
2885
2886 sv = strv_split(what, ":");
2887 if (!sv)
2888 return log_oom();
2889
2890 if (!strv_contains(sv,
2891 a == ACTION_HALT ||
2892 a == ACTION_POWEROFF ||
2893 a == ACTION_REBOOT ||
2894 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2895 continue;
2896
2897 get_process_comm(pid, &comm);
2898 user = uid_to_name(uid);
2899
2900 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
2901 who, pid, strna(comm), strna(user), why);
2902
2903 c++;
2904 }
2905 if (r < 0)
2906 return bus_log_parse_error(r);
2907
2908 r = sd_bus_message_exit_container(reply);
2909 if (r < 0)
2910 return bus_log_parse_error(r);
2911
2912 /* Check for current sessions */
2913 sd_get_sessions(&sessions);
2914 STRV_FOREACH(s, sessions) {
2915 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2916
2917 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2918 continue;
2919
2920 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2921 continue;
2922
2923 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2924 continue;
2925
2926 sd_session_get_tty(*s, &tty);
2927 sd_session_get_seat(*s, &seat);
2928 sd_session_get_service(*s, &service);
2929 user = uid_to_name(uid);
2930
2931 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2932 c++;
2933 }
2934
2935 if (c <= 0)
2936 return 0;
2937
2938 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2939 action_table[a].verb);
2940
2941 return -EPERM;
2942 #else
2943 return 0;
2944 #endif
2945 }
2946
2947 static int start_special(sd_bus *bus, char **args) {
2948 enum action a;
2949 int r;
2950
2951 assert(args);
2952
2953 a = verb_to_action(args[0]);
2954
2955 r = check_inhibitors(bus, a);
2956 if (r < 0)
2957 return r;
2958
2959 if (arg_force >= 2 && geteuid() != 0) {
2960 log_error("Must be root.");
2961 return -EPERM;
2962 }
2963
2964 if (arg_force >= 2 &&
2965 (a == ACTION_HALT ||
2966 a == ACTION_POWEROFF ||
2967 a == ACTION_REBOOT))
2968 return halt_now(a);
2969
2970 if (arg_force >= 1 &&
2971 (a == ACTION_HALT ||
2972 a == ACTION_POWEROFF ||
2973 a == ACTION_REBOOT ||
2974 a == ACTION_KEXEC ||
2975 a == ACTION_EXIT))
2976 return daemon_reload(bus, args);
2977
2978 /* first try logind, to allow authentication with polkit */
2979 if (geteuid() != 0 &&
2980 (a == ACTION_POWEROFF ||
2981 a == ACTION_REBOOT ||
2982 a == ACTION_SUSPEND ||
2983 a == ACTION_HIBERNATE ||
2984 a == ACTION_HYBRID_SLEEP)) {
2985 r = reboot_with_logind(bus, a);
2986 if (r >= 0)
2987 return r;
2988 }
2989
2990 r = start_unit(bus, args);
2991 if (r == EXIT_SUCCESS)
2992 warn_wall(a);
2993
2994 return r;
2995 }
2996
2997 static int check_unit_generic(sd_bus *bus, int code, const char *good_states, char **args) {
2998 _cleanup_strv_free_ char **names = NULL;
2999 char **name;
3000 int r;
3001
3002 assert(bus);
3003 assert(args);
3004
3005 r = expand_names(bus, args, NULL, &names);
3006 if (r < 0) {
3007 log_error("Failed to expand names: %s", strerror(-r));
3008 return r;
3009 }
3010
3011 STRV_FOREACH(name, names) {
3012 int state;
3013
3014 state = check_one_unit(bus, *name, good_states, arg_quiet);
3015 if (state < 0)
3016 return state;
3017 if (state == 0)
3018 r = code;
3019 }
3020
3021 return r;
3022 }
3023
3024 static int check_unit_active(sd_bus *bus, char **args) {
3025 /* According to LSB: 3, "program is not running" */
3026 return check_unit_generic(bus, 3, "active\0reloading\0", args + 1);
3027 }
3028
3029 static int check_unit_failed(sd_bus *bus, char **args) {
3030 return check_unit_generic(bus, 1, "failed\0", args + 1);
3031 }
3032
3033 static int kill_unit(sd_bus *bus, char **args) {
3034 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3035 _cleanup_strv_free_ char **names = NULL;
3036 char **name;
3037 int r, q;
3038
3039 assert(bus);
3040 assert(args);
3041
3042 if (!arg_kill_who)
3043 arg_kill_who = "all";
3044
3045 r = expand_names(bus, args + 1, NULL, &names);
3046 if (r < 0)
3047 log_error("Failed to expand names: %s", strerror(-r));
3048
3049 STRV_FOREACH(name, names) {
3050 q = sd_bus_call_method(
3051 bus,
3052 "org.freedesktop.systemd1",
3053 "/org/freedesktop/systemd1",
3054 "org.freedesktop.systemd1.Manager",
3055 "KillUnit",
3056 &error,
3057 NULL,
3058 "ssi", *names, arg_kill_who, arg_signal);
3059 if (q < 0) {
3060 log_error("Failed to kill unit %s: %s",
3061 *names, bus_error_message(&error, r));
3062 if (r == 0)
3063 r = q;
3064 }
3065 }
3066
3067 return r;
3068 }
3069
3070 typedef struct ExecStatusInfo {
3071 char *name;
3072
3073 char *path;
3074 char **argv;
3075
3076 bool ignore;
3077
3078 usec_t start_timestamp;
3079 usec_t exit_timestamp;
3080 pid_t pid;
3081 int code;
3082 int status;
3083
3084 LIST_FIELDS(struct ExecStatusInfo, exec);
3085 } ExecStatusInfo;
3086
3087 static void exec_status_info_free(ExecStatusInfo *i) {
3088 assert(i);
3089
3090 free(i->name);
3091 free(i->path);
3092 strv_free(i->argv);
3093 free(i);
3094 }
3095
3096 static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
3097 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
3098 const char *path;
3099 uint32_t pid;
3100 int32_t code, status;
3101 int ignore, r;
3102
3103 assert(m);
3104 assert(i);
3105
3106 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii");
3107 if (r < 0)
3108 return bus_log_parse_error(r);
3109 else if (r == 0)
3110 return 0;
3111
3112 r = sd_bus_message_read(m, "s", &path);
3113 if (r < 0)
3114 return bus_log_parse_error(r);
3115
3116 i->path = strdup(path);
3117 if (!i->path)
3118 return log_oom();
3119
3120 r = sd_bus_message_read_strv(m, &i->argv);
3121 if (r < 0)
3122 return bus_log_parse_error(r);
3123
3124 r = sd_bus_message_read(m,
3125 "bttttuii",
3126 &ignore,
3127 &start_timestamp, &start_timestamp_monotonic,
3128 &exit_timestamp, &exit_timestamp_monotonic,
3129 &pid,
3130 &code, &status);
3131 if (r < 0)
3132 return bus_log_parse_error(r);
3133
3134 i->ignore = ignore;
3135 i->start_timestamp = (usec_t) start_timestamp;
3136 i->exit_timestamp = (usec_t) exit_timestamp;
3137 i->pid = (pid_t) pid;
3138 i->code = code;
3139 i->status = status;
3140
3141 r = sd_bus_message_exit_container(m);
3142 if (r < 0)
3143 return bus_log_parse_error(r);
3144
3145 return 1;
3146 }
3147
3148 typedef struct UnitStatusInfo {
3149 const char *id;
3150 const char *load_state;
3151 const char *active_state;
3152 const char *sub_state;
3153 const char *unit_file_state;
3154
3155 const char *description;
3156 const char *following;
3157
3158 char **documentation;
3159
3160 const char *fragment_path;
3161 const char *source_path;
3162 const char *control_group;
3163
3164 char **dropin_paths;
3165
3166 const char *load_error;
3167 const char *result;
3168
3169 usec_t inactive_exit_timestamp;
3170 usec_t inactive_exit_timestamp_monotonic;
3171 usec_t active_enter_timestamp;
3172 usec_t active_exit_timestamp;
3173 usec_t inactive_enter_timestamp;
3174
3175 bool need_daemon_reload;
3176
3177 /* Service */
3178 pid_t main_pid;
3179 pid_t control_pid;
3180 const char *status_text;
3181 const char *pid_file;
3182 bool running:1;
3183 int status_errno;
3184
3185 usec_t start_timestamp;
3186 usec_t exit_timestamp;
3187
3188 int exit_code, exit_status;
3189
3190 usec_t condition_timestamp;
3191 bool condition_result;
3192 bool failed_condition_trigger;
3193 bool failed_condition_negate;
3194 const char *failed_condition;
3195 const char *failed_condition_param;
3196
3197 /* Socket */
3198 unsigned n_accepted;
3199 unsigned n_connections;
3200 bool accept;
3201
3202 /* Pairs of type, path */
3203 char **listen;
3204
3205 /* Device */
3206 const char *sysfs_path;
3207
3208 /* Mount, Automount */
3209 const char *where;
3210
3211 /* Swap */
3212 const char *what;
3213
3214 LIST_HEAD(ExecStatusInfo, exec);
3215 } UnitStatusInfo;
3216
3217 static void print_status_info(
3218 UnitStatusInfo *i,
3219 bool *ellipsized) {
3220
3221 ExecStatusInfo *p;
3222 const char *active_on, *active_off, *on, *off, *ss;
3223 usec_t timestamp;
3224 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
3225 char since2[FORMAT_TIMESTAMP_MAX], *s2;
3226 const char *path;
3227 int flags =
3228 arg_all * OUTPUT_SHOW_ALL |
3229 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
3230 on_tty() * OUTPUT_COLOR |
3231 !arg_quiet * OUTPUT_WARN_CUTOFF |
3232 arg_full * OUTPUT_FULL_WIDTH;
3233 char **t, **t2;
3234
3235 assert(i);
3236
3237 /* This shows pretty information about a unit. See
3238 * print_property() for a low-level property printer */
3239
3240 if (streq_ptr(i->active_state, "failed")) {
3241 active_on = ansi_highlight_red();
3242 active_off = ansi_highlight_off();
3243 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
3244 active_on = ansi_highlight_green();
3245 active_off = ansi_highlight_off();
3246 } else
3247 active_on = active_off = "";
3248
3249 printf("%s%s%s %s", active_on, draw_special_char(DRAW_BLACK_CIRCLE), active_off, strna(i->id));
3250
3251 if (i->description && !streq_ptr(i->id, i->description))
3252 printf(" - %s", i->description);
3253
3254 printf("\n");
3255
3256 if (i->following)
3257 printf(" Follow: unit currently follows state of %s\n", i->following);
3258
3259 if (streq_ptr(i->load_state, "error")) {
3260 on = ansi_highlight_red();
3261 off = ansi_highlight_off();
3262 } else
3263 on = off = "";
3264
3265 path = i->source_path ? i->source_path : i->fragment_path;
3266
3267 if (i->load_error)
3268 printf(" Loaded: %s%s%s (Reason: %s)\n",
3269 on, strna(i->load_state), off, i->load_error);
3270 else if (path && i->unit_file_state)
3271 printf(" Loaded: %s%s%s (%s; %s)\n",
3272 on, strna(i->load_state), off, path, i->unit_file_state);
3273 else if (path)
3274 printf(" Loaded: %s%s%s (%s)\n",
3275 on, strna(i->load_state), off, path);
3276 else
3277 printf(" Loaded: %s%s%s\n",
3278 on, strna(i->load_state), off);
3279
3280 if (!strv_isempty(i->dropin_paths)) {
3281 _cleanup_free_ char *dir = NULL;
3282 bool last = false;
3283 char ** dropin;
3284
3285 STRV_FOREACH(dropin, i->dropin_paths) {
3286 if (! dir || last) {
3287 printf(dir ? " " : " Drop-In: ");
3288
3289 free(dir);
3290 dir = NULL;
3291
3292 if (path_get_parent(*dropin, &dir) < 0) {
3293 log_oom();
3294 return;
3295 }
3296
3297 printf("%s\n %s", dir,
3298 draw_special_char(DRAW_TREE_RIGHT));
3299 }
3300
3301 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
3302
3303 printf("%s%s", basename(*dropin), last ? "\n" : ", ");
3304 }
3305 }
3306
3307 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
3308 if (ss)
3309 printf(" Active: %s%s (%s)%s",
3310 active_on, strna(i->active_state), ss, active_off);
3311 else
3312 printf(" Active: %s%s%s",
3313 active_on, strna(i->active_state), active_off);
3314
3315 if (!isempty(i->result) && !streq(i->result, "success"))
3316 printf(" (Result: %s)", i->result);
3317
3318 timestamp = (streq_ptr(i->active_state, "active") ||
3319 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
3320 (streq_ptr(i->active_state, "inactive") ||
3321 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
3322 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
3323 i->active_exit_timestamp;
3324
3325 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
3326 s2 = format_timestamp(since2, sizeof(since2), timestamp);
3327
3328 if (s1)
3329 printf(" since %s; %s\n", s2, s1);
3330 else if (s2)
3331 printf(" since %s\n", s2);
3332 else
3333 printf("\n");
3334
3335 if (!i->condition_result && i->condition_timestamp > 0) {
3336 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
3337 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
3338
3339 printf(" start condition failed at %s%s%s\n",
3340 s2, s1 ? "; " : "", s1 ? s1 : "");
3341 if (i->failed_condition_trigger)
3342 printf(" none of the trigger conditions were met\n");
3343 else if (i->failed_condition)
3344 printf(" %s=%s%s was not met\n",
3345 i->failed_condition,
3346 i->failed_condition_negate ? "!" : "",
3347 i->failed_condition_param);
3348 }
3349
3350 if (i->sysfs_path)
3351 printf(" Device: %s\n", i->sysfs_path);
3352 if (i->where)
3353 printf(" Where: %s\n", i->where);
3354 if (i->what)
3355 printf(" What: %s\n", i->what);
3356
3357 STRV_FOREACH(t, i->documentation)
3358 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
3359
3360 STRV_FOREACH_PAIR(t, t2, i->listen)
3361 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
3362
3363 if (i->accept)
3364 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
3365
3366 LIST_FOREACH(exec, p, i->exec) {
3367 _cleanup_free_ char *argv = NULL;
3368 bool good;
3369
3370 /* Only show exited processes here */
3371 if (p->code == 0)
3372 continue;
3373
3374 argv = strv_join(p->argv, " ");
3375 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
3376
3377 good = is_clean_exit_lsb(p->code, p->status, NULL);
3378 if (!good) {
3379 on = ansi_highlight_red();
3380 off = ansi_highlight_off();
3381 } else
3382 on = off = "";
3383
3384 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
3385
3386 if (p->code == CLD_EXITED) {
3387 const char *c;
3388
3389 printf("status=%i", p->status);
3390
3391 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
3392 if (c)
3393 printf("/%s", c);
3394
3395 } else
3396 printf("signal=%s", signal_to_string(p->status));
3397
3398 printf(")%s\n", off);
3399
3400 if (i->main_pid == p->pid &&
3401 i->start_timestamp == p->start_timestamp &&
3402 i->exit_timestamp == p->start_timestamp)
3403 /* Let's not show this twice */
3404 i->main_pid = 0;
3405
3406 if (p->pid == i->control_pid)
3407 i->control_pid = 0;
3408 }
3409
3410 if (i->main_pid > 0 || i->control_pid > 0) {
3411 if (i->main_pid > 0) {
3412 printf(" Main PID: %u", (unsigned) i->main_pid);
3413
3414 if (i->running) {
3415 _cleanup_free_ char *comm = NULL;
3416 get_process_comm(i->main_pid, &comm);
3417 if (comm)
3418 printf(" (%s)", comm);
3419 } else if (i->exit_code > 0) {
3420 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
3421
3422 if (i->exit_code == CLD_EXITED) {
3423 const char *c;
3424
3425 printf("status=%i", i->exit_status);
3426
3427 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
3428 if (c)
3429 printf("/%s", c);
3430
3431 } else
3432 printf("signal=%s", signal_to_string(i->exit_status));
3433 printf(")");
3434 }
3435
3436 if (i->control_pid > 0)
3437 printf(";");
3438 }
3439
3440 if (i->control_pid > 0) {
3441 _cleanup_free_ char *c = NULL;
3442
3443 printf(" %8s: %u", i->main_pid ? "" : " Control", (unsigned) i->control_pid);
3444
3445 get_process_comm(i->control_pid, &c);
3446 if (c)
3447 printf(" (%s)", c);
3448 }
3449
3450 printf("\n");
3451 }
3452
3453 if (i->status_text)
3454 printf(" Status: \"%s\"\n", i->status_text);
3455 if (i->status_errno > 0)
3456 printf(" Error: %i (%s)\n", i->status_errno, strerror(i->status_errno));
3457
3458 if (i->control_group &&
3459 (i->main_pid > 0 || i->control_pid > 0 ||
3460 ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_CONTAINER) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) {
3461 unsigned c;
3462
3463 printf(" CGroup: %s\n", i->control_group);
3464
3465 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
3466 unsigned k = 0;
3467 pid_t extra[2];
3468 static const char prefix[] = " ";
3469
3470 c = columns();
3471 if (c > sizeof(prefix) - 1)
3472 c -= sizeof(prefix) - 1;
3473 else
3474 c = 0;
3475
3476 if (i->main_pid > 0)
3477 extra[k++] = i->main_pid;
3478
3479 if (i->control_pid > 0)
3480 extra[k++] = i->control_pid;
3481
3482 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, false, extra, k, flags);
3483 }
3484 }
3485
3486 if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) {
3487 show_journal_by_unit(stdout,
3488 i->id,
3489 arg_output,
3490 0,
3491 i->inactive_exit_timestamp_monotonic,
3492 arg_lines,
3493 getuid(),
3494 flags | OUTPUT_BEGIN_NEWLINE,
3495 arg_scope == UNIT_FILE_SYSTEM,
3496 ellipsized);
3497 }
3498
3499 if (i->need_daemon_reload)
3500 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
3501 ansi_highlight_red(),
3502 ansi_highlight_off(),
3503 arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
3504 }
3505
3506 static void show_unit_help(UnitStatusInfo *i) {
3507 char **p;
3508
3509 assert(i);
3510
3511 if (!i->documentation) {
3512 log_info("Documentation for %s not known.", i->id);
3513 return;
3514 }
3515
3516 STRV_FOREACH(p, i->documentation)
3517 if (startswith(*p, "man:"))
3518 show_man_page(*p + 4, false);
3519 else
3520 log_info("Can't show: %s", *p);
3521 }
3522
3523 static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) {
3524 int r;
3525
3526 assert(name);
3527 assert(m);
3528 assert(i);
3529
3530 switch (contents[0]) {
3531
3532 case SD_BUS_TYPE_STRING: {
3533 const char *s;
3534
3535 r = sd_bus_message_read(m, "s", &s);
3536 if (r < 0)
3537 return bus_log_parse_error(r);
3538
3539 if (!isempty(s)) {
3540 if (streq(name, "Id"))
3541 i->id = s;
3542 else if (streq(name, "LoadState"))
3543 i->load_state = s;
3544 else if (streq(name, "ActiveState"))
3545 i->active_state = s;
3546 else if (streq(name, "SubState"))
3547 i->sub_state = s;
3548 else if (streq(name, "Description"))
3549 i->description = s;
3550 else if (streq(name, "FragmentPath"))
3551 i->fragment_path = s;
3552 else if (streq(name, "SourcePath"))
3553 i->source_path = s;
3554 #ifndef NOLEGACY
3555 else if (streq(name, "DefaultControlGroup")) {
3556 const char *e;
3557 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
3558 if (e)
3559 i->control_group = e;
3560 }
3561 #endif
3562 else if (streq(name, "ControlGroup"))
3563 i->control_group = s;
3564 else if (streq(name, "StatusText"))
3565 i->status_text = s;
3566 else if (streq(name, "PIDFile"))
3567 i->pid_file = s;
3568 else if (streq(name, "SysFSPath"))
3569 i->sysfs_path = s;
3570 else if (streq(name, "Where"))
3571 i->where = s;
3572 else if (streq(name, "What"))
3573 i->what = s;
3574 else if (streq(name, "Following"))
3575 i->following = s;
3576 else if (streq(name, "UnitFileState"))
3577 i->unit_file_state = s;
3578 else if (streq(name, "Result"))
3579 i->result = s;
3580 }
3581
3582 break;
3583 }
3584
3585 case SD_BUS_TYPE_BOOLEAN: {
3586 int b;
3587
3588 r = sd_bus_message_read(m, "b", &b);
3589 if (r < 0)
3590 return bus_log_parse_error(r);
3591
3592 if (streq(name, "Accept"))
3593 i->accept = b;
3594 else if (streq(name, "NeedDaemonReload"))
3595 i->need_daemon_reload = b;
3596 else if (streq(name, "ConditionResult"))
3597 i->condition_result = b;
3598
3599 break;
3600 }
3601
3602 case SD_BUS_TYPE_UINT32: {
3603 uint32_t u;
3604
3605 r = sd_bus_message_read(m, "u", &u);
3606 if (r < 0)
3607 return bus_log_parse_error(r);
3608
3609 if (streq(name, "MainPID")) {
3610 if (u > 0) {
3611 i->main_pid = (pid_t) u;
3612 i->running = true;
3613 }
3614 } else if (streq(name, "ControlPID"))
3615 i->control_pid = (pid_t) u;
3616 else if (streq(name, "ExecMainPID")) {
3617 if (u > 0)
3618 i->main_pid = (pid_t) u;
3619 } else if (streq(name, "NAccepted"))
3620 i->n_accepted = u;
3621 else if (streq(name, "NConnections"))
3622 i->n_connections = u;
3623
3624 break;
3625 }
3626
3627 case SD_BUS_TYPE_INT32: {
3628 int32_t j;
3629
3630 r = sd_bus_message_read(m, "i", &j);
3631 if (r < 0)
3632 return bus_log_parse_error(r);
3633
3634 if (streq(name, "ExecMainCode"))
3635 i->exit_code = (int) j;
3636 else if (streq(name, "ExecMainStatus"))
3637 i->exit_status = (int) j;
3638 else if (streq(name, "StatusErrno"))
3639 i->status_errno = (int) j;
3640
3641 break;
3642 }
3643
3644 case SD_BUS_TYPE_UINT64: {
3645 uint64_t u;
3646
3647 r = sd_bus_message_read(m, "t", &u);
3648 if (r < 0)
3649 return bus_log_parse_error(r);
3650
3651 if (streq(name, "ExecMainStartTimestamp"))
3652 i->start_timestamp = (usec_t) u;
3653 else if (streq(name, "ExecMainExitTimestamp"))
3654 i->exit_timestamp = (usec_t) u;
3655 else if (streq(name, "ActiveEnterTimestamp"))
3656 i->active_enter_timestamp = (usec_t) u;
3657 else if (streq(name, "InactiveEnterTimestamp"))
3658 i->inactive_enter_timestamp = (usec_t) u;
3659 else if (streq(name, "InactiveExitTimestamp"))
3660 i->inactive_exit_timestamp = (usec_t) u;
3661 else if (streq(name, "InactiveExitTimestampMonotonic"))
3662 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3663 else if (streq(name, "ActiveExitTimestamp"))
3664 i->active_exit_timestamp = (usec_t) u;
3665 else if (streq(name, "ConditionTimestamp"))
3666 i->condition_timestamp = (usec_t) u;
3667
3668 break;
3669 }
3670
3671 case SD_BUS_TYPE_ARRAY:
3672
3673 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3674 _cleanup_free_ ExecStatusInfo *info = NULL;
3675
3676 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3677 if (r < 0)
3678 return bus_log_parse_error(r);
3679
3680 info = new0(ExecStatusInfo, 1);
3681 if (!info)
3682 return log_oom();
3683
3684 while ((r = exec_status_info_deserialize(m, info)) > 0) {
3685
3686 info->name = strdup(name);
3687 if (!info->name)
3688 log_oom();
3689
3690 LIST_PREPEND(exec, i->exec, info);
3691
3692 info = new0(ExecStatusInfo, 1);
3693 if (!info)
3694 log_oom();
3695 }
3696
3697 if (r < 0)
3698 return bus_log_parse_error(r);
3699
3700 r = sd_bus_message_exit_container(m);
3701 if (r < 0)
3702 return bus_log_parse_error(r);
3703
3704 return 0;
3705
3706 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3707 const char *type, *path;
3708
3709 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3710 if (r < 0)
3711 return bus_log_parse_error(r);
3712
3713 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
3714
3715 r = strv_extend(&i->listen, type);
3716 if (r < 0)
3717 return r;
3718
3719 r = strv_extend(&i->listen, path);
3720 if (r < 0)
3721 return r;
3722 }
3723 if (r < 0)
3724 return bus_log_parse_error(r);
3725
3726 r = sd_bus_message_exit_container(m);
3727 if (r < 0)
3728 return bus_log_parse_error(r);
3729
3730 return 0;
3731
3732 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "DropInPaths")) {
3733
3734 r = sd_bus_message_read_strv(m, &i->dropin_paths);
3735 if (r < 0)
3736 return bus_log_parse_error(r);
3737
3738 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Documentation")) {
3739
3740 r = sd_bus_message_read_strv(m, &i->documentation);
3741 if (r < 0)
3742 return bus_log_parse_error(r);
3743
3744 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Conditions")) {
3745 const char *cond, *param;
3746 int trigger, negate;
3747 int32_t state;
3748
3749 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3750 if (r < 0)
3751 return bus_log_parse_error(r);
3752
3753 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, &param, &state)) > 0) {
3754 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3755 if (state < 0 && (!trigger || !i->failed_condition)) {
3756 i->failed_condition = cond;
3757 i->failed_condition_trigger = trigger;
3758 i->failed_condition_negate = negate;
3759 i->failed_condition_param = param;
3760 }
3761 }
3762 if (r < 0)
3763 return bus_log_parse_error(r);
3764
3765 r = sd_bus_message_exit_container(m);
3766 if (r < 0)
3767 return bus_log_parse_error(r);
3768
3769 } else
3770 goto skip;
3771
3772 break;
3773
3774 case SD_BUS_TYPE_STRUCT_BEGIN:
3775
3776 if (streq(name, "LoadError")) {
3777 const char *n, *message;
3778
3779 r = sd_bus_message_read(m, "(ss)", &n, &message);
3780 if (r < 0)
3781 return bus_log_parse_error(r);
3782
3783 if (!isempty(message))
3784 i->load_error = message;
3785 } else
3786 goto skip;
3787
3788 break;
3789
3790 default:
3791 goto skip;
3792 }
3793
3794 return 0;
3795
3796 skip:
3797 r = sd_bus_message_skip(m, contents);
3798 if (r < 0)
3799 return bus_log_parse_error(r);
3800
3801 return 0;
3802 }
3803
3804 static int print_property(const char *name, sd_bus_message *m, const char *contents) {
3805 int r;
3806
3807 assert(name);
3808 assert(m);
3809
3810 /* This is a low-level property printer, see
3811 * print_status_info() for the nicer output */
3812
3813 if (arg_properties && !strv_find(arg_properties, name)) {
3814 /* skip what we didn't read */
3815 r = sd_bus_message_skip(m, contents);
3816 return r;
3817 }
3818
3819 switch (contents[0]) {
3820
3821 case SD_BUS_TYPE_STRUCT_BEGIN:
3822
3823 if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
3824 uint32_t u;
3825
3826 r = sd_bus_message_read(m, "(uo)", &u, NULL);
3827 if (r < 0)
3828 return bus_log_parse_error(r);
3829
3830 if (u > 0)
3831 printf("%s=%u\n", name, (unsigned) u);
3832 else if (arg_all)
3833 printf("%s=\n", name);
3834
3835 return 0;
3836
3837 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
3838 const char *s;
3839
3840 r = sd_bus_message_read(m, "(so)", &s, NULL);
3841 if (r < 0)
3842 return bus_log_parse_error(r);
3843
3844 if (arg_all || !isempty(s))
3845 printf("%s=%s\n", name, s);
3846
3847 return 0;
3848
3849 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
3850 const char *a = NULL, *b = NULL;
3851
3852 r = sd_bus_message_read(m, "(ss)", &a, &b);
3853 if (r < 0)
3854 return bus_log_parse_error(r);
3855
3856 if (arg_all || !isempty(a) || !isempty(b))
3857 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3858
3859 return 0;
3860 } else if (streq_ptr(name, "SystemCallFilter")) {
3861 _cleanup_strv_free_ char **l = NULL;
3862 int whitelist;
3863
3864 r = sd_bus_message_enter_container(m, 'r', "bas");
3865 if (r < 0)
3866 return bus_log_parse_error(r);
3867
3868 r = sd_bus_message_read(m, "b", &whitelist);
3869 if (r < 0)
3870 return bus_log_parse_error(r);
3871
3872 r = sd_bus_message_read_strv(m, &l);
3873 if (r < 0)
3874 return bus_log_parse_error(r);
3875
3876 r = sd_bus_message_exit_container(m);
3877 if (r < 0)
3878 return bus_log_parse_error(r);
3879
3880 if (arg_all || whitelist || !strv_isempty(l)) {
3881 bool first = true;
3882 char **i;
3883
3884 fputs(name, stdout);
3885 fputc('=', stdout);
3886
3887 if (!whitelist)
3888 fputc('~', stdout);
3889
3890 STRV_FOREACH(i, l) {
3891 if (first)
3892 first = false;
3893 else
3894 fputc(' ', stdout);
3895
3896 fputs(*i, stdout);
3897 }
3898 fputc('\n', stdout);
3899 }
3900
3901 return 0;
3902 }
3903
3904 break;
3905
3906 case SD_BUS_TYPE_ARRAY:
3907
3908 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
3909 const char *path;
3910 int ignore;
3911
3912 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)");
3913 if (r < 0)
3914 return bus_log_parse_error(r);
3915
3916 while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
3917 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3918
3919 if (r < 0)
3920 return bus_log_parse_error(r);
3921
3922 r = sd_bus_message_exit_container(m);
3923 if (r < 0)
3924 return bus_log_parse_error(r);
3925
3926 return 0;
3927
3928 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
3929 const char *type, *path;
3930
3931 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3932 if (r < 0)
3933 return bus_log_parse_error(r);
3934
3935 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
3936 printf("%s=%s\n", type, path);
3937 if (r < 0)
3938 return bus_log_parse_error(r);
3939
3940 r = sd_bus_message_exit_container(m);
3941 if (r < 0)
3942 return bus_log_parse_error(r);
3943
3944 return 0;
3945
3946 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3947 const char *type, *path;
3948
3949 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3950 if (r < 0)
3951 return bus_log_parse_error(r);
3952
3953 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
3954 printf("Listen%s=%s\n", type, path);
3955 if (r < 0)
3956 return bus_log_parse_error(r);
3957
3958 r = sd_bus_message_exit_container(m);
3959 if (r < 0)
3960 return bus_log_parse_error(r);
3961
3962 return 0;
3963
3964 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Timers")) {
3965 const char *base;
3966 uint64_t value, next_elapse;
3967
3968 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
3969 if (r < 0)
3970 return bus_log_parse_error(r);
3971
3972 while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) {
3973 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3974
3975 printf("%s={ value=%s ; next_elapse=%s }\n",
3976 base,
3977 format_timespan(timespan1, sizeof(timespan1), value, 0),
3978 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
3979 }
3980 if (r < 0)
3981 return bus_log_parse_error(r);
3982
3983 r = sd_bus_message_exit_container(m);
3984 if (r < 0)
3985 return bus_log_parse_error(r);
3986
3987 return 0;
3988
3989 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3990 ExecStatusInfo info = {};
3991
3992 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3993 if (r < 0)
3994 return bus_log_parse_error(r);
3995
3996 while ((r = exec_status_info_deserialize(m, &info)) > 0) {
3997 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3998 _cleanup_free_ char *tt;
3999
4000 tt = strv_join(info.argv, " ");
4001
4002 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
4003 name,
4004 strna(info.path),
4005 strna(tt),
4006 yes_no(info.ignore),
4007 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
4008 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
4009 (unsigned) info. pid,
4010 sigchld_code_to_string(info.code),
4011 info.status,
4012 info.code == CLD_EXITED ? "" : "/",
4013 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
4014
4015 free(info.path);
4016 strv_free(info.argv);
4017 zero(info);
4018 }
4019
4020 r = sd_bus_message_exit_container(m);
4021 if (r < 0)
4022 return bus_log_parse_error(r);
4023
4024 return 0;
4025
4026 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
4027 const char *path, *rwm;
4028
4029 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4030 if (r < 0)
4031 return bus_log_parse_error(r);
4032
4033 while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
4034 printf("%s=%s %s\n", name, strna(path), strna(rwm));
4035 if (r < 0)
4036 return bus_log_parse_error(r);
4037
4038 r = sd_bus_message_exit_container(m);
4039 if (r < 0)
4040 return bus_log_parse_error(r);
4041
4042 return 0;
4043
4044 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "BlockIODeviceWeight")) {
4045 const char *path;
4046 uint64_t weight;
4047
4048 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4049 if (r < 0)
4050 return bus_log_parse_error(r);
4051
4052 while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
4053 printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
4054 if (r < 0)
4055 return bus_log_parse_error(r);
4056
4057 r = sd_bus_message_exit_container(m);
4058 if (r < 0)
4059 return bus_log_parse_error(r);
4060
4061 return 0;
4062
4063 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
4064 const char *path;
4065 uint64_t bandwidth;
4066
4067 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4068 if (r < 0)
4069 return bus_log_parse_error(r);
4070
4071 while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
4072 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
4073 if (r < 0)
4074 return bus_log_parse_error(r);
4075
4076 r = sd_bus_message_exit_container(m);
4077 if (r < 0)
4078 return bus_log_parse_error(r);
4079
4080 return 0;
4081 }
4082
4083 break;
4084 }
4085
4086 r = bus_print_property(name, m, arg_all);
4087 if (r < 0)
4088 return bus_log_parse_error(r);
4089
4090 if (r == 0) {
4091 r = sd_bus_message_skip(m, contents);
4092 if (r < 0)
4093 return bus_log_parse_error(r);
4094
4095 if (arg_all)
4096 printf("%s=[unprintable]\n", name);
4097 }
4098
4099 return 0;
4100 }
4101
4102 static int show_one(
4103 const char *verb,
4104 sd_bus *bus,
4105 const char *path,
4106 bool show_properties,
4107 bool *new_line,
4108 bool *ellipsized) {
4109
4110 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4111 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4112 UnitStatusInfo info = {};
4113 ExecStatusInfo *p;
4114 int r;
4115
4116 assert(path);
4117 assert(new_line);
4118
4119 log_debug("Showing one %s", path);
4120
4121 r = sd_bus_call_method(
4122 bus,
4123 "org.freedesktop.systemd1",
4124 path,
4125 "org.freedesktop.DBus.Properties",
4126 "GetAll",
4127 &error,
4128 &reply,
4129 "s", "");
4130 if (r < 0) {
4131 log_error("Failed to get properties: %s", bus_error_message(&error, r));
4132 return r;
4133 }
4134
4135 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
4136 if (r < 0)
4137 return bus_log_parse_error(r);
4138
4139 if (*new_line)
4140 printf("\n");
4141
4142 *new_line = true;
4143
4144 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
4145 const char *name, *contents;
4146
4147 r = sd_bus_message_read(reply, "s", &name);
4148 if (r < 0)
4149 return bus_log_parse_error(r);
4150
4151 r = sd_bus_message_peek_type(reply, NULL, &contents);
4152 if (r < 0)
4153 return bus_log_parse_error(r);
4154
4155 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
4156 if (r < 0)
4157 return bus_log_parse_error(r);
4158
4159 if (show_properties)
4160 r = print_property(name, reply, contents);
4161 else
4162 r = status_property(name, reply, &info, contents);
4163 if (r < 0)
4164 return r;
4165
4166 r = sd_bus_message_exit_container(reply);
4167 if (r < 0)
4168 return bus_log_parse_error(r);
4169
4170 r = sd_bus_message_exit_container(reply);
4171 if (r < 0)
4172 return bus_log_parse_error(r);
4173 }
4174 if (r < 0)
4175 return bus_log_parse_error(r);
4176
4177 r = sd_bus_message_exit_container(reply);
4178 if (r < 0)
4179 return bus_log_parse_error(r);
4180
4181 r = 0;
4182
4183 if (!show_properties) {
4184 if (streq(verb, "help"))
4185 show_unit_help(&info);
4186 else
4187 print_status_info(&info, ellipsized);
4188 }
4189
4190 strv_free(info.documentation);
4191 strv_free(info.dropin_paths);
4192 strv_free(info.listen);
4193
4194 if (!streq_ptr(info.active_state, "active") &&
4195 !streq_ptr(info.active_state, "reloading") &&
4196 streq(verb, "status")) {
4197 /* According to LSB: "program not running" */
4198 /* 0: program is running or service is OK
4199 * 1: program is dead and /run PID file exists
4200 * 2: program is dead and /run/lock lock file exists
4201 * 3: program is not running
4202 * 4: program or service status is unknown
4203 */
4204 if (info.pid_file && access(info.pid_file, F_OK) == 0)
4205 r = 1;
4206 else
4207 r = 3;
4208 }
4209
4210 while ((p = info.exec)) {
4211 LIST_REMOVE(exec, info.exec, p);
4212 exec_status_info_free(p);
4213 }
4214
4215 return r;
4216 }
4217
4218 static int get_unit_dbus_path_by_pid(
4219 sd_bus *bus,
4220 uint32_t pid,
4221 char **unit) {
4222
4223 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4224 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4225 char *u;
4226 int r;
4227
4228 r = sd_bus_call_method(
4229 bus,
4230 "org.freedesktop.systemd1",
4231 "/org/freedesktop/systemd1",
4232 "org.freedesktop.systemd1.Manager",
4233 "GetUnitByPID",
4234 &error,
4235 &reply,
4236 "u", pid);
4237 if (r < 0) {
4238 log_error("Failed to get unit for PID "PID_FMT": %s", pid, bus_error_message(&error, r));
4239 return r;
4240 }
4241
4242 r = sd_bus_message_read(reply, "o", &u);
4243 if (r < 0)
4244 return bus_log_parse_error(r);
4245
4246 u = strdup(u);
4247 if (!u)
4248 return log_oom();
4249
4250 *unit = u;
4251 return 0;
4252 }
4253
4254 static int show_all(
4255 const char* verb,
4256 sd_bus *bus,
4257 bool show_properties,
4258 bool *new_line,
4259 bool *ellipsized) {
4260
4261 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4262 _cleanup_free_ UnitInfo *unit_infos = NULL;
4263 const UnitInfo *u;
4264 unsigned c;
4265 int r, ret = 0;
4266
4267 r = get_unit_list(bus, NULL, NULL, &unit_infos, 0, &reply);
4268 if (r < 0)
4269 return r;
4270
4271 pager_open_if_enabled();
4272
4273 c = (unsigned) r;
4274
4275 qsort_safe(unit_infos, c, sizeof(UnitInfo), compare_unit_info);
4276
4277 for (u = unit_infos; u < unit_infos + c; u++) {
4278 _cleanup_free_ char *p = NULL;
4279
4280 p = unit_dbus_path_from_name(u->id);
4281 if (!p)
4282 return log_oom();
4283
4284 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
4285 if (r < 0)
4286 return r;
4287 else if (r > 0 && ret == 0)
4288 ret = r;
4289 }
4290
4291 return ret;
4292 }
4293
4294 static int show_system_status(sd_bus *bus) {
4295 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
4296 _cleanup_free_ char *hn = NULL;
4297 struct machine_info mi = {};
4298 const char *on, *off;
4299 int r;
4300
4301 hn = gethostname_malloc();
4302 if (!hn)
4303 return log_oom();
4304
4305 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &mi);
4306 if (r < 0) {
4307 log_error("Failed to read server status: %s", strerror(-r));
4308 return r;
4309 }
4310
4311 if (streq_ptr(mi.state, "degraded")) {
4312 on = ansi_highlight_red();
4313 off = ansi_highlight_off();
4314 } else if (!streq_ptr(mi.state, "running")) {
4315 on = ansi_highlight_yellow();
4316 off = ansi_highlight_off();
4317 } else
4318 on = off = "";
4319
4320 printf("%s%s%s %s\n", on, draw_special_char(DRAW_BLACK_CIRCLE), off, arg_host ? arg_host : hn);
4321
4322 printf(" State: %s%s%s\n",
4323 on, strna(mi.state), off);
4324
4325 printf(" Jobs: %u queued\n", mi.n_jobs);
4326 printf(" Failed: %u units\n", mi.n_failed_units);
4327
4328 printf(" Since: %s; %s\n",
4329 format_timestamp(since2, sizeof(since2), mi.timestamp),
4330 format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
4331
4332 printf(" CGroup: %s\n", mi.control_group ?: "/");
4333 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
4334 int flags =
4335 arg_all * OUTPUT_SHOW_ALL |
4336 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
4337 on_tty() * OUTPUT_COLOR |
4338 !arg_quiet * OUTPUT_WARN_CUTOFF |
4339 arg_full * OUTPUT_FULL_WIDTH;
4340
4341 static const char prefix[] = " ";
4342 unsigned c;
4343
4344 c = columns();
4345 if (c > sizeof(prefix) - 1)
4346 c -= sizeof(prefix) - 1;
4347 else
4348 c = 0;
4349
4350 show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, flags);
4351 }
4352
4353 free(mi.state);
4354 free(mi.control_group);
4355
4356 return 0;
4357 }
4358
4359 static int show(sd_bus *bus, char **args) {
4360 bool show_properties, show_status, new_line = false;
4361 bool ellipsized = false;
4362 int r, ret = 0;
4363
4364 assert(bus);
4365 assert(args);
4366
4367 show_properties = streq(args[0], "show");
4368 show_status = streq(args[0], "status");
4369
4370 if (show_properties)
4371 pager_open_if_enabled();
4372
4373 /* If no argument is specified inspect the manager itself */
4374
4375 if (show_properties && strv_length(args) <= 1)
4376 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
4377
4378 if (show_status && strv_length(args) <= 1) {
4379
4380 pager_open_if_enabled();
4381 show_system_status(bus);
4382 new_line = true;
4383
4384 if (arg_all)
4385 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
4386 } else {
4387 _cleanup_free_ char **patterns = NULL;
4388 char **name;
4389
4390 STRV_FOREACH(name, args + 1) {
4391 _cleanup_free_ char *unit = NULL;
4392 uint32_t id;
4393
4394 if (safe_atou32(*name, &id) < 0) {
4395 if (strv_push(&patterns, *name) < 0)
4396 return log_oom();
4397
4398 continue;
4399 } else if (show_properties) {
4400 /* Interpret as job id */
4401 if (asprintf(&unit, "/org/freedesktop/systemd1/job/%u", id) < 0)
4402 return log_oom();
4403
4404 } else {
4405 /* Interpret as PID */
4406 r = get_unit_dbus_path_by_pid(bus, id, &unit);
4407 if (r < 0) {
4408 ret = r;
4409 continue;
4410 }
4411 }
4412
4413 r = show_one(args[0], bus, unit, show_properties,
4414 &new_line, &ellipsized);
4415 if (r < 0)
4416 return r;
4417 else if (r > 0 && ret == 0)
4418 ret = r;
4419 }
4420
4421 if (!strv_isempty(patterns)) {
4422 _cleanup_strv_free_ char **names = NULL;
4423
4424 r = expand_names(bus, patterns, NULL, &names);
4425 if (r < 0)
4426 log_error("Failed to expand names: %s", strerror(-r));
4427
4428 STRV_FOREACH(name, names) {
4429 _cleanup_free_ char *unit;
4430
4431 unit = unit_dbus_path_from_name(*name);
4432 if (!unit)
4433 return log_oom();
4434
4435 r = show_one(args[0], bus, unit, show_properties,
4436 &new_line, &ellipsized);
4437 if (r < 0)
4438 return r;
4439 else if (r > 0 && ret == 0)
4440 ret = r;
4441 }
4442 }
4443 }
4444
4445 if (ellipsized && !arg_quiet)
4446 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4447
4448 return ret;
4449 }
4450
4451 static int cat(sd_bus *bus, char **args) {
4452 _cleanup_strv_free_ char **names = NULL;
4453 char **name;
4454 bool first = true;
4455 int r = 0;
4456
4457 assert(bus);
4458 assert(args);
4459
4460 r = expand_names(bus, args + 1, NULL, &names);
4461 if (r < 0)
4462 log_error("Failed to expand names: %s", strerror(-r));
4463
4464 pager_open_if_enabled();
4465
4466 STRV_FOREACH(name, names) {
4467 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4468 _cleanup_strv_free_ char **dropin_paths = NULL;
4469 _cleanup_free_ char *fragment_path = NULL, *unit = NULL;
4470 char **path;
4471
4472 unit = unit_dbus_path_from_name(*name);
4473 if (!unit)
4474 return log_oom();
4475
4476 if (need_daemon_reload(bus, *name) > 0)
4477 log_warning("Unit file of %s changed on disk. Run 'systemctl%s daemon-reload'.",
4478 *name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
4479
4480 r = sd_bus_get_property_string(
4481 bus,
4482 "org.freedesktop.systemd1",
4483 unit,
4484 "org.freedesktop.systemd1.Unit",
4485 "FragmentPath",
4486 &error,
4487 &fragment_path);
4488 if (r < 0) {
4489 log_warning("Failed to get FragmentPath: %s", bus_error_message(&error, r));
4490 continue;
4491 }
4492
4493 r = sd_bus_get_property_strv(
4494 bus,
4495 "org.freedesktop.systemd1",
4496 unit,
4497 "org.freedesktop.systemd1.Unit",
4498 "DropInPaths",
4499 &error,
4500 &dropin_paths);
4501 if (r < 0) {
4502 log_warning("Failed to get DropInPaths: %s", bus_error_message(&error, r));
4503 continue;
4504 }
4505
4506 if (first)
4507 first = false;
4508 else
4509 puts("");
4510
4511 if (!isempty(fragment_path)) {
4512 printf("%s# %s%s\n",
4513 ansi_highlight_blue(),
4514 fragment_path,
4515 ansi_highlight_off());
4516 fflush(stdout);
4517
4518 r = sendfile_full(STDOUT_FILENO, fragment_path);
4519 if (r < 0) {
4520 log_warning("Failed to cat %s: %s", fragment_path, strerror(-r));
4521 continue;
4522 }
4523 }
4524
4525 STRV_FOREACH(path, dropin_paths) {
4526 printf("%s%s# %s%s\n",
4527 isempty(fragment_path) && path == dropin_paths ? "" : "\n",
4528 ansi_highlight_blue(),
4529 *path,
4530 ansi_highlight_off());
4531 fflush(stdout);
4532
4533 r = sendfile_full(STDOUT_FILENO, *path);
4534 if (r < 0) {
4535 log_warning("Failed to cat %s: %s", *path, strerror(-r));
4536 continue;
4537 }
4538 }
4539 }
4540
4541 return r < 0 ? r : 0;
4542 }
4543
4544 static int set_property(sd_bus *bus, char **args) {
4545 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4546 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4547 _cleanup_free_ char *n = NULL;
4548 char **i;
4549 int r;
4550
4551 r = sd_bus_message_new_method_call(
4552 bus,
4553 &m,
4554 "org.freedesktop.systemd1",
4555 "/org/freedesktop/systemd1",
4556 "org.freedesktop.systemd1.Manager",
4557 "SetUnitProperties");
4558 if (r < 0)
4559 return bus_log_create_error(r);
4560
4561 n = unit_name_mangle(args[1], MANGLE_NOGLOB);
4562 if (!n)
4563 return log_oom();
4564
4565 r = sd_bus_message_append(m, "sb", n, arg_runtime);
4566 if (r < 0)
4567 return bus_log_create_error(r);
4568
4569 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)");
4570 if (r < 0)
4571 return bus_log_create_error(r);
4572
4573 STRV_FOREACH(i, args + 2) {
4574 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
4575 if (r < 0)
4576 return bus_log_create_error(r);
4577
4578 r = bus_append_unit_property_assignment(m, *i);
4579 if (r < 0)
4580 return r;
4581
4582 r = sd_bus_message_close_container(m);
4583 if (r < 0)
4584 return bus_log_create_error(r);
4585 }
4586
4587 r = sd_bus_message_close_container(m);
4588 if (r < 0)
4589 return bus_log_create_error(r);
4590
4591 r = sd_bus_call(bus, m, 0, &error, NULL);
4592 if (r < 0) {
4593 log_error("Failed to set unit properties on %s: %s", n, bus_error_message(&error, r));
4594 return r;
4595 }
4596
4597 return 0;
4598 }
4599
4600 static int snapshot(sd_bus *bus, char **args) {
4601 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4602 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4603 _cleanup_free_ char *n = NULL, *id = NULL;
4604 const char *path;
4605 int r;
4606
4607 if (strv_length(args) > 1)
4608 n = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".snapshot");
4609 else
4610 n = strdup("");
4611 if (!n)
4612 return log_oom();
4613
4614 r = sd_bus_call_method(
4615 bus,
4616 "org.freedesktop.systemd1",
4617 "/org/freedesktop/systemd1",
4618 "org.freedesktop.systemd1.Manager",
4619 "CreateSnapshot",
4620 &error,
4621 &reply,
4622 "sb", n, false);
4623 if (r < 0) {
4624 log_error("Failed to create snapshot: %s", bus_error_message(&error, r));
4625 return r;
4626 }
4627
4628 r = sd_bus_message_read(reply, "o", &path);
4629 if (r < 0)
4630 return bus_log_parse_error(r);
4631
4632 r = sd_bus_get_property_string(
4633 bus,
4634 "org.freedesktop.systemd1",
4635 path,
4636 "org.freedesktop.systemd1.Unit",
4637 "Id",
4638 &error,
4639 &id);
4640 if (r < 0) {
4641 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error, r));
4642 return r;
4643 }
4644
4645 if (!arg_quiet)
4646 puts(id);
4647
4648 return 0;
4649 }
4650
4651 static int delete_snapshot(sd_bus *bus, char **args) {
4652 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4653 _cleanup_strv_free_ char **names = NULL;
4654 char **name;
4655 int r, q;
4656
4657 assert(args);
4658
4659 r = expand_names(bus, args + 1, ".snapshot", &names);
4660 if (r < 0)
4661 log_error("Failed to expand names: %s", strerror(-r));
4662
4663 STRV_FOREACH(name, names) {
4664 q = sd_bus_call_method(
4665 bus,
4666 "org.freedesktop.systemd1",
4667 "/org/freedesktop/systemd1",
4668 "org.freedesktop.systemd1.Manager",
4669 "RemoveSnapshot",
4670 &error,
4671 NULL,
4672 "s", *name);
4673 if (q < 0) {
4674 log_error("Failed to remove snapshot %s: %s",
4675 *name, bus_error_message(&error, r));
4676 if (r == 0)
4677 r = q;
4678 }
4679 }
4680
4681 return r;
4682 }
4683
4684 static int daemon_reload(sd_bus *bus, char **args) {
4685 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4686 const char *method;
4687 int r;
4688
4689 if (arg_action == ACTION_RELOAD)
4690 method = "Reload";
4691 else if (arg_action == ACTION_REEXEC)
4692 method = "Reexecute";
4693 else {
4694 assert(arg_action == ACTION_SYSTEMCTL);
4695
4696 method =
4697 streq(args[0], "clear-jobs") ||
4698 streq(args[0], "cancel") ? "ClearJobs" :
4699 streq(args[0], "daemon-reexec") ? "Reexecute" :
4700 streq(args[0], "reset-failed") ? "ResetFailed" :
4701 streq(args[0], "halt") ? "Halt" :
4702 streq(args[0], "poweroff") ? "PowerOff" :
4703 streq(args[0], "reboot") ? "Reboot" :
4704 streq(args[0], "kexec") ? "KExec" :
4705 streq(args[0], "exit") ? "Exit" :
4706 /* "daemon-reload" */ "Reload";
4707 }
4708
4709 r = sd_bus_call_method(
4710 bus,
4711 "org.freedesktop.systemd1",
4712 "/org/freedesktop/systemd1",
4713 "org.freedesktop.systemd1.Manager",
4714 method,
4715 &error,
4716 NULL,
4717 NULL);
4718
4719 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
4720 /* There's always a fallback possible for
4721 * legacy actions. */
4722 r = -EADDRNOTAVAIL;
4723 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
4724 /* On reexecution, we expect a disconnect, not a
4725 * reply */
4726 r = 0;
4727 else if (r < 0)
4728 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
4729
4730 return r < 0 ? r : 0;
4731 }
4732
4733 static int reset_failed(sd_bus *bus, char **args) {
4734 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4735 _cleanup_strv_free_ char **names = NULL;
4736 char **name;
4737 int r, q;
4738
4739 if (strv_length(args) <= 1)
4740 return daemon_reload(bus, args);
4741
4742 r = expand_names(bus, args + 1, NULL, &names);
4743 if (r < 0)
4744 log_error("Failed to expand names: %s", strerror(-r));
4745
4746 STRV_FOREACH(name, names) {
4747 q = sd_bus_call_method(
4748 bus,
4749 "org.freedesktop.systemd1",
4750 "/org/freedesktop/systemd1",
4751 "org.freedesktop.systemd1.Manager",
4752 "ResetFailedUnit",
4753 &error,
4754 NULL,
4755 "s", *name);
4756 if (q < 0) {
4757 log_error("Failed to reset failed state of unit %s: %s",
4758 *name, bus_error_message(&error, r));
4759 if (r == 0)
4760 r = q;
4761 }
4762 }
4763
4764 return r;
4765 }
4766
4767 static int show_environment(sd_bus *bus, char **args) {
4768 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4769 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4770 const char *text;
4771 int r;
4772
4773 pager_open_if_enabled();
4774
4775 r = sd_bus_get_property(
4776 bus,
4777 "org.freedesktop.systemd1",
4778 "/org/freedesktop/systemd1",
4779 "org.freedesktop.systemd1.Manager",
4780 "Environment",
4781 &error,
4782 &reply,
4783 "as");
4784 if (r < 0) {
4785 log_error("Failed to get environment: %s", bus_error_message(&error, r));
4786 return r;
4787 }
4788
4789 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
4790 if (r < 0)
4791 return bus_log_parse_error(r);
4792
4793 while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0)
4794 puts(text);
4795 if (r < 0)
4796 return bus_log_parse_error(r);
4797
4798 r = sd_bus_message_exit_container(reply);
4799 if (r < 0)
4800 return bus_log_parse_error(r);
4801
4802 return 0;
4803 }
4804
4805 static int switch_root(sd_bus *bus, char **args) {
4806 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4807 _cleanup_free_ char *cmdline_init = NULL;
4808 const char *root, *init;
4809 unsigned l;
4810 int r;
4811
4812 l = strv_length(args);
4813 if (l < 2 || l > 3) {
4814 log_error("Wrong number of arguments.");
4815 return -EINVAL;
4816 }
4817
4818 root = args[1];
4819
4820 if (l >= 3)
4821 init = args[2];
4822 else {
4823 r = parse_env_file("/proc/cmdline", WHITESPACE,
4824 "init", &cmdline_init,
4825 NULL);
4826 if (r < 0)
4827 log_debug("Failed to parse /proc/cmdline: %s", strerror(-r));
4828
4829 init = cmdline_init;
4830 }
4831
4832 if (isempty(init))
4833 init = NULL;
4834
4835 if (init) {
4836 const char *root_systemd_path = NULL, *root_init_path = NULL;
4837
4838 root_systemd_path = strappenda(root, "/" SYSTEMD_BINARY_PATH);
4839 root_init_path = strappenda(root, "/", init);
4840
4841 /* If the passed init is actually the same as the
4842 * systemd binary, then let's suppress it. */
4843 if (files_same(root_init_path, root_systemd_path) > 0)
4844 init = NULL;
4845 }
4846
4847 log_debug("Switching root - root: %s; init: %s", root, strna(init));
4848
4849 r = sd_bus_call_method(
4850 bus,
4851 "org.freedesktop.systemd1",
4852 "/org/freedesktop/systemd1",
4853 "org.freedesktop.systemd1.Manager",
4854 "SwitchRoot",
4855 &error,
4856 NULL,
4857 "ss", root, init);
4858 if (r < 0) {
4859 log_error("Failed to switch root: %s", bus_error_message(&error, r));
4860 return r;
4861 }
4862
4863 return 0;
4864 }
4865
4866 static int set_environment(sd_bus *bus, char **args) {
4867 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4868 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4869 const char *method;
4870 int r;
4871
4872 assert(bus);
4873 assert(args);
4874
4875 method = streq(args[0], "set-environment")
4876 ? "SetEnvironment"
4877 : "UnsetEnvironment";
4878
4879 r = sd_bus_message_new_method_call(
4880 bus,
4881 &m,
4882 "org.freedesktop.systemd1",
4883 "/org/freedesktop/systemd1",
4884 "org.freedesktop.systemd1.Manager",
4885 method);
4886 if (r < 0)
4887 return bus_log_create_error(r);
4888
4889 r = sd_bus_message_append_strv(m, args + 1);
4890 if (r < 0)
4891 return bus_log_create_error(r);
4892
4893 r = sd_bus_call(bus, m, 0, &error, NULL);
4894 if (r < 0) {
4895 log_error("Failed to set environment: %s", bus_error_message(&error, r));
4896 return r;
4897 }
4898
4899 return 0;
4900 }
4901
4902 static int import_environment(sd_bus *bus, char **args) {
4903 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4904 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4905 int r;
4906
4907 assert(bus);
4908 assert(args);
4909
4910 r = sd_bus_message_new_method_call(
4911 bus,
4912 &m,
4913 "org.freedesktop.systemd1",
4914 "/org/freedesktop/systemd1",
4915 "org.freedesktop.systemd1.Manager",
4916 "SetEnvironment");
4917 if (r < 0)
4918 return bus_log_create_error(r);
4919
4920 if (strv_isempty(args + 1))
4921 r = sd_bus_message_append_strv(m, environ);
4922 else {
4923 char **a, **b;
4924
4925 r = sd_bus_message_open_container(m, 'a', "s");
4926 if (r < 0)
4927 return bus_log_create_error(r);
4928
4929 STRV_FOREACH(a, args + 1) {
4930
4931 if (!env_name_is_valid(*a)) {
4932 log_error("Not a valid environment variable name: %s", *a);
4933 return -EINVAL;
4934 }
4935
4936 STRV_FOREACH(b, environ) {
4937 const char *eq;
4938
4939 eq = startswith(*b, *a);
4940 if (eq && *eq == '=') {
4941
4942 r = sd_bus_message_append(m, "s", *b);
4943 if (r < 0)
4944 return bus_log_create_error(r);
4945
4946 break;
4947 }
4948 }
4949 }
4950
4951 r = sd_bus_message_close_container(m);
4952 }
4953 if (r < 0)
4954 return bus_log_create_error(r);
4955
4956 r = sd_bus_call(bus, m, 0, &error, NULL);
4957 if (r < 0) {
4958 log_error("Failed to import environment: %s", bus_error_message(&error, r));
4959 return r;
4960 }
4961
4962 return 0;
4963 }
4964
4965 static int enable_sysv_units(const char *verb, char **args) {
4966 int r = 0;
4967
4968 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4969 unsigned f = 1, t = 1;
4970 _cleanup_lookup_paths_free_ LookupPaths paths = {};
4971
4972 if (arg_scope != UNIT_FILE_SYSTEM)
4973 return 0;
4974
4975 if (!streq(verb, "enable") &&
4976 !streq(verb, "disable") &&
4977 !streq(verb, "is-enabled"))
4978 return 0;
4979
4980 /* Processes all SysV units, and reshuffles the array so that
4981 * afterwards only the native units remain */
4982
4983 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, arg_root, NULL, NULL, NULL);
4984 if (r < 0)
4985 return r;
4986
4987 r = 0;
4988 for (f = 0; args[f]; f++) {
4989 const char *name;
4990 _cleanup_free_ char *p = NULL, *q = NULL, *l = NULL;
4991 bool found_native = false, found_sysv;
4992 unsigned c = 1;
4993 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
4994 char **k;
4995 int j;
4996 pid_t pid;
4997 siginfo_t status;
4998
4999 name = args[f];
5000
5001 if (!endswith(name, ".service"))
5002 continue;
5003
5004 if (path_is_absolute(name))
5005 continue;
5006
5007 STRV_FOREACH(k, paths.unit_path) {
5008 _cleanup_free_ char *path = NULL;
5009
5010 path = path_join(arg_root, *k, name);
5011 if (!path)
5012 return log_oom();
5013
5014 found_native = access(path, F_OK) >= 0;
5015 if (found_native)
5016 break;
5017 }
5018
5019 if (found_native)
5020 continue;
5021
5022 p = path_join(arg_root, SYSTEM_SYSVINIT_PATH, name);
5023 if (!p)
5024 return log_oom();
5025
5026 p[strlen(p) - strlen(".service")] = 0;
5027 found_sysv = access(p, F_OK) >= 0;
5028 if (!found_sysv)
5029 continue;
5030
5031 /* Mark this entry, so that we don't try enabling it as native unit */
5032 args[f] = (char*) "";
5033
5034 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
5035
5036 if (!isempty(arg_root))
5037 argv[c++] = q = strappend("--root=", arg_root);
5038
5039 argv[c++] = basename(p);
5040 argv[c++] =
5041 streq(verb, "enable") ? "on" :
5042 streq(verb, "disable") ? "off" : "--level=5";
5043 argv[c] = NULL;
5044
5045 l = strv_join((char**)argv, " ");
5046 if (!l)
5047 return log_oom();
5048
5049 log_info("Executing %s", l);
5050
5051 pid = fork();
5052 if (pid < 0) {
5053 log_error("Failed to fork: %m");
5054 return -errno;
5055 } else if (pid == 0) {
5056 /* Child */
5057
5058 execv(argv[0], (char**) argv);
5059 _exit(EXIT_FAILURE);
5060 }
5061
5062 j = wait_for_terminate(pid, &status);
5063 if (j < 0) {
5064 log_error("Failed to wait for child: %s", strerror(-r));
5065 return j;
5066 }
5067
5068 if (status.si_code == CLD_EXITED) {
5069 if (streq(verb, "is-enabled")) {
5070 if (status.si_status == 0) {
5071 if (!arg_quiet)
5072 puts("enabled");
5073 r = 1;
5074 } else {
5075 if (!arg_quiet)
5076 puts("disabled");
5077 }
5078
5079 } else if (status.si_status != 0)
5080 return -EINVAL;
5081 } else
5082 return -EPROTO;
5083 }
5084
5085 /* Drop all SysV units */
5086 for (f = 0, t = 0; args[f]; f++) {
5087
5088 if (isempty(args[f]))
5089 continue;
5090
5091 args[t++] = args[f];
5092 }
5093
5094 args[t] = NULL;
5095
5096 #endif
5097 return r;
5098 }
5099
5100 static int mangle_names(char **original_names, char ***mangled_names) {
5101 char **i, **l, **name;
5102
5103 l = new(char*, strv_length(original_names) + 1);
5104 if (!l)
5105 return log_oom();
5106
5107 i = l;
5108 STRV_FOREACH(name, original_names) {
5109
5110 /* When enabling units qualified path names are OK,
5111 * too, hence allow them explicitly. */
5112
5113 if (is_path(*name))
5114 *i = strdup(*name);
5115 else
5116 *i = unit_name_mangle(*name, MANGLE_NOGLOB);
5117
5118 if (!*i) {
5119 strv_free(l);
5120 return log_oom();
5121 }
5122
5123 i++;
5124 }
5125
5126 *i = NULL;
5127 *mangled_names = l;
5128
5129 return 0;
5130 }
5131
5132 static int enable_unit(sd_bus *bus, char **args) {
5133 _cleanup_strv_free_ char **names = NULL;
5134 const char *verb = args[0];
5135 UnitFileChange *changes = NULL;
5136 unsigned n_changes = 0;
5137 int carries_install_info = -1;
5138 int r;
5139
5140 if (!args[1])
5141 return 0;
5142
5143 r = mangle_names(args+1, &names);
5144 if (r < 0)
5145 return r;
5146
5147 r = enable_sysv_units(verb, names);
5148 if (r < 0)
5149 return r;
5150
5151 /* If the operation was fully executed by the SysV compat,
5152 * let's finish early */
5153 if (strv_isempty(names))
5154 return 0;
5155
5156 if (!bus || avoid_bus()) {
5157 if (streq(verb, "enable")) {
5158 r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5159 carries_install_info = r;
5160 } else if (streq(verb, "disable"))
5161 r = unit_file_disable(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5162 else if (streq(verb, "reenable")) {
5163 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5164 carries_install_info = r;
5165 } else if (streq(verb, "link"))
5166 r = unit_file_link(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5167 else if (streq(verb, "preset")) {
5168 r = unit_file_preset(arg_scope, arg_runtime, arg_root, names, arg_preset_mode, arg_force, &changes, &n_changes);
5169 carries_install_info = r;
5170 } else if (streq(verb, "mask"))
5171 r = unit_file_mask(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5172 else if (streq(verb, "unmask"))
5173 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5174 else
5175 assert_not_reached("Unknown verb");
5176
5177 if (r < 0) {
5178 log_error("Operation failed: %s", strerror(-r));
5179 goto finish;
5180 }
5181
5182 if (!arg_quiet)
5183 dump_unit_file_changes(changes, n_changes);
5184
5185 r = 0;
5186 } else {
5187 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5188 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5189 int expect_carries_install_info = false;
5190 bool send_force = true, send_preset_mode = false;
5191 const char *method;
5192
5193 if (streq(verb, "enable")) {
5194 method = "EnableUnitFiles";
5195 expect_carries_install_info = true;
5196 } else if (streq(verb, "disable")) {
5197 method = "DisableUnitFiles";
5198 send_force = false;
5199 } else if (streq(verb, "reenable")) {
5200 method = "ReenableUnitFiles";
5201 expect_carries_install_info = true;
5202 } else if (streq(verb, "link"))
5203 method = "LinkUnitFiles";
5204 else if (streq(verb, "preset")) {
5205
5206 if (arg_preset_mode != UNIT_FILE_PRESET_FULL) {
5207 method = "PresetUnitFilesWithMode";
5208 send_preset_mode = true;
5209 } else
5210 method = "PresetUnitFiles";
5211
5212 expect_carries_install_info = true;
5213 } else if (streq(verb, "mask"))
5214 method = "MaskUnitFiles";
5215 else if (streq(verb, "unmask")) {
5216 method = "UnmaskUnitFiles";
5217 send_force = false;
5218 } else
5219 assert_not_reached("Unknown verb");
5220
5221 r = sd_bus_message_new_method_call(
5222 bus,
5223 &m,
5224 "org.freedesktop.systemd1",
5225 "/org/freedesktop/systemd1",
5226 "org.freedesktop.systemd1.Manager",
5227 method);
5228 if (r < 0)
5229 return bus_log_create_error(r);
5230
5231 r = sd_bus_message_append_strv(m, names);
5232 if (r < 0)
5233 return bus_log_create_error(r);
5234
5235 if (send_preset_mode) {
5236 r = sd_bus_message_append(m, "s", unit_file_preset_mode_to_string(arg_preset_mode));
5237 if (r < 0)
5238 return bus_log_create_error(r);
5239 }
5240
5241 r = sd_bus_message_append(m, "b", arg_runtime);
5242 if (r < 0)
5243 return bus_log_create_error(r);
5244
5245 if (send_force) {
5246 r = sd_bus_message_append(m, "b", arg_force);
5247 if (r < 0)
5248 return bus_log_create_error(r);
5249 }
5250
5251 r = sd_bus_call(bus, m, 0, &error, &reply);
5252 if (r < 0) {
5253 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5254 return r;
5255 }
5256
5257 if (expect_carries_install_info) {
5258 r = sd_bus_message_read(reply, "b", &carries_install_info);
5259 if (r < 0)
5260 return bus_log_parse_error(r);
5261 }
5262
5263 r = deserialize_and_dump_unit_file_changes(reply);
5264 if (r < 0)
5265 return r;
5266
5267 /* Try to reload if enabled */
5268 if (!arg_no_reload)
5269 r = daemon_reload(bus, args);
5270 else
5271 r = 0;
5272 }
5273
5274 if (carries_install_info == 0)
5275 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5276 "using systemctl.\n"
5277 "Possible reasons for having this kind of units are:\n"
5278 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5279 " .wants/ or .requires/ directory.\n"
5280 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5281 " a requirement dependency on it.\n"
5282 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5283 " D-Bus, udev, scripted systemctl call, ...).\n");
5284
5285 finish:
5286 unit_file_changes_free(changes, n_changes);
5287
5288 return r;
5289 }
5290
5291 static int add_dependency(sd_bus *bus, char **args) {
5292 _cleanup_strv_free_ char **names = NULL;
5293 _cleanup_free_ char *target = NULL;
5294 const char *verb = args[0];
5295 UnitDependency dep;
5296 int r = 0;
5297
5298 if (!args[1])
5299 return 0;
5300
5301 target = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
5302 if (!target)
5303 return log_oom();
5304
5305 r = mangle_names(args+2, &names);
5306 if (r < 0)
5307 return r;
5308
5309 if (streq(verb, "add-wants"))
5310 dep = UNIT_WANTS;
5311 else if (streq(verb, "add-requires"))
5312 dep = UNIT_REQUIRES;
5313 else
5314 assert_not_reached("Unknown verb");
5315
5316 if (!bus || avoid_bus()) {
5317 UnitFileChange *changes = NULL;
5318 unsigned n_changes = 0;
5319
5320 r = unit_file_add_dependency(arg_scope, arg_runtime, arg_root, names, target, dep, arg_force, &changes, &n_changes);
5321
5322 if (r < 0) {
5323 log_error("Can't add dependency: %s", strerror(-r));
5324 return r;
5325 }
5326
5327 if (!arg_quiet)
5328 dump_unit_file_changes(changes, n_changes);
5329
5330 unit_file_changes_free(changes, n_changes);
5331
5332 } else {
5333 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5334 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5335
5336 r = sd_bus_message_new_method_call(
5337 bus,
5338 &m,
5339 "org.freedesktop.systemd1",
5340 "/org/freedesktop/systemd1",
5341 "org.freedesktop.systemd1.Manager",
5342 "AddDependencyUnitFiles");
5343 if (r < 0)
5344 return bus_log_create_error(r);
5345
5346 r = sd_bus_message_append_strv(m, names);
5347 if (r < 0)
5348 return bus_log_create_error(r);
5349
5350 r = sd_bus_message_append(m, "s", target);
5351 if (r < 0)
5352 return bus_log_create_error(r);
5353
5354 r = sd_bus_message_append(m, "s", unit_dependency_to_string(dep));
5355 if (r < 0)
5356 return bus_log_create_error(r);
5357
5358 r = sd_bus_message_append(m, "b", arg_runtime);
5359 if (r < 0)
5360 return bus_log_create_error(r);
5361
5362 r = sd_bus_message_append(m, "b", arg_force);
5363 if (r < 0)
5364 return bus_log_create_error(r);
5365
5366 r = sd_bus_call(bus, m, 0, &error, &reply);
5367 if (r < 0) {
5368 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5369 return r;
5370 }
5371
5372 r = deserialize_and_dump_unit_file_changes(reply);
5373 if (r < 0)
5374 return r;
5375
5376 if (!arg_no_reload)
5377 r = daemon_reload(bus, args);
5378 else
5379 r = 0;
5380 }
5381
5382 return r;
5383 }
5384
5385 static int preset_all(sd_bus *bus, char **args) {
5386 UnitFileChange *changes = NULL;
5387 unsigned n_changes = 0;
5388 int r;
5389
5390 if (!bus || avoid_bus()) {
5391
5392 r = unit_file_preset_all(arg_scope, arg_runtime, arg_root, arg_preset_mode, arg_force, &changes, &n_changes);
5393 if (r < 0) {
5394 log_error("Operation failed: %s", strerror(-r));
5395 goto finish;
5396 }
5397
5398 if (!arg_quiet)
5399 dump_unit_file_changes(changes, n_changes);
5400
5401 r = 0;
5402
5403 } else {
5404 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
5405 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5406
5407 r = sd_bus_call_method(
5408 bus,
5409 "org.freedesktop.systemd1",
5410 "/org/freedesktop/systemd1",
5411 "org.freedesktop.systemd1.Manager",
5412 "PresetAllUnitFiles",
5413 &error,
5414 &reply,
5415 "sbb",
5416 unit_file_preset_mode_to_string(arg_preset_mode),
5417 arg_runtime,
5418 arg_force);
5419 if (r < 0) {
5420 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5421 return r;
5422 }
5423
5424 r = deserialize_and_dump_unit_file_changes(reply);
5425 if (r < 0)
5426 return r;
5427
5428 if (!arg_no_reload)
5429 r = daemon_reload(bus, args);
5430 else
5431 r = 0;
5432 }
5433
5434 finish:
5435 unit_file_changes_free(changes, n_changes);
5436
5437 return r;
5438 }
5439
5440 static int unit_is_enabled(sd_bus *bus, char **args) {
5441
5442 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5443 _cleanup_strv_free_ char **names = NULL;
5444 bool enabled;
5445 char **name;
5446 int r;
5447
5448 r = mangle_names(args+1, &names);
5449 if (r < 0)
5450 return r;
5451
5452 r = enable_sysv_units(args[0], names);
5453 if (r < 0)
5454 return r;
5455
5456 enabled = r > 0;
5457
5458 if (!bus || avoid_bus()) {
5459
5460 STRV_FOREACH(name, names) {
5461 UnitFileState state;
5462
5463 state = unit_file_get_state(arg_scope, arg_root, *name);
5464 if (state < 0) {
5465 log_error("Failed to get unit file state for %s: %s", *name, strerror(-state));
5466 return state;
5467 }
5468
5469 if (state == UNIT_FILE_ENABLED ||
5470 state == UNIT_FILE_ENABLED_RUNTIME ||
5471 state == UNIT_FILE_STATIC)
5472 enabled = true;
5473
5474 if (!arg_quiet)
5475 puts(unit_file_state_to_string(state));
5476 }
5477
5478 } else {
5479 STRV_FOREACH(name, names) {
5480 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
5481 const char *s;
5482
5483 r = sd_bus_call_method(
5484 bus,
5485 "org.freedesktop.systemd1",
5486 "/org/freedesktop/systemd1",
5487 "org.freedesktop.systemd1.Manager",
5488 "GetUnitFileState",
5489 &error,
5490 &reply,
5491 "s", *name);
5492 if (r < 0) {
5493 log_error("Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
5494 return r;
5495 }
5496
5497 r = sd_bus_message_read(reply, "s", &s);
5498 if (r < 0)
5499 return bus_log_parse_error(r);
5500
5501 if (streq(s, "enabled") ||
5502 streq(s, "enabled-runtime") ||
5503 streq(s, "static"))
5504 enabled = true;
5505
5506 if (!arg_quiet)
5507 puts(s);
5508 }
5509 }
5510
5511 return !enabled;
5512 }
5513
5514 static int is_system_running(sd_bus *bus, char **args) {
5515 _cleanup_free_ char *state = NULL;
5516 int r;
5517
5518 r = sd_bus_get_property_string(
5519 bus,
5520 "org.freedesktop.systemd1",
5521 "/org/freedesktop/systemd1",
5522 "org.freedesktop.systemd1.Manager",
5523 "SystemState",
5524 NULL,
5525 &state);
5526 if (r < 0) {
5527 if (!arg_quiet)
5528 puts("unknown");
5529 return 0;
5530 }
5531
5532 if (!arg_quiet)
5533 puts(state);
5534
5535 return streq(state, "running") ? EXIT_SUCCESS : EXIT_FAILURE;
5536 }
5537
5538 static void systemctl_help(void) {
5539
5540 pager_open_if_enabled();
5541
5542 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
5543 "Query or send control commands to the systemd manager.\n\n"
5544 " -h --help Show this help\n"
5545 " --version Show package version\n"
5546 " --system Connect to system manager\n"
5547 " --user Connect to user service manager\n"
5548 " -H --host=[USER@]HOST\n"
5549 " Operate on remote host\n"
5550 " -M --machine=CONTAINER\n"
5551 " Operate on local container\n"
5552 " -t --type=TYPE List only units of a particular type\n"
5553 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
5554 " -p --property=NAME Show only properties by this name\n"
5555 " -a --all Show all loaded units/properties, including dead/empty\n"
5556 " ones. To list all units installed on the system, use\n"
5557 " the 'list-unit-files' command instead.\n"
5558 " -l --full Don't ellipsize unit names on output\n"
5559 " -r --recursive Show unit list of host and local containers\n"
5560 " --reverse Show reverse dependencies with 'list-dependencies'\n"
5561 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
5562 " queueing a new job\n"
5563 " --show-types When showing sockets, explicitly show their type\n"
5564 " -i --ignore-inhibitors\n"
5565 " When shutting down or sleeping, ignore inhibitors\n"
5566 " --kill-who=WHO Who to send signal to\n"
5567 " -s --signal=SIGNAL Which signal to send\n"
5568 " -q --quiet Suppress output\n"
5569 " --no-block Do not wait until operation finished\n"
5570 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5571 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
5572 " configuration\n"
5573 " --no-legend Do not print a legend (column headers and hints)\n"
5574 " --no-pager Do not pipe output into a pager\n"
5575 " --no-ask-password\n"
5576 " Do not ask for system passwords\n"
5577 " --global Enable/disable unit files globally\n"
5578 " --runtime Enable unit files only temporarily until next reboot\n"
5579 " -f --force When enabling unit files, override existing symlinks\n"
5580 " When shutting down, execute action immediately\n"
5581 " --preset-mode= Specifies whether fully apply presets, or only enable,\n"
5582 " or only disable\n"
5583 " --root=PATH Enable unit files in the specified root directory\n"
5584 " -n --lines=INTEGER Number of journal entries to show\n"
5585 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
5586 " verbose, export, json, json-pretty, json-sse, cat)\n"
5587 " --plain Print unit dependencies as a list instead of a tree\n\n"
5588 "Unit Commands:\n"
5589 " list-units [PATTERN...] List loaded units\n"
5590 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
5591 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
5592 " start NAME... Start (activate) one or more units\n"
5593 " stop NAME... Stop (deactivate) one or more units\n"
5594 " reload NAME... Reload one or more units\n"
5595 " restart NAME... Start or restart one or more units\n"
5596 " try-restart NAME... Restart one or more units if active\n"
5597 " reload-or-restart NAME... Reload one or more units if possible,\n"
5598 " otherwise start or restart\n"
5599 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
5600 " otherwise restart if active\n"
5601 " isolate NAME Start one unit and stop all others\n"
5602 " kill NAME... Send signal to processes of a unit\n"
5603 " is-active PATTERN... Check whether units are active\n"
5604 " is-failed PATTERN... Check whether units are failed\n"
5605 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
5606 " show [PATTERN...|JOB...] Show properties of one or more\n"
5607 " units/jobs or the manager\n"
5608 " cat PATTERN... Show files and drop-ins of one or more units\n"
5609 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
5610 " help PATTERN...|PID... Show manual for one or more units\n"
5611 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
5612 " units\n"
5613 " list-dependencies [NAME] Recursively show units which are required\n"
5614 " or wanted by this unit or by which this\n"
5615 " unit is required or wanted\n\n"
5616 "Unit File Commands:\n"
5617 " list-unit-files [PATTERN...] List installed unit files\n"
5618 " enable NAME... Enable one or more unit files\n"
5619 " disable NAME... Disable one or more unit files\n"
5620 " reenable NAME... Reenable one or more unit files\n"
5621 " preset NAME... Enable/disable one or more unit files\n"
5622 " based on preset configuration\n"
5623 " preset-all Enable/disable all unit files based on\n"
5624 " preset configuration\n"
5625 " is-enabled NAME... Check whether unit files are enabled\n\n"
5626 " mask NAME... Mask one or more units\n"
5627 " unmask NAME... Unmask one or more units\n"
5628 " link PATH... Link one or more units files into\n"
5629 " the search path\n"
5630 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
5631 " on specified one or more units\n"
5632 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
5633 " on specified one or more units\n"
5634 " get-default Get the name of the default target\n"
5635 " set-default NAME Set the default target\n\n"
5636 "Machine Commands:\n"
5637 " list-machines [PATTERN...] List local containers and host\n\n"
5638 "Job Commands:\n"
5639 " list-jobs [PATTERN...] List jobs\n"
5640 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
5641 "Snapshot Commands:\n"
5642 " snapshot [NAME] Create a snapshot\n"
5643 " delete NAME... Remove one or more snapshots\n\n"
5644 "Environment Commands:\n"
5645 " show-environment Dump environment\n"
5646 " set-environment NAME=VALUE... Set one or more environment variables\n"
5647 " unset-environment NAME... Unset one or more environment variables\n"
5648 " import-environment NAME... Import all, one or more environment variables\n\n"
5649 "Manager Lifecycle Commands:\n"
5650 " daemon-reload Reload systemd manager configuration\n"
5651 " daemon-reexec Reexecute systemd manager\n\n"
5652 "System Commands:\n"
5653 " is-system-running Check whether system is fully running\n"
5654 " default Enter system default mode\n"
5655 " rescue Enter system rescue mode\n"
5656 " emergency Enter system emergency mode\n"
5657 " halt Shut down and halt the system\n"
5658 " poweroff Shut down and power-off the system\n"
5659 " reboot [ARG] Shut down and reboot the system\n"
5660 " kexec Shut down and reboot the system with kexec\n"
5661 " exit Request user instance exit\n"
5662 " switch-root ROOT [INIT] Change to a different root file system\n"
5663 " suspend Suspend the system\n"
5664 " hibernate Hibernate the system\n"
5665 " hybrid-sleep Hibernate and suspend the system\n",
5666 program_invocation_short_name);
5667 }
5668
5669 static void halt_help(void) {
5670 printf("%s [OPTIONS...]%s\n\n"
5671 "%s the system.\n\n"
5672 " --help Show this help\n"
5673 " --halt Halt the machine\n"
5674 " -p --poweroff Switch off the machine\n"
5675 " --reboot Reboot the machine\n"
5676 " -f --force Force immediate halt/power-off/reboot\n"
5677 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
5678 " -d --no-wtmp Don't write wtmp record\n"
5679 " --no-wall Don't send wall message before halt/power-off/reboot\n",
5680 program_invocation_short_name,
5681 arg_action == ACTION_REBOOT ? " [ARG]" : "",
5682 arg_action == ACTION_REBOOT ? "Reboot" :
5683 arg_action == ACTION_POWEROFF ? "Power off" :
5684 "Halt");
5685 }
5686
5687 static void shutdown_help(void) {
5688 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
5689 "Shut down the system.\n\n"
5690 " --help Show this help\n"
5691 " -H --halt Halt the machine\n"
5692 " -P --poweroff Power-off the machine\n"
5693 " -r --reboot Reboot the machine\n"
5694 " -h Equivalent to --poweroff, overridden by --halt\n"
5695 " -k Don't halt/power-off/reboot, just send warnings\n"
5696 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5697 " -c Cancel a pending shutdown\n",
5698 program_invocation_short_name);
5699 }
5700
5701 static void telinit_help(void) {
5702 printf("%s [OPTIONS...] {COMMAND}\n\n"
5703 "Send control commands to the init daemon.\n\n"
5704 " --help Show this help\n"
5705 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
5706 "Commands:\n"
5707 " 0 Power-off the machine\n"
5708 " 6 Reboot the machine\n"
5709 " 2, 3, 4, 5 Start runlevelX.target unit\n"
5710 " 1, s, S Enter rescue mode\n"
5711 " q, Q Reload init daemon configuration\n"
5712 " u, U Reexecute init daemon\n",
5713 program_invocation_short_name);
5714 }
5715
5716 static void runlevel_help(void) {
5717 printf("%s [OPTIONS...]\n\n"
5718 "Prints the previous and current runlevel of the init system.\n\n"
5719 " --help Show this help\n",
5720 program_invocation_short_name);
5721 }
5722
5723 static void help_types(void) {
5724 int i;
5725 const char *t;
5726
5727 if (!arg_no_legend)
5728 puts("Available unit types:");
5729 for (i = 0; i < _UNIT_TYPE_MAX; i++) {
5730 t = unit_type_to_string(i);
5731 if (t)
5732 puts(t);
5733 }
5734 }
5735
5736 static int systemctl_parse_argv(int argc, char *argv[]) {
5737
5738 enum {
5739 ARG_FAIL = 0x100,
5740 ARG_REVERSE,
5741 ARG_AFTER,
5742 ARG_BEFORE,
5743 ARG_SHOW_TYPES,
5744 ARG_IRREVERSIBLE,
5745 ARG_IGNORE_DEPENDENCIES,
5746 ARG_VERSION,
5747 ARG_USER,
5748 ARG_SYSTEM,
5749 ARG_GLOBAL,
5750 ARG_NO_BLOCK,
5751 ARG_NO_LEGEND,
5752 ARG_NO_PAGER,
5753 ARG_NO_WALL,
5754 ARG_ROOT,
5755 ARG_NO_RELOAD,
5756 ARG_KILL_WHO,
5757 ARG_NO_ASK_PASSWORD,
5758 ARG_FAILED,
5759 ARG_RUNTIME,
5760 ARG_FORCE,
5761 ARG_PLAIN,
5762 ARG_STATE,
5763 ARG_JOB_MODE,
5764 ARG_PRESET_MODE,
5765 };
5766
5767 static const struct option options[] = {
5768 { "help", no_argument, NULL, 'h' },
5769 { "version", no_argument, NULL, ARG_VERSION },
5770 { "type", required_argument, NULL, 't' },
5771 { "property", required_argument, NULL, 'p' },
5772 { "all", no_argument, NULL, 'a' },
5773 { "reverse", no_argument, NULL, ARG_REVERSE },
5774 { "after", no_argument, NULL, ARG_AFTER },
5775 { "before", no_argument, NULL, ARG_BEFORE },
5776 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
5777 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
5778 { "full", no_argument, NULL, 'l' },
5779 { "job-mode", required_argument, NULL, ARG_JOB_MODE },
5780 { "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */
5781 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */
5782 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
5783 { "ignore-inhibitors", no_argument, NULL, 'i' },
5784 { "user", no_argument, NULL, ARG_USER },
5785 { "system", no_argument, NULL, ARG_SYSTEM },
5786 { "global", no_argument, NULL, ARG_GLOBAL },
5787 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
5788 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
5789 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
5790 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5791 { "quiet", no_argument, NULL, 'q' },
5792 { "root", required_argument, NULL, ARG_ROOT },
5793 { "force", no_argument, NULL, ARG_FORCE },
5794 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
5795 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
5796 { "signal", required_argument, NULL, 's' },
5797 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
5798 { "host", required_argument, NULL, 'H' },
5799 { "machine", required_argument, NULL, 'M' },
5800 { "runtime", no_argument, NULL, ARG_RUNTIME },
5801 { "lines", required_argument, NULL, 'n' },
5802 { "output", required_argument, NULL, 'o' },
5803 { "plain", no_argument, NULL, ARG_PLAIN },
5804 { "state", required_argument, NULL, ARG_STATE },
5805 { "recursive", no_argument, NULL, 'r' },
5806 { "preset-mode", required_argument, NULL, ARG_PRESET_MODE },
5807 {}
5808 };
5809
5810 int c;
5811
5812 assert(argc >= 0);
5813 assert(argv);
5814
5815 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0)
5816
5817 switch (c) {
5818
5819 case 'h':
5820 systemctl_help();
5821 return 0;
5822
5823 case ARG_VERSION:
5824 puts(PACKAGE_STRING);
5825 puts(SYSTEMD_FEATURES);
5826 return 0;
5827
5828 case 't': {
5829 const char *word, *state;
5830 size_t size;
5831
5832 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5833 _cleanup_free_ char *type;
5834
5835 type = strndup(word, size);
5836 if (!type)
5837 return -ENOMEM;
5838
5839 if (streq(type, "help")) {
5840 help_types();
5841 return 0;
5842 }
5843
5844 if (unit_type_from_string(type) >= 0) {
5845 if (strv_push(&arg_types, type))
5846 return log_oom();
5847 type = NULL;
5848 continue;
5849 }
5850
5851 /* It's much nicer to use --state= for
5852 * load states, but let's support this
5853 * in --types= too for compatibility
5854 * with old versions */
5855 if (unit_load_state_from_string(optarg) >= 0) {
5856 if (strv_push(&arg_states, type) < 0)
5857 return log_oom();
5858 type = NULL;
5859 continue;
5860 }
5861
5862 log_error("Unknown unit type or load state '%s'.", type);
5863 log_info("Use -t help to see a list of allowed values.");
5864 return -EINVAL;
5865 }
5866
5867 break;
5868 }
5869
5870 case 'p': {
5871 /* Make sure that if the empty property list
5872 was specified, we won't show any properties. */
5873 if (isempty(optarg) && !arg_properties) {
5874 arg_properties = new0(char*, 1);
5875 if (!arg_properties)
5876 return log_oom();
5877 } else {
5878 const char *word, *state;
5879 size_t size;
5880
5881 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5882 char *prop;
5883
5884 prop = strndup(word, size);
5885 if (!prop)
5886 return log_oom();
5887
5888 if (strv_consume(&arg_properties, prop) < 0)
5889 return log_oom();
5890 }
5891 }
5892
5893 /* If the user asked for a particular
5894 * property, show it to him, even if it is
5895 * empty. */
5896 arg_all = true;
5897
5898 break;
5899 }
5900
5901 case 'a':
5902 arg_all = true;
5903 break;
5904
5905 case ARG_REVERSE:
5906 arg_dependency = DEPENDENCY_REVERSE;
5907 break;
5908
5909 case ARG_AFTER:
5910 arg_dependency = DEPENDENCY_AFTER;
5911 break;
5912
5913 case ARG_BEFORE:
5914 arg_dependency = DEPENDENCY_BEFORE;
5915 break;
5916
5917 case ARG_SHOW_TYPES:
5918 arg_show_types = true;
5919 break;
5920
5921 case ARG_JOB_MODE:
5922 arg_job_mode = optarg;
5923 break;
5924
5925 case ARG_FAIL:
5926 arg_job_mode = "fail";
5927 break;
5928
5929 case ARG_IRREVERSIBLE:
5930 arg_job_mode = "replace-irreversibly";
5931 break;
5932
5933 case ARG_IGNORE_DEPENDENCIES:
5934 arg_job_mode = "ignore-dependencies";
5935 break;
5936
5937 case ARG_USER:
5938 arg_scope = UNIT_FILE_USER;
5939 break;
5940
5941 case ARG_SYSTEM:
5942 arg_scope = UNIT_FILE_SYSTEM;
5943 break;
5944
5945 case ARG_GLOBAL:
5946 arg_scope = UNIT_FILE_GLOBAL;
5947 break;
5948
5949 case ARG_NO_BLOCK:
5950 arg_no_block = true;
5951 break;
5952
5953 case ARG_NO_LEGEND:
5954 arg_no_legend = true;
5955 break;
5956
5957 case ARG_NO_PAGER:
5958 arg_no_pager = true;
5959 break;
5960
5961 case ARG_NO_WALL:
5962 arg_no_wall = true;
5963 break;
5964
5965 case ARG_ROOT:
5966 arg_root = optarg;
5967 break;
5968
5969 case 'l':
5970 arg_full = true;
5971 break;
5972
5973 case ARG_FAILED:
5974 if (strv_extend(&arg_states, "failed") < 0)
5975 return log_oom();
5976
5977 break;
5978
5979 case 'q':
5980 arg_quiet = true;
5981 break;
5982
5983 case ARG_FORCE:
5984 arg_force ++;
5985 break;
5986
5987 case 'f':
5988 arg_force ++;
5989 break;
5990
5991 case ARG_NO_RELOAD:
5992 arg_no_reload = true;
5993 break;
5994
5995 case ARG_KILL_WHO:
5996 arg_kill_who = optarg;
5997 break;
5998
5999 case 's':
6000 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
6001 log_error("Failed to parse signal string %s.", optarg);
6002 return -EINVAL;
6003 }
6004 break;
6005
6006 case ARG_NO_ASK_PASSWORD:
6007 arg_ask_password = false;
6008 break;
6009
6010 case 'H':
6011 arg_transport = BUS_TRANSPORT_REMOTE;
6012 arg_host = optarg;
6013 break;
6014
6015 case 'M':
6016 arg_transport = BUS_TRANSPORT_CONTAINER;
6017 arg_host = optarg;
6018 break;
6019
6020 case ARG_RUNTIME:
6021 arg_runtime = true;
6022 break;
6023
6024 case 'n':
6025 if (safe_atou(optarg, &arg_lines) < 0) {
6026 log_error("Failed to parse lines '%s'", optarg);
6027 return -EINVAL;
6028 }
6029 break;
6030
6031 case 'o':
6032 arg_output = output_mode_from_string(optarg);
6033 if (arg_output < 0) {
6034 log_error("Unknown output '%s'.", optarg);
6035 return -EINVAL;
6036 }
6037 break;
6038
6039 case 'i':
6040 arg_ignore_inhibitors = true;
6041 break;
6042
6043 case ARG_PLAIN:
6044 arg_plain = true;
6045 break;
6046
6047 case ARG_STATE: {
6048 const char *word, *state;
6049 size_t size;
6050
6051 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6052 char *s;
6053
6054 s = strndup(word, size);
6055 if (!s)
6056 return log_oom();
6057
6058 if (strv_consume(&arg_states, s) < 0)
6059 return log_oom();
6060 }
6061 break;
6062 }
6063
6064 case 'r':
6065 if (geteuid() != 0) {
6066 log_error("--recursive requires root privileges.");
6067 return -EPERM;
6068 }
6069
6070 arg_recursive = true;
6071 break;
6072
6073 case ARG_PRESET_MODE:
6074
6075 arg_preset_mode = unit_file_preset_mode_from_string(optarg);
6076 if (arg_preset_mode < 0) {
6077 log_error("Failed to parse preset mode: %s.", optarg);
6078 return -EINVAL;
6079 }
6080
6081 break;
6082
6083 case '?':
6084 return -EINVAL;
6085
6086 default:
6087 assert_not_reached("Unhandled option");
6088 }
6089
6090 if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM) {
6091 log_error("Cannot access user instance remotely.");
6092 return -EINVAL;
6093 }
6094
6095 return 1;
6096 }
6097
6098 static int halt_parse_argv(int argc, char *argv[]) {
6099
6100 enum {
6101 ARG_HELP = 0x100,
6102 ARG_HALT,
6103 ARG_REBOOT,
6104 ARG_NO_WALL
6105 };
6106
6107 static const struct option options[] = {
6108 { "help", no_argument, NULL, ARG_HELP },
6109 { "halt", no_argument, NULL, ARG_HALT },
6110 { "poweroff", no_argument, NULL, 'p' },
6111 { "reboot", no_argument, NULL, ARG_REBOOT },
6112 { "force", no_argument, NULL, 'f' },
6113 { "wtmp-only", no_argument, NULL, 'w' },
6114 { "no-wtmp", no_argument, NULL, 'd' },
6115 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6116 {}
6117 };
6118
6119 int c, r, runlevel;
6120
6121 assert(argc >= 0);
6122 assert(argv);
6123
6124 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
6125 if (runlevel == '0' || runlevel == '6')
6126 arg_force = 2;
6127
6128 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0)
6129 switch (c) {
6130
6131 case ARG_HELP:
6132 halt_help();
6133 return 0;
6134
6135 case ARG_HALT:
6136 arg_action = ACTION_HALT;
6137 break;
6138
6139 case 'p':
6140 if (arg_action != ACTION_REBOOT)
6141 arg_action = ACTION_POWEROFF;
6142 break;
6143
6144 case ARG_REBOOT:
6145 arg_action = ACTION_REBOOT;
6146 break;
6147
6148 case 'f':
6149 arg_force = 2;
6150 break;
6151
6152 case 'w':
6153 arg_dry = true;
6154 break;
6155
6156 case 'd':
6157 arg_no_wtmp = true;
6158 break;
6159
6160 case ARG_NO_WALL:
6161 arg_no_wall = true;
6162 break;
6163
6164 case 'i':
6165 case 'h':
6166 case 'n':
6167 /* Compatibility nops */
6168 break;
6169
6170 case '?':
6171 return -EINVAL;
6172
6173 default:
6174 assert_not_reached("Unhandled option");
6175 }
6176
6177 if (arg_action == ACTION_REBOOT && (argc == optind || argc == optind + 1)) {
6178 r = update_reboot_param_file(argc == optind + 1 ? argv[optind] : NULL);
6179 if (r < 0)
6180 return r;
6181 } else if (optind < argc) {
6182 log_error("Too many arguments.");
6183 return -EINVAL;
6184 }
6185
6186 return 1;
6187 }
6188
6189 static int parse_time_spec(const char *t, usec_t *_u) {
6190 assert(t);
6191 assert(_u);
6192
6193 if (streq(t, "now"))
6194 *_u = 0;
6195 else if (!strchr(t, ':')) {
6196 uint64_t u;
6197
6198 if (safe_atou64(t, &u) < 0)
6199 return -EINVAL;
6200
6201 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
6202 } else {
6203 char *e = NULL;
6204 long hour, minute;
6205 struct tm tm = {};
6206 time_t s;
6207 usec_t n;
6208
6209 errno = 0;
6210 hour = strtol(t, &e, 10);
6211 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
6212 return -EINVAL;
6213
6214 minute = strtol(e+1, &e, 10);
6215 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
6216 return -EINVAL;
6217
6218 n = now(CLOCK_REALTIME);
6219 s = (time_t) (n / USEC_PER_SEC);
6220
6221 assert_se(localtime_r(&s, &tm));
6222
6223 tm.tm_hour = (int) hour;
6224 tm.tm_min = (int) minute;
6225 tm.tm_sec = 0;
6226
6227 assert_se(s = mktime(&tm));
6228
6229 *_u = (usec_t) s * USEC_PER_SEC;
6230
6231 while (*_u <= n)
6232 *_u += USEC_PER_DAY;
6233 }
6234
6235 return 0;
6236 }
6237
6238 static int shutdown_parse_argv(int argc, char *argv[]) {
6239
6240 enum {
6241 ARG_HELP = 0x100,
6242 ARG_NO_WALL
6243 };
6244
6245 static const struct option options[] = {
6246 { "help", no_argument, NULL, ARG_HELP },
6247 { "halt", no_argument, NULL, 'H' },
6248 { "poweroff", no_argument, NULL, 'P' },
6249 { "reboot", no_argument, NULL, 'r' },
6250 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
6251 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6252 {}
6253 };
6254
6255 int c, r;
6256
6257 assert(argc >= 0);
6258 assert(argv);
6259
6260 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0)
6261 switch (c) {
6262
6263 case ARG_HELP:
6264 shutdown_help();
6265 return 0;
6266
6267 case 'H':
6268 arg_action = ACTION_HALT;
6269 break;
6270
6271 case 'P':
6272 arg_action = ACTION_POWEROFF;
6273 break;
6274
6275 case 'r':
6276 if (kexec_loaded())
6277 arg_action = ACTION_KEXEC;
6278 else
6279 arg_action = ACTION_REBOOT;
6280 break;
6281
6282 case 'K':
6283 arg_action = ACTION_KEXEC;
6284 break;
6285
6286 case 'h':
6287 if (arg_action != ACTION_HALT)
6288 arg_action = ACTION_POWEROFF;
6289 break;
6290
6291 case 'k':
6292 arg_dry = true;
6293 break;
6294
6295 case ARG_NO_WALL:
6296 arg_no_wall = true;
6297 break;
6298
6299 case 't':
6300 case 'a':
6301 /* Compatibility nops */
6302 break;
6303
6304 case 'c':
6305 arg_action = ACTION_CANCEL_SHUTDOWN;
6306 break;
6307
6308 case '?':
6309 return -EINVAL;
6310
6311 default:
6312 assert_not_reached("Unhandled option");
6313 }
6314
6315 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
6316 r = parse_time_spec(argv[optind], &arg_when);
6317 if (r < 0) {
6318 log_error("Failed to parse time specification: %s", argv[optind]);
6319 return r;
6320 }
6321 } else
6322 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
6323
6324 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
6325 /* No time argument for shutdown cancel */
6326 arg_wall = argv + optind;
6327 else if (argc > optind + 1)
6328 /* We skip the time argument */
6329 arg_wall = argv + optind + 1;
6330
6331 optind = argc;
6332
6333 return 1;
6334 }
6335
6336 static int telinit_parse_argv(int argc, char *argv[]) {
6337
6338 enum {
6339 ARG_HELP = 0x100,
6340 ARG_NO_WALL
6341 };
6342
6343 static const struct option options[] = {
6344 { "help", no_argument, NULL, ARG_HELP },
6345 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6346 {}
6347 };
6348
6349 static const struct {
6350 char from;
6351 enum action to;
6352 } table[] = {
6353 { '0', ACTION_POWEROFF },
6354 { '6', ACTION_REBOOT },
6355 { '1', ACTION_RESCUE },
6356 { '2', ACTION_RUNLEVEL2 },
6357 { '3', ACTION_RUNLEVEL3 },
6358 { '4', ACTION_RUNLEVEL4 },
6359 { '5', ACTION_RUNLEVEL5 },
6360 { 's', ACTION_RESCUE },
6361 { 'S', ACTION_RESCUE },
6362 { 'q', ACTION_RELOAD },
6363 { 'Q', ACTION_RELOAD },
6364 { 'u', ACTION_REEXEC },
6365 { 'U', ACTION_REEXEC }
6366 };
6367
6368 unsigned i;
6369 int c;
6370
6371 assert(argc >= 0);
6372 assert(argv);
6373
6374 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
6375 switch (c) {
6376
6377 case ARG_HELP:
6378 telinit_help();
6379 return 0;
6380
6381 case ARG_NO_WALL:
6382 arg_no_wall = true;
6383 break;
6384
6385 case '?':
6386 return -EINVAL;
6387
6388 default:
6389 assert_not_reached("Unhandled option");
6390 }
6391
6392 if (optind >= argc) {
6393 log_error("%s: required argument missing.",
6394 program_invocation_short_name);
6395 return -EINVAL;
6396 }
6397
6398 if (optind + 1 < argc) {
6399 log_error("Too many arguments.");
6400 return -EINVAL;
6401 }
6402
6403 if (strlen(argv[optind]) != 1) {
6404 log_error("Expected single character argument.");
6405 return -EINVAL;
6406 }
6407
6408 for (i = 0; i < ELEMENTSOF(table); i++)
6409 if (table[i].from == argv[optind][0])
6410 break;
6411
6412 if (i >= ELEMENTSOF(table)) {
6413 log_error("Unknown command '%s'.", argv[optind]);
6414 return -EINVAL;
6415 }
6416
6417 arg_action = table[i].to;
6418
6419 optind ++;
6420
6421 return 1;
6422 }
6423
6424 static int runlevel_parse_argv(int argc, char *argv[]) {
6425
6426 enum {
6427 ARG_HELP = 0x100,
6428 };
6429
6430 static const struct option options[] = {
6431 { "help", no_argument, NULL, ARG_HELP },
6432 {}
6433 };
6434
6435 int c;
6436
6437 assert(argc >= 0);
6438 assert(argv);
6439
6440 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
6441 switch (c) {
6442
6443 case ARG_HELP:
6444 runlevel_help();
6445 return 0;
6446
6447 case '?':
6448 return -EINVAL;
6449
6450 default:
6451 assert_not_reached("Unhandled option");
6452 }
6453
6454 if (optind < argc) {
6455 log_error("Too many arguments.");
6456 return -EINVAL;
6457 }
6458
6459 return 1;
6460 }
6461
6462 static int parse_argv(int argc, char *argv[]) {
6463 assert(argc >= 0);
6464 assert(argv);
6465
6466 if (program_invocation_short_name) {
6467
6468 if (strstr(program_invocation_short_name, "halt")) {
6469 arg_action = ACTION_HALT;
6470 return halt_parse_argv(argc, argv);
6471 } else if (strstr(program_invocation_short_name, "poweroff")) {
6472 arg_action = ACTION_POWEROFF;
6473 return halt_parse_argv(argc, argv);
6474 } else if (strstr(program_invocation_short_name, "reboot")) {
6475 if (kexec_loaded())
6476 arg_action = ACTION_KEXEC;
6477 else
6478 arg_action = ACTION_REBOOT;
6479 return halt_parse_argv(argc, argv);
6480 } else if (strstr(program_invocation_short_name, "shutdown")) {
6481 arg_action = ACTION_POWEROFF;
6482 return shutdown_parse_argv(argc, argv);
6483 } else if (strstr(program_invocation_short_name, "init")) {
6484
6485 if (sd_booted() > 0) {
6486 arg_action = _ACTION_INVALID;
6487 return telinit_parse_argv(argc, argv);
6488 } else {
6489 /* Hmm, so some other init system is
6490 * running, we need to forward this
6491 * request to it. For now we simply
6492 * guess that it is Upstart. */
6493
6494 execv(TELINIT, argv);
6495
6496 log_error("Couldn't find an alternative telinit implementation to spawn.");
6497 return -EIO;
6498 }
6499
6500 } else if (strstr(program_invocation_short_name, "runlevel")) {
6501 arg_action = ACTION_RUNLEVEL;
6502 return runlevel_parse_argv(argc, argv);
6503 }
6504 }
6505
6506 arg_action = ACTION_SYSTEMCTL;
6507 return systemctl_parse_argv(argc, argv);
6508 }
6509
6510 _pure_ static int action_to_runlevel(void) {
6511
6512 static const char table[_ACTION_MAX] = {
6513 [ACTION_HALT] = '0',
6514 [ACTION_POWEROFF] = '0',
6515 [ACTION_REBOOT] = '6',
6516 [ACTION_RUNLEVEL2] = '2',
6517 [ACTION_RUNLEVEL3] = '3',
6518 [ACTION_RUNLEVEL4] = '4',
6519 [ACTION_RUNLEVEL5] = '5',
6520 [ACTION_RESCUE] = '1'
6521 };
6522
6523 assert(arg_action < _ACTION_MAX);
6524
6525 return table[arg_action];
6526 }
6527
6528 static int talk_initctl(void) {
6529
6530 struct init_request request = {
6531 .magic = INIT_MAGIC,
6532 .sleeptime = 0,
6533 .cmd = INIT_CMD_RUNLVL
6534 };
6535
6536 _cleanup_close_ int fd = -1;
6537 char rl;
6538 int r;
6539
6540 rl = action_to_runlevel();
6541 if (!rl)
6542 return 0;
6543
6544 request.runlevel = rl;
6545
6546 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
6547 if (fd < 0) {
6548 if (errno == ENOENT)
6549 return 0;
6550
6551 log_error("Failed to open "INIT_FIFO": %m");
6552 return -errno;
6553 }
6554
6555 errno = 0;
6556 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
6557 if (r) {
6558 log_error("Failed to write to "INIT_FIFO": %m");
6559 return errno > 0 ? -errno : -EIO;
6560 }
6561
6562 return 1;
6563 }
6564
6565 static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
6566
6567 static const struct {
6568 const char* verb;
6569 const enum {
6570 MORE,
6571 LESS,
6572 EQUAL
6573 } argc_cmp;
6574 const int argc;
6575 int (* const dispatch)(sd_bus *bus, char **args);
6576 const enum {
6577 NOBUS = 1,
6578 FORCE,
6579 } bus;
6580 } verbs[] = {
6581 { "list-units", MORE, 0, list_units },
6582 { "list-unit-files", MORE, 1, list_unit_files, NOBUS },
6583 { "list-sockets", MORE, 1, list_sockets },
6584 { "list-timers", MORE, 1, list_timers },
6585 { "list-jobs", MORE, 1, list_jobs },
6586 { "list-machines", MORE, 1, list_machines },
6587 { "clear-jobs", EQUAL, 1, daemon_reload },
6588 { "cancel", MORE, 2, cancel_job },
6589 { "start", MORE, 2, start_unit },
6590 { "stop", MORE, 2, start_unit },
6591 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
6592 { "reload", MORE, 2, start_unit },
6593 { "restart", MORE, 2, start_unit },
6594 { "try-restart", MORE, 2, start_unit },
6595 { "reload-or-restart", MORE, 2, start_unit },
6596 { "reload-or-try-restart", MORE, 2, start_unit },
6597 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
6598 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
6599 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
6600 { "isolate", EQUAL, 2, start_unit },
6601 { "kill", MORE, 2, kill_unit },
6602 { "is-active", MORE, 2, check_unit_active },
6603 { "check", MORE, 2, check_unit_active },
6604 { "is-failed", MORE, 2, check_unit_failed },
6605 { "show", MORE, 1, show },
6606 { "cat", MORE, 2, cat },
6607 { "status", MORE, 1, show },
6608 { "help", MORE, 2, show },
6609 { "snapshot", LESS, 2, snapshot },
6610 { "delete", MORE, 2, delete_snapshot },
6611 { "daemon-reload", EQUAL, 1, daemon_reload },
6612 { "daemon-reexec", EQUAL, 1, daemon_reload },
6613 { "show-environment", EQUAL, 1, show_environment },
6614 { "set-environment", MORE, 2, set_environment },
6615 { "unset-environment", MORE, 2, set_environment },
6616 { "import-environment", MORE, 1, import_environment},
6617 { "halt", EQUAL, 1, start_special, FORCE },
6618 { "poweroff", EQUAL, 1, start_special, FORCE },
6619 { "reboot", EQUAL, 1, start_special, FORCE },
6620 { "kexec", EQUAL, 1, start_special },
6621 { "suspend", EQUAL, 1, start_special },
6622 { "hibernate", EQUAL, 1, start_special },
6623 { "hybrid-sleep", EQUAL, 1, start_special },
6624 { "default", EQUAL, 1, start_special },
6625 { "rescue", EQUAL, 1, start_special },
6626 { "emergency", EQUAL, 1, start_special },
6627 { "exit", EQUAL, 1, start_special },
6628 { "reset-failed", MORE, 1, reset_failed },
6629 { "enable", MORE, 2, enable_unit, NOBUS },
6630 { "disable", MORE, 2, enable_unit, NOBUS },
6631 { "is-enabled", MORE, 2, unit_is_enabled, NOBUS },
6632 { "reenable", MORE, 2, enable_unit, NOBUS },
6633 { "preset", MORE, 2, enable_unit, NOBUS },
6634 { "preset-all", EQUAL, 1, preset_all, NOBUS },
6635 { "mask", MORE, 2, enable_unit, NOBUS },
6636 { "unmask", MORE, 2, enable_unit, NOBUS },
6637 { "link", MORE, 2, enable_unit, NOBUS },
6638 { "switch-root", MORE, 2, switch_root },
6639 { "list-dependencies", LESS, 2, list_dependencies },
6640 { "set-default", EQUAL, 2, set_default, NOBUS },
6641 { "get-default", EQUAL, 1, get_default, NOBUS },
6642 { "set-property", MORE, 3, set_property },
6643 { "is-system-running", EQUAL, 1, is_system_running },
6644 { "add-wants", MORE, 3, add_dependency, NOBUS },
6645 { "add-requires", MORE, 3, add_dependency, NOBUS },
6646 {}
6647 }, *verb = verbs;
6648
6649 int left;
6650
6651 assert(argc >= 0);
6652 assert(argv);
6653
6654 left = argc - optind;
6655
6656 /* Special rule: no arguments (left == 0) means "list-units" */
6657 if (left > 0) {
6658 if (streq(argv[optind], "help") && !argv[optind+1]) {
6659 log_error("This command expects one or more "
6660 "unit names. Did you mean --help?");
6661 return -EINVAL;
6662 }
6663
6664 for (; verb->verb; verb++)
6665 if (streq(argv[optind], verb->verb))
6666 goto found;
6667
6668 log_error("Unknown operation '%s'.", argv[optind]);
6669 return -EINVAL;
6670 }
6671 found:
6672
6673 switch (verb->argc_cmp) {
6674
6675 case EQUAL:
6676 if (left != verb->argc) {
6677 log_error("Invalid number of arguments.");
6678 return -EINVAL;
6679 }
6680
6681 break;
6682
6683 case MORE:
6684 if (left < verb->argc) {
6685 log_error("Too few arguments.");
6686 return -EINVAL;
6687 }
6688
6689 break;
6690
6691 case LESS:
6692 if (left > verb->argc) {
6693 log_error("Too many arguments.");
6694 return -EINVAL;
6695 }
6696
6697 break;
6698
6699 default:
6700 assert_not_reached("Unknown comparison operator.");
6701 }
6702
6703 /* Require a bus connection for all operations but
6704 * enable/disable */
6705 if (verb->bus == NOBUS) {
6706 if (!bus && !avoid_bus()) {
6707 log_error("Failed to get D-Bus connection: %s", strerror(-bus_error));
6708 return -EIO;
6709 }
6710
6711 } else {
6712 if (running_in_chroot() > 0) {
6713 log_info("Running in chroot, ignoring request.");
6714 return 0;
6715 }
6716
6717 if ((verb->bus != FORCE || arg_force <= 0) && !bus) {
6718 log_error("Failed to get D-Bus connection: %s", strerror(-bus_error));
6719 return -EIO;
6720 }
6721 }
6722
6723 return verb->dispatch(bus, argv + optind);
6724 }
6725
6726 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
6727
6728 struct sd_shutdown_command c = {
6729 .usec = t,
6730 .mode = mode,
6731 .dry_run = dry_run,
6732 .warn_wall = warn,
6733 };
6734
6735 union sockaddr_union sockaddr = {
6736 .un.sun_family = AF_UNIX,
6737 .un.sun_path = "/run/systemd/shutdownd",
6738 };
6739
6740 struct iovec iovec[2] = {{
6741 .iov_base = (char*) &c,
6742 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
6743 }};
6744
6745 struct msghdr msghdr = {
6746 .msg_name = &sockaddr,
6747 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
6748 + strlen("/run/systemd/shutdownd"),
6749 .msg_iov = iovec,
6750 .msg_iovlen = 1,
6751 };
6752
6753 _cleanup_close_ int fd;
6754
6755 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
6756 if (fd < 0)
6757 return -errno;
6758
6759 if (!isempty(message)) {
6760 iovec[1].iov_base = (char*) message;
6761 iovec[1].iov_len = strlen(message);
6762 msghdr.msg_iovlen++;
6763 }
6764
6765 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
6766 return -errno;
6767
6768 return 0;
6769 }
6770
6771 static int reload_with_fallback(sd_bus *bus) {
6772
6773 if (bus) {
6774 /* First, try systemd via D-Bus. */
6775 if (daemon_reload(bus, NULL) >= 0)
6776 return 0;
6777 }
6778
6779 /* Nothing else worked, so let's try signals */
6780 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
6781
6782 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
6783 log_error("kill() failed: %m");
6784 return -errno;
6785 }
6786
6787 return 0;
6788 }
6789
6790 static int start_with_fallback(sd_bus *bus) {
6791
6792 if (bus) {
6793 /* First, try systemd via D-Bus. */
6794 if (start_unit(bus, NULL) >= 0)
6795 goto done;
6796 }
6797
6798 /* Nothing else worked, so let's try
6799 * /dev/initctl */
6800 if (talk_initctl() > 0)
6801 goto done;
6802
6803 log_error("Failed to talk to init daemon.");
6804 return -EIO;
6805
6806 done:
6807 warn_wall(arg_action);
6808 return 0;
6809 }
6810
6811 static int halt_now(enum action a) {
6812
6813 /* Make sure C-A-D is handled by the kernel from this
6814 * point on... */
6815 reboot(RB_ENABLE_CAD);
6816
6817 switch (a) {
6818
6819 case ACTION_HALT:
6820 log_info("Halting.");
6821 reboot(RB_HALT_SYSTEM);
6822 return -errno;
6823
6824 case ACTION_POWEROFF:
6825 log_info("Powering off.");
6826 reboot(RB_POWER_OFF);
6827 return -errno;
6828
6829 case ACTION_REBOOT: {
6830 _cleanup_free_ char *param = NULL;
6831
6832 if (read_one_line_file(REBOOT_PARAM_FILE, &param) >= 0) {
6833 log_info("Rebooting with argument '%s'.", param);
6834 syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
6835 LINUX_REBOOT_CMD_RESTART2, param);
6836 }
6837
6838 log_info("Rebooting.");
6839 reboot(RB_AUTOBOOT);
6840 return -errno;
6841 }
6842
6843 default:
6844 assert_not_reached("Unknown action.");
6845 }
6846 }
6847
6848 static int halt_main(sd_bus *bus) {
6849 int r;
6850
6851 r = check_inhibitors(bus, arg_action);
6852 if (r < 0)
6853 return r;
6854
6855 if (geteuid() != 0) {
6856 /* Try logind if we are a normal user and no special
6857 * mode applies. Maybe PolicyKit allows us to shutdown
6858 * the machine. */
6859
6860 if (arg_when <= 0 &&
6861 !arg_dry &&
6862 arg_force <= 0 &&
6863 (arg_action == ACTION_POWEROFF ||
6864 arg_action == ACTION_REBOOT)) {
6865 r = reboot_with_logind(bus, arg_action);
6866 if (r >= 0)
6867 return r;
6868 }
6869
6870 log_error("Must be root.");
6871 return -EPERM;
6872 }
6873
6874 if (arg_when > 0) {
6875 _cleanup_free_ char *m;
6876
6877 m = strv_join(arg_wall, " ");
6878 if (!m)
6879 return log_oom();
6880
6881 r = send_shutdownd(arg_when,
6882 arg_action == ACTION_HALT ? 'H' :
6883 arg_action == ACTION_POWEROFF ? 'P' :
6884 arg_action == ACTION_KEXEC ? 'K' :
6885 'r',
6886 arg_dry,
6887 !arg_no_wall,
6888 m);
6889
6890 if (r < 0)
6891 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
6892 else {
6893 char date[FORMAT_TIMESTAMP_MAX];
6894
6895 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
6896 format_timestamp(date, sizeof(date), arg_when));
6897 return 0;
6898 }
6899 }
6900
6901 if (!arg_dry && !arg_force)
6902 return start_with_fallback(bus);
6903
6904 if (!arg_no_wtmp) {
6905 if (sd_booted() > 0)
6906 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
6907 else {
6908 r = utmp_put_shutdown();
6909 if (r < 0)
6910 log_warning("Failed to write utmp record: %s", strerror(-r));
6911 }
6912 }
6913
6914 if (arg_dry)
6915 return 0;
6916
6917 r = halt_now(arg_action);
6918 log_error("Failed to reboot: %s", strerror(-r));
6919
6920 return r;
6921 }
6922
6923 static int runlevel_main(void) {
6924 int r, runlevel, previous;
6925
6926 r = utmp_get_runlevel(&runlevel, &previous);
6927 if (r < 0) {
6928 puts("unknown");
6929 return r;
6930 }
6931
6932 printf("%c %c\n",
6933 previous <= 0 ? 'N' : previous,
6934 runlevel <= 0 ? 'N' : runlevel);
6935
6936 return 0;
6937 }
6938
6939 int main(int argc, char*argv[]) {
6940 _cleanup_bus_close_unref_ sd_bus *bus = NULL;
6941 int r;
6942
6943 setlocale(LC_ALL, "");
6944 log_parse_environment();
6945 log_open();
6946
6947 /* Explicitly not on_tty() to avoid setting cached value.
6948 * This becomes relevant for piping output which might be
6949 * ellipsized. */
6950 original_stdout_is_tty = isatty(STDOUT_FILENO);
6951
6952 r = parse_argv(argc, argv);
6953 if (r <= 0)
6954 goto finish;
6955
6956 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
6957 * let's shortcut this */
6958 if (arg_action == ACTION_RUNLEVEL) {
6959 r = runlevel_main();
6960 goto finish;
6961 }
6962
6963 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
6964 log_info("Running in chroot, ignoring request.");
6965 r = 0;
6966 goto finish;
6967 }
6968
6969 if (!avoid_bus())
6970 r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus);
6971
6972 /* systemctl_main() will print an error message for the bus
6973 * connection, but only if it needs to */
6974
6975 switch (arg_action) {
6976
6977 case ACTION_SYSTEMCTL:
6978 r = systemctl_main(bus, argc, argv, r);
6979 break;
6980
6981 case ACTION_HALT:
6982 case ACTION_POWEROFF:
6983 case ACTION_REBOOT:
6984 case ACTION_KEXEC:
6985 r = halt_main(bus);
6986 break;
6987
6988 case ACTION_RUNLEVEL2:
6989 case ACTION_RUNLEVEL3:
6990 case ACTION_RUNLEVEL4:
6991 case ACTION_RUNLEVEL5:
6992 case ACTION_RESCUE:
6993 case ACTION_EMERGENCY:
6994 case ACTION_DEFAULT:
6995 r = start_with_fallback(bus);
6996 break;
6997
6998 case ACTION_RELOAD:
6999 case ACTION_REEXEC:
7000 r = reload_with_fallback(bus);
7001 break;
7002
7003 case ACTION_CANCEL_SHUTDOWN: {
7004 _cleanup_free_ char *m = NULL;
7005
7006 if (arg_wall) {
7007 m = strv_join(arg_wall, " ");
7008 if (!m) {
7009 r = log_oom();
7010 goto finish;
7011 }
7012 }
7013
7014 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
7015 if (r < 0)
7016 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
7017 break;
7018 }
7019
7020 case ACTION_RUNLEVEL:
7021 case _ACTION_INVALID:
7022 default:
7023 assert_not_reached("Unknown action");
7024 }
7025
7026 finish:
7027 pager_close();
7028 ask_password_agent_close();
7029 polkit_agent_close();
7030
7031 strv_free(arg_types);
7032 strv_free(arg_states);
7033 strv_free(arg_properties);
7034
7035 return r < 0 ? EXIT_FAILURE : r;
7036 }