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