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