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