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