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>
33 #include <sys/socket.h>
36 #include "sd-daemon.h"
43 #include "utmp-wtmp.h"
46 #include "path-util.h"
48 #include "cgroup-show.h"
49 #include "cgroup-util.h"
51 #include "path-lookup.h"
52 #include "exit-status.h"
54 #include "unit-name.h"
56 #include "spawn-ask-password-agent.h"
57 #include "spawn-polkit-agent.h"
59 #include "logs-show.h"
60 #include "socket-util.h"
65 #include "bus-message.h"
66 #include "bus-error.h"
67 #include "bus-common-errors.h"
71 #include "formats-util.h"
72 #include "process-util.h"
73 #include "terminal-util.h"
75 static char **arg_types
= NULL
;
76 static char **arg_states
= NULL
;
77 static char **arg_properties
= NULL
;
78 static bool arg_all
= false;
79 static enum dependency
{
85 } arg_dependency
= DEPENDENCY_FORWARD
;
86 static const char *arg_job_mode
= "replace";
87 static UnitFileScope arg_scope
= UNIT_FILE_SYSTEM
;
88 static bool arg_no_block
= false;
89 static bool arg_no_legend
= false;
90 static bool arg_no_pager
= false;
91 static bool arg_no_wtmp
= false;
92 static bool arg_no_wall
= false;
93 static bool arg_no_reload
= false;
94 static bool arg_show_types
= false;
95 static bool arg_ignore_inhibitors
= false;
96 static bool arg_dry
= false;
97 static bool arg_quiet
= false;
98 static bool arg_full
= false;
99 static bool arg_recursive
= false;
100 static int arg_force
= 0;
101 static bool arg_ask_password
= true;
102 static bool arg_runtime
= false;
103 static UnitFilePresetMode arg_preset_mode
= UNIT_FILE_PRESET_FULL
;
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;
138 static bool arg_firmware_setup
= false;
139 static bool arg_now
= false;
141 static bool original_stdout_is_tty
;
143 static int daemon_reload(sd_bus
*bus
, char **args
);
144 static int halt_now(enum action a
);
145 static int check_one_unit(sd_bus
*bus
, const char *name
, const char *good_states
, bool quiet
);
147 static char** strv_skip_first(char **strv
) {
148 if (strv_length(strv
) > 0)
153 static void pager_open_if_enabled(void) {
161 static void ask_password_agent_open_if_enabled(void) {
163 /* Open the password agent as a child process if necessary */
165 if (!arg_ask_password
)
168 if (arg_scope
!= UNIT_FILE_SYSTEM
)
171 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
174 ask_password_agent_open();
177 static void polkit_agent_open_if_enabled(void) {
179 /* Open the polkit agent as a child process if necessary */
181 if (!arg_ask_password
)
184 if (arg_scope
!= UNIT_FILE_SYSTEM
)
187 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
193 static OutputFlags
get_output_flags(void) {
195 arg_all
* OUTPUT_SHOW_ALL
|
196 arg_full
* OUTPUT_FULL_WIDTH
|
197 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH
|
198 on_tty() * OUTPUT_COLOR
|
199 !arg_quiet
* OUTPUT_WARN_CUTOFF
;
202 static int translate_bus_error_to_exit_status(int r
, const sd_bus_error
*error
) {
205 if (!sd_bus_error_is_set(error
))
208 if (sd_bus_error_has_name(error
, SD_BUS_ERROR_ACCESS_DENIED
) ||
209 sd_bus_error_has_name(error
, BUS_ERROR_ONLY_BY_DEPENDENCY
) ||
210 sd_bus_error_has_name(error
, BUS_ERROR_NO_ISOLATION
) ||
211 sd_bus_error_has_name(error
, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE
))
212 return EXIT_NOPERMISSION
;
214 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
))
215 return EXIT_NOTINSTALLED
;
217 if (sd_bus_error_has_name(error
, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE
) ||
218 sd_bus_error_has_name(error
, SD_BUS_ERROR_NOT_SUPPORTED
))
219 return EXIT_NOTIMPLEMENTED
;
221 if (sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
))
222 return EXIT_NOTCONFIGURED
;
230 static void warn_wall(enum action a
) {
231 static const char *table
[_ACTION_MAX
] = {
232 [ACTION_HALT
] = "The system is going down for system halt NOW!",
233 [ACTION_REBOOT
] = "The system is going down for reboot NOW!",
234 [ACTION_POWEROFF
] = "The system is going down for power-off NOW!",
235 [ACTION_KEXEC
] = "The system is going down for kexec reboot NOW!",
236 [ACTION_RESCUE
] = "The system is going down to rescue mode NOW!",
237 [ACTION_EMERGENCY
] = "The system is going down to emergency mode NOW!",
238 [ACTION_CANCEL_SHUTDOWN
] = "The system shutdown has been cancelled NOW!"
245 _cleanup_free_
char *p
;
247 p
= strv_join(arg_wall
, " ");
254 utmp_wall(p
, NULL
, NULL
, NULL
, NULL
);
262 utmp_wall(table
[a
], NULL
, NULL
, NULL
, NULL
);
265 static bool avoid_bus(void) {
267 if (running_in_chroot() > 0)
270 if (sd_booted() <= 0)
273 if (!isempty(arg_root
))
276 if (arg_scope
== UNIT_FILE_GLOBAL
)
282 static int compare_unit_info(const void *a
, const void *b
) {
283 const UnitInfo
*u
= a
, *v
= b
;
287 /* First, order by machine */
288 if (!u
->machine
&& v
->machine
)
290 if (u
->machine
&& !v
->machine
)
292 if (u
->machine
&& v
->machine
) {
293 r
= strcasecmp(u
->machine
, v
->machine
);
298 /* Second, order by unit type */
299 d1
= strrchr(u
->id
, '.');
300 d2
= strrchr(v
->id
, '.');
302 r
= strcasecmp(d1
, d2
);
307 /* Third, order by name */
308 return strcasecmp(u
->id
, v
->id
);
311 static bool output_show_unit(const UnitInfo
*u
, char **patterns
) {
312 if (!strv_fnmatch_or_empty(patterns
, u
->id
, FNM_NOESCAPE
))
318 dot
= strrchr(u
->id
, '.');
322 if (!strv_find(arg_types
, dot
+1))
332 if (streq(u
->active_state
, "inactive") || u
->following
[0])
338 static int output_units_list(const UnitInfo
*unit_infos
, unsigned c
) {
339 unsigned circle_len
= 0, id_len
, max_id_len
, load_len
, active_len
, sub_len
, job_len
, desc_len
;
341 unsigned n_shown
= 0;
344 max_id_len
= strlen("UNIT");
345 load_len
= strlen("LOAD");
346 active_len
= strlen("ACTIVE");
347 sub_len
= strlen("SUB");
348 job_len
= strlen("JOB");
351 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
352 max_id_len
= MAX(max_id_len
, strlen(u
->id
) + (u
->machine
? strlen(u
->machine
)+1 : 0));
353 load_len
= MAX(load_len
, strlen(u
->load_state
));
354 active_len
= MAX(active_len
, strlen(u
->active_state
));
355 sub_len
= MAX(sub_len
, strlen(u
->sub_state
));
357 if (u
->job_id
!= 0) {
358 job_len
= MAX(job_len
, strlen(u
->job_type
));
362 if (!arg_no_legend
&&
363 (streq(u
->active_state
, "failed") ||
364 STR_IN_SET(u
->load_state
, "error", "not-found", "masked")))
368 if (!arg_full
&& original_stdout_is_tty
) {
371 id_len
= MIN(max_id_len
, 25u);
372 basic_len
= circle_len
+ 5 + id_len
+ 5 + active_len
+ sub_len
;
375 basic_len
+= job_len
+ 1;
377 if (basic_len
< (unsigned) columns()) {
378 unsigned extra_len
, incr
;
379 extra_len
= columns() - basic_len
;
381 /* Either UNIT already got 25, or is fully satisfied.
382 * Grant up to 25 to DESC now. */
383 incr
= MIN(extra_len
, 25u);
387 /* split the remaining space between UNIT and DESC,
388 * but do not give UNIT more than it needs. */
390 incr
= MIN(extra_len
/ 2, max_id_len
- id_len
);
392 desc_len
+= extra_len
- incr
;
398 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
399 _cleanup_free_
char *e
= NULL
, *j
= NULL
;
400 const char *on_loaded
= "", *off_loaded
= "";
401 const char *on_active
= "", *off_active
= "";
402 const char *on_circle
= "", *off_circle
= "";
406 if (!n_shown
&& !arg_no_legend
) {
411 printf("%-*s %-*s %-*s %-*s ",
414 active_len
, "ACTIVE",
418 printf("%-*s ", job_len
, "JOB");
420 if (!arg_full
&& arg_no_pager
)
421 printf("%.*s\n", desc_len
, "DESCRIPTION");
423 printf("%s\n", "DESCRIPTION");
428 if (STR_IN_SET(u
->load_state
, "error", "not-found", "masked") && !arg_plain
) {
429 on_loaded
= ansi_highlight_red();
430 on_circle
= ansi_highlight_yellow();
431 off_loaded
= off_circle
= ansi_highlight_off();
433 } else if (streq(u
->active_state
, "failed") && !arg_plain
) {
434 on_circle
= on_active
= ansi_highlight_red();
435 off_circle
= off_active
= ansi_highlight_off();
440 j
= strjoin(u
->machine
, ":", u
->id
, NULL
);
449 e
= ellipsize(id
, id_len
, 33);
457 printf("%s%s%s ", on_circle
, circle
? draw_special_char(DRAW_BLACK_CIRCLE
) : " ", off_circle
);
459 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
460 on_active
, id_len
, id
, off_active
,
461 on_loaded
, load_len
, u
->load_state
, off_loaded
,
462 on_active
, active_len
, u
->active_state
,
463 sub_len
, u
->sub_state
, off_active
,
464 job_count
? job_len
+ 1 : 0, u
->job_id
? u
->job_type
: "");
467 printf("%.*s\n", desc_len
, u
->description
);
469 printf("%s\n", u
->description
);
472 if (!arg_no_legend
) {
473 const char *on
, *off
;
477 "LOAD = Reflects whether the unit definition was properly loaded.\n"
478 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
479 "SUB = The low-level unit activation state, values depend on unit type.");
480 puts(job_count
? "JOB = Pending job for the unit.\n" : "");
481 on
= ansi_highlight();
482 off
= ansi_highlight_off();
484 on
= ansi_highlight_red();
485 off
= ansi_highlight_off();
489 printf("%s%u loaded units listed.%s\n"
490 "To show all installed unit files use 'systemctl list-unit-files'.\n",
493 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
494 "To show all installed unit files use 'systemctl list-unit-files'.\n",
501 static int get_unit_list(
505 UnitInfo
**unit_infos
,
507 sd_bus_message
**_reply
) {
509 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
510 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
511 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
520 r
= sd_bus_message_new_method_call(
523 "org.freedesktop.systemd1",
524 "/org/freedesktop/systemd1",
525 "org.freedesktop.systemd1.Manager",
526 "ListUnitsFiltered");
529 return bus_log_create_error(r
);
531 r
= sd_bus_message_append_strv(m
, arg_states
);
533 return bus_log_create_error(r
);
535 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
537 log_error("Failed to list units: %s", bus_error_message(&error
, r
));
541 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssssouso)");
543 return bus_log_parse_error(r
);
545 while ((r
= bus_parse_unit_info(reply
, &u
)) > 0) {
548 if (!output_show_unit(&u
, patterns
))
551 if (!GREEDY_REALLOC(*unit_infos
, size
, c
+1))
554 (*unit_infos
)[c
++] = u
;
557 return bus_log_parse_error(r
);
559 r
= sd_bus_message_exit_container(reply
);
561 return bus_log_parse_error(r
);
569 static void message_set_freep(Set
**set
) {
572 while ((m
= set_steal_first(*set
)))
573 sd_bus_message_unref(m
);
578 static int get_unit_list_recursive(
581 UnitInfo
**_unit_infos
,
585 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
586 _cleanup_(message_set_freep
) Set
*replies
;
587 sd_bus_message
*reply
;
595 replies
= set_new(NULL
);
599 c
= get_unit_list(bus
, NULL
, patterns
, &unit_infos
, 0, &reply
);
603 r
= set_put(replies
, reply
);
605 sd_bus_message_unref(reply
);
610 _cleanup_strv_free_
char **machines
= NULL
;
613 r
= sd_get_machine_names(&machines
);
617 STRV_FOREACH(i
, machines
) {
618 _cleanup_bus_close_unref_ sd_bus
*container
= NULL
;
621 r
= sd_bus_open_system_machine(&container
, *i
);
623 log_error_errno(r
, "Failed to connect to container %s: %m", *i
);
627 k
= get_unit_list(container
, *i
, patterns
, &unit_infos
, c
, &reply
);
633 r
= set_put(replies
, reply
);
635 sd_bus_message_unref(reply
);
640 *_machines
= machines
;
645 *_unit_infos
= unit_infos
;
654 static int list_units(sd_bus
*bus
, char **args
) {
655 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
656 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
657 _cleanup_strv_free_
char **machines
= NULL
;
660 pager_open_if_enabled();
662 r
= get_unit_list_recursive(bus
, strv_skip_first(args
), &unit_infos
, &replies
, &machines
);
666 qsort_safe(unit_infos
, r
, sizeof(UnitInfo
), compare_unit_info
);
667 return output_units_list(unit_infos
, r
);
670 static int get_triggered_units(
675 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
678 r
= sd_bus_get_property_strv(
680 "org.freedesktop.systemd1",
682 "org.freedesktop.systemd1.Unit",
688 log_error("Failed to determine triggers: %s", bus_error_message(&error
, r
));
693 static int get_listening(
695 const char* unit_path
,
698 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
699 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
700 const char *type
, *path
;
703 r
= sd_bus_get_property(
705 "org.freedesktop.systemd1",
707 "org.freedesktop.systemd1.Socket",
713 log_error("Failed to get list of listening sockets: %s", bus_error_message(&error
, r
));
717 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
719 return bus_log_parse_error(r
);
721 while ((r
= sd_bus_message_read(reply
, "(ss)", &type
, &path
)) > 0) {
723 r
= strv_extend(listening
, type
);
727 r
= strv_extend(listening
, path
);
734 return bus_log_parse_error(r
);
736 r
= sd_bus_message_exit_container(reply
);
738 return bus_log_parse_error(r
);
750 /* Note: triggered is a list here, although it almost certainly
751 * will always be one unit. Nevertheless, dbus API allows for multiple
752 * values, so let's follow that. */
755 /* The strv above is shared. free is set only in the first one. */
759 static int socket_info_compare(const struct socket_info
*a
, const struct socket_info
*b
) {
765 if (!a
->machine
&& b
->machine
)
767 if (a
->machine
&& !b
->machine
)
769 if (a
->machine
&& b
->machine
) {
770 o
= strcasecmp(a
->machine
, b
->machine
);
775 o
= strcmp(a
->path
, b
->path
);
777 o
= strcmp(a
->type
, b
->type
);
782 static int output_sockets_list(struct socket_info
*socket_infos
, unsigned cs
) {
783 struct socket_info
*s
;
784 unsigned pathlen
= strlen("LISTEN"),
785 typelen
= strlen("TYPE") * arg_show_types
,
786 socklen
= strlen("UNIT"),
787 servlen
= strlen("ACTIVATES");
788 const char *on
, *off
;
790 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
794 socklen
= MAX(socklen
, strlen(s
->id
));
796 typelen
= MAX(typelen
, strlen(s
->type
));
797 pathlen
= MAX(pathlen
, strlen(s
->path
) + (s
->machine
? strlen(s
->machine
)+1 : 0));
799 STRV_FOREACH(a
, s
->triggered
)
800 tmp
+= strlen(*a
) + 2*(a
!= s
->triggered
);
801 servlen
= MAX(servlen
, tmp
);
806 printf("%-*s %-*.*s%-*s %s\n",
808 typelen
+ arg_show_types
, typelen
+ arg_show_types
, "TYPE ",
812 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
813 _cleanup_free_
char *j
= NULL
;
818 j
= strjoin(s
->machine
, ":", s
->path
, NULL
);
826 printf("%-*s %-*s %-*s",
827 pathlen
, path
, typelen
, s
->type
, socklen
, s
->id
);
830 pathlen
, path
, socklen
, s
->id
);
831 STRV_FOREACH(a
, s
->triggered
)
833 a
== s
->triggered
? "" : ",", *a
);
837 on
= ansi_highlight();
838 off
= ansi_highlight_off();
842 on
= ansi_highlight_red();
843 off
= ansi_highlight_off();
846 if (!arg_no_legend
) {
847 printf("%s%u sockets listed.%s\n", on
, cs
, off
);
849 printf("Pass --all to see loaded but inactive sockets, too.\n");
855 static int list_sockets(sd_bus
*bus
, char **args
) {
856 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
857 _cleanup_strv_free_
char **machines
= NULL
;
858 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
859 _cleanup_free_
struct socket_info
*socket_infos
= NULL
;
861 struct socket_info
*s
;
866 pager_open_if_enabled();
868 n
= get_unit_list_recursive(bus
, strv_skip_first(args
), &unit_infos
, &replies
, &machines
);
872 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
873 _cleanup_strv_free_
char **listening
= NULL
, **triggered
= NULL
;
876 if (!endswith(u
->id
, ".socket"))
879 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
883 c
= get_listening(bus
, u
->unit_path
, &listening
);
889 if (!GREEDY_REALLOC(socket_infos
, size
, cs
+ c
)) {
894 for (i
= 0; i
< c
; i
++)
895 socket_infos
[cs
+ i
] = (struct socket_info
) {
896 .machine
= u
->machine
,
898 .type
= listening
[i
*2],
899 .path
= listening
[i
*2 + 1],
900 .triggered
= triggered
,
901 .own_triggered
= i
==0,
904 /* from this point on we will cleanup those socket_infos */
907 listening
= triggered
= NULL
; /* avoid cleanup */
910 qsort_safe(socket_infos
, cs
, sizeof(struct socket_info
),
911 (__compar_fn_t
) socket_info_compare
);
913 output_sockets_list(socket_infos
, cs
);
916 assert(cs
== 0 || socket_infos
);
917 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
920 if (s
->own_triggered
)
921 strv_free(s
->triggered
);
927 static int get_next_elapse(
930 dual_timestamp
*next
) {
932 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
940 r
= sd_bus_get_property_trivial(
942 "org.freedesktop.systemd1",
944 "org.freedesktop.systemd1.Timer",
945 "NextElapseUSecMonotonic",
950 log_error("Failed to get next elapsation time: %s", bus_error_message(&error
, r
));
954 r
= sd_bus_get_property_trivial(
956 "org.freedesktop.systemd1",
958 "org.freedesktop.systemd1.Timer",
959 "NextElapseUSecRealtime",
964 log_error("Failed to get next elapsation time: %s", bus_error_message(&error
, r
));
972 static int get_last_trigger(
977 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
984 r
= sd_bus_get_property_trivial(
986 "org.freedesktop.systemd1",
988 "org.freedesktop.systemd1.Timer",
994 log_error("Failed to get last trigger time: %s", bus_error_message(&error
, r
));
1002 const char* machine
;
1005 usec_t last_trigger
;
1009 static int timer_info_compare(const struct timer_info
*a
, const struct timer_info
*b
) {
1015 if (!a
->machine
&& b
->machine
)
1017 if (a
->machine
&& !b
->machine
)
1019 if (a
->machine
&& b
->machine
) {
1020 o
= strcasecmp(a
->machine
, b
->machine
);
1025 if (a
->next_elapse
< b
->next_elapse
)
1027 if (a
->next_elapse
> b
->next_elapse
)
1030 return strcmp(a
->id
, b
->id
);
1033 static int output_timers_list(struct timer_info
*timer_infos
, unsigned n
) {
1034 struct timer_info
*t
;
1036 nextlen
= strlen("NEXT"),
1037 leftlen
= strlen("LEFT"),
1038 lastlen
= strlen("LAST"),
1039 passedlen
= strlen("PASSED"),
1040 unitlen
= strlen("UNIT"),
1041 activatelen
= strlen("ACTIVATES");
1043 const char *on
, *off
;
1045 assert(timer_infos
|| n
== 0);
1047 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1051 if (t
->next_elapse
> 0) {
1052 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1054 format_timestamp(tstamp
, sizeof(tstamp
), t
->next_elapse
);
1055 nextlen
= MAX(nextlen
, strlen(tstamp
) + 1);
1057 format_timestamp_relative(trel
, sizeof(trel
), t
->next_elapse
);
1058 leftlen
= MAX(leftlen
, strlen(trel
));
1061 if (t
->last_trigger
> 0) {
1062 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1064 format_timestamp(tstamp
, sizeof(tstamp
), t
->last_trigger
);
1065 lastlen
= MAX(lastlen
, strlen(tstamp
) + 1);
1067 format_timestamp_relative(trel
, sizeof(trel
), t
->last_trigger
);
1068 passedlen
= MAX(passedlen
, strlen(trel
));
1071 unitlen
= MAX(unitlen
, strlen(t
->id
) + (t
->machine
? strlen(t
->machine
)+1 : 0));
1073 STRV_FOREACH(a
, t
->triggered
)
1074 ul
+= strlen(*a
) + 2*(a
!= t
->triggered
);
1076 activatelen
= MAX(activatelen
, ul
);
1081 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1085 passedlen
, "PASSED",
1089 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1090 _cleanup_free_
char *j
= NULL
;
1092 char tstamp1
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel1
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1093 char tstamp2
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel2
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1096 format_timestamp(tstamp1
, sizeof(tstamp1
), t
->next_elapse
);
1097 format_timestamp_relative(trel1
, sizeof(trel1
), t
->next_elapse
);
1099 format_timestamp(tstamp2
, sizeof(tstamp2
), t
->last_trigger
);
1100 format_timestamp_relative(trel2
, sizeof(trel2
), t
->last_trigger
);
1103 j
= strjoin(t
->machine
, ":", t
->id
, NULL
);
1110 printf("%-*s %-*s %-*s %-*s %-*s",
1111 nextlen
, tstamp1
, leftlen
, trel1
, lastlen
, tstamp2
, passedlen
, trel2
, unitlen
, unit
);
1113 STRV_FOREACH(a
, t
->triggered
)
1115 a
== t
->triggered
? "" : ",", *a
);
1119 on
= ansi_highlight();
1120 off
= ansi_highlight_off();
1124 on
= ansi_highlight_red();
1125 off
= ansi_highlight_off();
1128 if (!arg_no_legend
) {
1129 printf("%s%u timers listed.%s\n", on
, n
, off
);
1131 printf("Pass --all to see loaded but inactive timers, too.\n");
1137 static usec_t
calc_next_elapse(dual_timestamp
*nw
, dual_timestamp
*next
) {
1143 if (next
->monotonic
!= USEC_INFINITY
&& next
->monotonic
> 0) {
1146 if (next
->monotonic
> nw
->monotonic
)
1147 converted
= nw
->realtime
+ (next
->monotonic
- nw
->monotonic
);
1149 converted
= nw
->realtime
- (nw
->monotonic
- next
->monotonic
);
1151 if (next
->realtime
!= USEC_INFINITY
&& next
->realtime
> 0)
1152 next_elapse
= MIN(converted
, next
->realtime
);
1154 next_elapse
= converted
;
1157 next_elapse
= next
->realtime
;
1162 static int list_timers(sd_bus
*bus
, char **args
) {
1163 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
1164 _cleanup_strv_free_
char **machines
= NULL
;
1165 _cleanup_free_
struct timer_info
*timer_infos
= NULL
;
1166 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
1167 struct timer_info
*t
;
1174 pager_open_if_enabled();
1176 n
= get_unit_list_recursive(bus
, strv_skip_first(args
), &unit_infos
, &replies
, &machines
);
1180 dual_timestamp_get(&nw
);
1182 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
1183 _cleanup_strv_free_
char **triggered
= NULL
;
1184 dual_timestamp next
= {};
1187 if (!endswith(u
->id
, ".timer"))
1190 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
1194 r
= get_next_elapse(bus
, u
->unit_path
, &next
);
1198 get_last_trigger(bus
, u
->unit_path
, &last
);
1200 if (!GREEDY_REALLOC(timer_infos
, size
, c
+1)) {
1205 m
= calc_next_elapse(&nw
, &next
);
1207 timer_infos
[c
++] = (struct timer_info
) {
1208 .machine
= u
->machine
,
1211 .last_trigger
= last
,
1212 .triggered
= triggered
,
1215 triggered
= NULL
; /* avoid cleanup */
1218 qsort_safe(timer_infos
, c
, sizeof(struct timer_info
),
1219 (__compar_fn_t
) timer_info_compare
);
1221 output_timers_list(timer_infos
, c
);
1224 for (t
= timer_infos
; t
< timer_infos
+ c
; t
++)
1225 strv_free(t
->triggered
);
1230 static int compare_unit_file_list(const void *a
, const void *b
) {
1231 const char *d1
, *d2
;
1232 const UnitFileList
*u
= a
, *v
= b
;
1234 d1
= strrchr(u
->path
, '.');
1235 d2
= strrchr(v
->path
, '.');
1240 r
= strcasecmp(d1
, d2
);
1245 return strcasecmp(basename(u
->path
), basename(v
->path
));
1248 static bool output_show_unit_file(const UnitFileList
*u
, char **patterns
) {
1249 if (!strv_fnmatch_or_empty(patterns
, basename(u
->path
), FNM_NOESCAPE
))
1252 if (!strv_isempty(arg_types
)) {
1255 dot
= strrchr(u
->path
, '.');
1259 if (!strv_find(arg_types
, dot
+1))
1263 if (!strv_isempty(arg_states
) &&
1264 !strv_find(arg_states
, unit_file_state_to_string(u
->state
)))
1270 static void output_unit_file_list(const UnitFileList
*units
, unsigned c
) {
1271 unsigned max_id_len
, id_cols
, state_cols
;
1272 const UnitFileList
*u
;
1274 max_id_len
= strlen("UNIT FILE");
1275 state_cols
= strlen("STATE");
1277 for (u
= units
; u
< units
+ c
; u
++) {
1278 max_id_len
= MAX(max_id_len
, strlen(basename(u
->path
)));
1279 state_cols
= MAX(state_cols
, strlen(unit_file_state_to_string(u
->state
)));
1283 unsigned basic_cols
;
1285 id_cols
= MIN(max_id_len
, 25u);
1286 basic_cols
= 1 + id_cols
+ state_cols
;
1287 if (basic_cols
< (unsigned) columns())
1288 id_cols
+= MIN(columns() - basic_cols
, max_id_len
- id_cols
);
1290 id_cols
= max_id_len
;
1293 printf("%-*s %-*s\n",
1294 id_cols
, "UNIT FILE",
1295 state_cols
, "STATE");
1297 for (u
= units
; u
< units
+ c
; u
++) {
1298 _cleanup_free_
char *e
= NULL
;
1299 const char *on
, *off
;
1302 if (u
->state
== UNIT_FILE_MASKED
||
1303 u
->state
== UNIT_FILE_MASKED_RUNTIME
||
1304 u
->state
== UNIT_FILE_DISABLED
||
1305 u
->state
== UNIT_FILE_INVALID
) {
1306 on
= ansi_highlight_red();
1307 off
= ansi_highlight_off();
1308 } else if (u
->state
== UNIT_FILE_ENABLED
) {
1309 on
= ansi_highlight_green();
1310 off
= ansi_highlight_off();
1314 id
= basename(u
->path
);
1316 e
= arg_full
? NULL
: ellipsize(id
, id_cols
, 33);
1318 printf("%-*s %s%-*s%s\n",
1319 id_cols
, e
? e
: id
,
1320 on
, state_cols
, unit_file_state_to_string(u
->state
), off
);
1324 printf("\n%u unit files listed.\n", c
);
1327 static int list_unit_files(sd_bus
*bus
, char **args
) {
1328 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1329 _cleanup_free_ UnitFileList
*units
= NULL
;
1337 pager_open_if_enabled();
1345 h
= hashmap_new(&string_hash_ops
);
1349 r
= unit_file_get_list(arg_scope
, arg_root
, h
);
1351 unit_file_list_free(h
);
1352 log_error_errno(r
, "Failed to get unit file list: %m");
1356 n_units
= hashmap_size(h
);
1358 units
= new(UnitFileList
, n_units
);
1359 if (!units
&& n_units
> 0) {
1360 unit_file_list_free(h
);
1364 HASHMAP_FOREACH(u
, h
, i
) {
1365 if (!output_show_unit_file(u
, strv_skip_first(args
)))
1372 assert(c
<= n_units
);
1375 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1377 r
= sd_bus_call_method(
1379 "org.freedesktop.systemd1",
1380 "/org/freedesktop/systemd1",
1381 "org.freedesktop.systemd1.Manager",
1387 log_error("Failed to list unit files: %s", bus_error_message(&error
, r
));
1391 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
1393 return bus_log_parse_error(r
);
1395 while ((r
= sd_bus_message_read(reply
, "(ss)", &path
, &state
)) > 0) {
1397 if (!GREEDY_REALLOC(units
, size
, c
+ 1))
1400 units
[c
] = (struct UnitFileList
) {
1402 unit_file_state_from_string(state
)
1405 if (output_show_unit_file(&units
[c
], strv_skip_first(args
)))
1410 return bus_log_parse_error(r
);
1412 r
= sd_bus_message_exit_container(reply
);
1414 return bus_log_parse_error(r
);
1417 qsort_safe(units
, c
, sizeof(UnitFileList
), compare_unit_file_list
);
1418 output_unit_file_list(units
, c
);
1421 for (unit
= units
; unit
< units
+ c
; unit
++)
1428 static int list_dependencies_print(const char *name
, int level
, unsigned int branches
, bool last
) {
1429 _cleanup_free_
char *n
= NULL
;
1430 size_t max_len
= MAX(columns(),20u);
1436 for (i
= level
- 1; i
>= 0; i
--) {
1438 if (len
> max_len
- 3 && !arg_full
) {
1439 printf("%s...\n",max_len
% 2 ? "" : " ");
1442 printf("%s", draw_special_char(branches
& (1 << i
) ? DRAW_TREE_VERTICAL
: DRAW_TREE_SPACE
));
1446 if (len
> max_len
- 3 && !arg_full
) {
1447 printf("%s...\n",max_len
% 2 ? "" : " ");
1451 printf("%s", draw_special_char(last
? DRAW_TREE_RIGHT
: DRAW_TREE_BRANCH
));
1455 printf("%s\n", name
);
1459 n
= ellipsize(name
, max_len
-len
, 100);
1467 static int list_dependencies_get_dependencies(sd_bus
*bus
, const char *name
, char ***deps
) {
1469 static const char *dependencies
[_DEPENDENCY_MAX
] = {
1470 [DEPENDENCY_FORWARD
] = "Requires\0"
1471 "RequiresOverridable\0"
1473 "RequisiteOverridable\0"
1476 [DEPENDENCY_REVERSE
] = "RequiredBy\0"
1477 "RequiredByOverridable\0"
1481 [DEPENDENCY_AFTER
] = "After\0",
1482 [DEPENDENCY_BEFORE
] = "Before\0",
1485 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1486 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1487 _cleanup_strv_free_
char **ret
= NULL
;
1488 _cleanup_free_
char *path
= NULL
;
1494 assert_cc(ELEMENTSOF(dependencies
) == _DEPENDENCY_MAX
);
1496 path
= unit_dbus_path_from_name(name
);
1500 r
= sd_bus_call_method(
1502 "org.freedesktop.systemd1",
1504 "org.freedesktop.DBus.Properties",
1508 "s", "org.freedesktop.systemd1.Unit");
1510 log_error("Failed to get properties of %s: %s", name
, bus_error_message(&error
, r
));
1514 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
1516 return bus_log_parse_error(r
);
1518 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
1521 r
= sd_bus_message_read(reply
, "s", &prop
);
1523 return bus_log_parse_error(r
);
1525 if (!nulstr_contains(dependencies
[arg_dependency
], prop
)) {
1526 r
= sd_bus_message_skip(reply
, "v");
1528 return bus_log_parse_error(r
);
1531 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, "as");
1533 return bus_log_parse_error(r
);
1535 r
= bus_message_read_strv_extend(reply
, &ret
);
1537 return bus_log_parse_error(r
);
1539 r
= sd_bus_message_exit_container(reply
);
1541 return bus_log_parse_error(r
);
1544 r
= sd_bus_message_exit_container(reply
);
1546 return bus_log_parse_error(r
);
1550 return bus_log_parse_error(r
);
1552 r
= sd_bus_message_exit_container(reply
);
1554 return bus_log_parse_error(r
);
1562 static int list_dependencies_compare(const void *_a
, const void *_b
) {
1563 const char **a
= (const char**) _a
, **b
= (const char**) _b
;
1565 if (unit_name_to_type(*a
) == UNIT_TARGET
&& unit_name_to_type(*b
) != UNIT_TARGET
)
1567 if (unit_name_to_type(*a
) != UNIT_TARGET
&& unit_name_to_type(*b
) == UNIT_TARGET
)
1570 return strcasecmp(*a
, *b
);
1573 static int list_dependencies_one(
1578 unsigned int branches
) {
1580 _cleanup_strv_free_
char **deps
= NULL
;
1588 r
= strv_extend(units
, name
);
1592 r
= list_dependencies_get_dependencies(bus
, name
, &deps
);
1596 qsort_safe(deps
, strv_length(deps
), sizeof (char*), list_dependencies_compare
);
1598 STRV_FOREACH(c
, deps
) {
1599 if (strv_contains(*units
, *c
)) {
1601 r
= list_dependencies_print("...", level
+ 1, (branches
<< 1) | (c
[1] == NULL
? 0 : 1), 1);
1614 state
= check_one_unit(bus
, *c
, "activating\0active\0reloading\0", true);
1615 on
= state
> 0 ? ansi_highlight_green() : ansi_highlight_red();
1616 printf("%s%s%s ", on
, draw_special_char(DRAW_BLACK_CIRCLE
), ansi_highlight_off());
1619 r
= list_dependencies_print(*c
, level
, branches
, c
[1] == NULL
);
1623 if (arg_all
|| unit_name_to_type(*c
) == UNIT_TARGET
) {
1624 r
= list_dependencies_one(bus
, *c
, level
+ 1, units
, (branches
<< 1) | (c
[1] == NULL
? 0 : 1));
1631 strv_remove(*units
, name
);
1636 static int list_dependencies(sd_bus
*bus
, char **args
) {
1637 _cleanup_strv_free_
char **units
= NULL
;
1638 _cleanup_free_
char *unit
= NULL
;
1645 r
= unit_name_mangle(args
[1], UNIT_NAME_NOGLOB
, &unit
);
1647 return log_error_errno(r
, "Failed to mangle unit name: %m");
1651 u
= SPECIAL_DEFAULT_TARGET
;
1653 pager_open_if_enabled();
1657 return list_dependencies_one(bus
, u
, 0, &units
, 0);
1660 struct machine_info
{
1664 char *control_group
;
1665 uint32_t n_failed_units
;
1670 static const struct bus_properties_map machine_info_property_map
[] = {
1671 { "SystemState", "s", NULL
, offsetof(struct machine_info
, state
) },
1672 { "NJobs", "u", NULL
, offsetof(struct machine_info
, n_jobs
) },
1673 { "NFailedUnits", "u", NULL
, offsetof(struct machine_info
, n_failed_units
) },
1674 { "ControlGroup", "s", NULL
, offsetof(struct machine_info
, control_group
) },
1675 { "UserspaceTimestamp", "t", NULL
, offsetof(struct machine_info
, timestamp
) },
1679 static void free_machines_list(struct machine_info
*machine_infos
, int n
) {
1685 for (i
= 0; i
< n
; i
++) {
1686 free(machine_infos
[i
].name
);
1687 free(machine_infos
[i
].state
);
1688 free(machine_infos
[i
].control_group
);
1691 free(machine_infos
);
1694 static int compare_machine_info(const void *a
, const void *b
) {
1695 const struct machine_info
*u
= a
, *v
= b
;
1697 if (u
->is_host
!= v
->is_host
)
1698 return u
->is_host
> v
->is_host
? -1 : 1;
1700 return strcasecmp(u
->name
, v
->name
);
1703 static int get_machine_properties(sd_bus
*bus
, struct machine_info
*mi
) {
1704 _cleanup_bus_close_unref_ sd_bus
*container
= NULL
;
1710 r
= sd_bus_open_system_machine(&container
, mi
->name
);
1717 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, mi
);
1724 static bool output_show_machine(const char *name
, char **patterns
) {
1725 return strv_fnmatch_or_empty(patterns
, name
, FNM_NOESCAPE
);
1728 static int get_machine_list(
1730 struct machine_info
**_machine_infos
,
1733 struct machine_info
*machine_infos
= NULL
;
1734 _cleanup_strv_free_
char **m
= NULL
;
1735 _cleanup_free_
char *hn
= NULL
;
1740 hn
= gethostname_malloc();
1744 if (output_show_machine(hn
, patterns
)) {
1745 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1))
1748 machine_infos
[c
].is_host
= true;
1749 machine_infos
[c
].name
= hn
;
1752 get_machine_properties(bus
, &machine_infos
[c
]);
1756 sd_get_machine_names(&m
);
1757 STRV_FOREACH(i
, m
) {
1758 _cleanup_free_
char *class = NULL
;
1760 if (!output_show_machine(*i
, patterns
))
1763 sd_machine_get_class(*i
, &class);
1764 if (!streq_ptr(class, "container"))
1767 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1)) {
1768 free_machines_list(machine_infos
, c
);
1772 machine_infos
[c
].is_host
= false;
1773 machine_infos
[c
].name
= strdup(*i
);
1774 if (!machine_infos
[c
].name
) {
1775 free_machines_list(machine_infos
, c
);
1779 get_machine_properties(NULL
, &machine_infos
[c
]);
1783 *_machine_infos
= machine_infos
;
1787 static void output_machines_list(struct machine_info
*machine_infos
, unsigned n
) {
1788 struct machine_info
*m
;
1791 namelen
= sizeof("NAME") - 1,
1792 statelen
= sizeof("STATE") - 1,
1793 failedlen
= sizeof("FAILED") - 1,
1794 jobslen
= sizeof("JOBS") - 1;
1796 assert(machine_infos
|| n
== 0);
1798 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
1799 namelen
= MAX(namelen
, strlen(m
->name
) + (m
->is_host
? sizeof(" (host)") - 1 : 0));
1800 statelen
= MAX(statelen
, m
->state
? strlen(m
->state
) : 0);
1801 failedlen
= MAX(failedlen
, DECIMAL_STR_WIDTH(m
->n_failed_units
));
1802 jobslen
= MAX(jobslen
, DECIMAL_STR_WIDTH(m
->n_jobs
));
1804 if (!arg_plain
&& !streq_ptr(m
->state
, "running"))
1808 if (!arg_no_legend
) {
1812 printf("%-*s %-*s %-*s %-*s\n",
1815 failedlen
, "FAILED",
1819 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
1820 const char *on_state
= "", *off_state
= "";
1821 const char *on_failed
= "", *off_failed
= "";
1822 bool circle
= false;
1824 if (streq_ptr(m
->state
, "degraded")) {
1825 on_state
= ansi_highlight_red();
1826 off_state
= ansi_highlight_off();
1828 } else if (!streq_ptr(m
->state
, "running")) {
1829 on_state
= ansi_highlight_yellow();
1830 off_state
= ansi_highlight_off();
1834 if (m
->n_failed_units
> 0) {
1835 on_failed
= ansi_highlight_red();
1836 off_failed
= ansi_highlight_off();
1838 on_failed
= off_failed
= "";
1841 printf("%s%s%s ", on_state
, circle
? draw_special_char(DRAW_BLACK_CIRCLE
) : " ", off_state
);
1844 printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
1845 (int) (namelen
- (sizeof(" (host)")-1)), strna(m
->name
),
1846 on_state
, statelen
, strna(m
->state
), off_state
,
1847 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
1848 jobslen
, m
->n_jobs
);
1850 printf("%-*s %s%-*s%s %s%*u%s %*u\n",
1851 namelen
, strna(m
->name
),
1852 on_state
, statelen
, strna(m
->state
), off_state
,
1853 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
1854 jobslen
, m
->n_jobs
);
1858 printf("\n%u machines listed.\n", n
);
1861 static int list_machines(sd_bus
*bus
, char **args
) {
1862 struct machine_info
*machine_infos
= NULL
;
1867 if (geteuid() != 0) {
1868 log_error("Must be root.");
1872 pager_open_if_enabled();
1874 r
= get_machine_list(bus
, &machine_infos
, strv_skip_first(args
));
1878 qsort_safe(machine_infos
, r
, sizeof(struct machine_info
), compare_machine_info
);
1879 output_machines_list(machine_infos
, r
);
1880 free_machines_list(machine_infos
, r
);
1885 static int get_default(sd_bus
*bus
, char **args
) {
1886 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1887 _cleanup_free_
char *_path
= NULL
;
1891 if (!bus
|| avoid_bus()) {
1892 r
= unit_file_get_default(arg_scope
, arg_root
, &_path
);
1894 return log_error_errno(r
, "Failed to get default target: %m");
1898 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1900 r
= sd_bus_call_method(
1902 "org.freedesktop.systemd1",
1903 "/org/freedesktop/systemd1",
1904 "org.freedesktop.systemd1.Manager",
1910 log_error("Failed to get default target: %s", bus_error_message(&error
, -r
));
1914 r
= sd_bus_message_read(reply
, "s", &path
);
1916 return bus_log_parse_error(r
);
1920 printf("%s\n", path
);
1925 static void dump_unit_file_changes(const UnitFileChange
*changes
, unsigned n_changes
) {
1928 assert(changes
|| n_changes
== 0);
1930 for (i
= 0; i
< n_changes
; i
++) {
1931 if (changes
[i
].type
== UNIT_FILE_SYMLINK
)
1932 log_info("Created symlink from %s to %s.", changes
[i
].path
, changes
[i
].source
);
1934 log_info("Removed symlink %s.", changes
[i
].path
);
1938 static int set_default(sd_bus
*bus
, char **args
) {
1939 _cleanup_free_
char *unit
= NULL
;
1940 UnitFileChange
*changes
= NULL
;
1941 unsigned n_changes
= 0;
1944 r
= unit_name_mangle_with_suffix(args
[1], UNIT_NAME_NOGLOB
, ".target", &unit
);
1946 return log_error_errno(r
, "Failed to mangle unit name: %m");
1948 if (!bus
|| avoid_bus()) {
1949 r
= unit_file_set_default(arg_scope
, arg_root
, unit
, true, &changes
, &n_changes
);
1951 return log_error_errno(r
, "Failed to set default target: %m");
1954 dump_unit_file_changes(changes
, n_changes
);
1958 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1959 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1961 polkit_agent_open_if_enabled();
1963 r
= sd_bus_call_method(
1965 "org.freedesktop.systemd1",
1966 "/org/freedesktop/systemd1",
1967 "org.freedesktop.systemd1.Manager",
1973 log_error("Failed to set default target: %s", bus_error_message(&error
, -r
));
1977 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, NULL
, NULL
);
1981 /* Try to reload if enabled */
1983 r
= daemon_reload(bus
, args
);
1988 unit_file_changes_free(changes
, n_changes
);
1995 const char *name
, *type
, *state
;
1998 static void output_jobs_list(const struct job_info
* jobs
, unsigned n
, bool skipped
) {
1999 unsigned id_len
, unit_len
, type_len
, state_len
;
2000 const struct job_info
*j
;
2001 const char *on
, *off
;
2002 bool shorten
= false;
2004 assert(n
== 0 || jobs
);
2007 if (!arg_no_legend
) {
2008 on
= ansi_highlight_green();
2009 off
= ansi_highlight_off();
2011 printf("%sNo jobs %s.%s\n", on
, skipped
? "listed" : "running", off
);
2016 pager_open_if_enabled();
2018 id_len
= strlen("JOB");
2019 unit_len
= strlen("UNIT");
2020 type_len
= strlen("TYPE");
2021 state_len
= strlen("STATE");
2023 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2024 uint32_t id
= j
->id
;
2025 assert(j
->name
&& j
->type
&& j
->state
);
2027 id_len
= MAX(id_len
, DECIMAL_STR_WIDTH(id
));
2028 unit_len
= MAX(unit_len
, strlen(j
->name
));
2029 type_len
= MAX(type_len
, strlen(j
->type
));
2030 state_len
= MAX(state_len
, strlen(j
->state
));
2033 if (!arg_full
&& id_len
+ 1 + unit_len
+ type_len
+ 1 + state_len
> columns()) {
2034 unit_len
= MAX(33u, columns() - id_len
- type_len
- state_len
- 3);
2039 printf("%*s %-*s %-*s %-*s\n",
2043 state_len
, "STATE");
2045 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2046 _cleanup_free_
char *e
= NULL
;
2048 if (streq(j
->state
, "running")) {
2049 on
= ansi_highlight();
2050 off
= ansi_highlight_off();
2054 e
= shorten
? ellipsize(j
->name
, unit_len
, 33) : NULL
;
2055 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2057 on
, unit_len
, e
? e
: j
->name
, off
,
2059 on
, state_len
, j
->state
, off
);
2062 if (!arg_no_legend
) {
2063 on
= ansi_highlight();
2064 off
= ansi_highlight_off();
2066 printf("\n%s%u jobs listed%s.\n", on
, n
, off
);
2070 static bool output_show_job(struct job_info
*job
, char **patterns
) {
2071 return strv_fnmatch_or_empty(patterns
, job
->name
, FNM_NOESCAPE
);
2074 static int list_jobs(sd_bus
*bus
, char **args
) {
2075 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2076 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2077 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2078 _cleanup_free_
struct job_info
*jobs
= NULL
;
2083 bool skipped
= false;
2085 r
= sd_bus_call_method(
2087 "org.freedesktop.systemd1",
2088 "/org/freedesktop/systemd1",
2089 "org.freedesktop.systemd1.Manager",
2095 log_error("Failed to list jobs: %s", bus_error_message(&error
, r
));
2099 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2101 return bus_log_parse_error(r
);
2103 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0) {
2104 struct job_info job
= { id
, name
, type
, state
};
2106 if (!output_show_job(&job
, strv_skip_first(args
))) {
2111 if (!GREEDY_REALLOC(jobs
, size
, c
+ 1))
2117 return bus_log_parse_error(r
);
2119 r
= sd_bus_message_exit_container(reply
);
2121 return bus_log_parse_error(r
);
2123 output_jobs_list(jobs
, c
, skipped
);
2127 static int cancel_job(sd_bus
*bus
, char **args
) {
2133 if (strv_length(args
) <= 1)
2134 return daemon_reload(bus
, args
);
2136 polkit_agent_open_if_enabled();
2138 STRV_FOREACH(name
, args
+1) {
2139 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2143 q
= safe_atou32(*name
, &id
);
2145 return log_error_errno(q
, "Failed to parse job id \"%s\": %m", *name
);
2147 q
= sd_bus_call_method(
2149 "org.freedesktop.systemd1",
2150 "/org/freedesktop/systemd1",
2151 "org.freedesktop.systemd1.Manager",
2157 log_error("Failed to cancel job %"PRIu32
": %s", id
, bus_error_message(&error
, q
));
2166 static int need_daemon_reload(sd_bus
*bus
, const char *unit
) {
2167 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2171 /* We ignore all errors here, since this is used to show a
2174 /* We don't use unit_dbus_path_from_name() directly since we
2175 * don't want to load the unit if it isn't loaded. */
2177 r
= sd_bus_call_method(
2179 "org.freedesktop.systemd1",
2180 "/org/freedesktop/systemd1",
2181 "org.freedesktop.systemd1.Manager",
2189 r
= sd_bus_message_read(reply
, "o", &path
);
2193 r
= sd_bus_get_property_trivial(
2195 "org.freedesktop.systemd1",
2197 "org.freedesktop.systemd1.Unit",
2207 static void warn_unit_file_changed(const char *name
) {
2208 log_warning("%sWarning:%s %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
2209 ansi_highlight_red(),
2210 ansi_highlight_off(),
2212 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user");
2215 static int unit_file_find_path(LookupPaths
*lp
, const char *unit_name
, char **unit_path
) {
2222 STRV_FOREACH(p
, lp
->unit_path
) {
2223 _cleanup_free_
char *path
;
2225 path
= path_join(arg_root
, *p
, unit_name
);
2229 if (access(path
, F_OK
) == 0) {
2239 static int unit_find_paths(
2241 const char *unit_name
,
2242 bool avoid_bus_cache
,
2244 char **fragment_path
,
2245 char ***dropin_paths
) {
2247 _cleanup_free_
char *path
= NULL
;
2248 _cleanup_strv_free_
char **dropins
= NULL
;
2252 * Finds where the unit is defined on disk. Returns 0 if the unit
2253 * is not found. Returns 1 if it is found, and sets
2254 * - the path to the unit in *path, if it exists on disk,
2255 * - and a strv of existing drop-ins in *dropins,
2256 * if the arg is not NULL and any dropins were found.
2260 assert(fragment_path
);
2263 if (!avoid_bus_cache
&& !unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
2264 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2265 _cleanup_bus_message_unref_ sd_bus_message
*unit_load_error
= NULL
;
2266 _cleanup_free_
char *unit
= NULL
;
2267 char *unit_load_error_name
, *unit_load_error_message
;
2269 unit
= unit_dbus_path_from_name(unit_name
);
2273 if (need_daemon_reload(bus
, unit_name
) > 0)
2274 warn_unit_file_changed(unit_name
);
2276 r
= sd_bus_get_property(
2278 "org.freedesktop.systemd1",
2280 "org.freedesktop.systemd1.Unit",
2286 return log_error_errno(r
, "Failed to get LoadError: %s", bus_error_message(&error
, r
));
2288 r
= sd_bus_message_read(
2291 &unit_load_error_name
,
2292 &unit_load_error_message
);
2294 return bus_log_parse_error(r
);
2296 if (!isempty(unit_load_error_name
)) {
2297 log_error("Unit %s is not loaded: %s", unit_name
, unit_load_error_message
);
2301 r
= sd_bus_get_property_string(
2303 "org.freedesktop.systemd1",
2305 "org.freedesktop.systemd1.Unit",
2310 return log_error_errno(r
, "Failed to get FragmentPath: %s", bus_error_message(&error
, r
));
2313 r
= sd_bus_get_property_strv(
2315 "org.freedesktop.systemd1",
2317 "org.freedesktop.systemd1.Unit",
2322 return log_error_errno(r
, "Failed to get DropInPaths: %s", bus_error_message(&error
, r
));
2325 _cleanup_set_free_ Set
*names
;
2327 names
= set_new(NULL
);
2331 r
= set_put(names
, unit_name
);
2333 return log_error_errno(r
, "Failed to add unit name: %m");
2335 r
= unit_file_find_path(lp
, unit_name
, &path
);
2340 _cleanup_free_
char *template = NULL
;
2342 r
= unit_name_template(unit_name
, &template);
2343 if (r
< 0 && r
!= -EINVAL
)
2344 return log_error_errno(r
, "Failed to determine template name: %m");
2346 r
= unit_file_find_path(lp
, template, &path
);
2353 r
= unit_file_find_dropin_paths(lp
->unit_path
, NULL
, names
, &dropins
);
2361 if (!isempty(path
)) {
2362 *fragment_path
= path
;
2367 if (dropin_paths
&& !strv_isempty(dropins
)) {
2368 *dropin_paths
= dropins
;
2374 log_error("No files found for %s.", unit_name
);
2379 static int check_one_unit(sd_bus
*bus
, const char *name
, const char *good_states
, bool quiet
) {
2380 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2381 _cleanup_free_
char *n
= NULL
, *state
= NULL
;
2387 r
= unit_name_mangle(name
, UNIT_NAME_NOGLOB
, &n
);
2389 return log_error_errno(r
, "Failed to mangle unit name: %m");
2391 /* We don't use unit_dbus_path_from_name() directly since we
2392 * don't want to load the unit if it isn't loaded. */
2394 r
= sd_bus_call_method(
2396 "org.freedesktop.systemd1",
2397 "/org/freedesktop/systemd1",
2398 "org.freedesktop.systemd1.Manager",
2409 r
= sd_bus_message_read(reply
, "o", &path
);
2411 return bus_log_parse_error(r
);
2413 r
= sd_bus_get_property_string(
2415 "org.freedesktop.systemd1",
2417 "org.freedesktop.systemd1.Unit",
2430 return nulstr_contains(good_states
, state
);
2433 static int check_triggering_units(
2437 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2438 _cleanup_free_
char *path
= NULL
, *n
= NULL
, *state
= NULL
;
2439 _cleanup_strv_free_
char **triggered_by
= NULL
;
2440 bool print_warning_label
= true;
2444 r
= unit_name_mangle(name
, UNIT_NAME_NOGLOB
, &n
);
2446 return log_error_errno(r
, "Failed to mangle unit name: %m");
2448 path
= unit_dbus_path_from_name(n
);
2452 r
= sd_bus_get_property_string(
2454 "org.freedesktop.systemd1",
2456 "org.freedesktop.systemd1.Unit",
2461 log_error("Failed to get load state of %s: %s", n
, bus_error_message(&error
, r
));
2465 if (streq(state
, "masked"))
2468 r
= sd_bus_get_property_strv(
2470 "org.freedesktop.systemd1",
2472 "org.freedesktop.systemd1.Unit",
2477 log_error("Failed to get triggered by array of %s: %s", n
, bus_error_message(&error
, r
));
2481 STRV_FOREACH(i
, triggered_by
) {
2482 r
= check_one_unit(bus
, *i
, "active\0reloading\0", true);
2484 return log_error_errno(r
, "Failed to check unit: %m");
2489 if (print_warning_label
) {
2490 log_warning("Warning: Stopping %s, but it can still be activated by:", n
);
2491 print_warning_label
= false;
2494 log_warning(" %s", *i
);
2500 static const struct {
2503 } unit_actions
[] = {
2504 { "start", "StartUnit" },
2505 { "stop", "StopUnit" },
2506 { "condstop", "StopUnit" },
2507 { "reload", "ReloadUnit" },
2508 { "restart", "RestartUnit" },
2509 { "try-restart", "TryRestartUnit" },
2510 { "condrestart", "TryRestartUnit" },
2511 { "reload-or-restart", "ReloadOrRestartUnit" },
2512 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2513 { "condreload", "ReloadOrTryRestartUnit" },
2514 { "force-reload", "ReloadOrTryRestartUnit" }
2517 static const char *verb_to_method(const char *verb
) {
2520 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2521 if (streq_ptr(unit_actions
[i
].verb
, verb
))
2522 return unit_actions
[i
].method
;
2527 static const char *method_to_verb(const char *method
) {
2530 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2531 if (streq_ptr(unit_actions
[i
].method
, method
))
2532 return unit_actions
[i
].verb
;
2537 static int start_unit_one(
2542 sd_bus_error
*error
,
2543 BusWaitForJobs
*w
) {
2545 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2554 log_debug("Calling manager for %s on %s, %s", method
, name
, mode
);
2556 r
= sd_bus_call_method(
2558 "org.freedesktop.systemd1",
2559 "/org/freedesktop/systemd1",
2560 "org.freedesktop.systemd1.Manager",
2568 if (r
== -ENOENT
&& arg_action
!= ACTION_SYSTEMCTL
)
2569 /* There's always a fallback possible for
2570 * legacy actions. */
2571 return -EADDRNOTAVAIL
;
2573 verb
= method_to_verb(method
);
2575 log_error("Failed to %s %s: %s", verb
, name
, bus_error_message(error
, r
));
2579 r
= sd_bus_message_read(reply
, "o", &path
);
2581 return bus_log_parse_error(r
);
2583 if (need_daemon_reload(bus
, name
) > 0)
2584 warn_unit_file_changed(name
);
2587 log_debug("Adding %s to the set", path
);
2588 r
= bus_wait_for_jobs_add(w
, path
);
2596 static int expand_names(sd_bus
*bus
, char **names
, const char* suffix
, char ***ret
) {
2598 _cleanup_strv_free_
char **mangled
= NULL
, **globs
= NULL
;
2602 STRV_FOREACH(name
, names
) {
2606 r
= unit_name_mangle_with_suffix(*name
, UNIT_NAME_GLOB
, suffix
, &t
);
2608 r
= unit_name_mangle(*name
, UNIT_NAME_GLOB
, &t
);
2610 return log_error_errno(r
, "Failed to mangle name: %m");
2612 if (string_is_glob(t
))
2613 r
= strv_consume(&globs
, t
);
2615 r
= strv_consume(&mangled
, t
);
2620 /* Query the manager only if any of the names are a glob, since
2621 * this is fairly expensive */
2622 if (!strv_isempty(globs
)) {
2623 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2624 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
2627 return log_error_errno(EOPNOTSUPP
, "Unit name globbing without bus is not implemented.");
2629 r
= get_unit_list(bus
, NULL
, globs
, &unit_infos
, 0, &reply
);
2633 for (i
= 0; i
< r
; i
++)
2634 if (strv_extend(&mangled
, unit_infos
[i
].id
) < 0)
2639 mangled
= NULL
; /* do not free */
2644 static const struct {
2648 } action_table
[_ACTION_MAX
] = {
2649 [ACTION_HALT
] = { SPECIAL_HALT_TARGET
, "halt", "replace-irreversibly" },
2650 [ACTION_POWEROFF
] = { SPECIAL_POWEROFF_TARGET
, "poweroff", "replace-irreversibly" },
2651 [ACTION_REBOOT
] = { SPECIAL_REBOOT_TARGET
, "reboot", "replace-irreversibly" },
2652 [ACTION_KEXEC
] = { SPECIAL_KEXEC_TARGET
, "kexec", "replace-irreversibly" },
2653 [ACTION_RUNLEVEL2
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2654 [ACTION_RUNLEVEL3
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2655 [ACTION_RUNLEVEL4
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2656 [ACTION_RUNLEVEL5
] = { SPECIAL_GRAPHICAL_TARGET
, NULL
, "isolate" },
2657 [ACTION_RESCUE
] = { SPECIAL_RESCUE_TARGET
, "rescue", "isolate" },
2658 [ACTION_EMERGENCY
] = { SPECIAL_EMERGENCY_TARGET
, "emergency", "isolate" },
2659 [ACTION_DEFAULT
] = { SPECIAL_DEFAULT_TARGET
, "default", "isolate" },
2660 [ACTION_EXIT
] = { SPECIAL_EXIT_TARGET
, "exit", "replace-irreversibly" },
2661 [ACTION_SUSPEND
] = { SPECIAL_SUSPEND_TARGET
, "suspend", "replace-irreversibly" },
2662 [ACTION_HIBERNATE
] = { SPECIAL_HIBERNATE_TARGET
, "hibernate", "replace-irreversibly" },
2663 [ACTION_HYBRID_SLEEP
] = { SPECIAL_HYBRID_SLEEP_TARGET
, "hybrid-sleep", "replace-irreversibly" },
2666 static enum action
verb_to_action(const char *verb
) {
2669 for (i
= _ACTION_INVALID
; i
< _ACTION_MAX
; i
++)
2670 if (streq_ptr(action_table
[i
].verb
, verb
))
2673 return _ACTION_INVALID
;
2676 static int start_unit(sd_bus
*bus
, char **args
) {
2677 _cleanup_(bus_wait_for_jobs_freep
) BusWaitForJobs
*w
= NULL
;
2678 const char *method
, *mode
, *one_name
, *suffix
= NULL
;
2679 _cleanup_strv_free_
char **names
= NULL
;
2685 ask_password_agent_open_if_enabled();
2686 polkit_agent_open_if_enabled();
2688 if (arg_action
== ACTION_SYSTEMCTL
) {
2690 method
= verb_to_method(args
[0]);
2691 action
= verb_to_action(args
[0]);
2693 if (streq(args
[0], "isolate")) {
2697 mode
= action_table
[action
].mode
?: arg_job_mode
;
2699 one_name
= action_table
[action
].target
;
2701 assert(arg_action
< ELEMENTSOF(action_table
));
2702 assert(action_table
[arg_action
].target
);
2704 method
= "StartUnit";
2706 mode
= action_table
[arg_action
].mode
;
2707 one_name
= action_table
[arg_action
].target
;
2711 names
= strv_new(one_name
, NULL
);
2713 r
= expand_names(bus
, args
+ 1, suffix
, &names
);
2715 log_error_errno(r
, "Failed to expand names: %m");
2718 if (!arg_no_block
) {
2719 r
= bus_wait_for_jobs_new(bus
, &w
);
2721 return log_error_errno(r
, "Could not watch jobs: %m");
2724 STRV_FOREACH(name
, names
) {
2725 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2728 q
= start_unit_one(bus
, method
, *name
, mode
, &error
, w
);
2729 if (r
>= 0 && q
< 0)
2730 r
= translate_bus_error_to_exit_status(q
, &error
);
2733 if (!arg_no_block
) {
2736 q
= bus_wait_for_jobs(w
, arg_quiet
);
2740 /* When stopping units, warn if they can still be triggered by
2741 * another active unit (socket, path, timer) */
2742 if (!arg_quiet
&& streq(method
, "StopUnit"))
2743 STRV_FOREACH(name
, names
)
2744 check_triggering_units(bus
, *name
);
2750 /* Ask systemd-logind, which might grant access to unprivileged users
2751 * through PolicyKit */
2752 static int reboot_with_logind(sd_bus
*bus
, enum action a
) {
2754 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2761 polkit_agent_open_if_enabled();
2769 case ACTION_POWEROFF
:
2770 method
= "PowerOff";
2773 case ACTION_SUSPEND
:
2777 case ACTION_HIBERNATE
:
2778 method
= "Hibernate";
2781 case ACTION_HYBRID_SLEEP
:
2782 method
= "HybridSleep";
2789 r
= sd_bus_call_method(
2791 "org.freedesktop.login1",
2792 "/org/freedesktop/login1",
2793 "org.freedesktop.login1.Manager",
2797 "b", arg_ask_password
);
2799 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
2807 static int check_inhibitors(sd_bus
*bus
, enum action a
) {
2809 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2810 _cleanup_strv_free_
char **sessions
= NULL
;
2811 const char *what
, *who
, *why
, *mode
;
2820 if (arg_ignore_inhibitors
|| arg_force
> 0)
2832 r
= sd_bus_call_method(
2834 "org.freedesktop.login1",
2835 "/org/freedesktop/login1",
2836 "org.freedesktop.login1.Manager",
2842 /* If logind is not around, then there are no inhibitors... */
2845 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssuu)");
2847 return bus_log_parse_error(r
);
2849 while ((r
= sd_bus_message_read(reply
, "(ssssuu)", &what
, &who
, &why
, &mode
, &uid
, &pid
)) > 0) {
2850 _cleanup_free_
char *comm
= NULL
, *user
= NULL
;
2851 _cleanup_strv_free_
char **sv
= NULL
;
2853 if (!streq(mode
, "block"))
2856 sv
= strv_split(what
, ":");
2860 if ((pid_t
) pid
< 0)
2861 return log_error_errno(ERANGE
, "Bad PID %"PRIu32
": %m", pid
);
2863 if (!strv_contains(sv
,
2865 a
== ACTION_POWEROFF
||
2866 a
== ACTION_REBOOT
||
2867 a
== ACTION_KEXEC
? "shutdown" : "sleep"))
2870 get_process_comm(pid
, &comm
);
2871 user
= uid_to_name(uid
);
2873 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT
" \"%s\", user %s), reason is \"%s\".",
2874 who
, (pid_t
) pid
, strna(comm
), strna(user
), why
);
2879 return bus_log_parse_error(r
);
2881 r
= sd_bus_message_exit_container(reply
);
2883 return bus_log_parse_error(r
);
2885 /* Check for current sessions */
2886 sd_get_sessions(&sessions
);
2887 STRV_FOREACH(s
, sessions
) {
2888 _cleanup_free_
char *type
= NULL
, *tty
= NULL
, *seat
= NULL
, *user
= NULL
, *service
= NULL
, *class = NULL
;
2890 if (sd_session_get_uid(*s
, &uid
) < 0 || uid
== getuid())
2893 if (sd_session_get_class(*s
, &class) < 0 || !streq(class, "user"))
2896 if (sd_session_get_type(*s
, &type
) < 0 || (!streq(type
, "x11") && !streq(type
, "tty")))
2899 sd_session_get_tty(*s
, &tty
);
2900 sd_session_get_seat(*s
, &seat
);
2901 sd_session_get_service(*s
, &service
);
2902 user
= uid_to_name(uid
);
2904 log_warning("User %s is logged in on %s.", strna(user
), isempty(tty
) ? (isempty(seat
) ? strna(service
) : seat
) : tty
);
2911 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2912 action_table
[a
].verb
);
2920 static int prepare_firmware_setup(sd_bus
*bus
) {
2922 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2926 if (!arg_firmware_setup
)
2929 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
2931 r
= efi_set_reboot_to_firmware(true);
2933 log_debug_errno(r
, "Cannot indicate to EFI to boot into setup mode, will retry via logind: %m");
2939 r
= sd_bus_call_method(
2941 "org.freedesktop.login1",
2942 "/org/freedesktop/login1",
2943 "org.freedesktop.login1.Manager",
2944 "SetRebootToFirmwareSetup",
2949 log_error("Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error
, r
));
2955 log_error("Cannot remotely indicate to EFI to boot into setup mode.");
2960 static int start_special(sd_bus
*bus
, char **args
) {
2966 a
= verb_to_action(args
[0]);
2968 r
= check_inhibitors(bus
, a
);
2972 if (arg_force
>= 2 && geteuid() != 0) {
2973 log_error("Must be root.");
2977 r
= prepare_firmware_setup(bus
);
2981 if (a
== ACTION_REBOOT
&& args
[1]) {
2982 r
= update_reboot_param_file(args
[1]);
2987 if (arg_force
>= 2 &&
2988 (a
== ACTION_HALT
||
2989 a
== ACTION_POWEROFF
||
2990 a
== ACTION_REBOOT
))
2993 if (arg_force
>= 1 &&
2994 (a
== ACTION_HALT
||
2995 a
== ACTION_POWEROFF
||
2996 a
== ACTION_REBOOT
||
2997 a
== ACTION_KEXEC
||
2999 return daemon_reload(bus
, args
);
3001 /* first try logind, to allow authentication with polkit */
3002 if (geteuid() != 0 &&
3003 (a
== ACTION_POWEROFF
||
3004 a
== ACTION_REBOOT
||
3005 a
== ACTION_SUSPEND
||
3006 a
== ACTION_HIBERNATE
||
3007 a
== ACTION_HYBRID_SLEEP
)) {
3008 r
= reboot_with_logind(bus
, a
);
3009 if (r
>= 0 || IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
3013 r
= start_unit(bus
, args
);
3014 if (r
== EXIT_SUCCESS
)
3020 static int check_unit_generic(sd_bus
*bus
, int code
, const char *good_states
, char **args
) {
3021 _cleanup_strv_free_
char **names
= NULL
;
3028 r
= expand_names(bus
, args
, NULL
, &names
);
3030 return log_error_errno(r
, "Failed to expand names: %m");
3032 STRV_FOREACH(name
, names
) {
3035 state
= check_one_unit(bus
, *name
, good_states
, arg_quiet
);
3045 static int check_unit_active(sd_bus
*bus
, char **args
) {
3046 /* According to LSB: 3, "program is not running" */
3047 return check_unit_generic(bus
, 3, "active\0reloading\0", args
+ 1);
3050 static int check_unit_failed(sd_bus
*bus
, char **args
) {
3051 return check_unit_generic(bus
, 1, "failed\0", args
+ 1);
3054 static int kill_unit(sd_bus
*bus
, char **args
) {
3055 _cleanup_strv_free_
char **names
= NULL
;
3062 polkit_agent_open_if_enabled();
3065 arg_kill_who
= "all";
3067 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
3069 log_error_errno(r
, "Failed to expand names: %m");
3071 STRV_FOREACH(name
, names
) {
3072 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
3074 q
= sd_bus_call_method(
3076 "org.freedesktop.systemd1",
3077 "/org/freedesktop/systemd1",
3078 "org.freedesktop.systemd1.Manager",
3082 "ssi", *names
, arg_kill_who
, arg_signal
);
3084 log_error("Failed to kill unit %s: %s", *names
, bus_error_message(&error
, q
));
3093 typedef struct ExecStatusInfo
{
3101 usec_t start_timestamp
;
3102 usec_t exit_timestamp
;
3107 LIST_FIELDS(struct ExecStatusInfo
, exec
);
3110 static void exec_status_info_free(ExecStatusInfo
*i
) {
3119 static int exec_status_info_deserialize(sd_bus_message
*m
, ExecStatusInfo
*i
) {
3120 uint64_t start_timestamp
, exit_timestamp
, start_timestamp_monotonic
, exit_timestamp_monotonic
;
3123 int32_t code
, status
;
3129 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_STRUCT
, "sasbttttuii");
3131 return bus_log_parse_error(r
);
3135 r
= sd_bus_message_read(m
, "s", &path
);
3137 return bus_log_parse_error(r
);
3139 i
->path
= strdup(path
);
3143 r
= sd_bus_message_read_strv(m
, &i
->argv
);
3145 return bus_log_parse_error(r
);
3147 r
= sd_bus_message_read(m
,
3150 &start_timestamp
, &start_timestamp_monotonic
,
3151 &exit_timestamp
, &exit_timestamp_monotonic
,
3155 return bus_log_parse_error(r
);
3158 i
->start_timestamp
= (usec_t
) start_timestamp
;
3159 i
->exit_timestamp
= (usec_t
) exit_timestamp
;
3160 i
->pid
= (pid_t
) pid
;
3164 r
= sd_bus_message_exit_container(m
);
3166 return bus_log_parse_error(r
);
3171 typedef struct UnitStatusInfo
{
3173 const char *load_state
;
3174 const char *active_state
;
3175 const char *sub_state
;
3176 const char *unit_file_state
;
3177 const char *unit_file_preset
;
3179 const char *description
;
3180 const char *following
;
3182 char **documentation
;
3184 const char *fragment_path
;
3185 const char *source_path
;
3186 const char *control_group
;
3188 char **dropin_paths
;
3190 const char *load_error
;
3193 usec_t inactive_exit_timestamp
;
3194 usec_t inactive_exit_timestamp_monotonic
;
3195 usec_t active_enter_timestamp
;
3196 usec_t active_exit_timestamp
;
3197 usec_t inactive_enter_timestamp
;
3199 bool need_daemon_reload
;
3204 const char *status_text
;
3205 const char *pid_file
;
3209 usec_t start_timestamp
;
3210 usec_t exit_timestamp
;
3212 int exit_code
, exit_status
;
3214 usec_t condition_timestamp
;
3215 bool condition_result
;
3216 bool failed_condition_trigger
;
3217 bool failed_condition_negate
;
3218 const char *failed_condition
;
3219 const char *failed_condition_parameter
;
3221 usec_t assert_timestamp
;
3223 bool failed_assert_trigger
;
3224 bool failed_assert_negate
;
3225 const char *failed_assert
;
3226 const char *failed_assert_parameter
;
3229 unsigned n_accepted
;
3230 unsigned n_connections
;
3233 /* Pairs of type, path */
3237 const char *sysfs_path
;
3239 /* Mount, Automount */
3246 uint64_t memory_current
;
3247 uint64_t memory_limit
;
3248 uint64_t cpu_usage_nsec
;
3250 LIST_HEAD(ExecStatusInfo
, exec
);
3253 static void print_status_info(
3258 const char *active_on
, *active_off
, *on
, *off
, *ss
;
3260 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], *s1
;
3261 char since2
[FORMAT_TIMESTAMP_MAX
], *s2
;
3267 /* This shows pretty information about a unit. See
3268 * print_property() for a low-level property printer */
3270 if (streq_ptr(i
->active_state
, "failed")) {
3271 active_on
= ansi_highlight_red();
3272 active_off
= ansi_highlight_off();
3273 } else if (streq_ptr(i
->active_state
, "active") || streq_ptr(i
->active_state
, "reloading")) {
3274 active_on
= ansi_highlight_green();
3275 active_off
= ansi_highlight_off();
3277 active_on
= active_off
= "";
3279 printf("%s%s%s %s", active_on
, draw_special_char(DRAW_BLACK_CIRCLE
), active_off
, strna(i
->id
));
3281 if (i
->description
&& !streq_ptr(i
->id
, i
->description
))
3282 printf(" - %s", i
->description
);
3287 printf(" Follow: unit currently follows state of %s\n", i
->following
);
3289 if (streq_ptr(i
->load_state
, "error")) {
3290 on
= ansi_highlight_red();
3291 off
= ansi_highlight_off();
3295 path
= i
->source_path
? i
->source_path
: i
->fragment_path
;
3298 printf(" Loaded: %s%s%s (Reason: %s)\n",
3299 on
, strna(i
->load_state
), off
, i
->load_error
);
3300 else if (path
&& !isempty(i
->unit_file_state
) && !isempty(i
->unit_file_preset
))
3301 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
3302 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
, i
->unit_file_preset
);
3303 else if (path
&& !isempty(i
->unit_file_state
))
3304 printf(" Loaded: %s%s%s (%s; %s)\n",
3305 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
);
3307 printf(" Loaded: %s%s%s (%s)\n",
3308 on
, strna(i
->load_state
), off
, path
);
3310 printf(" Loaded: %s%s%s\n",
3311 on
, strna(i
->load_state
), off
);
3313 if (!strv_isempty(i
->dropin_paths
)) {
3314 _cleanup_free_
char *dir
= NULL
;
3318 STRV_FOREACH(dropin
, i
->dropin_paths
) {
3319 if (! dir
|| last
) {
3320 printf(dir
? " " : " Drop-In: ");
3325 if (path_get_parent(*dropin
, &dir
) < 0) {
3330 printf("%s\n %s", dir
,
3331 draw_special_char(DRAW_TREE_RIGHT
));
3334 last
= ! (*(dropin
+ 1) && startswith(*(dropin
+ 1), dir
));
3336 printf("%s%s", basename(*dropin
), last
? "\n" : ", ");
3340 ss
= streq_ptr(i
->active_state
, i
->sub_state
) ? NULL
: i
->sub_state
;
3342 printf(" Active: %s%s (%s)%s",
3343 active_on
, strna(i
->active_state
), ss
, active_off
);
3345 printf(" Active: %s%s%s",
3346 active_on
, strna(i
->active_state
), active_off
);
3348 if (!isempty(i
->result
) && !streq(i
->result
, "success"))
3349 printf(" (Result: %s)", i
->result
);
3351 timestamp
= (streq_ptr(i
->active_state
, "active") ||
3352 streq_ptr(i
->active_state
, "reloading")) ? i
->active_enter_timestamp
:
3353 (streq_ptr(i
->active_state
, "inactive") ||
3354 streq_ptr(i
->active_state
, "failed")) ? i
->inactive_enter_timestamp
:
3355 streq_ptr(i
->active_state
, "activating") ? i
->inactive_exit_timestamp
:
3356 i
->active_exit_timestamp
;
3358 s1
= format_timestamp_relative(since1
, sizeof(since1
), timestamp
);
3359 s2
= format_timestamp(since2
, sizeof(since2
), timestamp
);
3362 printf(" since %s; %s\n", s2
, s1
);
3364 printf(" since %s\n", s2
);
3368 if (!i
->condition_result
&& i
->condition_timestamp
> 0) {
3369 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->condition_timestamp
);
3370 s2
= format_timestamp(since2
, sizeof(since2
), i
->condition_timestamp
);
3372 printf("Condition: start %scondition failed%s at %s%s%s\n",
3373 ansi_highlight_yellow(), ansi_highlight_off(),
3374 s2
, s1
? "; " : "", s1
? s1
: "");
3375 if (i
->failed_condition_trigger
)
3376 printf(" none of the trigger conditions were met\n");
3377 else if (i
->failed_condition
)
3378 printf(" %s=%s%s was not met\n",
3379 i
->failed_condition
,
3380 i
->failed_condition_negate
? "!" : "",
3381 i
->failed_condition_parameter
);
3384 if (!i
->assert_result
&& i
->assert_timestamp
> 0) {
3385 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->assert_timestamp
);
3386 s2
= format_timestamp(since2
, sizeof(since2
), i
->assert_timestamp
);
3388 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
3389 ansi_highlight_red(), ansi_highlight_off(),
3390 s2
, s1
? "; " : "", s1
? s1
: "");
3391 if (i
->failed_assert_trigger
)
3392 printf(" none of the trigger assertions were met\n");
3393 else if (i
->failed_assert
)
3394 printf(" %s=%s%s was not met\n",
3396 i
->failed_assert_negate
? "!" : "",
3397 i
->failed_assert_parameter
);
3401 printf(" Device: %s\n", i
->sysfs_path
);
3403 printf(" Where: %s\n", i
->where
);
3405 printf(" What: %s\n", i
->what
);
3407 STRV_FOREACH(t
, i
->documentation
)
3408 printf(" %*s %s\n", 9, t
== i
->documentation
? "Docs:" : "", *t
);
3410 STRV_FOREACH_PAIR(t
, t2
, i
->listen
)
3411 printf(" %*s %s (%s)\n", 9, t
== i
->listen
? "Listen:" : "", *t2
, *t
);
3414 printf(" Accepted: %u; Connected: %u\n", i
->n_accepted
, i
->n_connections
);
3416 LIST_FOREACH(exec
, p
, i
->exec
) {
3417 _cleanup_free_
char *argv
= NULL
;
3420 /* Only show exited processes here */
3424 argv
= strv_join(p
->argv
, " ");
3425 printf(" Process: "PID_FMT
" %s=%s ", p
->pid
, p
->name
, strna(argv
));
3427 good
= is_clean_exit_lsb(p
->code
, p
->status
, NULL
);
3429 on
= ansi_highlight_red();
3430 off
= ansi_highlight_off();
3434 printf("%s(code=%s, ", on
, sigchld_code_to_string(p
->code
));
3436 if (p
->code
== CLD_EXITED
) {
3439 printf("status=%i", p
->status
);
3441 c
= exit_status_to_string(p
->status
, EXIT_STATUS_SYSTEMD
);
3446 printf("signal=%s", signal_to_string(p
->status
));
3448 printf(")%s\n", off
);
3450 if (i
->main_pid
== p
->pid
&&
3451 i
->start_timestamp
== p
->start_timestamp
&&
3452 i
->exit_timestamp
== p
->start_timestamp
)
3453 /* Let's not show this twice */
3456 if (p
->pid
== i
->control_pid
)
3460 if (i
->main_pid
> 0 || i
->control_pid
> 0) {
3461 if (i
->main_pid
> 0) {
3462 printf(" Main PID: "PID_FMT
, i
->main_pid
);
3465 _cleanup_free_
char *comm
= NULL
;
3466 get_process_comm(i
->main_pid
, &comm
);
3468 printf(" (%s)", comm
);
3469 } else if (i
->exit_code
> 0) {
3470 printf(" (code=%s, ", sigchld_code_to_string(i
->exit_code
));
3472 if (i
->exit_code
== CLD_EXITED
) {
3475 printf("status=%i", i
->exit_status
);
3477 c
= exit_status_to_string(i
->exit_status
, EXIT_STATUS_SYSTEMD
);
3482 printf("signal=%s", signal_to_string(i
->exit_status
));
3486 if (i
->control_pid
> 0)
3490 if (i
->control_pid
> 0) {
3491 _cleanup_free_
char *c
= NULL
;
3493 printf(" %8s: "PID_FMT
, i
->main_pid
? "" : " Control", i
->control_pid
);
3495 get_process_comm(i
->control_pid
, &c
);
3504 printf(" Status: \"%s\"\n", i
->status_text
);
3505 if (i
->status_errno
> 0)
3506 printf(" Error: %i (%s)\n", i
->status_errno
, strerror(i
->status_errno
));
3508 if (i
->memory_current
!= (uint64_t) -1) {
3509 char buf
[FORMAT_BYTES_MAX
];
3511 printf(" Memory: %s", format_bytes(buf
, sizeof(buf
), i
->memory_current
));
3513 if (i
->memory_limit
!= (uint64_t) -1)
3514 printf(" (limit: %s)\n", format_bytes(buf
, sizeof(buf
), i
->memory_limit
));
3519 if (i
->cpu_usage_nsec
!= (uint64_t) -1) {
3520 char buf
[FORMAT_TIMESPAN_MAX
];
3521 printf(" CPU: %s\n", format_timespan(buf
, sizeof(buf
), i
->cpu_usage_nsec
/ NSEC_PER_USEC
, USEC_PER_MSEC
));
3524 if (i
->control_group
&&
3525 (i
->main_pid
> 0 || i
->control_pid
> 0 ||
3526 ((arg_transport
!= BUS_TRANSPORT_LOCAL
&& arg_transport
!= BUS_TRANSPORT_MACHINE
) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, false) == 0))) {
3529 printf(" CGroup: %s\n", i
->control_group
);
3531 if (arg_transport
== BUS_TRANSPORT_LOCAL
|| arg_transport
== BUS_TRANSPORT_MACHINE
) {
3534 static const char prefix
[] = " ";
3537 if (c
> sizeof(prefix
) - 1)
3538 c
-= sizeof(prefix
) - 1;
3542 if (i
->main_pid
> 0)
3543 extra
[k
++] = i
->main_pid
;
3545 if (i
->control_pid
> 0)
3546 extra
[k
++] = i
->control_pid
;
3548 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, prefix
, c
, false, extra
, k
, get_output_flags());
3552 if (i
->id
&& arg_transport
== BUS_TRANSPORT_LOCAL
) {
3553 show_journal_by_unit(
3558 i
->inactive_exit_timestamp_monotonic
,
3561 get_output_flags() | OUTPUT_BEGIN_NEWLINE
,
3562 SD_JOURNAL_LOCAL_ONLY
,
3563 arg_scope
== UNIT_FILE_SYSTEM
,
3567 if (i
->need_daemon_reload
)
3568 warn_unit_file_changed(i
->id
);
3571 static void show_unit_help(UnitStatusInfo
*i
) {
3576 if (!i
->documentation
) {
3577 log_info("Documentation for %s not known.", i
->id
);
3581 STRV_FOREACH(p
, i
->documentation
)
3582 if (startswith(*p
, "man:"))
3583 show_man_page(*p
+ 4, false);
3585 log_info("Can't show: %s", *p
);
3588 static int status_property(const char *name
, sd_bus_message
*m
, UnitStatusInfo
*i
, const char *contents
) {
3595 switch (contents
[0]) {
3597 case SD_BUS_TYPE_STRING
: {
3600 r
= sd_bus_message_read(m
, "s", &s
);
3602 return bus_log_parse_error(r
);
3605 if (streq(name
, "Id"))
3607 else if (streq(name
, "LoadState"))
3609 else if (streq(name
, "ActiveState"))
3610 i
->active_state
= s
;
3611 else if (streq(name
, "SubState"))
3613 else if (streq(name
, "Description"))
3615 else if (streq(name
, "FragmentPath"))
3616 i
->fragment_path
= s
;
3617 else if (streq(name
, "SourcePath"))
3620 else if (streq(name
, "DefaultControlGroup")) {
3622 e
= startswith(s
, SYSTEMD_CGROUP_CONTROLLER
":");
3624 i
->control_group
= e
;
3627 else if (streq(name
, "ControlGroup"))
3628 i
->control_group
= s
;
3629 else if (streq(name
, "StatusText"))
3631 else if (streq(name
, "PIDFile"))
3633 else if (streq(name
, "SysFSPath"))
3635 else if (streq(name
, "Where"))
3637 else if (streq(name
, "What"))
3639 else if (streq(name
, "Following"))
3641 else if (streq(name
, "UnitFileState"))
3642 i
->unit_file_state
= s
;
3643 else if (streq(name
, "UnitFilePreset"))
3644 i
->unit_file_preset
= s
;
3645 else if (streq(name
, "Result"))
3652 case SD_BUS_TYPE_BOOLEAN
: {
3655 r
= sd_bus_message_read(m
, "b", &b
);
3657 return bus_log_parse_error(r
);
3659 if (streq(name
, "Accept"))
3661 else if (streq(name
, "NeedDaemonReload"))
3662 i
->need_daemon_reload
= b
;
3663 else if (streq(name
, "ConditionResult"))
3664 i
->condition_result
= b
;
3665 else if (streq(name
, "AssertResult"))
3666 i
->assert_result
= b
;
3671 case SD_BUS_TYPE_UINT32
: {
3674 r
= sd_bus_message_read(m
, "u", &u
);
3676 return bus_log_parse_error(r
);
3678 if (streq(name
, "MainPID")) {
3680 i
->main_pid
= (pid_t
) u
;
3683 } else if (streq(name
, "ControlPID"))
3684 i
->control_pid
= (pid_t
) u
;
3685 else if (streq(name
, "ExecMainPID")) {
3687 i
->main_pid
= (pid_t
) u
;
3688 } else if (streq(name
, "NAccepted"))
3690 else if (streq(name
, "NConnections"))
3691 i
->n_connections
= u
;
3696 case SD_BUS_TYPE_INT32
: {
3699 r
= sd_bus_message_read(m
, "i", &j
);
3701 return bus_log_parse_error(r
);
3703 if (streq(name
, "ExecMainCode"))
3704 i
->exit_code
= (int) j
;
3705 else if (streq(name
, "ExecMainStatus"))
3706 i
->exit_status
= (int) j
;
3707 else if (streq(name
, "StatusErrno"))
3708 i
->status_errno
= (int) j
;
3713 case SD_BUS_TYPE_UINT64
: {
3716 r
= sd_bus_message_read(m
, "t", &u
);
3718 return bus_log_parse_error(r
);
3720 if (streq(name
, "ExecMainStartTimestamp"))
3721 i
->start_timestamp
= (usec_t
) u
;
3722 else if (streq(name
, "ExecMainExitTimestamp"))
3723 i
->exit_timestamp
= (usec_t
) u
;
3724 else if (streq(name
, "ActiveEnterTimestamp"))
3725 i
->active_enter_timestamp
= (usec_t
) u
;
3726 else if (streq(name
, "InactiveEnterTimestamp"))
3727 i
->inactive_enter_timestamp
= (usec_t
) u
;
3728 else if (streq(name
, "InactiveExitTimestamp"))
3729 i
->inactive_exit_timestamp
= (usec_t
) u
;
3730 else if (streq(name
, "InactiveExitTimestampMonotonic"))
3731 i
->inactive_exit_timestamp_monotonic
= (usec_t
) u
;
3732 else if (streq(name
, "ActiveExitTimestamp"))
3733 i
->active_exit_timestamp
= (usec_t
) u
;
3734 else if (streq(name
, "ConditionTimestamp"))
3735 i
->condition_timestamp
= (usec_t
) u
;
3736 else if (streq(name
, "AssertTimestamp"))
3737 i
->assert_timestamp
= (usec_t
) u
;
3738 else if (streq(name
, "MemoryCurrent"))
3739 i
->memory_current
= u
;
3740 else if (streq(name
, "MemoryLimit"))
3741 i
->memory_limit
= u
;
3742 else if (streq(name
, "CPUUsageNSec"))
3743 i
->cpu_usage_nsec
= u
;
3748 case SD_BUS_TYPE_ARRAY
:
3750 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
3751 _cleanup_free_ ExecStatusInfo
*info
= NULL
;
3753 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
3755 return bus_log_parse_error(r
);
3757 info
= new0(ExecStatusInfo
, 1);
3761 while ((r
= exec_status_info_deserialize(m
, info
)) > 0) {
3763 info
->name
= strdup(name
);
3767 LIST_PREPEND(exec
, i
->exec
, info
);
3769 info
= new0(ExecStatusInfo
, 1);
3775 return bus_log_parse_error(r
);
3777 r
= sd_bus_message_exit_container(m
);
3779 return bus_log_parse_error(r
);
3783 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
3784 const char *type
, *path
;
3786 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
3788 return bus_log_parse_error(r
);
3790 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0) {
3792 r
= strv_extend(&i
->listen
, type
);
3796 r
= strv_extend(&i
->listen
, path
);
3801 return bus_log_parse_error(r
);
3803 r
= sd_bus_message_exit_container(m
);
3805 return bus_log_parse_error(r
);
3809 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "DropInPaths")) {
3811 r
= sd_bus_message_read_strv(m
, &i
->dropin_paths
);
3813 return bus_log_parse_error(r
);
3815 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Documentation")) {
3817 r
= sd_bus_message_read_strv(m
, &i
->documentation
);
3819 return bus_log_parse_error(r
);
3821 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Conditions")) {
3822 const char *cond
, *param
;
3823 int trigger
, negate
;
3826 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
3828 return bus_log_parse_error(r
);
3830 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
3831 log_debug("%s %d %d %s %d", cond
, trigger
, negate
, param
, state
);
3832 if (state
< 0 && (!trigger
|| !i
->failed_condition
)) {
3833 i
->failed_condition
= cond
;
3834 i
->failed_condition_trigger
= trigger
;
3835 i
->failed_condition_negate
= negate
;
3836 i
->failed_condition_parameter
= param
;
3840 return bus_log_parse_error(r
);
3842 r
= sd_bus_message_exit_container(m
);
3844 return bus_log_parse_error(r
);
3846 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Asserts")) {
3847 const char *cond
, *param
;
3848 int trigger
, negate
;
3851 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
3853 return bus_log_parse_error(r
);
3855 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
3856 log_debug("%s %d %d %s %d", cond
, trigger
, negate
, param
, state
);
3857 if (state
< 0 && (!trigger
|| !i
->failed_assert
)) {
3858 i
->failed_assert
= cond
;
3859 i
->failed_assert_trigger
= trigger
;
3860 i
->failed_assert_negate
= negate
;
3861 i
->failed_assert_parameter
= param
;
3865 return bus_log_parse_error(r
);
3867 r
= sd_bus_message_exit_container(m
);
3869 return bus_log_parse_error(r
);
3876 case SD_BUS_TYPE_STRUCT_BEGIN
:
3878 if (streq(name
, "LoadError")) {
3879 const char *n
, *message
;
3881 r
= sd_bus_message_read(m
, "(ss)", &n
, &message
);
3883 return bus_log_parse_error(r
);
3885 if (!isempty(message
))
3886 i
->load_error
= message
;
3899 r
= sd_bus_message_skip(m
, contents
);
3901 return bus_log_parse_error(r
);
3906 static int print_property(const char *name
, sd_bus_message
*m
, const char *contents
) {
3912 /* This is a low-level property printer, see
3913 * print_status_info() for the nicer output */
3915 if (arg_properties
&& !strv_find(arg_properties
, name
)) {
3916 /* skip what we didn't read */
3917 r
= sd_bus_message_skip(m
, contents
);
3921 switch (contents
[0]) {
3923 case SD_BUS_TYPE_STRUCT_BEGIN
:
3925 if (contents
[1] == SD_BUS_TYPE_UINT32
&& streq(name
, "Job")) {
3928 r
= sd_bus_message_read(m
, "(uo)", &u
, NULL
);
3930 return bus_log_parse_error(r
);
3933 printf("%s=%"PRIu32
"\n", name
, u
);
3935 printf("%s=\n", name
);
3939 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Unit")) {
3942 r
= sd_bus_message_read(m
, "(so)", &s
, NULL
);
3944 return bus_log_parse_error(r
);
3946 if (arg_all
|| !isempty(s
))
3947 printf("%s=%s\n", name
, s
);
3951 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "LoadError")) {
3952 const char *a
= NULL
, *b
= NULL
;
3954 r
= sd_bus_message_read(m
, "(ss)", &a
, &b
);
3956 return bus_log_parse_error(r
);
3958 if (arg_all
|| !isempty(a
) || !isempty(b
))
3959 printf("%s=%s \"%s\"\n", name
, strempty(a
), strempty(b
));
3962 } else if (streq_ptr(name
, "SystemCallFilter")) {
3963 _cleanup_strv_free_
char **l
= NULL
;
3966 r
= sd_bus_message_enter_container(m
, 'r', "bas");
3968 return bus_log_parse_error(r
);
3970 r
= sd_bus_message_read(m
, "b", &whitelist
);
3972 return bus_log_parse_error(r
);
3974 r
= sd_bus_message_read_strv(m
, &l
);
3976 return bus_log_parse_error(r
);
3978 r
= sd_bus_message_exit_container(m
);
3980 return bus_log_parse_error(r
);
3982 if (arg_all
|| whitelist
|| !strv_isempty(l
)) {
3986 fputs(name
, stdout
);
3992 STRV_FOREACH(i
, l
) {
4000 fputc('\n', stdout
);
4008 case SD_BUS_TYPE_ARRAY
:
4010 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "EnvironmentFiles")) {
4014 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sb)");
4016 return bus_log_parse_error(r
);
4018 while ((r
= sd_bus_message_read(m
, "(sb)", &path
, &ignore
)) > 0)
4019 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path
, yes_no(ignore
));
4022 return bus_log_parse_error(r
);
4024 r
= sd_bus_message_exit_container(m
);
4026 return bus_log_parse_error(r
);
4030 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Paths")) {
4031 const char *type
, *path
;
4033 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4035 return bus_log_parse_error(r
);
4037 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4038 printf("%s=%s\n", type
, path
);
4040 return bus_log_parse_error(r
);
4042 r
= sd_bus_message_exit_container(m
);
4044 return bus_log_parse_error(r
);
4048 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
4049 const char *type
, *path
;
4051 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4053 return bus_log_parse_error(r
);
4055 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4056 printf("Listen%s=%s\n", type
, path
);
4058 return bus_log_parse_error(r
);
4060 r
= sd_bus_message_exit_container(m
);
4062 return bus_log_parse_error(r
);
4066 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Timers")) {
4068 uint64_t value
, next_elapse
;
4070 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(stt)");
4072 return bus_log_parse_error(r
);
4074 while ((r
= sd_bus_message_read(m
, "(stt)", &base
, &value
, &next_elapse
)) > 0) {
4075 char timespan1
[FORMAT_TIMESPAN_MAX
], timespan2
[FORMAT_TIMESPAN_MAX
];
4077 printf("%s={ value=%s ; next_elapse=%s }\n",
4079 format_timespan(timespan1
, sizeof(timespan1
), value
, 0),
4080 format_timespan(timespan2
, sizeof(timespan2
), next_elapse
, 0));
4083 return bus_log_parse_error(r
);
4085 r
= sd_bus_message_exit_container(m
);
4087 return bus_log_parse_error(r
);
4091 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
4092 ExecStatusInfo info
= {};
4094 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4096 return bus_log_parse_error(r
);
4098 while ((r
= exec_status_info_deserialize(m
, &info
)) > 0) {
4099 char timestamp1
[FORMAT_TIMESTAMP_MAX
], timestamp2
[FORMAT_TIMESTAMP_MAX
];
4100 _cleanup_free_
char *tt
;
4102 tt
= strv_join(info
.argv
, " ");
4104 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT
" ; code=%s ; status=%i%s%s }\n",
4108 yes_no(info
.ignore
),
4109 strna(format_timestamp(timestamp1
, sizeof(timestamp1
), info
.start_timestamp
)),
4110 strna(format_timestamp(timestamp2
, sizeof(timestamp2
), info
.exit_timestamp
)),
4112 sigchld_code_to_string(info
.code
),
4114 info
.code
== CLD_EXITED
? "" : "/",
4115 strempty(info
.code
== CLD_EXITED
? NULL
: signal_to_string(info
.status
)));
4118 strv_free(info
.argv
);
4122 r
= sd_bus_message_exit_container(m
);
4124 return bus_log_parse_error(r
);
4128 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "DeviceAllow")) {
4129 const char *path
, *rwm
;
4131 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4133 return bus_log_parse_error(r
);
4135 while ((r
= sd_bus_message_read(m
, "(ss)", &path
, &rwm
)) > 0)
4136 printf("%s=%s %s\n", name
, strna(path
), strna(rwm
));
4138 return bus_log_parse_error(r
);
4140 r
= sd_bus_message_exit_container(m
);
4142 return bus_log_parse_error(r
);
4146 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "BlockIODeviceWeight")) {
4150 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4152 return bus_log_parse_error(r
);
4154 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &weight
)) > 0)
4155 printf("%s=%s %" PRIu64
"\n", name
, strna(path
), weight
);
4157 return bus_log_parse_error(r
);
4159 r
= sd_bus_message_exit_container(m
);
4161 return bus_log_parse_error(r
);
4165 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& (streq(name
, "BlockIOReadBandwidth") || streq(name
, "BlockIOWriteBandwidth"))) {
4169 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4171 return bus_log_parse_error(r
);
4173 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &bandwidth
)) > 0)
4174 printf("%s=%s %" PRIu64
"\n", name
, strna(path
), bandwidth
);
4176 return bus_log_parse_error(r
);
4178 r
= sd_bus_message_exit_container(m
);
4180 return bus_log_parse_error(r
);
4188 r
= bus_print_property(name
, m
, arg_all
);
4190 return bus_log_parse_error(r
);
4193 r
= sd_bus_message_skip(m
, contents
);
4195 return bus_log_parse_error(r
);
4198 printf("%s=[unprintable]\n", name
);
4204 static int show_one(
4208 bool show_properties
,
4212 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4213 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4214 UnitStatusInfo info
= {
4215 .memory_current
= (uint64_t) -1,
4216 .memory_limit
= (uint64_t) -1,
4217 .cpu_usage_nsec
= (uint64_t) -1,
4225 log_debug("Showing one %s", path
);
4227 r
= sd_bus_call_method(
4229 "org.freedesktop.systemd1",
4231 "org.freedesktop.DBus.Properties",
4237 log_error("Failed to get properties: %s", bus_error_message(&error
, r
));
4241 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
4243 return bus_log_parse_error(r
);
4250 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
4251 const char *name
, *contents
;
4253 r
= sd_bus_message_read(reply
, "s", &name
);
4255 return bus_log_parse_error(r
);
4257 r
= sd_bus_message_peek_type(reply
, NULL
, &contents
);
4259 return bus_log_parse_error(r
);
4261 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, contents
);
4263 return bus_log_parse_error(r
);
4265 if (show_properties
)
4266 r
= print_property(name
, reply
, contents
);
4268 r
= status_property(name
, reply
, &info
, contents
);
4272 r
= sd_bus_message_exit_container(reply
);
4274 return bus_log_parse_error(r
);
4276 r
= sd_bus_message_exit_container(reply
);
4278 return bus_log_parse_error(r
);
4281 return bus_log_parse_error(r
);
4283 r
= sd_bus_message_exit_container(reply
);
4285 return bus_log_parse_error(r
);
4289 if (!show_properties
) {
4290 if (streq(verb
, "help"))
4291 show_unit_help(&info
);
4293 print_status_info(&info
, ellipsized
);
4296 strv_free(info
.documentation
);
4297 strv_free(info
.dropin_paths
);
4298 strv_free(info
.listen
);
4300 if (!streq_ptr(info
.active_state
, "active") &&
4301 !streq_ptr(info
.active_state
, "reloading") &&
4302 streq(verb
, "status")) {
4303 /* According to LSB: "program not running" */
4304 /* 0: program is running or service is OK
4305 * 1: program is dead and /run PID file exists
4306 * 2: program is dead and /run/lock lock file exists
4307 * 3: program is not running
4308 * 4: program or service status is unknown
4310 if (info
.pid_file
&& access(info
.pid_file
, F_OK
) == 0)
4316 while ((p
= info
.exec
)) {
4317 LIST_REMOVE(exec
, info
.exec
, p
);
4318 exec_status_info_free(p
);
4324 static int get_unit_dbus_path_by_pid(
4329 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4330 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4334 r
= sd_bus_call_method(
4336 "org.freedesktop.systemd1",
4337 "/org/freedesktop/systemd1",
4338 "org.freedesktop.systemd1.Manager",
4344 log_error("Failed to get unit for PID %"PRIu32
": %s", pid
, bus_error_message(&error
, r
));
4348 r
= sd_bus_message_read(reply
, "o", &u
);
4350 return bus_log_parse_error(r
);
4360 static int show_all(
4363 bool show_properties
,
4367 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4368 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
4373 r
= get_unit_list(bus
, NULL
, NULL
, &unit_infos
, 0, &reply
);
4377 pager_open_if_enabled();
4381 qsort_safe(unit_infos
, c
, sizeof(UnitInfo
), compare_unit_info
);
4383 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
4384 _cleanup_free_
char *p
= NULL
;
4386 p
= unit_dbus_path_from_name(u
->id
);
4390 r
= show_one(verb
, bus
, p
, show_properties
, new_line
, ellipsized
);
4393 else if (r
> 0 && ret
== 0)
4400 static int show_system_status(sd_bus
*bus
) {
4401 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], since2
[FORMAT_TIMESTAMP_MAX
];
4402 _cleanup_free_
char *hn
= NULL
;
4403 struct machine_info mi
= {};
4404 const char *on
, *off
;
4407 hn
= gethostname_malloc();
4411 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, &mi
);
4413 return log_error_errno(r
, "Failed to read server status: %m");
4415 if (streq_ptr(mi
.state
, "degraded")) {
4416 on
= ansi_highlight_red();
4417 off
= ansi_highlight_off();
4418 } else if (!streq_ptr(mi
.state
, "running")) {
4419 on
= ansi_highlight_yellow();
4420 off
= ansi_highlight_off();
4424 printf("%s%s%s %s\n", on
, draw_special_char(DRAW_BLACK_CIRCLE
), off
, arg_host
? arg_host
: hn
);
4426 printf(" State: %s%s%s\n",
4427 on
, strna(mi
.state
), off
);
4429 printf(" Jobs: %u queued\n", mi
.n_jobs
);
4430 printf(" Failed: %u units\n", mi
.n_failed_units
);
4432 printf(" Since: %s; %s\n",
4433 format_timestamp(since2
, sizeof(since2
), mi
.timestamp
),
4434 format_timestamp_relative(since1
, sizeof(since1
), mi
.timestamp
));
4436 printf(" CGroup: %s\n", mi
.control_group
?: "/");
4437 if (arg_transport
== BUS_TRANSPORT_LOCAL
|| arg_transport
== BUS_TRANSPORT_MACHINE
) {
4438 static const char prefix
[] = " ";
4442 if (c
> sizeof(prefix
) - 1)
4443 c
-= sizeof(prefix
) - 1;
4447 show_cgroup(SYSTEMD_CGROUP_CONTROLLER
, strempty(mi
.control_group
), prefix
, c
, false, get_output_flags());
4451 free(mi
.control_group
);
4456 static int show(sd_bus
*bus
, char **args
) {
4457 bool show_properties
, show_status
, new_line
= false;
4458 bool ellipsized
= false;
4464 show_properties
= streq(args
[0], "show");
4465 show_status
= streq(args
[0], "status");
4467 if (show_properties
)
4468 pager_open_if_enabled();
4471 /* Increase max number of open files to 16K if we can, we
4472 * might needs this when browsing journal files, which might
4473 * be split up into many files. */
4474 setrlimit_closest(RLIMIT_NOFILE
, &RLIMIT_MAKE_CONST(16384));
4476 /* If no argument is specified inspect the manager itself */
4478 if (show_properties
&& strv_length(args
) <= 1)
4479 return show_one(args
[0], bus
, "/org/freedesktop/systemd1", show_properties
, &new_line
, &ellipsized
);
4481 if (show_status
&& strv_length(args
) <= 1) {
4483 pager_open_if_enabled();
4484 show_system_status(bus
);
4488 ret
= show_all(args
[0], bus
, false, &new_line
, &ellipsized
);
4490 _cleanup_free_
char **patterns
= NULL
;
4493 STRV_FOREACH(name
, args
+ 1) {
4494 _cleanup_free_
char *unit
= NULL
;
4497 if (safe_atou32(*name
, &id
) < 0) {
4498 if (strv_push(&patterns
, *name
) < 0)
4502 } else if (show_properties
) {
4503 /* Interpret as job id */
4504 if (asprintf(&unit
, "/org/freedesktop/systemd1/job/%u", id
) < 0)
4508 /* Interpret as PID */
4509 r
= get_unit_dbus_path_by_pid(bus
, id
, &unit
);
4516 r
= show_one(args
[0], bus
, unit
, show_properties
,
4517 &new_line
, &ellipsized
);
4520 else if (r
> 0 && ret
== 0)
4524 if (!strv_isempty(patterns
)) {
4525 _cleanup_strv_free_
char **names
= NULL
;
4527 r
= expand_names(bus
, patterns
, NULL
, &names
);
4529 log_error_errno(r
, "Failed to expand names: %m");
4531 STRV_FOREACH(name
, names
) {
4532 _cleanup_free_
char *unit
;
4534 unit
= unit_dbus_path_from_name(*name
);
4538 r
= show_one(args
[0], bus
, unit
, show_properties
,
4539 &new_line
, &ellipsized
);
4542 else if (r
> 0 && ret
== 0)
4548 if (ellipsized
&& !arg_quiet
)
4549 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4554 static int init_home_and_lookup_paths(char **user_home
, char **user_runtime
, LookupPaths
*lp
) {
4558 assert(user_runtime
);
4561 if (arg_scope
== UNIT_FILE_USER
) {
4562 r
= user_config_home(user_home
);
4564 return log_error_errno(r
, "Failed to query XDG_CONFIG_HOME: %m");
4566 return log_error_errno(ENOTDIR
, "Cannot find units: $XDG_CONFIG_HOME and $HOME are not set.");
4568 r
= user_runtime_dir(user_runtime
);
4570 return log_error_errno(r
, "Failed to query XDG_CONFIG_HOME: %m");
4572 return log_error_errno(ENOTDIR
, "Cannot find units: $XDG_RUNTIME_DIR is not set.");
4575 r
= lookup_paths_init_from_scope(lp
, arg_scope
, arg_root
);
4577 return log_error_errno(r
, "Failed to query unit lookup paths: %m");
4582 static int cat_file(const char *filename
, bool newline
) {
4583 _cleanup_close_
int fd
;
4585 fd
= open(filename
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
4589 printf("%s%s# %s%s\n",
4590 newline
? "\n" : "",
4591 ansi_highlight_blue(),
4593 ansi_highlight_off());
4596 return copy_bytes(fd
, STDOUT_FILENO
, (off_t
) -1, false);
4599 static int cat(sd_bus
*bus
, char **args
) {
4600 _cleanup_free_
char *user_home
= NULL
;
4601 _cleanup_free_
char *user_runtime
= NULL
;
4602 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
4603 _cleanup_strv_free_
char **names
= NULL
;
4605 bool first
= true, avoid_bus_cache
;
4610 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
4611 log_error("Cannot remotely cat units");
4615 r
= init_home_and_lookup_paths(&user_home
, &user_runtime
, &lp
);
4619 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
4621 return log_error_errno(r
, "Failed to expand names: %m");
4623 avoid_bus_cache
= !bus
|| avoid_bus();
4625 pager_open_if_enabled();
4627 STRV_FOREACH(name
, names
) {
4628 _cleanup_free_
char *fragment_path
= NULL
;
4629 _cleanup_strv_free_
char **dropin_paths
= NULL
;
4632 r
= unit_find_paths(bus
, *name
, avoid_bus_cache
, &lp
, &fragment_path
, &dropin_paths
);
4643 if (fragment_path
) {
4644 r
= cat_file(fragment_path
, false);
4646 return log_warning_errno(r
, "Failed to cat %s: %m", fragment_path
);
4649 STRV_FOREACH(path
, dropin_paths
) {
4650 r
= cat_file(*path
, path
== dropin_paths
);
4652 return log_warning_errno(r
, "Failed to cat %s: %m", *path
);
4659 static int set_property(sd_bus
*bus
, char **args
) {
4660 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
4661 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4662 _cleanup_free_
char *n
= NULL
;
4666 polkit_agent_open_if_enabled();
4668 r
= sd_bus_message_new_method_call(
4671 "org.freedesktop.systemd1",
4672 "/org/freedesktop/systemd1",
4673 "org.freedesktop.systemd1.Manager",
4674 "SetUnitProperties");
4676 return bus_log_create_error(r
);
4678 r
= unit_name_mangle(args
[1], UNIT_NAME_NOGLOB
, &n
);
4680 return log_error_errno(r
, "Failed to mangle unit name: %m");
4682 r
= sd_bus_message_append(m
, "sb", n
, arg_runtime
);
4684 return bus_log_create_error(r
);
4686 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, "(sv)");
4688 return bus_log_create_error(r
);
4690 STRV_FOREACH(i
, args
+ 2) {
4691 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_STRUCT
, "sv");
4693 return bus_log_create_error(r
);
4695 r
= bus_append_unit_property_assignment(m
, *i
);
4699 r
= sd_bus_message_close_container(m
);
4701 return bus_log_create_error(r
);
4704 r
= sd_bus_message_close_container(m
);
4706 return bus_log_create_error(r
);
4708 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
4710 log_error("Failed to set unit properties on %s: %s", n
, bus_error_message(&error
, r
));
4717 static int snapshot(sd_bus
*bus
, char **args
) {
4718 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4719 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4720 _cleanup_free_
char *n
= NULL
, *id
= NULL
;
4724 polkit_agent_open_if_enabled();
4726 if (strv_length(args
) > 1) {
4727 r
= unit_name_mangle_with_suffix(args
[1], UNIT_NAME_NOGLOB
, ".snapshot", &n
);
4729 return log_error_errno(r
, "Failed to generate unit name: %m");
4736 r
= sd_bus_call_method(
4738 "org.freedesktop.systemd1",
4739 "/org/freedesktop/systemd1",
4740 "org.freedesktop.systemd1.Manager",
4746 log_error("Failed to create snapshot: %s", bus_error_message(&error
, r
));
4750 r
= sd_bus_message_read(reply
, "o", &path
);
4752 return bus_log_parse_error(r
);
4754 r
= sd_bus_get_property_string(
4756 "org.freedesktop.systemd1",
4758 "org.freedesktop.systemd1.Unit",
4763 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error
, r
));
4773 static int delete_snapshot(sd_bus
*bus
, char **args
) {
4774 _cleanup_strv_free_
char **names
= NULL
;
4780 polkit_agent_open_if_enabled();
4782 r
= expand_names(bus
, args
+ 1, ".snapshot", &names
);
4784 log_error_errno(r
, "Failed to expand names: %m");
4786 STRV_FOREACH(name
, names
) {
4787 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4790 q
= sd_bus_call_method(
4792 "org.freedesktop.systemd1",
4793 "/org/freedesktop/systemd1",
4794 "org.freedesktop.systemd1.Manager",
4800 log_error("Failed to remove snapshot %s: %s", *name
, bus_error_message(&error
, q
));
4809 static int daemon_reload(sd_bus
*bus
, char **args
) {
4810 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4814 polkit_agent_open_if_enabled();
4816 if (arg_action
== ACTION_RELOAD
)
4818 else if (arg_action
== ACTION_REEXEC
)
4819 method
= "Reexecute";
4821 assert(arg_action
== ACTION_SYSTEMCTL
);
4824 streq(args
[0], "clear-jobs") ||
4825 streq(args
[0], "cancel") ? "ClearJobs" :
4826 streq(args
[0], "daemon-reexec") ? "Reexecute" :
4827 streq(args
[0], "reset-failed") ? "ResetFailed" :
4828 streq(args
[0], "halt") ? "Halt" :
4829 streq(args
[0], "poweroff") ? "PowerOff" :
4830 streq(args
[0], "reboot") ? "Reboot" :
4831 streq(args
[0], "kexec") ? "KExec" :
4832 streq(args
[0], "exit") ? "Exit" :
4833 /* "daemon-reload" */ "Reload";
4836 r
= sd_bus_call_method(
4838 "org.freedesktop.systemd1",
4839 "/org/freedesktop/systemd1",
4840 "org.freedesktop.systemd1.Manager",
4845 if (r
== -ENOENT
&& arg_action
!= ACTION_SYSTEMCTL
)
4846 /* There's always a fallback possible for
4847 * legacy actions. */
4849 else if ((r
== -ETIMEDOUT
|| r
== -ECONNRESET
) && streq(method
, "Reexecute"))
4850 /* On reexecution, we expect a disconnect, not a
4854 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
4856 return r
< 0 ? r
: 0;
4859 static int reset_failed(sd_bus
*bus
, char **args
) {
4860 _cleanup_strv_free_
char **names
= NULL
;
4864 if (strv_length(args
) <= 1)
4865 return daemon_reload(bus
, args
);
4867 polkit_agent_open_if_enabled();
4869 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
4871 log_error_errno(r
, "Failed to expand names: %m");
4873 STRV_FOREACH(name
, names
) {
4874 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4876 q
= sd_bus_call_method(
4878 "org.freedesktop.systemd1",
4879 "/org/freedesktop/systemd1",
4880 "org.freedesktop.systemd1.Manager",
4886 log_error("Failed to reset failed state of unit %s: %s", *name
, bus_error_message(&error
, q
));
4895 static int show_environment(sd_bus
*bus
, char **args
) {
4896 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4897 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4901 pager_open_if_enabled();
4903 r
= sd_bus_get_property(
4905 "org.freedesktop.systemd1",
4906 "/org/freedesktop/systemd1",
4907 "org.freedesktop.systemd1.Manager",
4913 log_error("Failed to get environment: %s", bus_error_message(&error
, r
));
4917 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
4919 return bus_log_parse_error(r
);
4921 while ((r
= sd_bus_message_read_basic(reply
, SD_BUS_TYPE_STRING
, &text
)) > 0)
4924 return bus_log_parse_error(r
);
4926 r
= sd_bus_message_exit_container(reply
);
4928 return bus_log_parse_error(r
);
4933 static int switch_root(sd_bus
*bus
, char **args
) {
4934 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4935 _cleanup_free_
char *cmdline_init
= NULL
;
4936 const char *root
, *init
;
4940 l
= strv_length(args
);
4941 if (l
< 2 || l
> 3) {
4942 log_error("Wrong number of arguments.");
4951 r
= parse_env_file("/proc/cmdline", WHITESPACE
,
4952 "init", &cmdline_init
,
4955 log_debug_errno(r
, "Failed to parse /proc/cmdline: %m");
4957 init
= cmdline_init
;
4964 const char *root_systemd_path
= NULL
, *root_init_path
= NULL
;
4966 root_systemd_path
= strjoina(root
, "/" SYSTEMD_BINARY_PATH
);
4967 root_init_path
= strjoina(root
, "/", init
);
4969 /* If the passed init is actually the same as the
4970 * systemd binary, then let's suppress it. */
4971 if (files_same(root_init_path
, root_systemd_path
) > 0)
4975 log_debug("Switching root - root: %s; init: %s", root
, strna(init
));
4977 r
= sd_bus_call_method(
4979 "org.freedesktop.systemd1",
4980 "/org/freedesktop/systemd1",
4981 "org.freedesktop.systemd1.Manager",
4987 log_error("Failed to switch root: %s", bus_error_message(&error
, r
));
4994 static int set_environment(sd_bus
*bus
, char **args
) {
4995 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4996 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
5003 polkit_agent_open_if_enabled();
5005 method
= streq(args
[0], "set-environment")
5007 : "UnsetEnvironment";
5009 r
= sd_bus_message_new_method_call(
5012 "org.freedesktop.systemd1",
5013 "/org/freedesktop/systemd1",
5014 "org.freedesktop.systemd1.Manager",
5017 return bus_log_create_error(r
);
5019 r
= sd_bus_message_append_strv(m
, args
+ 1);
5021 return bus_log_create_error(r
);
5023 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5025 log_error("Failed to set environment: %s", bus_error_message(&error
, r
));
5032 static int import_environment(sd_bus
*bus
, char **args
) {
5033 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5034 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
5040 polkit_agent_open_if_enabled();
5042 r
= sd_bus_message_new_method_call(
5045 "org.freedesktop.systemd1",
5046 "/org/freedesktop/systemd1",
5047 "org.freedesktop.systemd1.Manager",
5050 return bus_log_create_error(r
);
5052 if (strv_isempty(args
+ 1))
5053 r
= sd_bus_message_append_strv(m
, environ
);
5057 r
= sd_bus_message_open_container(m
, 'a', "s");
5059 return bus_log_create_error(r
);
5061 STRV_FOREACH(a
, args
+ 1) {
5063 if (!env_name_is_valid(*a
)) {
5064 log_error("Not a valid environment variable name: %s", *a
);
5068 STRV_FOREACH(b
, environ
) {
5071 eq
= startswith(*b
, *a
);
5072 if (eq
&& *eq
== '=') {
5074 r
= sd_bus_message_append(m
, "s", *b
);
5076 return bus_log_create_error(r
);
5083 r
= sd_bus_message_close_container(m
);
5086 return bus_log_create_error(r
);
5088 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5090 log_error("Failed to import environment: %s", bus_error_message(&error
, r
));
5097 static int enable_sysv_units(const char *verb
, char **args
) {
5100 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
5102 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
5104 if (arg_scope
!= UNIT_FILE_SYSTEM
)
5107 if (!streq(verb
, "enable") &&
5108 !streq(verb
, "disable") &&
5109 !streq(verb
, "is-enabled"))
5112 /* Processes all SysV units, and reshuffles the array so that
5113 * afterwards only the native units remain */
5115 r
= lookup_paths_init(&paths
, MANAGER_SYSTEM
, false, arg_root
, NULL
, NULL
, NULL
);
5122 _cleanup_free_
char *p
= NULL
, *q
= NULL
, *l
= NULL
;
5123 bool found_native
= false, found_sysv
;
5125 const char *argv
[6] = { "/sbin/chkconfig", NULL
, NULL
, NULL
, NULL
};
5133 if (!endswith(name
, ".service"))
5136 if (path_is_absolute(name
))
5139 STRV_FOREACH(k
, paths
.unit_path
) {
5140 _cleanup_free_
char *path
= NULL
;
5142 path
= path_join(arg_root
, *k
, name
);
5146 found_native
= access(path
, F_OK
) >= 0;
5154 p
= path_join(arg_root
, SYSTEM_SYSVINIT_PATH
, name
);
5158 p
[strlen(p
) - strlen(".service")] = 0;
5159 found_sysv
= access(p
, F_OK
) >= 0;
5163 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name
);
5165 if (!isempty(arg_root
))
5166 argv
[c
++] = q
= strappend("--root=", arg_root
);
5168 argv
[c
++] = basename(p
);
5170 streq(verb
, "enable") ? "on" :
5171 streq(verb
, "disable") ? "off" : "--level=5";
5174 l
= strv_join((char**)argv
, " ");
5178 log_info("Executing %s", l
);
5182 return log_error_errno(errno
, "Failed to fork: %m");
5183 else if (pid
== 0) {
5186 execv(argv
[0], (char**) argv
);
5187 _exit(EXIT_FAILURE
);
5190 j
= wait_for_terminate(pid
, &status
);
5192 log_error_errno(r
, "Failed to wait for child: %m");
5196 if (status
.si_code
== CLD_EXITED
) {
5197 if (streq(verb
, "is-enabled")) {
5198 if (status
.si_status
== 0) {
5207 } else if (status
.si_status
!= 0)
5212 /* Remove this entry, so that we don't try enabling it as native unit */
5215 assert(args
[f
] == name
);
5216 strv_remove(args
, name
);
5223 static int mangle_names(char **original_names
, char ***mangled_names
) {
5224 char **i
, **l
, **name
;
5227 l
= i
= new(char*, strv_length(original_names
) + 1);
5231 STRV_FOREACH(name
, original_names
) {
5233 /* When enabling units qualified path names are OK,
5234 * too, hence allow them explicitly. */
5236 if (is_path(*name
)) {
5243 r
= unit_name_mangle(*name
, UNIT_NAME_NOGLOB
, i
);
5246 return log_error_errno(r
, "Failed to mangle unit name: %m");
5259 static int enable_unit(sd_bus
*bus
, char **args
) {
5260 _cleanup_strv_free_
char **names
= NULL
;
5261 const char *verb
= args
[0];
5262 UnitFileChange
*changes
= NULL
;
5263 unsigned n_changes
= 0;
5264 int carries_install_info
= -1;
5270 r
= mangle_names(args
+1, &names
);
5274 r
= enable_sysv_units(verb
, names
);
5278 /* If the operation was fully executed by the SysV compat,
5279 * let's finish early */
5280 if (strv_isempty(names
))
5283 if (!bus
|| avoid_bus()) {
5284 if (streq(verb
, "enable")) {
5285 r
= unit_file_enable(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5286 carries_install_info
= r
;
5287 } else if (streq(verb
, "disable"))
5288 r
= unit_file_disable(arg_scope
, arg_runtime
, arg_root
, names
, &changes
, &n_changes
);
5289 else if (streq(verb
, "reenable")) {
5290 r
= unit_file_reenable(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5291 carries_install_info
= r
;
5292 } else if (streq(verb
, "link"))
5293 r
= unit_file_link(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5294 else if (streq(verb
, "preset")) {
5295 r
= unit_file_preset(arg_scope
, arg_runtime
, arg_root
, names
, arg_preset_mode
, arg_force
, &changes
, &n_changes
);
5296 carries_install_info
= r
;
5297 } else if (streq(verb
, "mask"))
5298 r
= unit_file_mask(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5299 else if (streq(verb
, "unmask"))
5300 r
= unit_file_unmask(arg_scope
, arg_runtime
, arg_root
, names
, &changes
, &n_changes
);
5302 assert_not_reached("Unknown verb");
5305 log_error_errno(r
, "Operation failed: %m");
5310 dump_unit_file_changes(changes
, n_changes
);
5314 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
, *m
= NULL
;
5315 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5316 int expect_carries_install_info
= false;
5317 bool send_force
= true, send_preset_mode
= false;
5320 polkit_agent_open_if_enabled();
5322 if (streq(verb
, "enable")) {
5323 method
= "EnableUnitFiles";
5324 expect_carries_install_info
= true;
5325 } else if (streq(verb
, "disable")) {
5326 method
= "DisableUnitFiles";
5328 } else if (streq(verb
, "reenable")) {
5329 method
= "ReenableUnitFiles";
5330 expect_carries_install_info
= true;
5331 } else if (streq(verb
, "link"))
5332 method
= "LinkUnitFiles";
5333 else if (streq(verb
, "preset")) {
5335 if (arg_preset_mode
!= UNIT_FILE_PRESET_FULL
) {
5336 method
= "PresetUnitFilesWithMode";
5337 send_preset_mode
= true;
5339 method
= "PresetUnitFiles";
5341 expect_carries_install_info
= true;
5342 } else if (streq(verb
, "mask"))
5343 method
= "MaskUnitFiles";
5344 else if (streq(verb
, "unmask")) {
5345 method
= "UnmaskUnitFiles";
5348 assert_not_reached("Unknown verb");
5350 r
= sd_bus_message_new_method_call(
5353 "org.freedesktop.systemd1",
5354 "/org/freedesktop/systemd1",
5355 "org.freedesktop.systemd1.Manager",
5358 return bus_log_create_error(r
);
5360 r
= sd_bus_message_append_strv(m
, names
);
5362 return bus_log_create_error(r
);
5364 if (send_preset_mode
) {
5365 r
= sd_bus_message_append(m
, "s", unit_file_preset_mode_to_string(arg_preset_mode
));
5367 return bus_log_create_error(r
);
5370 r
= sd_bus_message_append(m
, "b", arg_runtime
);
5372 return bus_log_create_error(r
);
5375 r
= sd_bus_message_append(m
, "b", arg_force
);
5377 return bus_log_create_error(r
);
5380 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
5382 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
5386 if (expect_carries_install_info
) {
5387 r
= sd_bus_message_read(reply
, "b", &carries_install_info
);
5389 return bus_log_parse_error(r
);
5392 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
5396 /* Try to reload if enabled */
5398 r
= daemon_reload(bus
, args
);
5403 if (carries_install_info
== 0)
5404 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5405 "using systemctl.\n"
5406 "Possible reasons for having this kind of units are:\n"
5407 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5408 " .wants/ or .requires/ directory.\n"
5409 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5410 " a requirement dependency on it.\n"
5411 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5412 " D-Bus, udev, scripted systemctl call, ...).\n");
5414 if (arg_now
&& n_changes
> 0 && STR_IN_SET(args
[0], "enable", "disable", "mask")) {
5415 char *new_args
[n_changes
+ 2];
5418 new_args
[0] = streq(args
[0], "enable") ? (char *)"start" : (char *)"stop";
5419 for (i
= 0; i
< n_changes
; i
++)
5420 new_args
[i
+ 1] = basename(changes
[i
].path
);
5421 new_args
[i
+ 1] = NULL
;
5423 r
= start_unit(bus
, new_args
);
5427 unit_file_changes_free(changes
, n_changes
);
5432 static int add_dependency(sd_bus
*bus
, char **args
) {
5433 _cleanup_strv_free_
char **names
= NULL
;
5434 _cleanup_free_
char *target
= NULL
;
5435 const char *verb
= args
[0];
5442 r
= unit_name_mangle_with_suffix(args
[1], UNIT_NAME_NOGLOB
, ".target", &target
);
5444 return log_error_errno(r
, "Failed to mangle unit name: %m");
5446 r
= mangle_names(args
+2, &names
);
5450 if (streq(verb
, "add-wants"))
5452 else if (streq(verb
, "add-requires"))
5453 dep
= UNIT_REQUIRES
;
5455 assert_not_reached("Unknown verb");
5457 if (!bus
|| avoid_bus()) {
5458 UnitFileChange
*changes
= NULL
;
5459 unsigned n_changes
= 0;
5461 r
= unit_file_add_dependency(arg_scope
, arg_runtime
, arg_root
, names
, target
, dep
, arg_force
, &changes
, &n_changes
);
5464 return log_error_errno(r
, "Can't add dependency: %m");
5467 dump_unit_file_changes(changes
, n_changes
);
5469 unit_file_changes_free(changes
, n_changes
);
5472 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
, *m
= NULL
;
5473 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5475 polkit_agent_open_if_enabled();
5477 r
= sd_bus_message_new_method_call(
5480 "org.freedesktop.systemd1",
5481 "/org/freedesktop/systemd1",
5482 "org.freedesktop.systemd1.Manager",
5483 "AddDependencyUnitFiles");
5485 return bus_log_create_error(r
);
5487 r
= sd_bus_message_append_strv(m
, names
);
5489 return bus_log_create_error(r
);
5491 r
= sd_bus_message_append(m
, "ssbb", target
, unit_dependency_to_string(dep
), arg_runtime
, arg_force
);
5493 return bus_log_create_error(r
);
5495 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
5497 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
5501 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, NULL
, NULL
);
5506 r
= daemon_reload(bus
, args
);
5514 static int preset_all(sd_bus
*bus
, char **args
) {
5515 UnitFileChange
*changes
= NULL
;
5516 unsigned n_changes
= 0;
5519 if (!bus
|| avoid_bus()) {
5521 r
= unit_file_preset_all(arg_scope
, arg_runtime
, arg_root
, arg_preset_mode
, arg_force
, &changes
, &n_changes
);
5523 log_error_errno(r
, "Operation failed: %m");
5528 dump_unit_file_changes(changes
, n_changes
);
5533 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5534 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
5536 polkit_agent_open_if_enabled();
5538 r
= sd_bus_call_method(
5540 "org.freedesktop.systemd1",
5541 "/org/freedesktop/systemd1",
5542 "org.freedesktop.systemd1.Manager",
5543 "PresetAllUnitFiles",
5547 unit_file_preset_mode_to_string(arg_preset_mode
),
5551 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
5555 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, NULL
, NULL
);
5560 r
= daemon_reload(bus
, args
);
5566 unit_file_changes_free(changes
, n_changes
);
5571 static int unit_is_enabled(sd_bus
*bus
, char **args
) {
5573 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5574 _cleanup_strv_free_
char **names
= NULL
;
5579 r
= mangle_names(args
+1, &names
);
5583 r
= enable_sysv_units(args
[0], names
);
5589 if (!bus
|| avoid_bus()) {
5591 STRV_FOREACH(name
, names
) {
5592 UnitFileState state
;
5594 state
= unit_file_get_state(arg_scope
, arg_root
, *name
);
5596 return log_error_errno(state
, "Failed to get unit file state for %s: %m", *name
);
5598 if (state
== UNIT_FILE_ENABLED
||
5599 state
== UNIT_FILE_ENABLED_RUNTIME
||
5600 state
== UNIT_FILE_STATIC
||
5601 state
== UNIT_FILE_INDIRECT
)
5605 puts(unit_file_state_to_string(state
));
5609 STRV_FOREACH(name
, names
) {
5610 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
5613 r
= sd_bus_call_method(
5615 "org.freedesktop.systemd1",
5616 "/org/freedesktop/systemd1",
5617 "org.freedesktop.systemd1.Manager",
5623 log_error("Failed to get unit file state for %s: %s", *name
, bus_error_message(&error
, r
));
5627 r
= sd_bus_message_read(reply
, "s", &s
);
5629 return bus_log_parse_error(r
);
5631 if (STR_IN_SET(s
, "enabled", "enabled-runtime", "static", "indirect"))
5642 static int is_system_running(sd_bus
*bus
, char **args
) {
5643 _cleanup_free_
char *state
= NULL
;
5646 r
= sd_bus_get_property_string(
5648 "org.freedesktop.systemd1",
5649 "/org/freedesktop/systemd1",
5650 "org.freedesktop.systemd1.Manager",
5663 return streq(state
, "running") ? EXIT_SUCCESS
: EXIT_FAILURE
;
5666 static int create_edit_temp_file(const char *new_path
, const char *original_path
, char **ret_tmp_fn
) {
5671 assert(original_path
);
5674 r
= tempfn_random(new_path
, &t
);
5676 return log_error_errno(r
, "Failed to determine temporary filename for \"%s\": %m", new_path
);
5678 r
= mkdir_parents(new_path
, 0755);
5680 log_error_errno(r
, "Failed to create directories for \"%s\": %m", new_path
);
5685 r
= copy_file(original_path
, t
, 0, 0644, 0);
5689 log_error_errno(r
, "Failed to create temporary file \"%s\": %m", t
);
5694 log_error_errno(r
, "Failed to copy \"%s\" to \"%s\": %m", original_path
, t
);
5704 static int get_file_to_edit(const char *name
, const char *user_home
, const char *user_runtime
, char **ret_path
) {
5705 _cleanup_free_
char *path
= NULL
, *path2
= NULL
, *run
= NULL
;
5707 switch (arg_scope
) {
5708 case UNIT_FILE_SYSTEM
:
5709 path
= path_join(arg_root
, SYSTEM_CONFIG_UNIT_PATH
, name
);
5711 run
= path_join(arg_root
, "/run/systemd/system/", name
);
5713 case UNIT_FILE_GLOBAL
:
5714 path
= path_join(arg_root
, USER_CONFIG_UNIT_PATH
, name
);
5716 run
= path_join(arg_root
, "/run/systemd/user/", name
);
5718 case UNIT_FILE_USER
:
5720 assert(user_runtime
);
5722 path
= path_join(arg_root
, user_home
, name
);
5724 path2
= path_join(arg_root
, USER_CONFIG_UNIT_PATH
, name
);
5727 run
= path_join(arg_root
, user_runtime
, name
);
5731 assert_not_reached("Invalid scope");
5733 if (!path
|| (arg_runtime
&& !run
))
5737 if (access(path
, F_OK
) >= 0)
5738 return log_error_errno(EEXIST
, "Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.",
5740 if (path2
&& access(path2
, F_OK
) >= 0)
5741 return log_error_errno(EEXIST
, "Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.",
5753 static int unit_file_create_dropin(const char *unit_name
, const char *user_home
, const char *user_runtime
, char **ret_new_path
, char **ret_tmp_path
) {
5754 char *tmp_new_path
, *ending
;
5759 assert(ret_new_path
);
5760 assert(ret_tmp_path
);
5762 ending
= strjoina(unit_name
, ".d/override.conf");
5763 r
= get_file_to_edit(ending
, user_home
, user_runtime
, &tmp_new_path
);
5767 r
= create_edit_temp_file(tmp_new_path
, tmp_new_path
, &tmp_tmp_path
);
5773 *ret_new_path
= tmp_new_path
;
5774 *ret_tmp_path
= tmp_tmp_path
;
5779 static int unit_file_create_copy(
5780 const char *unit_name
,
5781 const char *fragment_path
,
5782 const char *user_home
,
5783 const char *user_runtime
,
5784 char **ret_new_path
,
5785 char **ret_tmp_path
) {
5791 assert(fragment_path
);
5793 assert(ret_new_path
);
5794 assert(ret_tmp_path
);
5796 r
= get_file_to_edit(unit_name
, user_home
, user_runtime
, &tmp_new_path
);
5800 if (!path_equal(fragment_path
, tmp_new_path
) && access(tmp_new_path
, F_OK
) == 0) {
5803 r
= ask_char(&response
, "yn", "\"%s\" already exists. Overwrite with \"%s\"? [(y)es, (n)o] ", tmp_new_path
, fragment_path
);
5808 if (response
!= 'y') {
5809 log_warning("%s ignored", unit_name
);
5815 r
= create_edit_temp_file(tmp_new_path
, fragment_path
, &tmp_tmp_path
);
5817 log_error_errno(r
, "Failed to create temporary file for \"%s\": %m", tmp_new_path
);
5822 *ret_new_path
= tmp_new_path
;
5823 *ret_tmp_path
= tmp_tmp_path
;
5828 static int run_editor(char **paths
) {
5836 log_error_errno(errno
, "Failed to fork: %m");
5843 char **tmp_path
, **original_path
, *p
;
5847 argc
= strv_length(paths
)/2 + 1;
5848 args
= newa(const char*, argc
+ 1);
5851 STRV_FOREACH_PAIR(original_path
, tmp_path
, paths
) {
5852 args
[i
] = *tmp_path
;
5857 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
5858 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
5859 * we try to execute well known editors
5861 editor
= getenv("SYSTEMD_EDITOR");
5863 editor
= getenv("EDITOR");
5865 editor
= getenv("VISUAL");
5867 if (!isempty(editor
)) {
5869 execvp(editor
, (char* const*) args
);
5872 FOREACH_STRING(p
, "nano", "vim", "vi") {
5874 execvp(p
, (char* const*) args
);
5875 /* We do not fail if the editor doesn't exist
5876 * because we want to try each one of them before
5879 if (errno
!= ENOENT
) {
5880 log_error("Failed to execute %s: %m", editor
);
5881 _exit(EXIT_FAILURE
);
5885 log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR, $EDITOR or $VISUAL.");
5886 _exit(EXIT_FAILURE
);
5889 r
= wait_for_terminate_and_warn("editor", pid
, true);
5891 return log_error_errno(r
, "Failed to wait for child: %m");
5896 static int find_paths_to_edit(sd_bus
*bus
, char **names
, char ***paths
) {
5897 _cleanup_free_
char *user_home
= NULL
;
5898 _cleanup_free_
char *user_runtime
= NULL
;
5899 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
5900 bool avoid_bus_cache
;
5907 r
= init_home_and_lookup_paths(&user_home
, &user_runtime
, &lp
);
5911 avoid_bus_cache
= !bus
|| avoid_bus();
5913 STRV_FOREACH(name
, names
) {
5914 _cleanup_free_
char *path
= NULL
;
5915 char *new_path
, *tmp_path
;
5917 r
= unit_find_paths(bus
, *name
, avoid_bus_cache
, &lp
, &path
, NULL
);
5923 // FIXME: support units with path==NULL (no FragmentPath)
5924 log_error("No fragment exists for %s.", *name
);
5929 r
= unit_file_create_copy(*name
, path
, user_home
, user_runtime
, &new_path
, &tmp_path
);
5931 r
= unit_file_create_dropin(*name
, user_home
, user_runtime
, &new_path
, &tmp_path
);
5935 r
= strv_push_pair(paths
, new_path
, tmp_path
);
5943 static int edit(sd_bus
*bus
, char **args
) {
5944 _cleanup_strv_free_
char **names
= NULL
;
5945 _cleanup_strv_free_
char **paths
= NULL
;
5946 char **original
, **tmp
;
5952 log_error("Cannot edit units if not on a tty");
5956 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
5957 log_error("Cannot remotely edit units");
5961 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
5963 return log_error_errno(r
, "Failed to expand names: %m");
5965 r
= find_paths_to_edit(bus
, names
, &paths
);
5969 if (strv_isempty(paths
))
5972 r
= run_editor(paths
);
5976 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
5977 /* If the temporary file is empty we ignore it.
5978 * It's useful if the user wants to cancel its modification
5980 if (null_or_empty_path(*tmp
)) {
5981 log_warning("Editing \"%s\" canceled: temporary file is empty", *original
);
5984 r
= rename(*tmp
, *original
);
5986 r
= log_error_errno(errno
, "Failed to rename \"%s\" to \"%s\": %m", *tmp
, *original
);
5991 if (!arg_no_reload
&& bus
&& !avoid_bus())
5992 r
= daemon_reload(bus
, args
);
5995 STRV_FOREACH_PAIR(original
, tmp
, paths
)
5996 unlink_noerrno(*tmp
);
6001 static void systemctl_help(void) {
6003 pager_open_if_enabled();
6005 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
6006 "Query or send control commands to the systemd manager.\n\n"
6007 " -h --help Show this help\n"
6008 " --version Show package version\n"
6009 " --system Connect to system manager\n"
6010 " --user Connect to user service manager\n"
6011 " -H --host=[USER@]HOST\n"
6012 " Operate on remote host\n"
6013 " -M --machine=CONTAINER\n"
6014 " Operate on local container\n"
6015 " -t --type=TYPE List units of a particular type\n"
6016 " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n"
6017 " -p --property=NAME Show only properties by this name\n"
6018 " -a --all Show all loaded units/properties, including dead/empty\n"
6019 " ones. To list all units installed on the system, use\n"
6020 " the 'list-unit-files' command instead.\n"
6021 " -l --full Don't ellipsize unit names on output\n"
6022 " -r --recursive Show unit list of host and local containers\n"
6023 " --reverse Show reverse dependencies with 'list-dependencies'\n"
6024 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
6025 " queueing a new job\n"
6026 " --show-types When showing sockets, explicitly show their type\n"
6027 " -i --ignore-inhibitors\n"
6028 " When shutting down or sleeping, ignore inhibitors\n"
6029 " --kill-who=WHO Who to send signal to\n"
6030 " -s --signal=SIGNAL Which signal to send\n"
6031 " --now Start or stop unit in addition to enabling or disabling it\n"
6032 " -q --quiet Suppress output\n"
6033 " --no-block Do not wait until operation finished\n"
6034 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6035 " --no-reload Don't reload daemon after en-/dis-abling unit files\n"
6036 " --no-legend Do not print a legend (column headers and hints)\n"
6037 " --no-pager Do not pipe output into a pager\n"
6038 " --no-ask-password\n"
6039 " Do not ask for system passwords\n"
6040 " --global Enable/disable unit files globally\n"
6041 " --runtime Enable unit files only temporarily until next reboot\n"
6042 " -f --force When enabling unit files, override existing symlinks\n"
6043 " When shutting down, execute action immediately\n"
6044 " --preset-mode= Apply only enable, only disable, or all presets\n"
6045 " --root=PATH Enable unit files in the specified root directory\n"
6046 " -n --lines=INTEGER Number of journal entries to show\n"
6047 " -o --output=STRING Change journal output mode (short, short-iso,\n"
6048 " short-precise, short-monotonic, verbose,\n"
6049 " export, json, json-pretty, json-sse, cat)\n"
6050 " --firmware-setup Tell the firmware to show the setup menu on next boot\n"
6051 " --plain Print unit dependencies as a list instead of a tree\n\n"
6053 " list-units [PATTERN...] List loaded units\n"
6054 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
6055 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
6056 " start NAME... Start (activate) one or more units\n"
6057 " stop NAME... Stop (deactivate) one or more units\n"
6058 " reload NAME... Reload one or more units\n"
6059 " restart NAME... Start or restart one or more units\n"
6060 " try-restart NAME... Restart one or more units if active\n"
6061 " reload-or-restart NAME... Reload one or more units if possible,\n"
6062 " otherwise start or restart\n"
6063 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
6064 " otherwise restart if active\n"
6065 " isolate NAME Start one unit and stop all others\n"
6066 " kill NAME... Send signal to processes of a unit\n"
6067 " is-active PATTERN... Check whether units are active\n"
6068 " is-failed PATTERN... Check whether units are failed\n"
6069 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
6070 " show [PATTERN...|JOB...] Show properties of one or more\n"
6071 " units/jobs or the manager\n"
6072 " cat PATTERN... Show files and drop-ins of one or more units\n"
6073 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
6074 " help PATTERN...|PID... Show manual for one or more units\n"
6075 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
6077 " list-dependencies [NAME] Recursively show units which are required\n"
6078 " or wanted by this unit or by which this\n"
6079 " unit is required or wanted\n\n"
6080 "Unit File Commands:\n"
6081 " list-unit-files [PATTERN...] List installed unit files\n"
6082 " enable NAME... Enable one or more unit files\n"
6083 " disable NAME... Disable one or more unit files\n"
6084 " reenable NAME... Reenable one or more unit files\n"
6085 " preset NAME... Enable/disable one or more unit files\n"
6086 " based on preset configuration\n"
6087 " preset-all Enable/disable all unit files based on\n"
6088 " preset configuration\n"
6089 " is-enabled NAME... Check whether unit files are enabled\n"
6090 " mask NAME... Mask one or more units\n"
6091 " unmask NAME... Unmask one or more units\n"
6092 " link PATH... Link one or more units files into\n"
6093 " the search path\n"
6094 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
6095 " on specified one or more units\n"
6096 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
6097 " on specified one or more units\n"
6098 " edit NAME... Edit one or more unit files\n"
6099 " get-default Get the name of the default target\n"
6100 " set-default NAME Set the default target\n\n"
6101 "Machine Commands:\n"
6102 " list-machines [PATTERN...] List local containers and host\n\n"
6104 " list-jobs [PATTERN...] List jobs\n"
6105 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
6106 "Snapshot Commands:\n"
6107 " snapshot [NAME] Create a snapshot\n"
6108 " delete NAME... Remove one or more snapshots\n\n"
6109 "Environment Commands:\n"
6110 " show-environment Dump environment\n"
6111 " set-environment NAME=VALUE... Set one or more environment variables\n"
6112 " unset-environment NAME... Unset one or more environment variables\n"
6113 " import-environment [NAME...] Import all or some environment variables\n\n"
6114 "Manager Lifecycle Commands:\n"
6115 " daemon-reload Reload systemd manager configuration\n"
6116 " daemon-reexec Reexecute systemd manager\n\n"
6117 "System Commands:\n"
6118 " is-system-running Check whether system is fully running\n"
6119 " default Enter system default mode\n"
6120 " rescue Enter system rescue mode\n"
6121 " emergency Enter system emergency mode\n"
6122 " halt Shut down and halt the system\n"
6123 " poweroff Shut down and power-off the system\n"
6124 " reboot [ARG] Shut down and reboot the system\n"
6125 " kexec Shut down and reboot the system with kexec\n"
6126 " exit Request user instance exit\n"
6127 " switch-root ROOT [INIT] Change to a different root file system\n"
6128 " suspend Suspend the system\n"
6129 " hibernate Hibernate the system\n"
6130 " hybrid-sleep Hibernate and suspend the system\n",
6131 program_invocation_short_name
);
6134 static void halt_help(void) {
6135 printf("%s [OPTIONS...]%s\n\n"
6136 "%s the system.\n\n"
6137 " --help Show this help\n"
6138 " --halt Halt the machine\n"
6139 " -p --poweroff Switch off the machine\n"
6140 " --reboot Reboot the machine\n"
6141 " -f --force Force immediate halt/power-off/reboot\n"
6142 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
6143 " -d --no-wtmp Don't write wtmp record\n"
6144 " --no-wall Don't send wall message before halt/power-off/reboot\n",
6145 program_invocation_short_name
,
6146 arg_action
== ACTION_REBOOT
? " [ARG]" : "",
6147 arg_action
== ACTION_REBOOT
? "Reboot" :
6148 arg_action
== ACTION_POWEROFF
? "Power off" :
6152 static void shutdown_help(void) {
6153 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
6154 "Shut down the system.\n\n"
6155 " --help Show this help\n"
6156 " -H --halt Halt the machine\n"
6157 " -P --poweroff Power-off the machine\n"
6158 " -r --reboot Reboot the machine\n"
6159 " -h Equivalent to --poweroff, overridden by --halt\n"
6160 " -k Don't halt/power-off/reboot, just send warnings\n"
6161 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6162 " -c Cancel a pending shutdown\n",
6163 program_invocation_short_name
);
6166 static void telinit_help(void) {
6167 printf("%s [OPTIONS...] {COMMAND}\n\n"
6168 "Send control commands to the init daemon.\n\n"
6169 " --help Show this help\n"
6170 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
6172 " 0 Power-off the machine\n"
6173 " 6 Reboot the machine\n"
6174 " 2, 3, 4, 5 Start runlevelX.target unit\n"
6175 " 1, s, S Enter rescue mode\n"
6176 " q, Q Reload init daemon configuration\n"
6177 " u, U Reexecute init daemon\n",
6178 program_invocation_short_name
);
6181 static void runlevel_help(void) {
6182 printf("%s [OPTIONS...]\n\n"
6183 "Prints the previous and current runlevel of the init system.\n\n"
6184 " --help Show this help\n",
6185 program_invocation_short_name
);
6188 static void help_types(void) {
6193 puts("Available unit types:");
6194 for (i
= 0; i
< _UNIT_TYPE_MAX
; i
++) {
6195 t
= unit_type_to_string(i
);
6201 static int systemctl_parse_argv(int argc
, char *argv
[]) {
6210 ARG_IGNORE_DEPENDENCIES
,
6222 ARG_NO_ASK_PASSWORD
,
6234 static const struct option options
[] = {
6235 { "help", no_argument
, NULL
, 'h' },
6236 { "version", no_argument
, NULL
, ARG_VERSION
},
6237 { "type", required_argument
, NULL
, 't' },
6238 { "property", required_argument
, NULL
, 'p' },
6239 { "all", no_argument
, NULL
, 'a' },
6240 { "reverse", no_argument
, NULL
, ARG_REVERSE
},
6241 { "after", no_argument
, NULL
, ARG_AFTER
},
6242 { "before", no_argument
, NULL
, ARG_BEFORE
},
6243 { "show-types", no_argument
, NULL
, ARG_SHOW_TYPES
},
6244 { "failed", no_argument
, NULL
, ARG_FAILED
}, /* compatibility only */
6245 { "full", no_argument
, NULL
, 'l' },
6246 { "job-mode", required_argument
, NULL
, ARG_JOB_MODE
},
6247 { "fail", no_argument
, NULL
, ARG_FAIL
}, /* compatibility only */
6248 { "irreversible", no_argument
, NULL
, ARG_IRREVERSIBLE
}, /* compatibility only */
6249 { "ignore-dependencies", no_argument
, NULL
, ARG_IGNORE_DEPENDENCIES
}, /* compatibility only */
6250 { "ignore-inhibitors", no_argument
, NULL
, 'i' },
6251 { "user", no_argument
, NULL
, ARG_USER
},
6252 { "system", no_argument
, NULL
, ARG_SYSTEM
},
6253 { "global", no_argument
, NULL
, ARG_GLOBAL
},
6254 { "no-block", no_argument
, NULL
, ARG_NO_BLOCK
},
6255 { "no-legend", no_argument
, NULL
, ARG_NO_LEGEND
},
6256 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
6257 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6258 { "quiet", no_argument
, NULL
, 'q' },
6259 { "root", required_argument
, NULL
, ARG_ROOT
},
6260 { "force", no_argument
, NULL
, ARG_FORCE
},
6261 { "no-reload", no_argument
, NULL
, ARG_NO_RELOAD
},
6262 { "kill-who", required_argument
, NULL
, ARG_KILL_WHO
},
6263 { "signal", required_argument
, NULL
, 's' },
6264 { "no-ask-password", no_argument
, NULL
, ARG_NO_ASK_PASSWORD
},
6265 { "host", required_argument
, NULL
, 'H' },
6266 { "machine", required_argument
, NULL
, 'M' },
6267 { "runtime", no_argument
, NULL
, ARG_RUNTIME
},
6268 { "lines", required_argument
, NULL
, 'n' },
6269 { "output", required_argument
, NULL
, 'o' },
6270 { "plain", no_argument
, NULL
, ARG_PLAIN
},
6271 { "state", required_argument
, NULL
, ARG_STATE
},
6272 { "recursive", no_argument
, NULL
, 'r' },
6273 { "preset-mode", required_argument
, NULL
, ARG_PRESET_MODE
},
6274 { "firmware-setup", no_argument
, NULL
, ARG_FIRMWARE_SETUP
},
6275 { "now", no_argument
, NULL
, ARG_NOW
},
6284 while ((c
= getopt_long(argc
, argv
, "ht:p:alqfs:H:M:n:o:ir", options
, NULL
)) >= 0)
6293 puts(PACKAGE_STRING
);
6294 puts(SYSTEMD_FEATURES
);
6298 const char *word
, *state
;
6301 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
6302 _cleanup_free_
char *type
;
6304 type
= strndup(word
, size
);
6308 if (streq(type
, "help")) {
6313 if (unit_type_from_string(type
) >= 0) {
6314 if (strv_push(&arg_types
, type
))
6320 /* It's much nicer to use --state= for
6321 * load states, but let's support this
6322 * in --types= too for compatibility
6323 * with old versions */
6324 if (unit_load_state_from_string(optarg
) >= 0) {
6325 if (strv_push(&arg_states
, type
) < 0)
6331 log_error("Unknown unit type or load state '%s'.", type
);
6332 log_info("Use -t help to see a list of allowed values.");
6340 /* Make sure that if the empty property list
6341 was specified, we won't show any properties. */
6342 if (isempty(optarg
) && !arg_properties
) {
6343 arg_properties
= new0(char*, 1);
6344 if (!arg_properties
)
6347 const char *word
, *state
;
6350 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
6353 prop
= strndup(word
, size
);
6357 if (strv_consume(&arg_properties
, prop
) < 0)
6362 /* If the user asked for a particular
6363 * property, show it to him, even if it is
6375 arg_dependency
= DEPENDENCY_REVERSE
;
6379 arg_dependency
= DEPENDENCY_AFTER
;
6383 arg_dependency
= DEPENDENCY_BEFORE
;
6386 case ARG_SHOW_TYPES
:
6387 arg_show_types
= true;
6391 arg_job_mode
= optarg
;
6395 arg_job_mode
= "fail";
6398 case ARG_IRREVERSIBLE
:
6399 arg_job_mode
= "replace-irreversibly";
6402 case ARG_IGNORE_DEPENDENCIES
:
6403 arg_job_mode
= "ignore-dependencies";
6407 arg_scope
= UNIT_FILE_USER
;
6411 arg_scope
= UNIT_FILE_SYSTEM
;
6415 arg_scope
= UNIT_FILE_GLOBAL
;
6419 arg_no_block
= true;
6423 arg_no_legend
= true;
6427 arg_no_pager
= true;
6443 if (strv_extend(&arg_states
, "failed") < 0)
6461 arg_no_reload
= true;
6465 arg_kill_who
= optarg
;
6469 if ((arg_signal
= signal_from_string_try_harder(optarg
)) < 0) {
6470 log_error("Failed to parse signal string %s.", optarg
);
6475 case ARG_NO_ASK_PASSWORD
:
6476 arg_ask_password
= false;
6480 arg_transport
= BUS_TRANSPORT_REMOTE
;
6485 arg_transport
= BUS_TRANSPORT_MACHINE
;
6494 if (safe_atou(optarg
, &arg_lines
) < 0) {
6495 log_error("Failed to parse lines '%s'", optarg
);
6501 arg_output
= output_mode_from_string(optarg
);
6502 if (arg_output
< 0) {
6503 log_error("Unknown output '%s'.", optarg
);
6509 arg_ignore_inhibitors
= true;
6516 case ARG_FIRMWARE_SETUP
:
6517 arg_firmware_setup
= true;
6521 const char *word
, *state
;
6524 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
6527 s
= strndup(word
, size
);
6531 if (strv_consume(&arg_states
, s
) < 0)
6538 if (geteuid() != 0) {
6539 log_error("--recursive requires root privileges.");
6543 arg_recursive
= true;
6546 case ARG_PRESET_MODE
:
6548 arg_preset_mode
= unit_file_preset_mode_from_string(optarg
);
6549 if (arg_preset_mode
< 0) {
6550 log_error("Failed to parse preset mode: %s.", optarg
);
6564 assert_not_reached("Unhandled option");
6567 if (arg_transport
!= BUS_TRANSPORT_LOCAL
&& arg_scope
!= UNIT_FILE_SYSTEM
) {
6568 log_error("Cannot access user instance remotely.");
6575 static int halt_parse_argv(int argc
, char *argv
[]) {
6584 static const struct option options
[] = {
6585 { "help", no_argument
, NULL
, ARG_HELP
},
6586 { "halt", no_argument
, NULL
, ARG_HALT
},
6587 { "poweroff", no_argument
, NULL
, 'p' },
6588 { "reboot", no_argument
, NULL
, ARG_REBOOT
},
6589 { "force", no_argument
, NULL
, 'f' },
6590 { "wtmp-only", no_argument
, NULL
, 'w' },
6591 { "no-wtmp", no_argument
, NULL
, 'd' },
6592 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6601 if (utmp_get_runlevel(&runlevel
, NULL
) >= 0)
6602 if (runlevel
== '0' || runlevel
== '6')
6605 while ((c
= getopt_long(argc
, argv
, "pfwdnih", options
, NULL
)) >= 0)
6613 arg_action
= ACTION_HALT
;
6617 if (arg_action
!= ACTION_REBOOT
)
6618 arg_action
= ACTION_POWEROFF
;
6622 arg_action
= ACTION_REBOOT
;
6644 /* Compatibility nops */
6651 assert_not_reached("Unhandled option");
6654 if (arg_action
== ACTION_REBOOT
&& (argc
== optind
|| argc
== optind
+ 1)) {
6655 r
= update_reboot_param_file(argc
== optind
+ 1 ? argv
[optind
] : NULL
);
6658 } else if (optind
< argc
) {
6659 log_error("Too many arguments.");
6666 static int parse_time_spec(const char *t
, usec_t
*_u
) {
6670 if (streq(t
, "now"))
6672 else if (!strchr(t
, ':')) {
6675 if (safe_atou64(t
, &u
) < 0)
6678 *_u
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
* u
;
6687 hour
= strtol(t
, &e
, 10);
6688 if (errno
> 0 || *e
!= ':' || hour
< 0 || hour
> 23)
6691 minute
= strtol(e
+1, &e
, 10);
6692 if (errno
> 0 || *e
!= 0 || minute
< 0 || minute
> 59)
6695 n
= now(CLOCK_REALTIME
);
6696 s
= (time_t) (n
/ USEC_PER_SEC
);
6698 assert_se(localtime_r(&s
, &tm
));
6700 tm
.tm_hour
= (int) hour
;
6701 tm
.tm_min
= (int) minute
;
6704 assert_se(s
= mktime(&tm
));
6706 *_u
= (usec_t
) s
* USEC_PER_SEC
;
6709 *_u
+= USEC_PER_DAY
;
6715 static int shutdown_parse_argv(int argc
, char *argv
[]) {
6722 static const struct option options
[] = {
6723 { "help", no_argument
, NULL
, ARG_HELP
},
6724 { "halt", no_argument
, NULL
, 'H' },
6725 { "poweroff", no_argument
, NULL
, 'P' },
6726 { "reboot", no_argument
, NULL
, 'r' },
6727 { "kexec", no_argument
, NULL
, 'K' }, /* not documented extension */
6728 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6737 while ((c
= getopt_long(argc
, argv
, "HPrhkKt:afFc", options
, NULL
)) >= 0)
6745 arg_action
= ACTION_HALT
;
6749 arg_action
= ACTION_POWEROFF
;
6754 arg_action
= ACTION_KEXEC
;
6756 arg_action
= ACTION_REBOOT
;
6760 arg_action
= ACTION_KEXEC
;
6764 if (arg_action
!= ACTION_HALT
)
6765 arg_action
= ACTION_POWEROFF
;
6780 /* Compatibility nops */
6784 arg_action
= ACTION_CANCEL_SHUTDOWN
;
6791 assert_not_reached("Unhandled option");
6794 if (argc
> optind
&& arg_action
!= ACTION_CANCEL_SHUTDOWN
) {
6795 r
= parse_time_spec(argv
[optind
], &arg_when
);
6797 log_error("Failed to parse time specification: %s", argv
[optind
]);
6801 arg_when
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
;
6803 if (argc
> optind
&& arg_action
== ACTION_CANCEL_SHUTDOWN
)
6804 /* No time argument for shutdown cancel */
6805 arg_wall
= argv
+ optind
;
6806 else if (argc
> optind
+ 1)
6807 /* We skip the time argument */
6808 arg_wall
= argv
+ optind
+ 1;
6815 static int telinit_parse_argv(int argc
, char *argv
[]) {
6822 static const struct option options
[] = {
6823 { "help", no_argument
, NULL
, ARG_HELP
},
6824 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6828 static const struct {
6832 { '0', ACTION_POWEROFF
},
6833 { '6', ACTION_REBOOT
},
6834 { '1', ACTION_RESCUE
},
6835 { '2', ACTION_RUNLEVEL2
},
6836 { '3', ACTION_RUNLEVEL3
},
6837 { '4', ACTION_RUNLEVEL4
},
6838 { '5', ACTION_RUNLEVEL5
},
6839 { 's', ACTION_RESCUE
},
6840 { 'S', ACTION_RESCUE
},
6841 { 'q', ACTION_RELOAD
},
6842 { 'Q', ACTION_RELOAD
},
6843 { 'u', ACTION_REEXEC
},
6844 { 'U', ACTION_REEXEC
}
6853 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
6868 assert_not_reached("Unhandled option");
6871 if (optind
>= argc
) {
6872 log_error("%s: required argument missing.",
6873 program_invocation_short_name
);
6877 if (optind
+ 1 < argc
) {
6878 log_error("Too many arguments.");
6882 if (strlen(argv
[optind
]) != 1) {
6883 log_error("Expected single character argument.");
6887 for (i
= 0; i
< ELEMENTSOF(table
); i
++)
6888 if (table
[i
].from
== argv
[optind
][0])
6891 if (i
>= ELEMENTSOF(table
)) {
6892 log_error("Unknown command '%s'.", argv
[optind
]);
6896 arg_action
= table
[i
].to
;
6903 static int runlevel_parse_argv(int argc
, char *argv
[]) {
6909 static const struct option options
[] = {
6910 { "help", no_argument
, NULL
, ARG_HELP
},
6919 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
6930 assert_not_reached("Unhandled option");
6933 if (optind
< argc
) {
6934 log_error("Too many arguments.");
6941 static int parse_argv(int argc
, char *argv
[]) {
6945 if (program_invocation_short_name
) {
6947 if (strstr(program_invocation_short_name
, "halt")) {
6948 arg_action
= ACTION_HALT
;
6949 return halt_parse_argv(argc
, argv
);
6950 } else if (strstr(program_invocation_short_name
, "poweroff")) {
6951 arg_action
= ACTION_POWEROFF
;
6952 return halt_parse_argv(argc
, argv
);
6953 } else if (strstr(program_invocation_short_name
, "reboot")) {
6955 arg_action
= ACTION_KEXEC
;
6957 arg_action
= ACTION_REBOOT
;
6958 return halt_parse_argv(argc
, argv
);
6959 } else if (strstr(program_invocation_short_name
, "shutdown")) {
6960 arg_action
= ACTION_POWEROFF
;
6961 return shutdown_parse_argv(argc
, argv
);
6962 } else if (strstr(program_invocation_short_name
, "init")) {
6964 if (sd_booted() > 0) {
6965 arg_action
= _ACTION_INVALID
;
6966 return telinit_parse_argv(argc
, argv
);
6968 /* Hmm, so some other init system is
6969 * running, we need to forward this
6970 * request to it. For now we simply
6971 * guess that it is Upstart. */
6973 execv(TELINIT
, argv
);
6975 log_error("Couldn't find an alternative telinit implementation to spawn.");
6979 } else if (strstr(program_invocation_short_name
, "runlevel")) {
6980 arg_action
= ACTION_RUNLEVEL
;
6981 return runlevel_parse_argv(argc
, argv
);
6985 arg_action
= ACTION_SYSTEMCTL
;
6986 return systemctl_parse_argv(argc
, argv
);
6989 _pure_
static int action_to_runlevel(void) {
6991 static const char table
[_ACTION_MAX
] = {
6992 [ACTION_HALT
] = '0',
6993 [ACTION_POWEROFF
] = '0',
6994 [ACTION_REBOOT
] = '6',
6995 [ACTION_RUNLEVEL2
] = '2',
6996 [ACTION_RUNLEVEL3
] = '3',
6997 [ACTION_RUNLEVEL4
] = '4',
6998 [ACTION_RUNLEVEL5
] = '5',
6999 [ACTION_RESCUE
] = '1'
7002 assert(arg_action
< _ACTION_MAX
);
7004 return table
[arg_action
];
7007 static int talk_initctl(void) {
7009 struct init_request request
= {
7010 .magic
= INIT_MAGIC
,
7012 .cmd
= INIT_CMD_RUNLVL
7015 _cleanup_close_
int fd
= -1;
7019 rl
= action_to_runlevel();
7023 request
.runlevel
= rl
;
7025 fd
= open(INIT_FIFO
, O_WRONLY
|O_NDELAY
|O_CLOEXEC
|O_NOCTTY
);
7027 if (errno
== ENOENT
)
7030 log_error_errno(errno
, "Failed to open "INIT_FIFO
": %m");
7034 r
= loop_write(fd
, &request
, sizeof(request
), false);
7036 return log_error_errno(r
, "Failed to write to "INIT_FIFO
": %m");
7041 static int systemctl_main(sd_bus
*bus
, int argc
, char *argv
[], int bus_error
) {
7043 static const struct {
7051 int (* const dispatch
)(sd_bus
*bus
, char **args
);
7057 { "list-units", MORE
, 0, list_units
},
7058 { "list-unit-files", MORE
, 1, list_unit_files
, NOBUS
},
7059 { "list-sockets", MORE
, 1, list_sockets
},
7060 { "list-timers", MORE
, 1, list_timers
},
7061 { "list-jobs", MORE
, 1, list_jobs
},
7062 { "list-machines", MORE
, 1, list_machines
},
7063 { "clear-jobs", EQUAL
, 1, daemon_reload
},
7064 { "cancel", MORE
, 2, cancel_job
},
7065 { "start", MORE
, 2, start_unit
},
7066 { "stop", MORE
, 2, start_unit
},
7067 { "condstop", MORE
, 2, start_unit
}, /* For compatibility with ALTLinux */
7068 { "reload", MORE
, 2, start_unit
},
7069 { "restart", MORE
, 2, start_unit
},
7070 { "try-restart", MORE
, 2, start_unit
},
7071 { "reload-or-restart", MORE
, 2, start_unit
},
7072 { "reload-or-try-restart", MORE
, 2, start_unit
},
7073 { "force-reload", MORE
, 2, start_unit
}, /* For compatibility with SysV */
7074 { "condreload", MORE
, 2, start_unit
}, /* For compatibility with ALTLinux */
7075 { "condrestart", MORE
, 2, start_unit
}, /* For compatibility with RH */
7076 { "isolate", EQUAL
, 2, start_unit
},
7077 { "kill", MORE
, 2, kill_unit
},
7078 { "is-active", MORE
, 2, check_unit_active
},
7079 { "check", MORE
, 2, check_unit_active
},
7080 { "is-failed", MORE
, 2, check_unit_failed
},
7081 { "show", MORE
, 1, show
},
7082 { "cat", MORE
, 2, cat
, NOBUS
},
7083 { "status", MORE
, 1, show
},
7084 { "help", MORE
, 2, show
},
7085 { "snapshot", LESS
, 2, snapshot
},
7086 { "delete", MORE
, 2, delete_snapshot
},
7087 { "daemon-reload", EQUAL
, 1, daemon_reload
},
7088 { "daemon-reexec", EQUAL
, 1, daemon_reload
},
7089 { "show-environment", EQUAL
, 1, show_environment
},
7090 { "set-environment", MORE
, 2, set_environment
},
7091 { "unset-environment", MORE
, 2, set_environment
},
7092 { "import-environment", MORE
, 1, import_environment
},
7093 { "halt", EQUAL
, 1, start_special
, FORCE
},
7094 { "poweroff", EQUAL
, 1, start_special
, FORCE
},
7095 { "reboot", MORE
, 1, start_special
, FORCE
},
7096 { "kexec", EQUAL
, 1, start_special
},
7097 { "suspend", EQUAL
, 1, start_special
},
7098 { "hibernate", EQUAL
, 1, start_special
},
7099 { "hybrid-sleep", EQUAL
, 1, start_special
},
7100 { "default", EQUAL
, 1, start_special
},
7101 { "rescue", EQUAL
, 1, start_special
},
7102 { "emergency", EQUAL
, 1, start_special
},
7103 { "exit", EQUAL
, 1, start_special
},
7104 { "reset-failed", MORE
, 1, reset_failed
},
7105 { "enable", MORE
, 2, enable_unit
, NOBUS
},
7106 { "disable", MORE
, 2, enable_unit
, NOBUS
},
7107 { "is-enabled", MORE
, 2, unit_is_enabled
, NOBUS
},
7108 { "reenable", MORE
, 2, enable_unit
, NOBUS
},
7109 { "preset", MORE
, 2, enable_unit
, NOBUS
},
7110 { "preset-all", EQUAL
, 1, preset_all
, NOBUS
},
7111 { "mask", MORE
, 2, enable_unit
, NOBUS
},
7112 { "unmask", MORE
, 2, enable_unit
, NOBUS
},
7113 { "link", MORE
, 2, enable_unit
, NOBUS
},
7114 { "switch-root", MORE
, 2, switch_root
},
7115 { "list-dependencies", LESS
, 2, list_dependencies
},
7116 { "set-default", EQUAL
, 2, set_default
, NOBUS
},
7117 { "get-default", EQUAL
, 1, get_default
, NOBUS
},
7118 { "set-property", MORE
, 3, set_property
},
7119 { "is-system-running", EQUAL
, 1, is_system_running
},
7120 { "add-wants", MORE
, 3, add_dependency
, NOBUS
},
7121 { "add-requires", MORE
, 3, add_dependency
, NOBUS
},
7122 { "edit", MORE
, 2, edit
, NOBUS
},
7131 left
= argc
- optind
;
7133 /* Special rule: no arguments (left == 0) means "list-units" */
7135 if (streq(argv
[optind
], "help") && !argv
[optind
+1]) {
7136 log_error("This command expects one or more "
7137 "unit names. Did you mean --help?");
7141 for (; verb
->verb
; verb
++)
7142 if (streq(argv
[optind
], verb
->verb
))
7145 log_error("Unknown operation '%s'.", argv
[optind
]);
7150 switch (verb
->argc_cmp
) {
7153 if (left
!= verb
->argc
) {
7154 log_error("Invalid number of arguments.");
7161 if (left
< verb
->argc
) {
7162 log_error("Too few arguments.");
7169 if (left
> verb
->argc
) {
7170 log_error("Too many arguments.");
7177 assert_not_reached("Unknown comparison operator.");
7180 /* Require a bus connection for all operations but
7182 if (verb
->bus
== NOBUS
) {
7183 if (!bus
&& !avoid_bus()) {
7184 log_error_errno(bus_error
, "Failed to get D-Bus connection: %m");
7189 if (running_in_chroot() > 0) {
7190 log_info("Running in chroot, ignoring request.");
7194 if ((verb
->bus
!= FORCE
|| arg_force
<= 0) && !bus
) {
7195 log_error_errno(bus_error
, "Failed to get D-Bus connection: %m");
7200 return verb
->dispatch(bus
, argv
+ optind
);
7203 static int reload_with_fallback(sd_bus
*bus
) {
7206 /* First, try systemd via D-Bus. */
7207 if (daemon_reload(bus
, NULL
) >= 0)
7211 /* Nothing else worked, so let's try signals */
7212 assert(arg_action
== ACTION_RELOAD
|| arg_action
== ACTION_REEXEC
);
7214 if (kill(1, arg_action
== ACTION_RELOAD
? SIGHUP
: SIGTERM
) < 0)
7215 return log_error_errno(errno
, "kill() failed: %m");
7220 static int start_with_fallback(sd_bus
*bus
) {
7223 /* First, try systemd via D-Bus. */
7224 if (start_unit(bus
, NULL
) >= 0)
7228 /* Nothing else worked, so let's try
7230 if (talk_initctl() > 0)
7233 log_error("Failed to talk to init daemon.");
7237 warn_wall(arg_action
);
7241 static int halt_now(enum action a
) {
7243 /* The kernel will automaticall flush ATA disks and suchlike
7244 * on reboot(), but the file systems need to be synce'd
7245 * explicitly in advance. */
7248 /* Make sure C-A-D is handled by the kernel from this point
7250 reboot(RB_ENABLE_CAD
);
7255 log_info("Halting.");
7256 reboot(RB_HALT_SYSTEM
);
7259 case ACTION_POWEROFF
:
7260 log_info("Powering off.");
7261 reboot(RB_POWER_OFF
);
7264 case ACTION_REBOOT
: {
7265 _cleanup_free_
char *param
= NULL
;
7267 if (read_one_line_file(REBOOT_PARAM_FILE
, ¶m
) >= 0) {
7268 log_info("Rebooting with argument '%s'.", param
);
7269 syscall(SYS_reboot
, LINUX_REBOOT_MAGIC1
, LINUX_REBOOT_MAGIC2
,
7270 LINUX_REBOOT_CMD_RESTART2
, param
);
7273 log_info("Rebooting.");
7274 reboot(RB_AUTOBOOT
);
7279 assert_not_reached("Unknown action.");
7283 static int halt_main(sd_bus
*bus
) {
7286 r
= check_inhibitors(bus
, arg_action
);
7290 if (geteuid() != 0) {
7291 /* Try logind if we are a normal user and no special
7292 * mode applies. Maybe PolicyKit allows us to shutdown
7295 if (arg_when
<= 0 &&
7298 (arg_action
== ACTION_POWEROFF
||
7299 arg_action
== ACTION_REBOOT
)) {
7300 r
= reboot_with_logind(bus
, arg_action
);
7305 log_error("Must be root.");
7310 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
7311 _cleanup_bus_close_unref_ sd_bus
*b
= NULL
;
7312 _cleanup_free_
char *m
= NULL
;
7315 log_error("Unable to perform operation without bus connection.");
7319 r
= sd_bus_open_system(&b
);
7321 return log_error_errno(r
, "Unable to open system bus: %m");
7323 m
= strv_join(arg_wall
, " ");
7327 r
= sd_bus_set_property(
7329 "org.freedesktop.login1",
7330 "/org/freedesktop/login1",
7331 "org.freedesktop.login1.Manager",
7336 log_warning_errno(r
, "Failed to set WallMessage property in logind: %s",
7337 bus_error_message(&error
, r
));
7338 sd_bus_error_free(&error
);
7341 r
= sd_bus_set_property(
7343 "org.freedesktop.login1",
7344 "/org/freedesktop/login1",
7345 "org.freedesktop.login1.Manager",
7346 "EnableWallMessages",
7350 log_warning_errno(r
, "Failed to set EnableWallMessages property in logind: %s",
7351 bus_error_message(&error
, r
));
7352 sd_bus_error_free(&error
);
7355 r
= sd_bus_call_method(
7357 "org.freedesktop.login1",
7358 "/org/freedesktop/login1",
7359 "org.freedesktop.login1.Manager",
7364 arg_action
== ACTION_HALT
? "halt" :
7365 arg_action
== ACTION_POWEROFF
? "poweroff" :
7366 arg_action
== ACTION_KEXEC
? "kexec" :
7370 log_warning_errno(r
, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s",
7371 bus_error_message(&error
, r
));
7373 char date
[FORMAT_TIMESTAMP_MAX
];
7375 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
7376 format_timestamp(date
, sizeof(date
), arg_when
));
7381 if (!arg_dry
&& !arg_force
)
7382 return start_with_fallback(bus
);
7385 if (sd_booted() > 0)
7386 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
7388 r
= utmp_put_shutdown();
7390 log_warning_errno(r
, "Failed to write utmp record: %m");
7397 r
= halt_now(arg_action
);
7398 log_error_errno(r
, "Failed to reboot: %m");
7403 static int runlevel_main(void) {
7404 int r
, runlevel
, previous
;
7406 r
= utmp_get_runlevel(&runlevel
, &previous
);
7413 previous
<= 0 ? 'N' : previous
,
7414 runlevel
<= 0 ? 'N' : runlevel
);
7419 int main(int argc
, char*argv
[]) {
7420 _cleanup_bus_close_unref_ sd_bus
*bus
= NULL
;
7423 setlocale(LC_ALL
, "");
7424 log_parse_environment();
7427 /* Explicitly not on_tty() to avoid setting cached value.
7428 * This becomes relevant for piping output which might be
7430 original_stdout_is_tty
= isatty(STDOUT_FILENO
);
7432 r
= parse_argv(argc
, argv
);
7436 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
7437 * let's shortcut this */
7438 if (arg_action
== ACTION_RUNLEVEL
) {
7439 r
= runlevel_main();
7443 if (running_in_chroot() > 0 && arg_action
!= ACTION_SYSTEMCTL
) {
7444 log_info("Running in chroot, ignoring request.");
7450 r
= bus_open_transport_systemd(arg_transport
, arg_host
, arg_scope
!= UNIT_FILE_SYSTEM
, &bus
);
7453 sd_bus_set_allow_interactive_authorization(bus
, arg_ask_password
);
7455 /* systemctl_main() will print an error message for the bus
7456 * connection, but only if it needs to */
7458 switch (arg_action
) {
7460 case ACTION_SYSTEMCTL
:
7461 r
= systemctl_main(bus
, argc
, argv
, r
);
7465 case ACTION_POWEROFF
:
7471 case ACTION_RUNLEVEL2
:
7472 case ACTION_RUNLEVEL3
:
7473 case ACTION_RUNLEVEL4
:
7474 case ACTION_RUNLEVEL5
:
7476 case ACTION_EMERGENCY
:
7477 case ACTION_DEFAULT
:
7478 r
= start_with_fallback(bus
);
7483 r
= reload_with_fallback(bus
);
7486 case ACTION_CANCEL_SHUTDOWN
: {
7487 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
7488 _cleanup_bus_close_unref_ sd_bus
*b
= NULL
;
7489 _cleanup_free_
char *m
= NULL
;
7492 log_error("Unable to perform operation without bus connection.");
7496 r
= sd_bus_open_system(&b
);
7498 return log_error_errno(r
, "Unable to open system bus: %m");
7501 m
= strv_join(arg_wall
, " ");
7508 r
= sd_bus_set_property(
7510 "org.freedesktop.login1",
7511 "/org/freedesktop/login1",
7512 "org.freedesktop.login1.Manager",
7517 log_warning_errno(r
, "Failed to set WallMessage property in logind: %s",
7518 bus_error_message(&error
, r
));
7519 sd_bus_error_free(&error
);
7522 r
= sd_bus_set_property(
7524 "org.freedesktop.login1",
7525 "/org/freedesktop/login1",
7526 "org.freedesktop.login1.Manager",
7527 "EnableWallMessages",
7531 log_warning_errno(r
, "Failed to set EnableWallMessages property in logind: %s",
7532 bus_error_message(&error
, r
));
7533 sd_bus_error_free(&error
);
7536 r
= sd_bus_call_method(
7538 "org.freedesktop.login1",
7539 "/org/freedesktop/login1",
7540 "org.freedesktop.login1.Manager",
7541 "CancelScheduledShutdown",
7545 log_warning_errno(r
, "Failed to talk to logind, shutdown hasn't been cancelled: %s",
7546 bus_error_message(&error
, r
));
7550 case ACTION_RUNLEVEL
:
7551 case _ACTION_INVALID
:
7553 assert_not_reached("Unknown action");
7558 ask_password_agent_close();
7559 polkit_agent_close();
7561 strv_free(arg_types
);
7562 strv_free(arg_states
);
7563 strv_free(arg_properties
);
7565 return r
< 0 ? EXIT_FAILURE
: r
;