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