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