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