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