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