1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
7 Copyright 2013 Marc-Antoine Perennou
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.
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.
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/>.
23 #include <sys/reboot.h>
24 #include <linux/reboot.h>
25 #include <sys/syscall.h>
32 #include <sys/ioctl.h>
36 #include <sys/socket.h>
39 #include <sys/prctl.h>
42 #include "sd-daemon.h"
43 #include "sd-shutdown.h"
50 #include "utmp-wtmp.h"
53 #include "path-util.h"
55 #include "cgroup-show.h"
56 #include "cgroup-util.h"
58 #include "path-lookup.h"
59 #include "conf-parser.h"
60 #include "exit-status.h"
62 #include "unit-name.h"
64 #include "spawn-ask-password-agent.h"
65 #include "spawn-polkit-agent.h"
67 #include "logs-show.h"
68 #include "socket-util.h"
72 #include "bus-message.h"
73 #include "bus-error.h"
74 #include "bus-errors.h"
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 enum dependency
{
86 } arg_dependency
= DEPENDENCY_FORWARD
;
87 static const char *arg_job_mode
= "replace";
88 static UnitFileScope arg_scope
= UNIT_FILE_SYSTEM
;
89 static bool arg_no_block
= false;
90 static bool arg_no_legend
= false;
91 static bool arg_no_pager
= false;
92 static bool arg_no_wtmp
= false;
93 static bool arg_no_wall
= false;
94 static bool arg_no_reload
= false;
95 static bool arg_show_types
= false;
96 static bool arg_ignore_inhibitors
= false;
97 static bool arg_dry
= false;
98 static bool arg_quiet
= false;
99 static bool arg_full
= false;
100 static bool arg_recursive
= 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;
130 ACTION_CANCEL_SHUTDOWN
,
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;
139 static const struct {
143 { "start", "StartUnit" },
144 { "stop", "StopUnit" },
145 { "condstop", "StopUnit" },
146 { "reload", "ReloadUnit" },
147 { "restart", "RestartUnit" },
148 { "try-restart", "TryRestartUnit" },
149 { "condrestart", "TryRestartUnit" },
150 { "reload-or-restart", "ReloadOrRestartUnit" },
151 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
152 { "condreload", "ReloadOrTryRestartUnit" },
153 { "force-reload", "ReloadOrTryRestartUnit" }
156 static bool original_stdout_is_tty
;
158 static int daemon_reload(sd_bus
*bus
, char **args
);
159 static int halt_now(enum action a
);
160 static int check_one_unit(sd_bus
*bus
, const char *name
, const char *good_states
, bool quiet
);
162 static char** strv_skip_first(char **strv
) {
163 if (strv_length(strv
) > 0)
168 static void pager_open_if_enabled(void) {
176 static void ask_password_agent_open_if_enabled(void) {
178 /* Open the password agent as a child process if necessary */
180 if (!arg_ask_password
)
183 if (arg_scope
!= UNIT_FILE_SYSTEM
)
186 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
189 ask_password_agent_open();
193 static void polkit_agent_open_if_enabled(void) {
195 /* Open the polkit agent as a child process if necessary */
197 if (!arg_ask_password
)
200 if (arg_scope
!= UNIT_FILE_SYSTEM
)
203 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
210 static int translate_bus_error_to_exit_status(int r
, const sd_bus_error
*error
) {
213 if (!sd_bus_error_is_set(error
))
216 if (sd_bus_error_has_name(error
, SD_BUS_ERROR_ACCESS_DENIED
) ||
217 sd_bus_error_has_name(error
, BUS_ERROR_ONLY_BY_DEPENDENCY
) ||
218 sd_bus_error_has_name(error
, BUS_ERROR_NO_ISOLATION
) ||
219 sd_bus_error_has_name(error
, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE
))
220 return EXIT_NOPERMISSION
;
222 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
))
223 return EXIT_NOTINSTALLED
;
225 if (sd_bus_error_has_name(error
, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE
) ||
226 sd_bus_error_has_name(error
, SD_BUS_ERROR_NOT_SUPPORTED
))
227 return EXIT_NOTIMPLEMENTED
;
229 if (sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
))
230 return EXIT_NOTCONFIGURED
;
238 static void warn_wall(enum action a
) {
239 static const char *table
[_ACTION_MAX
] = {
240 [ACTION_HALT
] = "The system is going down for system halt NOW!",
241 [ACTION_REBOOT
] = "The system is going down for reboot NOW!",
242 [ACTION_POWEROFF
] = "The system is going down for power-off NOW!",
243 [ACTION_KEXEC
] = "The system is going down for kexec reboot NOW!",
244 [ACTION_RESCUE
] = "The system is going down to rescue mode NOW!",
245 [ACTION_EMERGENCY
] = "The system is going down to emergency mode NOW!",
246 [ACTION_CANCEL_SHUTDOWN
] = "The system shutdown has been cancelled NOW!"
253 _cleanup_free_
char *p
;
255 p
= strv_join(arg_wall
, " ");
262 utmp_wall(p
, NULL
, NULL
);
270 utmp_wall(table
[a
], NULL
, NULL
);
273 static bool avoid_bus(void) {
275 if (running_in_chroot() > 0)
278 if (sd_booted() <= 0)
281 if (!isempty(arg_root
))
284 if (arg_scope
== UNIT_FILE_GLOBAL
)
290 static int compare_unit_info(const void *a
, const void *b
) {
291 const UnitInfo
*u
= a
, *v
= b
;
295 /* First, order by machine */
296 if (!u
->machine
&& v
->machine
)
298 if (u
->machine
&& !v
->machine
)
300 if (u
->machine
&& v
->machine
) {
301 r
= strcasecmp(u
->machine
, v
->machine
);
306 /* Second, order by unit type */
307 d1
= strrchr(u
->id
, '.');
308 d2
= strrchr(v
->id
, '.');
310 r
= strcasecmp(d1
, d2
);
315 /* Third, order by name */
316 return strcasecmp(u
->id
, v
->id
);
319 static bool output_show_unit(const UnitInfo
*u
, char **patterns
) {
322 if (!strv_isempty(patterns
)) {
325 STRV_FOREACH(pattern
, patterns
)
326 if (fnmatch(*pattern
, u
->id
, FNM_NOESCAPE
) == 0)
331 return (!arg_types
|| ((dot
= strrchr(u
->id
, '.')) &&
332 strv_find(arg_types
, dot
+1))) &&
333 (arg_all
|| !(streq(u
->active_state
, "inactive")
334 || u
->following
[0]) || u
->job_id
> 0);
337 static int output_units_list(const UnitInfo
*unit_infos
, unsigned c
) {
338 unsigned circle_len
= 0, id_len
, max_id_len
, load_len
, active_len
, sub_len
, job_len
, desc_len
;
340 unsigned n_shown
= 0;
343 max_id_len
= strlen("UNIT");
344 load_len
= strlen("LOAD");
345 active_len
= strlen("ACTIVE");
346 sub_len
= strlen("SUB");
347 job_len
= strlen("JOB");
350 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
351 max_id_len
= MAX(max_id_len
, strlen(u
->id
) + (u
->machine
? strlen(u
->machine
)+1 : 0));
352 load_len
= MAX(load_len
, strlen(u
->load_state
));
353 active_len
= MAX(active_len
, strlen(u
->active_state
));
354 sub_len
= MAX(sub_len
, strlen(u
->sub_state
));
356 if (u
->job_id
!= 0) {
357 job_len
= MAX(job_len
, strlen(u
->job_type
));
361 if (!arg_no_legend
&&
362 (streq(u
->active_state
, "failed") ||
363 STR_IN_SET(u
->load_state
, "error", "not-found", "masked")))
367 if (!arg_full
&& original_stdout_is_tty
) {
370 id_len
= MIN(max_id_len
, 25u);
371 basic_len
= circle_len
+ 5 + id_len
+ 5 + active_len
+ sub_len
;
374 basic_len
+= job_len
+ 1;
376 if (basic_len
< (unsigned) columns()) {
377 unsigned extra_len
, incr
;
378 extra_len
= columns() - basic_len
;
380 /* Either UNIT already got 25, or is fully satisfied.
381 * Grant up to 25 to DESC now. */
382 incr
= MIN(extra_len
, 25u);
386 /* split the remaining space between UNIT and DESC,
387 * but do not give UNIT more than it needs. */
389 incr
= MIN(extra_len
/ 2, max_id_len
- id_len
);
391 desc_len
+= extra_len
- incr
;
397 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
398 _cleanup_free_
char *e
= NULL
, *j
= NULL
;
399 const char *on_loaded
= "", *off_loaded
= "";
400 const char *on_active
= "", *off_active
= "";
401 const char *on_circle
= "", *off_circle
= "";
405 if (!n_shown
&& !arg_no_legend
) {
410 printf("%-*s %-*s %-*s %-*s ",
413 active_len
, "ACTIVE",
417 printf("%-*s ", job_len
, "JOB");
419 if (!arg_full
&& arg_no_pager
)
420 printf("%.*s\n", desc_len
, "DESCRIPTION");
422 printf("%s\n", "DESCRIPTION");
427 if (STR_IN_SET(u
->load_state
, "error", "not-found", "masked")) {
428 on_loaded
= ansi_highlight_red();
429 on_circle
= ansi_highlight_yellow();
430 off_loaded
= off_circle
= ansi_highlight_off();
434 if (streq(u
->active_state
, "failed")) {
435 on_circle
= on_active
= ansi_highlight_red();
436 off_circle
= off_active
= ansi_highlight_off();
441 j
= strjoin(u
->machine
, ":", u
->id
, NULL
);
450 e
= ellipsize(id
, id_len
, 33);
458 printf("%s%s%s", on_circle
, circle
? draw_special_char(DRAW_BLACK_CIRCLE
) : " ", off_circle
);
460 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
461 on_active
, id_len
, id
, off_active
,
462 on_loaded
, load_len
, u
->load_state
, off_loaded
,
463 on_active
, active_len
, u
->active_state
,
464 sub_len
, u
->sub_state
, off_active
,
465 job_count
? job_len
+ 1 : 0, u
->job_id
? u
->job_type
: "");
468 printf("%.*s\n", desc_len
, u
->description
);
470 printf("%s\n", u
->description
);
473 if (!arg_no_legend
) {
474 const char *on
, *off
;
478 "LOAD = Reflects whether the unit definition was properly loaded.\n"
479 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
480 "SUB = The low-level unit activation state, values depend on unit type.");
481 puts(job_count
? "JOB = Pending job for the unit.\n" : "");
482 on
= ansi_highlight();
483 off
= ansi_highlight_off();
485 on
= ansi_highlight_red();
486 off
= ansi_highlight_off();
490 printf("%s%u loaded units listed.%s\n"
491 "To show all installed unit files use 'systemctl list-unit-files'.\n",
494 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
495 "To show all installed unit files use 'systemctl list-unit-files'.\n",
502 static int get_unit_list(
506 UnitInfo
**unit_infos
,
508 sd_bus_message
**_reply
) {
510 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
511 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
512 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
521 r
= sd_bus_message_new_method_call(
524 "org.freedesktop.systemd1",
525 "/org/freedesktop/systemd1",
526 "org.freedesktop.systemd1.Manager",
527 "ListUnitsFiltered");
530 return bus_log_create_error(r
);
532 r
= sd_bus_message_append_strv(m
, arg_states
);
534 return bus_log_create_error(r
);
536 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
538 log_error("Failed to list units: %s", bus_error_message(&error
, r
));
542 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssssouso)");
544 return bus_log_parse_error(r
);
546 while ((r
= bus_parse_unit_info(reply
, &u
)) > 0) {
549 if (!output_show_unit(&u
, patterns
))
552 if (!GREEDY_REALLOC(*unit_infos
, size
, c
+1))
555 (*unit_infos
)[c
++] = u
;
558 return bus_log_parse_error(r
);
560 r
= sd_bus_message_exit_container(reply
);
562 return bus_log_parse_error(r
);
570 static void message_set_freep(Set
**set
) {
573 while ((m
= set_steal_first(*set
)))
574 sd_bus_message_unref(m
);
579 static int get_unit_list_recursive(
582 UnitInfo
**_unit_infos
,
586 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
587 _cleanup_(message_set_freep
) Set
*replies
;
588 sd_bus_message
*reply
;
596 replies
= set_new(NULL
, NULL
);
600 c
= get_unit_list(bus
, NULL
, patterns
, &unit_infos
, 0, &reply
);
604 r
= set_put(replies
, reply
);
606 sd_bus_message_unref(reply
);
611 _cleanup_strv_free_
char **machines
= NULL
;
614 r
= sd_get_machine_names(&machines
);
618 STRV_FOREACH(i
, machines
) {
619 _cleanup_bus_unref_ sd_bus
*container
= NULL
;
622 r
= sd_bus_open_system_container(&container
, *i
);
624 log_error("Failed to connect to container %s: %s", *i
, strerror(-r
));
628 k
= get_unit_list(container
, *i
, patterns
, &unit_infos
, c
, &reply
);
634 r
= set_put(replies
, reply
);
636 sd_bus_message_unref(reply
);
641 *_machines
= machines
;
646 *_unit_infos
= unit_infos
;
655 static int list_units(sd_bus
*bus
, char **args
) {
656 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
657 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
658 _cleanup_strv_free_
char **machines
= NULL
;
661 pager_open_if_enabled();
663 r
= get_unit_list_recursive(bus
, strv_skip_first(args
), &unit_infos
, &replies
, &machines
);
667 qsort_safe(unit_infos
, r
, sizeof(UnitInfo
), compare_unit_info
);
668 return output_units_list(unit_infos
, r
);
671 static int get_triggered_units(
676 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
679 r
= sd_bus_get_property_strv(
681 "org.freedesktop.systemd1",
683 "org.freedesktop.systemd1.Unit",
689 log_error("Failed to determine triggers: %s", bus_error_message(&error
, r
));
694 static int get_listening(
696 const char* unit_path
,
699 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
700 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
701 const char *type
, *path
;
704 r
= sd_bus_get_property(
706 "org.freedesktop.systemd1",
708 "org.freedesktop.systemd1.Socket",
714 log_error("Failed to get list of listening sockets: %s", bus_error_message(&error
, r
));
718 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
720 return bus_log_parse_error(r
);
722 while ((r
= sd_bus_message_read(reply
, "(ss)", &type
, &path
)) > 0) {
724 r
= strv_extend(listening
, type
);
728 r
= strv_extend(listening
, path
);
735 return bus_log_parse_error(r
);
737 r
= sd_bus_message_exit_container(reply
);
739 return bus_log_parse_error(r
);
751 /* Note: triggered is a list here, although it almost certainly
752 * will always be one unit. Nevertheless, dbus API allows for multiple
753 * values, so let's follow that.*/
756 /* The strv above is shared. free is set only in the first one. */
760 static int socket_info_compare(const struct socket_info
*a
, const struct socket_info
*b
) {
766 if (!a
->machine
&& b
->machine
)
768 if (a
->machine
&& !b
->machine
)
770 if (a
->machine
&& b
->machine
) {
771 o
= strcasecmp(a
->machine
, b
->machine
);
776 o
= strcmp(a
->path
, b
->path
);
778 o
= strcmp(a
->type
, b
->type
);
783 static int output_sockets_list(struct socket_info
*socket_infos
, unsigned cs
) {
784 struct socket_info
*s
;
785 unsigned pathlen
= strlen("LISTEN"),
786 typelen
= strlen("TYPE") * arg_show_types
,
787 socklen
= strlen("UNIT"),
788 servlen
= strlen("ACTIVATES");
789 const char *on
, *off
;
791 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
795 socklen
= MAX(socklen
, strlen(s
->id
));
797 typelen
= MAX(typelen
, strlen(s
->type
));
798 pathlen
= MAX(pathlen
, strlen(s
->path
) + (s
->machine
? strlen(s
->machine
)+1 : 0));
800 STRV_FOREACH(a
, s
->triggered
)
801 tmp
+= strlen(*a
) + 2*(a
!= s
->triggered
);
802 servlen
= MAX(servlen
, tmp
);
807 printf("%-*s %-*.*s%-*s %s\n",
809 typelen
+ arg_show_types
, typelen
+ arg_show_types
, "TYPE ",
813 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
814 _cleanup_free_
char *j
= NULL
;
819 j
= strjoin(s
->machine
, ":", s
->path
, NULL
);
827 printf("%-*s %-*s %-*s",
828 pathlen
, path
, typelen
, s
->type
, socklen
, s
->id
);
831 pathlen
, path
, socklen
, s
->id
);
832 STRV_FOREACH(a
, s
->triggered
)
834 a
== s
->triggered
? "" : ",", *a
);
838 on
= ansi_highlight();
839 off
= ansi_highlight_off();
843 on
= ansi_highlight_red();
844 off
= ansi_highlight_off();
847 if (!arg_no_legend
) {
848 printf("%s%u sockets listed.%s\n", on
, cs
, off
);
850 printf("Pass --all to see loaded but inactive sockets, too.\n");
856 static int list_sockets(sd_bus
*bus
, char **args
) {
857 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
858 _cleanup_strv_free_
char **machines
= NULL
;
859 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
860 _cleanup_free_
struct socket_info
*socket_infos
= NULL
;
862 struct socket_info
*s
;
867 pager_open_if_enabled();
869 n
= get_unit_list_recursive(bus
, strv_skip_first(args
), &unit_infos
, &replies
, &machines
);
873 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
874 _cleanup_strv_free_
char **listening
= NULL
, **triggered
= NULL
;
877 if (!endswith(u
->id
, ".socket"))
880 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
884 c
= get_listening(bus
, u
->unit_path
, &listening
);
890 if (!GREEDY_REALLOC(socket_infos
, size
, cs
+ c
)) {
895 for (i
= 0; i
< c
; i
++)
896 socket_infos
[cs
+ i
] = (struct socket_info
) {
897 .machine
= u
->machine
,
899 .type
= listening
[i
*2],
900 .path
= listening
[i
*2 + 1],
901 .triggered
= triggered
,
902 .own_triggered
= i
==0,
905 /* from this point on we will cleanup those socket_infos */
908 listening
= triggered
= NULL
; /* avoid cleanup */
911 qsort_safe(socket_infos
, cs
, sizeof(struct socket_info
),
912 (__compar_fn_t
) socket_info_compare
);
914 output_sockets_list(socket_infos
, cs
);
917 assert(cs
== 0 || socket_infos
);
918 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
921 if (s
->own_triggered
)
922 strv_free(s
->triggered
);
928 static int get_next_elapse(
931 dual_timestamp
*next
) {
933 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
941 r
= sd_bus_get_property_trivial(
943 "org.freedesktop.systemd1",
945 "org.freedesktop.systemd1.Timer",
946 "NextElapseUSecMonotonic",
951 log_error("Failed to get next elapsation time: %s", bus_error_message(&error
, r
));
955 r
= sd_bus_get_property_trivial(
957 "org.freedesktop.systemd1",
959 "org.freedesktop.systemd1.Timer",
960 "NextElapseUSecRealtime",
965 log_error("Failed to get next elapsation time: %s", bus_error_message(&error
, r
));
973 static int get_last_trigger(
978 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
985 r
= sd_bus_get_property_trivial(
987 "org.freedesktop.systemd1",
989 "org.freedesktop.systemd1.Timer",
995 log_error("Failed to get last trigger time: %s", bus_error_message(&error
, r
));
1003 const char* machine
;
1006 usec_t last_trigger
;
1010 static int timer_info_compare(const struct timer_info
*a
, const struct timer_info
*b
) {
1016 if (!a
->machine
&& b
->machine
)
1018 if (a
->machine
&& !b
->machine
)
1020 if (a
->machine
&& b
->machine
) {
1021 o
= strcasecmp(a
->machine
, b
->machine
);
1026 if (a
->next_elapse
< b
->next_elapse
)
1028 if (a
->next_elapse
> b
->next_elapse
)
1031 return strcmp(a
->id
, b
->id
);
1034 static int output_timers_list(struct timer_info
*timer_infos
, unsigned n
) {
1035 struct timer_info
*t
;
1037 nextlen
= strlen("NEXT"),
1038 leftlen
= strlen("LEFT"),
1039 lastlen
= strlen("LAST"),
1040 passedlen
= strlen("PASSED"),
1041 unitlen
= strlen("UNIT"),
1042 activatelen
= strlen("ACTIVATES");
1044 const char *on
, *off
;
1046 assert(timer_infos
|| n
== 0);
1048 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1052 if (t
->next_elapse
> 0) {
1053 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1055 format_timestamp(tstamp
, sizeof(tstamp
), t
->next_elapse
);
1056 nextlen
= MAX(nextlen
, strlen(tstamp
) + 1);
1058 format_timestamp_relative(trel
, sizeof(trel
), t
->next_elapse
);
1059 leftlen
= MAX(leftlen
, strlen(trel
));
1062 if (t
->last_trigger
> 0) {
1063 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1065 format_timestamp(tstamp
, sizeof(tstamp
), t
->last_trigger
);
1066 lastlen
= MAX(lastlen
, strlen(tstamp
) + 1);
1068 format_timestamp_relative(trel
, sizeof(trel
), t
->last_trigger
);
1069 passedlen
= MAX(passedlen
, strlen(trel
));
1072 unitlen
= MAX(unitlen
, strlen(t
->id
) + (t
->machine
? strlen(t
->machine
)+1 : 0));
1074 STRV_FOREACH(a
, t
->triggered
)
1075 ul
+= strlen(*a
) + 2*(a
!= t
->triggered
);
1077 activatelen
= MAX(activatelen
, ul
);
1082 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1086 passedlen
, "PASSED",
1090 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1091 _cleanup_free_
char *j
= NULL
;
1093 char tstamp1
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel1
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1094 char tstamp2
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel2
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1097 format_timestamp(tstamp1
, sizeof(tstamp1
), t
->next_elapse
);
1098 format_timestamp_relative(trel1
, sizeof(trel1
), t
->next_elapse
);
1100 format_timestamp(tstamp2
, sizeof(tstamp2
), t
->last_trigger
);
1101 format_timestamp_relative(trel2
, sizeof(trel2
), t
->last_trigger
);
1104 j
= strjoin(t
->machine
, ":", t
->id
, NULL
);
1111 printf("%-*s %-*s %-*s %-*s %-*s",
1112 nextlen
, tstamp1
, leftlen
, trel1
, lastlen
, tstamp2
, passedlen
, trel2
, unitlen
, unit
);
1114 STRV_FOREACH(a
, t
->triggered
)
1116 a
== t
->triggered
? "" : ",", *a
);
1120 on
= ansi_highlight();
1121 off
= ansi_highlight_off();
1125 on
= ansi_highlight_red();
1126 off
= ansi_highlight_off();
1129 if (!arg_no_legend
) {
1130 printf("%s%u timers listed.%s\n", on
, n
, off
);
1132 printf("Pass --all to see loaded but inactive timers, too.\n");
1138 static usec_t
calc_next_elapse(dual_timestamp
*nw
, dual_timestamp
*next
) {
1144 if (next
->monotonic
!= (usec_t
) -1 && next
->monotonic
> 0) {
1147 if (next
->monotonic
> nw
->monotonic
)
1148 converted
= nw
->realtime
+ (next
->monotonic
- nw
->monotonic
);
1150 converted
= nw
->realtime
- (nw
->monotonic
- next
->monotonic
);
1152 if (next
->realtime
!= (usec_t
) -1 && next
->realtime
> 0)
1153 next_elapse
= MIN(converted
, next
->realtime
);
1155 next_elapse
= converted
;
1158 next_elapse
= next
->realtime
;
1163 static int list_timers(sd_bus
*bus
, char **args
) {
1164 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
1165 _cleanup_strv_free_
char **machines
= NULL
;
1166 _cleanup_free_
struct timer_info
*timer_infos
= NULL
;
1167 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
1168 struct timer_info
*t
;
1175 pager_open_if_enabled();
1177 n
= get_unit_list_recursive(bus
, strv_skip_first(args
), &unit_infos
, &replies
, &machines
);
1181 dual_timestamp_get(&nw
);
1183 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
1184 _cleanup_strv_free_
char **triggered
= NULL
;
1185 dual_timestamp next
= {};
1188 if (!endswith(u
->id
, ".timer"))
1191 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
1195 r
= get_next_elapse(bus
, u
->unit_path
, &next
);
1199 get_last_trigger(bus
, u
->unit_path
, &last
);
1201 if (!GREEDY_REALLOC(timer_infos
, size
, c
+1)) {
1206 m
= calc_next_elapse(&nw
, &next
);
1208 timer_infos
[c
++] = (struct timer_info
) {
1209 .machine
= u
->machine
,
1212 .last_trigger
= last
,
1213 .triggered
= triggered
,
1216 triggered
= NULL
; /* avoid cleanup */
1219 qsort_safe(timer_infos
, c
, sizeof(struct timer_info
),
1220 (__compar_fn_t
) timer_info_compare
);
1222 output_timers_list(timer_infos
, c
);
1225 for (t
= timer_infos
; t
< timer_infos
+ c
; t
++)
1226 strv_free(t
->triggered
);
1231 static int compare_unit_file_list(const void *a
, const void *b
) {
1232 const char *d1
, *d2
;
1233 const UnitFileList
*u
= a
, *v
= b
;
1235 d1
= strrchr(u
->path
, '.');
1236 d2
= strrchr(v
->path
, '.');
1241 r
= strcasecmp(d1
, d2
);
1246 return strcasecmp(basename(u
->path
), basename(v
->path
));
1249 static bool output_show_unit_file(const UnitFileList
*u
, char **patterns
) {
1252 if (!strv_isempty(patterns
)) {
1255 STRV_FOREACH(pattern
, patterns
)
1256 if (fnmatch(*pattern
, basename(u
->path
), FNM_NOESCAPE
) == 0)
1261 return !arg_types
|| ((dot
= strrchr(u
->path
, '.')) && strv_find(arg_types
, dot
+1));
1264 static void output_unit_file_list(const UnitFileList
*units
, unsigned c
) {
1265 unsigned max_id_len
, id_cols
, state_cols
;
1266 const UnitFileList
*u
;
1268 max_id_len
= strlen("UNIT FILE");
1269 state_cols
= strlen("STATE");
1271 for (u
= units
; u
< units
+ c
; u
++) {
1272 max_id_len
= MAX(max_id_len
, strlen(basename(u
->path
)));
1273 state_cols
= MAX(state_cols
, strlen(unit_file_state_to_string(u
->state
)));
1277 unsigned basic_cols
;
1279 id_cols
= MIN(max_id_len
, 25u);
1280 basic_cols
= 1 + id_cols
+ state_cols
;
1281 if (basic_cols
< (unsigned) columns())
1282 id_cols
+= MIN(columns() - basic_cols
, max_id_len
- id_cols
);
1284 id_cols
= max_id_len
;
1287 printf("%-*s %-*s\n",
1288 id_cols
, "UNIT FILE",
1289 state_cols
, "STATE");
1291 for (u
= units
; u
< units
+ c
; u
++) {
1292 _cleanup_free_
char *e
= NULL
;
1293 const char *on
, *off
;
1296 if (u
->state
== UNIT_FILE_MASKED
||
1297 u
->state
== UNIT_FILE_MASKED_RUNTIME
||
1298 u
->state
== UNIT_FILE_DISABLED
||
1299 u
->state
== UNIT_FILE_INVALID
) {
1300 on
= ansi_highlight_red();
1301 off
= ansi_highlight_off();
1302 } else if (u
->state
== UNIT_FILE_ENABLED
) {
1303 on
= ansi_highlight_green();
1304 off
= ansi_highlight_off();
1308 id
= basename(u
->path
);
1310 e
= arg_full
? NULL
: ellipsize(id
, id_cols
, 33);
1312 printf("%-*s %s%-*s%s\n",
1313 id_cols
, e
? e
: id
,
1314 on
, state_cols
, unit_file_state_to_string(u
->state
), off
);
1318 printf("\n%u unit files listed.\n", c
);
1321 static int list_unit_files(sd_bus
*bus
, char **args
) {
1322 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1323 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1324 _cleanup_free_ UnitFileList
*units
= NULL
;
1332 pager_open_if_enabled();
1340 h
= hashmap_new(string_hash_func
, string_compare_func
);
1344 r
= unit_file_get_list(arg_scope
, arg_root
, h
);
1346 unit_file_list_free(h
);
1347 log_error("Failed to get unit file list: %s", strerror(-r
));
1351 n_units
= hashmap_size(h
);
1352 units
= new(UnitFileList
, n_units
);
1354 unit_file_list_free(h
);
1358 HASHMAP_FOREACH(u
, h
, i
) {
1359 if (!output_show_unit_file(u
, strv_skip_first(args
)))
1366 assert(c
<= n_units
);
1369 r
= sd_bus_call_method(
1371 "org.freedesktop.systemd1",
1372 "/org/freedesktop/systemd1",
1373 "org.freedesktop.systemd1.Manager",
1379 log_error("Failed to list unit files: %s", bus_error_message(&error
, r
));
1383 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
1385 return bus_log_parse_error(r
);
1387 while ((r
= sd_bus_message_read(reply
, "(ss)", &path
, &state
)) > 0) {
1389 if (!GREEDY_REALLOC(units
, size
, c
+ 1))
1392 units
[c
] = (struct UnitFileList
) {
1394 unit_file_state_from_string(state
)
1397 if (output_show_unit_file(&units
[c
], strv_skip_first(args
)))
1402 return bus_log_parse_error(r
);
1404 r
= sd_bus_message_exit_container(reply
);
1406 return bus_log_parse_error(r
);
1410 qsort(units
, c
, sizeof(UnitFileList
), compare_unit_file_list
);
1411 output_unit_file_list(units
, c
);
1415 for (unit
= units
; unit
< units
+ c
; unit
++)
1421 static int list_dependencies_print(const char *name
, int level
, unsigned int branches
, bool last
) {
1422 _cleanup_free_
char *n
= NULL
;
1423 size_t max_len
= MAX(columns(),20u);
1429 for (i
= level
- 1; i
>= 0; i
--) {
1431 if (len
> max_len
- 3 && !arg_full
) {
1432 printf("%s...\n",max_len
% 2 ? "" : " ");
1435 printf("%s", draw_special_char(branches
& (1 << i
) ? DRAW_TREE_VERTICAL
: DRAW_TREE_SPACE
));
1439 if (len
> max_len
- 3 && !arg_full
) {
1440 printf("%s...\n",max_len
% 2 ? "" : " ");
1444 printf("%s", draw_special_char(last
? DRAW_TREE_RIGHT
: DRAW_TREE_BRANCH
));
1448 printf("%s\n", name
);
1452 n
= ellipsize(name
, max_len
-len
, 100);
1460 static int list_dependencies_get_dependencies(sd_bus
*bus
, const char *name
, char ***deps
) {
1462 static const char *dependencies
[_DEPENDENCY_MAX
] = {
1463 [DEPENDENCY_FORWARD
] = "Requires\0"
1464 "RequiresOverridable\0"
1466 "RequisiteOverridable\0"
1468 [DEPENDENCY_REVERSE
] = "RequiredBy\0"
1469 "RequiredByOverridable\0"
1472 [DEPENDENCY_AFTER
] = "After\0",
1473 [DEPENDENCY_BEFORE
] = "Before\0",
1476 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1477 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1478 _cleanup_strv_free_
char **ret
= NULL
;
1479 _cleanup_free_
char *path
= NULL
;
1485 assert_cc(ELEMENTSOF(dependencies
) == _DEPENDENCY_MAX
);
1487 path
= unit_dbus_path_from_name(name
);
1491 r
= sd_bus_call_method(
1493 "org.freedesktop.systemd1",
1495 "org.freedesktop.DBus.Properties",
1499 "s", "org.freedesktop.systemd1.Unit");
1501 log_error("Failed to get properties of %s: %s", name
, bus_error_message(&error
, r
));
1505 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
1507 return bus_log_parse_error(r
);
1509 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
1512 r
= sd_bus_message_read(reply
, "s", &prop
);
1514 return bus_log_parse_error(r
);
1516 if (!nulstr_contains(dependencies
[arg_dependency
], prop
)) {
1517 r
= sd_bus_message_skip(reply
, "v");
1519 return bus_log_parse_error(r
);
1522 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, "as");
1524 return bus_log_parse_error(r
);
1526 r
= bus_message_read_strv_extend(reply
, &ret
);
1528 return bus_log_parse_error(r
);
1530 r
= sd_bus_message_exit_container(reply
);
1532 return bus_log_parse_error(r
);
1535 r
= sd_bus_message_exit_container(reply
);
1537 return bus_log_parse_error(r
);
1541 return bus_log_parse_error(r
);
1543 r
= sd_bus_message_exit_container(reply
);
1545 return bus_log_parse_error(r
);
1553 static int list_dependencies_compare(const void *_a
, const void *_b
) {
1554 const char **a
= (const char**) _a
, **b
= (const char**) _b
;
1556 if (unit_name_to_type(*a
) == UNIT_TARGET
&& unit_name_to_type(*b
) != UNIT_TARGET
)
1558 if (unit_name_to_type(*a
) != UNIT_TARGET
&& unit_name_to_type(*b
) == UNIT_TARGET
)
1561 return strcasecmp(*a
, *b
);
1564 static int list_dependencies_one(
1569 unsigned int branches
) {
1571 _cleanup_strv_free_
char **deps
= NULL
;
1579 r
= strv_extend(units
, name
);
1583 r
= list_dependencies_get_dependencies(bus
, name
, &deps
);
1587 qsort_safe(deps
, strv_length(deps
), sizeof (char*), list_dependencies_compare
);
1589 STRV_FOREACH(c
, deps
) {
1592 if (strv_contains(*units
, *c
)) {
1594 r
= list_dependencies_print("...", level
+ 1, (branches
<< 1) | (c
[1] == NULL
? 0 : 1), 1);
1601 state
= check_one_unit(bus
, *c
, "activating\0active\0reloading\0", true);
1603 printf("%s%s%s ", ansi_highlight_green(), draw_special_char(DRAW_BLACK_CIRCLE
), ansi_highlight_off());
1605 printf("%s%s%s ", ansi_highlight_red(), draw_special_char(DRAW_BLACK_CIRCLE
), ansi_highlight_off());
1607 r
= list_dependencies_print(*c
, level
, branches
, c
[1] == NULL
);
1611 if (arg_all
|| unit_name_to_type(*c
) == UNIT_TARGET
) {
1612 r
= list_dependencies_one(bus
, *c
, level
+ 1, units
, (branches
<< 1) | (c
[1] == NULL
? 0 : 1));
1619 strv_remove(*units
, name
);
1624 static int list_dependencies(sd_bus
*bus
, char **args
) {
1625 _cleanup_strv_free_
char **units
= NULL
;
1626 _cleanup_free_
char *unit
= NULL
;
1632 unit
= unit_name_mangle(args
[1], MANGLE_NOGLOB
);
1637 u
= SPECIAL_DEFAULT_TARGET
;
1639 pager_open_if_enabled();
1643 return list_dependencies_one(bus
, u
, 0, &units
, 0);
1646 struct machine_info
{
1650 char *control_group
;
1651 uint32_t n_failed_units
;
1656 static const struct bus_properties_map machine_info_property_map
[] = {
1657 { "SystemState", "s", NULL
, offsetof(struct machine_info
, state
) },
1658 { "NJobs", "u", NULL
, offsetof(struct machine_info
, n_jobs
) },
1659 { "NFailedUnits", "u", NULL
, offsetof(struct machine_info
, n_failed_units
) },
1660 { "ControlGroup", "s", NULL
, offsetof(struct machine_info
, control_group
) },
1661 { "UserspaceTimestamp", "t", NULL
, offsetof(struct machine_info
, timestamp
) },
1665 static void free_machines_list(struct machine_info
*machine_infos
, int n
) {
1671 for (i
= 0; i
< n
; i
++) {
1672 free(machine_infos
[i
].name
);
1673 free(machine_infos
[i
].state
);
1674 free(machine_infos
[i
].control_group
);
1677 free(machine_infos
);
1680 static int compare_machine_info(const void *a
, const void *b
) {
1681 const struct machine_info
*u
= a
, *v
= b
;
1683 if (u
->is_host
!= v
->is_host
)
1684 return u
->is_host
> v
->is_host
? -1 : 1;
1686 return strcasecmp(u
->name
, v
->name
);
1689 static int get_machine_properties(sd_bus
*bus
, struct machine_info
*mi
) {
1690 _cleanup_bus_unref_ sd_bus
*container
= NULL
;
1696 r
= sd_bus_open_system_container(&container
, mi
->name
);
1703 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, mi
);
1710 static bool output_show_machine(const char *name
, char **patterns
) {
1715 if (strv_isempty(patterns
))
1718 STRV_FOREACH(i
, patterns
)
1719 if (fnmatch(*i
, name
, FNM_NOESCAPE
) == 0)
1725 static int get_machine_list(
1727 struct machine_info
**_machine_infos
,
1730 struct machine_info
*machine_infos
= NULL
;
1731 _cleanup_strv_free_
char **m
= NULL
;
1732 _cleanup_free_
char *hn
= NULL
;
1737 hn
= gethostname_malloc();
1741 if (output_show_machine(hn
, patterns
)) {
1742 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1))
1745 machine_infos
[c
].is_host
= true;
1746 machine_infos
[c
].name
= hn
;
1749 get_machine_properties(bus
, &machine_infos
[c
]);
1753 sd_get_machine_names(&m
);
1754 STRV_FOREACH(i
, m
) {
1755 _cleanup_free_
char *class = NULL
;
1757 if (!output_show_machine(*i
, patterns
))
1760 sd_machine_get_class(*i
, &class);
1761 if (!streq_ptr(class, "container"))
1764 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1)) {
1765 free_machines_list(machine_infos
, c
);
1769 machine_infos
[c
].is_host
= false;
1770 machine_infos
[c
].name
= strdup(*i
);
1771 if (!machine_infos
[c
].name
) {
1772 free_machines_list(machine_infos
, c
);
1776 get_machine_properties(NULL
, &machine_infos
[c
]);
1780 *_machine_infos
= machine_infos
;
1784 static void output_machines_list(struct machine_info
*machine_infos
, unsigned n
) {
1785 struct machine_info
*m
;
1788 namelen
= sizeof("NAME") - 1,
1789 statelen
= sizeof("STATE") - 1,
1790 failedlen
= sizeof("FAILED") - 1,
1791 jobslen
= sizeof("JOBS") - 1;
1793 assert(machine_infos
|| n
== 0);
1795 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
1796 namelen
= MAX(namelen
, strlen(m
->name
) + (m
->is_host
? sizeof(" (host)") - 1 : 0));
1797 statelen
= MAX(statelen
, m
->state
? strlen(m
->state
) : 0);
1798 failedlen
= MAX(failedlen
, DECIMAL_STR_WIDTH(m
->n_failed_units
));
1799 jobslen
= MAX(jobslen
, DECIMAL_STR_WIDTH(m
->n_jobs
));
1801 if (!arg_no_legend
&& !streq_ptr(m
->state
, "running"))
1805 if (!arg_no_legend
) {
1809 printf("%-*s %-*s %-*s %-*s\n",
1812 failedlen
, "FAILED",
1816 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
1817 const char *on_state
= "", *off_state
= "";
1818 const char *on_failed
= "", *off_failed
= "";
1819 bool circle
= false;
1821 if (streq_ptr(m
->state
, "degraded")) {
1822 on_state
= ansi_highlight_red();
1823 off_state
= ansi_highlight_off();
1825 } else if (!streq_ptr(m
->state
, "running")) {
1826 on_state
= ansi_highlight_yellow();
1827 off_state
= ansi_highlight_off();
1831 if (m
->n_failed_units
> 0) {
1832 on_failed
= ansi_highlight_red();
1833 off_failed
= ansi_highlight_off();
1835 on_failed
= off_failed
= "";
1838 printf("%s%s%s ", on_state
, circle
? draw_special_char(DRAW_BLACK_CIRCLE
) : " ", off_state
);
1841 printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
1842 (int) (namelen
- (sizeof(" (host)")-1)), strna(m
->name
),
1843 on_state
, statelen
, strna(m
->state
), off_state
,
1844 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
1845 jobslen
, m
->n_jobs
);
1847 printf("%-*s %s%-*s%s %s%*u%s %*u\n",
1848 namelen
, strna(m
->name
),
1849 on_state
, statelen
, strna(m
->state
), off_state
,
1850 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
1851 jobslen
, m
->n_jobs
);
1855 printf("\n%u machines listed.\n", n
);
1858 static int list_machines(sd_bus
*bus
, char **args
) {
1859 struct machine_info
*machine_infos
= NULL
;
1864 if (geteuid() != 0) {
1865 log_error("Must be root.");
1869 pager_open_if_enabled();
1871 r
= get_machine_list(bus
, &machine_infos
, strv_skip_first(args
));
1875 qsort_safe(machine_infos
, r
, sizeof(struct machine_info
), compare_machine_info
);
1876 output_machines_list(machine_infos
, r
);
1877 free_machines_list(machine_infos
, r
);
1882 static int get_default(sd_bus
*bus
, char **args
) {
1883 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1884 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1885 _cleanup_free_
char *_path
= NULL
;
1889 if (!bus
|| avoid_bus()) {
1890 r
= unit_file_get_default(arg_scope
, arg_root
, &_path
);
1892 log_error("Failed to get default target: %s", strerror(-r
));
1898 r
= sd_bus_call_method(
1900 "org.freedesktop.systemd1",
1901 "/org/freedesktop/systemd1",
1902 "org.freedesktop.systemd1.Manager",
1908 log_error("Failed to get default target: %s", bus_error_message(&error
, -r
));
1912 r
= sd_bus_message_read(reply
, "s", &path
);
1914 return bus_log_parse_error(r
);
1918 printf("%s\n", path
);
1923 static void dump_unit_file_changes(const UnitFileChange
*changes
, unsigned n_changes
) {
1926 assert(changes
|| n_changes
== 0);
1928 for (i
= 0; i
< n_changes
; i
++) {
1929 if (changes
[i
].type
== UNIT_FILE_SYMLINK
)
1930 log_info("ln -s '%s' '%s'", changes
[i
].source
, changes
[i
].path
);
1932 log_info("rm '%s'", changes
[i
].path
);
1936 static int deserialize_and_dump_unit_file_changes(sd_bus_message
*m
) {
1937 const char *type
, *path
, *source
;
1940 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sss)");
1942 return bus_log_parse_error(r
);
1944 while ((r
= sd_bus_message_read(m
, "(sss)", &type
, &path
, &source
)) > 0) {
1946 if (streq(type
, "symlink"))
1947 log_info("ln -s '%s' '%s'", source
, path
);
1949 log_info("rm '%s'", path
);
1953 return bus_log_parse_error(r
);
1955 r
= sd_bus_message_exit_container(m
);
1957 return bus_log_parse_error(r
);
1962 static int set_default(sd_bus
*bus
, char **args
) {
1963 _cleanup_free_
char *unit
= NULL
;
1964 UnitFileChange
*changes
= NULL
;
1965 unsigned n_changes
= 0;
1968 unit
= unit_name_mangle_with_suffix(args
[1], MANGLE_NOGLOB
, ".target");
1972 if (!bus
|| avoid_bus()) {
1973 r
= unit_file_set_default(arg_scope
, arg_root
, unit
, true, &changes
, &n_changes
);
1975 log_error("Failed to set default target: %s", strerror(-r
));
1980 dump_unit_file_changes(changes
, n_changes
);
1984 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1985 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1987 r
= sd_bus_call_method(
1989 "org.freedesktop.systemd1",
1990 "/org/freedesktop/systemd1",
1991 "org.freedesktop.systemd1.Manager",
1997 log_error("Failed to set default target: %s", bus_error_message(&error
, -r
));
2001 r
= deserialize_and_dump_unit_file_changes(reply
);
2005 /* Try to reload if enabled */
2007 r
= daemon_reload(bus
, args
);
2012 unit_file_changes_free(changes
, n_changes
);
2019 const char *name
, *type
, *state
;
2022 static void output_jobs_list(const struct job_info
* jobs
, unsigned n
, bool skipped
) {
2023 unsigned id_len
, unit_len
, type_len
, state_len
;
2024 const struct job_info
*j
;
2025 const char *on
, *off
;
2026 bool shorten
= false;
2028 assert(n
== 0 || jobs
);
2031 on
= ansi_highlight_green();
2032 off
= ansi_highlight_off();
2034 printf("%sNo jobs %s.%s\n", on
, skipped
? "listed" : "running", off
);
2038 pager_open_if_enabled();
2040 id_len
= strlen("JOB");
2041 unit_len
= strlen("UNIT");
2042 type_len
= strlen("TYPE");
2043 state_len
= strlen("STATE");
2045 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2046 uint32_t id
= j
->id
;
2047 assert(j
->name
&& j
->type
&& j
->state
);
2049 id_len
= MAX(id_len
, DECIMAL_STR_WIDTH(id
));
2050 unit_len
= MAX(unit_len
, strlen(j
->name
));
2051 type_len
= MAX(type_len
, strlen(j
->type
));
2052 state_len
= MAX(state_len
, strlen(j
->state
));
2055 if (!arg_full
&& id_len
+ 1 + unit_len
+ type_len
+ 1 + state_len
> columns()) {
2056 unit_len
= MAX(33u, columns() - id_len
- type_len
- state_len
- 3);
2061 printf("%*s %-*s %-*s %-*s\n",
2065 state_len
, "STATE");
2067 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2068 _cleanup_free_
char *e
= NULL
;
2070 if (streq(j
->state
, "running")) {
2071 on
= ansi_highlight();
2072 off
= ansi_highlight_off();
2076 e
= shorten
? ellipsize(j
->name
, unit_len
, 33) : NULL
;
2077 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2079 on
, unit_len
, e
? e
: j
->name
, off
,
2081 on
, state_len
, j
->state
, off
);
2084 if (!arg_no_legend
) {
2085 on
= ansi_highlight();
2086 off
= ansi_highlight_off();
2088 printf("\n%s%u jobs listed%s.\n", on
, n
, off
);
2092 static bool output_show_job(struct job_info
*job
, char **patterns
) {
2097 if (strv_isempty(patterns
))
2100 STRV_FOREACH(pattern
, patterns
)
2101 if (fnmatch(*pattern
, job
->name
, FNM_NOESCAPE
) == 0)
2106 static int list_jobs(sd_bus
*bus
, char **args
) {
2107 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2108 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2109 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2110 _cleanup_free_
struct job_info
*jobs
= NULL
;
2115 bool skipped
= false;
2117 r
= sd_bus_call_method(
2119 "org.freedesktop.systemd1",
2120 "/org/freedesktop/systemd1",
2121 "org.freedesktop.systemd1.Manager",
2127 log_error("Failed to list jobs: %s", bus_error_message(&error
, r
));
2131 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2133 return bus_log_parse_error(r
);
2135 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0) {
2136 struct job_info job
= { id
, name
, type
, state
};
2138 if (!output_show_job(&job
, strv_skip_first(args
))) {
2143 if (!GREEDY_REALLOC(jobs
, size
, c
+ 1))
2149 return bus_log_parse_error(r
);
2151 r
= sd_bus_message_exit_container(reply
);
2153 return bus_log_parse_error(r
);
2155 output_jobs_list(jobs
, c
, skipped
);
2159 static int cancel_job(sd_bus
*bus
, char **args
) {
2160 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2165 if (strv_length(args
) <= 1)
2166 return daemon_reload(bus
, args
);
2168 STRV_FOREACH(name
, args
+1) {
2172 r
= safe_atou32(*name
, &id
);
2174 log_error("Failed to parse job id \"%s\": %s", *name
, strerror(-r
));
2178 r
= sd_bus_call_method(
2180 "org.freedesktop.systemd1",
2181 "/org/freedesktop/systemd1",
2182 "org.freedesktop.systemd1.Manager",
2188 log_error("Failed to cancel job %u: %s", (unsigned) id
, bus_error_message(&error
, r
));
2196 static int need_daemon_reload(sd_bus
*bus
, const char *unit
) {
2197 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2201 /* We ignore all errors here, since this is used to show a
2204 /* We don't use unit_dbus_path_from_name() directly since we
2205 * don't want to load the unit if it isn't loaded. */
2207 r
= sd_bus_call_method(
2209 "org.freedesktop.systemd1",
2210 "/org/freedesktop/systemd1",
2211 "org.freedesktop.systemd1.Manager",
2219 r
= sd_bus_message_read(reply
, "o", &path
);
2223 r
= sd_bus_get_property_trivial(
2225 "org.freedesktop.systemd1",
2227 "org.freedesktop.systemd1.Unit",
2237 typedef struct WaitData
{
2244 static int wait_filter(sd_bus
*bus
, sd_bus_message
*m
, void *data
, sd_bus_error
*error
) {
2251 log_debug("Got D-Bus request: %s.%s() on %s",
2252 sd_bus_message_get_interface(m
),
2253 sd_bus_message_get_member(m
),
2254 sd_bus_message_get_path(m
));
2256 if (sd_bus_message_is_signal(m
, "org.freedesktop.DBus.Local", "Disconnected")) {
2257 log_error("Warning! D-Bus connection terminated.");
2259 } else if (sd_bus_message_is_signal(m
, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
2261 const char *path
, *result
, *unit
;
2265 r
= sd_bus_message_read(m
, "uoss", &id
, &path
, &unit
, &result
);
2267 ret
= set_remove(d
->set
, (char*) path
);
2273 if (!isempty(result
))
2274 d
->result
= strdup(result
);
2277 d
->name
= strdup(unit
);
2282 r
= sd_bus_message_read(m
, "uos", &id
, &path
, &result
);
2284 ret
= set_remove(d
->set
, (char*) path
);
2291 d
->result
= strdup(result
);
2297 bus_log_parse_error(r
);
2303 static int enable_wait_for_jobs(sd_bus
*bus
) {
2308 r
= sd_bus_add_match(
2312 "sender='org.freedesktop.systemd1',"
2313 "interface='org.freedesktop.systemd1.Manager',"
2314 "member='JobRemoved',"
2315 "path='/org/freedesktop/systemd1'",
2318 log_error("Failed to add match");
2322 /* This is slightly dirty, since we don't undo the match registrations. */
2326 static int bus_process_wait(sd_bus
*bus
) {
2330 r
= sd_bus_process(bus
, NULL
);
2335 r
= sd_bus_wait(bus
, (uint64_t) -1);
2341 static int check_wait_response(WaitData
*d
) {
2347 if (streq(d
->result
, "timeout"))
2348 log_error("Job for %s timed out.", strna(d
->name
));
2349 else if (streq(d
->result
, "canceled"))
2350 log_error("Job for %s canceled.", strna(d
->name
));
2351 else if (streq(d
->result
, "dependency"))
2352 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d
->name
));
2353 else if (!streq(d
->result
, "done") && !streq(d
->result
, "skipped"))
2354 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d
->name
), strna(d
->name
));
2357 if (streq(d
->result
, "timeout"))
2359 else if (streq(d
->result
, "canceled"))
2361 else if (streq(d
->result
, "dependency"))
2363 else if (!streq(d
->result
, "done") && !streq(d
->result
, "skipped"))
2369 static int wait_for_jobs(sd_bus
*bus
, Set
*s
) {
2370 _cleanup_bus_slot_unref_ sd_bus_slot
*slot
= NULL
;
2371 WaitData d
= { .set
= s
};
2377 q
= sd_bus_add_filter(bus
, &slot
, wait_filter
, &d
);
2381 while (!set_isempty(s
)) {
2382 q
= bus_process_wait(bus
);
2384 log_error("Failed to wait for response: %s", strerror(-r
));
2389 q
= check_wait_response(&d
);
2390 /* Return the first error as it is most likely to be
2392 if (q
< 0 && r
== 0)
2394 log_debug("Got result %s/%s for job %s",
2395 strna(d
.result
), strerror(-q
), strna(d
.name
));
2408 static int check_one_unit(sd_bus
*bus
, const char *name
, const char *good_states
, bool quiet
) {
2409 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2410 _cleanup_free_
char *n
= NULL
, *state
= NULL
;
2416 n
= unit_name_mangle(name
, MANGLE_NOGLOB
);
2420 /* We don't use unit_dbus_path_from_name() directly since we
2421 * don't want to load the unit if it isn't loaded. */
2423 r
= sd_bus_call_method(
2425 "org.freedesktop.systemd1",
2426 "/org/freedesktop/systemd1",
2427 "org.freedesktop.systemd1.Manager",
2438 r
= sd_bus_message_read(reply
, "o", &path
);
2440 return bus_log_parse_error(r
);
2442 r
= sd_bus_get_property_string(
2444 "org.freedesktop.systemd1",
2446 "org.freedesktop.systemd1.Unit",
2459 return nulstr_contains(good_states
, state
);
2462 static int check_triggering_units(
2466 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2467 _cleanup_free_
char *path
= NULL
, *n
= NULL
, *state
= NULL
;
2468 _cleanup_strv_free_
char **triggered_by
= NULL
;
2469 bool print_warning_label
= true;
2473 n
= unit_name_mangle(name
, MANGLE_NOGLOB
);
2477 path
= unit_dbus_path_from_name(n
);
2481 r
= sd_bus_get_property_string(
2483 "org.freedesktop.systemd1",
2485 "org.freedesktop.systemd1.Unit",
2490 log_error("Failed to get load state of %s: %s", n
, bus_error_message(&error
, r
));
2494 if (streq(state
, "masked"))
2497 r
= sd_bus_get_property_strv(
2499 "org.freedesktop.systemd1",
2501 "org.freedesktop.systemd1.Unit",
2506 log_error("Failed to get triggered by array of %s: %s", n
, bus_error_message(&error
, r
));
2510 STRV_FOREACH(i
, triggered_by
) {
2511 r
= check_one_unit(bus
, *i
, "active\0reloading\0", true);
2513 log_error("Failed to check unit: %s", strerror(-r
));
2520 if (print_warning_label
) {
2521 log_warning("Warning: Stopping %s, but it can still be activated by:", n
);
2522 print_warning_label
= false;
2525 log_warning(" %s", *i
);
2531 static const char *verb_to_method(const char *verb
) {
2534 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2535 if (streq_ptr(unit_actions
[i
].verb
, verb
))
2536 return unit_actions
[i
].method
;
2541 static const char *method_to_verb(const char *method
) {
2544 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2545 if (streq_ptr(unit_actions
[i
].method
, method
))
2546 return unit_actions
[i
].verb
;
2551 static int start_unit_one(
2556 sd_bus_error
*error
,
2559 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2568 log_debug("Calling manager for %s on %s, %s", method
, name
, mode
);
2569 r
= sd_bus_call_method(
2571 "org.freedesktop.systemd1",
2572 "/org/freedesktop/systemd1",
2573 "org.freedesktop.systemd1.Manager",
2581 if (r
== -ENOENT
&& arg_action
!= ACTION_SYSTEMCTL
)
2582 /* There's always a fallback possible for
2583 * legacy actions. */
2584 return -EADDRNOTAVAIL
;
2586 verb
= method_to_verb(method
);
2588 log_error("Failed to %s %s: %s", verb
, name
, bus_error_message(error
, r
));
2592 r
= sd_bus_message_read(reply
, "o", &path
);
2594 return bus_log_parse_error(r
);
2596 if (need_daemon_reload(bus
, name
) > 0)
2597 log_warning("Warning: Unit file of %s changed on disk, 'systemctl%s daemon-reload' recommended.",
2598 name
, arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user");
2607 log_debug("Adding %s to the set", p
);
2608 r
= set_consume(s
, p
);
2616 static int expand_names(sd_bus
*bus
, char **names
, const char* suffix
, char ***ret
) {
2618 _cleanup_strv_free_
char **mangled
= NULL
, **globs
= NULL
;
2622 STRV_FOREACH(name
, names
) {
2626 t
= unit_name_mangle_with_suffix(*name
, MANGLE_GLOB
, suffix
);
2628 t
= unit_name_mangle(*name
, MANGLE_GLOB
);
2632 if (string_is_glob(t
))
2633 r
= strv_consume(&globs
, t
);
2635 r
= strv_consume(&mangled
, t
);
2640 /* Query the manager only if any of the names are a glob, since
2641 * this is fairly expensive */
2642 if (!strv_isempty(globs
)) {
2643 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2644 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
2646 r
= get_unit_list(bus
, NULL
, globs
, &unit_infos
, 0, &reply
);
2650 for (i
= 0; i
< r
; i
++)
2651 if (strv_extend(&mangled
, unit_infos
[i
].id
) < 0)
2656 mangled
= NULL
; /* do not free */
2661 static const struct {
2665 } action_table
[_ACTION_MAX
] = {
2666 [ACTION_HALT
] = { SPECIAL_HALT_TARGET
, "halt", "replace-irreversibly" },
2667 [ACTION_POWEROFF
] = { SPECIAL_POWEROFF_TARGET
, "poweroff", "replace-irreversibly" },
2668 [ACTION_REBOOT
] = { SPECIAL_REBOOT_TARGET
, "reboot", "replace-irreversibly" },
2669 [ACTION_KEXEC
] = { SPECIAL_KEXEC_TARGET
, "kexec", "replace-irreversibly" },
2670 [ACTION_RUNLEVEL2
] = { SPECIAL_RUNLEVEL2_TARGET
, NULL
, "isolate" },
2671 [ACTION_RUNLEVEL3
] = { SPECIAL_RUNLEVEL3_TARGET
, NULL
, "isolate" },
2672 [ACTION_RUNLEVEL4
] = { SPECIAL_RUNLEVEL4_TARGET
, NULL
, "isolate" },
2673 [ACTION_RUNLEVEL5
] = { SPECIAL_RUNLEVEL5_TARGET
, NULL
, "isolate" },
2674 [ACTION_RESCUE
] = { SPECIAL_RESCUE_TARGET
, "rescue", "isolate" },
2675 [ACTION_EMERGENCY
] = { SPECIAL_EMERGENCY_TARGET
, "emergency", "isolate" },
2676 [ACTION_DEFAULT
] = { SPECIAL_DEFAULT_TARGET
, "default", "isolate" },
2677 [ACTION_EXIT
] = { SPECIAL_EXIT_TARGET
, "exit", "replace-irreversibly" },
2678 [ACTION_SUSPEND
] = { SPECIAL_SUSPEND_TARGET
, "suspend", "replace-irreversibly" },
2679 [ACTION_HIBERNATE
] = { SPECIAL_HIBERNATE_TARGET
, "hibernate", "replace-irreversibly" },
2680 [ACTION_HYBRID_SLEEP
] = { SPECIAL_HYBRID_SLEEP_TARGET
, "hybrid-sleep", "replace-irreversibly" },
2683 static enum action
verb_to_action(const char *verb
) {
2686 for (i
= _ACTION_INVALID
; i
< _ACTION_MAX
; i
++)
2687 if (streq_ptr(action_table
[i
].verb
, verb
))
2690 return _ACTION_INVALID
;
2693 static int start_unit(sd_bus
*bus
, char **args
) {
2694 _cleanup_set_free_free_ Set
*s
= NULL
;
2695 _cleanup_strv_free_
char **names
= NULL
;
2696 const char *method
, *mode
, *one_name
;
2702 ask_password_agent_open_if_enabled();
2704 if (arg_action
== ACTION_SYSTEMCTL
) {
2706 method
= verb_to_method(args
[0]);
2707 action
= verb_to_action(args
[0]);
2709 mode
= streq(args
[0], "isolate") ? "isolate" :
2710 action_table
[action
].mode
?: arg_job_mode
;
2712 one_name
= action_table
[action
].target
;
2714 assert(arg_action
< ELEMENTSOF(action_table
));
2715 assert(action_table
[arg_action
].target
);
2717 method
= "StartUnit";
2719 mode
= action_table
[arg_action
].mode
;
2720 one_name
= action_table
[arg_action
].target
;
2724 names
= strv_new(one_name
, NULL
);
2726 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
2728 log_error("Failed to expand names: %s", strerror(-r
));
2731 if (!arg_no_block
) {
2732 r
= enable_wait_for_jobs(bus
);
2734 log_error("Could not watch jobs: %s", strerror(-r
));
2738 s
= set_new(string_hash_func
, string_compare_func
);
2743 STRV_FOREACH(name
, names
) {
2744 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2747 q
= start_unit_one(bus
, method
, *name
, mode
, &error
, s
);
2748 if (r
>= 0 && q
< 0)
2749 r
= translate_bus_error_to_exit_status(q
, &error
);
2752 if (!arg_no_block
) {
2755 q
= wait_for_jobs(bus
, s
);
2759 /* When stopping units, warn if they can still be triggered by
2760 * another active unit (socket, path, timer) */
2761 if (!arg_quiet
&& streq(method
, "StopUnit"))
2762 STRV_FOREACH(name
, names
)
2763 check_triggering_units(bus
, *name
);
2769 /* Ask systemd-logind, which might grant access to unprivileged users
2770 * through PolicyKit */
2771 static int reboot_with_logind(sd_bus
*bus
, enum action a
) {
2773 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2780 polkit_agent_open_if_enabled();
2788 case ACTION_POWEROFF
:
2789 method
= "PowerOff";
2792 case ACTION_SUSPEND
:
2796 case ACTION_HIBERNATE
:
2797 method
= "Hibernate";
2800 case ACTION_HYBRID_SLEEP
:
2801 method
= "HybridSleep";
2808 r
= sd_bus_call_method(
2810 "org.freedesktop.login1",
2811 "/org/freedesktop/login1",
2812 "org.freedesktop.login1.Manager",
2818 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
2826 static int check_inhibitors(sd_bus
*bus
, enum action a
) {
2828 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2829 _cleanup_strv_free_
char **sessions
= NULL
;
2830 const char *what
, *who
, *why
, *mode
;
2839 if (arg_ignore_inhibitors
|| arg_force
> 0)
2851 r
= sd_bus_call_method(
2853 "org.freedesktop.login1",
2854 "/org/freedesktop/login1",
2855 "org.freedesktop.login1.Manager",
2861 /* If logind is not around, then there are no inhibitors... */
2864 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssuu)");
2866 return bus_log_parse_error(r
);
2868 while ((r
= sd_bus_message_read(reply
, "(ssssuu)", &what
, &who
, &why
, &mode
, &uid
, &pid
)) > 0) {
2869 _cleanup_free_
char *comm
= NULL
, *user
= NULL
;
2870 _cleanup_strv_free_
char **sv
= NULL
;
2872 if (!streq(mode
, "block"))
2875 sv
= strv_split(what
, ":");
2879 if (!strv_contains(sv
,
2881 a
== ACTION_POWEROFF
||
2882 a
== ACTION_REBOOT
||
2883 a
== ACTION_KEXEC
? "shutdown" : "sleep"))
2886 get_process_comm(pid
, &comm
);
2887 user
= uid_to_name(uid
);
2889 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT
" \"%s\", user %s), reason is \"%s\".",
2890 who
, pid
, strna(comm
), strna(user
), why
);
2895 return bus_log_parse_error(r
);
2897 r
= sd_bus_message_exit_container(reply
);
2899 return bus_log_parse_error(r
);
2901 /* Check for current sessions */
2902 sd_get_sessions(&sessions
);
2903 STRV_FOREACH(s
, sessions
) {
2904 _cleanup_free_
char *type
= NULL
, *tty
= NULL
, *seat
= NULL
, *user
= NULL
, *service
= NULL
, *class = NULL
;
2906 if (sd_session_get_uid(*s
, &uid
) < 0 || uid
== getuid())
2909 if (sd_session_get_class(*s
, &class) < 0 || !streq(class, "user"))
2912 if (sd_session_get_type(*s
, &type
) < 0 || (!streq(type
, "x11") && !streq(type
, "tty")))
2915 sd_session_get_tty(*s
, &tty
);
2916 sd_session_get_seat(*s
, &seat
);
2917 sd_session_get_service(*s
, &service
);
2918 user
= uid_to_name(uid
);
2920 log_warning("User %s is logged in on %s.", strna(user
), isempty(tty
) ? (isempty(seat
) ? strna(service
) : seat
) : tty
);
2927 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2928 action_table
[a
].verb
);
2936 static int start_special(sd_bus
*bus
, char **args
) {
2942 a
= verb_to_action(args
[0]);
2944 r
= check_inhibitors(bus
, a
);
2948 if (arg_force
>= 2 && geteuid() != 0) {
2949 log_error("Must be root.");
2953 if (arg_force
>= 2 &&
2954 (a
== ACTION_HALT
||
2955 a
== ACTION_POWEROFF
||
2956 a
== ACTION_REBOOT
))
2959 if (arg_force
>= 1 &&
2960 (a
== ACTION_HALT
||
2961 a
== ACTION_POWEROFF
||
2962 a
== ACTION_REBOOT
||
2963 a
== ACTION_KEXEC
||
2965 return daemon_reload(bus
, args
);
2967 /* first try logind, to allow authentication with polkit */
2968 if (geteuid() != 0 &&
2969 (a
== ACTION_POWEROFF
||
2970 a
== ACTION_REBOOT
||
2971 a
== ACTION_SUSPEND
||
2972 a
== ACTION_HIBERNATE
||
2973 a
== ACTION_HYBRID_SLEEP
)) {
2974 r
= reboot_with_logind(bus
, a
);
2979 r
= start_unit(bus
, args
);
2980 if (r
== EXIT_SUCCESS
)
2986 static int check_unit_generic(sd_bus
*bus
, int code
, const char *good_states
, char **args
) {
2987 _cleanup_strv_free_
char **names
= NULL
;
2994 r
= expand_names(bus
, args
, NULL
, &names
);
2996 log_error("Failed to expand names: %s", strerror(-r
));
3000 STRV_FOREACH(name
, names
) {
3003 state
= check_one_unit(bus
, *name
, good_states
, arg_quiet
);
3013 static int check_unit_active(sd_bus
*bus
, char **args
) {
3014 /* According to LSB: 3, "program is not running" */
3015 return check_unit_generic(bus
, 3, "active\0reloading\0", args
+ 1);
3018 static int check_unit_failed(sd_bus
*bus
, char **args
) {
3019 return check_unit_generic(bus
, 1, "failed\0", args
+ 1);
3022 static int kill_unit(sd_bus
*bus
, char **args
) {
3023 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
3024 _cleanup_strv_free_
char **names
= NULL
;
3032 arg_kill_who
= "all";
3034 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
3036 log_error("Failed to expand names: %s", strerror(-r
));
3038 STRV_FOREACH(name
, names
) {
3039 q
= sd_bus_call_method(
3041 "org.freedesktop.systemd1",
3042 "/org/freedesktop/systemd1",
3043 "org.freedesktop.systemd1.Manager",
3047 "ssi", *names
, arg_kill_who
, arg_signal
);
3049 log_error("Failed to kill unit %s: %s",
3050 *names
, bus_error_message(&error
, r
));
3059 typedef struct ExecStatusInfo
{
3067 usec_t start_timestamp
;
3068 usec_t exit_timestamp
;
3073 LIST_FIELDS(struct ExecStatusInfo
, exec
);
3076 static void exec_status_info_free(ExecStatusInfo
*i
) {
3085 static int exec_status_info_deserialize(sd_bus_message
*m
, ExecStatusInfo
*i
) {
3086 uint64_t start_timestamp
, exit_timestamp
, start_timestamp_monotonic
, exit_timestamp_monotonic
;
3089 int32_t code
, status
;
3095 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_STRUCT
, "sasbttttuii");
3097 return bus_log_parse_error(r
);
3101 r
= sd_bus_message_read(m
, "s", &path
);
3103 return bus_log_parse_error(r
);
3105 i
->path
= strdup(path
);
3109 r
= sd_bus_message_read_strv(m
, &i
->argv
);
3111 return bus_log_parse_error(r
);
3113 r
= sd_bus_message_read(m
,
3116 &start_timestamp
, &start_timestamp_monotonic
,
3117 &exit_timestamp
, &exit_timestamp_monotonic
,
3121 return bus_log_parse_error(r
);
3124 i
->start_timestamp
= (usec_t
) start_timestamp
;
3125 i
->exit_timestamp
= (usec_t
) exit_timestamp
;
3126 i
->pid
= (pid_t
) pid
;
3130 r
= sd_bus_message_exit_container(m
);
3132 return bus_log_parse_error(r
);
3137 typedef struct UnitStatusInfo
{
3139 const char *load_state
;
3140 const char *active_state
;
3141 const char *sub_state
;
3142 const char *unit_file_state
;
3144 const char *description
;
3145 const char *following
;
3147 char **documentation
;
3149 const char *fragment_path
;
3150 const char *source_path
;
3151 const char *control_group
;
3153 char **dropin_paths
;
3155 const char *load_error
;
3158 usec_t inactive_exit_timestamp
;
3159 usec_t inactive_exit_timestamp_monotonic
;
3160 usec_t active_enter_timestamp
;
3161 usec_t active_exit_timestamp
;
3162 usec_t inactive_enter_timestamp
;
3164 bool need_daemon_reload
;
3169 const char *status_text
;
3170 const char *pid_file
;
3173 usec_t start_timestamp
;
3174 usec_t exit_timestamp
;
3176 int exit_code
, exit_status
;
3178 usec_t condition_timestamp
;
3179 bool condition_result
;
3180 bool failed_condition_trigger
;
3181 bool failed_condition_negate
;
3182 const char *failed_condition
;
3183 const char *failed_condition_param
;
3186 unsigned n_accepted
;
3187 unsigned n_connections
;
3190 /* Pairs of type, path */
3194 const char *sysfs_path
;
3196 /* Mount, Automount */
3202 LIST_HEAD(ExecStatusInfo
, exec
);
3205 static void print_status_info(
3210 const char *active_on
, *active_off
, *on
, *off
, *ss
;
3212 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], *s1
;
3213 char since2
[FORMAT_TIMESTAMP_MAX
], *s2
;
3216 arg_all
* OUTPUT_SHOW_ALL
|
3217 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH
|
3218 on_tty() * OUTPUT_COLOR
|
3219 !arg_quiet
* OUTPUT_WARN_CUTOFF
|
3220 arg_full
* OUTPUT_FULL_WIDTH
;
3225 /* This shows pretty information about a unit. See
3226 * print_property() for a low-level property printer */
3228 if (streq_ptr(i
->active_state
, "failed")) {
3229 active_on
= ansi_highlight_red();
3230 active_off
= ansi_highlight_off();
3231 } else if (streq_ptr(i
->active_state
, "active") || streq_ptr(i
->active_state
, "reloading")) {
3232 active_on
= ansi_highlight_green();
3233 active_off
= ansi_highlight_off();
3235 active_on
= active_off
= "";
3237 printf("%s%s%s %s", active_on
, draw_special_char(DRAW_BLACK_CIRCLE
), active_off
, strna(i
->id
));
3239 if (i
->description
&& !streq_ptr(i
->id
, i
->description
))
3240 printf(" - %s", i
->description
);
3245 printf(" Follow: unit currently follows state of %s\n", i
->following
);
3247 if (streq_ptr(i
->load_state
, "error")) {
3248 on
= ansi_highlight_red();
3249 off
= ansi_highlight_off();
3253 path
= i
->source_path
? i
->source_path
: i
->fragment_path
;
3256 printf(" Loaded: %s%s%s (Reason: %s)\n",
3257 on
, strna(i
->load_state
), off
, i
->load_error
);
3258 else if (path
&& i
->unit_file_state
)
3259 printf(" Loaded: %s%s%s (%s; %s)\n",
3260 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
);
3262 printf(" Loaded: %s%s%s (%s)\n",
3263 on
, strna(i
->load_state
), off
, path
);
3265 printf(" Loaded: %s%s%s\n",
3266 on
, strna(i
->load_state
), off
);
3268 if (!strv_isempty(i
->dropin_paths
)) {
3269 _cleanup_free_
char *dir
= NULL
;
3273 STRV_FOREACH(dropin
, i
->dropin_paths
) {
3274 if (! dir
|| last
) {
3275 printf(dir
? " " : " Drop-In: ");
3280 if (path_get_parent(*dropin
, &dir
) < 0) {
3285 printf("%s\n %s", dir
,
3286 draw_special_char(DRAW_TREE_RIGHT
));
3289 last
= ! (*(dropin
+ 1) && startswith(*(dropin
+ 1), dir
));
3291 printf("%s%s", basename(*dropin
), last
? "\n" : ", ");
3295 ss
= streq_ptr(i
->active_state
, i
->sub_state
) ? NULL
: i
->sub_state
;
3297 printf(" Active: %s%s (%s)%s",
3298 active_on
, strna(i
->active_state
), ss
, active_off
);
3300 printf(" Active: %s%s%s",
3301 active_on
, strna(i
->active_state
), active_off
);
3303 if (!isempty(i
->result
) && !streq(i
->result
, "success"))
3304 printf(" (Result: %s)", i
->result
);
3306 timestamp
= (streq_ptr(i
->active_state
, "active") ||
3307 streq_ptr(i
->active_state
, "reloading")) ? i
->active_enter_timestamp
:
3308 (streq_ptr(i
->active_state
, "inactive") ||
3309 streq_ptr(i
->active_state
, "failed")) ? i
->inactive_enter_timestamp
:
3310 streq_ptr(i
->active_state
, "activating") ? i
->inactive_exit_timestamp
:
3311 i
->active_exit_timestamp
;
3313 s1
= format_timestamp_relative(since1
, sizeof(since1
), timestamp
);
3314 s2
= format_timestamp(since2
, sizeof(since2
), timestamp
);
3317 printf(" since %s; %s\n", s2
, s1
);
3319 printf(" since %s\n", s2
);
3323 if (!i
->condition_result
&& i
->condition_timestamp
> 0) {
3324 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->condition_timestamp
);
3325 s2
= format_timestamp(since2
, sizeof(since2
), i
->condition_timestamp
);
3327 printf(" start condition failed at %s%s%s\n",
3328 s2
, s1
? "; " : "", s1
? s1
: "");
3329 if (i
->failed_condition_trigger
)
3330 printf(" none of the trigger conditions were met\n");
3331 else if (i
->failed_condition
)
3332 printf(" %s=%s%s was not met\n",
3333 i
->failed_condition
,
3334 i
->failed_condition_negate
? "!" : "",
3335 i
->failed_condition_param
);
3339 printf(" Device: %s\n", i
->sysfs_path
);
3341 printf(" Where: %s\n", i
->where
);
3343 printf(" What: %s\n", i
->what
);
3345 STRV_FOREACH(t
, i
->documentation
)
3346 printf(" %*s %s\n", 9, t
== i
->documentation
? "Docs:" : "", *t
);
3348 STRV_FOREACH_PAIR(t
, t2
, i
->listen
)
3349 printf(" %*s %s (%s)\n", 9, t
== i
->listen
? "Listen:" : "", *t2
, *t
);
3352 printf(" Accepted: %u; Connected: %u\n", i
->n_accepted
, i
->n_connections
);
3354 LIST_FOREACH(exec
, p
, i
->exec
) {
3355 _cleanup_free_
char *argv
= NULL
;
3358 /* Only show exited processes here */
3362 argv
= strv_join(p
->argv
, " ");
3363 printf(" Process: %u %s=%s ", p
->pid
, p
->name
, strna(argv
));
3365 good
= is_clean_exit_lsb(p
->code
, p
->status
, NULL
);
3367 on
= ansi_highlight_red();
3368 off
= ansi_highlight_off();
3372 printf("%s(code=%s, ", on
, sigchld_code_to_string(p
->code
));
3374 if (p
->code
== CLD_EXITED
) {
3377 printf("status=%i", p
->status
);
3379 c
= exit_status_to_string(p
->status
, EXIT_STATUS_SYSTEMD
);
3384 printf("signal=%s", signal_to_string(p
->status
));
3386 printf(")%s\n", off
);
3388 if (i
->main_pid
== p
->pid
&&
3389 i
->start_timestamp
== p
->start_timestamp
&&
3390 i
->exit_timestamp
== p
->start_timestamp
)
3391 /* Let's not show this twice */
3394 if (p
->pid
== i
->control_pid
)
3398 if (i
->main_pid
> 0 || i
->control_pid
> 0) {
3399 if (i
->main_pid
> 0) {
3400 printf(" Main PID: %u", (unsigned) i
->main_pid
);
3403 _cleanup_free_
char *comm
= NULL
;
3404 get_process_comm(i
->main_pid
, &comm
);
3406 printf(" (%s)", comm
);
3407 } else if (i
->exit_code
> 0) {
3408 printf(" (code=%s, ", sigchld_code_to_string(i
->exit_code
));
3410 if (i
->exit_code
== CLD_EXITED
) {
3413 printf("status=%i", i
->exit_status
);
3415 c
= exit_status_to_string(i
->exit_status
, EXIT_STATUS_SYSTEMD
);
3420 printf("signal=%s", signal_to_string(i
->exit_status
));
3424 if (i
->control_pid
> 0)
3428 if (i
->control_pid
> 0) {
3429 _cleanup_free_
char *c
= NULL
;
3431 printf(" %8s: %u", i
->main_pid
? "" : " Control", (unsigned) i
->control_pid
);
3433 get_process_comm(i
->control_pid
, &c
);
3442 printf(" Status: \"%s\"\n", i
->status_text
);
3444 if (i
->control_group
&&
3445 (i
->main_pid
> 0 || i
->control_pid
> 0 ||
3446 ((arg_transport
!= BUS_TRANSPORT_LOCAL
&& arg_transport
!= BUS_TRANSPORT_CONTAINER
) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, false) == 0))) {
3449 printf(" CGroup: %s\n", i
->control_group
);
3451 if (arg_transport
== BUS_TRANSPORT_LOCAL
|| arg_transport
== BUS_TRANSPORT_CONTAINER
) {
3454 static const char prefix
[] = " ";
3457 if (c
> sizeof(prefix
) - 1)
3458 c
-= sizeof(prefix
) - 1;
3462 if (i
->main_pid
> 0)
3463 extra
[k
++] = i
->main_pid
;
3465 if (i
->control_pid
> 0)
3466 extra
[k
++] = i
->control_pid
;
3468 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, prefix
, c
, false, extra
, k
, flags
);
3472 if (i
->id
&& arg_transport
== BUS_TRANSPORT_LOCAL
) {
3473 show_journal_by_unit(stdout
,
3477 i
->inactive_exit_timestamp_monotonic
,
3480 flags
| OUTPUT_BEGIN_NEWLINE
,
3481 arg_scope
== UNIT_FILE_SYSTEM
,
3485 if (i
->need_daemon_reload
)
3486 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
3487 ansi_highlight_red(),
3488 ansi_highlight_off(),
3489 arg_scope
== UNIT_FILE_SYSTEM
? "" : "--user ");
3492 static void show_unit_help(UnitStatusInfo
*i
) {
3497 if (!i
->documentation
) {
3498 log_info("Documentation for %s not known.", i
->id
);
3502 STRV_FOREACH(p
, i
->documentation
) {
3504 if (startswith(*p
, "man:")) {
3505 const char *args
[4] = { "man", NULL
, NULL
, NULL
};
3506 _cleanup_free_
char *page
= NULL
, *section
= NULL
;
3513 if ((*p
)[k
-1] == ')')
3514 e
= strrchr(*p
, '(');
3517 page
= strndup((*p
) + 4, e
- *p
- 4);
3518 section
= strndup(e
+ 1, *p
+ k
- e
- 2);
3519 if (!page
|| !section
) {
3531 log_error("Failed to fork: %m");
3537 execvp(args
[0], (char**) args
);
3538 log_error("Failed to execute man: %m");
3539 _exit(EXIT_FAILURE
);
3542 wait_for_terminate(pid
, NULL
);
3544 log_info("Can't show: %s", *p
);
3548 static int status_property(const char *name
, sd_bus_message
*m
, UnitStatusInfo
*i
, const char *contents
) {
3555 switch (contents
[0]) {
3557 case SD_BUS_TYPE_STRING
: {
3560 r
= sd_bus_message_read(m
, "s", &s
);
3562 return bus_log_parse_error(r
);
3565 if (streq(name
, "Id"))
3567 else if (streq(name
, "LoadState"))
3569 else if (streq(name
, "ActiveState"))
3570 i
->active_state
= s
;
3571 else if (streq(name
, "SubState"))
3573 else if (streq(name
, "Description"))
3575 else if (streq(name
, "FragmentPath"))
3576 i
->fragment_path
= s
;
3577 else if (streq(name
, "SourcePath"))
3580 else if (streq(name
, "DefaultControlGroup")) {
3582 e
= startswith(s
, SYSTEMD_CGROUP_CONTROLLER
":");
3584 i
->control_group
= e
;
3587 else if (streq(name
, "ControlGroup"))
3588 i
->control_group
= s
;
3589 else if (streq(name
, "StatusText"))
3591 else if (streq(name
, "PIDFile"))
3593 else if (streq(name
, "SysFSPath"))
3595 else if (streq(name
, "Where"))
3597 else if (streq(name
, "What"))
3599 else if (streq(name
, "Following"))
3601 else if (streq(name
, "UnitFileState"))
3602 i
->unit_file_state
= s
;
3603 else if (streq(name
, "Result"))
3610 case SD_BUS_TYPE_BOOLEAN
: {
3613 r
= sd_bus_message_read(m
, "b", &b
);
3615 return bus_log_parse_error(r
);
3617 if (streq(name
, "Accept"))
3619 else if (streq(name
, "NeedDaemonReload"))
3620 i
->need_daemon_reload
= b
;
3621 else if (streq(name
, "ConditionResult"))
3622 i
->condition_result
= b
;
3627 case SD_BUS_TYPE_UINT32
: {
3630 r
= sd_bus_message_read(m
, "u", &u
);
3632 return bus_log_parse_error(r
);
3634 if (streq(name
, "MainPID")) {
3636 i
->main_pid
= (pid_t
) u
;
3639 } else if (streq(name
, "ControlPID"))
3640 i
->control_pid
= (pid_t
) u
;
3641 else if (streq(name
, "ExecMainPID")) {
3643 i
->main_pid
= (pid_t
) u
;
3644 } else if (streq(name
, "NAccepted"))
3646 else if (streq(name
, "NConnections"))
3647 i
->n_connections
= u
;
3652 case SD_BUS_TYPE_INT32
: {
3655 r
= sd_bus_message_read(m
, "i", &j
);
3657 return bus_log_parse_error(r
);
3659 if (streq(name
, "ExecMainCode"))
3660 i
->exit_code
= (int) j
;
3661 else if (streq(name
, "ExecMainStatus"))
3662 i
->exit_status
= (int) j
;
3667 case SD_BUS_TYPE_UINT64
: {
3670 r
= sd_bus_message_read(m
, "t", &u
);
3672 return bus_log_parse_error(r
);
3674 if (streq(name
, "ExecMainStartTimestamp"))
3675 i
->start_timestamp
= (usec_t
) u
;
3676 else if (streq(name
, "ExecMainExitTimestamp"))
3677 i
->exit_timestamp
= (usec_t
) u
;
3678 else if (streq(name
, "ActiveEnterTimestamp"))
3679 i
->active_enter_timestamp
= (usec_t
) u
;
3680 else if (streq(name
, "InactiveEnterTimestamp"))
3681 i
->inactive_enter_timestamp
= (usec_t
) u
;
3682 else if (streq(name
, "InactiveExitTimestamp"))
3683 i
->inactive_exit_timestamp
= (usec_t
) u
;
3684 else if (streq(name
, "InactiveExitTimestampMonotonic"))
3685 i
->inactive_exit_timestamp_monotonic
= (usec_t
) u
;
3686 else if (streq(name
, "ActiveExitTimestamp"))
3687 i
->active_exit_timestamp
= (usec_t
) u
;
3688 else if (streq(name
, "ConditionTimestamp"))
3689 i
->condition_timestamp
= (usec_t
) u
;
3694 case SD_BUS_TYPE_ARRAY
:
3696 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
3697 _cleanup_free_ ExecStatusInfo
*info
= NULL
;
3699 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
3701 return bus_log_parse_error(r
);
3703 info
= new0(ExecStatusInfo
, 1);
3707 while ((r
= exec_status_info_deserialize(m
, info
)) > 0) {
3709 info
->name
= strdup(name
);
3713 LIST_PREPEND(exec
, i
->exec
, info
);
3715 info
= new0(ExecStatusInfo
, 1);
3721 return bus_log_parse_error(r
);
3723 r
= sd_bus_message_exit_container(m
);
3725 return bus_log_parse_error(r
);
3729 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
3730 const char *type
, *path
;
3732 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
3734 return bus_log_parse_error(r
);
3736 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0) {
3738 r
= strv_extend(&i
->listen
, type
);
3742 r
= strv_extend(&i
->listen
, path
);
3747 return bus_log_parse_error(r
);
3749 r
= sd_bus_message_exit_container(m
);
3751 return bus_log_parse_error(r
);
3755 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "DropInPaths")) {
3757 r
= sd_bus_message_read_strv(m
, &i
->dropin_paths
);
3759 return bus_log_parse_error(r
);
3761 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Documentation")) {
3763 r
= sd_bus_message_read_strv(m
, &i
->documentation
);
3765 return bus_log_parse_error(r
);
3767 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Conditions")) {
3768 const char *cond
, *param
;
3769 int trigger
, negate
;
3772 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
3774 return bus_log_parse_error(r
);
3776 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
3777 log_debug("%s %d %d %s %d", cond
, trigger
, negate
, param
, state
);
3778 if (state
< 0 && (!trigger
|| !i
->failed_condition
)) {
3779 i
->failed_condition
= cond
;
3780 i
->failed_condition_trigger
= trigger
;
3781 i
->failed_condition_negate
= negate
;
3782 i
->failed_condition_param
= param
;
3786 return bus_log_parse_error(r
);
3788 r
= sd_bus_message_exit_container(m
);
3790 return bus_log_parse_error(r
);
3797 case SD_BUS_TYPE_STRUCT_BEGIN
:
3799 if (streq(name
, "LoadError")) {
3800 const char *n
, *message
;
3802 r
= sd_bus_message_read(m
, "(ss)", &n
, &message
);
3804 return bus_log_parse_error(r
);
3806 if (!isempty(message
))
3807 i
->load_error
= message
;
3820 r
= sd_bus_message_skip(m
, contents
);
3822 return bus_log_parse_error(r
);
3827 static int print_property(const char *name
, sd_bus_message
*m
, const char *contents
) {
3833 /* This is a low-level property printer, see
3834 * print_status_info() for the nicer output */
3836 if (arg_properties
&& !strv_find(arg_properties
, name
)) {
3837 /* skip what we didn't read */
3838 r
= sd_bus_message_skip(m
, contents
);
3842 switch (contents
[0]) {
3844 case SD_BUS_TYPE_STRUCT_BEGIN
:
3846 if (contents
[1] == SD_BUS_TYPE_UINT32
&& streq(name
, "Job")) {
3849 r
= sd_bus_message_read(m
, "(uo)", &u
, NULL
);
3851 return bus_log_parse_error(r
);
3854 printf("%s=%u\n", name
, (unsigned) u
);
3856 printf("%s=\n", name
);
3860 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Unit")) {
3863 r
= sd_bus_message_read(m
, "(so)", &s
, NULL
);
3865 return bus_log_parse_error(r
);
3867 if (arg_all
|| !isempty(s
))
3868 printf("%s=%s\n", name
, s
);
3872 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "LoadError")) {
3873 const char *a
= NULL
, *b
= NULL
;
3875 r
= sd_bus_message_read(m
, "(ss)", &a
, &b
);
3877 return bus_log_parse_error(r
);
3879 if (arg_all
|| !isempty(a
) || !isempty(b
))
3880 printf("%s=%s \"%s\"\n", name
, strempty(a
), strempty(b
));
3883 } else if (streq_ptr(name
, "SystemCallFilter")) {
3884 _cleanup_strv_free_
char **l
= NULL
;
3887 r
= sd_bus_message_enter_container(m
, 'r', "bas");
3889 return bus_log_parse_error(r
);
3891 r
= sd_bus_message_read(m
, "b", &whitelist
);
3893 return bus_log_parse_error(r
);
3895 r
= sd_bus_message_read_strv(m
, &l
);
3897 return bus_log_parse_error(r
);
3899 r
= sd_bus_message_exit_container(m
);
3901 return bus_log_parse_error(r
);
3903 if (arg_all
|| whitelist
|| !strv_isempty(l
)) {
3907 fputs(name
, stdout
);
3913 STRV_FOREACH(i
, l
) {
3921 fputc('\n', stdout
);
3929 case SD_BUS_TYPE_ARRAY
:
3931 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "EnvironmentFiles")) {
3935 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sb)");
3937 return bus_log_parse_error(r
);
3939 while ((r
= sd_bus_message_read(m
, "(sb)", &path
, &ignore
)) > 0)
3940 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path
, yes_no(ignore
));
3943 return bus_log_parse_error(r
);
3945 r
= sd_bus_message_exit_container(m
);
3947 return bus_log_parse_error(r
);
3951 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Paths")) {
3952 const char *type
, *path
;
3954 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
3956 return bus_log_parse_error(r
);
3958 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
3959 printf("%s=%s\n", type
, path
);
3961 return bus_log_parse_error(r
);
3963 r
= sd_bus_message_exit_container(m
);
3965 return bus_log_parse_error(r
);
3969 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
3970 const char *type
, *path
;
3972 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
3974 return bus_log_parse_error(r
);
3976 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
3977 printf("Listen%s=%s\n", type
, path
);
3979 return bus_log_parse_error(r
);
3981 r
= sd_bus_message_exit_container(m
);
3983 return bus_log_parse_error(r
);
3987 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Timers")) {
3989 uint64_t value
, next_elapse
;
3991 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(stt)");
3993 return bus_log_parse_error(r
);
3995 while ((r
= sd_bus_message_read(m
, "(stt)", &base
, &value
, &next_elapse
)) > 0) {
3996 char timespan1
[FORMAT_TIMESPAN_MAX
], timespan2
[FORMAT_TIMESPAN_MAX
];
3998 printf("%s={ value=%s ; next_elapse=%s }\n",
4000 format_timespan(timespan1
, sizeof(timespan1
), value
, 0),
4001 format_timespan(timespan2
, sizeof(timespan2
), next_elapse
, 0));
4004 return bus_log_parse_error(r
);
4006 r
= sd_bus_message_exit_container(m
);
4008 return bus_log_parse_error(r
);
4012 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
4013 ExecStatusInfo info
= {};
4015 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4017 return bus_log_parse_error(r
);
4019 while ((r
= exec_status_info_deserialize(m
, &info
)) > 0) {
4020 char timestamp1
[FORMAT_TIMESTAMP_MAX
], timestamp2
[FORMAT_TIMESTAMP_MAX
];
4021 _cleanup_free_
char *tt
;
4023 tt
= strv_join(info
.argv
, " ");
4025 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
4029 yes_no(info
.ignore
),
4030 strna(format_timestamp(timestamp1
, sizeof(timestamp1
), info
.start_timestamp
)),
4031 strna(format_timestamp(timestamp2
, sizeof(timestamp2
), info
.exit_timestamp
)),
4032 (unsigned) info
. pid
,
4033 sigchld_code_to_string(info
.code
),
4035 info
.code
== CLD_EXITED
? "" : "/",
4036 strempty(info
.code
== CLD_EXITED
? NULL
: signal_to_string(info
.status
)));
4039 strv_free(info
.argv
);
4043 r
= sd_bus_message_exit_container(m
);
4045 return bus_log_parse_error(r
);
4049 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "DeviceAllow")) {
4050 const char *path
, *rwm
;
4052 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4054 return bus_log_parse_error(r
);
4056 while ((r
= sd_bus_message_read(m
, "(ss)", &path
, &rwm
)) > 0)
4057 printf("%s=%s %s\n", name
, strna(path
), strna(rwm
));
4059 return bus_log_parse_error(r
);
4061 r
= sd_bus_message_exit_container(m
);
4063 return bus_log_parse_error(r
);
4067 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "BlockIODeviceWeight")) {
4071 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4073 return bus_log_parse_error(r
);
4075 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &weight
)) > 0)
4076 printf("%s=%s %" PRIu64
"\n", name
, strna(path
), weight
);
4078 return bus_log_parse_error(r
);
4080 r
= sd_bus_message_exit_container(m
);
4082 return bus_log_parse_error(r
);
4086 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& (streq(name
, "BlockIOReadBandwidth") || streq(name
, "BlockIOWriteBandwidth"))) {
4090 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4092 return bus_log_parse_error(r
);
4094 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &bandwidth
)) > 0)
4095 printf("%s=%s %" PRIu64
"\n", name
, strna(path
), bandwidth
);
4097 return bus_log_parse_error(r
);
4099 r
= sd_bus_message_exit_container(m
);
4101 return bus_log_parse_error(r
);
4109 r
= bus_print_property(name
, m
, arg_all
);
4111 return bus_log_parse_error(r
);
4114 r
= sd_bus_message_skip(m
, contents
);
4116 return bus_log_parse_error(r
);
4119 printf("%s=[unprintable]\n", name
);
4125 static int show_one(
4129 bool show_properties
,
4133 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4134 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4135 UnitStatusInfo info
= {};
4142 log_debug("Showing one %s", path
);
4144 r
= sd_bus_call_method(
4146 "org.freedesktop.systemd1",
4148 "org.freedesktop.DBus.Properties",
4154 log_error("Failed to get properties: %s", bus_error_message(&error
, r
));
4158 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
4160 return bus_log_parse_error(r
);
4167 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
4168 const char *name
, *contents
;
4170 r
= sd_bus_message_read(reply
, "s", &name
);
4172 return bus_log_parse_error(r
);
4174 r
= sd_bus_message_peek_type(reply
, NULL
, &contents
);
4176 return bus_log_parse_error(r
);
4178 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, contents
);
4180 return bus_log_parse_error(r
);
4182 if (show_properties
)
4183 r
= print_property(name
, reply
, contents
);
4185 r
= status_property(name
, reply
, &info
, contents
);
4189 r
= sd_bus_message_exit_container(reply
);
4191 return bus_log_parse_error(r
);
4193 r
= sd_bus_message_exit_container(reply
);
4195 return bus_log_parse_error(r
);
4198 return bus_log_parse_error(r
);
4200 r
= sd_bus_message_exit_container(reply
);
4202 return bus_log_parse_error(r
);
4206 if (!show_properties
) {
4207 if (streq(verb
, "help"))
4208 show_unit_help(&info
);
4210 print_status_info(&info
, ellipsized
);
4213 strv_free(info
.documentation
);
4214 strv_free(info
.dropin_paths
);
4215 strv_free(info
.listen
);
4217 if (!streq_ptr(info
.active_state
, "active") &&
4218 !streq_ptr(info
.active_state
, "reloading") &&
4219 streq(verb
, "status")) {
4220 /* According to LSB: "program not running" */
4221 /* 0: program is running or service is OK
4222 * 1: program is dead and /run PID file exists
4223 * 2: program is dead and /run/lock lock file exists
4224 * 3: program is not running
4225 * 4: program or service status is unknown
4227 if (info
.pid_file
&& access(info
.pid_file
, F_OK
) == 0)
4233 while ((p
= info
.exec
)) {
4234 LIST_REMOVE(exec
, info
.exec
, p
);
4235 exec_status_info_free(p
);
4241 static int get_unit_dbus_path_by_pid(
4246 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4247 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4251 r
= sd_bus_call_method(
4253 "org.freedesktop.systemd1",
4254 "/org/freedesktop/systemd1",
4255 "org.freedesktop.systemd1.Manager",
4261 log_error("Failed to get unit for PID "PID_FMT
": %s", pid
, bus_error_message(&error
, r
));
4265 r
= sd_bus_message_read(reply
, "o", &u
);
4267 return bus_log_parse_error(r
);
4277 static int show_all(
4280 bool show_properties
,
4284 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4285 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
4290 r
= get_unit_list(bus
, NULL
, NULL
, &unit_infos
, 0, &reply
);
4294 pager_open_if_enabled();
4298 qsort_safe(unit_infos
, c
, sizeof(UnitInfo
), compare_unit_info
);
4300 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
4301 _cleanup_free_
char *p
= NULL
;
4303 p
= unit_dbus_path_from_name(u
->id
);
4307 r
= show_one(verb
, bus
, p
, show_properties
, new_line
, ellipsized
);
4310 else if (r
> 0 && ret
== 0)
4317 static int show_system_status(sd_bus
*bus
) {
4318 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], since2
[FORMAT_TIMESTAMP_MAX
];
4319 _cleanup_free_
char *hn
= NULL
;
4320 struct machine_info mi
= {};
4321 const char *on
, *off
;
4324 hn
= gethostname_malloc();
4328 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, &mi
);
4330 log_error("Failed to read server status: %s", strerror(-r
));
4334 if (streq_ptr(mi
.state
, "degraded")) {
4335 on
= ansi_highlight_red();
4336 off
= ansi_highlight_off();
4337 } else if (!streq_ptr(mi
.state
, "running")) {
4338 on
= ansi_highlight_yellow();
4339 off
= ansi_highlight_off();
4343 printf("%s%s%s %s\n", on
, draw_special_char(DRAW_BLACK_CIRCLE
), off
, arg_host
? arg_host
: hn
);
4345 printf(" State: %s%s%s\n",
4346 on
, strna(mi
.state
), off
);
4348 printf(" Jobs: %u queued\n", mi
.n_jobs
);
4349 printf(" Failed: %u units\n", mi
.n_failed_units
);
4351 printf(" Since: %s; %s\n",
4352 format_timestamp(since2
, sizeof(since2
), mi
.timestamp
),
4353 format_timestamp_relative(since1
, sizeof(since1
), mi
.timestamp
));
4355 printf(" CGroup: %s\n", mi
.control_group
?: "/");
4356 if (arg_transport
== BUS_TRANSPORT_LOCAL
|| arg_transport
== BUS_TRANSPORT_CONTAINER
) {
4358 arg_all
* OUTPUT_SHOW_ALL
|
4359 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH
|
4360 on_tty() * OUTPUT_COLOR
|
4361 !arg_quiet
* OUTPUT_WARN_CUTOFF
|
4362 arg_full
* OUTPUT_FULL_WIDTH
;
4364 static const char prefix
[] = " ";
4368 if (c
> sizeof(prefix
) - 1)
4369 c
-= sizeof(prefix
) - 1;
4373 show_cgroup(SYSTEMD_CGROUP_CONTROLLER
, strempty(mi
.control_group
), prefix
, c
, false, flags
);
4377 free(mi
.control_group
);
4382 static int show(sd_bus
*bus
, char **args
) {
4383 bool show_properties
, show_status
, new_line
= false;
4384 bool ellipsized
= false;
4390 show_properties
= streq(args
[0], "show");
4391 show_status
= streq(args
[0], "status");
4393 if (show_properties
)
4394 pager_open_if_enabled();
4396 /* If no argument is specified inspect the manager itself */
4398 if (show_properties
&& strv_length(args
) <= 1)
4399 return show_one(args
[0], bus
, "/org/freedesktop/systemd1", show_properties
, &new_line
, &ellipsized
);
4401 if (show_status
&& strv_length(args
) <= 1) {
4403 pager_open_if_enabled();
4404 show_system_status(bus
);
4408 ret
= show_all(args
[0], bus
, false, &new_line
, &ellipsized
);
4410 _cleanup_free_
char **patterns
= NULL
;
4413 STRV_FOREACH(name
, args
+ 1) {
4414 _cleanup_free_
char *unit
= NULL
;
4417 if (safe_atou32(*name
, &id
) < 0) {
4418 if (strv_push(&patterns
, *name
) < 0)
4422 } else if (show_properties
) {
4423 /* Interpret as job id */
4424 if (asprintf(&unit
, "/org/freedesktop/systemd1/job/%u", id
) < 0)
4428 /* Interpret as PID */
4429 r
= get_unit_dbus_path_by_pid(bus
, id
, &unit
);
4436 r
= show_one(args
[0], bus
, unit
, show_properties
,
4437 &new_line
, &ellipsized
);
4440 else if (r
> 0 && ret
== 0)
4444 if (!strv_isempty(patterns
)) {
4445 _cleanup_strv_free_
char **names
= NULL
;
4447 r
= expand_names(bus
, patterns
, NULL
, &names
);
4449 log_error("Failed to expand names: %s", strerror(-r
));
4451 STRV_FOREACH(name
, names
) {
4452 _cleanup_free_
char *unit
;
4454 unit
= unit_dbus_path_from_name(*name
);
4458 r
= show_one(args
[0], bus
, unit
, show_properties
,
4459 &new_line
, &ellipsized
);
4462 else if (r
> 0 && ret
== 0)
4468 if (ellipsized
&& !arg_quiet
)
4469 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4474 static int cat(sd_bus
*bus
, char **args
) {
4475 _cleanup_free_
char *unit
= NULL
;
4476 _cleanup_strv_free_
char **names
= NULL
;
4484 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
4486 log_error("Failed to expand names: %s", strerror(-r
));
4488 pager_open_if_enabled();
4490 STRV_FOREACH(name
, names
) {
4491 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4492 _cleanup_strv_free_
char **dropin_paths
= NULL
;
4493 _cleanup_free_
char *fragment_path
= NULL
;
4496 unit
= unit_dbus_path_from_name(*name
);
4500 if (need_daemon_reload(bus
, *name
) > 0)
4501 log_warning("Unit file of %s changed on disk. Run 'systemctl%s daemon-reload'.",
4502 *name
, arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user");
4504 r
= sd_bus_get_property_string(
4506 "org.freedesktop.systemd1",
4508 "org.freedesktop.systemd1.Unit",
4513 log_warning("Failed to get FragmentPath: %s", bus_error_message(&error
, r
));
4517 r
= sd_bus_get_property_strv(
4519 "org.freedesktop.systemd1",
4521 "org.freedesktop.systemd1.Unit",
4526 log_warning("Failed to get DropInPaths: %s", bus_error_message(&error
, r
));
4535 if (!isempty(fragment_path
)) {
4536 printf("%s# %s%s\n",
4537 ansi_highlight_blue(),
4539 ansi_highlight_off());
4542 r
= sendfile_full(STDOUT_FILENO
, fragment_path
);
4544 log_warning("Failed to cat %s: %s", fragment_path
, strerror(-r
));
4549 STRV_FOREACH(path
, dropin_paths
) {
4550 printf("%s%s# %s%s\n",
4551 isempty(fragment_path
) && path
== dropin_paths
? "" : "\n",
4552 ansi_highlight_blue(),
4554 ansi_highlight_off());
4557 r
= sendfile_full(STDOUT_FILENO
, *path
);
4559 log_warning("Failed to cat %s: %s", *path
, strerror(-r
));
4565 return r
< 0 ? r
: 0;
4568 static int set_property(sd_bus
*bus
, char **args
) {
4569 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
4570 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4571 _cleanup_free_
char *n
= NULL
;
4575 r
= sd_bus_message_new_method_call(
4578 "org.freedesktop.systemd1",
4579 "/org/freedesktop/systemd1",
4580 "org.freedesktop.systemd1.Manager",
4581 "SetUnitProperties");
4583 return bus_log_create_error(r
);
4585 n
= unit_name_mangle(args
[1], MANGLE_NOGLOB
);
4589 r
= sd_bus_message_append(m
, "sb", n
, arg_runtime
);
4591 return bus_log_create_error(r
);
4593 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, "(sv)");
4595 return bus_log_create_error(r
);
4597 STRV_FOREACH(i
, args
+ 2) {
4598 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_STRUCT
, "sv");
4600 return bus_log_create_error(r
);
4602 r
= bus_append_unit_property_assignment(m
, *i
);
4606 r
= sd_bus_message_close_container(m
);
4608 return bus_log_create_error(r
);
4611 r
= sd_bus_message_close_container(m
);
4613 return bus_log_create_error(r
);
4615 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
4617 log_error("Failed to set unit properties on %s: %s", n
, bus_error_message(&error
, r
));
4624 static int snapshot(sd_bus
*bus
, char **args
) {
4625 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4626 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4627 _cleanup_free_
char *n
= NULL
, *id
= NULL
;
4631 if (strv_length(args
) > 1)
4632 n
= unit_name_mangle_with_suffix(args
[1], MANGLE_NOGLOB
, ".snapshot");
4638 r
= sd_bus_call_method(
4640 "org.freedesktop.systemd1",
4641 "/org/freedesktop/systemd1",
4642 "org.freedesktop.systemd1.Manager",
4648 log_error("Failed to create snapshot: %s", bus_error_message(&error
, r
));
4652 r
= sd_bus_message_read(reply
, "o", &path
);
4654 return bus_log_parse_error(r
);
4656 r
= sd_bus_get_property_string(
4658 "org.freedesktop.systemd1",
4660 "org.freedesktop.systemd1.Unit",
4665 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error
, r
));
4675 static int delete_snapshot(sd_bus
*bus
, char **args
) {
4676 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4677 _cleanup_strv_free_
char **names
= NULL
;
4683 r
= expand_names(bus
, args
+ 1, ".snapshot", &names
);
4685 log_error("Failed to expand names: %s", strerror(-r
));
4687 STRV_FOREACH(name
, names
) {
4688 q
= sd_bus_call_method(
4690 "org.freedesktop.systemd1",
4691 "/org/freedesktop/systemd1",
4692 "org.freedesktop.systemd1.Manager",
4698 log_error("Failed to remove snapshot %s: %s",
4699 *name
, bus_error_message(&error
, r
));
4708 static int daemon_reload(sd_bus
*bus
, char **args
) {
4709 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4713 if (arg_action
== ACTION_RELOAD
)
4715 else if (arg_action
== ACTION_REEXEC
)
4716 method
= "Reexecute";
4718 assert(arg_action
== ACTION_SYSTEMCTL
);
4721 streq(args
[0], "clear-jobs") ||
4722 streq(args
[0], "cancel") ? "ClearJobs" :
4723 streq(args
[0], "daemon-reexec") ? "Reexecute" :
4724 streq(args
[0], "reset-failed") ? "ResetFailed" :
4725 streq(args
[0], "halt") ? "Halt" :
4726 streq(args
[0], "poweroff") ? "PowerOff" :
4727 streq(args
[0], "reboot") ? "Reboot" :
4728 streq(args
[0], "kexec") ? "KExec" :
4729 streq(args
[0], "exit") ? "Exit" :
4730 /* "daemon-reload" */ "Reload";
4733 r
= sd_bus_call_method(
4735 "org.freedesktop.systemd1",
4736 "/org/freedesktop/systemd1",
4737 "org.freedesktop.systemd1.Manager",
4743 if (r
== -ENOENT
&& arg_action
!= ACTION_SYSTEMCTL
)
4744 /* There's always a fallback possible for
4745 * legacy actions. */
4747 else if ((r
== -ETIMEDOUT
|| r
== -ECONNRESET
) && streq(method
, "Reexecute"))
4748 /* On reexecution, we expect a disconnect, not a
4752 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
4754 return r
< 0 ? r
: 0;
4757 static int reset_failed(sd_bus
*bus
, char **args
) {
4758 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4759 _cleanup_strv_free_
char **names
= NULL
;
4763 if (strv_length(args
) <= 1)
4764 return daemon_reload(bus
, args
);
4766 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
4768 log_error("Failed to expand names: %s", strerror(-r
));
4770 STRV_FOREACH(name
, names
) {
4771 q
= sd_bus_call_method(
4773 "org.freedesktop.systemd1",
4774 "/org/freedesktop/systemd1",
4775 "org.freedesktop.systemd1.Manager",
4781 log_error("Failed to reset failed state of unit %s: %s",
4782 *name
, bus_error_message(&error
, r
));
4791 static int show_environment(sd_bus
*bus
, char **args
) {
4792 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4793 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4797 pager_open_if_enabled();
4799 r
= sd_bus_get_property(
4801 "org.freedesktop.systemd1",
4802 "/org/freedesktop/systemd1",
4803 "org.freedesktop.systemd1.Manager",
4809 log_error("Failed to get environment: %s", bus_error_message(&error
, r
));
4813 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
4815 return bus_log_parse_error(r
);
4817 while ((r
= sd_bus_message_read_basic(reply
, SD_BUS_TYPE_STRING
, &text
)) > 0)
4820 return bus_log_parse_error(r
);
4822 r
= sd_bus_message_exit_container(reply
);
4824 return bus_log_parse_error(r
);
4829 static int switch_root(sd_bus
*bus
, char **args
) {
4830 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4831 _cleanup_free_
char *cmdline_init
= NULL
;
4832 const char *root
, *init
;
4836 l
= strv_length(args
);
4837 if (l
< 2 || l
> 3) {
4838 log_error("Wrong number of arguments.");
4847 r
= parse_env_file("/proc/cmdline", WHITESPACE
,
4848 "init", &cmdline_init
,
4851 log_debug("Failed to parse /proc/cmdline: %s", strerror(-r
));
4853 init
= cmdline_init
;
4860 const char *root_systemd_path
= NULL
, *root_init_path
= NULL
;
4862 root_systemd_path
= strappenda(root
, "/" SYSTEMD_BINARY_PATH
);
4863 root_init_path
= strappenda3(root
, "/", init
);
4865 /* If the passed init is actually the same as the
4866 * systemd binary, then let's suppress it. */
4867 if (files_same(root_init_path
, root_systemd_path
) > 0)
4871 log_debug("Switching root - root: %s; init: %s", root
, strna(init
));
4873 r
= sd_bus_call_method(
4875 "org.freedesktop.systemd1",
4876 "/org/freedesktop/systemd1",
4877 "org.freedesktop.systemd1.Manager",
4883 log_error("Failed to switch root: %s", bus_error_message(&error
, r
));
4890 static int set_environment(sd_bus
*bus
, char **args
) {
4891 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4892 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
4899 method
= streq(args
[0], "set-environment")
4901 : "UnsetEnvironment";
4903 r
= sd_bus_message_new_method_call(
4906 "org.freedesktop.systemd1",
4907 "/org/freedesktop/systemd1",
4908 "org.freedesktop.systemd1.Manager",
4911 return bus_log_create_error(r
);
4913 r
= sd_bus_message_append_strv(m
, args
+ 1);
4915 return bus_log_create_error(r
);
4917 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
4919 log_error("Failed to set environment: %s", bus_error_message(&error
, r
));
4926 static int import_environment(sd_bus
*bus
, char **args
) {
4927 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4928 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
4934 r
= sd_bus_message_new_method_call(
4937 "org.freedesktop.systemd1",
4938 "/org/freedesktop/systemd1",
4939 "org.freedesktop.systemd1.Manager",
4942 return bus_log_create_error(r
);
4944 if (strv_isempty(args
+ 1))
4945 r
= sd_bus_message_append_strv(m
, environ
);
4949 r
= sd_bus_message_open_container(m
, 'a', "s");
4951 return bus_log_create_error(r
);
4953 STRV_FOREACH(a
, args
+ 1) {
4955 if (!env_name_is_valid(*a
)) {
4956 log_error("Not a valid environment variable name: %s", *a
);
4960 STRV_FOREACH(b
, environ
) {
4963 eq
= startswith(*b
, *a
);
4964 if (eq
&& *eq
== '=') {
4966 r
= sd_bus_message_append(m
, "s", *b
);
4968 return bus_log_create_error(r
);
4975 r
= sd_bus_message_close_container(m
);
4978 return bus_log_create_error(r
);
4980 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
4982 log_error("Failed to import environment: %s", bus_error_message(&error
, r
));
4989 static int enable_sysv_units(const char *verb
, char **args
) {
4992 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4993 unsigned f
= 1, t
= 1;
4994 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
4996 if (arg_scope
!= UNIT_FILE_SYSTEM
)
4999 if (!streq(verb
, "enable") &&
5000 !streq(verb
, "disable") &&
5001 !streq(verb
, "is-enabled"))
5004 /* Processes all SysV units, and reshuffles the array so that
5005 * afterwards only the native units remain */
5007 r
= lookup_paths_init(&paths
, SYSTEMD_SYSTEM
, false, arg_root
, NULL
, NULL
, NULL
);
5012 for (f
= 0; args
[f
]; f
++) {
5014 _cleanup_free_
char *p
= NULL
, *q
= NULL
, *l
= NULL
;
5015 bool found_native
= false, found_sysv
;
5017 const char *argv
[6] = { "/sbin/chkconfig", NULL
, NULL
, NULL
, NULL
};
5025 if (!endswith(name
, ".service"))
5028 if (path_is_absolute(name
))
5031 STRV_FOREACH(k
, paths
.unit_path
) {
5032 _cleanup_free_
char *path
= NULL
;
5034 if (!isempty(arg_root
))
5035 asprintf(&path
, "%s/%s/%s", arg_root
, *k
, name
);
5037 asprintf(&path
, "%s/%s", *k
, name
);
5044 found_native
= access(path
, F_OK
) >= 0;
5052 if (!isempty(arg_root
))
5053 asprintf(&p
, "%s/" SYSTEM_SYSVINIT_PATH
"/%s", arg_root
, name
);
5055 asprintf(&p
, SYSTEM_SYSVINIT_PATH
"/%s", name
);
5061 p
[strlen(p
) - strlen(".service")] = 0;
5062 found_sysv
= access(p
, F_OK
) >= 0;
5066 /* Mark this entry, so that we don't try enabling it as native unit */
5067 args
[f
] = (char*) "";
5069 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name
);
5071 if (!isempty(arg_root
))
5072 argv
[c
++] = q
= strappend("--root=", arg_root
);
5074 argv
[c
++] = basename(p
);
5076 streq(verb
, "enable") ? "on" :
5077 streq(verb
, "disable") ? "off" : "--level=5";
5080 l
= strv_join((char**)argv
, " ");
5086 log_info("Executing %s", l
);
5090 log_error("Failed to fork: %m");
5093 } else if (pid
== 0) {
5096 execv(argv
[0], (char**) argv
);
5097 _exit(EXIT_FAILURE
);
5100 j
= wait_for_terminate(pid
, &status
);
5102 log_error("Failed to wait for child: %s", strerror(-r
));
5107 if (status
.si_code
== CLD_EXITED
) {
5108 if (streq(verb
, "is-enabled")) {
5109 if (status
.si_status
== 0) {
5118 } else if (status
.si_status
!= 0) {
5129 /* Drop all SysV units */
5130 for (f
= 0, t
= 0; args
[f
]; f
++) {
5132 if (isempty(args
[f
]))
5135 args
[t
++] = args
[f
];
5144 static int mangle_names(char **original_names
, char ***mangled_names
) {
5145 char **i
, **l
, **name
;
5147 l
= new(char*, strv_length(original_names
) + 1);
5152 STRV_FOREACH(name
, original_names
) {
5154 /* When enabling units qualified path names are OK,
5155 * too, hence allow them explicitly. */
5160 *i
= unit_name_mangle(*name
, MANGLE_NOGLOB
);
5176 static int enable_unit(sd_bus
*bus
, char **args
) {
5177 _cleanup_strv_free_
char **names
= NULL
;
5178 const char *verb
= args
[0];
5179 UnitFileChange
*changes
= NULL
;
5180 unsigned n_changes
= 0;
5181 int carries_install_info
= -1;
5187 r
= mangle_names(args
+1, &names
);
5191 r
= enable_sysv_units(verb
, names
);
5195 /* If the operation was fully executed by the SysV compat,
5196 * let's finish early */
5197 if (strv_isempty(names
))
5200 if (!bus
|| avoid_bus()) {
5201 if (streq(verb
, "enable")) {
5202 r
= unit_file_enable(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5203 carries_install_info
= r
;
5204 } else if (streq(verb
, "disable"))
5205 r
= unit_file_disable(arg_scope
, arg_runtime
, arg_root
, names
, &changes
, &n_changes
);
5206 else if (streq(verb
, "reenable")) {
5207 r
= unit_file_reenable(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5208 carries_install_info
= r
;
5209 } else if (streq(verb
, "link"))
5210 r
= unit_file_link(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5211 else if (streq(verb
, "preset")) {
5212 r
= unit_file_preset(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5213 carries_install_info
= r
;
5214 } else if (streq(verb
, "mask"))
5215 r
= unit_file_mask(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5216 else if (streq(verb
, "unmask"))
5217 r
= unit_file_unmask(arg_scope
, arg_runtime
, arg_root
, names
, &changes
, &n_changes
);
5219 assert_not_reached("Unknown verb");
5222 log_error("Operation failed: %s", strerror(-r
));
5227 dump_unit_file_changes(changes
, n_changes
);
5231 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
, *m
= NULL
;
5232 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5233 int expect_carries_install_info
= false;
5234 bool send_force
= true;
5237 if (streq(verb
, "enable")) {
5238 method
= "EnableUnitFiles";
5239 expect_carries_install_info
= true;
5240 } else if (streq(verb
, "disable")) {
5241 method
= "DisableUnitFiles";
5243 } else if (streq(verb
, "reenable")) {
5244 method
= "ReenableUnitFiles";
5245 expect_carries_install_info
= true;
5246 } else if (streq(verb
, "link"))
5247 method
= "LinkUnitFiles";
5248 else if (streq(verb
, "preset")) {
5249 method
= "PresetUnitFiles";
5250 expect_carries_install_info
= true;
5251 } else if (streq(verb
, "mask"))
5252 method
= "MaskUnitFiles";
5253 else if (streq(verb
, "unmask")) {
5254 method
= "UnmaskUnitFiles";
5257 assert_not_reached("Unknown verb");
5259 r
= sd_bus_message_new_method_call(
5262 "org.freedesktop.systemd1",
5263 "/org/freedesktop/systemd1",
5264 "org.freedesktop.systemd1.Manager",
5267 return bus_log_create_error(r
);
5269 r
= sd_bus_message_append_strv(m
, names
);
5271 return bus_log_create_error(r
);
5273 r
= sd_bus_message_append(m
, "b", arg_runtime
);
5275 return bus_log_create_error(r
);
5278 r
= sd_bus_message_append(m
, "b", arg_force
);
5280 return bus_log_create_error(r
);
5283 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
5285 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
5289 if (expect_carries_install_info
) {
5290 r
= sd_bus_message_read(reply
, "b", &carries_install_info
);
5292 return bus_log_parse_error(r
);
5295 r
= deserialize_and_dump_unit_file_changes(reply
);
5299 /* Try to reload if enabled */
5301 r
= daemon_reload(bus
, args
);
5306 if (carries_install_info
== 0)
5307 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5308 "using systemctl.\n"
5309 "Possible reasons for having this kind of units are:\n"
5310 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5311 " .wants/ or .requires/ directory.\n"
5312 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5313 " a requirement dependency on it.\n"
5314 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5315 " D-Bus, udev, scripted systemctl call, ...).\n");
5318 unit_file_changes_free(changes
, n_changes
);
5323 static int unit_is_enabled(sd_bus
*bus
, char **args
) {
5325 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5326 _cleanup_strv_free_
char **names
= NULL
;
5331 r
= mangle_names(args
+1, &names
);
5335 r
= enable_sysv_units(args
[0], names
);
5341 if (!bus
|| avoid_bus()) {
5343 STRV_FOREACH(name
, names
) {
5344 UnitFileState state
;
5346 state
= unit_file_get_state(arg_scope
, arg_root
, *name
);
5348 log_error("Failed to get unit file state for %s: %s", *name
, strerror(-state
));
5352 if (state
== UNIT_FILE_ENABLED
||
5353 state
== UNIT_FILE_ENABLED_RUNTIME
||
5354 state
== UNIT_FILE_STATIC
)
5358 puts(unit_file_state_to_string(state
));
5362 STRV_FOREACH(name
, names
) {
5363 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
5366 r
= sd_bus_call_method(
5368 "org.freedesktop.systemd1",
5369 "/org/freedesktop/systemd1",
5370 "org.freedesktop.systemd1.Manager",
5376 log_error("Failed to get unit file state for %s: %s", *name
, bus_error_message(&error
, r
));
5380 r
= sd_bus_message_read(reply
, "s", &s
);
5382 return bus_log_parse_error(r
);
5384 if (streq(s
, "enabled") ||
5385 streq(s
, "enabled-runtime") ||
5397 static int systemctl_help(void) {
5399 pager_open_if_enabled();
5401 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
5402 "Query or send control commands to the systemd manager.\n\n"
5403 " -h --help Show this help\n"
5404 " --version Show package version\n"
5405 " --system Connect to system manager\n"
5406 " --user Connect to user service manager\n"
5407 " -H --host=[USER@]HOST\n"
5408 " Operate on remote host\n"
5409 " -M --machine=CONTAINER\n"
5410 " Operate on local container\n"
5411 " -t --type=TYPE List only units of a particular type\n"
5412 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
5413 " -p --property=NAME Show only properties by this name\n"
5414 " -a --all Show all loaded units/properties, including dead/empty\n"
5415 " ones. To list all units installed on the system, use\n"
5416 " the 'list-unit-files' command instead.\n"
5417 " -l --full Don't ellipsize unit names on output\n"
5418 " -r --recursive Show unit list of host and local containers\n"
5419 " --reverse Show reverse dependencies with 'list-dependencies'\n"
5420 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
5421 " queueing a new job\n"
5422 " --show-types When showing sockets, explicitly show their type\n"
5423 " -i --ignore-inhibitors\n"
5424 " When shutting down or sleeping, ignore inhibitors\n"
5425 " --kill-who=WHO Who to send signal to\n"
5426 " -s --signal=SIGNAL Which signal to send\n"
5427 " -q --quiet Suppress output\n"
5428 " --no-block Do not wait until operation finished\n"
5429 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5430 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
5432 " --no-legend Do not print a legend (column headers and hints)\n"
5433 " --no-pager Do not pipe output into a pager\n"
5434 " --no-ask-password\n"
5435 " Do not ask for system passwords\n"
5436 " --global Enable/disable unit files globally\n"
5437 " --runtime Enable unit files only temporarily until next reboot\n"
5438 " -f --force When enabling unit files, override existing symlinks\n"
5439 " When shutting down, execute action immediately\n"
5440 " --root=PATH Enable unit files in the specified root directory\n"
5441 " -n --lines=INTEGER Number of journal entries to show\n"
5442 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
5443 " verbose, export, json, json-pretty, json-sse, cat)\n"
5444 " --plain Print unit dependencies as a list instead of a tree\n\n"
5446 " list-units [PATTERN...] List loaded units\n"
5447 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
5448 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
5449 " start NAME... Start (activate) one or more units\n"
5450 " stop NAME... Stop (deactivate) one or more units\n"
5451 " reload NAME... Reload one or more units\n"
5452 " restart NAME... Start or restart one or more units\n"
5453 " try-restart NAME... Restart one or more units if active\n"
5454 " reload-or-restart NAME... Reload one or more units if possible,\n"
5455 " otherwise start or restart\n"
5456 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
5457 " otherwise restart if active\n"
5458 " isolate NAME Start one unit and stop all others\n"
5459 " kill NAME... Send signal to processes of a unit\n"
5460 " is-active PATTERN... Check whether units are active\n"
5461 " is-failed PATTERN... Check whether units are failed\n"
5462 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
5463 " show [PATTERN...|JOB...] Show properties of one or more\n"
5464 " units/jobs or the manager\n"
5465 " cat PATTERN... Show files and drop-ins of one or more units\n"
5466 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
5467 " help PATTERN...|PID... Show manual for one or more units\n"
5468 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
5470 " list-dependencies [NAME] Recursively show units which are required\n"
5471 " or wanted by this unit or by which this\n"
5472 " unit is required or wanted\n\n"
5473 "Unit File Commands:\n"
5474 " list-unit-files [PATTERN...] List installed unit files\n"
5475 " enable NAME... Enable one or more unit files\n"
5476 " disable NAME... Disable one or more unit files\n"
5477 " reenable NAME... Reenable one or more unit files\n"
5478 " preset NAME... Enable/disable one or more unit files\n"
5479 " based on preset configuration\n"
5480 " is-enabled NAME... Check whether unit files are enabled\n\n"
5481 " mask NAME... Mask one or more units\n"
5482 " unmask NAME... Unmask one or more units\n"
5483 " link PATH... Link one or more units files into\n"
5484 " the search path\n"
5485 " get-default Get the name of the default target\n"
5486 " set-default NAME Set the default target\n\n"
5487 "Machine Commands:\n"
5488 " list-machines [PATTERN...] List local containers and host\n\n"
5490 " list-jobs [PATTERN...] List jobs\n"
5491 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
5492 "Snapshot Commands:\n"
5493 " snapshot [NAME] Create a snapshot\n"
5494 " delete NAME... Remove one or more snapshots\n\n"
5495 "Environment Commands:\n"
5496 " show-environment Dump environment\n"
5497 " set-environment NAME=VALUE... Set one or more environment variables\n"
5498 " unset-environment NAME... Unset one or more environment variables\n"
5499 " import-environment NAME... Import all, one or more environment variables\n\n"
5500 "Manager Lifecycle Commands:\n"
5501 " daemon-reload Reload systemd manager configuration\n"
5502 " daemon-reexec Reexecute systemd manager\n\n"
5503 "System Commands:\n"
5504 " default Enter system default mode\n"
5505 " rescue Enter system rescue mode\n"
5506 " emergency Enter system emergency mode\n"
5507 " halt Shut down and halt the system\n"
5508 " poweroff Shut down and power-off the system\n"
5509 " reboot [ARG] Shut down and reboot the system\n"
5510 " kexec Shut down and reboot the system with kexec\n"
5511 " exit Request user instance exit\n"
5512 " switch-root ROOT [INIT] Change to a different root file system\n"
5513 " suspend Suspend the system\n"
5514 " hibernate Hibernate the system\n"
5515 " hybrid-sleep Hibernate and suspend the system\n",
5516 program_invocation_short_name
);
5521 static int halt_help(void) {
5523 printf("%s [OPTIONS...]%s\n\n"
5524 "%s the system.\n\n"
5525 " --help Show this help\n"
5526 " --halt Halt the machine\n"
5527 " -p --poweroff Switch off the machine\n"
5528 " --reboot Reboot the machine\n"
5529 " -f --force Force immediate halt/power-off/reboot\n"
5530 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
5531 " -d --no-wtmp Don't write wtmp record\n"
5532 " --no-wall Don't send wall message before halt/power-off/reboot\n",
5533 program_invocation_short_name
,
5534 arg_action
== ACTION_REBOOT
? " [ARG]" : "",
5535 arg_action
== ACTION_REBOOT
? "Reboot" :
5536 arg_action
== ACTION_POWEROFF
? "Power off" :
5542 static int shutdown_help(void) {
5544 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
5545 "Shut down the system.\n\n"
5546 " --help Show this help\n"
5547 " -H --halt Halt the machine\n"
5548 " -P --poweroff Power-off the machine\n"
5549 " -r --reboot Reboot the machine\n"
5550 " -h Equivalent to --poweroff, overridden by --halt\n"
5551 " -k Don't halt/power-off/reboot, just send warnings\n"
5552 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5553 " -c Cancel a pending shutdown\n",
5554 program_invocation_short_name
);
5559 static int telinit_help(void) {
5561 printf("%s [OPTIONS...] {COMMAND}\n\n"
5562 "Send control commands to the init daemon.\n\n"
5563 " --help Show this help\n"
5564 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
5566 " 0 Power-off the machine\n"
5567 " 6 Reboot the machine\n"
5568 " 2, 3, 4, 5 Start runlevelX.target unit\n"
5569 " 1, s, S Enter rescue mode\n"
5570 " q, Q Reload init daemon configuration\n"
5571 " u, U Reexecute init daemon\n",
5572 program_invocation_short_name
);
5577 static int runlevel_help(void) {
5579 printf("%s [OPTIONS...]\n\n"
5580 "Prints the previous and current runlevel of the init system.\n\n"
5581 " --help Show this help\n",
5582 program_invocation_short_name
);
5587 static int help_types(void) {
5591 puts("Available unit types:");
5592 for (i
= 0; i
< _UNIT_TYPE_MAX
; i
++) {
5593 t
= unit_type_to_string(i
);
5601 static int systemctl_parse_argv(int argc
, char *argv
[]) {
5610 ARG_IGNORE_DEPENDENCIES
,
5622 ARG_NO_ASK_PASSWORD
,
5631 static const struct option options
[] = {
5632 { "help", no_argument
, NULL
, 'h' },
5633 { "version", no_argument
, NULL
, ARG_VERSION
},
5634 { "type", required_argument
, NULL
, 't' },
5635 { "property", required_argument
, NULL
, 'p' },
5636 { "all", no_argument
, NULL
, 'a' },
5637 { "reverse", no_argument
, NULL
, ARG_REVERSE
},
5638 { "after", no_argument
, NULL
, ARG_AFTER
},
5639 { "before", no_argument
, NULL
, ARG_BEFORE
},
5640 { "show-types", no_argument
, NULL
, ARG_SHOW_TYPES
},
5641 { "failed", no_argument
, NULL
, ARG_FAILED
}, /* compatibility only */
5642 { "full", no_argument
, NULL
, 'l' },
5643 { "job-mode", required_argument
, NULL
, ARG_JOB_MODE
},
5644 { "fail", no_argument
, NULL
, ARG_FAIL
}, /* compatibility only */
5645 { "irreversible", no_argument
, NULL
, ARG_IRREVERSIBLE
}, /* compatibility only */
5646 { "ignore-dependencies", no_argument
, NULL
, ARG_IGNORE_DEPENDENCIES
}, /* compatibility only */
5647 { "ignore-inhibitors", no_argument
, NULL
, 'i' },
5648 { "user", no_argument
, NULL
, ARG_USER
},
5649 { "system", no_argument
, NULL
, ARG_SYSTEM
},
5650 { "global", no_argument
, NULL
, ARG_GLOBAL
},
5651 { "no-block", no_argument
, NULL
, ARG_NO_BLOCK
},
5652 { "no-legend", no_argument
, NULL
, ARG_NO_LEGEND
},
5653 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
5654 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
5655 { "quiet", no_argument
, NULL
, 'q' },
5656 { "root", required_argument
, NULL
, ARG_ROOT
},
5657 { "force", no_argument
, NULL
, ARG_FORCE
},
5658 { "no-reload", no_argument
, NULL
, ARG_NO_RELOAD
},
5659 { "kill-who", required_argument
, NULL
, ARG_KILL_WHO
},
5660 { "signal", required_argument
, NULL
, 's' },
5661 { "no-ask-password", no_argument
, NULL
, ARG_NO_ASK_PASSWORD
},
5662 { "host", required_argument
, NULL
, 'H' },
5663 { "machine", required_argument
, NULL
, 'M' },
5664 { "runtime", no_argument
, NULL
, ARG_RUNTIME
},
5665 { "lines", required_argument
, NULL
, 'n' },
5666 { "output", required_argument
, NULL
, 'o' },
5667 { "plain", no_argument
, NULL
, ARG_PLAIN
},
5668 { "state", required_argument
, NULL
, ARG_STATE
},
5669 { "recursive", no_argument
, NULL
, 'r' },
5678 while ((c
= getopt_long(argc
, argv
, "ht:p:alqfs:H:M:n:o:ir", options
, NULL
)) >= 0) {
5683 return systemctl_help();
5686 puts(PACKAGE_STRING
);
5687 puts(SYSTEMD_FEATURES
);
5694 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
5695 _cleanup_free_
char *type
;
5697 type
= strndup(word
, size
);
5701 if (streq(type
, "help")) {
5706 if (unit_type_from_string(type
) >= 0) {
5707 if (strv_push(&arg_types
, type
))
5713 /* It's much nicer to use --state= for
5714 * load states, but let's support this
5715 * in --types= too for compatibility
5716 * with old versions */
5717 if (unit_load_state_from_string(optarg
) >= 0) {
5718 if (strv_push(&arg_states
, type
) < 0)
5724 log_error("Unknown unit type or load state '%s'.", type
);
5725 log_info("Use -t help to see a list of allowed values.");
5733 /* Make sure that if the empty property list
5734 was specified, we won't show any properties. */
5735 if (isempty(optarg
) && !arg_properties
) {
5736 arg_properties
= new0(char*, 1);
5737 if (!arg_properties
)
5743 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
5746 prop
= strndup(word
, size
);
5750 if (strv_consume(&arg_properties
, prop
) < 0)
5755 /* If the user asked for a particular
5756 * property, show it to him, even if it is
5768 arg_dependency
= DEPENDENCY_REVERSE
;
5772 arg_dependency
= DEPENDENCY_AFTER
;
5776 arg_dependency
= DEPENDENCY_BEFORE
;
5779 case ARG_SHOW_TYPES
:
5780 arg_show_types
= true;
5784 arg_job_mode
= optarg
;
5788 arg_job_mode
= "fail";
5791 case ARG_IRREVERSIBLE
:
5792 arg_job_mode
= "replace-irreversibly";
5795 case ARG_IGNORE_DEPENDENCIES
:
5796 arg_job_mode
= "ignore-dependencies";
5800 arg_scope
= UNIT_FILE_USER
;
5804 arg_scope
= UNIT_FILE_SYSTEM
;
5808 arg_scope
= UNIT_FILE_GLOBAL
;
5812 arg_no_block
= true;
5816 arg_no_legend
= true;
5820 arg_no_pager
= true;
5836 if (strv_extend(&arg_states
, "failed") < 0)
5854 arg_no_reload
= true;
5858 arg_kill_who
= optarg
;
5862 if ((arg_signal
= signal_from_string_try_harder(optarg
)) < 0) {
5863 log_error("Failed to parse signal string %s.", optarg
);
5868 case ARG_NO_ASK_PASSWORD
:
5869 arg_ask_password
= false;
5873 arg_transport
= BUS_TRANSPORT_REMOTE
;
5878 arg_transport
= BUS_TRANSPORT_CONTAINER
;
5887 if (safe_atou(optarg
, &arg_lines
) < 0) {
5888 log_error("Failed to parse lines '%s'", optarg
);
5894 arg_output
= output_mode_from_string(optarg
);
5895 if (arg_output
< 0) {
5896 log_error("Unknown output '%s'.", optarg
);
5902 arg_ignore_inhibitors
= true;
5913 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
5916 s
= strndup(word
, size
);
5920 if (strv_consume(&arg_states
, s
) < 0)
5927 if (geteuid() != 0) {
5928 log_error("--recursive requires root privileges.");
5932 arg_recursive
= true;
5939 assert_not_reached("Unhandled option");
5943 if (arg_transport
!= BUS_TRANSPORT_LOCAL
&& arg_scope
!= UNIT_FILE_SYSTEM
) {
5944 log_error("Cannot access user instance remotely.");
5951 static int halt_parse_argv(int argc
, char *argv
[]) {
5960 static const struct option options
[] = {
5961 { "help", no_argument
, NULL
, ARG_HELP
},
5962 { "halt", no_argument
, NULL
, ARG_HALT
},
5963 { "poweroff", no_argument
, NULL
, 'p' },
5964 { "reboot", no_argument
, NULL
, ARG_REBOOT
},
5965 { "force", no_argument
, NULL
, 'f' },
5966 { "wtmp-only", no_argument
, NULL
, 'w' },
5967 { "no-wtmp", no_argument
, NULL
, 'd' },
5968 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
5977 if (utmp_get_runlevel(&runlevel
, NULL
) >= 0)
5978 if (runlevel
== '0' || runlevel
== '6')
5981 while ((c
= getopt_long(argc
, argv
, "pfwdnih", options
, NULL
)) >= 0) {
5988 arg_action
= ACTION_HALT
;
5992 if (arg_action
!= ACTION_REBOOT
)
5993 arg_action
= ACTION_POWEROFF
;
5997 arg_action
= ACTION_REBOOT
;
6019 /* Compatibility nops */
6026 assert_not_reached("Unhandled option");
6030 if (arg_action
== ACTION_REBOOT
&& (argc
== optind
|| argc
== optind
+ 1)) {
6031 r
= update_reboot_param_file(argc
== optind
+ 1 ? argv
[optind
] : NULL
);
6034 } else if (optind
< argc
) {
6035 log_error("Too many arguments.");
6042 static int parse_time_spec(const char *t
, usec_t
*_u
) {
6046 if (streq(t
, "now"))
6048 else if (!strchr(t
, ':')) {
6051 if (safe_atou64(t
, &u
) < 0)
6054 *_u
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
* u
;
6063 hour
= strtol(t
, &e
, 10);
6064 if (errno
> 0 || *e
!= ':' || hour
< 0 || hour
> 23)
6067 minute
= strtol(e
+1, &e
, 10);
6068 if (errno
> 0 || *e
!= 0 || minute
< 0 || minute
> 59)
6071 n
= now(CLOCK_REALTIME
);
6072 s
= (time_t) (n
/ USEC_PER_SEC
);
6074 assert_se(localtime_r(&s
, &tm
));
6076 tm
.tm_hour
= (int) hour
;
6077 tm
.tm_min
= (int) minute
;
6080 assert_se(s
= mktime(&tm
));
6082 *_u
= (usec_t
) s
* USEC_PER_SEC
;
6085 *_u
+= USEC_PER_DAY
;
6091 static int shutdown_parse_argv(int argc
, char *argv
[]) {
6098 static const struct option options
[] = {
6099 { "help", no_argument
, NULL
, ARG_HELP
},
6100 { "halt", no_argument
, NULL
, 'H' },
6101 { "poweroff", no_argument
, NULL
, 'P' },
6102 { "reboot", no_argument
, NULL
, 'r' },
6103 { "kexec", no_argument
, NULL
, 'K' }, /* not documented extension */
6104 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6113 while ((c
= getopt_long(argc
, argv
, "HPrhkt:afFc", options
, NULL
)) >= 0) {
6117 return shutdown_help();
6120 arg_action
= ACTION_HALT
;
6124 arg_action
= ACTION_POWEROFF
;
6129 arg_action
= ACTION_KEXEC
;
6131 arg_action
= ACTION_REBOOT
;
6135 arg_action
= ACTION_KEXEC
;
6139 if (arg_action
!= ACTION_HALT
)
6140 arg_action
= ACTION_POWEROFF
;
6153 /* Compatibility nops */
6157 arg_action
= ACTION_CANCEL_SHUTDOWN
;
6164 assert_not_reached("Unhandled option");
6168 if (argc
> optind
&& arg_action
!= ACTION_CANCEL_SHUTDOWN
) {
6169 r
= parse_time_spec(argv
[optind
], &arg_when
);
6171 log_error("Failed to parse time specification: %s", argv
[optind
]);
6175 arg_when
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
;
6177 if (argc
> optind
&& arg_action
== ACTION_CANCEL_SHUTDOWN
)
6178 /* No time argument for shutdown cancel */
6179 arg_wall
= argv
+ optind
;
6180 else if (argc
> optind
+ 1)
6181 /* We skip the time argument */
6182 arg_wall
= argv
+ optind
+ 1;
6189 static int telinit_parse_argv(int argc
, char *argv
[]) {
6196 static const struct option options
[] = {
6197 { "help", no_argument
, NULL
, ARG_HELP
},
6198 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6202 static const struct {
6206 { '0', ACTION_POWEROFF
},
6207 { '6', ACTION_REBOOT
},
6208 { '1', ACTION_RESCUE
},
6209 { '2', ACTION_RUNLEVEL2
},
6210 { '3', ACTION_RUNLEVEL3
},
6211 { '4', ACTION_RUNLEVEL4
},
6212 { '5', ACTION_RUNLEVEL5
},
6213 { 's', ACTION_RESCUE
},
6214 { 'S', ACTION_RESCUE
},
6215 { 'q', ACTION_RELOAD
},
6216 { 'Q', ACTION_RELOAD
},
6217 { 'u', ACTION_REEXEC
},
6218 { 'U', ACTION_REEXEC
}
6227 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0) {
6231 return telinit_help();
6241 assert_not_reached("Unhandled option");
6245 if (optind
>= argc
) {
6250 if (optind
+ 1 < argc
) {
6251 log_error("Too many arguments.");
6255 if (strlen(argv
[optind
]) != 1) {
6256 log_error("Expected single character argument.");
6260 for (i
= 0; i
< ELEMENTSOF(table
); i
++)
6261 if (table
[i
].from
== argv
[optind
][0])
6264 if (i
>= ELEMENTSOF(table
)) {
6265 log_error("Unknown command '%s'.", argv
[optind
]);
6269 arg_action
= table
[i
].to
;
6276 static int runlevel_parse_argv(int argc
, char *argv
[]) {
6282 static const struct option options
[] = {
6283 { "help", no_argument
, NULL
, ARG_HELP
},
6292 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0) {
6296 return runlevel_help();
6302 assert_not_reached("Unhandled option");
6306 if (optind
< argc
) {
6307 log_error("Too many arguments.");
6314 static int parse_argv(int argc
, char *argv
[]) {
6318 if (program_invocation_short_name
) {
6320 if (strstr(program_invocation_short_name
, "halt")) {
6321 arg_action
= ACTION_HALT
;
6322 return halt_parse_argv(argc
, argv
);
6323 } else if (strstr(program_invocation_short_name
, "poweroff")) {
6324 arg_action
= ACTION_POWEROFF
;
6325 return halt_parse_argv(argc
, argv
);
6326 } else if (strstr(program_invocation_short_name
, "reboot")) {
6328 arg_action
= ACTION_KEXEC
;
6330 arg_action
= ACTION_REBOOT
;
6331 return halt_parse_argv(argc
, argv
);
6332 } else if (strstr(program_invocation_short_name
, "shutdown")) {
6333 arg_action
= ACTION_POWEROFF
;
6334 return shutdown_parse_argv(argc
, argv
);
6335 } else if (strstr(program_invocation_short_name
, "init")) {
6337 if (sd_booted() > 0) {
6338 arg_action
= _ACTION_INVALID
;
6339 return telinit_parse_argv(argc
, argv
);
6341 /* Hmm, so some other init system is
6342 * running, we need to forward this
6343 * request to it. For now we simply
6344 * guess that it is Upstart. */
6346 execv(TELINIT
, argv
);
6348 log_error("Couldn't find an alternative telinit implementation to spawn.");
6352 } else if (strstr(program_invocation_short_name
, "runlevel")) {
6353 arg_action
= ACTION_RUNLEVEL
;
6354 return runlevel_parse_argv(argc
, argv
);
6358 arg_action
= ACTION_SYSTEMCTL
;
6359 return systemctl_parse_argv(argc
, argv
);
6362 _pure_
static int action_to_runlevel(void) {
6364 static const char table
[_ACTION_MAX
] = {
6365 [ACTION_HALT
] = '0',
6366 [ACTION_POWEROFF
] = '0',
6367 [ACTION_REBOOT
] = '6',
6368 [ACTION_RUNLEVEL2
] = '2',
6369 [ACTION_RUNLEVEL3
] = '3',
6370 [ACTION_RUNLEVEL4
] = '4',
6371 [ACTION_RUNLEVEL5
] = '5',
6372 [ACTION_RESCUE
] = '1'
6375 assert(arg_action
< _ACTION_MAX
);
6377 return table
[arg_action
];
6380 static int talk_initctl(void) {
6382 struct init_request request
= {
6383 .magic
= INIT_MAGIC
,
6385 .cmd
= INIT_CMD_RUNLVL
6388 _cleanup_close_
int fd
= -1;
6392 rl
= action_to_runlevel();
6396 request
.runlevel
= rl
;
6398 fd
= open(INIT_FIFO
, O_WRONLY
|O_NDELAY
|O_CLOEXEC
|O_NOCTTY
);
6400 if (errno
== ENOENT
)
6403 log_error("Failed to open "INIT_FIFO
": %m");
6408 r
= loop_write(fd
, &request
, sizeof(request
), false) != sizeof(request
);
6410 log_error("Failed to write to "INIT_FIFO
": %m");
6411 return errno
> 0 ? -errno
: -EIO
;
6417 static int systemctl_main(sd_bus
*bus
, int argc
, char *argv
[], int bus_error
) {
6419 static const struct {
6427 int (* const dispatch
)(sd_bus
*bus
, char **args
);
6433 { "list-units", MORE
, 0, list_units
},
6434 { "list-unit-files", MORE
, 1, list_unit_files
, NOBUS
},
6435 { "list-sockets", MORE
, 1, list_sockets
},
6436 { "list-timers", MORE
, 1, list_timers
},
6437 { "list-jobs", MORE
, 1, list_jobs
},
6438 { "list-machines", MORE
, 1, list_machines
},
6439 { "clear-jobs", EQUAL
, 1, daemon_reload
},
6440 { "cancel", MORE
, 2, cancel_job
},
6441 { "start", MORE
, 2, start_unit
},
6442 { "stop", MORE
, 2, start_unit
},
6443 { "condstop", MORE
, 2, start_unit
}, /* For compatibility with ALTLinux */
6444 { "reload", MORE
, 2, start_unit
},
6445 { "restart", MORE
, 2, start_unit
},
6446 { "try-restart", MORE
, 2, start_unit
},
6447 { "reload-or-restart", MORE
, 2, start_unit
},
6448 { "reload-or-try-restart", MORE
, 2, start_unit
},
6449 { "force-reload", MORE
, 2, start_unit
}, /* For compatibility with SysV */
6450 { "condreload", MORE
, 2, start_unit
}, /* For compatibility with ALTLinux */
6451 { "condrestart", MORE
, 2, start_unit
}, /* For compatibility with RH */
6452 { "isolate", EQUAL
, 2, start_unit
},
6453 { "kill", MORE
, 2, kill_unit
},
6454 { "is-active", MORE
, 2, check_unit_active
},
6455 { "check", MORE
, 2, check_unit_active
},
6456 { "is-failed", MORE
, 2, check_unit_failed
},
6457 { "show", MORE
, 1, show
},
6458 { "cat", MORE
, 2, cat
},
6459 { "status", MORE
, 1, show
},
6460 { "help", MORE
, 2, show
},
6461 { "snapshot", LESS
, 2, snapshot
},
6462 { "delete", MORE
, 2, delete_snapshot
},
6463 { "daemon-reload", EQUAL
, 1, daemon_reload
},
6464 { "daemon-reexec", EQUAL
, 1, daemon_reload
},
6465 { "show-environment", EQUAL
, 1, show_environment
},
6466 { "set-environment", MORE
, 2, set_environment
},
6467 { "unset-environment", MORE
, 2, set_environment
},
6468 { "import-environment", MORE
, 1, import_environment
},
6469 { "halt", EQUAL
, 1, start_special
, FORCE
},
6470 { "poweroff", EQUAL
, 1, start_special
, FORCE
},
6471 { "reboot", EQUAL
, 1, start_special
, FORCE
},
6472 { "kexec", EQUAL
, 1, start_special
},
6473 { "suspend", EQUAL
, 1, start_special
},
6474 { "hibernate", EQUAL
, 1, start_special
},
6475 { "hybrid-sleep", EQUAL
, 1, start_special
},
6476 { "default", EQUAL
, 1, start_special
},
6477 { "rescue", EQUAL
, 1, start_special
},
6478 { "emergency", EQUAL
, 1, start_special
},
6479 { "exit", EQUAL
, 1, start_special
},
6480 { "reset-failed", MORE
, 1, reset_failed
},
6481 { "enable", MORE
, 2, enable_unit
, NOBUS
},
6482 { "disable", MORE
, 2, enable_unit
, NOBUS
},
6483 { "is-enabled", MORE
, 2, unit_is_enabled
, NOBUS
},
6484 { "reenable", MORE
, 2, enable_unit
, NOBUS
},
6485 { "preset", MORE
, 2, enable_unit
, NOBUS
},
6486 { "mask", MORE
, 2, enable_unit
, NOBUS
},
6487 { "unmask", MORE
, 2, enable_unit
, NOBUS
},
6488 { "link", MORE
, 2, enable_unit
, NOBUS
},
6489 { "switch-root", MORE
, 2, switch_root
},
6490 { "list-dependencies", LESS
, 2, list_dependencies
},
6491 { "set-default", EQUAL
, 2, set_default
, NOBUS
},
6492 { "get-default", EQUAL
, 1, get_default
, NOBUS
},
6493 { "set-property", MORE
, 3, set_property
},
6502 left
= argc
- optind
;
6504 /* Special rule: no arguments (left == 0) means "list-units" */
6506 if (streq(argv
[optind
], "help") && !argv
[optind
+1]) {
6507 log_error("This command expects one or more "
6508 "unit names. Did you mean --help?");
6512 for (; verb
->verb
; verb
++)
6513 if (streq(argv
[optind
], verb
->verb
))
6516 log_error("Unknown operation '%s'.", argv
[optind
]);
6521 switch (verb
->argc_cmp
) {
6524 if (left
!= verb
->argc
) {
6525 log_error("Invalid number of arguments.");
6532 if (left
< verb
->argc
) {
6533 log_error("Too few arguments.");
6540 if (left
> verb
->argc
) {
6541 log_error("Too many arguments.");
6548 assert_not_reached("Unknown comparison operator.");
6551 /* Require a bus connection for all operations but
6553 if (verb
->bus
== NOBUS
) {
6554 if (!bus
&& !avoid_bus()) {
6555 log_error("Failed to get D-Bus connection: %s", strerror(-bus_error
));
6560 if (running_in_chroot() > 0) {
6561 log_info("Running in chroot, ignoring request.");
6565 if ((verb
->bus
!= FORCE
|| arg_force
<= 0) && !bus
) {
6566 log_error("Failed to get D-Bus connection: %s", strerror(-bus_error
));
6571 return verb
->dispatch(bus
, argv
+ optind
);
6574 static int send_shutdownd(usec_t t
, char mode
, bool dry_run
, bool warn
, const char *message
) {
6576 struct sd_shutdown_command c
= {
6583 union sockaddr_union sockaddr
= {
6584 .un
.sun_family
= AF_UNIX
,
6585 .un
.sun_path
= "/run/systemd/shutdownd",
6588 struct iovec iovec
[2] = {{
6589 .iov_base
= (char*) &c
,
6590 .iov_len
= offsetof(struct sd_shutdown_command
, wall_message
),
6593 struct msghdr msghdr
= {
6594 .msg_name
= &sockaddr
,
6595 .msg_namelen
= offsetof(struct sockaddr_un
, sun_path
)
6596 + strlen("/run/systemd/shutdownd"),
6601 _cleanup_close_
int fd
;
6603 fd
= socket(AF_UNIX
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0);
6607 if (!isempty(message
)) {
6608 iovec
[1].iov_base
= (char*) message
;
6609 iovec
[1].iov_len
= strlen(message
);
6610 msghdr
.msg_iovlen
++;
6613 if (sendmsg(fd
, &msghdr
, MSG_NOSIGNAL
) < 0)
6619 static int reload_with_fallback(sd_bus
*bus
) {
6622 /* First, try systemd via D-Bus. */
6623 if (daemon_reload(bus
, NULL
) >= 0)
6627 /* Nothing else worked, so let's try signals */
6628 assert(arg_action
== ACTION_RELOAD
|| arg_action
== ACTION_REEXEC
);
6630 if (kill(1, arg_action
== ACTION_RELOAD
? SIGHUP
: SIGTERM
) < 0) {
6631 log_error("kill() failed: %m");
6638 static int start_with_fallback(sd_bus
*bus
) {
6641 /* First, try systemd via D-Bus. */
6642 if (start_unit(bus
, NULL
) >= 0)
6646 /* Nothing else worked, so let's try
6648 if (talk_initctl() > 0)
6651 log_error("Failed to talk to init daemon.");
6655 warn_wall(arg_action
);
6659 static int halt_now(enum action a
) {
6661 /* Make sure C-A-D is handled by the kernel from this
6663 reboot(RB_ENABLE_CAD
);
6668 log_info("Halting.");
6669 reboot(RB_HALT_SYSTEM
);
6672 case ACTION_POWEROFF
:
6673 log_info("Powering off.");
6674 reboot(RB_POWER_OFF
);
6677 case ACTION_REBOOT
: {
6678 _cleanup_free_
char *param
= NULL
;
6680 if (read_one_line_file(REBOOT_PARAM_FILE
, ¶m
) >= 0) {
6681 log_info("Rebooting with argument '%s'.", param
);
6682 syscall(SYS_reboot
, LINUX_REBOOT_MAGIC1
, LINUX_REBOOT_MAGIC2
,
6683 LINUX_REBOOT_CMD_RESTART2
, param
);
6686 log_info("Rebooting.");
6687 reboot(RB_AUTOBOOT
);
6692 assert_not_reached("Unknown action.");
6696 static int halt_main(sd_bus
*bus
) {
6699 r
= check_inhibitors(bus
, arg_action
);
6703 if (geteuid() != 0) {
6704 /* Try logind if we are a normal user and no special
6705 * mode applies. Maybe PolicyKit allows us to shutdown
6708 if (arg_when
<= 0 &&
6711 (arg_action
== ACTION_POWEROFF
||
6712 arg_action
== ACTION_REBOOT
)) {
6713 r
= reboot_with_logind(bus
, arg_action
);
6718 log_error("Must be root.");
6723 _cleanup_free_
char *m
;
6725 m
= strv_join(arg_wall
, " ");
6729 r
= send_shutdownd(arg_when
,
6730 arg_action
== ACTION_HALT
? 'H' :
6731 arg_action
== ACTION_POWEROFF
? 'P' :
6732 arg_action
== ACTION_KEXEC
? 'K' :
6739 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r
));
6741 char date
[FORMAT_TIMESTAMP_MAX
];
6743 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
6744 format_timestamp(date
, sizeof(date
), arg_when
));
6749 if (!arg_dry
&& !arg_force
)
6750 return start_with_fallback(bus
);
6753 if (sd_booted() > 0)
6754 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
6756 r
= utmp_put_shutdown();
6758 log_warning("Failed to write utmp record: %s", strerror(-r
));
6765 r
= halt_now(arg_action
);
6766 log_error("Failed to reboot: %s", strerror(-r
));
6771 static int runlevel_main(void) {
6772 int r
, runlevel
, previous
;
6774 r
= utmp_get_runlevel(&runlevel
, &previous
);
6781 previous
<= 0 ? 'N' : previous
,
6782 runlevel
<= 0 ? 'N' : runlevel
);
6787 int main(int argc
, char*argv
[]) {
6788 _cleanup_bus_unref_ sd_bus
*bus
= NULL
;
6791 setlocale(LC_ALL
, "");
6792 log_parse_environment();
6795 /* Explicitly not on_tty() to avoid setting cached value.
6796 * This becomes relevant for piping output which might be
6798 original_stdout_is_tty
= isatty(STDOUT_FILENO
);
6800 r
= parse_argv(argc
, argv
);
6804 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
6805 * let's shortcut this */
6806 if (arg_action
== ACTION_RUNLEVEL
) {
6807 r
= runlevel_main();
6811 if (running_in_chroot() > 0 && arg_action
!= ACTION_SYSTEMCTL
) {
6812 log_info("Running in chroot, ignoring request.");
6818 r
= bus_open_transport_systemd(arg_transport
, arg_host
, arg_scope
!= UNIT_FILE_SYSTEM
, &bus
);
6820 /* systemctl_main() will print an error message for the bus
6821 * connection, but only if it needs to */
6823 switch (arg_action
) {
6825 case ACTION_SYSTEMCTL
:
6826 r
= systemctl_main(bus
, argc
, argv
, r
);
6830 case ACTION_POWEROFF
:
6836 case ACTION_RUNLEVEL2
:
6837 case ACTION_RUNLEVEL3
:
6838 case ACTION_RUNLEVEL4
:
6839 case ACTION_RUNLEVEL5
:
6841 case ACTION_EMERGENCY
:
6842 case ACTION_DEFAULT
:
6843 r
= start_with_fallback(bus
);
6848 r
= reload_with_fallback(bus
);
6851 case ACTION_CANCEL_SHUTDOWN
: {
6852 _cleanup_free_
char *m
= NULL
;
6855 m
= strv_join(arg_wall
, " ");
6862 r
= send_shutdownd(arg_when
, SD_SHUTDOWN_NONE
, false, !arg_no_wall
, m
);
6864 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r
));
6868 case ACTION_RUNLEVEL
:
6869 case _ACTION_INVALID
:
6871 assert_not_reached("Unknown action");
6876 ask_password_agent_close();
6877 polkit_agent_close();
6879 strv_free(arg_types
);
6880 strv_free(arg_states
);
6881 strv_free(arg_properties
);
6883 return r
< 0 ? EXIT_FAILURE
: r
;