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