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