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