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