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