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