]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/systemctl/systemctl.c
includes: remove duplicate includes
[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 = code;
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
2523 STRV_FOREACH(name, names) {
2524 int state;
2525
2526 state = check_one_unit(bus, *name, good_states, arg_quiet);
2527 if (state < 0)
2528 return state;
2529 if (state > 0)
2530 r = 0;
2531 }
2532
2533 return r;
2534 }
2535
2536 static int check_unit_active(sd_bus *bus, char **args) {
2537 /* According to LSB: 3, "program is not running" */
2538 return check_unit_generic(bus, 3, "active\0reloading\0", args + 1);
2539 }
2540
2541 static int check_unit_failed(sd_bus *bus, char **args) {
2542 return check_unit_generic(bus, 1, "failed\0", args + 1);
2543 }
2544
2545 static int kill_unit(sd_bus *bus, char **args) {
2546 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2547 _cleanup_strv_free_ char **names = NULL;
2548 char **name;
2549 int r, q;
2550
2551 assert(bus);
2552 assert(args);
2553
2554 if (!arg_kill_who)
2555 arg_kill_who = "all";
2556
2557 r = expand_names(bus, args + 1, NULL, &names);
2558 if (r < 0)
2559 log_error("Failed to expand names: %s", strerror(-r));
2560
2561 STRV_FOREACH(name, names) {
2562 q = sd_bus_call_method(
2563 bus,
2564 "org.freedesktop.systemd1",
2565 "/org/freedesktop/systemd1",
2566 "org.freedesktop.systemd1.Manager",
2567 "KillUnit",
2568 &error,
2569 NULL,
2570 "ssi", *names, arg_kill_who, arg_signal);
2571 if (q < 0) {
2572 log_error("Failed to kill unit %s: %s",
2573 *names, bus_error_message(&error, r));
2574 if (r == 0)
2575 r = q;
2576 }
2577 }
2578
2579 return r;
2580 }
2581
2582 typedef struct ExecStatusInfo {
2583 char *name;
2584
2585 char *path;
2586 char **argv;
2587
2588 bool ignore;
2589
2590 usec_t start_timestamp;
2591 usec_t exit_timestamp;
2592 pid_t pid;
2593 int code;
2594 int status;
2595
2596 LIST_FIELDS(struct ExecStatusInfo, exec);
2597 } ExecStatusInfo;
2598
2599 static void exec_status_info_free(ExecStatusInfo *i) {
2600 assert(i);
2601
2602 free(i->name);
2603 free(i->path);
2604 strv_free(i->argv);
2605 free(i);
2606 }
2607
2608 static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
2609 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2610 const char *path;
2611 uint32_t pid;
2612 int32_t code, status;
2613 int ignore, r;
2614
2615 assert(m);
2616 assert(i);
2617
2618 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii");
2619 if (r < 0)
2620 return bus_log_parse_error(r);
2621 else if (r == 0)
2622 return 0;
2623
2624 r = sd_bus_message_read(m, "s", &path);
2625 if (r < 0)
2626 return bus_log_parse_error(r);
2627
2628 i->path = strdup(path);
2629 if (!i->path)
2630 return log_oom();
2631
2632 r = sd_bus_message_read_strv(m, &i->argv);
2633 if (r < 0)
2634 return bus_log_parse_error(r);
2635
2636 r = sd_bus_message_read(m,
2637 "bttttuii",
2638 &ignore,
2639 &start_timestamp, &start_timestamp_monotonic,
2640 &exit_timestamp, &exit_timestamp_monotonic,
2641 &pid,
2642 &code, &status);
2643 if (r < 0)
2644 return bus_log_parse_error(r);
2645
2646 i->ignore = ignore;
2647 i->start_timestamp = (usec_t) start_timestamp;
2648 i->exit_timestamp = (usec_t) exit_timestamp;
2649 i->pid = (pid_t) pid;
2650 i->code = code;
2651 i->status = status;
2652
2653 r = sd_bus_message_exit_container(m);
2654 if (r < 0)
2655 return bus_log_parse_error(r);
2656
2657 return 1;
2658 }
2659
2660 typedef struct UnitStatusInfo {
2661 const char *id;
2662 const char *load_state;
2663 const char *active_state;
2664 const char *sub_state;
2665 const char *unit_file_state;
2666
2667 const char *description;
2668 const char *following;
2669
2670 char **documentation;
2671
2672 const char *fragment_path;
2673 const char *source_path;
2674 const char *control_group;
2675
2676 char **dropin_paths;
2677
2678 const char *load_error;
2679 const char *result;
2680
2681 usec_t inactive_exit_timestamp;
2682 usec_t inactive_exit_timestamp_monotonic;
2683 usec_t active_enter_timestamp;
2684 usec_t active_exit_timestamp;
2685 usec_t inactive_enter_timestamp;
2686
2687 bool need_daemon_reload;
2688
2689 /* Service */
2690 pid_t main_pid;
2691 pid_t control_pid;
2692 const char *status_text;
2693 const char *pid_file;
2694 bool running:1;
2695
2696 usec_t start_timestamp;
2697 usec_t exit_timestamp;
2698
2699 int exit_code, exit_status;
2700
2701 usec_t condition_timestamp;
2702 bool condition_result;
2703 bool failed_condition_trigger;
2704 bool failed_condition_negate;
2705 const char *failed_condition;
2706 const char *failed_condition_param;
2707
2708 /* Socket */
2709 unsigned n_accepted;
2710 unsigned n_connections;
2711 bool accept;
2712
2713 /* Pairs of type, path */
2714 char **listen;
2715
2716 /* Device */
2717 const char *sysfs_path;
2718
2719 /* Mount, Automount */
2720 const char *where;
2721
2722 /* Swap */
2723 const char *what;
2724
2725 LIST_HEAD(ExecStatusInfo, exec);
2726 } UnitStatusInfo;
2727
2728 static void print_status_info(
2729 UnitStatusInfo *i,
2730 bool *ellipsized) {
2731
2732 ExecStatusInfo *p;
2733 const char *on, *off, *ss;
2734 usec_t timestamp;
2735 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2736 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2737 const char *path;
2738 int flags =
2739 arg_all * OUTPUT_SHOW_ALL |
2740 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2741 on_tty() * OUTPUT_COLOR |
2742 !arg_quiet * OUTPUT_WARN_CUTOFF |
2743 arg_full * OUTPUT_FULL_WIDTH;
2744 char **t, **t2;
2745
2746 assert(i);
2747
2748 /* This shows pretty information about a unit. See
2749 * print_property() for a low-level property printer */
2750
2751 printf("%s", strna(i->id));
2752
2753 if (i->description && !streq_ptr(i->id, i->description))
2754 printf(" - %s", i->description);
2755
2756 printf("\n");
2757
2758 if (i->following)
2759 printf(" Follow: unit currently follows state of %s\n", i->following);
2760
2761 if (streq_ptr(i->load_state, "error")) {
2762 on = ansi_highlight_red();
2763 off = ansi_highlight_off();
2764 } else
2765 on = off = "";
2766
2767 path = i->source_path ? i->source_path : i->fragment_path;
2768
2769 if (i->load_error)
2770 printf(" Loaded: %s%s%s (Reason: %s)\n",
2771 on, strna(i->load_state), off, i->load_error);
2772 else if (path && i->unit_file_state)
2773 printf(" Loaded: %s%s%s (%s; %s)\n",
2774 on, strna(i->load_state), off, path, i->unit_file_state);
2775 else if (path)
2776 printf(" Loaded: %s%s%s (%s)\n",
2777 on, strna(i->load_state), off, path);
2778 else
2779 printf(" Loaded: %s%s%s\n",
2780 on, strna(i->load_state), off);
2781
2782 if (!strv_isempty(i->dropin_paths)) {
2783 _cleanup_free_ char *dir = NULL;
2784 bool last = false;
2785 char ** dropin;
2786
2787 STRV_FOREACH(dropin, i->dropin_paths) {
2788 if (! dir || last) {
2789 printf(dir ? " " : " Drop-In: ");
2790
2791 free(dir);
2792 dir = NULL;
2793
2794 if (path_get_parent(*dropin, &dir) < 0) {
2795 log_oom();
2796 return;
2797 }
2798
2799 printf("%s\n %s", dir,
2800 draw_special_char(DRAW_TREE_RIGHT));
2801 }
2802
2803 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
2804
2805 printf("%s%s", basename(*dropin), last ? "\n" : ", ");
2806 }
2807 }
2808
2809 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2810
2811 if (streq_ptr(i->active_state, "failed")) {
2812 on = ansi_highlight_red();
2813 off = ansi_highlight_off();
2814 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2815 on = ansi_highlight_green();
2816 off = ansi_highlight_off();
2817 } else
2818 on = off = "";
2819
2820 if (ss)
2821 printf(" Active: %s%s (%s)%s",
2822 on, strna(i->active_state), ss, off);
2823 else
2824 printf(" Active: %s%s%s",
2825 on, strna(i->active_state), off);
2826
2827 if (!isempty(i->result) && !streq(i->result, "success"))
2828 printf(" (Result: %s)", i->result);
2829
2830 timestamp = (streq_ptr(i->active_state, "active") ||
2831 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2832 (streq_ptr(i->active_state, "inactive") ||
2833 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2834 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2835 i->active_exit_timestamp;
2836
2837 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2838 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2839
2840 if (s1)
2841 printf(" since %s; %s\n", s2, s1);
2842 else if (s2)
2843 printf(" since %s\n", s2);
2844 else
2845 printf("\n");
2846
2847 if (!i->condition_result && i->condition_timestamp > 0) {
2848 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2849 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2850
2851 printf(" start condition failed at %s%s%s\n",
2852 s2, s1 ? "; " : "", s1 ? s1 : "");
2853 if (i->failed_condition_trigger)
2854 printf(" none of the trigger conditions were met\n");
2855 else if (i->failed_condition)
2856 printf(" %s=%s%s was not met\n",
2857 i->failed_condition,
2858 i->failed_condition_negate ? "!" : "",
2859 i->failed_condition_param);
2860 }
2861
2862 if (i->sysfs_path)
2863 printf(" Device: %s\n", i->sysfs_path);
2864 if (i->where)
2865 printf(" Where: %s\n", i->where);
2866 if (i->what)
2867 printf(" What: %s\n", i->what);
2868
2869 STRV_FOREACH(t, i->documentation)
2870 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
2871
2872 STRV_FOREACH_PAIR(t, t2, i->listen)
2873 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
2874
2875 if (i->accept)
2876 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2877
2878 LIST_FOREACH(exec, p, i->exec) {
2879 _cleanup_free_ char *argv = NULL;
2880 bool good;
2881
2882 /* Only show exited processes here */
2883 if (p->code == 0)
2884 continue;
2885
2886 argv = strv_join(p->argv, " ");
2887 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
2888
2889 good = is_clean_exit_lsb(p->code, p->status, NULL);
2890 if (!good) {
2891 on = ansi_highlight_red();
2892 off = ansi_highlight_off();
2893 } else
2894 on = off = "";
2895
2896 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2897
2898 if (p->code == CLD_EXITED) {
2899 const char *c;
2900
2901 printf("status=%i", p->status);
2902
2903 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2904 if (c)
2905 printf("/%s", c);
2906
2907 } else
2908 printf("signal=%s", signal_to_string(p->status));
2909
2910 printf(")%s\n", off);
2911
2912 if (i->main_pid == p->pid &&
2913 i->start_timestamp == p->start_timestamp &&
2914 i->exit_timestamp == p->start_timestamp)
2915 /* Let's not show this twice */
2916 i->main_pid = 0;
2917
2918 if (p->pid == i->control_pid)
2919 i->control_pid = 0;
2920 }
2921
2922 if (i->main_pid > 0 || i->control_pid > 0) {
2923 if (i->main_pid > 0) {
2924 printf(" Main PID: %u", (unsigned) i->main_pid);
2925
2926 if (i->running) {
2927 _cleanup_free_ char *comm = NULL;
2928 get_process_comm(i->main_pid, &comm);
2929 if (comm)
2930 printf(" (%s)", comm);
2931 } else if (i->exit_code > 0) {
2932 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2933
2934 if (i->exit_code == CLD_EXITED) {
2935 const char *c;
2936
2937 printf("status=%i", i->exit_status);
2938
2939 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2940 if (c)
2941 printf("/%s", c);
2942
2943 } else
2944 printf("signal=%s", signal_to_string(i->exit_status));
2945 printf(")");
2946 }
2947
2948 if (i->control_pid > 0)
2949 printf(";");
2950 }
2951
2952 if (i->control_pid > 0) {
2953 _cleanup_free_ char *c = NULL;
2954
2955 printf(" %8s: %u", i->main_pid ? "" : " Control", (unsigned) i->control_pid);
2956
2957 get_process_comm(i->control_pid, &c);
2958 if (c)
2959 printf(" (%s)", c);
2960 }
2961
2962 printf("\n");
2963 }
2964
2965 if (i->status_text)
2966 printf(" Status: \"%s\"\n", i->status_text);
2967
2968 if (i->control_group &&
2969 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0)) {
2970 unsigned c;
2971
2972 printf(" CGroup: %s\n", i->control_group);
2973
2974 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
2975 unsigned k = 0;
2976 pid_t extra[2];
2977 char prefix[] = " ";
2978
2979 c = columns();
2980 if (c > sizeof(prefix) - 1)
2981 c -= sizeof(prefix) - 1;
2982 else
2983 c = 0;
2984
2985 if (i->main_pid > 0)
2986 extra[k++] = i->main_pid;
2987
2988 if (i->control_pid > 0)
2989 extra[k++] = i->control_pid;
2990
2991 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix,
2992 c, false, extra, k, flags);
2993 }
2994 }
2995
2996 if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) {
2997 printf("\n");
2998 show_journal_by_unit(stdout,
2999 i->id,
3000 arg_output,
3001 0,
3002 i->inactive_exit_timestamp_monotonic,
3003 arg_lines,
3004 getuid(),
3005 flags,
3006 arg_scope == UNIT_FILE_SYSTEM,
3007 ellipsized);
3008 }
3009
3010 if (i->need_daemon_reload)
3011 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
3012 ansi_highlight_red(),
3013 ansi_highlight_off(),
3014 arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
3015 }
3016
3017 static void show_unit_help(UnitStatusInfo *i) {
3018 char **p;
3019
3020 assert(i);
3021
3022 if (!i->documentation) {
3023 log_info("Documentation for %s not known.", i->id);
3024 return;
3025 }
3026
3027 STRV_FOREACH(p, i->documentation) {
3028
3029 if (startswith(*p, "man:")) {
3030 const char *args[4] = { "man", NULL, NULL, NULL };
3031 _cleanup_free_ char *page = NULL, *section = NULL;
3032 char *e = NULL;
3033 pid_t pid;
3034 size_t k;
3035
3036 k = strlen(*p);
3037
3038 if ((*p)[k-1] == ')')
3039 e = strrchr(*p, '(');
3040
3041 if (e) {
3042 page = strndup((*p) + 4, e - *p - 4);
3043 section = strndup(e + 1, *p + k - e - 2);
3044 if (!page || !section) {
3045 log_oom();
3046 return;
3047 }
3048
3049 args[1] = section;
3050 args[2] = page;
3051 } else
3052 args[1] = *p + 4;
3053
3054 pid = fork();
3055 if (pid < 0) {
3056 log_error("Failed to fork: %m");
3057 continue;
3058 }
3059
3060 if (pid == 0) {
3061 /* Child */
3062 execvp(args[0], (char**) args);
3063 log_error("Failed to execute man: %m");
3064 _exit(EXIT_FAILURE);
3065 }
3066
3067 wait_for_terminate(pid, NULL);
3068 } else
3069 log_info("Can't show: %s", *p);
3070 }
3071 }
3072
3073 static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) {
3074 int r;
3075
3076 assert(name);
3077 assert(m);
3078 assert(i);
3079
3080 switch (contents[0]) {
3081
3082 case SD_BUS_TYPE_STRING: {
3083 const char *s;
3084
3085 r = sd_bus_message_read(m, "s", &s);
3086 if (r < 0)
3087 return bus_log_parse_error(r);
3088
3089 if (!isempty(s)) {
3090 if (streq(name, "Id"))
3091 i->id = s;
3092 else if (streq(name, "LoadState"))
3093 i->load_state = s;
3094 else if (streq(name, "ActiveState"))
3095 i->active_state = s;
3096 else if (streq(name, "SubState"))
3097 i->sub_state = s;
3098 else if (streq(name, "Description"))
3099 i->description = s;
3100 else if (streq(name, "FragmentPath"))
3101 i->fragment_path = s;
3102 else if (streq(name, "SourcePath"))
3103 i->source_path = s;
3104 #ifndef NOLEGACY
3105 else if (streq(name, "DefaultControlGroup")) {
3106 const char *e;
3107 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
3108 if (e)
3109 i->control_group = e;
3110 }
3111 #endif
3112 else if (streq(name, "ControlGroup"))
3113 i->control_group = s;
3114 else if (streq(name, "StatusText"))
3115 i->status_text = s;
3116 else if (streq(name, "PIDFile"))
3117 i->pid_file = s;
3118 else if (streq(name, "SysFSPath"))
3119 i->sysfs_path = s;
3120 else if (streq(name, "Where"))
3121 i->where = s;
3122 else if (streq(name, "What"))
3123 i->what = s;
3124 else if (streq(name, "Following"))
3125 i->following = s;
3126 else if (streq(name, "UnitFileState"))
3127 i->unit_file_state = s;
3128 else if (streq(name, "Result"))
3129 i->result = s;
3130 }
3131
3132 break;
3133 }
3134
3135 case SD_BUS_TYPE_BOOLEAN: {
3136 int b;
3137
3138 r = sd_bus_message_read(m, "b", &b);
3139 if (r < 0)
3140 return bus_log_parse_error(r);
3141
3142 if (streq(name, "Accept"))
3143 i->accept = b;
3144 else if (streq(name, "NeedDaemonReload"))
3145 i->need_daemon_reload = b;
3146 else if (streq(name, "ConditionResult"))
3147 i->condition_result = b;
3148
3149 break;
3150 }
3151
3152 case SD_BUS_TYPE_UINT32: {
3153 uint32_t u;
3154
3155 r = sd_bus_message_read(m, "u", &u);
3156 if (r < 0)
3157 return bus_log_parse_error(r);
3158
3159 if (streq(name, "MainPID")) {
3160 if (u > 0) {
3161 i->main_pid = (pid_t) u;
3162 i->running = true;
3163 }
3164 } else if (streq(name, "ControlPID"))
3165 i->control_pid = (pid_t) u;
3166 else if (streq(name, "ExecMainPID")) {
3167 if (u > 0)
3168 i->main_pid = (pid_t) u;
3169 } else if (streq(name, "NAccepted"))
3170 i->n_accepted = u;
3171 else if (streq(name, "NConnections"))
3172 i->n_connections = u;
3173
3174 break;
3175 }
3176
3177 case SD_BUS_TYPE_INT32: {
3178 int32_t j;
3179
3180 r = sd_bus_message_read(m, "i", &j);
3181 if (r < 0)
3182 return bus_log_parse_error(r);
3183
3184 if (streq(name, "ExecMainCode"))
3185 i->exit_code = (int) j;
3186 else if (streq(name, "ExecMainStatus"))
3187 i->exit_status = (int) j;
3188
3189 break;
3190 }
3191
3192 case SD_BUS_TYPE_UINT64: {
3193 uint64_t u;
3194
3195 r = sd_bus_message_read(m, "t", &u);
3196 if (r < 0)
3197 return bus_log_parse_error(r);
3198
3199 if (streq(name, "ExecMainStartTimestamp"))
3200 i->start_timestamp = (usec_t) u;
3201 else if (streq(name, "ExecMainExitTimestamp"))
3202 i->exit_timestamp = (usec_t) u;
3203 else if (streq(name, "ActiveEnterTimestamp"))
3204 i->active_enter_timestamp = (usec_t) u;
3205 else if (streq(name, "InactiveEnterTimestamp"))
3206 i->inactive_enter_timestamp = (usec_t) u;
3207 else if (streq(name, "InactiveExitTimestamp"))
3208 i->inactive_exit_timestamp = (usec_t) u;
3209 else if (streq(name, "InactiveExitTimestampMonotonic"))
3210 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3211 else if (streq(name, "ActiveExitTimestamp"))
3212 i->active_exit_timestamp = (usec_t) u;
3213 else if (streq(name, "ConditionTimestamp"))
3214 i->condition_timestamp = (usec_t) u;
3215
3216 break;
3217 }
3218
3219 case SD_BUS_TYPE_ARRAY:
3220
3221 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3222 _cleanup_free_ ExecStatusInfo *info = NULL;
3223
3224 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3225 if (r < 0)
3226 return bus_log_parse_error(r);
3227
3228 info = new0(ExecStatusInfo, 1);
3229 if (!info)
3230 return log_oom();
3231
3232 while ((r = exec_status_info_deserialize(m, info)) > 0) {
3233
3234 info->name = strdup(name);
3235 if (!info->name)
3236 log_oom();
3237
3238 LIST_PREPEND(exec, i->exec, info);
3239
3240 info = new0(ExecStatusInfo, 1);
3241 if (!info)
3242 log_oom();
3243 }
3244
3245 if (r < 0)
3246 return bus_log_parse_error(r);
3247
3248 r = sd_bus_message_exit_container(m);
3249 if (r < 0)
3250 return bus_log_parse_error(r);
3251
3252 return 0;
3253
3254 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3255 const char *type, *path;
3256
3257 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3258 if (r < 0)
3259 return bus_log_parse_error(r);
3260
3261 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
3262
3263 r = strv_extend(&i->listen, type);
3264 if (r < 0)
3265 return r;
3266
3267 r = strv_extend(&i->listen, path);
3268 if (r < 0)
3269 return r;
3270 }
3271 if (r < 0)
3272 return bus_log_parse_error(r);
3273
3274 r = sd_bus_message_exit_container(m);
3275 if (r < 0)
3276 return bus_log_parse_error(r);
3277
3278 return 0;
3279
3280 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "DropInPaths")) {
3281
3282 r = sd_bus_message_read_strv(m, &i->dropin_paths);
3283 if (r < 0)
3284 return bus_log_parse_error(r);
3285
3286 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Documentation")) {
3287
3288 r = sd_bus_message_read_strv(m, &i->documentation);
3289 if (r < 0)
3290 return bus_log_parse_error(r);
3291
3292 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Conditions")) {
3293 const char *cond, *param;
3294 int trigger, negate;
3295 int32_t state;
3296
3297 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3298 if (r < 0)
3299 return bus_log_parse_error(r);
3300
3301 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, &param, &state)) > 0) {
3302 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3303 if (state < 0 && (!trigger || !i->failed_condition)) {
3304 i->failed_condition = cond;
3305 i->failed_condition_trigger = trigger;
3306 i->failed_condition_negate = negate;
3307 i->failed_condition_param = param;
3308 }
3309 }
3310 if (r < 0)
3311 return bus_log_parse_error(r);
3312
3313 r = sd_bus_message_exit_container(m);
3314 if (r < 0)
3315 return bus_log_parse_error(r);
3316
3317 } else
3318 goto skip;
3319
3320 break;
3321
3322 case SD_BUS_TYPE_STRUCT_BEGIN:
3323
3324 if (streq(name, "LoadError")) {
3325 const char *n, *message;
3326
3327 r = sd_bus_message_read(m, "(ss)", &n, &message);
3328 if (r < 0)
3329 return bus_log_parse_error(r);
3330
3331 if (!isempty(message))
3332 i->load_error = message;
3333 } else
3334 goto skip;
3335
3336 break;
3337
3338 default:
3339 goto skip;
3340 }
3341
3342 return 0;
3343
3344 skip:
3345 r = sd_bus_message_skip(m, contents);
3346 if (r < 0)
3347 return bus_log_parse_error(r);
3348
3349 return 0;
3350 }
3351
3352 static int print_property(const char *name, sd_bus_message *m, const char *contents) {
3353 int r;
3354
3355 assert(name);
3356 assert(m);
3357
3358 /* This is a low-level property printer, see
3359 * print_status_info() for the nicer output */
3360
3361 if (arg_properties && !strv_find(arg_properties, name)) {
3362 /* skip what we didn't read */
3363 r = sd_bus_message_skip(m, contents);
3364 return r;
3365 }
3366
3367 switch (contents[0]) {
3368
3369 case SD_BUS_TYPE_STRUCT_BEGIN:
3370
3371 if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
3372 uint32_t u;
3373
3374 r = sd_bus_message_read(m, "(uo)", &u, NULL);
3375 if (r < 0)
3376 return bus_log_parse_error(r);
3377
3378 if (u > 0)
3379 printf("%s=%u\n", name, (unsigned) u);
3380 else if (arg_all)
3381 printf("%s=\n", name);
3382
3383 return 0;
3384
3385 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
3386 const char *s;
3387
3388 r = sd_bus_message_read(m, "(so)", &s, NULL);
3389 if (r < 0)
3390 return bus_log_parse_error(r);
3391
3392 if (arg_all || !isempty(s))
3393 printf("%s=%s\n", name, s);
3394
3395 return 0;
3396
3397 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
3398 const char *a = NULL, *b = NULL;
3399
3400 r = sd_bus_message_read(m, "(ss)", &a, &b);
3401 if (r < 0)
3402 return bus_log_parse_error(r);
3403
3404 if (arg_all || !isempty(a) || !isempty(b))
3405 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3406
3407 return 0;
3408 }
3409
3410 break;
3411
3412 case SD_BUS_TYPE_ARRAY:
3413
3414 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
3415 const char *path;
3416 int ignore;
3417
3418 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)");
3419 if (r < 0)
3420 return bus_log_parse_error(r);
3421
3422 while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
3423 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3424
3425 if (r < 0)
3426 return bus_log_parse_error(r);
3427
3428 r = sd_bus_message_exit_container(m);
3429 if (r < 0)
3430 return bus_log_parse_error(r);
3431
3432 return 0;
3433
3434 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
3435 const char *type, *path;
3436
3437 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3438 if (r < 0)
3439 return bus_log_parse_error(r);
3440
3441 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
3442 printf("%s=%s\n", type, path);
3443 if (r < 0)
3444 return bus_log_parse_error(r);
3445
3446 r = sd_bus_message_exit_container(m);
3447 if (r < 0)
3448 return bus_log_parse_error(r);
3449
3450 return 0;
3451
3452 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3453 const char *type, *path;
3454
3455 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3456 if (r < 0)
3457 return bus_log_parse_error(r);
3458
3459 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
3460 printf("Listen%s=%s\n", type, path);
3461 if (r < 0)
3462 return bus_log_parse_error(r);
3463
3464 r = sd_bus_message_exit_container(m);
3465 if (r < 0)
3466 return bus_log_parse_error(r);
3467
3468 return 0;
3469
3470 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Timers")) {
3471 const char *base;
3472 uint64_t value, next_elapse;
3473
3474 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
3475 if (r < 0)
3476 return bus_log_parse_error(r);
3477
3478 while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) {
3479 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3480
3481 printf("%s={ value=%s ; next_elapse=%s }\n",
3482 base,
3483 format_timespan(timespan1, sizeof(timespan1), value, 0),
3484 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
3485 }
3486 if (r < 0)
3487 return bus_log_parse_error(r);
3488
3489 r = sd_bus_message_exit_container(m);
3490 if (r < 0)
3491 return bus_log_parse_error(r);
3492
3493 return 0;
3494
3495 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3496 ExecStatusInfo info = {};
3497
3498 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3499 if (r < 0)
3500 return bus_log_parse_error(r);
3501
3502 while ((r = exec_status_info_deserialize(m, &info)) > 0) {
3503 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3504 _cleanup_free_ char *tt;
3505
3506 tt = strv_join(info.argv, " ");
3507
3508 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3509 name,
3510 strna(info.path),
3511 strna(tt),
3512 yes_no(info.ignore),
3513 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3514 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3515 (unsigned) info. pid,
3516 sigchld_code_to_string(info.code),
3517 info.status,
3518 info.code == CLD_EXITED ? "" : "/",
3519 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3520
3521 free(info.path);
3522 strv_free(info.argv);
3523 zero(info);
3524 }
3525
3526 r = sd_bus_message_exit_container(m);
3527 if (r < 0)
3528 return bus_log_parse_error(r);
3529
3530 return 0;
3531
3532 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
3533 const char *path, *rwm;
3534
3535 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3536 if (r < 0)
3537 return bus_log_parse_error(r);
3538
3539 while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
3540 printf("%s=%s %s\n", name, strna(path), strna(rwm));
3541 if (r < 0)
3542 return bus_log_parse_error(r);
3543
3544 r = sd_bus_message_exit_container(m);
3545 if (r < 0)
3546 return bus_log_parse_error(r);
3547
3548 return 0;
3549
3550 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "BlockIODeviceWeight")) {
3551 const char *path;
3552 uint64_t weight;
3553
3554 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
3555 if (r < 0)
3556 return bus_log_parse_error(r);
3557
3558 while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
3559 printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
3560 if (r < 0)
3561 return bus_log_parse_error(r);
3562
3563 r = sd_bus_message_exit_container(m);
3564 if (r < 0)
3565 return bus_log_parse_error(r);
3566
3567 return 0;
3568
3569 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
3570 const char *path;
3571 uint64_t bandwidth;
3572
3573 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
3574 if (r < 0)
3575 return bus_log_parse_error(r);
3576
3577 while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
3578 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
3579 if (r < 0)
3580 return bus_log_parse_error(r);
3581
3582 r = sd_bus_message_exit_container(m);
3583 if (r < 0)
3584 return bus_log_parse_error(r);
3585
3586 return 0;
3587 }
3588
3589 break;
3590 }
3591
3592 r = bus_print_property(name, m, arg_all);
3593 if (r < 0)
3594 return bus_log_parse_error(r);
3595
3596 if (r == 0) {
3597 r = sd_bus_message_skip(m, contents);
3598 if (r < 0)
3599 return bus_log_parse_error(r);
3600
3601 if (arg_all)
3602 printf("%s=[unprintable]\n", name);
3603 }
3604
3605 return 0;
3606 }
3607
3608 static int show_one(
3609 const char *verb,
3610 sd_bus *bus,
3611 const char *path,
3612 bool show_properties,
3613 bool *new_line,
3614 bool *ellipsized) {
3615
3616 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
3617 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3618 UnitStatusInfo info = {};
3619 ExecStatusInfo *p;
3620 int r;
3621
3622 assert(path);
3623 assert(new_line);
3624
3625 log_debug("Showing one %s", path);
3626
3627 r = sd_bus_call_method(
3628 bus,
3629 "org.freedesktop.systemd1",
3630 path,
3631 "org.freedesktop.DBus.Properties",
3632 "GetAll",
3633 &error,
3634 &reply,
3635 "s", "");
3636 if (r < 0) {
3637 log_error("Failed to get properties: %s", bus_error_message(&error, r));
3638 return r;
3639 }
3640
3641 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
3642 if (r < 0)
3643 return bus_log_parse_error(r);
3644
3645 if (*new_line)
3646 printf("\n");
3647
3648 *new_line = true;
3649
3650 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
3651 const char *name, *contents;
3652
3653 r = sd_bus_message_read(reply, "s", &name);
3654 if (r < 0)
3655 return bus_log_parse_error(r);
3656
3657 r = sd_bus_message_peek_type(reply, NULL, &contents);
3658 if (r < 0)
3659 return bus_log_parse_error(r);
3660
3661 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
3662 if (r < 0)
3663 return bus_log_parse_error(r);
3664
3665 if (show_properties)
3666 r = print_property(name, reply, contents);
3667 else
3668 r = status_property(name, reply, &info, contents);
3669 if (r < 0)
3670 return r;
3671
3672 r = sd_bus_message_exit_container(reply);
3673 if (r < 0)
3674 return bus_log_parse_error(r);
3675
3676 r = sd_bus_message_exit_container(reply);
3677 if (r < 0)
3678 return bus_log_parse_error(r);
3679 }
3680 if (r < 0)
3681 return bus_log_parse_error(r);
3682
3683 r = sd_bus_message_exit_container(reply);
3684 if (r < 0)
3685 return bus_log_parse_error(r);
3686
3687 r = 0;
3688
3689 if (!show_properties) {
3690 if (streq(verb, "help"))
3691 show_unit_help(&info);
3692 else
3693 print_status_info(&info, ellipsized);
3694 }
3695
3696 strv_free(info.documentation);
3697 strv_free(info.dropin_paths);
3698 strv_free(info.listen);
3699
3700 if (!streq_ptr(info.active_state, "active") &&
3701 !streq_ptr(info.active_state, "reloading") &&
3702 streq(verb, "status")) {
3703 /* According to LSB: "program not running" */
3704 /* 0: program is running or service is OK
3705 * 1: program is dead and /var/run pid file exists
3706 * 2: program is dead and /var/lock lock file exists
3707 * 3: program is not running
3708 * 4: program or service status is unknown
3709 */
3710 if (info.pid_file && access(info.pid_file, F_OK) == 0)
3711 r = 1;
3712 else
3713 r = 3;
3714 }
3715
3716 while ((p = info.exec)) {
3717 LIST_REMOVE(exec, info.exec, p);
3718 exec_status_info_free(p);
3719 }
3720
3721 return r;
3722 }
3723
3724 static int get_unit_dbus_path_by_pid(
3725 sd_bus *bus,
3726 uint32_t pid,
3727 char **unit) {
3728
3729 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3730 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
3731 char *u;
3732 int r;
3733
3734 r = sd_bus_call_method(
3735 bus,
3736 "org.freedesktop.systemd1",
3737 "/org/freedesktop/systemd1",
3738 "org.freedesktop.systemd1.Manager",
3739 "GetUnitByPID",
3740 &error,
3741 &reply,
3742 "u", pid);
3743 if (r < 0) {
3744 log_error("Failed to get unit for PID %lu: %s", (unsigned long) pid, bus_error_message(&error, r));
3745 return r;
3746 }
3747
3748 r = sd_bus_message_read(reply, "o", &u);
3749 if (r < 0)
3750 return bus_log_parse_error(r);
3751
3752 u = strdup(u);
3753 if (!u)
3754 return log_oom();
3755
3756 *unit = u;
3757 return 0;
3758 }
3759
3760 static int show_all(
3761 const char* verb,
3762 sd_bus *bus,
3763 bool show_properties,
3764 bool *new_line,
3765 bool *ellipsized) {
3766
3767 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
3768 _cleanup_free_ UnitInfo *unit_infos = NULL;
3769 const UnitInfo *u;
3770 unsigned c;
3771 int r;
3772
3773 r = get_unit_list(bus, &reply, &unit_infos, NULL);
3774 if (r < 0)
3775 return r;
3776
3777 pager_open_if_enabled();
3778
3779 c = (unsigned) r;
3780
3781 qsort_safe(unit_infos, c, sizeof(UnitInfo), compare_unit_info);
3782
3783 for (u = unit_infos; u < unit_infos + c; u++) {
3784 _cleanup_free_ char *p = NULL;
3785
3786 p = unit_dbus_path_from_name(u->id);
3787 if (!p)
3788 return log_oom();
3789
3790 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
3791 if (r != 0)
3792 return r;
3793 }
3794
3795 return 0;
3796 }
3797
3798 static int cat(sd_bus *bus, char **args) {
3799 _cleanup_free_ char *unit = NULL;
3800 _cleanup_strv_free_ char **names = NULL;
3801 char **name;
3802 bool first = true;
3803 int r = 0;
3804
3805 assert(bus);
3806 assert(args);
3807
3808 r = expand_names(bus, args + 1, NULL, &names);
3809 if (r < 0)
3810 log_error("Failed to expand names: %s", strerror(-r));
3811
3812 pager_open_if_enabled();
3813
3814 STRV_FOREACH(name, names) {
3815 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3816 _cleanup_strv_free_ char **dropin_paths = NULL;
3817 _cleanup_free_ char *fragment_path = NULL;
3818 char **path;
3819
3820 unit = unit_dbus_path_from_name(*name);
3821 if (!unit)
3822 return log_oom();
3823
3824 if (need_daemon_reload(bus, *name) > 0)
3825 log_warning("Unit file of %s changed on disk. Run 'systemctl%s daemon-reload'.",
3826 *name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
3827
3828 r = sd_bus_get_property_string(
3829 bus,
3830 "org.freedesktop.systemd1",
3831 unit,
3832 "org.freedesktop.systemd1.Unit",
3833 "FragmentPath",
3834 &error,
3835 &fragment_path);
3836 if (r < 0) {
3837 log_warning("Failed to get FragmentPath: %s", bus_error_message(&error, r));
3838 continue;
3839 }
3840
3841 r = sd_bus_get_property_strv(
3842 bus,
3843 "org.freedesktop.systemd1",
3844 unit,
3845 "org.freedesktop.systemd1.Unit",
3846 "DropInPaths",
3847 &error,
3848 &dropin_paths);
3849 if (r < 0) {
3850 log_warning("Failed to get DropInPaths: %s", bus_error_message(&error, r));
3851 continue;
3852 }
3853
3854 if (first)
3855 first = false;
3856 else
3857 puts("");
3858
3859 if (!isempty(fragment_path)) {
3860 printf("%s# %s%s\n",
3861 ansi_highlight_blue(),
3862 fragment_path,
3863 ansi_highlight_off());
3864 fflush(stdout);
3865
3866 r = sendfile_full(STDOUT_FILENO, fragment_path);
3867 if (r < 0) {
3868 log_warning("Failed to cat %s: %s", fragment_path, strerror(-r));
3869 continue;
3870 }
3871 }
3872
3873 STRV_FOREACH(path, dropin_paths) {
3874 printf("%s%s# %s%s\n",
3875 isempty(fragment_path) && path == dropin_paths ? "" : "\n",
3876 ansi_highlight_blue(),
3877 *path,
3878 ansi_highlight_off());
3879 fflush(stdout);
3880
3881 r = sendfile_full(STDOUT_FILENO, *path);
3882 if (r < 0) {
3883 log_warning("Failed to cat %s: %s", *path, strerror(-r));
3884 continue;
3885 }
3886 }
3887 }
3888
3889 return r < 0 ? r : 0;
3890 }
3891
3892 static int show(sd_bus *bus, char **args) {
3893 bool show_properties, show_status, new_line = false;
3894 bool ellipsized = false;
3895 int r, ret = 0;
3896
3897 assert(bus);
3898 assert(args);
3899
3900 show_properties = streq(args[0], "show");
3901 show_status = streq(args[0], "status");
3902
3903 if (show_properties)
3904 pager_open_if_enabled();
3905
3906 /* If no argument is specified inspect the manager itself */
3907
3908 if (show_properties && strv_length(args) <= 1)
3909 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
3910
3911 if (show_status && strv_length(args) <= 1)
3912 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
3913 else {
3914 _cleanup_free_ char **patterns = NULL;
3915 char **name;
3916
3917 STRV_FOREACH(name, args + 1) {
3918 _cleanup_free_ char *unit = NULL;
3919 uint32_t id;
3920
3921 if (safe_atou32(*name, &id) < 0) {
3922 if (strv_push(&patterns, *name) < 0)
3923 return log_oom();
3924
3925 continue;
3926 } else if (show_properties) {
3927 /* Interpret as job id */
3928 if (asprintf(&unit, "/org/freedesktop/systemd1/job/%u", id) < 0)
3929 return log_oom();
3930
3931 } else {
3932 /* Interpret as PID */
3933 r = get_unit_dbus_path_by_pid(bus, id, &unit);
3934 if (r < 0) {
3935 ret = r;
3936 continue;
3937 }
3938 }
3939
3940 show_one(args[0], bus, unit, show_properties, &new_line, &ellipsized);
3941 }
3942
3943 if (!strv_isempty(patterns)) {
3944 _cleanup_strv_free_ char **names = NULL;
3945
3946 r = expand_names(bus, patterns, NULL, &names);
3947 if (r < 0)
3948 log_error("Failed to expand names: %s", strerror(-r));
3949
3950 STRV_FOREACH(name, names) {
3951 _cleanup_free_ char *unit;
3952
3953 unit = unit_dbus_path_from_name(*name);
3954 if (!unit)
3955 return log_oom();
3956
3957 show_one(args[0], bus, unit, show_properties, &new_line, &ellipsized);
3958 }
3959 }
3960 }
3961
3962 if (ellipsized && !arg_quiet)
3963 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
3964
3965 return ret;
3966 }
3967
3968 static int append_assignment(sd_bus_message *m, const char *assignment) {
3969 const char *eq;
3970 char *field;
3971 int r;
3972
3973 assert(m);
3974 assert(assignment);
3975
3976 eq = strchr(assignment, '=');
3977 if (!eq) {
3978 log_error("Not an assignment: %s", assignment);
3979 return -EINVAL;
3980 }
3981
3982 field = strndupa(assignment, eq - assignment);
3983 eq ++;
3984
3985 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
3986 if (r < 0)
3987 return bus_log_create_error(r);
3988
3989 if (streq(field, "CPUAccounting") ||
3990 streq(field, "MemoryAccounting") ||
3991 streq(field, "BlockIOAccounting")) {
3992
3993 r = parse_boolean(eq);
3994 if (r < 0) {
3995 log_error("Failed to parse boolean assignment %s.", assignment);
3996 return -EINVAL;
3997 }
3998
3999 r = sd_bus_message_append(m, "v", "b", r);
4000
4001 } else if (streq(field, "MemoryLimit")) {
4002 off_t bytes;
4003
4004 r = parse_bytes(eq, &bytes);
4005 if (r < 0) {
4006 log_error("Failed to parse bytes specification %s", assignment);
4007 return -EINVAL;
4008 }
4009
4010 r = sd_bus_message_append(m, "v", "t", (uint64_t) bytes);
4011
4012 } else if (streq(field, "CPUShares") || streq(field, "BlockIOWeight")) {
4013 uint64_t u;
4014
4015 r = safe_atou64(eq, &u);
4016 if (r < 0) {
4017 log_error("Failed to parse %s value %s.", field, eq);
4018 return -EINVAL;
4019 }
4020
4021 r = sd_bus_message_append(m, "v", "t", u);
4022
4023 } else if (streq(field, "DevicePolicy"))
4024 r = sd_bus_message_append(m, "v", "s", eq);
4025
4026 else if (streq(field, "DeviceAllow")) {
4027
4028 if (isempty(eq))
4029 r = sd_bus_message_append(m, "v", "a(ss)", 0);
4030 else {
4031 const char *path, *rwm;
4032 char *e;
4033
4034 e = strchr(eq, ' ');
4035 if (e) {
4036 path = strndupa(eq, e - eq);
4037 rwm = e+1;
4038 } else {
4039 path = eq;
4040 rwm = "";
4041 }
4042
4043 if (!path_startswith(path, "/dev")) {
4044 log_error("%s is not a device file in /dev.", path);
4045 return -EINVAL;
4046 }
4047
4048 r = sd_bus_message_append(m, "v", "a(ss)", 1, path, rwm);
4049 }
4050
4051 } else if (streq(field, "BlockIOReadBandwidth") || streq(field, "BlockIOWriteBandwidth")) {
4052
4053 if (isempty(eq))
4054 r = sd_bus_message_append(m, "v", "a(st)", 0);
4055 else {
4056 const char *path, *bandwidth;
4057 off_t bytes;
4058 char *e;
4059
4060 e = strchr(eq, ' ');
4061 if (e) {
4062 path = strndupa(eq, e - eq);
4063 bandwidth = e+1;
4064 } else {
4065 log_error("Failed to parse %s value %s.", field, eq);
4066 return -EINVAL;
4067 }
4068
4069 if (!path_startswith(path, "/dev")) {
4070 log_error("%s is not a device file in /dev.", path);
4071 return -EINVAL;
4072 }
4073
4074 r = parse_bytes(bandwidth, &bytes);
4075 if (r < 0) {
4076 log_error("Failed to parse byte value %s.", bandwidth);
4077 return -EINVAL;
4078 }
4079
4080 r = sd_bus_message_append(m, "v", "a(st)", 1, path, (uint64_t) bytes);
4081 }
4082
4083 } else if (streq(field, "BlockIODeviceWeight")) {
4084
4085 if (isempty(eq))
4086 r = sd_bus_message_append(m, "v", "a(st)", 0);
4087 else {
4088 const char *path, *weight;
4089 uint64_t u;
4090 char *e;
4091
4092 e = strchr(eq, ' ');
4093 if (e) {
4094 path = strndupa(eq, e - eq);
4095 weight = e+1;
4096 } else {
4097 log_error("Failed to parse %s value %s.", field, eq);
4098 return -EINVAL;
4099 }
4100
4101 if (!path_startswith(path, "/dev")) {
4102 log_error("%s is not a device file in /dev.", path);
4103 return -EINVAL;
4104 }
4105
4106 r = safe_atou64(weight, &u);
4107 if (r < 0) {
4108 log_error("Failed to parse %s value %s.", field, weight);
4109 return -EINVAL;
4110 }
4111 r = sd_bus_message_append(m, "v", "a(st)", path, u);
4112 }
4113
4114 } else {
4115 log_error("Unknown assignment %s.", assignment);
4116 return -EINVAL;
4117 }
4118
4119 if (r < 0)
4120 return bus_log_create_error(r);
4121
4122 return 0;
4123 }
4124
4125 static int set_property(sd_bus *bus, char **args) {
4126 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4127 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4128 _cleanup_free_ char *n = NULL;
4129 char **i;
4130 int r;
4131
4132 r = sd_bus_message_new_method_call(
4133 bus,
4134 "org.freedesktop.systemd1",
4135 "/org/freedesktop/systemd1",
4136 "org.freedesktop.systemd1.Manager",
4137 "SetUnitProperties",
4138 &m);
4139 if (r < 0)
4140 return bus_log_create_error(r);
4141
4142 n = unit_name_mangle(args[1], MANGLE_NOGLOB);
4143 if (!n)
4144 return log_oom();
4145
4146 r = sd_bus_message_append(m, "sb", n, arg_runtime);
4147 if (r < 0)
4148 return bus_log_create_error(r);
4149
4150 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)");
4151 if (r < 0)
4152 return bus_log_create_error(r);
4153
4154 STRV_FOREACH(i, args + 2) {
4155 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
4156 if (r < 0)
4157 return bus_log_create_error(r);
4158
4159 r = append_assignment(m, *i);
4160 if (r < 0)
4161 return r;
4162
4163 r = sd_bus_message_close_container(m);
4164 if (r < 0)
4165 return bus_log_create_error(r);
4166 }
4167
4168 r = sd_bus_message_close_container(m);
4169 if (r < 0)
4170 return bus_log_create_error(r);
4171
4172 r = sd_bus_call(bus, m, 0, &error, NULL);
4173 if (r < 0) {
4174 log_error("Failed to set unit properties on %s: %s", n, bus_error_message(&error, r));
4175 return r;
4176 }
4177
4178 return 0;
4179 }
4180
4181 static int snapshot(sd_bus *bus, char **args) {
4182 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4183 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4184 _cleanup_free_ char *n = NULL, *id = NULL;
4185 const char *path;
4186 int r;
4187
4188 if (strv_length(args) > 1)
4189 n = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".snapshot");
4190 else
4191 n = strdup("");
4192 if (!n)
4193 return log_oom();
4194
4195 r = sd_bus_call_method(
4196 bus,
4197 "org.freedesktop.systemd1",
4198 "/org/freedesktop/systemd1",
4199 "org.freedesktop.systemd1.Manager",
4200 "CreateSnapshot",
4201 &error,
4202 &reply,
4203 "sb", n, false);
4204 if (r < 0) {
4205 log_error("Failed to create snapshot: %s", bus_error_message(&error, r));
4206 return r;
4207 }
4208
4209 r = sd_bus_message_read(reply, "o", &path);
4210 if (r < 0)
4211 return bus_log_parse_error(r);
4212
4213 r = sd_bus_get_property_string(
4214 bus,
4215 "org.freedesktop.systemd1",
4216 path,
4217 "org.freedesktop.systemd1.Unit",
4218 "Id",
4219 &error,
4220 &id);
4221 if (r < 0) {
4222 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error, r));
4223 return r;
4224 }
4225
4226 if (!arg_quiet)
4227 puts(id);
4228
4229 return 0;
4230 }
4231
4232 static int delete_snapshot(sd_bus *bus, char **args) {
4233 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4234 _cleanup_strv_free_ char **names = NULL;
4235 char **name;
4236 int r, q;
4237
4238 assert(args);
4239
4240 r = expand_names(bus, args + 1, ".snapshot", &names);
4241 if (r < 0)
4242 log_error("Failed to expand names: %s", strerror(-r));
4243
4244 STRV_FOREACH(name, names) {
4245 q = sd_bus_call_method(
4246 bus,
4247 "org.freedesktop.systemd1",
4248 "/org/freedesktop/systemd1",
4249 "org.freedesktop.systemd1.Manager",
4250 "RemoveSnapshot",
4251 &error,
4252 NULL,
4253 "s", *name);
4254 if (q < 0) {
4255 log_error("Failed to remove snapshot %s: %s",
4256 *name, bus_error_message(&error, r));
4257 if (r == 0)
4258 r = q;
4259 }
4260 }
4261
4262 return r;
4263 }
4264
4265 static int daemon_reload(sd_bus *bus, char **args) {
4266 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4267 const char *method;
4268 int r;
4269
4270 if (arg_action == ACTION_RELOAD)
4271 method = "Reload";
4272 else if (arg_action == ACTION_REEXEC)
4273 method = "Reexecute";
4274 else {
4275 assert(arg_action == ACTION_SYSTEMCTL);
4276
4277 method =
4278 streq(args[0], "clear-jobs") ||
4279 streq(args[0], "cancel") ? "ClearJobs" :
4280 streq(args[0], "daemon-reexec") ? "Reexecute" :
4281 streq(args[0], "reset-failed") ? "ResetFailed" :
4282 streq(args[0], "halt") ? "Halt" :
4283 streq(args[0], "poweroff") ? "PowerOff" :
4284 streq(args[0], "reboot") ? "Reboot" :
4285 streq(args[0], "kexec") ? "KExec" :
4286 streq(args[0], "exit") ? "Exit" :
4287 /* "daemon-reload" */ "Reload";
4288 }
4289
4290 r = sd_bus_call_method(
4291 bus,
4292 "org.freedesktop.systemd1",
4293 "/org/freedesktop/systemd1",
4294 "org.freedesktop.systemd1.Manager",
4295 method,
4296 &error,
4297 NULL,
4298 NULL);
4299
4300 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
4301 /* There's always a fallback possible for
4302 * legacy actions. */
4303 r = -EADDRNOTAVAIL;
4304 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
4305 /* On reexecution, we expect a disconnect, not a
4306 * reply */
4307 r = 0;
4308 else if (r < 0)
4309 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
4310
4311 return r < 0 ? r : 0;
4312 }
4313
4314 static int reset_failed(sd_bus *bus, char **args) {
4315 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4316 _cleanup_strv_free_ char **names = NULL;
4317 char **name;
4318 int r, q;
4319
4320 if (strv_length(args) <= 1)
4321 return daemon_reload(bus, args);
4322
4323 r = expand_names(bus, args + 1, NULL, &names);
4324 if (r < 0)
4325 log_error("Failed to expand names: %s", strerror(-r));
4326
4327 STRV_FOREACH(name, names) {
4328 q = sd_bus_call_method(
4329 bus,
4330 "org.freedesktop.systemd1",
4331 "/org/freedesktop/systemd1",
4332 "org.freedesktop.systemd1.Manager",
4333 "ResetFailedUnit",
4334 &error,
4335 NULL,
4336 "s", *name);
4337 if (q < 0) {
4338 log_error("Failed to reset failed state of unit %s: %s",
4339 *name, bus_error_message(&error, r));
4340 if (r == 0)
4341 r = q;
4342 }
4343 }
4344
4345 return r;
4346 }
4347
4348 static int show_environment(sd_bus *bus, char **args) {
4349 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4350 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4351 const char *text;
4352 int r;
4353
4354 pager_open_if_enabled();
4355
4356 r = sd_bus_get_property(
4357 bus,
4358 "org.freedesktop.systemd1",
4359 "/org/freedesktop/systemd1",
4360 "org.freedesktop.systemd1.Manager",
4361 "Environment",
4362 &error,
4363 &reply,
4364 "as");
4365 if (r < 0) {
4366 log_error("Failed to get environment: %s", bus_error_message(&error, r));
4367 return r;
4368 }
4369
4370 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
4371 if (r < 0)
4372 return bus_log_parse_error(r);
4373
4374 while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0)
4375 puts(text);
4376 if (r < 0)
4377 return bus_log_parse_error(r);
4378
4379 r = sd_bus_message_exit_container(reply);
4380 if (r < 0)
4381 return bus_log_parse_error(r);
4382
4383 return 0;
4384 }
4385
4386 static int switch_root(sd_bus *bus, char **args) {
4387 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4388 _cleanup_free_ char *init = NULL;
4389 const char *root;
4390 unsigned l;
4391 int r;
4392
4393 l = strv_length(args);
4394 if (l < 2 || l > 3) {
4395 log_error("Wrong number of arguments.");
4396 return -EINVAL;
4397 }
4398
4399 root = args[1];
4400
4401 if (l >= 3)
4402 init = strdup(args[2]);
4403 else {
4404 parse_env_file("/proc/cmdline", WHITESPACE,
4405 "init", &init,
4406 NULL);
4407
4408 if (!init)
4409 init = strdup("");
4410 }
4411
4412 if (!init)
4413 return log_oom();
4414
4415 log_debug("switching root - root: %s; init: %s", root, init);
4416
4417 r = sd_bus_call_method(
4418 bus,
4419 "org.freedesktop.systemd1",
4420 "/org/freedesktop/systemd1",
4421 "org.freedesktop.systemd1.Manager",
4422 "SwitchRoot",
4423 &error,
4424 NULL,
4425 "ss", root, init);
4426 if (r < 0) {
4427 log_error("Failed to switch root: %s", bus_error_message(&error, r));
4428 return r;
4429 }
4430
4431 return 0;
4432 }
4433
4434 static int set_environment(sd_bus *bus, char **args) {
4435 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4436 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4437 const char *method;
4438 int r;
4439
4440 assert(bus);
4441 assert(args);
4442
4443 method = streq(args[0], "set-environment")
4444 ? "SetEnvironment"
4445 : "UnsetEnvironment";
4446
4447 r = sd_bus_message_new_method_call(
4448 bus,
4449 "org.freedesktop.systemd1",
4450 "/org/freedesktop/systemd1",
4451 "org.freedesktop.systemd1.Manager",
4452 method,
4453 &m);
4454 if (r < 0)
4455 return bus_log_create_error(r);
4456
4457 r = sd_bus_message_append_strv(m, args + 1);
4458 if (r < 0)
4459 return bus_log_create_error(r);
4460
4461 r = sd_bus_call(bus, m, 0, &error, NULL);
4462 if (r < 0) {
4463 log_error("Failed to set environment: %s", bus_error_message(&error, r));
4464 return r;
4465 }
4466
4467 return 0;
4468 }
4469
4470 static int import_environment(sd_bus *bus, char **args) {
4471 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4472 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4473 int r;
4474
4475 assert(bus);
4476 assert(args);
4477
4478 r = sd_bus_message_new_method_call(
4479 bus,
4480 "org.freedesktop.systemd1",
4481 "/org/freedesktop/systemd1",
4482 "org.freedesktop.systemd1.Manager",
4483 "SetEnvironment",
4484 &m);
4485 if (r < 0)
4486 return bus_log_create_error(r);
4487
4488 if (strv_isempty(args + 1))
4489 r = sd_bus_message_append_strv(m, environ);
4490 else {
4491 char **a, **b;
4492
4493 r = sd_bus_message_open_container(m, 'a', "s");
4494 if (r < 0)
4495 return bus_log_create_error(r);
4496
4497 STRV_FOREACH(a, args + 1) {
4498
4499 if (!env_name_is_valid(*a)) {
4500 log_error("Not a valid environment variable name: %s", *a);
4501 return -EINVAL;
4502 }
4503
4504 STRV_FOREACH(b, environ) {
4505 const char *eq;
4506
4507 eq = startswith(*b, *a);
4508 if (eq && *eq == '=') {
4509
4510 r = sd_bus_message_append(m, "s", *b);
4511 if (r < 0)
4512 return bus_log_create_error(r);
4513
4514 break;
4515 }
4516 }
4517 }
4518
4519 r = sd_bus_message_close_container(m);
4520 }
4521 if (r < 0)
4522 return bus_log_create_error(r);
4523
4524 r = sd_bus_call(bus, m, 0, &error, NULL);
4525 if (r < 0) {
4526 log_error("Failed to import environment: %s", bus_error_message(&error, r));
4527 return r;
4528 }
4529
4530 return 0;
4531 }
4532
4533 static int enable_sysv_units(const char *verb, char **args) {
4534 int r = 0;
4535
4536 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4537 unsigned f = 1, t = 1;
4538 _cleanup_lookup_paths_free_ LookupPaths paths = {};
4539
4540 if (arg_scope != UNIT_FILE_SYSTEM)
4541 return 0;
4542
4543 if (!streq(verb, "enable") &&
4544 !streq(verb, "disable") &&
4545 !streq(verb, "is-enabled"))
4546 return 0;
4547
4548 /* Processes all SysV units, and reshuffles the array so that
4549 * afterwards only the native units remain */
4550
4551 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
4552 if (r < 0)
4553 return r;
4554
4555 r = 0;
4556 for (f = 0; args[f]; f++) {
4557 const char *name;
4558 _cleanup_free_ char *p = NULL, *q = NULL;
4559 bool found_native = false, found_sysv;
4560 unsigned c = 1;
4561 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
4562 char **k, *l;
4563 int j;
4564 pid_t pid;
4565 siginfo_t status;
4566
4567 name = args[f];
4568
4569 if (!endswith(name, ".service"))
4570 continue;
4571
4572 if (path_is_absolute(name))
4573 continue;
4574
4575 STRV_FOREACH(k, paths.unit_path) {
4576 if (!isempty(arg_root))
4577 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
4578 else
4579 asprintf(&p, "%s/%s", *k, name);
4580
4581 if (!p) {
4582 r = log_oom();
4583 goto finish;
4584 }
4585
4586 found_native = access(p, F_OK) >= 0;
4587 free(p);
4588 p = NULL;
4589
4590 if (found_native)
4591 break;
4592 }
4593
4594 if (found_native)
4595 continue;
4596
4597 if (!isempty(arg_root))
4598 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
4599 else
4600 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
4601 if (!p) {
4602 r = log_oom();
4603 goto finish;
4604 }
4605
4606 p[strlen(p) - sizeof(".service") + 1] = 0;
4607 found_sysv = access(p, F_OK) >= 0;
4608
4609 if (!found_sysv)
4610 continue;
4611
4612 /* Mark this entry, so that we don't try enabling it as native unit */
4613 args[f] = (char*) "";
4614
4615 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
4616
4617 if (!isempty(arg_root))
4618 argv[c++] = q = strappend("--root=", arg_root);
4619
4620 argv[c++] = basename(p);
4621 argv[c++] =
4622 streq(verb, "enable") ? "on" :
4623 streq(verb, "disable") ? "off" : "--level=5";
4624 argv[c] = NULL;
4625
4626 l = strv_join((char**)argv, " ");
4627 if (!l) {
4628 r = log_oom();
4629 goto finish;
4630 }
4631
4632 log_info("Executing %s", l);
4633 free(l);
4634
4635 pid = fork();
4636 if (pid < 0) {
4637 log_error("Failed to fork: %m");
4638 r = -errno;
4639 goto finish;
4640 } else if (pid == 0) {
4641 /* Child */
4642
4643 execv(argv[0], (char**) argv);
4644 _exit(EXIT_FAILURE);
4645 }
4646
4647 j = wait_for_terminate(pid, &status);
4648 if (j < 0) {
4649 log_error("Failed to wait for child: %s", strerror(-r));
4650 r = j;
4651 goto finish;
4652 }
4653
4654 if (status.si_code == CLD_EXITED) {
4655 if (streq(verb, "is-enabled")) {
4656 if (status.si_status == 0) {
4657 if (!arg_quiet)
4658 puts("enabled");
4659 r = 1;
4660 } else {
4661 if (!arg_quiet)
4662 puts("disabled");
4663 }
4664
4665 } else if (status.si_status != 0) {
4666 r = -EINVAL;
4667 goto finish;
4668 }
4669 } else {
4670 r = -EPROTO;
4671 goto finish;
4672 }
4673 }
4674
4675 finish:
4676 /* Drop all SysV units */
4677 for (f = 0, t = 0; args[f]; f++) {
4678
4679 if (isempty(args[f]))
4680 continue;
4681
4682 args[t++] = args[f];
4683 }
4684
4685 args[t] = NULL;
4686
4687 #endif
4688 return r;
4689 }
4690
4691 static int mangle_names(char **original_names, char ***mangled_names) {
4692 char **i, **l, **name;
4693
4694 l = new(char*, strv_length(original_names) + 1);
4695 if (!l)
4696 return log_oom();
4697
4698 i = l;
4699 STRV_FOREACH(name, original_names) {
4700
4701 /* When enabling units qualified path names are OK,
4702 * too, hence allow them explicitly. */
4703
4704 if (is_path(*name))
4705 *i = strdup(*name);
4706 else
4707 *i = unit_name_mangle(*name, MANGLE_NOGLOB);
4708
4709 if (!*i) {
4710 strv_free(l);
4711 return log_oom();
4712 }
4713
4714 i++;
4715 }
4716
4717 *i = NULL;
4718 *mangled_names = l;
4719
4720 return 0;
4721 }
4722
4723 static int enable_unit(sd_bus *bus, char **args) {
4724 _cleanup_strv_free_ char **names = NULL;
4725 const char *verb = args[0];
4726 UnitFileChange *changes = NULL;
4727 unsigned n_changes = 0;
4728 int carries_install_info = -1;
4729 int r;
4730
4731 if (!args[1])
4732 return 0;
4733
4734 r = mangle_names(args+1, &names);
4735 if (r < 0)
4736 return r;
4737
4738 r = enable_sysv_units(verb, names);
4739 if (r < 0)
4740 return r;
4741
4742 /* If the operation was fully executed by the SysV compat,
4743 * let's finish early */
4744 if (strv_isempty(names))
4745 return 0;
4746
4747 if (!bus || avoid_bus()) {
4748 if (streq(verb, "enable")) {
4749 r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
4750 carries_install_info = r;
4751 } else if (streq(verb, "disable"))
4752 r = unit_file_disable(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
4753 else if (streq(verb, "reenable")) {
4754 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
4755 carries_install_info = r;
4756 } else if (streq(verb, "link"))
4757 r = unit_file_link(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
4758 else if (streq(verb, "preset")) {
4759 r = unit_file_preset(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
4760 carries_install_info = r;
4761 } else if (streq(verb, "mask"))
4762 r = unit_file_mask(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
4763 else if (streq(verb, "unmask"))
4764 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
4765 else
4766 assert_not_reached("Unknown verb");
4767
4768 if (r < 0) {
4769 log_error("Operation failed: %s", strerror(-r));
4770 goto finish;
4771 }
4772
4773 if (!arg_quiet)
4774 dump_unit_file_changes(changes, n_changes);
4775
4776 r = 0;
4777 } else {
4778 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
4779 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4780 int expect_carries_install_info = false;
4781 bool send_force = true;
4782 const char *method;
4783
4784 if (streq(verb, "enable")) {
4785 method = "EnableUnitFiles";
4786 expect_carries_install_info = true;
4787 } else if (streq(verb, "disable")) {
4788 method = "DisableUnitFiles";
4789 send_force = false;
4790 } else if (streq(verb, "reenable")) {
4791 method = "ReenableUnitFiles";
4792 expect_carries_install_info = true;
4793 } else if (streq(verb, "link"))
4794 method = "LinkUnitFiles";
4795 else if (streq(verb, "preset")) {
4796 method = "PresetUnitFiles";
4797 expect_carries_install_info = true;
4798 } else if (streq(verb, "mask"))
4799 method = "MaskUnitFiles";
4800 else if (streq(verb, "unmask")) {
4801 method = "UnmaskUnitFiles";
4802 send_force = false;
4803 } else
4804 assert_not_reached("Unknown verb");
4805
4806 r = sd_bus_message_new_method_call(
4807 bus,
4808 "org.freedesktop.systemd1",
4809 "/org/freedesktop/systemd1",
4810 "org.freedesktop.systemd1.Manager",
4811 method,
4812 &m);
4813 if (r < 0)
4814 return bus_log_create_error(r);
4815
4816 r = sd_bus_message_append_strv(m, names);
4817 if (r < 0)
4818 return bus_log_create_error(r);
4819
4820 r = sd_bus_message_append(m, "b", arg_runtime);
4821 if (r < 0)
4822 return bus_log_create_error(r);
4823
4824 if (send_force) {
4825 r = sd_bus_message_append(m, "b", arg_force);
4826 if (r < 0)
4827 return bus_log_create_error(r);
4828 }
4829
4830 r = sd_bus_call(bus, m, 0, &error, &reply);
4831 if (r < 0) {
4832 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
4833 return r;
4834 }
4835
4836 if (expect_carries_install_info) {
4837 r = sd_bus_message_read(reply, "b", &carries_install_info);
4838 if (r < 0)
4839 return bus_log_parse_error(r);
4840 }
4841
4842 r = deserialize_and_dump_unit_file_changes(reply);
4843 if (r < 0)
4844 return r;
4845
4846 /* Try to reload if enabeld */
4847 if (!arg_no_reload)
4848 r = daemon_reload(bus, args);
4849 else
4850 r = 0;
4851 }
4852
4853 if (carries_install_info == 0)
4854 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
4855 "using systemctl.\n"
4856 "Possible reasons for having this kind of units are:\n"
4857 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4858 " .wants/ or .requires/ directory.\n"
4859 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4860 " a requirement dependency on it.\n"
4861 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4862 " D-Bus, udev, scripted systemctl call, ...).\n");
4863
4864 finish:
4865 unit_file_changes_free(changes, n_changes);
4866
4867 return r;
4868 }
4869
4870 static int unit_is_enabled(sd_bus *bus, char **args) {
4871
4872 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4873 _cleanup_strv_free_ char **names = NULL;
4874 bool enabled;
4875 char **name;
4876 int r;
4877
4878 r = mangle_names(args+1, &names);
4879 if (r < 0)
4880 return r;
4881
4882 r = enable_sysv_units(args[0], names);
4883 if (r < 0)
4884 return r;
4885
4886 enabled = r > 0;
4887
4888 if (!bus || avoid_bus()) {
4889
4890 STRV_FOREACH(name, names) {
4891 UnitFileState state;
4892
4893 state = unit_file_get_state(arg_scope, arg_root, *name);
4894 if (state < 0) {
4895 log_error("Failed to get unit file state for %s: %s", *name, strerror(-state));
4896 return state;
4897 }
4898
4899 if (state == UNIT_FILE_ENABLED ||
4900 state == UNIT_FILE_ENABLED_RUNTIME ||
4901 state == UNIT_FILE_STATIC)
4902 enabled = true;
4903
4904 if (!arg_quiet)
4905 puts(unit_file_state_to_string(state));
4906 }
4907
4908 } else {
4909 STRV_FOREACH(name, names) {
4910 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4911 const char *s;
4912
4913 r = sd_bus_call_method(
4914 bus,
4915 "org.freedesktop.systemd1",
4916 "/org/freedesktop/systemd1",
4917 "org.freedesktop.systemd1.Manager",
4918 "GetUnitFileState",
4919 &error,
4920 &reply,
4921 "s", *name);
4922 if (r < 0) {
4923 log_error("Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
4924 return r;
4925 }
4926
4927 r = sd_bus_message_read(reply, "s", &s);
4928 if (r < 0)
4929 return bus_log_parse_error(r);
4930
4931 if (streq(s, "enabled") ||
4932 streq(s, "enabled-runtime") ||
4933 streq(s, "static"))
4934 enabled = true;
4935
4936 if (!arg_quiet)
4937 puts(s);
4938 }
4939 }
4940
4941 return !enabled;
4942 }
4943
4944 static int systemctl_help(void) {
4945
4946 pager_open_if_enabled();
4947
4948 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4949 "Query or send control commands to the systemd manager.\n\n"
4950 " -h --help Show this help\n"
4951 " --version Show package version\n"
4952 " --system Connect to system manager\n"
4953 " --user Connect to user service manager\n"
4954 " -H --host=[USER@]HOST\n"
4955 " Operate on remote host\n"
4956 " -M --machine=CONTAINER\n"
4957 " Operate on local container\n"
4958 " -t --type=TYPE List only units of a particular type\n"
4959 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
4960 " -p --property=NAME Show only properties by this name\n"
4961 " -a --all Show all loaded units/properties, including dead/empty\n"
4962 " ones. To list all units installed on the system, use\n"
4963 " the 'list-unit-files' command instead.\n"
4964 " -l --full Don't ellipsize unit names on output\n"
4965 " --reverse Show reverse dependencies with 'list-dependencies'\n"
4966 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
4967 " queueing a new job\n"
4968 " --show-types When showing sockets, explicitly show their type\n"
4969 " -i --ignore-inhibitors\n"
4970 " When shutting down or sleeping, ignore inhibitors\n"
4971 " --kill-who=WHO Who to send signal to\n"
4972 " -s --signal=SIGNAL Which signal to send\n"
4973 " -q --quiet Suppress output\n"
4974 " --no-block Do not wait until operation finished\n"
4975 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4976 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4977 " configuration\n"
4978 " --no-legend Do not print a legend (column headers and hints)\n"
4979 " --no-pager Do not pipe output into a pager\n"
4980 " --no-ask-password\n"
4981 " Do not ask for system passwords\n"
4982 " --global Enable/disable unit files globally\n"
4983 " --runtime Enable unit files only temporarily until next reboot\n"
4984 " -f --force When enabling unit files, override existing symlinks\n"
4985 " When shutting down, execute action immediately\n"
4986 " --root=PATH Enable unit files in the specified root directory\n"
4987 " -n --lines=INTEGER Number of journal entries to show\n"
4988 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4989 " verbose, export, json, json-pretty, json-sse, cat)\n"
4990 " --plain Print unit dependencies as a list instead of a tree\n\n"
4991 "Unit Commands:\n"
4992 " list-units [PATTERN...] List loaded units\n"
4993 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
4994 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
4995 " start NAME... Start (activate) one or more units\n"
4996 " stop NAME... Stop (deactivate) one or more units\n"
4997 " reload NAME... Reload one or more units\n"
4998 " restart NAME... Start or restart one or more units\n"
4999 " try-restart NAME... Restart one or more units if active\n"
5000 " reload-or-restart NAME... Reload one or more units if possible,\n"
5001 " otherwise start or restart\n"
5002 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
5003 " otherwise restart if active\n"
5004 " isolate NAME Start one unit and stop all others\n"
5005 " kill NAME... Send signal to processes of a unit\n"
5006 " is-active NAME... Check whether units are active\n"
5007 " is-failed NAME... Check whether units are failed\n"
5008 " status [NAME...|PID...] Show runtime status of one or more units\n"
5009 " show [NAME...|JOB...] Show properties of one or more\n"
5010 " units/jobs or the manager\n"
5011 " cat NAME... Show files and drop-ins of one or more units\n"
5012 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
5013 " help NAME...|PID... Show manual for one or more units\n"
5014 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
5015 " units\n"
5016 " list-dependencies [NAME] Recursively show units which are required\n"
5017 " or wanted by this unit or by which this\n"
5018 " unit is required or wanted\n\n"
5019 "Unit File Commands:\n"
5020 " list-unit-files [PATTERN...] List installed unit files\n"
5021 " enable NAME... Enable one or more unit files\n"
5022 " disable NAME... Disable one or more unit files\n"
5023 " reenable NAME... Reenable one or more unit files\n"
5024 " preset NAME... Enable/disable one or more unit files\n"
5025 " based on preset configuration\n"
5026 " is-enabled NAME... Check whether unit files are enabled\n\n"
5027 " mask NAME... Mask one or more units\n"
5028 " unmask NAME... Unmask one or more units\n"
5029 " link PATH... Link one or more units files into\n"
5030 " the search path\n"
5031 " get-default Get the name of the default target\n"
5032 " set-default NAME Set the default target\n\n"
5033 "Job Commands:\n"
5034 " list-jobs [PATTERN...] List jobs\n"
5035 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
5036 "Snapshot Commands:\n"
5037 " snapshot [NAME] Create a snapshot\n"
5038 " delete NAME... Remove one or more snapshots\n\n"
5039 "Environment Commands:\n"
5040 " show-environment Dump environment\n"
5041 " set-environment NAME=VALUE... Set one or more environment variables\n"
5042 " unset-environment NAME... Unset one or more environment variables\n"
5043 " import-environment NAME... Import all, one or more environment variables\n\n"
5044 "Manager Lifecycle Commands:\n"
5045 " daemon-reload Reload systemd manager configuration\n"
5046 " daemon-reexec Reexecute systemd manager\n\n"
5047 "System Commands:\n"
5048 " default Enter system default mode\n"
5049 " rescue Enter system rescue mode\n"
5050 " emergency Enter system emergency mode\n"
5051 " halt Shut down and halt the system\n"
5052 " poweroff Shut down and power-off the system\n"
5053 " reboot [ARG] Shut down and reboot the system\n"
5054 " kexec Shut down and reboot the system with kexec\n"
5055 " exit Request user instance exit\n"
5056 " switch-root ROOT [INIT] Change to a different root file system\n"
5057 " suspend Suspend the system\n"
5058 " hibernate Hibernate the system\n"
5059 " hybrid-sleep Hibernate and suspend the system\n",
5060 program_invocation_short_name);
5061
5062 return 0;
5063 }
5064
5065 static int halt_help(void) {
5066
5067 printf("%s [OPTIONS...]%s\n\n"
5068 "%s the system.\n\n"
5069 " --help Show this help\n"
5070 " --halt Halt the machine\n"
5071 " -p --poweroff Switch off the machine\n"
5072 " --reboot Reboot the machine\n"
5073 " -f --force Force immediate halt/power-off/reboot\n"
5074 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
5075 " -d --no-wtmp Don't write wtmp record\n"
5076 " --no-wall Don't send wall message before halt/power-off/reboot\n",
5077 program_invocation_short_name,
5078 arg_action == ACTION_REBOOT ? " [ARG]" : "",
5079 arg_action == ACTION_REBOOT ? "Reboot" :
5080 arg_action == ACTION_POWEROFF ? "Power off" :
5081 "Halt");
5082
5083 return 0;
5084 }
5085
5086 static int shutdown_help(void) {
5087
5088 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
5089 "Shut down the system.\n\n"
5090 " --help Show this help\n"
5091 " -H --halt Halt the machine\n"
5092 " -P --poweroff Power-off the machine\n"
5093 " -r --reboot Reboot the machine\n"
5094 " -h Equivalent to --poweroff, overridden by --halt\n"
5095 " -k Don't halt/power-off/reboot, just send warnings\n"
5096 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5097 " -c Cancel a pending shutdown\n",
5098 program_invocation_short_name);
5099
5100 return 0;
5101 }
5102
5103 static int telinit_help(void) {
5104
5105 printf("%s [OPTIONS...] {COMMAND}\n\n"
5106 "Send control commands to the init daemon.\n\n"
5107 " --help Show this help\n"
5108 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
5109 "Commands:\n"
5110 " 0 Power-off the machine\n"
5111 " 6 Reboot the machine\n"
5112 " 2, 3, 4, 5 Start runlevelX.target unit\n"
5113 " 1, s, S Enter rescue mode\n"
5114 " q, Q Reload init daemon configuration\n"
5115 " u, U Reexecute init daemon\n",
5116 program_invocation_short_name);
5117
5118 return 0;
5119 }
5120
5121 static int runlevel_help(void) {
5122
5123 printf("%s [OPTIONS...]\n\n"
5124 "Prints the previous and current runlevel of the init system.\n\n"
5125 " --help Show this help\n",
5126 program_invocation_short_name);
5127
5128 return 0;
5129 }
5130
5131 static int help_types(void) {
5132 int i;
5133 const char *t;
5134
5135 puts("Available unit types:");
5136 for (i = 0; i < _UNIT_TYPE_MAX; i++) {
5137 t = unit_type_to_string(i);
5138 if (t)
5139 puts(t);
5140 }
5141
5142 return 0;
5143 }
5144
5145 static int systemctl_parse_argv(int argc, char *argv[]) {
5146
5147 enum {
5148 ARG_FAIL = 0x100,
5149 ARG_REVERSE,
5150 ARG_AFTER,
5151 ARG_BEFORE,
5152 ARG_SHOW_TYPES,
5153 ARG_IRREVERSIBLE,
5154 ARG_IGNORE_DEPENDENCIES,
5155 ARG_VERSION,
5156 ARG_USER,
5157 ARG_SYSTEM,
5158 ARG_GLOBAL,
5159 ARG_NO_BLOCK,
5160 ARG_NO_LEGEND,
5161 ARG_NO_PAGER,
5162 ARG_NO_WALL,
5163 ARG_ROOT,
5164 ARG_NO_RELOAD,
5165 ARG_KILL_WHO,
5166 ARG_NO_ASK_PASSWORD,
5167 ARG_FAILED,
5168 ARG_RUNTIME,
5169 ARG_FORCE,
5170 ARG_PLAIN,
5171 ARG_STATE,
5172 ARG_JOB_MODE
5173 };
5174
5175 static const struct option options[] = {
5176 { "help", no_argument, NULL, 'h' },
5177 { "version", no_argument, NULL, ARG_VERSION },
5178 { "type", required_argument, NULL, 't' },
5179 { "property", required_argument, NULL, 'p' },
5180 { "all", no_argument, NULL, 'a' },
5181 { "reverse", no_argument, NULL, ARG_REVERSE },
5182 { "after", no_argument, NULL, ARG_AFTER },
5183 { "before", no_argument, NULL, ARG_BEFORE },
5184 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
5185 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
5186 { "full", no_argument, NULL, 'l' },
5187 { "job-mode", required_argument, NULL, ARG_JOB_MODE },
5188 { "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */
5189 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */
5190 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
5191 { "ignore-inhibitors", no_argument, NULL, 'i' },
5192 { "user", no_argument, NULL, ARG_USER },
5193 { "system", no_argument, NULL, ARG_SYSTEM },
5194 { "global", no_argument, NULL, ARG_GLOBAL },
5195 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
5196 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
5197 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
5198 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5199 { "quiet", no_argument, NULL, 'q' },
5200 { "root", required_argument, NULL, ARG_ROOT },
5201 { "force", no_argument, NULL, ARG_FORCE },
5202 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
5203 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
5204 { "signal", required_argument, NULL, 's' },
5205 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
5206 { "host", required_argument, NULL, 'H' },
5207 { "machine", required_argument, NULL, 'M' },
5208 { "runtime", no_argument, NULL, ARG_RUNTIME },
5209 { "lines", required_argument, NULL, 'n' },
5210 { "output", required_argument, NULL, 'o' },
5211 { "plain", no_argument, NULL, ARG_PLAIN },
5212 { "state", required_argument, NULL, ARG_STATE },
5213 {}
5214 };
5215
5216 int c;
5217
5218 assert(argc >= 0);
5219 assert(argv);
5220
5221 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:i", options, NULL)) >= 0) {
5222
5223 switch (c) {
5224
5225 case 'h':
5226 return systemctl_help();
5227
5228 case ARG_VERSION:
5229 puts(PACKAGE_STRING);
5230 puts(SYSTEMD_FEATURES);
5231 return 0;
5232
5233 case 't': {
5234 char *word, *state;
5235 size_t size;
5236
5237 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5238 _cleanup_free_ char *type;
5239
5240 type = strndup(word, size);
5241 if (!type)
5242 return -ENOMEM;
5243
5244 if (streq(type, "help")) {
5245 help_types();
5246 return 0;
5247 }
5248
5249 if (unit_type_from_string(type) >= 0) {
5250 if (strv_push(&arg_types, type))
5251 return log_oom();
5252 type = NULL;
5253 continue;
5254 }
5255
5256 /* It's much nicer to use --state= for
5257 * load states, but let's support this
5258 * in --types= too for compatibility
5259 * with old versions */
5260 if (unit_load_state_from_string(optarg) >= 0) {
5261 if (strv_push(&arg_states, type) < 0)
5262 return log_oom();
5263 type = NULL;
5264 continue;
5265 }
5266
5267 log_error("Unknown unit type or load state '%s'.", type);
5268 log_info("Use -t help to see a list of allowed values.");
5269 return -EINVAL;
5270 }
5271
5272 break;
5273 }
5274
5275 case 'p': {
5276 /* Make sure that if the empty property list
5277 was specified, we won't show any properties. */
5278 if (isempty(optarg) && !arg_properties) {
5279 arg_properties = new0(char*, 1);
5280 if (!arg_properties)
5281 return log_oom();
5282 } else {
5283 char *word, *state;
5284 size_t size;
5285
5286 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5287 char *prop;
5288
5289 prop = strndup(word, size);
5290 if (!prop)
5291 return log_oom();
5292
5293 if (strv_push(&arg_properties, prop) < 0) {
5294 free(prop);
5295 return log_oom();
5296 }
5297 }
5298 }
5299
5300 /* If the user asked for a particular
5301 * property, show it to him, even if it is
5302 * empty. */
5303 arg_all = true;
5304
5305 break;
5306 }
5307
5308 case 'a':
5309 arg_all = true;
5310 break;
5311
5312 case ARG_REVERSE:
5313 arg_dependency = DEPENDENCY_REVERSE;
5314 break;
5315
5316 case ARG_AFTER:
5317 arg_dependency = DEPENDENCY_AFTER;
5318 break;
5319
5320 case ARG_BEFORE:
5321 arg_dependency = DEPENDENCY_BEFORE;
5322 break;
5323
5324 case ARG_SHOW_TYPES:
5325 arg_show_types = true;
5326 break;
5327
5328 case ARG_JOB_MODE:
5329 arg_job_mode = optarg;
5330 break;
5331
5332 case ARG_FAIL:
5333 arg_job_mode = "fail";
5334 break;
5335
5336 case ARG_IRREVERSIBLE:
5337 arg_job_mode = "replace-irreversibly";
5338 break;
5339
5340 case ARG_IGNORE_DEPENDENCIES:
5341 arg_job_mode = "ignore-dependencies";
5342 break;
5343
5344 case ARG_USER:
5345 arg_scope = UNIT_FILE_USER;
5346 break;
5347
5348 case ARG_SYSTEM:
5349 arg_scope = UNIT_FILE_SYSTEM;
5350 break;
5351
5352 case ARG_GLOBAL:
5353 arg_scope = UNIT_FILE_GLOBAL;
5354 break;
5355
5356 case ARG_NO_BLOCK:
5357 arg_no_block = true;
5358 break;
5359
5360 case ARG_NO_LEGEND:
5361 arg_no_legend = true;
5362 break;
5363
5364 case ARG_NO_PAGER:
5365 arg_no_pager = true;
5366 break;
5367
5368 case ARG_NO_WALL:
5369 arg_no_wall = true;
5370 break;
5371
5372 case ARG_ROOT:
5373 arg_root = optarg;
5374 break;
5375
5376 case 'l':
5377 arg_full = true;
5378 break;
5379
5380 case ARG_FAILED:
5381 if (strv_extend(&arg_states, "failed") < 0)
5382 return log_oom();
5383
5384 break;
5385
5386 case 'q':
5387 arg_quiet = true;
5388 break;
5389
5390 case ARG_FORCE:
5391 arg_force ++;
5392 break;
5393
5394 case 'f':
5395 arg_force ++;
5396 break;
5397
5398 case ARG_NO_RELOAD:
5399 arg_no_reload = true;
5400 break;
5401
5402 case ARG_KILL_WHO:
5403 arg_kill_who = optarg;
5404 break;
5405
5406 case 's':
5407 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
5408 log_error("Failed to parse signal string %s.", optarg);
5409 return -EINVAL;
5410 }
5411 break;
5412
5413 case ARG_NO_ASK_PASSWORD:
5414 arg_ask_password = false;
5415 break;
5416
5417 case 'H':
5418 arg_transport = BUS_TRANSPORT_REMOTE;
5419 arg_host = optarg;
5420 break;
5421
5422 case 'M':
5423 arg_transport = BUS_TRANSPORT_CONTAINER;
5424 arg_host = optarg;
5425 break;
5426
5427 case ARG_RUNTIME:
5428 arg_runtime = true;
5429 break;
5430
5431 case 'n':
5432 if (safe_atou(optarg, &arg_lines) < 0) {
5433 log_error("Failed to parse lines '%s'", optarg);
5434 return -EINVAL;
5435 }
5436 break;
5437
5438 case 'o':
5439 arg_output = output_mode_from_string(optarg);
5440 if (arg_output < 0) {
5441 log_error("Unknown output '%s'.", optarg);
5442 return -EINVAL;
5443 }
5444 break;
5445
5446 case 'i':
5447 arg_ignore_inhibitors = true;
5448 break;
5449
5450 case ARG_PLAIN:
5451 arg_plain = true;
5452 break;
5453
5454 case ARG_STATE: {
5455 char *word, *state;
5456 size_t size;
5457
5458 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5459 char *s;
5460
5461 s = strndup(word, size);
5462 if (!s)
5463 return log_oom();
5464
5465 if (strv_push(&arg_states, s) < 0) {
5466 free(s);
5467 return log_oom();
5468 }
5469 }
5470 break;
5471 }
5472
5473 case '?':
5474 return -EINVAL;
5475
5476 default:
5477 assert_not_reached("Unhandled option");
5478 }
5479 }
5480
5481 if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM) {
5482 log_error("Cannot access user instance remotely.");
5483 return -EINVAL;
5484 }
5485
5486 return 1;
5487 }
5488
5489 static int halt_parse_argv(int argc, char *argv[]) {
5490
5491 enum {
5492 ARG_HELP = 0x100,
5493 ARG_HALT,
5494 ARG_REBOOT,
5495 ARG_NO_WALL
5496 };
5497
5498 static const struct option options[] = {
5499 { "help", no_argument, NULL, ARG_HELP },
5500 { "halt", no_argument, NULL, ARG_HALT },
5501 { "poweroff", no_argument, NULL, 'p' },
5502 { "reboot", no_argument, NULL, ARG_REBOOT },
5503 { "force", no_argument, NULL, 'f' },
5504 { "wtmp-only", no_argument, NULL, 'w' },
5505 { "no-wtmp", no_argument, NULL, 'd' },
5506 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5507 {}
5508 };
5509
5510 int c, r, runlevel;
5511
5512 assert(argc >= 0);
5513 assert(argv);
5514
5515 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
5516 if (runlevel == '0' || runlevel == '6')
5517 arg_force = 2;
5518
5519 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
5520 switch (c) {
5521
5522 case ARG_HELP:
5523 return halt_help();
5524
5525 case ARG_HALT:
5526 arg_action = ACTION_HALT;
5527 break;
5528
5529 case 'p':
5530 if (arg_action != ACTION_REBOOT)
5531 arg_action = ACTION_POWEROFF;
5532 break;
5533
5534 case ARG_REBOOT:
5535 arg_action = ACTION_REBOOT;
5536 break;
5537
5538 case 'f':
5539 arg_force = 2;
5540 break;
5541
5542 case 'w':
5543 arg_dry = true;
5544 break;
5545
5546 case 'd':
5547 arg_no_wtmp = true;
5548 break;
5549
5550 case ARG_NO_WALL:
5551 arg_no_wall = true;
5552 break;
5553
5554 case 'i':
5555 case 'h':
5556 case 'n':
5557 /* Compatibility nops */
5558 break;
5559
5560 case '?':
5561 return -EINVAL;
5562
5563 default:
5564 assert_not_reached("Unhandled option");
5565 }
5566 }
5567
5568 if (arg_action == ACTION_REBOOT && argc == optind + 1) {
5569 r = write_string_file(REBOOT_PARAM_FILE, argv[optind]);
5570 if (r < 0) {
5571 log_error("Failed to write reboot param to "
5572 REBOOT_PARAM_FILE": %s", strerror(-r));
5573 return r;
5574 }
5575 } else if (optind < argc) {
5576 log_error("Too many arguments.");
5577 return -EINVAL;
5578 }
5579
5580 return 1;
5581 }
5582
5583 static int parse_time_spec(const char *t, usec_t *_u) {
5584 assert(t);
5585 assert(_u);
5586
5587 if (streq(t, "now"))
5588 *_u = 0;
5589 else if (!strchr(t, ':')) {
5590 uint64_t u;
5591
5592 if (safe_atou64(t, &u) < 0)
5593 return -EINVAL;
5594
5595 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
5596 } else {
5597 char *e = NULL;
5598 long hour, minute;
5599 struct tm tm = {};
5600 time_t s;
5601 usec_t n;
5602
5603 errno = 0;
5604 hour = strtol(t, &e, 10);
5605 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
5606 return -EINVAL;
5607
5608 minute = strtol(e+1, &e, 10);
5609 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
5610 return -EINVAL;
5611
5612 n = now(CLOCK_REALTIME);
5613 s = (time_t) (n / USEC_PER_SEC);
5614
5615 assert_se(localtime_r(&s, &tm));
5616
5617 tm.tm_hour = (int) hour;
5618 tm.tm_min = (int) minute;
5619 tm.tm_sec = 0;
5620
5621 assert_se(s = mktime(&tm));
5622
5623 *_u = (usec_t) s * USEC_PER_SEC;
5624
5625 while (*_u <= n)
5626 *_u += USEC_PER_DAY;
5627 }
5628
5629 return 0;
5630 }
5631
5632 static int shutdown_parse_argv(int argc, char *argv[]) {
5633
5634 enum {
5635 ARG_HELP = 0x100,
5636 ARG_NO_WALL
5637 };
5638
5639 static const struct option options[] = {
5640 { "help", no_argument, NULL, ARG_HELP },
5641 { "halt", no_argument, NULL, 'H' },
5642 { "poweroff", no_argument, NULL, 'P' },
5643 { "reboot", no_argument, NULL, 'r' },
5644 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
5645 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5646 {}
5647 };
5648
5649 int c, r;
5650
5651 assert(argc >= 0);
5652 assert(argv);
5653
5654 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
5655 switch (c) {
5656
5657 case ARG_HELP:
5658 return shutdown_help();
5659
5660 case 'H':
5661 arg_action = ACTION_HALT;
5662 break;
5663
5664 case 'P':
5665 arg_action = ACTION_POWEROFF;
5666 break;
5667
5668 case 'r':
5669 if (kexec_loaded())
5670 arg_action = ACTION_KEXEC;
5671 else
5672 arg_action = ACTION_REBOOT;
5673 break;
5674
5675 case 'K':
5676 arg_action = ACTION_KEXEC;
5677 break;
5678
5679 case 'h':
5680 if (arg_action != ACTION_HALT)
5681 arg_action = ACTION_POWEROFF;
5682 break;
5683
5684 case 'k':
5685 arg_dry = true;
5686 break;
5687
5688 case ARG_NO_WALL:
5689 arg_no_wall = true;
5690 break;
5691
5692 case 't':
5693 case 'a':
5694 /* Compatibility nops */
5695 break;
5696
5697 case 'c':
5698 arg_action = ACTION_CANCEL_SHUTDOWN;
5699 break;
5700
5701 case '?':
5702 return -EINVAL;
5703
5704 default:
5705 assert_not_reached("Unhandled option");
5706 }
5707 }
5708
5709 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
5710 r = parse_time_spec(argv[optind], &arg_when);
5711 if (r < 0) {
5712 log_error("Failed to parse time specification: %s", argv[optind]);
5713 return r;
5714 }
5715 } else
5716 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
5717
5718 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
5719 /* No time argument for shutdown cancel */
5720 arg_wall = argv + optind;
5721 else if (argc > optind + 1)
5722 /* We skip the time argument */
5723 arg_wall = argv + optind + 1;
5724
5725 optind = argc;
5726
5727 return 1;
5728 }
5729
5730 static int telinit_parse_argv(int argc, char *argv[]) {
5731
5732 enum {
5733 ARG_HELP = 0x100,
5734 ARG_NO_WALL
5735 };
5736
5737 static const struct option options[] = {
5738 { "help", no_argument, NULL, ARG_HELP },
5739 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5740 {}
5741 };
5742
5743 static const struct {
5744 char from;
5745 enum action to;
5746 } table[] = {
5747 { '0', ACTION_POWEROFF },
5748 { '6', ACTION_REBOOT },
5749 { '1', ACTION_RESCUE },
5750 { '2', ACTION_RUNLEVEL2 },
5751 { '3', ACTION_RUNLEVEL3 },
5752 { '4', ACTION_RUNLEVEL4 },
5753 { '5', ACTION_RUNLEVEL5 },
5754 { 's', ACTION_RESCUE },
5755 { 'S', ACTION_RESCUE },
5756 { 'q', ACTION_RELOAD },
5757 { 'Q', ACTION_RELOAD },
5758 { 'u', ACTION_REEXEC },
5759 { 'U', ACTION_REEXEC }
5760 };
5761
5762 unsigned i;
5763 int c;
5764
5765 assert(argc >= 0);
5766 assert(argv);
5767
5768 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5769 switch (c) {
5770
5771 case ARG_HELP:
5772 return telinit_help();
5773
5774 case ARG_NO_WALL:
5775 arg_no_wall = true;
5776 break;
5777
5778 case '?':
5779 return -EINVAL;
5780
5781 default:
5782 assert_not_reached("Unhandled option");
5783 }
5784 }
5785
5786 if (optind >= argc) {
5787 telinit_help();
5788 return -EINVAL;
5789 }
5790
5791 if (optind + 1 < argc) {
5792 log_error("Too many arguments.");
5793 return -EINVAL;
5794 }
5795
5796 if (strlen(argv[optind]) != 1) {
5797 log_error("Expected single character argument.");
5798 return -EINVAL;
5799 }
5800
5801 for (i = 0; i < ELEMENTSOF(table); i++)
5802 if (table[i].from == argv[optind][0])
5803 break;
5804
5805 if (i >= ELEMENTSOF(table)) {
5806 log_error("Unknown command '%s'.", argv[optind]);
5807 return -EINVAL;
5808 }
5809
5810 arg_action = table[i].to;
5811
5812 optind ++;
5813
5814 return 1;
5815 }
5816
5817 static int runlevel_parse_argv(int argc, char *argv[]) {
5818
5819 enum {
5820 ARG_HELP = 0x100,
5821 };
5822
5823 static const struct option options[] = {
5824 { "help", no_argument, NULL, ARG_HELP },
5825 {}
5826 };
5827
5828 int c;
5829
5830 assert(argc >= 0);
5831 assert(argv);
5832
5833 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5834 switch (c) {
5835
5836 case ARG_HELP:
5837 return runlevel_help();
5838 return 0;
5839
5840 case '?':
5841 return -EINVAL;
5842
5843 default:
5844 assert_not_reached("Unhandled option");
5845 }
5846 }
5847
5848 if (optind < argc) {
5849 log_error("Too many arguments.");
5850 return -EINVAL;
5851 }
5852
5853 return 1;
5854 }
5855
5856 static int parse_argv(int argc, char *argv[]) {
5857 assert(argc >= 0);
5858 assert(argv);
5859
5860 if (program_invocation_short_name) {
5861
5862 if (strstr(program_invocation_short_name, "halt")) {
5863 arg_action = ACTION_HALT;
5864 return halt_parse_argv(argc, argv);
5865 } else if (strstr(program_invocation_short_name, "poweroff")) {
5866 arg_action = ACTION_POWEROFF;
5867 return halt_parse_argv(argc, argv);
5868 } else if (strstr(program_invocation_short_name, "reboot")) {
5869 if (kexec_loaded())
5870 arg_action = ACTION_KEXEC;
5871 else
5872 arg_action = ACTION_REBOOT;
5873 return halt_parse_argv(argc, argv);
5874 } else if (strstr(program_invocation_short_name, "shutdown")) {
5875 arg_action = ACTION_POWEROFF;
5876 return shutdown_parse_argv(argc, argv);
5877 } else if (strstr(program_invocation_short_name, "init")) {
5878
5879 if (sd_booted() > 0) {
5880 arg_action = _ACTION_INVALID;
5881 return telinit_parse_argv(argc, argv);
5882 } else {
5883 /* Hmm, so some other init system is
5884 * running, we need to forward this
5885 * request to it. For now we simply
5886 * guess that it is Upstart. */
5887
5888 execv(TELINIT, argv);
5889
5890 log_error("Couldn't find an alternative telinit implementation to spawn.");
5891 return -EIO;
5892 }
5893
5894 } else if (strstr(program_invocation_short_name, "runlevel")) {
5895 arg_action = ACTION_RUNLEVEL;
5896 return runlevel_parse_argv(argc, argv);
5897 }
5898 }
5899
5900 arg_action = ACTION_SYSTEMCTL;
5901 return systemctl_parse_argv(argc, argv);
5902 }
5903
5904 _pure_ static int action_to_runlevel(void) {
5905
5906 static const char table[_ACTION_MAX] = {
5907 [ACTION_HALT] = '0',
5908 [ACTION_POWEROFF] = '0',
5909 [ACTION_REBOOT] = '6',
5910 [ACTION_RUNLEVEL2] = '2',
5911 [ACTION_RUNLEVEL3] = '3',
5912 [ACTION_RUNLEVEL4] = '4',
5913 [ACTION_RUNLEVEL5] = '5',
5914 [ACTION_RESCUE] = '1'
5915 };
5916
5917 assert(arg_action < _ACTION_MAX);
5918
5919 return table[arg_action];
5920 }
5921
5922 static int talk_initctl(void) {
5923
5924 struct init_request request = {
5925 .magic = INIT_MAGIC,
5926 .sleeptime = 0,
5927 .cmd = INIT_CMD_RUNLVL
5928 };
5929
5930 _cleanup_close_ int fd = -1;
5931 char rl;
5932 int r;
5933
5934 rl = action_to_runlevel();
5935 if (!rl)
5936 return 0;
5937
5938 request.runlevel = rl;
5939
5940 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
5941 if (fd < 0) {
5942 if (errno == ENOENT)
5943 return 0;
5944
5945 log_error("Failed to open "INIT_FIFO": %m");
5946 return -errno;
5947 }
5948
5949 errno = 0;
5950 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5951 if (r) {
5952 log_error("Failed to write to "INIT_FIFO": %m");
5953 return errno > 0 ? -errno : -EIO;
5954 }
5955
5956 return 1;
5957 }
5958
5959 static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
5960
5961 static const struct {
5962 const char* verb;
5963 const enum {
5964 MORE,
5965 LESS,
5966 EQUAL
5967 } argc_cmp;
5968 const int argc;
5969 int (* const dispatch)(sd_bus *bus, char **args);
5970 const enum {
5971 NOBUS = 1,
5972 FORCE,
5973 } bus;
5974 } verbs[] = {
5975 { "list-units", MORE, 0, list_units },
5976 { "list-unit-files", MORE, 1, list_unit_files, NOBUS },
5977 { "list-sockets", MORE, 1, list_sockets },
5978 { "list-timers", MORE, 1, list_timers },
5979 { "list-jobs", MORE, 1, list_jobs },
5980 { "clear-jobs", EQUAL, 1, daemon_reload },
5981 { "cancel", MORE, 2, cancel_job },
5982 { "start", MORE, 2, start_unit },
5983 { "stop", MORE, 2, start_unit },
5984 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5985 { "reload", MORE, 2, start_unit },
5986 { "restart", MORE, 2, start_unit },
5987 { "try-restart", MORE, 2, start_unit },
5988 { "reload-or-restart", MORE, 2, start_unit },
5989 { "reload-or-try-restart", MORE, 2, start_unit },
5990 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5991 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5992 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5993 { "isolate", EQUAL, 2, start_unit },
5994 { "kill", MORE, 2, kill_unit },
5995 { "is-active", MORE, 2, check_unit_active },
5996 { "check", MORE, 2, check_unit_active },
5997 { "is-failed", MORE, 2, check_unit_failed },
5998 { "show", MORE, 1, show },
5999 { "cat", MORE, 2, cat },
6000 { "status", MORE, 1, show },
6001 { "help", MORE, 2, show },
6002 { "snapshot", LESS, 2, snapshot },
6003 { "delete", MORE, 2, delete_snapshot },
6004 { "daemon-reload", EQUAL, 1, daemon_reload },
6005 { "daemon-reexec", EQUAL, 1, daemon_reload },
6006 { "show-environment", EQUAL, 1, show_environment },
6007 { "set-environment", MORE, 2, set_environment },
6008 { "unset-environment", MORE, 2, set_environment },
6009 { "import-environment", MORE, 1, import_environment},
6010 { "halt", EQUAL, 1, start_special, FORCE },
6011 { "poweroff", EQUAL, 1, start_special, FORCE },
6012 { "reboot", EQUAL, 1, start_special, FORCE },
6013 { "kexec", EQUAL, 1, start_special },
6014 { "suspend", EQUAL, 1, start_special },
6015 { "hibernate", EQUAL, 1, start_special },
6016 { "hybrid-sleep", EQUAL, 1, start_special },
6017 { "default", EQUAL, 1, start_special },
6018 { "rescue", EQUAL, 1, start_special },
6019 { "emergency", EQUAL, 1, start_special },
6020 { "exit", EQUAL, 1, start_special },
6021 { "reset-failed", MORE, 1, reset_failed },
6022 { "enable", MORE, 2, enable_unit, NOBUS },
6023 { "disable", MORE, 2, enable_unit, NOBUS },
6024 { "is-enabled", MORE, 2, unit_is_enabled, NOBUS },
6025 { "reenable", MORE, 2, enable_unit, NOBUS },
6026 { "preset", MORE, 2, enable_unit, NOBUS },
6027 { "mask", MORE, 2, enable_unit, NOBUS },
6028 { "unmask", MORE, 2, enable_unit, NOBUS },
6029 { "link", MORE, 2, enable_unit, NOBUS },
6030 { "switch-root", MORE, 2, switch_root },
6031 { "list-dependencies", LESS, 2, list_dependencies },
6032 { "set-default", EQUAL, 2, set_default, NOBUS },
6033 { "get-default", EQUAL, 1, get_default, NOBUS },
6034 { "set-property", MORE, 3, set_property },
6035 {}
6036 }, *verb = verbs;
6037
6038 int left;
6039
6040 assert(argc >= 0);
6041 assert(argv);
6042
6043 left = argc - optind;
6044
6045 /* Special rule: no arguments (left == 0) means "list-units" */
6046 if (left > 0) {
6047 if (streq(argv[optind], "help") && !argv[optind+1]) {
6048 log_error("This command expects one or more "
6049 "unit names. Did you mean --help?");
6050 return -EINVAL;
6051 }
6052
6053 for (; verb->verb; verb++)
6054 if (streq(argv[optind], verb->verb))
6055 goto found;
6056
6057 log_error("Unknown operation '%s'.", argv[optind]);
6058 return -EINVAL;
6059 }
6060 found:
6061
6062 switch (verb->argc_cmp) {
6063
6064 case EQUAL:
6065 if (left != verb->argc) {
6066 log_error("Invalid number of arguments.");
6067 return -EINVAL;
6068 }
6069
6070 break;
6071
6072 case MORE:
6073 if (left < verb->argc) {
6074 log_error("Too few arguments.");
6075 return -EINVAL;
6076 }
6077
6078 break;
6079
6080 case LESS:
6081 if (left > verb->argc) {
6082 log_error("Too many arguments.");
6083 return -EINVAL;
6084 }
6085
6086 break;
6087
6088 default:
6089 assert_not_reached("Unknown comparison operator.");
6090 }
6091
6092 /* Require a bus connection for all operations but
6093 * enable/disable */
6094 if (verb->bus == NOBUS) {
6095 if (!bus && !avoid_bus()) {
6096 log_error("Failed to get D-Bus connection: %s", strerror(-bus_error));
6097 return -EIO;
6098 }
6099
6100 } else {
6101 if (running_in_chroot() > 0) {
6102 log_info("Running in chroot, ignoring request.");
6103 return 0;
6104 }
6105
6106 if ((verb->bus != FORCE || arg_force <= 0) && !bus) {
6107 log_error("Failed to get D-Bus connection: %s", strerror(-bus_error));
6108 return -EIO;
6109 }
6110 }
6111
6112 return verb->dispatch(bus, argv + optind);
6113 }
6114
6115 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
6116
6117 struct sd_shutdown_command c = {
6118 .usec = t,
6119 .mode = mode,
6120 .dry_run = dry_run,
6121 .warn_wall = warn,
6122 };
6123
6124 union sockaddr_union sockaddr = {
6125 .un.sun_family = AF_UNIX,
6126 .un.sun_path = "/run/systemd/shutdownd",
6127 };
6128
6129 struct iovec iovec[2] = {{
6130 .iov_base = (char*) &c,
6131 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
6132 }};
6133
6134 struct msghdr msghdr = {
6135 .msg_name = &sockaddr,
6136 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
6137 + sizeof("/run/systemd/shutdownd") - 1,
6138 .msg_iov = iovec,
6139 .msg_iovlen = 1,
6140 };
6141
6142 _cleanup_close_ int fd;
6143
6144 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
6145 if (fd < 0)
6146 return -errno;
6147
6148 if (!isempty(message)) {
6149 iovec[1].iov_base = (char*) message;
6150 iovec[1].iov_len = strlen(message);
6151 msghdr.msg_iovlen++;
6152 }
6153
6154 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
6155 return -errno;
6156
6157 return 0;
6158 }
6159
6160 static int reload_with_fallback(sd_bus *bus) {
6161
6162 if (bus) {
6163 /* First, try systemd via D-Bus. */
6164 if (daemon_reload(bus, NULL) >= 0)
6165 return 0;
6166 }
6167
6168 /* Nothing else worked, so let's try signals */
6169 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
6170
6171 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
6172 log_error("kill() failed: %m");
6173 return -errno;
6174 }
6175
6176 return 0;
6177 }
6178
6179 static int start_with_fallback(sd_bus *bus) {
6180
6181 if (bus) {
6182 /* First, try systemd via D-Bus. */
6183 if (start_unit(bus, NULL) >= 0)
6184 goto done;
6185 }
6186
6187 /* Nothing else worked, so let's try
6188 * /dev/initctl */
6189 if (talk_initctl() > 0)
6190 goto done;
6191
6192 log_error("Failed to talk to init daemon.");
6193 return -EIO;
6194
6195 done:
6196 warn_wall(arg_action);
6197 return 0;
6198 }
6199
6200 static int halt_now(enum action a) {
6201
6202 /* Make sure C-A-D is handled by the kernel from this
6203 * point on... */
6204 reboot(RB_ENABLE_CAD);
6205
6206 switch (a) {
6207
6208 case ACTION_HALT:
6209 log_info("Halting.");
6210 reboot(RB_HALT_SYSTEM);
6211 return -errno;
6212
6213 case ACTION_POWEROFF:
6214 log_info("Powering off.");
6215 reboot(RB_POWER_OFF);
6216 return -errno;
6217
6218 case ACTION_REBOOT: {
6219 _cleanup_free_ char *param = NULL;
6220
6221 if (read_one_line_file(REBOOT_PARAM_FILE, &param) >= 0) {
6222 log_info("Rebooting with argument '%s'.", param);
6223 syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
6224 LINUX_REBOOT_CMD_RESTART2, param);
6225 }
6226
6227 log_info("Rebooting.");
6228 reboot(RB_AUTOBOOT);
6229 return -errno;
6230 }
6231
6232 default:
6233 assert_not_reached("Unknown action.");
6234 }
6235 }
6236
6237 static int halt_main(sd_bus *bus) {
6238 int r;
6239
6240 r = check_inhibitors(bus, arg_action);
6241 if (r < 0)
6242 return r;
6243
6244 if (geteuid() != 0) {
6245 /* Try logind if we are a normal user and no special
6246 * mode applies. Maybe PolicyKit allows us to shutdown
6247 * the machine. */
6248
6249 if (arg_when <= 0 &&
6250 !arg_dry &&
6251 arg_force <= 0 &&
6252 (arg_action == ACTION_POWEROFF ||
6253 arg_action == ACTION_REBOOT)) {
6254 r = reboot_with_logind(bus, arg_action);
6255 if (r >= 0)
6256 return r;
6257 }
6258
6259 log_error("Must be root.");
6260 return -EPERM;
6261 }
6262
6263 if (arg_when > 0) {
6264 _cleanup_free_ char *m;
6265
6266 m = strv_join(arg_wall, " ");
6267 if (!m)
6268 return log_oom();
6269
6270 r = send_shutdownd(arg_when,
6271 arg_action == ACTION_HALT ? 'H' :
6272 arg_action == ACTION_POWEROFF ? 'P' :
6273 arg_action == ACTION_KEXEC ? 'K' :
6274 'r',
6275 arg_dry,
6276 !arg_no_wall,
6277 m);
6278
6279 if (r < 0)
6280 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
6281 else {
6282 char date[FORMAT_TIMESTAMP_MAX];
6283
6284 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
6285 format_timestamp(date, sizeof(date), arg_when));
6286 return 0;
6287 }
6288 }
6289
6290 if (!arg_dry && !arg_force)
6291 return start_with_fallback(bus);
6292
6293 if (!arg_no_wtmp) {
6294 if (sd_booted() > 0)
6295 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
6296 else {
6297 r = utmp_put_shutdown();
6298 if (r < 0)
6299 log_warning("Failed to write utmp record: %s", strerror(-r));
6300 }
6301 }
6302
6303 if (arg_dry)
6304 return 0;
6305
6306 r = halt_now(arg_action);
6307 log_error("Failed to reboot: %s", strerror(-r));
6308
6309 return r;
6310 }
6311
6312 static int runlevel_main(void) {
6313 int r, runlevel, previous;
6314
6315 r = utmp_get_runlevel(&runlevel, &previous);
6316 if (r < 0) {
6317 puts("unknown");
6318 return r;
6319 }
6320
6321 printf("%c %c\n",
6322 previous <= 0 ? 'N' : previous,
6323 runlevel <= 0 ? 'N' : runlevel);
6324
6325 return 0;
6326 }
6327
6328 int main(int argc, char*argv[]) {
6329 _cleanup_bus_unref_ sd_bus *bus = NULL;
6330 int r;
6331
6332 setlocale(LC_ALL, "");
6333 log_parse_environment();
6334 log_open();
6335
6336 /* Explicitly not on_tty() to avoid setting cached value.
6337 * This becomes relevant for piping output which might be
6338 * ellipsized. */
6339 original_stdout_is_tty = isatty(STDOUT_FILENO);
6340
6341 r = parse_argv(argc, argv);
6342 if (r <= 0)
6343 goto finish;
6344
6345 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
6346 * let's shortcut this */
6347 if (arg_action == ACTION_RUNLEVEL) {
6348 r = runlevel_main();
6349 goto finish;
6350 }
6351
6352 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
6353 log_info("Running in chroot, ignoring request.");
6354 r = 0;
6355 goto finish;
6356 }
6357
6358 if (!avoid_bus())
6359 r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus);
6360
6361 /* systemctl_main() will print an error message for the bus
6362 * connection, but only if it needs to */
6363
6364 switch (arg_action) {
6365
6366 case ACTION_SYSTEMCTL:
6367 r = systemctl_main(bus, argc, argv, r);
6368 break;
6369
6370 case ACTION_HALT:
6371 case ACTION_POWEROFF:
6372 case ACTION_REBOOT:
6373 case ACTION_KEXEC:
6374 r = halt_main(bus);
6375 break;
6376
6377 case ACTION_RUNLEVEL2:
6378 case ACTION_RUNLEVEL3:
6379 case ACTION_RUNLEVEL4:
6380 case ACTION_RUNLEVEL5:
6381 case ACTION_RESCUE:
6382 case ACTION_EMERGENCY:
6383 case ACTION_DEFAULT:
6384 r = start_with_fallback(bus);
6385 break;
6386
6387 case ACTION_RELOAD:
6388 case ACTION_REEXEC:
6389 r = reload_with_fallback(bus);
6390 break;
6391
6392 case ACTION_CANCEL_SHUTDOWN: {
6393 _cleanup_free_ char *m = NULL;
6394
6395 if (arg_wall) {
6396 m = strv_join(arg_wall, " ");
6397 if (!m) {
6398 r = log_oom();
6399 goto finish;
6400 }
6401 }
6402
6403 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
6404 if (r < 0)
6405 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
6406 break;
6407 }
6408
6409 case ACTION_RUNLEVEL:
6410 case _ACTION_INVALID:
6411 default:
6412 assert_not_reached("Unknown action");
6413 }
6414
6415 finish:
6416 pager_close();
6417 ask_password_agent_close();
6418 polkit_agent_close();
6419
6420 strv_free(arg_types);
6421 strv_free(arg_states);
6422 strv_free(arg_properties);
6423
6424 return r < 0 ? EXIT_FAILURE : r;
6425 }