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