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