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