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