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