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