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