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