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