]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/systemctl/systemctl.c
machinectl: add new "start" verb to start a container as a service in nspawn
[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-common-errors.h"
76 #include "mkdir.h"
77 #include "dropin.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_machine(&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_machine(&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 static void warn_unit_file_changed(const char *name) {
2275 log_warning("%sWarning:%s %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
2276 ansi_highlight_red(),
2277 ansi_highlight_off(),
2278 name,
2279 arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
2280 }
2281
2282 static int unit_file_find_path(LookupPaths *lp, const char *unit_name, char **unit_path) {
2283 char **p;
2284
2285 assert(lp);
2286 assert(unit_name);
2287 assert(unit_path);
2288
2289 STRV_FOREACH(p, lp->unit_path) {
2290 _cleanup_free_ char *path;
2291
2292 path = path_join(arg_root, *p, unit_name);
2293 if (!path)
2294 return log_oom();
2295
2296 if (access(path, F_OK) == 0) {
2297 *unit_path = path;
2298 path = NULL;
2299 return 1;
2300 }
2301 }
2302
2303 return 0;
2304 }
2305
2306 static int unit_find_paths(sd_bus *bus,
2307 const char *unit_name,
2308 bool avoid_bus_cache,
2309 LookupPaths *lp,
2310 char **fragment_path,
2311 char ***dropin_paths) {
2312 int r;
2313
2314 /**
2315 * Finds where the unit is defined on disk. Returns 0 if the unit
2316 * is not found. Returns 1 if it is found, and sets
2317 * - the path to the unit in *path, if it exists on disk,
2318 * - and a strv of existing drop-ins in *dropins,
2319 * if the arg is not NULL and any dropins were found.
2320 */
2321
2322 assert(unit_name);
2323 assert(fragment_path);
2324 assert(lp);
2325
2326 if (!avoid_bus_cache && !unit_name_is_template(unit_name)) {
2327 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2328 _cleanup_free_ char *unit = NULL;
2329 _cleanup_free_ char *path = NULL;
2330 _cleanup_strv_free_ char **dropins = NULL;
2331
2332 unit = unit_dbus_path_from_name(unit_name);
2333 if (!unit)
2334 return log_oom();
2335
2336 if (need_daemon_reload(bus, unit_name) > 0)
2337 warn_unit_file_changed(unit_name);
2338
2339 r = sd_bus_get_property_string(
2340 bus,
2341 "org.freedesktop.systemd1",
2342 unit,
2343 "org.freedesktop.systemd1.Unit",
2344 "FragmentPath",
2345 &error,
2346 &path);
2347 if (r < 0)
2348 return log_error_errno(r, "Failed to get FragmentPath: %s", bus_error_message(&error, r));
2349
2350 r = sd_bus_get_property_strv(
2351 bus,
2352 "org.freedesktop.systemd1",
2353 unit,
2354 "org.freedesktop.systemd1.Unit",
2355 "DropInPaths",
2356 &error,
2357 &dropins);
2358 if (r < 0)
2359 return log_error_errno(r, "Failed to get DropInPaths: %s", bus_error_message(&error, r));
2360
2361 r = 0;
2362 if (!isempty(path)) {
2363 *fragment_path = path;
2364 path = NULL;
2365 r = 1;
2366 }
2367
2368 if (dropin_paths && !strv_isempty(dropins)) {
2369 *dropin_paths = dropins;
2370 dropins = NULL;
2371 r = 1;
2372 }
2373 } else {
2374 _cleanup_set_free_ Set *names;
2375
2376 names = set_new(NULL);
2377 if (!names)
2378 return -ENOMEM;
2379
2380 r = set_put(names, unit_name);
2381 if (r < 0)
2382 return r;
2383
2384 r = unit_file_find_path(lp, unit_name, fragment_path);
2385 if (r < 0)
2386 return r;
2387
2388 if (r == 0) {
2389 _cleanup_free_ char *template;
2390
2391 template = unit_name_template(unit_name);
2392 if (!template)
2393 return log_oom();
2394
2395 if (!streq(template, unit_name)) {
2396 r = unit_file_find_path(lp, template, fragment_path);
2397 if (r < 0)
2398 return r;
2399 }
2400 }
2401
2402 if (dropin_paths)
2403 r = unit_file_find_dropin_paths(lp->unit_path, NULL, names, dropin_paths);
2404 }
2405
2406 return r;
2407 }
2408
2409 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
2410 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2411 _cleanup_free_ char *n = NULL, *state = NULL;
2412 const char *path;
2413 int r;
2414
2415 assert(name);
2416
2417 n = unit_name_mangle(name, MANGLE_NOGLOB);
2418 if (!n)
2419 return log_oom();
2420
2421 /* We don't use unit_dbus_path_from_name() directly since we
2422 * don't want to load the unit if it isn't loaded. */
2423
2424 r = sd_bus_call_method(
2425 bus,
2426 "org.freedesktop.systemd1",
2427 "/org/freedesktop/systemd1",
2428 "org.freedesktop.systemd1.Manager",
2429 "GetUnit",
2430 NULL,
2431 &reply,
2432 "s", n);
2433 if (r < 0) {
2434 if (!quiet)
2435 puts("unknown");
2436 return 0;
2437 }
2438
2439 r = sd_bus_message_read(reply, "o", &path);
2440 if (r < 0)
2441 return bus_log_parse_error(r);
2442
2443 r = sd_bus_get_property_string(
2444 bus,
2445 "org.freedesktop.systemd1",
2446 path,
2447 "org.freedesktop.systemd1.Unit",
2448 "ActiveState",
2449 NULL,
2450 &state);
2451 if (r < 0) {
2452 if (!quiet)
2453 puts("unknown");
2454 return 0;
2455 }
2456
2457 if (!quiet)
2458 puts(state);
2459
2460 return nulstr_contains(good_states, state);
2461 }
2462
2463 static int check_triggering_units(
2464 sd_bus *bus,
2465 const char *name) {
2466
2467 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2468 _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
2469 _cleanup_strv_free_ char **triggered_by = NULL;
2470 bool print_warning_label = true;
2471 char **i;
2472 int r;
2473
2474 n = unit_name_mangle(name, MANGLE_NOGLOB);
2475 if (!n)
2476 return log_oom();
2477
2478 path = unit_dbus_path_from_name(n);
2479 if (!path)
2480 return log_oom();
2481
2482 r = sd_bus_get_property_string(
2483 bus,
2484 "org.freedesktop.systemd1",
2485 path,
2486 "org.freedesktop.systemd1.Unit",
2487 "LoadState",
2488 &error,
2489 &state);
2490 if (r < 0) {
2491 log_error("Failed to get load state of %s: %s", n, bus_error_message(&error, r));
2492 return r;
2493 }
2494
2495 if (streq(state, "masked"))
2496 return 0;
2497
2498 r = sd_bus_get_property_strv(
2499 bus,
2500 "org.freedesktop.systemd1",
2501 path,
2502 "org.freedesktop.systemd1.Unit",
2503 "TriggeredBy",
2504 &error,
2505 &triggered_by);
2506 if (r < 0) {
2507 log_error("Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
2508 return r;
2509 }
2510
2511 STRV_FOREACH(i, triggered_by) {
2512 r = check_one_unit(bus, *i, "active\0reloading\0", true);
2513 if (r < 0)
2514 return log_error_errno(r, "Failed to check unit: %m");
2515
2516 if (r == 0)
2517 continue;
2518
2519 if (print_warning_label) {
2520 log_warning("Warning: Stopping %s, but it can still be activated by:", n);
2521 print_warning_label = false;
2522 }
2523
2524 log_warning(" %s", *i);
2525 }
2526
2527 return 0;
2528 }
2529
2530 static const struct {
2531 const char *verb;
2532 const char *method;
2533 } unit_actions[] = {
2534 { "start", "StartUnit" },
2535 { "stop", "StopUnit" },
2536 { "condstop", "StopUnit" },
2537 { "reload", "ReloadUnit" },
2538 { "restart", "RestartUnit" },
2539 { "try-restart", "TryRestartUnit" },
2540 { "condrestart", "TryRestartUnit" },
2541 { "reload-or-restart", "ReloadOrRestartUnit" },
2542 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2543 { "condreload", "ReloadOrTryRestartUnit" },
2544 { "force-reload", "ReloadOrTryRestartUnit" }
2545 };
2546
2547 static const char *verb_to_method(const char *verb) {
2548 uint i;
2549
2550 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2551 if (streq_ptr(unit_actions[i].verb, verb))
2552 return unit_actions[i].method;
2553
2554 return "StartUnit";
2555 }
2556
2557 static const char *method_to_verb(const char *method) {
2558 uint i;
2559
2560 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2561 if (streq_ptr(unit_actions[i].method, method))
2562 return unit_actions[i].verb;
2563
2564 return "n/a";
2565 }
2566
2567 static int start_unit_one(
2568 sd_bus *bus,
2569 const char *method,
2570 const char *name,
2571 const char *mode,
2572 sd_bus_error *error,
2573 BusWaitForJobs *w) {
2574
2575 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2576 const char *path;
2577 int r;
2578
2579 assert(method);
2580 assert(name);
2581 assert(mode);
2582 assert(error);
2583
2584 log_debug("Calling manager for %s on %s, %s", method, name, mode);
2585
2586 r = sd_bus_message_new_method_call(
2587 bus,
2588 &m,
2589 "org.freedesktop.systemd1",
2590 "/org/freedesktop/systemd1",
2591 "org.freedesktop.systemd1.Manager",
2592 method);
2593 if (r < 0)
2594 return bus_log_create_error(r);
2595
2596 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
2597 if (r < 0)
2598 return bus_log_create_error(r);
2599
2600 r = sd_bus_message_append(m, "ss", name, mode);
2601 if (r < 0)
2602 return bus_log_create_error(r);
2603
2604 r = sd_bus_call(bus, m, 0, error, &reply);
2605 if (r < 0) {
2606 const char *verb;
2607
2608 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
2609 /* There's always a fallback possible for
2610 * legacy actions. */
2611 return -EADDRNOTAVAIL;
2612
2613 verb = method_to_verb(method);
2614
2615 log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r));
2616 return r;
2617 }
2618
2619 r = sd_bus_message_read(reply, "o", &path);
2620 if (r < 0)
2621 return bus_log_parse_error(r);
2622
2623 if (need_daemon_reload(bus, name) > 0)
2624 warn_unit_file_changed(name);
2625
2626 if (w) {
2627 log_debug("Adding %s to the set", path);
2628 r = bus_wait_for_jobs_add(w, path);
2629 if (r < 0)
2630 return log_oom();
2631 }
2632
2633 return 0;
2634 }
2635
2636 static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret) {
2637
2638 _cleanup_strv_free_ char **mangled = NULL, **globs = NULL;
2639 char **name;
2640 int r = 0, i;
2641
2642 STRV_FOREACH(name, names) {
2643 char *t;
2644
2645 if (suffix)
2646 t = unit_name_mangle_with_suffix(*name, MANGLE_GLOB, suffix);
2647 else
2648 t = unit_name_mangle(*name, MANGLE_GLOB);
2649 if (!t)
2650 return log_oom();
2651
2652 if (string_is_glob(t))
2653 r = strv_consume(&globs, t);
2654 else
2655 r = strv_consume(&mangled, t);
2656 if (r < 0)
2657 return log_oom();
2658 }
2659
2660 /* Query the manager only if any of the names are a glob, since
2661 * this is fairly expensive */
2662 if (!strv_isempty(globs)) {
2663 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2664 _cleanup_free_ UnitInfo *unit_infos = NULL;
2665
2666 if (!bus)
2667 return log_error_errno(ENOTSUP, "Unit name globbing without bus is not implemented.");
2668
2669 r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
2670 if (r < 0)
2671 return r;
2672
2673 for (i = 0; i < r; i++)
2674 if (strv_extend(&mangled, unit_infos[i].id) < 0)
2675 return log_oom();
2676 }
2677
2678 *ret = mangled;
2679 mangled = NULL; /* do not free */
2680
2681 return 0;
2682 }
2683
2684 static const struct {
2685 const char *target;
2686 const char *verb;
2687 const char *mode;
2688 } action_table[_ACTION_MAX] = {
2689 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
2690 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
2691 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
2692 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
2693 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
2694 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
2695 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
2696 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
2697 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
2698 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
2699 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
2700 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
2701 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
2702 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
2703 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
2704 };
2705
2706 static enum action verb_to_action(const char *verb) {
2707 enum action i;
2708
2709 for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
2710 if (streq_ptr(action_table[i].verb, verb))
2711 return i;
2712
2713 return _ACTION_INVALID;
2714 }
2715
2716 static int start_unit(sd_bus *bus, char **args) {
2717 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
2718 const char *method, *mode, *one_name, *suffix = NULL;
2719 _cleanup_strv_free_ char **names = NULL;
2720 char **name;
2721 int r = 0;
2722
2723 assert(bus);
2724
2725 ask_password_agent_open_if_enabled();
2726
2727 if (arg_action == ACTION_SYSTEMCTL) {
2728 enum action action;
2729 method = verb_to_method(args[0]);
2730 action = verb_to_action(args[0]);
2731
2732 if (streq(args[0], "isolate")) {
2733 mode = "isolate";
2734 suffix = ".target";
2735 } else
2736 mode = action_table[action].mode ?: arg_job_mode;
2737
2738 one_name = action_table[action].target;
2739 } else {
2740 assert(arg_action < ELEMENTSOF(action_table));
2741 assert(action_table[arg_action].target);
2742
2743 method = "StartUnit";
2744
2745 mode = action_table[arg_action].mode;
2746 one_name = action_table[arg_action].target;
2747 }
2748
2749 if (one_name)
2750 names = strv_new(one_name, NULL);
2751 else {
2752 r = expand_names(bus, args + 1, suffix, &names);
2753 if (r < 0)
2754 log_error_errno(r, "Failed to expand names: %m");
2755 }
2756
2757 if (!arg_no_block) {
2758 r = bus_wait_for_jobs_new(bus, &w);
2759 if (r < 0)
2760 return log_error_errno(r, "Could not watch jobs: %m");
2761 }
2762
2763 STRV_FOREACH(name, names) {
2764 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2765 int q;
2766
2767 q = start_unit_one(bus, method, *name, mode, &error, w);
2768 if (r >= 0 && q < 0)
2769 r = translate_bus_error_to_exit_status(q, &error);
2770 }
2771
2772 if (!arg_no_block) {
2773 int q;
2774
2775 q = bus_wait_for_jobs(w, arg_quiet);
2776 if (q < 0)
2777 return q;
2778
2779 /* When stopping units, warn if they can still be triggered by
2780 * another active unit (socket, path, timer) */
2781 if (!arg_quiet && streq(method, "StopUnit"))
2782 STRV_FOREACH(name, names)
2783 check_triggering_units(bus, *name);
2784 }
2785
2786 return r;
2787 }
2788
2789 /* Ask systemd-logind, which might grant access to unprivileged users
2790 * through PolicyKit */
2791 static int reboot_with_logind(sd_bus *bus, enum action a) {
2792 #ifdef HAVE_LOGIND
2793 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2794 const char *method;
2795 int r;
2796
2797 if (!bus)
2798 return -EIO;
2799
2800 polkit_agent_open_if_enabled();
2801
2802 switch (a) {
2803
2804 case ACTION_REBOOT:
2805 method = "Reboot";
2806 break;
2807
2808 case ACTION_POWEROFF:
2809 method = "PowerOff";
2810 break;
2811
2812 case ACTION_SUSPEND:
2813 method = "Suspend";
2814 break;
2815
2816 case ACTION_HIBERNATE:
2817 method = "Hibernate";
2818 break;
2819
2820 case ACTION_HYBRID_SLEEP:
2821 method = "HybridSleep";
2822 break;
2823
2824 default:
2825 return -EINVAL;
2826 }
2827
2828 r = sd_bus_call_method(
2829 bus,
2830 "org.freedesktop.login1",
2831 "/org/freedesktop/login1",
2832 "org.freedesktop.login1.Manager",
2833 method,
2834 &error,
2835 NULL,
2836 "b", arg_ask_password);
2837 if (r < 0)
2838 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
2839
2840 return r;
2841 #else
2842 return -ENOSYS;
2843 #endif
2844 }
2845
2846 static int check_inhibitors(sd_bus *bus, enum action a) {
2847 #ifdef HAVE_LOGIND
2848 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2849 _cleanup_strv_free_ char **sessions = NULL;
2850 const char *what, *who, *why, *mode;
2851 uint32_t uid, pid;
2852 unsigned c = 0;
2853 char **s;
2854 int r;
2855
2856 if (!bus)
2857 return 0;
2858
2859 if (arg_ignore_inhibitors || arg_force > 0)
2860 return 0;
2861
2862 if (arg_when > 0)
2863 return 0;
2864
2865 if (geteuid() == 0)
2866 return 0;
2867
2868 if (!on_tty())
2869 return 0;
2870
2871 r = sd_bus_call_method(
2872 bus,
2873 "org.freedesktop.login1",
2874 "/org/freedesktop/login1",
2875 "org.freedesktop.login1.Manager",
2876 "ListInhibitors",
2877 NULL,
2878 &reply,
2879 NULL);
2880 if (r < 0)
2881 /* If logind is not around, then there are no inhibitors... */
2882 return 0;
2883
2884 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
2885 if (r < 0)
2886 return bus_log_parse_error(r);
2887
2888 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
2889 _cleanup_free_ char *comm = NULL, *user = NULL;
2890 _cleanup_strv_free_ char **sv = NULL;
2891
2892 if (!streq(mode, "block"))
2893 continue;
2894
2895 sv = strv_split(what, ":");
2896 if (!sv)
2897 return log_oom();
2898
2899 if (!strv_contains(sv,
2900 a == ACTION_HALT ||
2901 a == ACTION_POWEROFF ||
2902 a == ACTION_REBOOT ||
2903 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2904 continue;
2905
2906 get_process_comm(pid, &comm);
2907 user = uid_to_name(uid);
2908
2909 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
2910 who, pid, strna(comm), strna(user), why);
2911
2912 c++;
2913 }
2914 if (r < 0)
2915 return bus_log_parse_error(r);
2916
2917 r = sd_bus_message_exit_container(reply);
2918 if (r < 0)
2919 return bus_log_parse_error(r);
2920
2921 /* Check for current sessions */
2922 sd_get_sessions(&sessions);
2923 STRV_FOREACH(s, sessions) {
2924 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2925
2926 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2927 continue;
2928
2929 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2930 continue;
2931
2932 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2933 continue;
2934
2935 sd_session_get_tty(*s, &tty);
2936 sd_session_get_seat(*s, &seat);
2937 sd_session_get_service(*s, &service);
2938 user = uid_to_name(uid);
2939
2940 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2941 c++;
2942 }
2943
2944 if (c <= 0)
2945 return 0;
2946
2947 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2948 action_table[a].verb);
2949
2950 return -EPERM;
2951 #else
2952 return 0;
2953 #endif
2954 }
2955
2956 static int start_special(sd_bus *bus, char **args) {
2957 enum action a;
2958 int r;
2959
2960 assert(args);
2961
2962 a = verb_to_action(args[0]);
2963
2964 r = check_inhibitors(bus, a);
2965 if (r < 0)
2966 return r;
2967
2968 if (arg_force >= 2 && geteuid() != 0) {
2969 log_error("Must be root.");
2970 return -EPERM;
2971 }
2972
2973 if (arg_force >= 2 &&
2974 (a == ACTION_HALT ||
2975 a == ACTION_POWEROFF ||
2976 a == ACTION_REBOOT))
2977 return halt_now(a);
2978
2979 if (arg_force >= 1 &&
2980 (a == ACTION_HALT ||
2981 a == ACTION_POWEROFF ||
2982 a == ACTION_REBOOT ||
2983 a == ACTION_KEXEC ||
2984 a == ACTION_EXIT))
2985 return daemon_reload(bus, args);
2986
2987 /* first try logind, to allow authentication with polkit */
2988 if (geteuid() != 0 &&
2989 (a == ACTION_POWEROFF ||
2990 a == ACTION_REBOOT ||
2991 a == ACTION_SUSPEND ||
2992 a == ACTION_HIBERNATE ||
2993 a == ACTION_HYBRID_SLEEP)) {
2994 r = reboot_with_logind(bus, a);
2995 if (r >= 0)
2996 return r;
2997 }
2998
2999 r = start_unit(bus, args);
3000 if (r == EXIT_SUCCESS)
3001 warn_wall(a);
3002
3003 return r;
3004 }
3005
3006 static int check_unit_generic(sd_bus *bus, int code, const char *good_states, char **args) {
3007 _cleanup_strv_free_ char **names = NULL;
3008 char **name;
3009 int r;
3010
3011 assert(bus);
3012 assert(args);
3013
3014 r = expand_names(bus, args, NULL, &names);
3015 if (r < 0)
3016 return log_error_errno(r, "Failed to expand names: %m");
3017
3018 STRV_FOREACH(name, names) {
3019 int state;
3020
3021 state = check_one_unit(bus, *name, good_states, arg_quiet);
3022 if (state < 0)
3023 return state;
3024 if (state == 0)
3025 r = code;
3026 }
3027
3028 return r;
3029 }
3030
3031 static int check_unit_active(sd_bus *bus, char **args) {
3032 /* According to LSB: 3, "program is not running" */
3033 return check_unit_generic(bus, 3, "active\0reloading\0", args + 1);
3034 }
3035
3036 static int check_unit_failed(sd_bus *bus, char **args) {
3037 return check_unit_generic(bus, 1, "failed\0", args + 1);
3038 }
3039
3040 static int kill_unit(sd_bus *bus, char **args) {
3041 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3042 _cleanup_strv_free_ char **names = NULL;
3043 char **name;
3044 int r, q;
3045
3046 assert(bus);
3047 assert(args);
3048
3049 if (!arg_kill_who)
3050 arg_kill_who = "all";
3051
3052 r = expand_names(bus, args + 1, NULL, &names);
3053 if (r < 0)
3054 log_error_errno(r, "Failed to expand names: %m");
3055
3056 STRV_FOREACH(name, names) {
3057 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
3058
3059 q = sd_bus_message_new_method_call(
3060 bus,
3061 &m,
3062 "org.freedesktop.systemd1",
3063 "/org/freedesktop/systemd1",
3064 "org.freedesktop.systemd1.Manager",
3065 "KillUnit");
3066 if (q < 0)
3067 return bus_log_create_error(q);
3068
3069 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
3070 if (q < 0)
3071 return bus_log_create_error(q);
3072
3073 q = sd_bus_message_append(m, "ssi", *names, arg_kill_who, arg_signal);
3074 if (q < 0)
3075 return bus_log_create_error(q);
3076
3077 q = sd_bus_call(bus, m, 0, &error, NULL);
3078 if (q < 0) {
3079 log_error("Failed to kill unit %s: %s", *names, bus_error_message(&error, q));
3080 if (r == 0)
3081 r = q;
3082 }
3083 }
3084
3085 return r;
3086 }
3087
3088 typedef struct ExecStatusInfo {
3089 char *name;
3090
3091 char *path;
3092 char **argv;
3093
3094 bool ignore;
3095
3096 usec_t start_timestamp;
3097 usec_t exit_timestamp;
3098 pid_t pid;
3099 int code;
3100 int status;
3101
3102 LIST_FIELDS(struct ExecStatusInfo, exec);
3103 } ExecStatusInfo;
3104
3105 static void exec_status_info_free(ExecStatusInfo *i) {
3106 assert(i);
3107
3108 free(i->name);
3109 free(i->path);
3110 strv_free(i->argv);
3111 free(i);
3112 }
3113
3114 static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
3115 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
3116 const char *path;
3117 uint32_t pid;
3118 int32_t code, status;
3119 int ignore, r;
3120
3121 assert(m);
3122 assert(i);
3123
3124 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii");
3125 if (r < 0)
3126 return bus_log_parse_error(r);
3127 else if (r == 0)
3128 return 0;
3129
3130 r = sd_bus_message_read(m, "s", &path);
3131 if (r < 0)
3132 return bus_log_parse_error(r);
3133
3134 i->path = strdup(path);
3135 if (!i->path)
3136 return log_oom();
3137
3138 r = sd_bus_message_read_strv(m, &i->argv);
3139 if (r < 0)
3140 return bus_log_parse_error(r);
3141
3142 r = sd_bus_message_read(m,
3143 "bttttuii",
3144 &ignore,
3145 &start_timestamp, &start_timestamp_monotonic,
3146 &exit_timestamp, &exit_timestamp_monotonic,
3147 &pid,
3148 &code, &status);
3149 if (r < 0)
3150 return bus_log_parse_error(r);
3151
3152 i->ignore = ignore;
3153 i->start_timestamp = (usec_t) start_timestamp;
3154 i->exit_timestamp = (usec_t) exit_timestamp;
3155 i->pid = (pid_t) pid;
3156 i->code = code;
3157 i->status = status;
3158
3159 r = sd_bus_message_exit_container(m);
3160 if (r < 0)
3161 return bus_log_parse_error(r);
3162
3163 return 1;
3164 }
3165
3166 typedef struct UnitStatusInfo {
3167 const char *id;
3168 const char *load_state;
3169 const char *active_state;
3170 const char *sub_state;
3171 const char *unit_file_state;
3172 const char *unit_file_preset;
3173
3174 const char *description;
3175 const char *following;
3176
3177 char **documentation;
3178
3179 const char *fragment_path;
3180 const char *source_path;
3181 const char *control_group;
3182
3183 char **dropin_paths;
3184
3185 const char *load_error;
3186 const char *result;
3187
3188 usec_t inactive_exit_timestamp;
3189 usec_t inactive_exit_timestamp_monotonic;
3190 usec_t active_enter_timestamp;
3191 usec_t active_exit_timestamp;
3192 usec_t inactive_enter_timestamp;
3193
3194 bool need_daemon_reload;
3195
3196 /* Service */
3197 pid_t main_pid;
3198 pid_t control_pid;
3199 const char *status_text;
3200 const char *pid_file;
3201 bool running:1;
3202 int status_errno;
3203
3204 usec_t start_timestamp;
3205 usec_t exit_timestamp;
3206
3207 int exit_code, exit_status;
3208
3209 usec_t condition_timestamp;
3210 bool condition_result;
3211 bool failed_condition_trigger;
3212 bool failed_condition_negate;
3213 const char *failed_condition;
3214 const char *failed_condition_parameter;
3215
3216 usec_t assert_timestamp;
3217 bool assert_result;
3218 bool failed_assert_trigger;
3219 bool failed_assert_negate;
3220 const char *failed_assert;
3221 const char *failed_assert_parameter;
3222
3223 /* Socket */
3224 unsigned n_accepted;
3225 unsigned n_connections;
3226 bool accept;
3227
3228 /* Pairs of type, path */
3229 char **listen;
3230
3231 /* Device */
3232 const char *sysfs_path;
3233
3234 /* Mount, Automount */
3235 const char *where;
3236
3237 /* Swap */
3238 const char *what;
3239
3240 LIST_HEAD(ExecStatusInfo, exec);
3241 } UnitStatusInfo;
3242
3243 static void print_status_info(
3244 UnitStatusInfo *i,
3245 bool *ellipsized) {
3246
3247 ExecStatusInfo *p;
3248 const char *active_on, *active_off, *on, *off, *ss;
3249 usec_t timestamp;
3250 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
3251 char since2[FORMAT_TIMESTAMP_MAX], *s2;
3252 const char *path;
3253 int flags =
3254 arg_all * OUTPUT_SHOW_ALL |
3255 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
3256 on_tty() * OUTPUT_COLOR |
3257 !arg_quiet * OUTPUT_WARN_CUTOFF |
3258 arg_full * OUTPUT_FULL_WIDTH;
3259 char **t, **t2;
3260
3261 assert(i);
3262
3263 /* This shows pretty information about a unit. See
3264 * print_property() for a low-level property printer */
3265
3266 if (streq_ptr(i->active_state, "failed")) {
3267 active_on = ansi_highlight_red();
3268 active_off = ansi_highlight_off();
3269 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
3270 active_on = ansi_highlight_green();
3271 active_off = ansi_highlight_off();
3272 } else
3273 active_on = active_off = "";
3274
3275 printf("%s%s%s %s", active_on, draw_special_char(DRAW_BLACK_CIRCLE), active_off, strna(i->id));
3276
3277 if (i->description && !streq_ptr(i->id, i->description))
3278 printf(" - %s", i->description);
3279
3280 printf("\n");
3281
3282 if (i->following)
3283 printf(" Follow: unit currently follows state of %s\n", i->following);
3284
3285 if (streq_ptr(i->load_state, "error")) {
3286 on = ansi_highlight_red();
3287 off = ansi_highlight_off();
3288 } else
3289 on = off = "";
3290
3291 path = i->source_path ? i->source_path : i->fragment_path;
3292
3293 if (i->load_error)
3294 printf(" Loaded: %s%s%s (Reason: %s)\n",
3295 on, strna(i->load_state), off, i->load_error);
3296 else if (path && !isempty(i->unit_file_state) && !isempty(i->unit_file_preset))
3297 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
3298 on, strna(i->load_state), off, path, i->unit_file_state, i->unit_file_preset);
3299 else if (path && !isempty(i->unit_file_state))
3300 printf(" Loaded: %s%s%s (%s; %s)\n",
3301 on, strna(i->load_state), off, path, i->unit_file_state);
3302 else if (path)
3303 printf(" Loaded: %s%s%s (%s)\n",
3304 on, strna(i->load_state), off, path);
3305 else
3306 printf(" Loaded: %s%s%s\n",
3307 on, strna(i->load_state), off);
3308
3309 if (!strv_isempty(i->dropin_paths)) {
3310 _cleanup_free_ char *dir = NULL;
3311 bool last = false;
3312 char ** dropin;
3313
3314 STRV_FOREACH(dropin, i->dropin_paths) {
3315 if (! dir || last) {
3316 printf(dir ? " " : " Drop-In: ");
3317
3318 free(dir);
3319 dir = NULL;
3320
3321 if (path_get_parent(*dropin, &dir) < 0) {
3322 log_oom();
3323 return;
3324 }
3325
3326 printf("%s\n %s", dir,
3327 draw_special_char(DRAW_TREE_RIGHT));
3328 }
3329
3330 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
3331
3332 printf("%s%s", basename(*dropin), last ? "\n" : ", ");
3333 }
3334 }
3335
3336 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
3337 if (ss)
3338 printf(" Active: %s%s (%s)%s",
3339 active_on, strna(i->active_state), ss, active_off);
3340 else
3341 printf(" Active: %s%s%s",
3342 active_on, strna(i->active_state), active_off);
3343
3344 if (!isempty(i->result) && !streq(i->result, "success"))
3345 printf(" (Result: %s)", i->result);
3346
3347 timestamp = (streq_ptr(i->active_state, "active") ||
3348 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
3349 (streq_ptr(i->active_state, "inactive") ||
3350 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
3351 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
3352 i->active_exit_timestamp;
3353
3354 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
3355 s2 = format_timestamp(since2, sizeof(since2), timestamp);
3356
3357 if (s1)
3358 printf(" since %s; %s\n", s2, s1);
3359 else if (s2)
3360 printf(" since %s\n", s2);
3361 else
3362 printf("\n");
3363
3364 if (!i->condition_result && i->condition_timestamp > 0) {
3365 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
3366 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
3367
3368 printf("Condition: start %scondition failed%s at %s%s%s\n",
3369 ansi_highlight_yellow(), ansi_highlight_off(),
3370 s2, s1 ? "; " : "", s1 ? s1 : "");
3371 if (i->failed_condition_trigger)
3372 printf(" none of the trigger conditions were met\n");
3373 else if (i->failed_condition)
3374 printf(" %s=%s%s was not met\n",
3375 i->failed_condition,
3376 i->failed_condition_negate ? "!" : "",
3377 i->failed_condition_parameter);
3378 }
3379
3380 if (!i->assert_result && i->assert_timestamp > 0) {
3381 s1 = format_timestamp_relative(since1, sizeof(since1), i->assert_timestamp);
3382 s2 = format_timestamp(since2, sizeof(since2), i->assert_timestamp);
3383
3384 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
3385 ansi_highlight_red(), ansi_highlight_off(),
3386 s2, s1 ? "; " : "", s1 ? s1 : "");
3387 if (i->failed_assert_trigger)
3388 printf(" none of the trigger assertions were met\n");
3389 else if (i->failed_assert)
3390 printf(" %s=%s%s was not met\n",
3391 i->failed_assert,
3392 i->failed_assert_negate ? "!" : "",
3393 i->failed_assert_parameter);
3394 }
3395
3396 if (i->sysfs_path)
3397 printf(" Device: %s\n", i->sysfs_path);
3398 if (i->where)
3399 printf(" Where: %s\n", i->where);
3400 if (i->what)
3401 printf(" What: %s\n", i->what);
3402
3403 STRV_FOREACH(t, i->documentation)
3404 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
3405
3406 STRV_FOREACH_PAIR(t, t2, i->listen)
3407 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
3408
3409 if (i->accept)
3410 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
3411
3412 LIST_FOREACH(exec, p, i->exec) {
3413 _cleanup_free_ char *argv = NULL;
3414 bool good;
3415
3416 /* Only show exited processes here */
3417 if (p->code == 0)
3418 continue;
3419
3420 argv = strv_join(p->argv, " ");
3421 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
3422
3423 good = is_clean_exit_lsb(p->code, p->status, NULL);
3424 if (!good) {
3425 on = ansi_highlight_red();
3426 off = ansi_highlight_off();
3427 } else
3428 on = off = "";
3429
3430 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
3431
3432 if (p->code == CLD_EXITED) {
3433 const char *c;
3434
3435 printf("status=%i", p->status);
3436
3437 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
3438 if (c)
3439 printf("/%s", c);
3440
3441 } else
3442 printf("signal=%s", signal_to_string(p->status));
3443
3444 printf(")%s\n", off);
3445
3446 if (i->main_pid == p->pid &&
3447 i->start_timestamp == p->start_timestamp &&
3448 i->exit_timestamp == p->start_timestamp)
3449 /* Let's not show this twice */
3450 i->main_pid = 0;
3451
3452 if (p->pid == i->control_pid)
3453 i->control_pid = 0;
3454 }
3455
3456 if (i->main_pid > 0 || i->control_pid > 0) {
3457 if (i->main_pid > 0) {
3458 printf(" Main PID: "PID_FMT, i->main_pid);
3459
3460 if (i->running) {
3461 _cleanup_free_ char *comm = NULL;
3462 get_process_comm(i->main_pid, &comm);
3463 if (comm)
3464 printf(" (%s)", comm);
3465 } else if (i->exit_code > 0) {
3466 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
3467
3468 if (i->exit_code == CLD_EXITED) {
3469 const char *c;
3470
3471 printf("status=%i", i->exit_status);
3472
3473 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
3474 if (c)
3475 printf("/%s", c);
3476
3477 } else
3478 printf("signal=%s", signal_to_string(i->exit_status));
3479 printf(")");
3480 }
3481
3482 if (i->control_pid > 0)
3483 printf(";");
3484 }
3485
3486 if (i->control_pid > 0) {
3487 _cleanup_free_ char *c = NULL;
3488
3489 printf(" %8s: "PID_FMT, i->main_pid ? "" : " Control", i->control_pid);
3490
3491 get_process_comm(i->control_pid, &c);
3492 if (c)
3493 printf(" (%s)", c);
3494 }
3495
3496 printf("\n");
3497 }
3498
3499 if (i->status_text)
3500 printf(" Status: \"%s\"\n", i->status_text);
3501 if (i->status_errno > 0)
3502 printf(" Error: %i (%s)\n", i->status_errno, strerror(i->status_errno));
3503
3504 if (i->control_group &&
3505 (i->main_pid > 0 || i->control_pid > 0 ||
3506 ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_MACHINE) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) {
3507 unsigned c;
3508
3509 printf(" CGroup: %s\n", i->control_group);
3510
3511 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_MACHINE) {
3512 unsigned k = 0;
3513 pid_t extra[2];
3514 static const char prefix[] = " ";
3515
3516 c = columns();
3517 if (c > sizeof(prefix) - 1)
3518 c -= sizeof(prefix) - 1;
3519 else
3520 c = 0;
3521
3522 if (i->main_pid > 0)
3523 extra[k++] = i->main_pid;
3524
3525 if (i->control_pid > 0)
3526 extra[k++] = i->control_pid;
3527
3528 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, false, extra, k, flags);
3529 }
3530 }
3531
3532 if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) {
3533 show_journal_by_unit(stdout,
3534 i->id,
3535 arg_output,
3536 0,
3537 i->inactive_exit_timestamp_monotonic,
3538 arg_lines,
3539 getuid(),
3540 flags | OUTPUT_BEGIN_NEWLINE,
3541 arg_scope == UNIT_FILE_SYSTEM,
3542 ellipsized);
3543 }
3544
3545 if (i->need_daemon_reload)
3546 warn_unit_file_changed(i->id);
3547 }
3548
3549 static void show_unit_help(UnitStatusInfo *i) {
3550 char **p;
3551
3552 assert(i);
3553
3554 if (!i->documentation) {
3555 log_info("Documentation for %s not known.", i->id);
3556 return;
3557 }
3558
3559 STRV_FOREACH(p, i->documentation)
3560 if (startswith(*p, "man:"))
3561 show_man_page(*p + 4, false);
3562 else
3563 log_info("Can't show: %s", *p);
3564 }
3565
3566 static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) {
3567 int r;
3568
3569 assert(name);
3570 assert(m);
3571 assert(i);
3572
3573 switch (contents[0]) {
3574
3575 case SD_BUS_TYPE_STRING: {
3576 const char *s;
3577
3578 r = sd_bus_message_read(m, "s", &s);
3579 if (r < 0)
3580 return bus_log_parse_error(r);
3581
3582 if (!isempty(s)) {
3583 if (streq(name, "Id"))
3584 i->id = s;
3585 else if (streq(name, "LoadState"))
3586 i->load_state = s;
3587 else if (streq(name, "ActiveState"))
3588 i->active_state = s;
3589 else if (streq(name, "SubState"))
3590 i->sub_state = s;
3591 else if (streq(name, "Description"))
3592 i->description = s;
3593 else if (streq(name, "FragmentPath"))
3594 i->fragment_path = s;
3595 else if (streq(name, "SourcePath"))
3596 i->source_path = s;
3597 #ifndef NOLEGACY
3598 else if (streq(name, "DefaultControlGroup")) {
3599 const char *e;
3600 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
3601 if (e)
3602 i->control_group = e;
3603 }
3604 #endif
3605 else if (streq(name, "ControlGroup"))
3606 i->control_group = s;
3607 else if (streq(name, "StatusText"))
3608 i->status_text = s;
3609 else if (streq(name, "PIDFile"))
3610 i->pid_file = s;
3611 else if (streq(name, "SysFSPath"))
3612 i->sysfs_path = s;
3613 else if (streq(name, "Where"))
3614 i->where = s;
3615 else if (streq(name, "What"))
3616 i->what = s;
3617 else if (streq(name, "Following"))
3618 i->following = s;
3619 else if (streq(name, "UnitFileState"))
3620 i->unit_file_state = s;
3621 else if (streq(name, "UnitFilePreset"))
3622 i->unit_file_preset = s;
3623 else if (streq(name, "Result"))
3624 i->result = s;
3625 }
3626
3627 break;
3628 }
3629
3630 case SD_BUS_TYPE_BOOLEAN: {
3631 int b;
3632
3633 r = sd_bus_message_read(m, "b", &b);
3634 if (r < 0)
3635 return bus_log_parse_error(r);
3636
3637 if (streq(name, "Accept"))
3638 i->accept = b;
3639 else if (streq(name, "NeedDaemonReload"))
3640 i->need_daemon_reload = b;
3641 else if (streq(name, "ConditionResult"))
3642 i->condition_result = b;
3643 else if (streq(name, "AssertResult"))
3644 i->assert_result = b;
3645
3646 break;
3647 }
3648
3649 case SD_BUS_TYPE_UINT32: {
3650 uint32_t u;
3651
3652 r = sd_bus_message_read(m, "u", &u);
3653 if (r < 0)
3654 return bus_log_parse_error(r);
3655
3656 if (streq(name, "MainPID")) {
3657 if (u > 0) {
3658 i->main_pid = (pid_t) u;
3659 i->running = true;
3660 }
3661 } else if (streq(name, "ControlPID"))
3662 i->control_pid = (pid_t) u;
3663 else if (streq(name, "ExecMainPID")) {
3664 if (u > 0)
3665 i->main_pid = (pid_t) u;
3666 } else if (streq(name, "NAccepted"))
3667 i->n_accepted = u;
3668 else if (streq(name, "NConnections"))
3669 i->n_connections = u;
3670
3671 break;
3672 }
3673
3674 case SD_BUS_TYPE_INT32: {
3675 int32_t j;
3676
3677 r = sd_bus_message_read(m, "i", &j);
3678 if (r < 0)
3679 return bus_log_parse_error(r);
3680
3681 if (streq(name, "ExecMainCode"))
3682 i->exit_code = (int) j;
3683 else if (streq(name, "ExecMainStatus"))
3684 i->exit_status = (int) j;
3685 else if (streq(name, "StatusErrno"))
3686 i->status_errno = (int) j;
3687
3688 break;
3689 }
3690
3691 case SD_BUS_TYPE_UINT64: {
3692 uint64_t u;
3693
3694 r = sd_bus_message_read(m, "t", &u);
3695 if (r < 0)
3696 return bus_log_parse_error(r);
3697
3698 if (streq(name, "ExecMainStartTimestamp"))
3699 i->start_timestamp = (usec_t) u;
3700 else if (streq(name, "ExecMainExitTimestamp"))
3701 i->exit_timestamp = (usec_t) u;
3702 else if (streq(name, "ActiveEnterTimestamp"))
3703 i->active_enter_timestamp = (usec_t) u;
3704 else if (streq(name, "InactiveEnterTimestamp"))
3705 i->inactive_enter_timestamp = (usec_t) u;
3706 else if (streq(name, "InactiveExitTimestamp"))
3707 i->inactive_exit_timestamp = (usec_t) u;
3708 else if (streq(name, "InactiveExitTimestampMonotonic"))
3709 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3710 else if (streq(name, "ActiveExitTimestamp"))
3711 i->active_exit_timestamp = (usec_t) u;
3712 else if (streq(name, "ConditionTimestamp"))
3713 i->condition_timestamp = (usec_t) u;
3714 else if (streq(name, "AssertTimestamp"))
3715 i->assert_timestamp = (usec_t) u;
3716
3717 break;
3718 }
3719
3720 case SD_BUS_TYPE_ARRAY:
3721
3722 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3723 _cleanup_free_ ExecStatusInfo *info = NULL;
3724
3725 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3726 if (r < 0)
3727 return bus_log_parse_error(r);
3728
3729 info = new0(ExecStatusInfo, 1);
3730 if (!info)
3731 return log_oom();
3732
3733 while ((r = exec_status_info_deserialize(m, info)) > 0) {
3734
3735 info->name = strdup(name);
3736 if (!info->name)
3737 log_oom();
3738
3739 LIST_PREPEND(exec, i->exec, info);
3740
3741 info = new0(ExecStatusInfo, 1);
3742 if (!info)
3743 log_oom();
3744 }
3745
3746 if (r < 0)
3747 return bus_log_parse_error(r);
3748
3749 r = sd_bus_message_exit_container(m);
3750 if (r < 0)
3751 return bus_log_parse_error(r);
3752
3753 return 0;
3754
3755 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3756 const char *type, *path;
3757
3758 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3759 if (r < 0)
3760 return bus_log_parse_error(r);
3761
3762 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
3763
3764 r = strv_extend(&i->listen, type);
3765 if (r < 0)
3766 return r;
3767
3768 r = strv_extend(&i->listen, path);
3769 if (r < 0)
3770 return r;
3771 }
3772 if (r < 0)
3773 return bus_log_parse_error(r);
3774
3775 r = sd_bus_message_exit_container(m);
3776 if (r < 0)
3777 return bus_log_parse_error(r);
3778
3779 return 0;
3780
3781 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "DropInPaths")) {
3782
3783 r = sd_bus_message_read_strv(m, &i->dropin_paths);
3784 if (r < 0)
3785 return bus_log_parse_error(r);
3786
3787 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Documentation")) {
3788
3789 r = sd_bus_message_read_strv(m, &i->documentation);
3790 if (r < 0)
3791 return bus_log_parse_error(r);
3792
3793 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Conditions")) {
3794 const char *cond, *param;
3795 int trigger, negate;
3796 int32_t state;
3797
3798 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3799 if (r < 0)
3800 return bus_log_parse_error(r);
3801
3802 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, &param, &state)) > 0) {
3803 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3804 if (state < 0 && (!trigger || !i->failed_condition)) {
3805 i->failed_condition = cond;
3806 i->failed_condition_trigger = trigger;
3807 i->failed_condition_negate = negate;
3808 i->failed_condition_parameter = param;
3809 }
3810 }
3811 if (r < 0)
3812 return bus_log_parse_error(r);
3813
3814 r = sd_bus_message_exit_container(m);
3815 if (r < 0)
3816 return bus_log_parse_error(r);
3817
3818 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Asserts")) {
3819 const char *cond, *param;
3820 int trigger, negate;
3821 int32_t state;
3822
3823 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3824 if (r < 0)
3825 return bus_log_parse_error(r);
3826
3827 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, &param, &state)) > 0) {
3828 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3829 if (state < 0 && (!trigger || !i->failed_assert)) {
3830 i->failed_assert = cond;
3831 i->failed_assert_trigger = trigger;
3832 i->failed_assert_negate = negate;
3833 i->failed_assert_parameter = param;
3834 }
3835 }
3836 if (r < 0)
3837 return bus_log_parse_error(r);
3838
3839 r = sd_bus_message_exit_container(m);
3840 if (r < 0)
3841 return bus_log_parse_error(r);
3842
3843 } else
3844 goto skip;
3845
3846 break;
3847
3848 case SD_BUS_TYPE_STRUCT_BEGIN:
3849
3850 if (streq(name, "LoadError")) {
3851 const char *n, *message;
3852
3853 r = sd_bus_message_read(m, "(ss)", &n, &message);
3854 if (r < 0)
3855 return bus_log_parse_error(r);
3856
3857 if (!isempty(message))
3858 i->load_error = message;
3859 } else
3860 goto skip;
3861
3862 break;
3863
3864 default:
3865 goto skip;
3866 }
3867
3868 return 0;
3869
3870 skip:
3871 r = sd_bus_message_skip(m, contents);
3872 if (r < 0)
3873 return bus_log_parse_error(r);
3874
3875 return 0;
3876 }
3877
3878 static int print_property(const char *name, sd_bus_message *m, const char *contents) {
3879 int r;
3880
3881 assert(name);
3882 assert(m);
3883
3884 /* This is a low-level property printer, see
3885 * print_status_info() for the nicer output */
3886
3887 if (arg_properties && !strv_find(arg_properties, name)) {
3888 /* skip what we didn't read */
3889 r = sd_bus_message_skip(m, contents);
3890 return r;
3891 }
3892
3893 switch (contents[0]) {
3894
3895 case SD_BUS_TYPE_STRUCT_BEGIN:
3896
3897 if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
3898 uint32_t u;
3899
3900 r = sd_bus_message_read(m, "(uo)", &u, NULL);
3901 if (r < 0)
3902 return bus_log_parse_error(r);
3903
3904 if (u > 0)
3905 printf("%s=%"PRIu32"\n", name, u);
3906 else if (arg_all)
3907 printf("%s=\n", name);
3908
3909 return 0;
3910
3911 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
3912 const char *s;
3913
3914 r = sd_bus_message_read(m, "(so)", &s, NULL);
3915 if (r < 0)
3916 return bus_log_parse_error(r);
3917
3918 if (arg_all || !isempty(s))
3919 printf("%s=%s\n", name, s);
3920
3921 return 0;
3922
3923 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
3924 const char *a = NULL, *b = NULL;
3925
3926 r = sd_bus_message_read(m, "(ss)", &a, &b);
3927 if (r < 0)
3928 return bus_log_parse_error(r);
3929
3930 if (arg_all || !isempty(a) || !isempty(b))
3931 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3932
3933 return 0;
3934 } else if (streq_ptr(name, "SystemCallFilter")) {
3935 _cleanup_strv_free_ char **l = NULL;
3936 int whitelist;
3937
3938 r = sd_bus_message_enter_container(m, 'r', "bas");
3939 if (r < 0)
3940 return bus_log_parse_error(r);
3941
3942 r = sd_bus_message_read(m, "b", &whitelist);
3943 if (r < 0)
3944 return bus_log_parse_error(r);
3945
3946 r = sd_bus_message_read_strv(m, &l);
3947 if (r < 0)
3948 return bus_log_parse_error(r);
3949
3950 r = sd_bus_message_exit_container(m);
3951 if (r < 0)
3952 return bus_log_parse_error(r);
3953
3954 if (arg_all || whitelist || !strv_isempty(l)) {
3955 bool first = true;
3956 char **i;
3957
3958 fputs(name, stdout);
3959 fputc('=', stdout);
3960
3961 if (!whitelist)
3962 fputc('~', stdout);
3963
3964 STRV_FOREACH(i, l) {
3965 if (first)
3966 first = false;
3967 else
3968 fputc(' ', stdout);
3969
3970 fputs(*i, stdout);
3971 }
3972 fputc('\n', stdout);
3973 }
3974
3975 return 0;
3976 }
3977
3978 break;
3979
3980 case SD_BUS_TYPE_ARRAY:
3981
3982 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
3983 const char *path;
3984 int ignore;
3985
3986 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)");
3987 if (r < 0)
3988 return bus_log_parse_error(r);
3989
3990 while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
3991 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3992
3993 if (r < 0)
3994 return bus_log_parse_error(r);
3995
3996 r = sd_bus_message_exit_container(m);
3997 if (r < 0)
3998 return bus_log_parse_error(r);
3999
4000 return 0;
4001
4002 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
4003 const char *type, *path;
4004
4005 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4006 if (r < 0)
4007 return bus_log_parse_error(r);
4008
4009 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
4010 printf("%s=%s\n", type, path);
4011 if (r < 0)
4012 return bus_log_parse_error(r);
4013
4014 r = sd_bus_message_exit_container(m);
4015 if (r < 0)
4016 return bus_log_parse_error(r);
4017
4018 return 0;
4019
4020 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
4021 const char *type, *path;
4022
4023 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4024 if (r < 0)
4025 return bus_log_parse_error(r);
4026
4027 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
4028 printf("Listen%s=%s\n", type, path);
4029 if (r < 0)
4030 return bus_log_parse_error(r);
4031
4032 r = sd_bus_message_exit_container(m);
4033 if (r < 0)
4034 return bus_log_parse_error(r);
4035
4036 return 0;
4037
4038 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Timers")) {
4039 const char *base;
4040 uint64_t value, next_elapse;
4041
4042 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
4043 if (r < 0)
4044 return bus_log_parse_error(r);
4045
4046 while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) {
4047 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
4048
4049 printf("%s={ value=%s ; next_elapse=%s }\n",
4050 base,
4051 format_timespan(timespan1, sizeof(timespan1), value, 0),
4052 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
4053 }
4054 if (r < 0)
4055 return bus_log_parse_error(r);
4056
4057 r = sd_bus_message_exit_container(m);
4058 if (r < 0)
4059 return bus_log_parse_error(r);
4060
4061 return 0;
4062
4063 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
4064 ExecStatusInfo info = {};
4065
4066 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
4067 if (r < 0)
4068 return bus_log_parse_error(r);
4069
4070 while ((r = exec_status_info_deserialize(m, &info)) > 0) {
4071 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
4072 _cleanup_free_ char *tt;
4073
4074 tt = strv_join(info.argv, " ");
4075
4076 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",
4077 name,
4078 strna(info.path),
4079 strna(tt),
4080 yes_no(info.ignore),
4081 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
4082 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
4083 info.pid,
4084 sigchld_code_to_string(info.code),
4085 info.status,
4086 info.code == CLD_EXITED ? "" : "/",
4087 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
4088
4089 free(info.path);
4090 strv_free(info.argv);
4091 zero(info);
4092 }
4093
4094 r = sd_bus_message_exit_container(m);
4095 if (r < 0)
4096 return bus_log_parse_error(r);
4097
4098 return 0;
4099
4100 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
4101 const char *path, *rwm;
4102
4103 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4104 if (r < 0)
4105 return bus_log_parse_error(r);
4106
4107 while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
4108 printf("%s=%s %s\n", name, strna(path), strna(rwm));
4109 if (r < 0)
4110 return bus_log_parse_error(r);
4111
4112 r = sd_bus_message_exit_container(m);
4113 if (r < 0)
4114 return bus_log_parse_error(r);
4115
4116 return 0;
4117
4118 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "BlockIODeviceWeight")) {
4119 const char *path;
4120 uint64_t weight;
4121
4122 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4123 if (r < 0)
4124 return bus_log_parse_error(r);
4125
4126 while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
4127 printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
4128 if (r < 0)
4129 return bus_log_parse_error(r);
4130
4131 r = sd_bus_message_exit_container(m);
4132 if (r < 0)
4133 return bus_log_parse_error(r);
4134
4135 return 0;
4136
4137 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
4138 const char *path;
4139 uint64_t bandwidth;
4140
4141 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4142 if (r < 0)
4143 return bus_log_parse_error(r);
4144
4145 while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
4146 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
4147 if (r < 0)
4148 return bus_log_parse_error(r);
4149
4150 r = sd_bus_message_exit_container(m);
4151 if (r < 0)
4152 return bus_log_parse_error(r);
4153
4154 return 0;
4155 }
4156
4157 break;
4158 }
4159
4160 r = bus_print_property(name, m, arg_all);
4161 if (r < 0)
4162 return bus_log_parse_error(r);
4163
4164 if (r == 0) {
4165 r = sd_bus_message_skip(m, contents);
4166 if (r < 0)
4167 return bus_log_parse_error(r);
4168
4169 if (arg_all)
4170 printf("%s=[unprintable]\n", name);
4171 }
4172
4173 return 0;
4174 }
4175
4176 static int show_one(
4177 const char *verb,
4178 sd_bus *bus,
4179 const char *path,
4180 bool show_properties,
4181 bool *new_line,
4182 bool *ellipsized) {
4183
4184 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4185 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4186 UnitStatusInfo info = {};
4187 ExecStatusInfo *p;
4188 int r;
4189
4190 assert(path);
4191 assert(new_line);
4192
4193 log_debug("Showing one %s", path);
4194
4195 r = sd_bus_call_method(
4196 bus,
4197 "org.freedesktop.systemd1",
4198 path,
4199 "org.freedesktop.DBus.Properties",
4200 "GetAll",
4201 &error,
4202 &reply,
4203 "s", "");
4204 if (r < 0) {
4205 log_error("Failed to get properties: %s", bus_error_message(&error, r));
4206 return r;
4207 }
4208
4209 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
4210 if (r < 0)
4211 return bus_log_parse_error(r);
4212
4213 if (*new_line)
4214 printf("\n");
4215
4216 *new_line = true;
4217
4218 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
4219 const char *name, *contents;
4220
4221 r = sd_bus_message_read(reply, "s", &name);
4222 if (r < 0)
4223 return bus_log_parse_error(r);
4224
4225 r = sd_bus_message_peek_type(reply, NULL, &contents);
4226 if (r < 0)
4227 return bus_log_parse_error(r);
4228
4229 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
4230 if (r < 0)
4231 return bus_log_parse_error(r);
4232
4233 if (show_properties)
4234 r = print_property(name, reply, contents);
4235 else
4236 r = status_property(name, reply, &info, contents);
4237 if (r < 0)
4238 return r;
4239
4240 r = sd_bus_message_exit_container(reply);
4241 if (r < 0)
4242 return bus_log_parse_error(r);
4243
4244 r = sd_bus_message_exit_container(reply);
4245 if (r < 0)
4246 return bus_log_parse_error(r);
4247 }
4248 if (r < 0)
4249 return bus_log_parse_error(r);
4250
4251 r = sd_bus_message_exit_container(reply);
4252 if (r < 0)
4253 return bus_log_parse_error(r);
4254
4255 r = 0;
4256
4257 if (!show_properties) {
4258 if (streq(verb, "help"))
4259 show_unit_help(&info);
4260 else
4261 print_status_info(&info, ellipsized);
4262 }
4263
4264 strv_free(info.documentation);
4265 strv_free(info.dropin_paths);
4266 strv_free(info.listen);
4267
4268 if (!streq_ptr(info.active_state, "active") &&
4269 !streq_ptr(info.active_state, "reloading") &&
4270 streq(verb, "status")) {
4271 /* According to LSB: "program not running" */
4272 /* 0: program is running or service is OK
4273 * 1: program is dead and /run PID file exists
4274 * 2: program is dead and /run/lock lock file exists
4275 * 3: program is not running
4276 * 4: program or service status is unknown
4277 */
4278 if (info.pid_file && access(info.pid_file, F_OK) == 0)
4279 r = 1;
4280 else
4281 r = 3;
4282 }
4283
4284 while ((p = info.exec)) {
4285 LIST_REMOVE(exec, info.exec, p);
4286 exec_status_info_free(p);
4287 }
4288
4289 return r;
4290 }
4291
4292 static int get_unit_dbus_path_by_pid(
4293 sd_bus *bus,
4294 uint32_t pid,
4295 char **unit) {
4296
4297 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4298 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4299 char *u;
4300 int r;
4301
4302 r = sd_bus_call_method(
4303 bus,
4304 "org.freedesktop.systemd1",
4305 "/org/freedesktop/systemd1",
4306 "org.freedesktop.systemd1.Manager",
4307 "GetUnitByPID",
4308 &error,
4309 &reply,
4310 "u", pid);
4311 if (r < 0) {
4312 log_error("Failed to get unit for PID "PID_FMT": %s", pid, bus_error_message(&error, r));
4313 return r;
4314 }
4315
4316 r = sd_bus_message_read(reply, "o", &u);
4317 if (r < 0)
4318 return bus_log_parse_error(r);
4319
4320 u = strdup(u);
4321 if (!u)
4322 return log_oom();
4323
4324 *unit = u;
4325 return 0;
4326 }
4327
4328 static int show_all(
4329 const char* verb,
4330 sd_bus *bus,
4331 bool show_properties,
4332 bool *new_line,
4333 bool *ellipsized) {
4334
4335 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4336 _cleanup_free_ UnitInfo *unit_infos = NULL;
4337 const UnitInfo *u;
4338 unsigned c;
4339 int r, ret = 0;
4340
4341 r = get_unit_list(bus, NULL, NULL, &unit_infos, 0, &reply);
4342 if (r < 0)
4343 return r;
4344
4345 pager_open_if_enabled();
4346
4347 c = (unsigned) r;
4348
4349 qsort_safe(unit_infos, c, sizeof(UnitInfo), compare_unit_info);
4350
4351 for (u = unit_infos; u < unit_infos + c; u++) {
4352 _cleanup_free_ char *p = NULL;
4353
4354 p = unit_dbus_path_from_name(u->id);
4355 if (!p)
4356 return log_oom();
4357
4358 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
4359 if (r < 0)
4360 return r;
4361 else if (r > 0 && ret == 0)
4362 ret = r;
4363 }
4364
4365 return ret;
4366 }
4367
4368 static int show_system_status(sd_bus *bus) {
4369 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
4370 _cleanup_free_ char *hn = NULL;
4371 struct machine_info mi = {};
4372 const char *on, *off;
4373 int r;
4374
4375 hn = gethostname_malloc();
4376 if (!hn)
4377 return log_oom();
4378
4379 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &mi);
4380 if (r < 0)
4381 return log_error_errno(r, "Failed to read server status: %m");
4382
4383 if (streq_ptr(mi.state, "degraded")) {
4384 on = ansi_highlight_red();
4385 off = ansi_highlight_off();
4386 } else if (!streq_ptr(mi.state, "running")) {
4387 on = ansi_highlight_yellow();
4388 off = ansi_highlight_off();
4389 } else
4390 on = off = "";
4391
4392 printf("%s%s%s %s\n", on, draw_special_char(DRAW_BLACK_CIRCLE), off, arg_host ? arg_host : hn);
4393
4394 printf(" State: %s%s%s\n",
4395 on, strna(mi.state), off);
4396
4397 printf(" Jobs: %u queued\n", mi.n_jobs);
4398 printf(" Failed: %u units\n", mi.n_failed_units);
4399
4400 printf(" Since: %s; %s\n",
4401 format_timestamp(since2, sizeof(since2), mi.timestamp),
4402 format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
4403
4404 printf(" CGroup: %s\n", mi.control_group ?: "/");
4405 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_MACHINE) {
4406 int flags =
4407 arg_all * OUTPUT_SHOW_ALL |
4408 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
4409 on_tty() * OUTPUT_COLOR |
4410 !arg_quiet * OUTPUT_WARN_CUTOFF |
4411 arg_full * OUTPUT_FULL_WIDTH;
4412
4413 static const char prefix[] = " ";
4414 unsigned c;
4415
4416 c = columns();
4417 if (c > sizeof(prefix) - 1)
4418 c -= sizeof(prefix) - 1;
4419 else
4420 c = 0;
4421
4422 show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, flags);
4423 }
4424
4425 free(mi.state);
4426 free(mi.control_group);
4427
4428 return 0;
4429 }
4430
4431 static int show(sd_bus *bus, char **args) {
4432 bool show_properties, show_status, new_line = false;
4433 bool ellipsized = false;
4434 int r, ret = 0;
4435
4436 assert(bus);
4437 assert(args);
4438
4439 show_properties = streq(args[0], "show");
4440 show_status = streq(args[0], "status");
4441
4442 if (show_properties)
4443 pager_open_if_enabled();
4444
4445 /* If no argument is specified inspect the manager itself */
4446
4447 if (show_properties && strv_length(args) <= 1)
4448 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
4449
4450 if (show_status && strv_length(args) <= 1) {
4451
4452 pager_open_if_enabled();
4453 show_system_status(bus);
4454 new_line = true;
4455
4456 if (arg_all)
4457 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
4458 } else {
4459 _cleanup_free_ char **patterns = NULL;
4460 char **name;
4461
4462 STRV_FOREACH(name, args + 1) {
4463 _cleanup_free_ char *unit = NULL;
4464 uint32_t id;
4465
4466 if (safe_atou32(*name, &id) < 0) {
4467 if (strv_push(&patterns, *name) < 0)
4468 return log_oom();
4469
4470 continue;
4471 } else if (show_properties) {
4472 /* Interpret as job id */
4473 if (asprintf(&unit, "/org/freedesktop/systemd1/job/%u", id) < 0)
4474 return log_oom();
4475
4476 } else {
4477 /* Interpret as PID */
4478 r = get_unit_dbus_path_by_pid(bus, id, &unit);
4479 if (r < 0) {
4480 ret = r;
4481 continue;
4482 }
4483 }
4484
4485 r = show_one(args[0], bus, unit, show_properties,
4486 &new_line, &ellipsized);
4487 if (r < 0)
4488 return r;
4489 else if (r > 0 && ret == 0)
4490 ret = r;
4491 }
4492
4493 if (!strv_isempty(patterns)) {
4494 _cleanup_strv_free_ char **names = NULL;
4495
4496 r = expand_names(bus, patterns, NULL, &names);
4497 if (r < 0)
4498 log_error_errno(r, "Failed to expand names: %m");
4499
4500 STRV_FOREACH(name, names) {
4501 _cleanup_free_ char *unit;
4502
4503 unit = unit_dbus_path_from_name(*name);
4504 if (!unit)
4505 return log_oom();
4506
4507 r = show_one(args[0], bus, unit, show_properties,
4508 &new_line, &ellipsized);
4509 if (r < 0)
4510 return r;
4511 else if (r > 0 && ret == 0)
4512 ret = r;
4513 }
4514 }
4515 }
4516
4517 if (ellipsized && !arg_quiet)
4518 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4519
4520 return ret;
4521 }
4522
4523 static int init_home_and_lookup_paths(char **user_home, char **user_runtime, LookupPaths *lp) {
4524 int r;
4525
4526 assert(user_home);
4527 assert(user_runtime);
4528 assert(lp);
4529
4530 if (arg_scope == UNIT_FILE_USER) {
4531 r = user_config_home(user_home);
4532 if (r < 0)
4533 return log_error_errno(r, "Failed to query XDG_CONFIG_HOME: %m");
4534 else if (r == 0)
4535 return log_error_errno(ENOTDIR, "Cannot find units: $XDG_CONFIG_HOME and $HOME are not set.");
4536
4537 r = user_runtime_dir(user_runtime);
4538 if (r < 0)
4539 return log_error_errno(r, "Failed to query XDG_CONFIG_HOME: %m");
4540 else if (r == 0)
4541 return log_error_errno(ENOTDIR, "Cannot find units: $XDG_RUNTIME_DIR is not set.");
4542 }
4543
4544 r = lookup_paths_init(lp,
4545 arg_scope == UNIT_FILE_SYSTEM ? SYSTEMD_SYSTEM : SYSTEMD_USER,
4546 arg_scope == UNIT_FILE_USER,
4547 arg_root,
4548 NULL, NULL, NULL);
4549 if (r < 0)
4550 return log_error_errno(r, "Failed to lookup unit lookup paths: %m");
4551
4552 return 0;
4553 }
4554
4555 static int cat(sd_bus *bus, char **args) {
4556 _cleanup_free_ char *user_home = NULL;
4557 _cleanup_free_ char *user_runtime = NULL;
4558 _cleanup_lookup_paths_free_ LookupPaths lp = {};
4559 _cleanup_strv_free_ char **names = NULL;
4560 char **name;
4561 bool first = true, avoid_bus_cache;
4562 int r = 0;
4563
4564 assert(args);
4565
4566 r = init_home_and_lookup_paths(&user_home, &user_runtime, &lp);
4567 if (r < 0)
4568 return r;
4569
4570 r = expand_names(bus, args + 1, NULL, &names);
4571 if (r < 0)
4572 log_error_errno(r, "Failed to expand names: %m");
4573
4574 avoid_bus_cache = !bus || avoid_bus();
4575
4576 pager_open_if_enabled();
4577
4578 STRV_FOREACH(name, names) {
4579 _cleanup_free_ char *fragment_path = NULL;
4580 _cleanup_strv_free_ char **dropin_paths = NULL;
4581 char **path;
4582
4583 r = unit_find_paths(bus, *name, avoid_bus_cache, &lp, &fragment_path, &dropin_paths);
4584 if (r < 0)
4585 return r;
4586 else if (r == 0) {
4587 log_warning("Unit %s does not have any files on disk", *name);
4588 continue;
4589 }
4590
4591 if (first)
4592 first = false;
4593 else
4594 puts("");
4595
4596 if (fragment_path) {
4597 printf("%s# %s%s\n",
4598 ansi_highlight_blue(),
4599 fragment_path,
4600 ansi_highlight_off());
4601 fflush(stdout);
4602
4603 r = copy_file_fd(fragment_path, STDOUT_FILENO, false);
4604 if (r < 0) {
4605 log_warning_errno(r, "Failed to cat %s: %m", fragment_path);
4606 continue;
4607 }
4608 }
4609
4610 STRV_FOREACH(path, dropin_paths) {
4611 printf("%s%s# %s%s\n",
4612 isempty(fragment_path) && path == dropin_paths ? "" : "\n",
4613 ansi_highlight_blue(),
4614 *path,
4615 ansi_highlight_off());
4616 fflush(stdout);
4617
4618 r = copy_file_fd(*path, STDOUT_FILENO, false);
4619 if (r < 0) {
4620 log_warning_errno(r, "Failed to cat %s: %m", *path);
4621 continue;
4622 }
4623 }
4624 }
4625
4626 return r < 0 ? r : 0;
4627 }
4628
4629 static int set_property(sd_bus *bus, char **args) {
4630 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4631 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4632 _cleanup_free_ char *n = NULL;
4633 char **i;
4634 int r;
4635
4636 r = sd_bus_message_new_method_call(
4637 bus,
4638 &m,
4639 "org.freedesktop.systemd1",
4640 "/org/freedesktop/systemd1",
4641 "org.freedesktop.systemd1.Manager",
4642 "SetUnitProperties");
4643 if (r < 0)
4644 return bus_log_create_error(r);
4645
4646 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4647 if (r < 0)
4648 return bus_log_create_error(r);
4649
4650 n = unit_name_mangle(args[1], MANGLE_NOGLOB);
4651 if (!n)
4652 return log_oom();
4653
4654 r = sd_bus_message_append(m, "sb", n, arg_runtime);
4655 if (r < 0)
4656 return bus_log_create_error(r);
4657
4658 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)");
4659 if (r < 0)
4660 return bus_log_create_error(r);
4661
4662 STRV_FOREACH(i, args + 2) {
4663 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
4664 if (r < 0)
4665 return bus_log_create_error(r);
4666
4667 r = bus_append_unit_property_assignment(m, *i);
4668 if (r < 0)
4669 return r;
4670
4671 r = sd_bus_message_close_container(m);
4672 if (r < 0)
4673 return bus_log_create_error(r);
4674 }
4675
4676 r = sd_bus_message_close_container(m);
4677 if (r < 0)
4678 return bus_log_create_error(r);
4679
4680 r = sd_bus_call(bus, m, 0, &error, NULL);
4681 if (r < 0) {
4682 log_error("Failed to set unit properties on %s: %s", n, bus_error_message(&error, r));
4683 return r;
4684 }
4685
4686 return 0;
4687 }
4688
4689 static int snapshot(sd_bus *bus, char **args) {
4690 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4691 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
4692 _cleanup_free_ char *n = NULL, *id = NULL;
4693 const char *path;
4694 int r;
4695
4696 if (strv_length(args) > 1)
4697 n = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".snapshot");
4698 else
4699 n = strdup("");
4700 if (!n)
4701 return log_oom();
4702
4703 r = sd_bus_message_new_method_call(
4704 bus,
4705 &m,
4706 "org.freedesktop.systemd1",
4707 "/org/freedesktop/systemd1",
4708 "org.freedesktop.systemd1.Manager",
4709 "CreateSnapshot");
4710 if (r < 0)
4711 return bus_log_create_error(r);
4712
4713 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4714 if (r < 0)
4715 return bus_log_create_error(r);
4716
4717 r = sd_bus_message_append(m, "sb", n, false);
4718 if (r < 0)
4719 return bus_log_create_error(r);
4720
4721 r = sd_bus_call(bus, m, 0, &error, &reply);
4722 if (r < 0) {
4723 log_error("Failed to create snapshot: %s", bus_error_message(&error, r));
4724 return r;
4725 }
4726
4727 r = sd_bus_message_read(reply, "o", &path);
4728 if (r < 0)
4729 return bus_log_parse_error(r);
4730
4731 r = sd_bus_get_property_string(
4732 bus,
4733 "org.freedesktop.systemd1",
4734 path,
4735 "org.freedesktop.systemd1.Unit",
4736 "Id",
4737 &error,
4738 &id);
4739 if (r < 0) {
4740 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error, r));
4741 return r;
4742 }
4743
4744 if (!arg_quiet)
4745 puts(id);
4746
4747 return 0;
4748 }
4749
4750 static int delete_snapshot(sd_bus *bus, char **args) {
4751 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4752 _cleanup_strv_free_ char **names = NULL;
4753 char **name;
4754 int r;
4755
4756 assert(args);
4757
4758 r = expand_names(bus, args + 1, ".snapshot", &names);
4759 if (r < 0)
4760 log_error_errno(r, "Failed to expand names: %m");
4761
4762 STRV_FOREACH(name, names) {
4763 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4764 int q;
4765
4766 q = sd_bus_message_new_method_call(
4767 bus,
4768 &m,
4769 "org.freedesktop.systemd1",
4770 "/org/freedesktop/systemd1",
4771 "org.freedesktop.systemd1.Manager",
4772 "RemoveSnapshot");
4773 if (q < 0)
4774 return bus_log_create_error(q);
4775
4776 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4777 if (q < 0)
4778 return bus_log_create_error(q);
4779
4780 q = sd_bus_message_append(m, "s", *name);
4781 if (q < 0)
4782 return bus_log_create_error(q);
4783
4784 q = sd_bus_call(bus, m, 0, &error, NULL);
4785 if (q < 0) {
4786 log_error("Failed to remove snapshot %s: %s", *name, bus_error_message(&error, q));
4787 if (r == 0)
4788 r = q;
4789 }
4790 }
4791
4792 return r;
4793 }
4794
4795 static int daemon_reload(sd_bus *bus, char **args) {
4796 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4797 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4798 const char *method;
4799 int r;
4800
4801 if (arg_action == ACTION_RELOAD)
4802 method = "Reload";
4803 else if (arg_action == ACTION_REEXEC)
4804 method = "Reexecute";
4805 else {
4806 assert(arg_action == ACTION_SYSTEMCTL);
4807
4808 method =
4809 streq(args[0], "clear-jobs") ||
4810 streq(args[0], "cancel") ? "ClearJobs" :
4811 streq(args[0], "daemon-reexec") ? "Reexecute" :
4812 streq(args[0], "reset-failed") ? "ResetFailed" :
4813 streq(args[0], "halt") ? "Halt" :
4814 streq(args[0], "poweroff") ? "PowerOff" :
4815 streq(args[0], "reboot") ? "Reboot" :
4816 streq(args[0], "kexec") ? "KExec" :
4817 streq(args[0], "exit") ? "Exit" :
4818 /* "daemon-reload" */ "Reload";
4819 }
4820
4821 r = sd_bus_message_new_method_call(
4822 bus,
4823 &m,
4824 "org.freedesktop.systemd1",
4825 "/org/freedesktop/systemd1",
4826 "org.freedesktop.systemd1.Manager",
4827 method);
4828 if (r < 0)
4829 return bus_log_create_error(r);
4830
4831 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4832 if (r < 0)
4833 return bus_log_create_error(r);
4834
4835 r = sd_bus_call(bus, m, 0, &error, NULL);
4836 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
4837 /* There's always a fallback possible for
4838 * legacy actions. */
4839 r = -EADDRNOTAVAIL;
4840 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
4841 /* On reexecution, we expect a disconnect, not a
4842 * reply */
4843 r = 0;
4844 else if (r < 0)
4845 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
4846
4847 return r < 0 ? r : 0;
4848 }
4849
4850 static int reset_failed(sd_bus *bus, char **args) {
4851 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4852 _cleanup_strv_free_ char **names = NULL;
4853 char **name;
4854 int r, q;
4855
4856 if (strv_length(args) <= 1)
4857 return daemon_reload(bus, args);
4858
4859 r = expand_names(bus, args + 1, NULL, &names);
4860 if (r < 0)
4861 log_error_errno(r, "Failed to expand names: %m");
4862
4863 STRV_FOREACH(name, names) {
4864 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4865
4866 q = sd_bus_message_new_method_call(
4867 bus,
4868 &m,
4869 "org.freedesktop.systemd1",
4870 "/org/freedesktop/systemd1",
4871 "org.freedesktop.systemd1.Manager",
4872 "ResetFailedUnit");
4873 if (q < 0)
4874 return bus_log_create_error(q);
4875
4876 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4877 if (q < 0)
4878 return bus_log_create_error(q);
4879
4880 q = sd_bus_message_append(m, "s", *name);
4881 if (q < 0)
4882 return bus_log_create_error(q);
4883
4884 q = sd_bus_call(bus, m, 0, &error, NULL);
4885 if (q < 0) {
4886 log_error("Failed to reset failed state of unit %s: %s", *name, bus_error_message(&error, q));
4887 if (r == 0)
4888 r = q;
4889 }
4890 }
4891
4892 return r;
4893 }
4894
4895 static int show_environment(sd_bus *bus, char **args) {
4896 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4897 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4898 const char *text;
4899 int r;
4900
4901 pager_open_if_enabled();
4902
4903 r = sd_bus_get_property(
4904 bus,
4905 "org.freedesktop.systemd1",
4906 "/org/freedesktop/systemd1",
4907 "org.freedesktop.systemd1.Manager",
4908 "Environment",
4909 &error,
4910 &reply,
4911 "as");
4912 if (r < 0) {
4913 log_error("Failed to get environment: %s", bus_error_message(&error, r));
4914 return r;
4915 }
4916
4917 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
4918 if (r < 0)
4919 return bus_log_parse_error(r);
4920
4921 while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0)
4922 puts(text);
4923 if (r < 0)
4924 return bus_log_parse_error(r);
4925
4926 r = sd_bus_message_exit_container(reply);
4927 if (r < 0)
4928 return bus_log_parse_error(r);
4929
4930 return 0;
4931 }
4932
4933 static int switch_root(sd_bus *bus, char **args) {
4934 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4935 _cleanup_free_ char *cmdline_init = NULL;
4936 const char *root, *init;
4937 unsigned l;
4938 int r;
4939
4940 l = strv_length(args);
4941 if (l < 2 || l > 3) {
4942 log_error("Wrong number of arguments.");
4943 return -EINVAL;
4944 }
4945
4946 root = args[1];
4947
4948 if (l >= 3)
4949 init = args[2];
4950 else {
4951 r = parse_env_file("/proc/cmdline", WHITESPACE,
4952 "init", &cmdline_init,
4953 NULL);
4954 if (r < 0)
4955 log_debug_errno(r, "Failed to parse /proc/cmdline: %m");
4956
4957 init = cmdline_init;
4958 }
4959
4960 if (isempty(init))
4961 init = NULL;
4962
4963 if (init) {
4964 const char *root_systemd_path = NULL, *root_init_path = NULL;
4965
4966 root_systemd_path = strappenda(root, "/" SYSTEMD_BINARY_PATH);
4967 root_init_path = strappenda(root, "/", init);
4968
4969 /* If the passed init is actually the same as the
4970 * systemd binary, then let's suppress it. */
4971 if (files_same(root_init_path, root_systemd_path) > 0)
4972 init = NULL;
4973 }
4974
4975 log_debug("Switching root - root: %s; init: %s", root, strna(init));
4976
4977 r = sd_bus_call_method(
4978 bus,
4979 "org.freedesktop.systemd1",
4980 "/org/freedesktop/systemd1",
4981 "org.freedesktop.systemd1.Manager",
4982 "SwitchRoot",
4983 &error,
4984 NULL,
4985 "ss", root, init);
4986 if (r < 0) {
4987 log_error("Failed to switch root: %s", bus_error_message(&error, r));
4988 return r;
4989 }
4990
4991 return 0;
4992 }
4993
4994 static int set_environment(sd_bus *bus, char **args) {
4995 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4996 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4997 const char *method;
4998 int r;
4999
5000 assert(bus);
5001 assert(args);
5002
5003 method = streq(args[0], "set-environment")
5004 ? "SetEnvironment"
5005 : "UnsetEnvironment";
5006
5007 r = sd_bus_message_new_method_call(
5008 bus,
5009 &m,
5010 "org.freedesktop.systemd1",
5011 "/org/freedesktop/systemd1",
5012 "org.freedesktop.systemd1.Manager",
5013 method);
5014 if (r < 0)
5015 return bus_log_create_error(r);
5016
5017 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5018 if (r < 0)
5019 return bus_log_create_error(r);
5020
5021 r = sd_bus_message_append_strv(m, args + 1);
5022 if (r < 0)
5023 return bus_log_create_error(r);
5024
5025 r = sd_bus_call(bus, m, 0, &error, NULL);
5026 if (r < 0) {
5027 log_error("Failed to set environment: %s", bus_error_message(&error, r));
5028 return r;
5029 }
5030
5031 return 0;
5032 }
5033
5034 static int import_environment(sd_bus *bus, char **args) {
5035 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5036 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
5037 int r;
5038
5039 assert(bus);
5040 assert(args);
5041
5042 r = sd_bus_message_new_method_call(
5043 bus,
5044 &m,
5045 "org.freedesktop.systemd1",
5046 "/org/freedesktop/systemd1",
5047 "org.freedesktop.systemd1.Manager",
5048 "SetEnvironment");
5049 if (r < 0)
5050 return bus_log_create_error(r);
5051
5052 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5053 if (r < 0)
5054 return bus_log_create_error(r);
5055
5056 if (strv_isempty(args + 1))
5057 r = sd_bus_message_append_strv(m, environ);
5058 else {
5059 char **a, **b;
5060
5061 r = sd_bus_message_open_container(m, 'a', "s");
5062 if (r < 0)
5063 return bus_log_create_error(r);
5064
5065 STRV_FOREACH(a, args + 1) {
5066
5067 if (!env_name_is_valid(*a)) {
5068 log_error("Not a valid environment variable name: %s", *a);
5069 return -EINVAL;
5070 }
5071
5072 STRV_FOREACH(b, environ) {
5073 const char *eq;
5074
5075 eq = startswith(*b, *a);
5076 if (eq && *eq == '=') {
5077
5078 r = sd_bus_message_append(m, "s", *b);
5079 if (r < 0)
5080 return bus_log_create_error(r);
5081
5082 break;
5083 }
5084 }
5085 }
5086
5087 r = sd_bus_message_close_container(m);
5088 }
5089 if (r < 0)
5090 return bus_log_create_error(r);
5091
5092 r = sd_bus_call(bus, m, 0, &error, NULL);
5093 if (r < 0) {
5094 log_error("Failed to import environment: %s", bus_error_message(&error, r));
5095 return r;
5096 }
5097
5098 return 0;
5099 }
5100
5101 static int enable_sysv_units(const char *verb, char **args) {
5102 int r = 0;
5103
5104 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
5105 unsigned f = 0;
5106 _cleanup_lookup_paths_free_ LookupPaths paths = {};
5107
5108 if (arg_scope != UNIT_FILE_SYSTEM)
5109 return 0;
5110
5111 if (!streq(verb, "enable") &&
5112 !streq(verb, "disable") &&
5113 !streq(verb, "is-enabled"))
5114 return 0;
5115
5116 /* Processes all SysV units, and reshuffles the array so that
5117 * afterwards only the native units remain */
5118
5119 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, arg_root, NULL, NULL, NULL);
5120 if (r < 0)
5121 return r;
5122
5123 r = 0;
5124 while (args[f]) {
5125 const char *name;
5126 _cleanup_free_ char *p = NULL, *q = NULL, *l = NULL;
5127 bool found_native = false, found_sysv;
5128 unsigned c = 1;
5129 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
5130 char **k;
5131 int j;
5132 pid_t pid;
5133 siginfo_t status;
5134
5135 name = args[f++];
5136
5137 if (!endswith(name, ".service"))
5138 continue;
5139
5140 if (path_is_absolute(name))
5141 continue;
5142
5143 STRV_FOREACH(k, paths.unit_path) {
5144 _cleanup_free_ char *path = NULL;
5145
5146 path = path_join(arg_root, *k, name);
5147 if (!path)
5148 return log_oom();
5149
5150 found_native = access(path, F_OK) >= 0;
5151 if (found_native)
5152 break;
5153 }
5154
5155 if (found_native)
5156 continue;
5157
5158 p = path_join(arg_root, SYSTEM_SYSVINIT_PATH, name);
5159 if (!p)
5160 return log_oom();
5161
5162 p[strlen(p) - strlen(".service")] = 0;
5163 found_sysv = access(p, F_OK) >= 0;
5164 if (!found_sysv)
5165 continue;
5166
5167 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
5168
5169 if (!isempty(arg_root))
5170 argv[c++] = q = strappend("--root=", arg_root);
5171
5172 argv[c++] = basename(p);
5173 argv[c++] =
5174 streq(verb, "enable") ? "on" :
5175 streq(verb, "disable") ? "off" : "--level=5";
5176 argv[c] = NULL;
5177
5178 l = strv_join((char**)argv, " ");
5179 if (!l)
5180 return log_oom();
5181
5182 log_info("Executing %s", l);
5183
5184 pid = fork();
5185 if (pid < 0)
5186 return log_error_errno(errno, "Failed to fork: %m");
5187 else if (pid == 0) {
5188 /* Child */
5189
5190 execv(argv[0], (char**) argv);
5191 _exit(EXIT_FAILURE);
5192 }
5193
5194 j = wait_for_terminate(pid, &status);
5195 if (j < 0) {
5196 log_error_errno(r, "Failed to wait for child: %m");
5197 return j;
5198 }
5199
5200 if (status.si_code == CLD_EXITED) {
5201 if (streq(verb, "is-enabled")) {
5202 if (status.si_status == 0) {
5203 if (!arg_quiet)
5204 puts("enabled");
5205 r = 1;
5206 } else {
5207 if (!arg_quiet)
5208 puts("disabled");
5209 }
5210
5211 } else if (status.si_status != 0)
5212 return -EINVAL;
5213 } else
5214 return -EPROTO;
5215
5216 /* Remove this entry, so that we don't try enabling it as native unit */
5217 assert(f > 0 && streq(args[f-1], name));
5218 assert_se(strv_remove(args + f - 1, name));
5219 }
5220
5221 #endif
5222 return r;
5223 }
5224
5225 static int mangle_names(char **original_names, char ***mangled_names) {
5226 char **i, **l, **name;
5227
5228 l = new(char*, strv_length(original_names) + 1);
5229 if (!l)
5230 return log_oom();
5231
5232 i = l;
5233 STRV_FOREACH(name, original_names) {
5234
5235 /* When enabling units qualified path names are OK,
5236 * too, hence allow them explicitly. */
5237
5238 if (is_path(*name))
5239 *i = strdup(*name);
5240 else
5241 *i = unit_name_mangle(*name, MANGLE_NOGLOB);
5242
5243 if (!*i) {
5244 strv_free(l);
5245 return log_oom();
5246 }
5247
5248 i++;
5249 }
5250
5251 *i = NULL;
5252 *mangled_names = l;
5253
5254 return 0;
5255 }
5256
5257 static int enable_unit(sd_bus *bus, char **args) {
5258 _cleanup_strv_free_ char **names = NULL;
5259 const char *verb = args[0];
5260 UnitFileChange *changes = NULL;
5261 unsigned n_changes = 0;
5262 int carries_install_info = -1;
5263 int r;
5264
5265 if (!args[1])
5266 return 0;
5267
5268 r = mangle_names(args+1, &names);
5269 if (r < 0)
5270 return r;
5271
5272 r = enable_sysv_units(verb, names);
5273 if (r < 0)
5274 return r;
5275
5276 /* If the operation was fully executed by the SysV compat,
5277 * let's finish early */
5278 if (strv_isempty(names))
5279 return 0;
5280
5281 if (!bus || avoid_bus()) {
5282 if (streq(verb, "enable")) {
5283 r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5284 carries_install_info = r;
5285 } else if (streq(verb, "disable"))
5286 r = unit_file_disable(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5287 else if (streq(verb, "reenable")) {
5288 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5289 carries_install_info = r;
5290 } else if (streq(verb, "link"))
5291 r = unit_file_link(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5292 else if (streq(verb, "preset")) {
5293 r = unit_file_preset(arg_scope, arg_runtime, arg_root, names, arg_preset_mode, arg_force, &changes, &n_changes);
5294 carries_install_info = r;
5295 } else if (streq(verb, "mask"))
5296 r = unit_file_mask(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5297 else if (streq(verb, "unmask"))
5298 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5299 else
5300 assert_not_reached("Unknown verb");
5301
5302 if (r < 0) {
5303 log_error_errno(r, "Operation failed: %m");
5304 goto finish;
5305 }
5306
5307 if (!arg_quiet)
5308 dump_unit_file_changes(changes, n_changes);
5309
5310 r = 0;
5311 } else {
5312 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5313 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5314 int expect_carries_install_info = false;
5315 bool send_force = true, send_preset_mode = false;
5316 const char *method;
5317
5318 if (streq(verb, "enable")) {
5319 method = "EnableUnitFiles";
5320 expect_carries_install_info = true;
5321 } else if (streq(verb, "disable")) {
5322 method = "DisableUnitFiles";
5323 send_force = false;
5324 } else if (streq(verb, "reenable")) {
5325 method = "ReenableUnitFiles";
5326 expect_carries_install_info = true;
5327 } else if (streq(verb, "link"))
5328 method = "LinkUnitFiles";
5329 else if (streq(verb, "preset")) {
5330
5331 if (arg_preset_mode != UNIT_FILE_PRESET_FULL) {
5332 method = "PresetUnitFilesWithMode";
5333 send_preset_mode = true;
5334 } else
5335 method = "PresetUnitFiles";
5336
5337 expect_carries_install_info = true;
5338 } else if (streq(verb, "mask"))
5339 method = "MaskUnitFiles";
5340 else if (streq(verb, "unmask")) {
5341 method = "UnmaskUnitFiles";
5342 send_force = false;
5343 } else
5344 assert_not_reached("Unknown verb");
5345
5346 r = sd_bus_message_new_method_call(
5347 bus,
5348 &m,
5349 "org.freedesktop.systemd1",
5350 "/org/freedesktop/systemd1",
5351 "org.freedesktop.systemd1.Manager",
5352 method);
5353 if (r < 0)
5354 return bus_log_create_error(r);
5355
5356 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5357 if (r < 0)
5358 return bus_log_create_error(r);
5359
5360 r = sd_bus_message_append_strv(m, names);
5361 if (r < 0)
5362 return bus_log_create_error(r);
5363
5364 if (send_preset_mode) {
5365 r = sd_bus_message_append(m, "s", unit_file_preset_mode_to_string(arg_preset_mode));
5366 if (r < 0)
5367 return bus_log_create_error(r);
5368 }
5369
5370 r = sd_bus_message_append(m, "b", arg_runtime);
5371 if (r < 0)
5372 return bus_log_create_error(r);
5373
5374 if (send_force) {
5375 r = sd_bus_message_append(m, "b", arg_force);
5376 if (r < 0)
5377 return bus_log_create_error(r);
5378 }
5379
5380 r = sd_bus_call(bus, m, 0, &error, &reply);
5381 if (r < 0) {
5382 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5383 return r;
5384 }
5385
5386 if (expect_carries_install_info) {
5387 r = sd_bus_message_read(reply, "b", &carries_install_info);
5388 if (r < 0)
5389 return bus_log_parse_error(r);
5390 }
5391
5392 r = deserialize_and_dump_unit_file_changes(reply);
5393 if (r < 0)
5394 return r;
5395
5396 /* Try to reload if enabled */
5397 if (!arg_no_reload)
5398 r = daemon_reload(bus, args);
5399 else
5400 r = 0;
5401 }
5402
5403 if (carries_install_info == 0)
5404 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5405 "using systemctl.\n"
5406 "Possible reasons for having this kind of units are:\n"
5407 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5408 " .wants/ or .requires/ directory.\n"
5409 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5410 " a requirement dependency on it.\n"
5411 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5412 " D-Bus, udev, scripted systemctl call, ...).\n");
5413
5414 finish:
5415 unit_file_changes_free(changes, n_changes);
5416
5417 return r;
5418 }
5419
5420 static int add_dependency(sd_bus *bus, char **args) {
5421 _cleanup_strv_free_ char **names = NULL;
5422 _cleanup_free_ char *target = NULL;
5423 const char *verb = args[0];
5424 UnitDependency dep;
5425 int r = 0;
5426
5427 if (!args[1])
5428 return 0;
5429
5430 target = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
5431 if (!target)
5432 return log_oom();
5433
5434 r = mangle_names(args+2, &names);
5435 if (r < 0)
5436 return r;
5437
5438 if (streq(verb, "add-wants"))
5439 dep = UNIT_WANTS;
5440 else if (streq(verb, "add-requires"))
5441 dep = UNIT_REQUIRES;
5442 else
5443 assert_not_reached("Unknown verb");
5444
5445 if (!bus || avoid_bus()) {
5446 UnitFileChange *changes = NULL;
5447 unsigned n_changes = 0;
5448
5449 r = unit_file_add_dependency(arg_scope, arg_runtime, arg_root, names, target, dep, arg_force, &changes, &n_changes);
5450
5451 if (r < 0)
5452 return log_error_errno(r, "Can't add dependency: %m");
5453
5454 if (!arg_quiet)
5455 dump_unit_file_changes(changes, n_changes);
5456
5457 unit_file_changes_free(changes, n_changes);
5458
5459 } else {
5460 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5461 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5462
5463 r = sd_bus_message_new_method_call(
5464 bus,
5465 &m,
5466 "org.freedesktop.systemd1",
5467 "/org/freedesktop/systemd1",
5468 "org.freedesktop.systemd1.Manager",
5469 "AddDependencyUnitFiles");
5470 if (r < 0)
5471 return bus_log_create_error(r);
5472
5473 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5474 if (r < 0)
5475 return bus_log_create_error(r);
5476
5477 r = sd_bus_message_append_strv(m, names);
5478 if (r < 0)
5479 return bus_log_create_error(r);
5480
5481 r = sd_bus_message_append(m, "ssbb", target, unit_dependency_to_string(dep), arg_runtime, arg_force);
5482 if (r < 0)
5483 return bus_log_create_error(r);
5484
5485 r = sd_bus_call(bus, m, 0, &error, &reply);
5486 if (r < 0) {
5487 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5488 return r;
5489 }
5490
5491 r = deserialize_and_dump_unit_file_changes(reply);
5492 if (r < 0)
5493 return r;
5494
5495 if (!arg_no_reload)
5496 r = daemon_reload(bus, args);
5497 else
5498 r = 0;
5499 }
5500
5501 return r;
5502 }
5503
5504 static int preset_all(sd_bus *bus, char **args) {
5505 UnitFileChange *changes = NULL;
5506 unsigned n_changes = 0;
5507 int r;
5508
5509 if (!bus || avoid_bus()) {
5510
5511 r = unit_file_preset_all(arg_scope, arg_runtime, arg_root, arg_preset_mode, arg_force, &changes, &n_changes);
5512 if (r < 0) {
5513 log_error_errno(r, "Operation failed: %m");
5514 goto finish;
5515 }
5516
5517 if (!arg_quiet)
5518 dump_unit_file_changes(changes, n_changes);
5519
5520 r = 0;
5521
5522 } else {
5523 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
5524 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5525
5526 r = sd_bus_message_new_method_call(
5527 bus,
5528 &m,
5529 "org.freedesktop.systemd1",
5530 "/org/freedesktop/systemd1",
5531 "org.freedesktop.systemd1.Manager",
5532 "PresetAllUnitFiles");
5533 if (r < 0)
5534 return bus_log_create_error(r);
5535
5536 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5537 if (r < 0)
5538 return bus_log_create_error(r);
5539
5540 r = sd_bus_message_append(
5541 m,
5542 "sbb",
5543 unit_file_preset_mode_to_string(arg_preset_mode),
5544 arg_runtime,
5545 arg_force);
5546 if (r < 0)
5547 return bus_log_create_error(r);
5548
5549 r = sd_bus_call(bus, m, 0, &error, &reply);
5550 if (r < 0) {
5551 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5552 return r;
5553 }
5554
5555 r = deserialize_and_dump_unit_file_changes(reply);
5556 if (r < 0)
5557 return r;
5558
5559 if (!arg_no_reload)
5560 r = daemon_reload(bus, args);
5561 else
5562 r = 0;
5563 }
5564
5565 finish:
5566 unit_file_changes_free(changes, n_changes);
5567
5568 return r;
5569 }
5570
5571 static int unit_is_enabled(sd_bus *bus, char **args) {
5572
5573 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5574 _cleanup_strv_free_ char **names = NULL;
5575 bool enabled;
5576 char **name;
5577 int r;
5578
5579 r = mangle_names(args+1, &names);
5580 if (r < 0)
5581 return r;
5582
5583 r = enable_sysv_units(args[0], names);
5584 if (r < 0)
5585 return r;
5586
5587 enabled = r > 0;
5588
5589 if (!bus || avoid_bus()) {
5590
5591 STRV_FOREACH(name, names) {
5592 UnitFileState state;
5593
5594 state = unit_file_get_state(arg_scope, arg_root, *name);
5595 if (state < 0)
5596 return log_error_errno(state, "Failed to get unit file state for %s: %m", *name);
5597
5598 if (state == UNIT_FILE_ENABLED ||
5599 state == UNIT_FILE_ENABLED_RUNTIME ||
5600 state == UNIT_FILE_STATIC ||
5601 state == UNIT_FILE_INDIRECT)
5602 enabled = true;
5603
5604 if (!arg_quiet)
5605 puts(unit_file_state_to_string(state));
5606 }
5607
5608 } else {
5609 STRV_FOREACH(name, names) {
5610 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
5611 const char *s;
5612
5613 r = sd_bus_call_method(
5614 bus,
5615 "org.freedesktop.systemd1",
5616 "/org/freedesktop/systemd1",
5617 "org.freedesktop.systemd1.Manager",
5618 "GetUnitFileState",
5619 &error,
5620 &reply,
5621 "s", *name);
5622 if (r < 0) {
5623 log_error("Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
5624 return r;
5625 }
5626
5627 r = sd_bus_message_read(reply, "s", &s);
5628 if (r < 0)
5629 return bus_log_parse_error(r);
5630
5631 if (STR_IN_SET(s, "enabled", "enabled-runtime", "static", "indirect"))
5632 enabled = true;
5633
5634 if (!arg_quiet)
5635 puts(s);
5636 }
5637 }
5638
5639 return !enabled;
5640 }
5641
5642 static int is_system_running(sd_bus *bus, char **args) {
5643 _cleanup_free_ char *state = NULL;
5644 int r;
5645
5646 r = sd_bus_get_property_string(
5647 bus,
5648 "org.freedesktop.systemd1",
5649 "/org/freedesktop/systemd1",
5650 "org.freedesktop.systemd1.Manager",
5651 "SystemState",
5652 NULL,
5653 &state);
5654 if (r < 0) {
5655 if (!arg_quiet)
5656 puts("unknown");
5657 return 0;
5658 }
5659
5660 if (!arg_quiet)
5661 puts(state);
5662
5663 return streq(state, "running") ? EXIT_SUCCESS : EXIT_FAILURE;
5664 }
5665
5666 static int create_edit_temp_file(const char *new_path, const char *original_path, char **ret_tmp_fn) {
5667 char *t;
5668 int r;
5669
5670 assert(new_path);
5671 assert(original_path);
5672 assert(ret_tmp_fn);
5673
5674 r = tempfn_random(new_path, &t);
5675 if (r < 0)
5676 return log_error_errno(r, "Failed to determine temporary filename for %s: %m", new_path);
5677
5678 r = mkdir_parents(new_path, 0755);
5679 if (r < 0) {
5680 log_error_errno(r, "Failed to create directories for %s: %m", new_path);
5681 free(t);
5682 return r;
5683 }
5684
5685 r = copy_file(original_path, t, 0, 0644);
5686 if (r == -ENOENT) {
5687 r = touch(t);
5688 if (r < 0) {
5689 log_error_errno(r, "Failed to create temporary file %s: %m", t);
5690 free(t);
5691 return r;
5692 }
5693 } else if (r < 0) {
5694 log_error_errno(r, "Failed to copy %s to %s: %m", original_path, t);
5695 free(t);
5696 return r;
5697 }
5698
5699 *ret_tmp_fn = t;
5700
5701 return 0;
5702 }
5703
5704 static int get_file_to_edit(const char *name, const char *user_home, const char *user_runtime, char **ret_path) {
5705 _cleanup_free_ char *path = NULL, *path2 = NULL, *run = NULL;
5706
5707 switch (arg_scope) {
5708 case UNIT_FILE_SYSTEM:
5709 path = path_join(arg_root, SYSTEM_CONFIG_UNIT_PATH, name);
5710 if (arg_runtime)
5711 run = path_join(arg_root, "/run/systemd/system/", name);
5712 break;
5713 case UNIT_FILE_GLOBAL:
5714 path = path_join(arg_root, USER_CONFIG_UNIT_PATH, name);
5715 if (arg_runtime)
5716 run = path_join(arg_root, "/run/systemd/user/", name);
5717 break;
5718 case UNIT_FILE_USER:
5719 assert(user_home);
5720 assert(user_runtime);
5721
5722 path = path_join(arg_root, user_home, name);
5723 if (arg_runtime) {
5724 path2 = path_join(arg_root, USER_CONFIG_UNIT_PATH, name);
5725 if (!path2)
5726 return log_oom();
5727 run = path_join(arg_root, user_runtime, name);
5728 }
5729 break;
5730 default:
5731 assert_not_reached("Invalid scope");
5732 }
5733 if (!path || (arg_runtime && !run))
5734 return log_oom();
5735
5736 if (arg_runtime) {
5737 if (access(path, F_OK) >= 0)
5738 return log_error_errno(EEXIST, "Refusing to create \"%s\" because it would be overriden by \"%s\" anyway.",
5739 run, path);
5740 if (path2 && access(path2, F_OK) >= 0)
5741 return log_error_errno(EEXIST, "Refusing to create \"%s\" because it would be overriden by \"%s\" anyway.",
5742 run, path2);
5743 *ret_path = run;
5744 run = NULL;
5745 } else {
5746 *ret_path = path;
5747 path = NULL;
5748 }
5749
5750 return 0;
5751 }
5752
5753
5754 static int unit_file_create_dropin(const char *unit_name, const char *user_home, const char *user_runtime, char **ret_new_path, char **ret_tmp_path) {
5755 char *tmp_new_path, *ending;
5756 char *tmp_tmp_path;
5757 int r;
5758
5759 assert(unit_name);
5760 assert(ret_new_path);
5761 assert(ret_tmp_path);
5762
5763 ending = strappenda(unit_name, ".d/override.conf");
5764 r = get_file_to_edit(ending, user_home, user_runtime, &tmp_new_path);
5765 if (r < 0)
5766 return r;
5767
5768 r = create_edit_temp_file(tmp_new_path, tmp_new_path, &tmp_tmp_path);
5769 if (r < 0) {
5770 free(tmp_new_path);
5771 return r;
5772 }
5773
5774 *ret_new_path = tmp_new_path;
5775 *ret_tmp_path = tmp_tmp_path;
5776
5777 return 0;
5778 }
5779
5780 static int unit_file_create_copy(const char *unit_name,
5781 const char *fragment_path,
5782 const char *user_home,
5783 const char *user_runtime,
5784 char **ret_new_path,
5785 char **ret_tmp_path) {
5786 char *tmp_new_path;
5787 char *tmp_tmp_path;
5788 int r;
5789
5790 assert(fragment_path);
5791 assert(unit_name);
5792 assert(ret_new_path);
5793 assert(ret_tmp_path);
5794
5795 r = get_file_to_edit(unit_name, user_home, user_runtime, &tmp_new_path);
5796 if (r < 0)
5797 return r;
5798
5799 if (!path_equal(fragment_path, tmp_new_path) && access(tmp_new_path, F_OK) == 0) {
5800 char response;
5801
5802 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);
5803 if (r < 0) {
5804 free(tmp_new_path);
5805 return r;
5806 }
5807 if (response != 'y') {
5808 log_warning("%s ignored", unit_name);
5809 free(tmp_new_path);
5810 return -1;
5811 }
5812 }
5813
5814 r = create_edit_temp_file(tmp_new_path, fragment_path, &tmp_tmp_path);
5815 if (r < 0) {
5816 log_error_errno(r, "Failed to create temporary file for %s: %m", tmp_new_path);
5817 free(tmp_new_path);
5818 return r;
5819 }
5820
5821 *ret_new_path = tmp_new_path;
5822 *ret_tmp_path = tmp_tmp_path;
5823
5824 return 0;
5825 }
5826
5827 static int run_editor(char **paths) {
5828 pid_t pid;
5829 int r;
5830
5831 assert(paths);
5832
5833 pid = fork();
5834 if (pid < 0) {
5835 log_error_errno(errno, "Failed to fork: %m");
5836 return -errno;
5837 }
5838
5839 if (pid == 0) {
5840 const char **args;
5841 char **backup_editors = STRV_MAKE("nano", "vim", "vi");
5842 char *editor;
5843 char **tmp_path, **original_path, **p;
5844 unsigned i = 1;
5845 size_t argc;
5846
5847 argc = strv_length(paths)/2 + 1;
5848 args = newa(const char*, argc + 1);
5849
5850 args[0] = NULL;
5851 STRV_FOREACH_PAIR(original_path, tmp_path, paths) {
5852 args[i] = *tmp_path;
5853 i++;
5854 }
5855 args[argc] = NULL;
5856
5857 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
5858 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
5859 * we try to execute well known editors
5860 */
5861 editor = getenv("SYSTEMD_EDITOR");
5862 if (!editor)
5863 editor = getenv("EDITOR");
5864 if (!editor)
5865 editor = getenv("VISUAL");
5866
5867 if (!isempty(editor)) {
5868 args[0] = editor;
5869 execvp(editor, (char* const*) args);
5870 }
5871
5872 STRV_FOREACH(p, backup_editors) {
5873 args[0] = *p;
5874 execvp(*p, (char* const*) args);
5875 /* We do not fail if the editor doesn't exist
5876 * because we want to try each one of them before
5877 * failing.
5878 */
5879 if (errno != ENOENT) {
5880 log_error("Failed to execute %s: %m", editor);
5881 _exit(EXIT_FAILURE);
5882 }
5883 }
5884
5885 log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR or $EDITOR or $VISUAL.");
5886 _exit(EXIT_FAILURE);
5887 }
5888
5889 r = wait_for_terminate_and_warn("editor", pid, true);
5890 if (r < 0)
5891 return log_error_errno(r, "Failed to wait for child: %m");
5892
5893 return r;
5894 }
5895
5896 static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) {
5897 _cleanup_free_ char *user_home = NULL;
5898 _cleanup_free_ char *user_runtime = NULL;
5899 _cleanup_lookup_paths_free_ LookupPaths lp = {};
5900 bool avoid_bus_cache;
5901 char **name;
5902 int r;
5903
5904 assert(names);
5905 assert(paths);
5906
5907 r = init_home_and_lookup_paths(&user_home, &user_runtime, &lp);
5908 if (r < 0)
5909 return r;
5910
5911 avoid_bus_cache = !bus || avoid_bus();
5912
5913 STRV_FOREACH(name, names) {
5914 _cleanup_free_ char *path = NULL;
5915 char *new_path, *tmp_path;
5916
5917 r = unit_find_paths(bus, *name, avoid_bus_cache, &lp, &path, NULL);
5918 if (r < 0)
5919 return r;
5920 else if (r == 0 || !path)
5921 // FIXME: support units with path==NULL (no FragmentPath)
5922 return log_error_errno(ENOENT, "Unit %s not found, cannot edit.", *name);
5923
5924 if (arg_full)
5925 r = unit_file_create_copy(*name, path, user_home, user_runtime, &new_path, &tmp_path);
5926 else
5927 r = unit_file_create_dropin(*name, user_home, user_runtime, &new_path, &tmp_path);
5928 if (r < 0)
5929 return r;
5930
5931 r = strv_push_pair(paths, new_path, tmp_path);
5932 if (r < 0)
5933 return log_oom();
5934 }
5935
5936 return 0;
5937 }
5938
5939 static int edit(sd_bus *bus, char **args) {
5940 _cleanup_strv_free_ char **names = NULL;
5941 _cleanup_strv_free_ char **paths = NULL;
5942 char **original, **tmp;
5943 int r;
5944
5945 assert(args);
5946
5947 if (!on_tty()) {
5948 log_error("Cannot edit units if we are not on a tty");
5949 return -EINVAL;
5950 }
5951
5952 if (arg_transport != BUS_TRANSPORT_LOCAL) {
5953 log_error("Cannot remotely edit units");
5954 return -EINVAL;
5955 }
5956
5957 r = expand_names(bus, args + 1, NULL, &names);
5958 if (r < 0)
5959 return log_error_errno(r, "Failed to expand names: %m");
5960
5961 if (!names) {
5962 log_error("No unit name found by expanding names");
5963 return -ENOENT;
5964 }
5965
5966 r = find_paths_to_edit(bus, names, &paths);
5967 if (r < 0)
5968 return r;
5969
5970 if (strv_isempty(paths)) {
5971 log_error("Cannot find any units to edit");
5972 return -ENOENT;
5973 }
5974
5975 r = run_editor(paths);
5976 if (r < 0)
5977 goto end;
5978
5979 STRV_FOREACH_PAIR(original, tmp, paths) {
5980 /* If the temporary file is empty we ignore it.
5981 * It's useful if the user wants to cancel its modification
5982 */
5983 if (null_or_empty_path(*tmp)) {
5984 log_warning("Edition of %s canceled: temporary file empty", *original);
5985 continue;
5986 }
5987 r = rename(*tmp, *original);
5988 if (r < 0) {
5989 r = log_error_errno(errno, "Failed to rename %s to %s: %m", *tmp, *original);
5990 goto end;
5991 }
5992 }
5993
5994 if (!arg_no_reload && bus && !avoid_bus())
5995 r = daemon_reload(bus, args);
5996
5997 end:
5998 STRV_FOREACH_PAIR(original, tmp, paths)
5999 unlink_noerrno(*tmp);
6000
6001 return r;
6002 }
6003
6004 static void systemctl_help(void) {
6005
6006 pager_open_if_enabled();
6007
6008 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
6009 "Query or send control commands to the systemd manager.\n\n"
6010 " -h --help Show this help\n"
6011 " --version Show package version\n"
6012 " --system Connect to system manager\n"
6013 " --user Connect to user service manager\n"
6014 " -H --host=[USER@]HOST\n"
6015 " Operate on remote host\n"
6016 " -M --machine=CONTAINER\n"
6017 " Operate on local container\n"
6018 " -t --type=TYPE List only units of a particular type\n"
6019 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
6020 " -p --property=NAME Show only properties by this name\n"
6021 " -a --all Show all loaded units/properties, including dead/empty\n"
6022 " ones. To list all units installed on the system, use\n"
6023 " the 'list-unit-files' command instead.\n"
6024 " -l --full Don't ellipsize unit names on output\n"
6025 " -r --recursive Show unit list of host and local containers\n"
6026 " --reverse Show reverse dependencies with 'list-dependencies'\n"
6027 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
6028 " queueing a new job\n"
6029 " --show-types When showing sockets, explicitly show their type\n"
6030 " -i --ignore-inhibitors\n"
6031 " When shutting down or sleeping, ignore inhibitors\n"
6032 " --kill-who=WHO Who to send signal to\n"
6033 " -s --signal=SIGNAL Which signal to send\n"
6034 " -q --quiet Suppress output\n"
6035 " --no-block Do not wait until operation finished\n"
6036 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6037 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
6038 " configuration\n"
6039 " --no-legend Do not print a legend (column headers and hints)\n"
6040 " --no-pager Do not pipe output into a pager\n"
6041 " --no-ask-password\n"
6042 " Do not ask for system passwords\n"
6043 " --global Enable/disable unit files globally\n"
6044 " --runtime Enable unit files only temporarily until next reboot\n"
6045 " -f --force When enabling unit files, override existing symlinks\n"
6046 " When shutting down, execute action immediately\n"
6047 " --preset-mode= Specifies whether fully apply presets, or only enable,\n"
6048 " or only disable\n"
6049 " --root=PATH Enable unit files in the specified root directory\n"
6050 " -n --lines=INTEGER Number of journal entries to show\n"
6051 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
6052 " verbose, export, json, json-pretty, json-sse, cat)\n"
6053 " --plain Print unit dependencies as a list instead of a tree\n\n"
6054 "Unit Commands:\n"
6055 " list-units [PATTERN...] List loaded units\n"
6056 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
6057 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
6058 " start NAME... Start (activate) one or more units\n"
6059 " stop NAME... Stop (deactivate) one or more units\n"
6060 " reload NAME... Reload one or more units\n"
6061 " restart NAME... Start or restart one or more units\n"
6062 " try-restart NAME... Restart one or more units if active\n"
6063 " reload-or-restart NAME... Reload one or more units if possible,\n"
6064 " otherwise start or restart\n"
6065 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
6066 " otherwise restart if active\n"
6067 " isolate NAME Start one unit and stop all others\n"
6068 " kill NAME... Send signal to processes of a unit\n"
6069 " is-active PATTERN... Check whether units are active\n"
6070 " is-failed PATTERN... Check whether units are failed\n"
6071 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
6072 " show [PATTERN...|JOB...] Show properties of one or more\n"
6073 " units/jobs or the manager\n"
6074 " cat PATTERN... Show files and drop-ins of one or more units\n"
6075 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
6076 " help PATTERN...|PID... Show manual for one or more units\n"
6077 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
6078 " units\n"
6079 " list-dependencies [NAME] Recursively show units which are required\n"
6080 " or wanted by this unit or by which this\n"
6081 " unit is required or wanted\n\n"
6082 "Unit File Commands:\n"
6083 " list-unit-files [PATTERN...] List installed unit files\n"
6084 " enable NAME... Enable one or more unit files\n"
6085 " disable NAME... Disable one or more unit files\n"
6086 " reenable NAME... Reenable one or more unit files\n"
6087 " preset NAME... Enable/disable one or more unit files\n"
6088 " based on preset configuration\n"
6089 " preset-all Enable/disable all unit files based on\n"
6090 " preset configuration\n"
6091 " is-enabled NAME... Check whether unit files are enabled\n\n"
6092 " mask NAME... Mask one or more units\n"
6093 " unmask NAME... Unmask one or more units\n"
6094 " link PATH... Link one or more units files into\n"
6095 " the search path\n"
6096 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
6097 " on specified one or more units\n"
6098 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
6099 " on specified one or more units\n"
6100 " get-default Get the name of the default target\n"
6101 " set-default NAME Set the default target\n"
6102 " edit NAME... Edit one or more unit files\n"
6103 "\n"
6104 "Machine Commands:\n"
6105 " list-machines [PATTERN...] List local containers and host\n\n"
6106 "Job Commands:\n"
6107 " list-jobs [PATTERN...] List jobs\n"
6108 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
6109 "Snapshot Commands:\n"
6110 " snapshot [NAME] Create a snapshot\n"
6111 " delete NAME... Remove one or more snapshots\n\n"
6112 "Environment Commands:\n"
6113 " show-environment Dump environment\n"
6114 " set-environment NAME=VALUE... Set one or more environment variables\n"
6115 " unset-environment NAME... Unset one or more environment variables\n"
6116 " import-environment NAME... Import all, one or more environment variables\n\n"
6117 "Manager Lifecycle Commands:\n"
6118 " daemon-reload Reload systemd manager configuration\n"
6119 " daemon-reexec Reexecute systemd manager\n\n"
6120 "System Commands:\n"
6121 " is-system-running Check whether system is fully running\n"
6122 " default Enter system default mode\n"
6123 " rescue Enter system rescue mode\n"
6124 " emergency Enter system emergency mode\n"
6125 " halt Shut down and halt the system\n"
6126 " poweroff Shut down and power-off the system\n"
6127 " reboot [ARG] Shut down and reboot the system\n"
6128 " kexec Shut down and reboot the system with kexec\n"
6129 " exit Request user instance exit\n"
6130 " switch-root ROOT [INIT] Change to a different root file system\n"
6131 " suspend Suspend the system\n"
6132 " hibernate Hibernate the system\n"
6133 " hybrid-sleep Hibernate and suspend the system\n",
6134 program_invocation_short_name);
6135 }
6136
6137 static void halt_help(void) {
6138 printf("%s [OPTIONS...]%s\n\n"
6139 "%s the system.\n\n"
6140 " --help Show this help\n"
6141 " --halt Halt the machine\n"
6142 " -p --poweroff Switch off the machine\n"
6143 " --reboot Reboot the machine\n"
6144 " -f --force Force immediate halt/power-off/reboot\n"
6145 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
6146 " -d --no-wtmp Don't write wtmp record\n"
6147 " --no-wall Don't send wall message before halt/power-off/reboot\n",
6148 program_invocation_short_name,
6149 arg_action == ACTION_REBOOT ? " [ARG]" : "",
6150 arg_action == ACTION_REBOOT ? "Reboot" :
6151 arg_action == ACTION_POWEROFF ? "Power off" :
6152 "Halt");
6153 }
6154
6155 static void shutdown_help(void) {
6156 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
6157 "Shut down the system.\n\n"
6158 " --help Show this help\n"
6159 " -H --halt Halt the machine\n"
6160 " -P --poweroff Power-off the machine\n"
6161 " -r --reboot Reboot the machine\n"
6162 " -h Equivalent to --poweroff, overridden by --halt\n"
6163 " -k Don't halt/power-off/reboot, just send warnings\n"
6164 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6165 " -c Cancel a pending shutdown\n",
6166 program_invocation_short_name);
6167 }
6168
6169 static void telinit_help(void) {
6170 printf("%s [OPTIONS...] {COMMAND}\n\n"
6171 "Send control commands to the init daemon.\n\n"
6172 " --help Show this help\n"
6173 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
6174 "Commands:\n"
6175 " 0 Power-off the machine\n"
6176 " 6 Reboot the machine\n"
6177 " 2, 3, 4, 5 Start runlevelX.target unit\n"
6178 " 1, s, S Enter rescue mode\n"
6179 " q, Q Reload init daemon configuration\n"
6180 " u, U Reexecute init daemon\n",
6181 program_invocation_short_name);
6182 }
6183
6184 static void runlevel_help(void) {
6185 printf("%s [OPTIONS...]\n\n"
6186 "Prints the previous and current runlevel of the init system.\n\n"
6187 " --help Show this help\n",
6188 program_invocation_short_name);
6189 }
6190
6191 static void help_types(void) {
6192 int i;
6193 const char *t;
6194
6195 if (!arg_no_legend)
6196 puts("Available unit types:");
6197 for (i = 0; i < _UNIT_TYPE_MAX; i++) {
6198 t = unit_type_to_string(i);
6199 if (t)
6200 puts(t);
6201 }
6202 }
6203
6204 static int systemctl_parse_argv(int argc, char *argv[]) {
6205
6206 enum {
6207 ARG_FAIL = 0x100,
6208 ARG_REVERSE,
6209 ARG_AFTER,
6210 ARG_BEFORE,
6211 ARG_SHOW_TYPES,
6212 ARG_IRREVERSIBLE,
6213 ARG_IGNORE_DEPENDENCIES,
6214 ARG_VERSION,
6215 ARG_USER,
6216 ARG_SYSTEM,
6217 ARG_GLOBAL,
6218 ARG_NO_BLOCK,
6219 ARG_NO_LEGEND,
6220 ARG_NO_PAGER,
6221 ARG_NO_WALL,
6222 ARG_ROOT,
6223 ARG_NO_RELOAD,
6224 ARG_KILL_WHO,
6225 ARG_NO_ASK_PASSWORD,
6226 ARG_FAILED,
6227 ARG_RUNTIME,
6228 ARG_FORCE,
6229 ARG_PLAIN,
6230 ARG_STATE,
6231 ARG_JOB_MODE,
6232 ARG_PRESET_MODE,
6233 };
6234
6235 static const struct option options[] = {
6236 { "help", no_argument, NULL, 'h' },
6237 { "version", no_argument, NULL, ARG_VERSION },
6238 { "type", required_argument, NULL, 't' },
6239 { "property", required_argument, NULL, 'p' },
6240 { "all", no_argument, NULL, 'a' },
6241 { "reverse", no_argument, NULL, ARG_REVERSE },
6242 { "after", no_argument, NULL, ARG_AFTER },
6243 { "before", no_argument, NULL, ARG_BEFORE },
6244 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
6245 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
6246 { "full", no_argument, NULL, 'l' },
6247 { "job-mode", required_argument, NULL, ARG_JOB_MODE },
6248 { "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */
6249 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */
6250 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
6251 { "ignore-inhibitors", no_argument, NULL, 'i' },
6252 { "user", no_argument, NULL, ARG_USER },
6253 { "system", no_argument, NULL, ARG_SYSTEM },
6254 { "global", no_argument, NULL, ARG_GLOBAL },
6255 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
6256 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
6257 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
6258 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6259 { "quiet", no_argument, NULL, 'q' },
6260 { "root", required_argument, NULL, ARG_ROOT },
6261 { "force", no_argument, NULL, ARG_FORCE },
6262 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
6263 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
6264 { "signal", required_argument, NULL, 's' },
6265 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
6266 { "host", required_argument, NULL, 'H' },
6267 { "machine", required_argument, NULL, 'M' },
6268 { "runtime", no_argument, NULL, ARG_RUNTIME },
6269 { "lines", required_argument, NULL, 'n' },
6270 { "output", required_argument, NULL, 'o' },
6271 { "plain", no_argument, NULL, ARG_PLAIN },
6272 { "state", required_argument, NULL, ARG_STATE },
6273 { "recursive", no_argument, NULL, 'r' },
6274 { "preset-mode", required_argument, NULL, ARG_PRESET_MODE },
6275 {}
6276 };
6277
6278 int c;
6279
6280 assert(argc >= 0);
6281 assert(argv);
6282
6283 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0)
6284
6285 switch (c) {
6286
6287 case 'h':
6288 systemctl_help();
6289 return 0;
6290
6291 case ARG_VERSION:
6292 puts(PACKAGE_STRING);
6293 puts(SYSTEMD_FEATURES);
6294 return 0;
6295
6296 case 't': {
6297 const char *word, *state;
6298 size_t size;
6299
6300 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6301 _cleanup_free_ char *type;
6302
6303 type = strndup(word, size);
6304 if (!type)
6305 return -ENOMEM;
6306
6307 if (streq(type, "help")) {
6308 help_types();
6309 return 0;
6310 }
6311
6312 if (unit_type_from_string(type) >= 0) {
6313 if (strv_push(&arg_types, type))
6314 return log_oom();
6315 type = NULL;
6316 continue;
6317 }
6318
6319 /* It's much nicer to use --state= for
6320 * load states, but let's support this
6321 * in --types= too for compatibility
6322 * with old versions */
6323 if (unit_load_state_from_string(optarg) >= 0) {
6324 if (strv_push(&arg_states, type) < 0)
6325 return log_oom();
6326 type = NULL;
6327 continue;
6328 }
6329
6330 log_error("Unknown unit type or load state '%s'.", type);
6331 log_info("Use -t help to see a list of allowed values.");
6332 return -EINVAL;
6333 }
6334
6335 break;
6336 }
6337
6338 case 'p': {
6339 /* Make sure that if the empty property list
6340 was specified, we won't show any properties. */
6341 if (isempty(optarg) && !arg_properties) {
6342 arg_properties = new0(char*, 1);
6343 if (!arg_properties)
6344 return log_oom();
6345 } else {
6346 const char *word, *state;
6347 size_t size;
6348
6349 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6350 char *prop;
6351
6352 prop = strndup(word, size);
6353 if (!prop)
6354 return log_oom();
6355
6356 if (strv_consume(&arg_properties, prop) < 0)
6357 return log_oom();
6358 }
6359 }
6360
6361 /* If the user asked for a particular
6362 * property, show it to him, even if it is
6363 * empty. */
6364 arg_all = true;
6365
6366 break;
6367 }
6368
6369 case 'a':
6370 arg_all = true;
6371 break;
6372
6373 case ARG_REVERSE:
6374 arg_dependency = DEPENDENCY_REVERSE;
6375 break;
6376
6377 case ARG_AFTER:
6378 arg_dependency = DEPENDENCY_AFTER;
6379 break;
6380
6381 case ARG_BEFORE:
6382 arg_dependency = DEPENDENCY_BEFORE;
6383 break;
6384
6385 case ARG_SHOW_TYPES:
6386 arg_show_types = true;
6387 break;
6388
6389 case ARG_JOB_MODE:
6390 arg_job_mode = optarg;
6391 break;
6392
6393 case ARG_FAIL:
6394 arg_job_mode = "fail";
6395 break;
6396
6397 case ARG_IRREVERSIBLE:
6398 arg_job_mode = "replace-irreversibly";
6399 break;
6400
6401 case ARG_IGNORE_DEPENDENCIES:
6402 arg_job_mode = "ignore-dependencies";
6403 break;
6404
6405 case ARG_USER:
6406 arg_scope = UNIT_FILE_USER;
6407 break;
6408
6409 case ARG_SYSTEM:
6410 arg_scope = UNIT_FILE_SYSTEM;
6411 break;
6412
6413 case ARG_GLOBAL:
6414 arg_scope = UNIT_FILE_GLOBAL;
6415 break;
6416
6417 case ARG_NO_BLOCK:
6418 arg_no_block = true;
6419 break;
6420
6421 case ARG_NO_LEGEND:
6422 arg_no_legend = true;
6423 break;
6424
6425 case ARG_NO_PAGER:
6426 arg_no_pager = true;
6427 break;
6428
6429 case ARG_NO_WALL:
6430 arg_no_wall = true;
6431 break;
6432
6433 case ARG_ROOT:
6434 arg_root = optarg;
6435 break;
6436
6437 case 'l':
6438 arg_full = true;
6439 break;
6440
6441 case ARG_FAILED:
6442 if (strv_extend(&arg_states, "failed") < 0)
6443 return log_oom();
6444
6445 break;
6446
6447 case 'q':
6448 arg_quiet = true;
6449 break;
6450
6451 case ARG_FORCE:
6452 arg_force ++;
6453 break;
6454
6455 case 'f':
6456 arg_force ++;
6457 break;
6458
6459 case ARG_NO_RELOAD:
6460 arg_no_reload = true;
6461 break;
6462
6463 case ARG_KILL_WHO:
6464 arg_kill_who = optarg;
6465 break;
6466
6467 case 's':
6468 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
6469 log_error("Failed to parse signal string %s.", optarg);
6470 return -EINVAL;
6471 }
6472 break;
6473
6474 case ARG_NO_ASK_PASSWORD:
6475 arg_ask_password = false;
6476 break;
6477
6478 case 'H':
6479 arg_transport = BUS_TRANSPORT_REMOTE;
6480 arg_host = optarg;
6481 break;
6482
6483 case 'M':
6484 arg_transport = BUS_TRANSPORT_MACHINE;
6485 arg_host = optarg;
6486 break;
6487
6488 case ARG_RUNTIME:
6489 arg_runtime = true;
6490 break;
6491
6492 case 'n':
6493 if (safe_atou(optarg, &arg_lines) < 0) {
6494 log_error("Failed to parse lines '%s'", optarg);
6495 return -EINVAL;
6496 }
6497 break;
6498
6499 case 'o':
6500 arg_output = output_mode_from_string(optarg);
6501 if (arg_output < 0) {
6502 log_error("Unknown output '%s'.", optarg);
6503 return -EINVAL;
6504 }
6505 break;
6506
6507 case 'i':
6508 arg_ignore_inhibitors = true;
6509 break;
6510
6511 case ARG_PLAIN:
6512 arg_plain = true;
6513 break;
6514
6515 case ARG_STATE: {
6516 const char *word, *state;
6517 size_t size;
6518
6519 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6520 char *s;
6521
6522 s = strndup(word, size);
6523 if (!s)
6524 return log_oom();
6525
6526 if (strv_consume(&arg_states, s) < 0)
6527 return log_oom();
6528 }
6529 break;
6530 }
6531
6532 case 'r':
6533 if (geteuid() != 0) {
6534 log_error("--recursive requires root privileges.");
6535 return -EPERM;
6536 }
6537
6538 arg_recursive = true;
6539 break;
6540
6541 case ARG_PRESET_MODE:
6542
6543 arg_preset_mode = unit_file_preset_mode_from_string(optarg);
6544 if (arg_preset_mode < 0) {
6545 log_error("Failed to parse preset mode: %s.", optarg);
6546 return -EINVAL;
6547 }
6548
6549 break;
6550
6551 case '?':
6552 return -EINVAL;
6553
6554 default:
6555 assert_not_reached("Unhandled option");
6556 }
6557
6558 if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM) {
6559 log_error("Cannot access user instance remotely.");
6560 return -EINVAL;
6561 }
6562
6563 return 1;
6564 }
6565
6566 static int halt_parse_argv(int argc, char *argv[]) {
6567
6568 enum {
6569 ARG_HELP = 0x100,
6570 ARG_HALT,
6571 ARG_REBOOT,
6572 ARG_NO_WALL
6573 };
6574
6575 static const struct option options[] = {
6576 { "help", no_argument, NULL, ARG_HELP },
6577 { "halt", no_argument, NULL, ARG_HALT },
6578 { "poweroff", no_argument, NULL, 'p' },
6579 { "reboot", no_argument, NULL, ARG_REBOOT },
6580 { "force", no_argument, NULL, 'f' },
6581 { "wtmp-only", no_argument, NULL, 'w' },
6582 { "no-wtmp", no_argument, NULL, 'd' },
6583 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6584 {}
6585 };
6586
6587 int c, r, runlevel;
6588
6589 assert(argc >= 0);
6590 assert(argv);
6591
6592 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
6593 if (runlevel == '0' || runlevel == '6')
6594 arg_force = 2;
6595
6596 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0)
6597 switch (c) {
6598
6599 case ARG_HELP:
6600 halt_help();
6601 return 0;
6602
6603 case ARG_HALT:
6604 arg_action = ACTION_HALT;
6605 break;
6606
6607 case 'p':
6608 if (arg_action != ACTION_REBOOT)
6609 arg_action = ACTION_POWEROFF;
6610 break;
6611
6612 case ARG_REBOOT:
6613 arg_action = ACTION_REBOOT;
6614 break;
6615
6616 case 'f':
6617 arg_force = 2;
6618 break;
6619
6620 case 'w':
6621 arg_dry = true;
6622 break;
6623
6624 case 'd':
6625 arg_no_wtmp = true;
6626 break;
6627
6628 case ARG_NO_WALL:
6629 arg_no_wall = true;
6630 break;
6631
6632 case 'i':
6633 case 'h':
6634 case 'n':
6635 /* Compatibility nops */
6636 break;
6637
6638 case '?':
6639 return -EINVAL;
6640
6641 default:
6642 assert_not_reached("Unhandled option");
6643 }
6644
6645 if (arg_action == ACTION_REBOOT && (argc == optind || argc == optind + 1)) {
6646 r = update_reboot_param_file(argc == optind + 1 ? argv[optind] : NULL);
6647 if (r < 0)
6648 return r;
6649 } else if (optind < argc) {
6650 log_error("Too many arguments.");
6651 return -EINVAL;
6652 }
6653
6654 return 1;
6655 }
6656
6657 static int parse_time_spec(const char *t, usec_t *_u) {
6658 assert(t);
6659 assert(_u);
6660
6661 if (streq(t, "now"))
6662 *_u = 0;
6663 else if (!strchr(t, ':')) {
6664 uint64_t u;
6665
6666 if (safe_atou64(t, &u) < 0)
6667 return -EINVAL;
6668
6669 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
6670 } else {
6671 char *e = NULL;
6672 long hour, minute;
6673 struct tm tm = {};
6674 time_t s;
6675 usec_t n;
6676
6677 errno = 0;
6678 hour = strtol(t, &e, 10);
6679 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
6680 return -EINVAL;
6681
6682 minute = strtol(e+1, &e, 10);
6683 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
6684 return -EINVAL;
6685
6686 n = now(CLOCK_REALTIME);
6687 s = (time_t) (n / USEC_PER_SEC);
6688
6689 assert_se(localtime_r(&s, &tm));
6690
6691 tm.tm_hour = (int) hour;
6692 tm.tm_min = (int) minute;
6693 tm.tm_sec = 0;
6694
6695 assert_se(s = mktime(&tm));
6696
6697 *_u = (usec_t) s * USEC_PER_SEC;
6698
6699 while (*_u <= n)
6700 *_u += USEC_PER_DAY;
6701 }
6702
6703 return 0;
6704 }
6705
6706 static int shutdown_parse_argv(int argc, char *argv[]) {
6707
6708 enum {
6709 ARG_HELP = 0x100,
6710 ARG_NO_WALL
6711 };
6712
6713 static const struct option options[] = {
6714 { "help", no_argument, NULL, ARG_HELP },
6715 { "halt", no_argument, NULL, 'H' },
6716 { "poweroff", no_argument, NULL, 'P' },
6717 { "reboot", no_argument, NULL, 'r' },
6718 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
6719 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6720 {}
6721 };
6722
6723 int c, r;
6724
6725 assert(argc >= 0);
6726 assert(argv);
6727
6728 while ((c = getopt_long(argc, argv, "HPrhkKt:afFc", options, NULL)) >= 0)
6729 switch (c) {
6730
6731 case ARG_HELP:
6732 shutdown_help();
6733 return 0;
6734
6735 case 'H':
6736 arg_action = ACTION_HALT;
6737 break;
6738
6739 case 'P':
6740 arg_action = ACTION_POWEROFF;
6741 break;
6742
6743 case 'r':
6744 if (kexec_loaded())
6745 arg_action = ACTION_KEXEC;
6746 else
6747 arg_action = ACTION_REBOOT;
6748 break;
6749
6750 case 'K':
6751 arg_action = ACTION_KEXEC;
6752 break;
6753
6754 case 'h':
6755 if (arg_action != ACTION_HALT)
6756 arg_action = ACTION_POWEROFF;
6757 break;
6758
6759 case 'k':
6760 arg_dry = true;
6761 break;
6762
6763 case ARG_NO_WALL:
6764 arg_no_wall = true;
6765 break;
6766
6767 case 't':
6768 case 'a':
6769 case 'f':
6770 case 'F':
6771 /* Compatibility nops */
6772 break;
6773
6774 case 'c':
6775 arg_action = ACTION_CANCEL_SHUTDOWN;
6776 break;
6777
6778 case '?':
6779 return -EINVAL;
6780
6781 default:
6782 assert_not_reached("Unhandled option");
6783 }
6784
6785 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
6786 r = parse_time_spec(argv[optind], &arg_when);
6787 if (r < 0) {
6788 log_error("Failed to parse time specification: %s", argv[optind]);
6789 return r;
6790 }
6791 } else
6792 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
6793
6794 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
6795 /* No time argument for shutdown cancel */
6796 arg_wall = argv + optind;
6797 else if (argc > optind + 1)
6798 /* We skip the time argument */
6799 arg_wall = argv + optind + 1;
6800
6801 optind = argc;
6802
6803 return 1;
6804 }
6805
6806 static int telinit_parse_argv(int argc, char *argv[]) {
6807
6808 enum {
6809 ARG_HELP = 0x100,
6810 ARG_NO_WALL
6811 };
6812
6813 static const struct option options[] = {
6814 { "help", no_argument, NULL, ARG_HELP },
6815 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6816 {}
6817 };
6818
6819 static const struct {
6820 char from;
6821 enum action to;
6822 } table[] = {
6823 { '0', ACTION_POWEROFF },
6824 { '6', ACTION_REBOOT },
6825 { '1', ACTION_RESCUE },
6826 { '2', ACTION_RUNLEVEL2 },
6827 { '3', ACTION_RUNLEVEL3 },
6828 { '4', ACTION_RUNLEVEL4 },
6829 { '5', ACTION_RUNLEVEL5 },
6830 { 's', ACTION_RESCUE },
6831 { 'S', ACTION_RESCUE },
6832 { 'q', ACTION_RELOAD },
6833 { 'Q', ACTION_RELOAD },
6834 { 'u', ACTION_REEXEC },
6835 { 'U', ACTION_REEXEC }
6836 };
6837
6838 unsigned i;
6839 int c;
6840
6841 assert(argc >= 0);
6842 assert(argv);
6843
6844 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
6845 switch (c) {
6846
6847 case ARG_HELP:
6848 telinit_help();
6849 return 0;
6850
6851 case ARG_NO_WALL:
6852 arg_no_wall = true;
6853 break;
6854
6855 case '?':
6856 return -EINVAL;
6857
6858 default:
6859 assert_not_reached("Unhandled option");
6860 }
6861
6862 if (optind >= argc) {
6863 log_error("%s: required argument missing.",
6864 program_invocation_short_name);
6865 return -EINVAL;
6866 }
6867
6868 if (optind + 1 < argc) {
6869 log_error("Too many arguments.");
6870 return -EINVAL;
6871 }
6872
6873 if (strlen(argv[optind]) != 1) {
6874 log_error("Expected single character argument.");
6875 return -EINVAL;
6876 }
6877
6878 for (i = 0; i < ELEMENTSOF(table); i++)
6879 if (table[i].from == argv[optind][0])
6880 break;
6881
6882 if (i >= ELEMENTSOF(table)) {
6883 log_error("Unknown command '%s'.", argv[optind]);
6884 return -EINVAL;
6885 }
6886
6887 arg_action = table[i].to;
6888
6889 optind ++;
6890
6891 return 1;
6892 }
6893
6894 static int runlevel_parse_argv(int argc, char *argv[]) {
6895
6896 enum {
6897 ARG_HELP = 0x100,
6898 };
6899
6900 static const struct option options[] = {
6901 { "help", no_argument, NULL, ARG_HELP },
6902 {}
6903 };
6904
6905 int c;
6906
6907 assert(argc >= 0);
6908 assert(argv);
6909
6910 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
6911 switch (c) {
6912
6913 case ARG_HELP:
6914 runlevel_help();
6915 return 0;
6916
6917 case '?':
6918 return -EINVAL;
6919
6920 default:
6921 assert_not_reached("Unhandled option");
6922 }
6923
6924 if (optind < argc) {
6925 log_error("Too many arguments.");
6926 return -EINVAL;
6927 }
6928
6929 return 1;
6930 }
6931
6932 static int parse_argv(int argc, char *argv[]) {
6933 assert(argc >= 0);
6934 assert(argv);
6935
6936 if (program_invocation_short_name) {
6937
6938 if (strstr(program_invocation_short_name, "halt")) {
6939 arg_action = ACTION_HALT;
6940 return halt_parse_argv(argc, argv);
6941 } else if (strstr(program_invocation_short_name, "poweroff")) {
6942 arg_action = ACTION_POWEROFF;
6943 return halt_parse_argv(argc, argv);
6944 } else if (strstr(program_invocation_short_name, "reboot")) {
6945 if (kexec_loaded())
6946 arg_action = ACTION_KEXEC;
6947 else
6948 arg_action = ACTION_REBOOT;
6949 return halt_parse_argv(argc, argv);
6950 } else if (strstr(program_invocation_short_name, "shutdown")) {
6951 arg_action = ACTION_POWEROFF;
6952 return shutdown_parse_argv(argc, argv);
6953 } else if (strstr(program_invocation_short_name, "init")) {
6954
6955 if (sd_booted() > 0) {
6956 arg_action = _ACTION_INVALID;
6957 return telinit_parse_argv(argc, argv);
6958 } else {
6959 /* Hmm, so some other init system is
6960 * running, we need to forward this
6961 * request to it. For now we simply
6962 * guess that it is Upstart. */
6963
6964 execv(TELINIT, argv);
6965
6966 log_error("Couldn't find an alternative telinit implementation to spawn.");
6967 return -EIO;
6968 }
6969
6970 } else if (strstr(program_invocation_short_name, "runlevel")) {
6971 arg_action = ACTION_RUNLEVEL;
6972 return runlevel_parse_argv(argc, argv);
6973 }
6974 }
6975
6976 arg_action = ACTION_SYSTEMCTL;
6977 return systemctl_parse_argv(argc, argv);
6978 }
6979
6980 _pure_ static int action_to_runlevel(void) {
6981
6982 static const char table[_ACTION_MAX] = {
6983 [ACTION_HALT] = '0',
6984 [ACTION_POWEROFF] = '0',
6985 [ACTION_REBOOT] = '6',
6986 [ACTION_RUNLEVEL2] = '2',
6987 [ACTION_RUNLEVEL3] = '3',
6988 [ACTION_RUNLEVEL4] = '4',
6989 [ACTION_RUNLEVEL5] = '5',
6990 [ACTION_RESCUE] = '1'
6991 };
6992
6993 assert(arg_action < _ACTION_MAX);
6994
6995 return table[arg_action];
6996 }
6997
6998 static int talk_initctl(void) {
6999
7000 struct init_request request = {
7001 .magic = INIT_MAGIC,
7002 .sleeptime = 0,
7003 .cmd = INIT_CMD_RUNLVL
7004 };
7005
7006 _cleanup_close_ int fd = -1;
7007 char rl;
7008 int r;
7009
7010 rl = action_to_runlevel();
7011 if (!rl)
7012 return 0;
7013
7014 request.runlevel = rl;
7015
7016 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
7017 if (fd < 0) {
7018 if (errno == ENOENT)
7019 return 0;
7020
7021 log_error_errno(errno, "Failed to open "INIT_FIFO": %m");
7022 return -errno;
7023 }
7024
7025 r = loop_write(fd, &request, sizeof(request), false);
7026 if (r < 0)
7027 return log_error_errno(r, "Failed to write to "INIT_FIFO": %m");
7028
7029 return 1;
7030 }
7031
7032 static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
7033
7034 static const struct {
7035 const char* verb;
7036 const enum {
7037 MORE,
7038 LESS,
7039 EQUAL
7040 } argc_cmp;
7041 const int argc;
7042 int (* const dispatch)(sd_bus *bus, char **args);
7043 const enum {
7044 NOBUS = 1,
7045 FORCE,
7046 } bus;
7047 } verbs[] = {
7048 { "list-units", MORE, 0, list_units },
7049 { "list-unit-files", MORE, 1, list_unit_files, NOBUS },
7050 { "list-sockets", MORE, 1, list_sockets },
7051 { "list-timers", MORE, 1, list_timers },
7052 { "list-jobs", MORE, 1, list_jobs },
7053 { "list-machines", MORE, 1, list_machines },
7054 { "clear-jobs", EQUAL, 1, daemon_reload },
7055 { "cancel", MORE, 2, cancel_job },
7056 { "start", MORE, 2, start_unit },
7057 { "stop", MORE, 2, start_unit },
7058 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
7059 { "reload", MORE, 2, start_unit },
7060 { "restart", MORE, 2, start_unit },
7061 { "try-restart", MORE, 2, start_unit },
7062 { "reload-or-restart", MORE, 2, start_unit },
7063 { "reload-or-try-restart", MORE, 2, start_unit },
7064 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
7065 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
7066 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
7067 { "isolate", EQUAL, 2, start_unit },
7068 { "kill", MORE, 2, kill_unit },
7069 { "is-active", MORE, 2, check_unit_active },
7070 { "check", MORE, 2, check_unit_active },
7071 { "is-failed", MORE, 2, check_unit_failed },
7072 { "show", MORE, 1, show },
7073 { "cat", MORE, 2, cat, NOBUS },
7074 { "status", MORE, 1, show },
7075 { "help", MORE, 2, show },
7076 { "snapshot", LESS, 2, snapshot },
7077 { "delete", MORE, 2, delete_snapshot },
7078 { "daemon-reload", EQUAL, 1, daemon_reload },
7079 { "daemon-reexec", EQUAL, 1, daemon_reload },
7080 { "show-environment", EQUAL, 1, show_environment },
7081 { "set-environment", MORE, 2, set_environment },
7082 { "unset-environment", MORE, 2, set_environment },
7083 { "import-environment", MORE, 1, import_environment},
7084 { "halt", EQUAL, 1, start_special, FORCE },
7085 { "poweroff", EQUAL, 1, start_special, FORCE },
7086 { "reboot", EQUAL, 1, start_special, FORCE },
7087 { "kexec", EQUAL, 1, start_special },
7088 { "suspend", EQUAL, 1, start_special },
7089 { "hibernate", EQUAL, 1, start_special },
7090 { "hybrid-sleep", EQUAL, 1, start_special },
7091 { "default", EQUAL, 1, start_special },
7092 { "rescue", EQUAL, 1, start_special },
7093 { "emergency", EQUAL, 1, start_special },
7094 { "exit", EQUAL, 1, start_special },
7095 { "reset-failed", MORE, 1, reset_failed },
7096 { "enable", MORE, 2, enable_unit, NOBUS },
7097 { "disable", MORE, 2, enable_unit, NOBUS },
7098 { "is-enabled", MORE, 2, unit_is_enabled, NOBUS },
7099 { "reenable", MORE, 2, enable_unit, NOBUS },
7100 { "preset", MORE, 2, enable_unit, NOBUS },
7101 { "preset-all", EQUAL, 1, preset_all, NOBUS },
7102 { "mask", MORE, 2, enable_unit, NOBUS },
7103 { "unmask", MORE, 2, enable_unit, NOBUS },
7104 { "link", MORE, 2, enable_unit, NOBUS },
7105 { "switch-root", MORE, 2, switch_root },
7106 { "list-dependencies", LESS, 2, list_dependencies },
7107 { "set-default", EQUAL, 2, set_default, NOBUS },
7108 { "get-default", EQUAL, 1, get_default, NOBUS },
7109 { "set-property", MORE, 3, set_property },
7110 { "is-system-running", EQUAL, 1, is_system_running },
7111 { "add-wants", MORE, 3, add_dependency, NOBUS },
7112 { "add-requires", MORE, 3, add_dependency, NOBUS },
7113 { "edit", MORE, 2, edit, NOBUS },
7114 {}
7115 }, *verb = verbs;
7116
7117 int left;
7118
7119 assert(argc >= 0);
7120 assert(argv);
7121
7122 left = argc - optind;
7123
7124 /* Special rule: no arguments (left == 0) means "list-units" */
7125 if (left > 0) {
7126 if (streq(argv[optind], "help") && !argv[optind+1]) {
7127 log_error("This command expects one or more "
7128 "unit names. Did you mean --help?");
7129 return -EINVAL;
7130 }
7131
7132 for (; verb->verb; verb++)
7133 if (streq(argv[optind], verb->verb))
7134 goto found;
7135
7136 log_error("Unknown operation '%s'.", argv[optind]);
7137 return -EINVAL;
7138 }
7139 found:
7140
7141 switch (verb->argc_cmp) {
7142
7143 case EQUAL:
7144 if (left != verb->argc) {
7145 log_error("Invalid number of arguments.");
7146 return -EINVAL;
7147 }
7148
7149 break;
7150
7151 case MORE:
7152 if (left < verb->argc) {
7153 log_error("Too few arguments.");
7154 return -EINVAL;
7155 }
7156
7157 break;
7158
7159 case LESS:
7160 if (left > verb->argc) {
7161 log_error("Too many arguments.");
7162 return -EINVAL;
7163 }
7164
7165 break;
7166
7167 default:
7168 assert_not_reached("Unknown comparison operator.");
7169 }
7170
7171 /* Require a bus connection for all operations but
7172 * enable/disable */
7173 if (verb->bus == NOBUS) {
7174 if (!bus && !avoid_bus()) {
7175 log_error_errno(bus_error, "Failed to get D-Bus connection: %m");
7176 return -EIO;
7177 }
7178
7179 } else {
7180 if (running_in_chroot() > 0) {
7181 log_info("Running in chroot, ignoring request.");
7182 return 0;
7183 }
7184
7185 if ((verb->bus != FORCE || arg_force <= 0) && !bus) {
7186 log_error_errno(bus_error, "Failed to get D-Bus connection: %m");
7187 return -EIO;
7188 }
7189 }
7190
7191 return verb->dispatch(bus, argv + optind);
7192 }
7193
7194 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
7195
7196 struct sd_shutdown_command c = {
7197 .usec = t,
7198 .mode = mode,
7199 .dry_run = dry_run,
7200 .warn_wall = warn,
7201 };
7202
7203 union sockaddr_union sockaddr = {
7204 .un.sun_family = AF_UNIX,
7205 .un.sun_path = "/run/systemd/shutdownd",
7206 };
7207
7208 struct iovec iovec[2] = {{
7209 .iov_base = (char*) &c,
7210 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
7211 }};
7212
7213 struct msghdr msghdr = {
7214 .msg_name = &sockaddr,
7215 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
7216 + strlen("/run/systemd/shutdownd"),
7217 .msg_iov = iovec,
7218 .msg_iovlen = 1,
7219 };
7220
7221 _cleanup_close_ int fd;
7222
7223 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
7224 if (fd < 0)
7225 return -errno;
7226
7227 if (!isempty(message)) {
7228 iovec[1].iov_base = (char*) message;
7229 iovec[1].iov_len = strlen(message);
7230 msghdr.msg_iovlen++;
7231 }
7232
7233 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
7234 return -errno;
7235
7236 return 0;
7237 }
7238
7239 static int reload_with_fallback(sd_bus *bus) {
7240
7241 if (bus) {
7242 /* First, try systemd via D-Bus. */
7243 if (daemon_reload(bus, NULL) >= 0)
7244 return 0;
7245 }
7246
7247 /* Nothing else worked, so let's try signals */
7248 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
7249
7250 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0)
7251 return log_error_errno(errno, "kill() failed: %m");
7252
7253 return 0;
7254 }
7255
7256 static int start_with_fallback(sd_bus *bus) {
7257
7258 if (bus) {
7259 /* First, try systemd via D-Bus. */
7260 if (start_unit(bus, NULL) >= 0)
7261 goto done;
7262 }
7263
7264 /* Nothing else worked, so let's try
7265 * /dev/initctl */
7266 if (talk_initctl() > 0)
7267 goto done;
7268
7269 log_error("Failed to talk to init daemon.");
7270 return -EIO;
7271
7272 done:
7273 warn_wall(arg_action);
7274 return 0;
7275 }
7276
7277 static int halt_now(enum action a) {
7278
7279 /* The kernel will automaticall flush ATA disks and suchlike
7280 * on reboot(), but the file systems need to be synce'd
7281 * explicitly in advance. */
7282 sync();
7283
7284 /* Make sure C-A-D is handled by the kernel from this point
7285 * on... */
7286 reboot(RB_ENABLE_CAD);
7287
7288 switch (a) {
7289
7290 case ACTION_HALT:
7291 log_info("Halting.");
7292 reboot(RB_HALT_SYSTEM);
7293 return -errno;
7294
7295 case ACTION_POWEROFF:
7296 log_info("Powering off.");
7297 reboot(RB_POWER_OFF);
7298 return -errno;
7299
7300 case ACTION_REBOOT: {
7301 _cleanup_free_ char *param = NULL;
7302
7303 if (read_one_line_file(REBOOT_PARAM_FILE, &param) >= 0) {
7304 log_info("Rebooting with argument '%s'.", param);
7305 syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
7306 LINUX_REBOOT_CMD_RESTART2, param);
7307 }
7308
7309 log_info("Rebooting.");
7310 reboot(RB_AUTOBOOT);
7311 return -errno;
7312 }
7313
7314 default:
7315 assert_not_reached("Unknown action.");
7316 }
7317 }
7318
7319 static int halt_main(sd_bus *bus) {
7320 int r;
7321
7322 r = check_inhibitors(bus, arg_action);
7323 if (r < 0)
7324 return r;
7325
7326 if (geteuid() != 0) {
7327 /* Try logind if we are a normal user and no special
7328 * mode applies. Maybe PolicyKit allows us to shutdown
7329 * the machine. */
7330
7331 if (arg_when <= 0 &&
7332 !arg_dry &&
7333 arg_force <= 0 &&
7334 (arg_action == ACTION_POWEROFF ||
7335 arg_action == ACTION_REBOOT)) {
7336 r = reboot_with_logind(bus, arg_action);
7337 if (r >= 0)
7338 return r;
7339 }
7340
7341 log_error("Must be root.");
7342 return -EPERM;
7343 }
7344
7345 if (arg_when > 0) {
7346 _cleanup_free_ char *m;
7347
7348 m = strv_join(arg_wall, " ");
7349 if (!m)
7350 return log_oom();
7351
7352 r = send_shutdownd(arg_when,
7353 arg_action == ACTION_HALT ? 'H' :
7354 arg_action == ACTION_POWEROFF ? 'P' :
7355 arg_action == ACTION_KEXEC ? 'K' :
7356 'r',
7357 arg_dry,
7358 !arg_no_wall,
7359 m);
7360
7361 if (r < 0)
7362 log_warning_errno(r, "Failed to talk to shutdownd, proceeding with immediate shutdown: %m");
7363 else {
7364 char date[FORMAT_TIMESTAMP_MAX];
7365
7366 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
7367 format_timestamp(date, sizeof(date), arg_when));
7368 return 0;
7369 }
7370 }
7371
7372 if (!arg_dry && !arg_force)
7373 return start_with_fallback(bus);
7374
7375 if (!arg_no_wtmp) {
7376 if (sd_booted() > 0)
7377 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
7378 else {
7379 r = utmp_put_shutdown();
7380 if (r < 0)
7381 log_warning_errno(r, "Failed to write utmp record: %m");
7382 }
7383 }
7384
7385 if (arg_dry)
7386 return 0;
7387
7388 r = halt_now(arg_action);
7389 log_error_errno(r, "Failed to reboot: %m");
7390
7391 return r;
7392 }
7393
7394 static int runlevel_main(void) {
7395 int r, runlevel, previous;
7396
7397 r = utmp_get_runlevel(&runlevel, &previous);
7398 if (r < 0) {
7399 puts("unknown");
7400 return r;
7401 }
7402
7403 printf("%c %c\n",
7404 previous <= 0 ? 'N' : previous,
7405 runlevel <= 0 ? 'N' : runlevel);
7406
7407 return 0;
7408 }
7409
7410 int main(int argc, char*argv[]) {
7411 _cleanup_bus_close_unref_ sd_bus *bus = NULL;
7412 int r;
7413
7414 setlocale(LC_ALL, "");
7415 log_parse_environment();
7416 log_open();
7417
7418 /* Explicitly not on_tty() to avoid setting cached value.
7419 * This becomes relevant for piping output which might be
7420 * ellipsized. */
7421 original_stdout_is_tty = isatty(STDOUT_FILENO);
7422
7423 r = parse_argv(argc, argv);
7424 if (r <= 0)
7425 goto finish;
7426
7427 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
7428 * let's shortcut this */
7429 if (arg_action == ACTION_RUNLEVEL) {
7430 r = runlevel_main();
7431 goto finish;
7432 }
7433
7434 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
7435 log_info("Running in chroot, ignoring request.");
7436 r = 0;
7437 goto finish;
7438 }
7439
7440 if (!avoid_bus())
7441 r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus);
7442
7443 /* systemctl_main() will print an error message for the bus
7444 * connection, but only if it needs to */
7445
7446 switch (arg_action) {
7447
7448 case ACTION_SYSTEMCTL:
7449 r = systemctl_main(bus, argc, argv, r);
7450 break;
7451
7452 case ACTION_HALT:
7453 case ACTION_POWEROFF:
7454 case ACTION_REBOOT:
7455 case ACTION_KEXEC:
7456 r = halt_main(bus);
7457 break;
7458
7459 case ACTION_RUNLEVEL2:
7460 case ACTION_RUNLEVEL3:
7461 case ACTION_RUNLEVEL4:
7462 case ACTION_RUNLEVEL5:
7463 case ACTION_RESCUE:
7464 case ACTION_EMERGENCY:
7465 case ACTION_DEFAULT:
7466 r = start_with_fallback(bus);
7467 break;
7468
7469 case ACTION_RELOAD:
7470 case ACTION_REEXEC:
7471 r = reload_with_fallback(bus);
7472 break;
7473
7474 case ACTION_CANCEL_SHUTDOWN: {
7475 _cleanup_free_ char *m = NULL;
7476
7477 if (arg_wall) {
7478 m = strv_join(arg_wall, " ");
7479 if (!m) {
7480 r = log_oom();
7481 goto finish;
7482 }
7483 }
7484
7485 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
7486 if (r < 0)
7487 log_warning_errno(r, "Failed to talk to shutdownd, shutdown hasn't been cancelled: %m");
7488 break;
7489 }
7490
7491 case ACTION_RUNLEVEL:
7492 case _ACTION_INVALID:
7493 default:
7494 assert_not_reached("Unknown action");
7495 }
7496
7497 finish:
7498 pager_close();
7499 ask_password_agent_close();
7500 polkit_agent_close();
7501
7502 strv_free(arg_types);
7503 strv_free(arg_states);
7504 strv_free(arg_properties);
7505
7506 return r < 0 ? EXIT_FAILURE : r;
7507 }