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