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/>.
26 #include <linux/reboot.h>
32 #include <sys/reboot.h>
33 #include <sys/socket.h>
37 #include "sd-daemon.h"
40 #include "bus-common-errors.h"
41 #include "bus-error.h"
42 #include "bus-message.h"
44 #include "cgroup-show.h"
45 #include "cgroup-util.h"
50 #include "exit-status.h"
52 #include "formats-util.h"
53 #include "hostname-util.h"
58 #include "logs-show.h"
62 #include "path-lookup.h"
63 #include "path-util.h"
64 #include "process-util.h"
66 #include "signal-util.h"
67 #include "socket-util.h"
68 #include "spawn-ask-password-agent.h"
69 #include "spawn-polkit-agent.h"
72 #include "terminal-util.h"
73 #include "unit-name.h"
75 #include "utmp-wtmp.h"
77 static char **arg_types
= NULL
;
78 static char **arg_states
= NULL
;
79 static char **arg_properties
= NULL
;
80 static bool arg_all
= false;
81 static enum dependency
{
87 } arg_dependency
= DEPENDENCY_FORWARD
;
88 static const char *arg_job_mode
= "replace";
89 static UnitFileScope arg_scope
= UNIT_FILE_SYSTEM
;
90 static bool arg_no_block
= false;
91 static bool arg_no_legend
= false;
92 static bool arg_no_pager
= false;
93 static bool arg_no_wtmp
= false;
94 static bool arg_no_wall
= false;
95 static bool arg_no_reload
= false;
96 static bool arg_show_types
= false;
97 static bool arg_ignore_inhibitors
= false;
98 static bool arg_dry
= false;
99 static bool arg_quiet
= false;
100 static bool arg_full
= false;
101 static bool arg_recursive
= false;
102 static int arg_force
= 0;
103 static bool arg_ask_password
= false;
104 static bool arg_runtime
= false;
105 static UnitFilePresetMode arg_preset_mode
= UNIT_FILE_PRESET_FULL
;
106 static char **arg_wall
= NULL
;
107 static const char *arg_kill_who
= NULL
;
108 static int arg_signal
= SIGTERM
;
109 static const char *arg_root
= NULL
;
110 static usec_t arg_when
= 0;
132 ACTION_CANCEL_SHUTDOWN
,
134 } arg_action
= ACTION_SYSTEMCTL
;
135 static BusTransport arg_transport
= BUS_TRANSPORT_LOCAL
;
136 static const char *arg_host
= NULL
;
137 static unsigned arg_lines
= 10;
138 static OutputMode arg_output
= OUTPUT_SHORT
;
139 static bool arg_plain
= false;
140 static bool arg_firmware_setup
= false;
141 static bool arg_now
= false;
143 static bool original_stdout_is_tty
;
145 static int daemon_reload(sd_bus
*bus
, char **args
);
146 static int halt_now(enum action a
);
147 static int check_one_unit(sd_bus
*bus
, const char *name
, const char *good_states
, bool quiet
);
149 static void pager_open_if_enabled(void) {
157 static void ask_password_agent_open_if_enabled(void) {
159 /* Open the password agent as a child process if necessary */
161 if (!arg_ask_password
)
164 if (arg_scope
!= UNIT_FILE_SYSTEM
)
167 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
170 ask_password_agent_open();
173 static void polkit_agent_open_if_enabled(void) {
175 /* Open the polkit agent as a child process if necessary */
177 if (!arg_ask_password
)
180 if (arg_scope
!= UNIT_FILE_SYSTEM
)
183 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
189 static OutputFlags
get_output_flags(void) {
191 arg_all
* OUTPUT_SHOW_ALL
|
192 arg_full
* OUTPUT_FULL_WIDTH
|
193 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH
|
194 on_tty() * OUTPUT_COLOR
|
195 !arg_quiet
* OUTPUT_WARN_CUTOFF
;
198 static int translate_bus_error_to_exit_status(int r
, const sd_bus_error
*error
) {
201 if (!sd_bus_error_is_set(error
))
204 if (sd_bus_error_has_name(error
, SD_BUS_ERROR_ACCESS_DENIED
) ||
205 sd_bus_error_has_name(error
, BUS_ERROR_ONLY_BY_DEPENDENCY
) ||
206 sd_bus_error_has_name(error
, BUS_ERROR_NO_ISOLATION
) ||
207 sd_bus_error_has_name(error
, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE
))
208 return EXIT_NOPERMISSION
;
210 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
))
211 return EXIT_NOTINSTALLED
;
213 if (sd_bus_error_has_name(error
, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE
) ||
214 sd_bus_error_has_name(error
, SD_BUS_ERROR_NOT_SUPPORTED
))
215 return EXIT_NOTIMPLEMENTED
;
217 if (sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
))
218 return EXIT_NOTCONFIGURED
;
226 static bool avoid_bus(void) {
228 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
229 * let's shortcut this */
230 if (arg_action
== ACTION_RUNLEVEL
)
233 if (running_in_chroot() > 0)
236 if (sd_booted() <= 0)
239 if (!isempty(arg_root
))
242 if (arg_scope
== UNIT_FILE_GLOBAL
)
248 static int compare_unit_info(const void *a
, const void *b
) {
249 const UnitInfo
*u
= a
, *v
= b
;
253 /* First, order by machine */
254 if (!u
->machine
&& v
->machine
)
256 if (u
->machine
&& !v
->machine
)
258 if (u
->machine
&& v
->machine
) {
259 r
= strcasecmp(u
->machine
, v
->machine
);
264 /* Second, order by unit type */
265 d1
= strrchr(u
->id
, '.');
266 d2
= strrchr(v
->id
, '.');
268 r
= strcasecmp(d1
, d2
);
273 /* Third, order by name */
274 return strcasecmp(u
->id
, v
->id
);
277 static bool output_show_unit(const UnitInfo
*u
, char **patterns
) {
278 if (!strv_fnmatch_or_empty(patterns
, u
->id
, FNM_NOESCAPE
))
284 dot
= strrchr(u
->id
, '.');
288 if (!strv_find(arg_types
, dot
+1))
298 if (streq(u
->active_state
, "inactive") || u
->following
[0])
304 static int output_units_list(const UnitInfo
*unit_infos
, unsigned c
) {
305 unsigned circle_len
= 0, id_len
, max_id_len
, load_len
, active_len
, sub_len
, job_len
, desc_len
;
307 unsigned n_shown
= 0;
310 max_id_len
= strlen("UNIT");
311 load_len
= strlen("LOAD");
312 active_len
= strlen("ACTIVE");
313 sub_len
= strlen("SUB");
314 job_len
= strlen("JOB");
317 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
318 max_id_len
= MAX(max_id_len
, strlen(u
->id
) + (u
->machine
? strlen(u
->machine
)+1 : 0));
319 load_len
= MAX(load_len
, strlen(u
->load_state
));
320 active_len
= MAX(active_len
, strlen(u
->active_state
));
321 sub_len
= MAX(sub_len
, strlen(u
->sub_state
));
323 if (u
->job_id
!= 0) {
324 job_len
= MAX(job_len
, strlen(u
->job_type
));
328 if (!arg_no_legend
&&
329 (streq(u
->active_state
, "failed") ||
330 STR_IN_SET(u
->load_state
, "error", "not-found", "masked")))
334 if (!arg_full
&& original_stdout_is_tty
) {
337 id_len
= MIN(max_id_len
, 25u);
338 basic_len
= circle_len
+ 5 + id_len
+ 5 + active_len
+ sub_len
;
341 basic_len
+= job_len
+ 1;
343 if (basic_len
< (unsigned) columns()) {
344 unsigned extra_len
, incr
;
345 extra_len
= columns() - basic_len
;
347 /* Either UNIT already got 25, or is fully satisfied.
348 * Grant up to 25 to DESC now. */
349 incr
= MIN(extra_len
, 25u);
353 /* split the remaining space between UNIT and DESC,
354 * but do not give UNIT more than it needs. */
356 incr
= MIN(extra_len
/ 2, max_id_len
- id_len
);
358 desc_len
+= extra_len
- incr
;
364 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
365 _cleanup_free_
char *e
= NULL
, *j
= NULL
;
366 const char *on_loaded
= "", *off_loaded
= "";
367 const char *on_active
= "", *off_active
= "";
368 const char *on_circle
= "", *off_circle
= "";
372 if (!n_shown
&& !arg_no_legend
) {
377 printf("%-*s %-*s %-*s %-*s ",
380 active_len
, "ACTIVE",
384 printf("%-*s ", job_len
, "JOB");
386 if (!arg_full
&& arg_no_pager
)
387 printf("%.*s\n", desc_len
, "DESCRIPTION");
389 printf("%s\n", "DESCRIPTION");
394 if (STR_IN_SET(u
->load_state
, "error", "not-found", "masked") && !arg_plain
) {
395 on_loaded
= ansi_highlight_red();
396 on_circle
= ansi_highlight_yellow();
397 off_loaded
= off_circle
= ansi_normal();
399 } else if (streq(u
->active_state
, "failed") && !arg_plain
) {
400 on_circle
= on_active
= ansi_highlight_red();
401 off_circle
= off_active
= ansi_normal();
406 j
= strjoin(u
->machine
, ":", u
->id
, NULL
);
415 e
= ellipsize(id
, id_len
, 33);
423 printf("%s%s%s ", on_circle
, circle
? draw_special_char(DRAW_BLACK_CIRCLE
) : " ", off_circle
);
425 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
426 on_active
, id_len
, id
, off_active
,
427 on_loaded
, load_len
, u
->load_state
, off_loaded
,
428 on_active
, active_len
, u
->active_state
,
429 sub_len
, u
->sub_state
, off_active
,
430 job_count
? job_len
+ 1 : 0, u
->job_id
? u
->job_type
: "");
433 printf("%.*s\n", desc_len
, u
->description
);
435 printf("%s\n", u
->description
);
438 if (!arg_no_legend
) {
439 const char *on
, *off
;
443 "LOAD = Reflects whether the unit definition was properly loaded.\n"
444 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
445 "SUB = The low-level unit activation state, values depend on unit type.");
446 puts(job_count
? "JOB = Pending job for the unit.\n" : "");
447 on
= ansi_highlight();
450 on
= ansi_highlight_red();
455 printf("%s%u loaded units listed.%s\n"
456 "To show all installed unit files use 'systemctl list-unit-files'.\n",
459 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
460 "To show all installed unit files use 'systemctl list-unit-files'.\n",
467 static int get_unit_list(
471 UnitInfo
**unit_infos
,
473 sd_bus_message
**_reply
) {
475 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
476 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
477 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
486 r
= sd_bus_message_new_method_call(
489 "org.freedesktop.systemd1",
490 "/org/freedesktop/systemd1",
491 "org.freedesktop.systemd1.Manager",
492 "ListUnitsFiltered");
495 return bus_log_create_error(r
);
497 r
= sd_bus_message_append_strv(m
, arg_states
);
499 return bus_log_create_error(r
);
501 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
503 return log_error_errno(r
, "Failed to list units: %s", bus_error_message(&error
, r
));
505 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssssouso)");
507 return bus_log_parse_error(r
);
509 while ((r
= bus_parse_unit_info(reply
, &u
)) > 0) {
512 if (!output_show_unit(&u
, patterns
))
515 if (!GREEDY_REALLOC(*unit_infos
, size
, c
+1))
518 (*unit_infos
)[c
++] = u
;
521 return bus_log_parse_error(r
);
523 r
= sd_bus_message_exit_container(reply
);
525 return bus_log_parse_error(r
);
533 static void message_set_freep(Set
**set
) {
536 while ((m
= set_steal_first(*set
)))
537 sd_bus_message_unref(m
);
542 static int get_unit_list_recursive(
545 UnitInfo
**_unit_infos
,
549 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
550 _cleanup_(message_set_freep
) Set
*replies
;
551 sd_bus_message
*reply
;
559 replies
= set_new(NULL
);
563 c
= get_unit_list(bus
, NULL
, patterns
, &unit_infos
, 0, &reply
);
567 r
= set_put(replies
, reply
);
569 sd_bus_message_unref(reply
);
574 _cleanup_strv_free_
char **machines
= NULL
;
577 r
= sd_get_machine_names(&machines
);
579 return log_error_errno(r
, "Failed to get machine names: %m");
581 STRV_FOREACH(i
, machines
) {
582 _cleanup_bus_flush_close_unref_ sd_bus
*container
= NULL
;
585 r
= sd_bus_open_system_machine(&container
, *i
);
587 log_warning_errno(r
, "Failed to connect to container %s, ignoring: %m", *i
);
591 k
= get_unit_list(container
, *i
, patterns
, &unit_infos
, c
, &reply
);
597 r
= set_put(replies
, reply
);
599 sd_bus_message_unref(reply
);
604 *_machines
= machines
;
609 *_unit_infos
= unit_infos
;
618 static int list_units(sd_bus
*bus
, char **args
) {
619 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
620 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
621 _cleanup_strv_free_
char **machines
= NULL
;
624 pager_open_if_enabled();
626 r
= get_unit_list_recursive(bus
, strv_skip(args
, 1), &unit_infos
, &replies
, &machines
);
630 qsort_safe(unit_infos
, r
, sizeof(UnitInfo
), compare_unit_info
);
631 return output_units_list(unit_infos
, r
);
634 static int get_triggered_units(
639 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
642 r
= sd_bus_get_property_strv(
644 "org.freedesktop.systemd1",
646 "org.freedesktop.systemd1.Unit",
652 log_error("Failed to determine triggers: %s", bus_error_message(&error
, r
));
657 static int get_listening(
659 const char* unit_path
,
662 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
663 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
664 const char *type
, *path
;
667 r
= sd_bus_get_property(
669 "org.freedesktop.systemd1",
671 "org.freedesktop.systemd1.Socket",
677 log_error("Failed to get list of listening sockets: %s", bus_error_message(&error
, r
));
681 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
683 return bus_log_parse_error(r
);
685 while ((r
= sd_bus_message_read(reply
, "(ss)", &type
, &path
)) > 0) {
687 r
= strv_extend(listening
, type
);
691 r
= strv_extend(listening
, path
);
698 return bus_log_parse_error(r
);
700 r
= sd_bus_message_exit_container(reply
);
702 return bus_log_parse_error(r
);
714 /* Note: triggered is a list here, although it almost certainly
715 * will always be one unit. Nevertheless, dbus API allows for multiple
716 * values, so let's follow that. */
719 /* The strv above is shared. free is set only in the first one. */
723 static int socket_info_compare(const struct socket_info
*a
, const struct socket_info
*b
) {
729 if (!a
->machine
&& b
->machine
)
731 if (a
->machine
&& !b
->machine
)
733 if (a
->machine
&& b
->machine
) {
734 o
= strcasecmp(a
->machine
, b
->machine
);
739 o
= strcmp(a
->path
, b
->path
);
741 o
= strcmp(a
->type
, b
->type
);
746 static int output_sockets_list(struct socket_info
*socket_infos
, unsigned cs
) {
747 struct socket_info
*s
;
748 unsigned pathlen
= strlen("LISTEN"),
749 typelen
= strlen("TYPE") * arg_show_types
,
750 socklen
= strlen("UNIT"),
751 servlen
= strlen("ACTIVATES");
752 const char *on
, *off
;
754 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
758 socklen
= MAX(socklen
, strlen(s
->id
));
760 typelen
= MAX(typelen
, strlen(s
->type
));
761 pathlen
= MAX(pathlen
, strlen(s
->path
) + (s
->machine
? strlen(s
->machine
)+1 : 0));
763 STRV_FOREACH(a
, s
->triggered
)
764 tmp
+= strlen(*a
) + 2*(a
!= s
->triggered
);
765 servlen
= MAX(servlen
, tmp
);
770 printf("%-*s %-*.*s%-*s %s\n",
772 typelen
+ arg_show_types
, typelen
+ arg_show_types
, "TYPE ",
776 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
777 _cleanup_free_
char *j
= NULL
;
782 j
= strjoin(s
->machine
, ":", s
->path
, NULL
);
790 printf("%-*s %-*s %-*s",
791 pathlen
, path
, typelen
, s
->type
, socklen
, s
->id
);
794 pathlen
, path
, socklen
, s
->id
);
795 STRV_FOREACH(a
, s
->triggered
)
797 a
== s
->triggered
? "" : ",", *a
);
801 on
= ansi_highlight();
806 on
= ansi_highlight_red();
810 if (!arg_no_legend
) {
811 printf("%s%u sockets listed.%s\n", on
, cs
, off
);
813 printf("Pass --all to see loaded but inactive sockets, too.\n");
819 static int list_sockets(sd_bus
*bus
, char **args
) {
820 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
821 _cleanup_strv_free_
char **machines
= NULL
;
822 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
823 _cleanup_free_
struct socket_info
*socket_infos
= NULL
;
825 struct socket_info
*s
;
830 pager_open_if_enabled();
832 n
= get_unit_list_recursive(bus
, strv_skip(args
, 1), &unit_infos
, &replies
, &machines
);
836 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
837 _cleanup_strv_free_
char **listening
= NULL
, **triggered
= NULL
;
840 if (!endswith(u
->id
, ".socket"))
843 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
847 c
= get_listening(bus
, u
->unit_path
, &listening
);
853 if (!GREEDY_REALLOC(socket_infos
, size
, cs
+ c
)) {
858 for (i
= 0; i
< c
; i
++)
859 socket_infos
[cs
+ i
] = (struct socket_info
) {
860 .machine
= u
->machine
,
862 .type
= listening
[i
*2],
863 .path
= listening
[i
*2 + 1],
864 .triggered
= triggered
,
865 .own_triggered
= i
==0,
868 /* from this point on we will cleanup those socket_infos */
871 listening
= triggered
= NULL
; /* avoid cleanup */
874 qsort_safe(socket_infos
, cs
, sizeof(struct socket_info
),
875 (__compar_fn_t
) socket_info_compare
);
877 output_sockets_list(socket_infos
, cs
);
880 assert(cs
== 0 || socket_infos
);
881 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
884 if (s
->own_triggered
)
885 strv_free(s
->triggered
);
891 static int get_next_elapse(
894 dual_timestamp
*next
) {
896 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
904 r
= sd_bus_get_property_trivial(
906 "org.freedesktop.systemd1",
908 "org.freedesktop.systemd1.Timer",
909 "NextElapseUSecMonotonic",
914 log_error("Failed to get next elapsation time: %s", bus_error_message(&error
, r
));
918 r
= sd_bus_get_property_trivial(
920 "org.freedesktop.systemd1",
922 "org.freedesktop.systemd1.Timer",
923 "NextElapseUSecRealtime",
928 log_error("Failed to get next elapsation time: %s", bus_error_message(&error
, r
));
936 static int get_last_trigger(
941 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
948 r
= sd_bus_get_property_trivial(
950 "org.freedesktop.systemd1",
952 "org.freedesktop.systemd1.Timer",
958 log_error("Failed to get last trigger time: %s", bus_error_message(&error
, r
));
973 static int timer_info_compare(const struct timer_info
*a
, const struct timer_info
*b
) {
979 if (!a
->machine
&& b
->machine
)
981 if (a
->machine
&& !b
->machine
)
983 if (a
->machine
&& b
->machine
) {
984 o
= strcasecmp(a
->machine
, b
->machine
);
989 if (a
->next_elapse
< b
->next_elapse
)
991 if (a
->next_elapse
> b
->next_elapse
)
994 return strcmp(a
->id
, b
->id
);
997 static int output_timers_list(struct timer_info
*timer_infos
, unsigned n
) {
998 struct timer_info
*t
;
1000 nextlen
= strlen("NEXT"),
1001 leftlen
= strlen("LEFT"),
1002 lastlen
= strlen("LAST"),
1003 passedlen
= strlen("PASSED"),
1004 unitlen
= strlen("UNIT"),
1005 activatelen
= strlen("ACTIVATES");
1007 const char *on
, *off
;
1009 assert(timer_infos
|| n
== 0);
1011 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1015 if (t
->next_elapse
> 0) {
1016 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1018 format_timestamp(tstamp
, sizeof(tstamp
), t
->next_elapse
);
1019 nextlen
= MAX(nextlen
, strlen(tstamp
) + 1);
1021 format_timestamp_relative(trel
, sizeof(trel
), t
->next_elapse
);
1022 leftlen
= MAX(leftlen
, strlen(trel
));
1025 if (t
->last_trigger
> 0) {
1026 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1028 format_timestamp(tstamp
, sizeof(tstamp
), t
->last_trigger
);
1029 lastlen
= MAX(lastlen
, strlen(tstamp
) + 1);
1031 format_timestamp_relative(trel
, sizeof(trel
), t
->last_trigger
);
1032 passedlen
= MAX(passedlen
, strlen(trel
));
1035 unitlen
= MAX(unitlen
, strlen(t
->id
) + (t
->machine
? strlen(t
->machine
)+1 : 0));
1037 STRV_FOREACH(a
, t
->triggered
)
1038 ul
+= strlen(*a
) + 2*(a
!= t
->triggered
);
1040 activatelen
= MAX(activatelen
, ul
);
1045 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1049 passedlen
, "PASSED",
1053 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1054 _cleanup_free_
char *j
= NULL
;
1056 char tstamp1
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel1
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1057 char tstamp2
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel2
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1060 format_timestamp(tstamp1
, sizeof(tstamp1
), t
->next_elapse
);
1061 format_timestamp_relative(trel1
, sizeof(trel1
), t
->next_elapse
);
1063 format_timestamp(tstamp2
, sizeof(tstamp2
), t
->last_trigger
);
1064 format_timestamp_relative(trel2
, sizeof(trel2
), t
->last_trigger
);
1067 j
= strjoin(t
->machine
, ":", t
->id
, NULL
);
1074 printf("%-*s %-*s %-*s %-*s %-*s",
1075 nextlen
, tstamp1
, leftlen
, trel1
, lastlen
, tstamp2
, passedlen
, trel2
, unitlen
, unit
);
1077 STRV_FOREACH(a
, t
->triggered
)
1079 a
== t
->triggered
? "" : ",", *a
);
1083 on
= ansi_highlight();
1084 off
= ansi_normal();
1088 on
= ansi_highlight_red();
1089 off
= ansi_normal();
1092 if (!arg_no_legend
) {
1093 printf("%s%u timers listed.%s\n", on
, n
, off
);
1095 printf("Pass --all to see loaded but inactive timers, too.\n");
1101 static usec_t
calc_next_elapse(dual_timestamp
*nw
, dual_timestamp
*next
) {
1107 if (next
->monotonic
!= USEC_INFINITY
&& next
->monotonic
> 0) {
1110 if (next
->monotonic
> nw
->monotonic
)
1111 converted
= nw
->realtime
+ (next
->monotonic
- nw
->monotonic
);
1113 converted
= nw
->realtime
- (nw
->monotonic
- next
->monotonic
);
1115 if (next
->realtime
!= USEC_INFINITY
&& next
->realtime
> 0)
1116 next_elapse
= MIN(converted
, next
->realtime
);
1118 next_elapse
= converted
;
1121 next_elapse
= next
->realtime
;
1126 static int list_timers(sd_bus
*bus
, char **args
) {
1127 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
1128 _cleanup_strv_free_
char **machines
= NULL
;
1129 _cleanup_free_
struct timer_info
*timer_infos
= NULL
;
1130 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
1131 struct timer_info
*t
;
1138 pager_open_if_enabled();
1140 n
= get_unit_list_recursive(bus
, strv_skip(args
, 1), &unit_infos
, &replies
, &machines
);
1144 dual_timestamp_get(&nw
);
1146 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
1147 _cleanup_strv_free_
char **triggered
= NULL
;
1148 dual_timestamp next
= DUAL_TIMESTAMP_NULL
;
1151 if (!endswith(u
->id
, ".timer"))
1154 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
1158 r
= get_next_elapse(bus
, u
->unit_path
, &next
);
1162 get_last_trigger(bus
, u
->unit_path
, &last
);
1164 if (!GREEDY_REALLOC(timer_infos
, size
, c
+1)) {
1169 m
= calc_next_elapse(&nw
, &next
);
1171 timer_infos
[c
++] = (struct timer_info
) {
1172 .machine
= u
->machine
,
1175 .last_trigger
= last
,
1176 .triggered
= triggered
,
1179 triggered
= NULL
; /* avoid cleanup */
1182 qsort_safe(timer_infos
, c
, sizeof(struct timer_info
),
1183 (__compar_fn_t
) timer_info_compare
);
1185 output_timers_list(timer_infos
, c
);
1188 for (t
= timer_infos
; t
< timer_infos
+ c
; t
++)
1189 strv_free(t
->triggered
);
1194 static int compare_unit_file_list(const void *a
, const void *b
) {
1195 const char *d1
, *d2
;
1196 const UnitFileList
*u
= a
, *v
= b
;
1198 d1
= strrchr(u
->path
, '.');
1199 d2
= strrchr(v
->path
, '.');
1204 r
= strcasecmp(d1
, d2
);
1209 return strcasecmp(basename(u
->path
), basename(v
->path
));
1212 static bool output_show_unit_file(const UnitFileList
*u
, char **patterns
) {
1213 if (!strv_fnmatch_or_empty(patterns
, basename(u
->path
), FNM_NOESCAPE
))
1216 if (!strv_isempty(arg_types
)) {
1219 dot
= strrchr(u
->path
, '.');
1223 if (!strv_find(arg_types
, dot
+1))
1227 if (!strv_isempty(arg_states
) &&
1228 !strv_find(arg_states
, unit_file_state_to_string(u
->state
)))
1234 static void output_unit_file_list(const UnitFileList
*units
, unsigned c
) {
1235 unsigned max_id_len
, id_cols
, state_cols
;
1236 const UnitFileList
*u
;
1238 max_id_len
= strlen("UNIT FILE");
1239 state_cols
= strlen("STATE");
1241 for (u
= units
; u
< units
+ c
; u
++) {
1242 max_id_len
= MAX(max_id_len
, strlen(basename(u
->path
)));
1243 state_cols
= MAX(state_cols
, strlen(unit_file_state_to_string(u
->state
)));
1247 unsigned basic_cols
;
1249 id_cols
= MIN(max_id_len
, 25u);
1250 basic_cols
= 1 + id_cols
+ state_cols
;
1251 if (basic_cols
< (unsigned) columns())
1252 id_cols
+= MIN(columns() - basic_cols
, max_id_len
- id_cols
);
1254 id_cols
= max_id_len
;
1257 printf("%-*s %-*s\n",
1258 id_cols
, "UNIT FILE",
1259 state_cols
, "STATE");
1261 for (u
= units
; u
< units
+ c
; u
++) {
1262 _cleanup_free_
char *e
= NULL
;
1263 const char *on
, *off
;
1266 if (IN_SET(u
->state
,
1268 UNIT_FILE_MASKED_RUNTIME
,
1270 UNIT_FILE_INVALID
)) {
1271 on
= ansi_highlight_red();
1272 off
= ansi_normal();
1273 } else if (u
->state
== UNIT_FILE_ENABLED
) {
1274 on
= ansi_highlight_green();
1275 off
= ansi_normal();
1279 id
= basename(u
->path
);
1281 e
= arg_full
? NULL
: ellipsize(id
, id_cols
, 33);
1283 printf("%-*s %s%-*s%s\n",
1284 id_cols
, e
? e
: id
,
1285 on
, state_cols
, unit_file_state_to_string(u
->state
), off
);
1289 printf("\n%u unit files listed.\n", c
);
1292 static int list_unit_files(sd_bus
*bus
, char **args
) {
1293 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1294 _cleanup_free_ UnitFileList
*units
= NULL
;
1302 pager_open_if_enabled();
1310 h
= hashmap_new(&string_hash_ops
);
1314 r
= unit_file_get_list(arg_scope
, arg_root
, h
);
1316 unit_file_list_free(h
);
1317 log_error_errno(r
, "Failed to get unit file list: %m");
1321 n_units
= hashmap_size(h
);
1323 units
= new(UnitFileList
, n_units
);
1324 if (!units
&& n_units
> 0) {
1325 unit_file_list_free(h
);
1329 HASHMAP_FOREACH(u
, h
, i
) {
1330 if (!output_show_unit_file(u
, strv_skip(args
, 1)))
1337 assert(c
<= n_units
);
1340 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1342 r
= sd_bus_call_method(
1344 "org.freedesktop.systemd1",
1345 "/org/freedesktop/systemd1",
1346 "org.freedesktop.systemd1.Manager",
1352 log_error("Failed to list unit files: %s", bus_error_message(&error
, r
));
1356 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
1358 return bus_log_parse_error(r
);
1360 while ((r
= sd_bus_message_read(reply
, "(ss)", &path
, &state
)) > 0) {
1362 if (!GREEDY_REALLOC(units
, size
, c
+ 1))
1365 units
[c
] = (struct UnitFileList
) {
1367 unit_file_state_from_string(state
)
1370 if (output_show_unit_file(&units
[c
], strv_skip(args
, 1)))
1375 return bus_log_parse_error(r
);
1377 r
= sd_bus_message_exit_container(reply
);
1379 return bus_log_parse_error(r
);
1382 qsort_safe(units
, c
, sizeof(UnitFileList
), compare_unit_file_list
);
1383 output_unit_file_list(units
, c
);
1386 for (unit
= units
; unit
< units
+ c
; unit
++)
1393 static int list_dependencies_print(const char *name
, int level
, unsigned int branches
, bool last
) {
1394 _cleanup_free_
char *n
= NULL
;
1395 size_t max_len
= MAX(columns(),20u);
1401 for (i
= level
- 1; i
>= 0; i
--) {
1403 if (len
> max_len
- 3 && !arg_full
) {
1404 printf("%s...\n",max_len
% 2 ? "" : " ");
1407 printf("%s", draw_special_char(branches
& (1 << i
) ? DRAW_TREE_VERTICAL
: DRAW_TREE_SPACE
));
1411 if (len
> max_len
- 3 && !arg_full
) {
1412 printf("%s...\n",max_len
% 2 ? "" : " ");
1416 printf("%s", draw_special_char(last
? DRAW_TREE_RIGHT
: DRAW_TREE_BRANCH
));
1420 printf("%s\n", name
);
1424 n
= ellipsize(name
, max_len
-len
, 100);
1432 static int list_dependencies_get_dependencies(sd_bus
*bus
, const char *name
, char ***deps
) {
1434 static const char *dependencies
[_DEPENDENCY_MAX
] = {
1435 [DEPENDENCY_FORWARD
] = "Requires\0"
1436 "RequiresOverridable\0"
1438 "RequisiteOverridable\0"
1442 [DEPENDENCY_REVERSE
] = "RequiredBy\0"
1443 "RequiredByOverridable\0"
1445 "RequisiteOfOverridable\0"
1449 [DEPENDENCY_AFTER
] = "After\0",
1450 [DEPENDENCY_BEFORE
] = "Before\0",
1453 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1454 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1455 _cleanup_strv_free_
char **ret
= NULL
;
1456 _cleanup_free_
char *path
= NULL
;
1462 assert_cc(ELEMENTSOF(dependencies
) == _DEPENDENCY_MAX
);
1464 path
= unit_dbus_path_from_name(name
);
1468 r
= sd_bus_call_method(
1470 "org.freedesktop.systemd1",
1472 "org.freedesktop.DBus.Properties",
1476 "s", "org.freedesktop.systemd1.Unit");
1478 log_error("Failed to get properties of %s: %s", name
, bus_error_message(&error
, r
));
1482 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
1484 return bus_log_parse_error(r
);
1486 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
1489 r
= sd_bus_message_read(reply
, "s", &prop
);
1491 return bus_log_parse_error(r
);
1493 if (!nulstr_contains(dependencies
[arg_dependency
], prop
)) {
1494 r
= sd_bus_message_skip(reply
, "v");
1496 return bus_log_parse_error(r
);
1499 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, "as");
1501 return bus_log_parse_error(r
);
1503 r
= bus_message_read_strv_extend(reply
, &ret
);
1505 return bus_log_parse_error(r
);
1507 r
= sd_bus_message_exit_container(reply
);
1509 return bus_log_parse_error(r
);
1512 r
= sd_bus_message_exit_container(reply
);
1514 return bus_log_parse_error(r
);
1518 return bus_log_parse_error(r
);
1520 r
= sd_bus_message_exit_container(reply
);
1522 return bus_log_parse_error(r
);
1530 static int list_dependencies_compare(const void *_a
, const void *_b
) {
1531 const char **a
= (const char**) _a
, **b
= (const char**) _b
;
1533 if (unit_name_to_type(*a
) == UNIT_TARGET
&& unit_name_to_type(*b
) != UNIT_TARGET
)
1535 if (unit_name_to_type(*a
) != UNIT_TARGET
&& unit_name_to_type(*b
) == UNIT_TARGET
)
1538 return strcasecmp(*a
, *b
);
1541 static int list_dependencies_one(
1546 unsigned int branches
) {
1548 _cleanup_strv_free_
char **deps
= NULL
;
1556 r
= strv_extend(units
, name
);
1560 r
= list_dependencies_get_dependencies(bus
, name
, &deps
);
1564 qsort_safe(deps
, strv_length(deps
), sizeof (char*), list_dependencies_compare
);
1566 STRV_FOREACH(c
, deps
) {
1567 if (strv_contains(*units
, *c
)) {
1569 r
= list_dependencies_print("...", level
+ 1, (branches
<< 1) | (c
[1] == NULL
? 0 : 1), 1);
1582 state
= check_one_unit(bus
, *c
, "activating\0active\0reloading\0", true);
1583 on
= state
> 0 ? ansi_highlight_green() : ansi_highlight_red();
1584 printf("%s%s%s ", on
, draw_special_char(DRAW_BLACK_CIRCLE
), ansi_normal());
1587 r
= list_dependencies_print(*c
, level
, branches
, c
[1] == NULL
);
1591 if (arg_all
|| unit_name_to_type(*c
) == UNIT_TARGET
) {
1592 r
= list_dependencies_one(bus
, *c
, level
+ 1, units
, (branches
<< 1) | (c
[1] == NULL
? 0 : 1));
1599 strv_remove(*units
, name
);
1604 static int list_dependencies(sd_bus
*bus
, char **args
) {
1605 _cleanup_strv_free_
char **units
= NULL
;
1606 _cleanup_free_
char *unit
= NULL
;
1613 r
= unit_name_mangle(args
[1], UNIT_NAME_NOGLOB
, &unit
);
1615 return log_error_errno(r
, "Failed to mangle unit name: %m");
1619 u
= SPECIAL_DEFAULT_TARGET
;
1621 pager_open_if_enabled();
1625 return list_dependencies_one(bus
, u
, 0, &units
, 0);
1628 struct machine_info
{
1632 char *control_group
;
1633 uint32_t n_failed_units
;
1638 static const struct bus_properties_map machine_info_property_map
[] = {
1639 { "SystemState", "s", NULL
, offsetof(struct machine_info
, state
) },
1640 { "NJobs", "u", NULL
, offsetof(struct machine_info
, n_jobs
) },
1641 { "NFailedUnits", "u", NULL
, offsetof(struct machine_info
, n_failed_units
) },
1642 { "ControlGroup", "s", NULL
, offsetof(struct machine_info
, control_group
) },
1643 { "UserspaceTimestamp", "t", NULL
, offsetof(struct machine_info
, timestamp
) },
1647 static void machine_info_clear(struct machine_info
*info
) {
1651 free(info
->control_group
);
1656 static void free_machines_list(struct machine_info
*machine_infos
, int n
) {
1662 for (i
= 0; i
< n
; i
++)
1663 machine_info_clear(&machine_infos
[i
]);
1665 free(machine_infos
);
1668 static int compare_machine_info(const void *a
, const void *b
) {
1669 const struct machine_info
*u
= a
, *v
= b
;
1671 if (u
->is_host
!= v
->is_host
)
1672 return u
->is_host
> v
->is_host
? -1 : 1;
1674 return strcasecmp(u
->name
, v
->name
);
1677 static int get_machine_properties(sd_bus
*bus
, struct machine_info
*mi
) {
1678 _cleanup_bus_flush_close_unref_ sd_bus
*container
= NULL
;
1684 r
= sd_bus_open_system_machine(&container
, mi
->name
);
1691 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, mi
);
1698 static bool output_show_machine(const char *name
, char **patterns
) {
1699 return strv_fnmatch_or_empty(patterns
, name
, FNM_NOESCAPE
);
1702 static int get_machine_list(
1704 struct machine_info
**_machine_infos
,
1707 struct machine_info
*machine_infos
= NULL
;
1708 _cleanup_strv_free_
char **m
= NULL
;
1709 _cleanup_free_
char *hn
= NULL
;
1714 hn
= gethostname_malloc();
1718 if (output_show_machine(hn
, patterns
)) {
1719 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1))
1722 machine_infos
[c
].is_host
= true;
1723 machine_infos
[c
].name
= hn
;
1726 get_machine_properties(bus
, &machine_infos
[c
]);
1730 r
= sd_get_machine_names(&m
);
1732 return log_error_errno(r
, "Failed to get machine list: %m");
1734 STRV_FOREACH(i
, m
) {
1735 _cleanup_free_
char *class = NULL
;
1737 if (!output_show_machine(*i
, patterns
))
1740 sd_machine_get_class(*i
, &class);
1741 if (!streq_ptr(class, "container"))
1744 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1)) {
1745 free_machines_list(machine_infos
, c
);
1749 machine_infos
[c
].is_host
= false;
1750 machine_infos
[c
].name
= strdup(*i
);
1751 if (!machine_infos
[c
].name
) {
1752 free_machines_list(machine_infos
, c
);
1756 get_machine_properties(NULL
, &machine_infos
[c
]);
1760 *_machine_infos
= machine_infos
;
1764 static void output_machines_list(struct machine_info
*machine_infos
, unsigned n
) {
1765 struct machine_info
*m
;
1768 namelen
= sizeof("NAME") - 1,
1769 statelen
= sizeof("STATE") - 1,
1770 failedlen
= sizeof("FAILED") - 1,
1771 jobslen
= sizeof("JOBS") - 1;
1773 assert(machine_infos
|| n
== 0);
1775 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
1776 namelen
= MAX(namelen
, strlen(m
->name
) + (m
->is_host
? sizeof(" (host)") - 1 : 0));
1777 statelen
= MAX(statelen
, m
->state
? strlen(m
->state
) : 0);
1778 failedlen
= MAX(failedlen
, DECIMAL_STR_WIDTH(m
->n_failed_units
));
1779 jobslen
= MAX(jobslen
, DECIMAL_STR_WIDTH(m
->n_jobs
));
1781 if (!arg_plain
&& !streq_ptr(m
->state
, "running"))
1785 if (!arg_no_legend
) {
1789 printf("%-*s %-*s %-*s %-*s\n",
1792 failedlen
, "FAILED",
1796 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
1797 const char *on_state
= "", *off_state
= "";
1798 const char *on_failed
= "", *off_failed
= "";
1799 bool circle
= false;
1801 if (streq_ptr(m
->state
, "degraded")) {
1802 on_state
= ansi_highlight_red();
1803 off_state
= ansi_normal();
1805 } else if (!streq_ptr(m
->state
, "running")) {
1806 on_state
= ansi_highlight_yellow();
1807 off_state
= ansi_normal();
1811 if (m
->n_failed_units
> 0) {
1812 on_failed
= ansi_highlight_red();
1813 off_failed
= ansi_normal();
1815 on_failed
= off_failed
= "";
1818 printf("%s%s%s ", on_state
, circle
? draw_special_char(DRAW_BLACK_CIRCLE
) : " ", off_state
);
1821 printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
1822 (int) (namelen
- (sizeof(" (host)")-1)), strna(m
->name
),
1823 on_state
, statelen
, strna(m
->state
), off_state
,
1824 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
1825 jobslen
, m
->n_jobs
);
1827 printf("%-*s %s%-*s%s %s%*u%s %*u\n",
1828 namelen
, strna(m
->name
),
1829 on_state
, statelen
, strna(m
->state
), off_state
,
1830 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
1831 jobslen
, m
->n_jobs
);
1835 printf("\n%u machines listed.\n", n
);
1838 static int list_machines(sd_bus
*bus
, char **args
) {
1839 struct machine_info
*machine_infos
= NULL
;
1844 if (geteuid() != 0) {
1845 log_error("Must be root.");
1849 pager_open_if_enabled();
1851 r
= get_machine_list(bus
, &machine_infos
, strv_skip(args
, 1));
1855 qsort_safe(machine_infos
, r
, sizeof(struct machine_info
), compare_machine_info
);
1856 output_machines_list(machine_infos
, r
);
1857 free_machines_list(machine_infos
, r
);
1862 static int get_default(sd_bus
*bus
, char **args
) {
1863 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1864 _cleanup_free_
char *_path
= NULL
;
1868 if (!bus
|| avoid_bus()) {
1869 r
= unit_file_get_default(arg_scope
, arg_root
, &_path
);
1871 return log_error_errno(r
, "Failed to get default target: %m");
1875 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1877 r
= sd_bus_call_method(
1879 "org.freedesktop.systemd1",
1880 "/org/freedesktop/systemd1",
1881 "org.freedesktop.systemd1.Manager",
1887 log_error("Failed to get default target: %s", bus_error_message(&error
, -r
));
1891 r
= sd_bus_message_read(reply
, "s", &path
);
1893 return bus_log_parse_error(r
);
1897 printf("%s\n", path
);
1902 static void dump_unit_file_changes(const UnitFileChange
*changes
, unsigned n_changes
) {
1905 assert(changes
|| n_changes
== 0);
1907 for (i
= 0; i
< n_changes
; i
++) {
1908 if (changes
[i
].type
== UNIT_FILE_SYMLINK
)
1909 log_info("Created symlink from %s to %s.", changes
[i
].path
, changes
[i
].source
);
1911 log_info("Removed symlink %s.", changes
[i
].path
);
1915 static int set_default(sd_bus
*bus
, char **args
) {
1916 _cleanup_free_
char *unit
= NULL
;
1917 UnitFileChange
*changes
= NULL
;
1918 unsigned n_changes
= 0;
1921 r
= unit_name_mangle_with_suffix(args
[1], UNIT_NAME_NOGLOB
, ".target", &unit
);
1923 return log_error_errno(r
, "Failed to mangle unit name: %m");
1925 if (!bus
|| avoid_bus()) {
1926 r
= unit_file_set_default(arg_scope
, arg_root
, unit
, true, &changes
, &n_changes
);
1928 return log_error_errno(r
, "Failed to set default target: %m");
1931 dump_unit_file_changes(changes
, n_changes
);
1935 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1936 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1938 polkit_agent_open_if_enabled();
1940 r
= sd_bus_call_method(
1942 "org.freedesktop.systemd1",
1943 "/org/freedesktop/systemd1",
1944 "org.freedesktop.systemd1.Manager",
1950 log_error("Failed to set default target: %s", bus_error_message(&error
, -r
));
1954 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, NULL
, NULL
);
1958 /* Try to reload if enabled */
1960 r
= daemon_reload(bus
, args
);
1965 unit_file_changes_free(changes
, n_changes
);
1972 const char *name
, *type
, *state
;
1975 static void output_jobs_list(const struct job_info
* jobs
, unsigned n
, bool skipped
) {
1976 unsigned id_len
, unit_len
, type_len
, state_len
;
1977 const struct job_info
*j
;
1978 const char *on
, *off
;
1979 bool shorten
= false;
1981 assert(n
== 0 || jobs
);
1984 if (!arg_no_legend
) {
1985 on
= ansi_highlight_green();
1986 off
= ansi_normal();
1988 printf("%sNo jobs %s.%s\n", on
, skipped
? "listed" : "running", off
);
1993 pager_open_if_enabled();
1995 id_len
= strlen("JOB");
1996 unit_len
= strlen("UNIT");
1997 type_len
= strlen("TYPE");
1998 state_len
= strlen("STATE");
2000 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2001 uint32_t id
= j
->id
;
2002 assert(j
->name
&& j
->type
&& j
->state
);
2004 id_len
= MAX(id_len
, DECIMAL_STR_WIDTH(id
));
2005 unit_len
= MAX(unit_len
, strlen(j
->name
));
2006 type_len
= MAX(type_len
, strlen(j
->type
));
2007 state_len
= MAX(state_len
, strlen(j
->state
));
2010 if (!arg_full
&& id_len
+ 1 + unit_len
+ type_len
+ 1 + state_len
> columns()) {
2011 unit_len
= MAX(33u, columns() - id_len
- type_len
- state_len
- 3);
2016 printf("%*s %-*s %-*s %-*s\n",
2020 state_len
, "STATE");
2022 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2023 _cleanup_free_
char *e
= NULL
;
2025 if (streq(j
->state
, "running")) {
2026 on
= ansi_highlight();
2027 off
= ansi_normal();
2031 e
= shorten
? ellipsize(j
->name
, unit_len
, 33) : NULL
;
2032 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2034 on
, unit_len
, e
? e
: j
->name
, off
,
2036 on
, state_len
, j
->state
, off
);
2039 if (!arg_no_legend
) {
2040 on
= ansi_highlight();
2041 off
= ansi_normal();
2043 printf("\n%s%u jobs listed%s.\n", on
, n
, off
);
2047 static bool output_show_job(struct job_info
*job
, char **patterns
) {
2048 return strv_fnmatch_or_empty(patterns
, job
->name
, FNM_NOESCAPE
);
2051 static int list_jobs(sd_bus
*bus
, char **args
) {
2052 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2053 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2054 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2055 _cleanup_free_
struct job_info
*jobs
= NULL
;
2060 bool skipped
= false;
2062 r
= sd_bus_call_method(
2064 "org.freedesktop.systemd1",
2065 "/org/freedesktop/systemd1",
2066 "org.freedesktop.systemd1.Manager",
2072 log_error("Failed to list jobs: %s", bus_error_message(&error
, r
));
2076 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2078 return bus_log_parse_error(r
);
2080 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0) {
2081 struct job_info job
= { id
, name
, type
, state
};
2083 if (!output_show_job(&job
, strv_skip(args
, 1))) {
2088 if (!GREEDY_REALLOC(jobs
, size
, c
+ 1))
2094 return bus_log_parse_error(r
);
2096 r
= sd_bus_message_exit_container(reply
);
2098 return bus_log_parse_error(r
);
2100 output_jobs_list(jobs
, c
, skipped
);
2104 static int cancel_job(sd_bus
*bus
, char **args
) {
2110 if (strv_length(args
) <= 1)
2111 return daemon_reload(bus
, args
);
2113 polkit_agent_open_if_enabled();
2115 STRV_FOREACH(name
, args
+1) {
2116 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2120 q
= safe_atou32(*name
, &id
);
2122 return log_error_errno(q
, "Failed to parse job id \"%s\": %m", *name
);
2124 q
= sd_bus_call_method(
2126 "org.freedesktop.systemd1",
2127 "/org/freedesktop/systemd1",
2128 "org.freedesktop.systemd1.Manager",
2134 log_error("Failed to cancel job %"PRIu32
": %s", id
, bus_error_message(&error
, q
));
2143 static int need_daemon_reload(sd_bus
*bus
, const char *unit
) {
2144 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2148 /* We ignore all errors here, since this is used to show a
2151 /* We don't use unit_dbus_path_from_name() directly since we
2152 * don't want to load the unit if it isn't loaded. */
2154 r
= sd_bus_call_method(
2156 "org.freedesktop.systemd1",
2157 "/org/freedesktop/systemd1",
2158 "org.freedesktop.systemd1.Manager",
2166 r
= sd_bus_message_read(reply
, "o", &path
);
2170 r
= sd_bus_get_property_trivial(
2172 "org.freedesktop.systemd1",
2174 "org.freedesktop.systemd1.Unit",
2184 static void warn_unit_file_changed(const char *name
) {
2185 log_warning("%sWarning:%s %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
2186 ansi_highlight_red(),
2189 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user");
2192 static int unit_file_find_path(LookupPaths
*lp
, const char *unit_name
, char **unit_path
) {
2199 STRV_FOREACH(p
, lp
->unit_path
) {
2200 _cleanup_free_
char *path
;
2202 path
= path_join(arg_root
, *p
, unit_name
);
2206 if (access(path
, F_OK
) == 0) {
2216 static int unit_find_paths(
2218 const char *unit_name
,
2219 bool avoid_bus_cache
,
2221 char **fragment_path
,
2222 char ***dropin_paths
) {
2224 _cleanup_free_
char *path
= NULL
;
2225 _cleanup_strv_free_
char **dropins
= NULL
;
2229 * Finds where the unit is defined on disk. Returns 0 if the unit
2230 * is not found. Returns 1 if it is found, and sets
2231 * - the path to the unit in *path, if it exists on disk,
2232 * - and a strv of existing drop-ins in *dropins,
2233 * if the arg is not NULL and any dropins were found.
2237 assert(fragment_path
);
2240 if (!avoid_bus_cache
&& !unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
2241 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2242 _cleanup_bus_message_unref_ sd_bus_message
*unit_load_error
= NULL
;
2243 _cleanup_free_
char *unit
= NULL
;
2244 char *unit_load_error_name
, *unit_load_error_message
;
2246 unit
= unit_dbus_path_from_name(unit_name
);
2250 if (need_daemon_reload(bus
, unit_name
) > 0)
2251 warn_unit_file_changed(unit_name
);
2253 r
= sd_bus_get_property(
2255 "org.freedesktop.systemd1",
2257 "org.freedesktop.systemd1.Unit",
2263 return log_error_errno(r
, "Failed to get LoadError: %s", bus_error_message(&error
, r
));
2265 r
= sd_bus_message_read(
2268 &unit_load_error_name
,
2269 &unit_load_error_message
);
2271 return bus_log_parse_error(r
);
2273 if (!isempty(unit_load_error_name
)) {
2274 log_error("Unit %s is not loaded: %s", unit_name
, unit_load_error_message
);
2278 r
= sd_bus_get_property_string(
2280 "org.freedesktop.systemd1",
2282 "org.freedesktop.systemd1.Unit",
2287 return log_error_errno(r
, "Failed to get FragmentPath: %s", bus_error_message(&error
, r
));
2290 r
= sd_bus_get_property_strv(
2292 "org.freedesktop.systemd1",
2294 "org.freedesktop.systemd1.Unit",
2299 return log_error_errno(r
, "Failed to get DropInPaths: %s", bus_error_message(&error
, r
));
2302 _cleanup_set_free_ Set
*names
;
2304 names
= set_new(NULL
);
2308 r
= set_put(names
, unit_name
);
2310 return log_error_errno(r
, "Failed to add unit name: %m");
2312 r
= unit_file_find_path(lp
, unit_name
, &path
);
2317 _cleanup_free_
char *template = NULL
;
2319 r
= unit_name_template(unit_name
, &template);
2320 if (r
< 0 && r
!= -EINVAL
)
2321 return log_error_errno(r
, "Failed to determine template name: %m");
2323 r
= unit_file_find_path(lp
, template, &path
);
2330 r
= unit_file_find_dropin_paths(lp
->unit_path
, NULL
, names
, &dropins
);
2338 if (!isempty(path
)) {
2339 *fragment_path
= path
;
2344 if (dropin_paths
&& !strv_isempty(dropins
)) {
2345 *dropin_paths
= dropins
;
2351 log_error("No files found for %s.", unit_name
);
2356 static int check_one_unit(sd_bus
*bus
, const char *name
, const char *good_states
, bool quiet
) {
2357 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2358 _cleanup_free_
char *n
= NULL
, *state
= NULL
;
2364 r
= unit_name_mangle(name
, UNIT_NAME_NOGLOB
, &n
);
2366 return log_error_errno(r
, "Failed to mangle unit name: %m");
2368 /* We don't use unit_dbus_path_from_name() directly since we
2369 * don't want to load the unit if it isn't loaded. */
2371 r
= sd_bus_call_method(
2373 "org.freedesktop.systemd1",
2374 "/org/freedesktop/systemd1",
2375 "org.freedesktop.systemd1.Manager",
2386 r
= sd_bus_message_read(reply
, "o", &path
);
2388 return bus_log_parse_error(r
);
2390 r
= sd_bus_get_property_string(
2392 "org.freedesktop.systemd1",
2394 "org.freedesktop.systemd1.Unit",
2407 return nulstr_contains(good_states
, state
);
2410 static int check_triggering_units(
2414 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2415 _cleanup_free_
char *path
= NULL
, *n
= NULL
, *state
= NULL
;
2416 _cleanup_strv_free_
char **triggered_by
= NULL
;
2417 bool print_warning_label
= true;
2421 r
= unit_name_mangle(name
, UNIT_NAME_NOGLOB
, &n
);
2423 return log_error_errno(r
, "Failed to mangle unit name: %m");
2425 path
= unit_dbus_path_from_name(n
);
2429 r
= sd_bus_get_property_string(
2431 "org.freedesktop.systemd1",
2433 "org.freedesktop.systemd1.Unit",
2438 log_error("Failed to get load state of %s: %s", n
, bus_error_message(&error
, r
));
2442 if (streq(state
, "masked"))
2445 r
= sd_bus_get_property_strv(
2447 "org.freedesktop.systemd1",
2449 "org.freedesktop.systemd1.Unit",
2454 log_error("Failed to get triggered by array of %s: %s", n
, bus_error_message(&error
, r
));
2458 STRV_FOREACH(i
, triggered_by
) {
2459 r
= check_one_unit(bus
, *i
, "active\0reloading\0", true);
2461 return log_error_errno(r
, "Failed to check unit: %m");
2466 if (print_warning_label
) {
2467 log_warning("Warning: Stopping %s, but it can still be activated by:", n
);
2468 print_warning_label
= false;
2471 log_warning(" %s", *i
);
2477 static const struct {
2480 } unit_actions
[] = {
2481 { "start", "StartUnit" },
2482 { "stop", "StopUnit" },
2483 { "condstop", "StopUnit" },
2484 { "reload", "ReloadUnit" },
2485 { "restart", "RestartUnit" },
2486 { "try-restart", "TryRestartUnit" },
2487 { "condrestart", "TryRestartUnit" },
2488 { "reload-or-restart", "ReloadOrRestartUnit" },
2489 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2490 { "condreload", "ReloadOrTryRestartUnit" },
2491 { "force-reload", "ReloadOrTryRestartUnit" }
2494 static const char *verb_to_method(const char *verb
) {
2497 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2498 if (streq_ptr(unit_actions
[i
].verb
, verb
))
2499 return unit_actions
[i
].method
;
2504 static const char *method_to_verb(const char *method
) {
2507 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2508 if (streq_ptr(unit_actions
[i
].method
, method
))
2509 return unit_actions
[i
].verb
;
2514 static int start_unit_one(
2519 sd_bus_error
*error
,
2520 BusWaitForJobs
*w
) {
2522 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2531 log_debug("Calling manager for %s on %s, %s", method
, name
, mode
);
2533 r
= sd_bus_call_method(
2535 "org.freedesktop.systemd1",
2536 "/org/freedesktop/systemd1",
2537 "org.freedesktop.systemd1.Manager",
2545 if (r
== -ENOENT
&& arg_action
!= ACTION_SYSTEMCTL
)
2546 /* There's always a fallback possible for
2547 * legacy actions. */
2548 return -EADDRNOTAVAIL
;
2550 verb
= method_to_verb(method
);
2552 log_error("Failed to %s %s: %s", verb
, name
, bus_error_message(error
, r
));
2556 r
= sd_bus_message_read(reply
, "o", &path
);
2558 return bus_log_parse_error(r
);
2560 if (need_daemon_reload(bus
, name
) > 0)
2561 warn_unit_file_changed(name
);
2564 log_debug("Adding %s to the set", path
);
2565 r
= bus_wait_for_jobs_add(w
, path
);
2573 static int expand_names(sd_bus
*bus
, char **names
, const char* suffix
, char ***ret
) {
2575 _cleanup_strv_free_
char **mangled
= NULL
, **globs
= NULL
;
2579 STRV_FOREACH(name
, names
) {
2583 r
= unit_name_mangle_with_suffix(*name
, UNIT_NAME_GLOB
, suffix
, &t
);
2585 r
= unit_name_mangle(*name
, UNIT_NAME_GLOB
, &t
);
2587 return log_error_errno(r
, "Failed to mangle name: %m");
2589 if (string_is_glob(t
))
2590 r
= strv_consume(&globs
, t
);
2592 r
= strv_consume(&mangled
, t
);
2597 /* Query the manager only if any of the names are a glob, since
2598 * this is fairly expensive */
2599 if (!strv_isempty(globs
)) {
2600 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2601 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
2604 return log_error_errno(EOPNOTSUPP
, "Unit name globbing without bus is not implemented.");
2606 r
= get_unit_list(bus
, NULL
, globs
, &unit_infos
, 0, &reply
);
2610 for (i
= 0; i
< r
; i
++)
2611 if (strv_extend(&mangled
, unit_infos
[i
].id
) < 0)
2616 mangled
= NULL
; /* do not free */
2621 static const struct {
2625 } action_table
[_ACTION_MAX
] = {
2626 [ACTION_HALT
] = { SPECIAL_HALT_TARGET
, "halt", "replace-irreversibly" },
2627 [ACTION_POWEROFF
] = { SPECIAL_POWEROFF_TARGET
, "poweroff", "replace-irreversibly" },
2628 [ACTION_REBOOT
] = { SPECIAL_REBOOT_TARGET
, "reboot", "replace-irreversibly" },
2629 [ACTION_KEXEC
] = { SPECIAL_KEXEC_TARGET
, "kexec", "replace-irreversibly" },
2630 [ACTION_RUNLEVEL2
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2631 [ACTION_RUNLEVEL3
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2632 [ACTION_RUNLEVEL4
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2633 [ACTION_RUNLEVEL5
] = { SPECIAL_GRAPHICAL_TARGET
, NULL
, "isolate" },
2634 [ACTION_RESCUE
] = { SPECIAL_RESCUE_TARGET
, "rescue", "isolate" },
2635 [ACTION_EMERGENCY
] = { SPECIAL_EMERGENCY_TARGET
, "emergency", "isolate" },
2636 [ACTION_DEFAULT
] = { SPECIAL_DEFAULT_TARGET
, "default", "isolate" },
2637 [ACTION_EXIT
] = { SPECIAL_EXIT_TARGET
, "exit", "replace-irreversibly" },
2638 [ACTION_SUSPEND
] = { SPECIAL_SUSPEND_TARGET
, "suspend", "replace-irreversibly" },
2639 [ACTION_HIBERNATE
] = { SPECIAL_HIBERNATE_TARGET
, "hibernate", "replace-irreversibly" },
2640 [ACTION_HYBRID_SLEEP
] = { SPECIAL_HYBRID_SLEEP_TARGET
, "hybrid-sleep", "replace-irreversibly" },
2643 static enum action
verb_to_action(const char *verb
) {
2646 for (i
= _ACTION_INVALID
; i
< _ACTION_MAX
; i
++)
2647 if (streq_ptr(action_table
[i
].verb
, verb
))
2650 return _ACTION_INVALID
;
2653 static int start_unit(sd_bus
*bus
, char **args
) {
2654 _cleanup_(bus_wait_for_jobs_freep
) BusWaitForJobs
*w
= NULL
;
2655 const char *method
, *mode
, *one_name
, *suffix
= NULL
;
2656 _cleanup_strv_free_
char **names
= NULL
;
2662 ask_password_agent_open_if_enabled();
2663 polkit_agent_open_if_enabled();
2665 if (arg_action
== ACTION_SYSTEMCTL
) {
2667 method
= verb_to_method(args
[0]);
2668 action
= verb_to_action(args
[0]);
2670 if (streq(args
[0], "isolate")) {
2674 mode
= action_table
[action
].mode
?: arg_job_mode
;
2676 one_name
= action_table
[action
].target
;
2678 assert(arg_action
< ELEMENTSOF(action_table
));
2679 assert(action_table
[arg_action
].target
);
2681 method
= "StartUnit";
2683 mode
= action_table
[arg_action
].mode
;
2684 one_name
= action_table
[arg_action
].target
;
2688 names
= strv_new(one_name
, NULL
);
2690 r
= expand_names(bus
, args
+ 1, suffix
, &names
);
2692 log_error_errno(r
, "Failed to expand names: %m");
2695 if (!arg_no_block
) {
2696 r
= bus_wait_for_jobs_new(bus
, &w
);
2698 return log_error_errno(r
, "Could not watch jobs: %m");
2701 STRV_FOREACH(name
, names
) {
2702 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2705 q
= start_unit_one(bus
, method
, *name
, mode
, &error
, w
);
2706 if (r
>= 0 && q
< 0)
2707 r
= translate_bus_error_to_exit_status(q
, &error
);
2710 if (!arg_no_block
) {
2713 q
= bus_wait_for_jobs(w
, arg_quiet
);
2717 /* When stopping units, warn if they can still be triggered by
2718 * another active unit (socket, path, timer) */
2719 if (!arg_quiet
&& streq(method
, "StopUnit"))
2720 STRV_FOREACH(name
, names
)
2721 check_triggering_units(bus
, *name
);
2727 static int logind_set_wall_message(sd_bus
*bus
) {
2729 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2730 _cleanup_free_
char *m
= NULL
;
2735 m
= strv_join(arg_wall
, " ");
2739 r
= sd_bus_call_method(
2741 "org.freedesktop.login1",
2742 "/org/freedesktop/login1",
2743 "org.freedesktop.login1.Manager",
2752 return log_warning_errno(r
, "Failed to set wall message, ignoring: %s", bus_error_message(&error
, r
));
2758 /* Ask systemd-logind, which might grant access to unprivileged users
2759 * through PolicyKit */
2760 static int logind_reboot(sd_bus
*bus
, enum action a
) {
2762 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2763 const char *method
, *description
;
2769 polkit_agent_open_if_enabled();
2771 (void) logind_set_wall_message(bus
);
2777 description
= "reboot system";
2780 case ACTION_POWEROFF
:
2781 method
= "PowerOff";
2782 description
= "power off system";
2785 case ACTION_SUSPEND
:
2787 description
= "suspend system";
2790 case ACTION_HIBERNATE
:
2791 method
= "Hibernate";
2792 description
= "hibernate system";
2795 case ACTION_HYBRID_SLEEP
:
2796 method
= "HybridSleep";
2797 description
= "put system into hybrid sleep";
2804 r
= sd_bus_call_method(
2806 "org.freedesktop.login1",
2807 "/org/freedesktop/login1",
2808 "org.freedesktop.login1.Manager",
2812 "b", arg_ask_password
);
2814 log_error("Failed to %s via logind: %s", description
, bus_error_message(&error
, r
));
2822 static int logind_check_inhibitors(sd_bus
*bus
, enum action a
) {
2824 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2825 _cleanup_strv_free_
char **sessions
= NULL
;
2826 const char *what
, *who
, *why
, *mode
;
2835 if (arg_ignore_inhibitors
|| arg_force
> 0)
2847 r
= sd_bus_call_method(
2849 "org.freedesktop.login1",
2850 "/org/freedesktop/login1",
2851 "org.freedesktop.login1.Manager",
2857 /* If logind is not around, then there are no inhibitors... */
2860 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssuu)");
2862 return bus_log_parse_error(r
);
2864 while ((r
= sd_bus_message_read(reply
, "(ssssuu)", &what
, &who
, &why
, &mode
, &uid
, &pid
)) > 0) {
2865 _cleanup_free_
char *comm
= NULL
, *user
= NULL
;
2866 _cleanup_strv_free_
char **sv
= NULL
;
2868 if (!streq(mode
, "block"))
2871 sv
= strv_split(what
, ":");
2875 if ((pid_t
) pid
< 0)
2876 return log_error_errno(ERANGE
, "Bad PID %"PRIu32
": %m", pid
);
2878 if (!strv_contains(sv
,
2883 ACTION_KEXEC
) ? "shutdown" : "sleep"))
2886 get_process_comm(pid
, &comm
);
2887 user
= uid_to_name(uid
);
2889 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT
" \"%s\", user %s), reason is \"%s\".",
2890 who
, (pid_t
) pid
, strna(comm
), strna(user
), why
);
2895 return bus_log_parse_error(r
);
2897 r
= sd_bus_message_exit_container(reply
);
2899 return bus_log_parse_error(r
);
2901 /* Check for current sessions */
2902 sd_get_sessions(&sessions
);
2903 STRV_FOREACH(s
, sessions
) {
2904 _cleanup_free_
char *type
= NULL
, *tty
= NULL
, *seat
= NULL
, *user
= NULL
, *service
= NULL
, *class = NULL
;
2906 if (sd_session_get_uid(*s
, &uid
) < 0 || uid
== getuid())
2909 if (sd_session_get_class(*s
, &class) < 0 || !streq(class, "user"))
2912 if (sd_session_get_type(*s
, &type
) < 0 || (!streq(type
, "x11") && !streq(type
, "tty")))
2915 sd_session_get_tty(*s
, &tty
);
2916 sd_session_get_seat(*s
, &seat
);
2917 sd_session_get_service(*s
, &service
);
2918 user
= uid_to_name(uid
);
2920 log_warning("User %s is logged in on %s.", strna(user
), isempty(tty
) ? (isempty(seat
) ? strna(service
) : seat
) : tty
);
2927 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2928 action_table
[a
].verb
);
2936 static int prepare_firmware_setup(sd_bus
*bus
) {
2938 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2942 if (!arg_firmware_setup
)
2945 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
2947 r
= efi_set_reboot_to_firmware(true);
2949 log_debug_errno(r
, "Cannot indicate to EFI to boot into setup mode, will retry via logind: %m");
2955 r
= sd_bus_call_method(
2957 "org.freedesktop.login1",
2958 "/org/freedesktop/login1",
2959 "org.freedesktop.login1.Manager",
2960 "SetRebootToFirmwareSetup",
2965 log_error("Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error
, r
));
2971 log_error("Cannot remotely indicate to EFI to boot into setup mode.");
2976 static int start_special(sd_bus
*bus
, char **args
) {
2977 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2983 a
= verb_to_action(args
[0]);
2985 r
= logind_check_inhibitors(bus
, a
);
2989 if (arg_force
>= 2 && geteuid() != 0) {
2990 log_error("Must be root.");
2994 r
= prepare_firmware_setup(bus
);
2998 if (a
== ACTION_REBOOT
&& args
[1]) {
2999 r
= update_reboot_param_file(args
[1]);
3002 } else if (a
== ACTION_EXIT
&& strv_length(args
) > 1) {
3003 /* If the exit code is not given on the command line, don't
3004 * reset it to zero: just keep it as it might have been set
3008 r
= safe_atou8(args
[1], &code
);
3010 log_error("Invalid exit code.");
3014 r
= sd_bus_call_method(
3016 "org.freedesktop.systemd1",
3017 "/org/freedesktop/systemd1",
3018 "org.freedesktop.systemd1.Manager",
3024 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
3029 if (arg_force
>= 2 &&
3036 if (arg_force
>= 1 &&
3043 return daemon_reload(bus
, args
);
3045 /* first try logind, to allow authentication with polkit */
3046 if (geteuid() != 0 &&
3052 ACTION_HYBRID_SLEEP
)) {
3053 r
= logind_reboot(bus
, a
);
3056 if (IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
3057 /* requested operation is not supported or already in progress */
3059 /* on all other errors, try low-level operation */
3062 return start_unit(bus
, args
);
3065 static int check_unit_generic(sd_bus
*bus
, int code
, const char *good_states
, char **args
) {
3066 _cleanup_strv_free_
char **names
= NULL
;
3073 r
= expand_names(bus
, args
, NULL
, &names
);
3075 return log_error_errno(r
, "Failed to expand names: %m");
3077 STRV_FOREACH(name
, names
) {
3080 state
= check_one_unit(bus
, *name
, good_states
, arg_quiet
);
3090 static int check_unit_active(sd_bus
*bus
, char **args
) {
3091 /* According to LSB: 3, "program is not running" */
3092 return check_unit_generic(bus
, 3, "active\0reloading\0", args
+ 1);
3095 static int check_unit_failed(sd_bus
*bus
, char **args
) {
3096 return check_unit_generic(bus
, 1, "failed\0", args
+ 1);
3099 static int kill_unit(sd_bus
*bus
, char **args
) {
3100 _cleanup_strv_free_
char **names
= NULL
;
3101 char *kill_who
= NULL
, **name
;
3107 polkit_agent_open_if_enabled();
3110 arg_kill_who
= "all";
3112 /* --fail was specified */
3113 if (streq(arg_job_mode
, "fail"))
3114 kill_who
= strjoina(arg_kill_who
, "-fail", NULL
);
3116 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
3118 log_error_errno(r
, "Failed to expand names: %m");
3120 STRV_FOREACH(name
, names
) {
3121 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
3123 q
= sd_bus_call_method(
3125 "org.freedesktop.systemd1",
3126 "/org/freedesktop/systemd1",
3127 "org.freedesktop.systemd1.Manager",
3131 "ssi", *names
, kill_who
? kill_who
: arg_kill_who
, arg_signal
);
3133 log_error("Failed to kill unit %s: %s", *names
, bus_error_message(&error
, q
));
3142 typedef struct ExecStatusInfo
{
3150 usec_t start_timestamp
;
3151 usec_t exit_timestamp
;
3156 LIST_FIELDS(struct ExecStatusInfo
, exec
);
3159 static void exec_status_info_free(ExecStatusInfo
*i
) {
3168 static int exec_status_info_deserialize(sd_bus_message
*m
, ExecStatusInfo
*i
) {
3169 uint64_t start_timestamp
, exit_timestamp
, start_timestamp_monotonic
, exit_timestamp_monotonic
;
3172 int32_t code
, status
;
3178 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_STRUCT
, "sasbttttuii");
3180 return bus_log_parse_error(r
);
3184 r
= sd_bus_message_read(m
, "s", &path
);
3186 return bus_log_parse_error(r
);
3188 i
->path
= strdup(path
);
3192 r
= sd_bus_message_read_strv(m
, &i
->argv
);
3194 return bus_log_parse_error(r
);
3196 r
= sd_bus_message_read(m
,
3199 &start_timestamp
, &start_timestamp_monotonic
,
3200 &exit_timestamp
, &exit_timestamp_monotonic
,
3204 return bus_log_parse_error(r
);
3207 i
->start_timestamp
= (usec_t
) start_timestamp
;
3208 i
->exit_timestamp
= (usec_t
) exit_timestamp
;
3209 i
->pid
= (pid_t
) pid
;
3213 r
= sd_bus_message_exit_container(m
);
3215 return bus_log_parse_error(r
);
3220 typedef struct UnitStatusInfo
{
3222 const char *load_state
;
3223 const char *active_state
;
3224 const char *sub_state
;
3225 const char *unit_file_state
;
3226 const char *unit_file_preset
;
3228 const char *description
;
3229 const char *following
;
3231 char **documentation
;
3233 const char *fragment_path
;
3234 const char *source_path
;
3235 const char *control_group
;
3237 char **dropin_paths
;
3239 const char *load_error
;
3242 usec_t inactive_exit_timestamp
;
3243 usec_t inactive_exit_timestamp_monotonic
;
3244 usec_t active_enter_timestamp
;
3245 usec_t active_exit_timestamp
;
3246 usec_t inactive_enter_timestamp
;
3248 bool need_daemon_reload
;
3253 const char *status_text
;
3254 const char *pid_file
;
3258 usec_t start_timestamp
;
3259 usec_t exit_timestamp
;
3261 int exit_code
, exit_status
;
3263 usec_t condition_timestamp
;
3264 bool condition_result
;
3265 bool failed_condition_trigger
;
3266 bool failed_condition_negate
;
3267 const char *failed_condition
;
3268 const char *failed_condition_parameter
;
3270 usec_t assert_timestamp
;
3272 bool failed_assert_trigger
;
3273 bool failed_assert_negate
;
3274 const char *failed_assert
;
3275 const char *failed_assert_parameter
;
3278 unsigned n_accepted
;
3279 unsigned n_connections
;
3282 /* Pairs of type, path */
3286 const char *sysfs_path
;
3288 /* Mount, Automount */
3295 uint64_t memory_current
;
3296 uint64_t memory_limit
;
3297 uint64_t cpu_usage_nsec
;
3298 uint64_t tasks_current
;
3301 LIST_HEAD(ExecStatusInfo
, exec
);
3304 static void print_status_info(
3309 const char *active_on
, *active_off
, *on
, *off
, *ss
;
3311 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], *s1
;
3312 char since2
[FORMAT_TIMESTAMP_MAX
], *s2
;
3318 /* This shows pretty information about a unit. See
3319 * print_property() for a low-level property printer */
3321 if (streq_ptr(i
->active_state
, "failed")) {
3322 active_on
= ansi_highlight_red();
3323 active_off
= ansi_normal();
3324 } else if (streq_ptr(i
->active_state
, "active") || streq_ptr(i
->active_state
, "reloading")) {
3325 active_on
= ansi_highlight_green();
3326 active_off
= ansi_normal();
3328 active_on
= active_off
= "";
3330 printf("%s%s%s %s", active_on
, draw_special_char(DRAW_BLACK_CIRCLE
), active_off
, strna(i
->id
));
3332 if (i
->description
&& !streq_ptr(i
->id
, i
->description
))
3333 printf(" - %s", i
->description
);
3338 printf(" Follow: unit currently follows state of %s\n", i
->following
);
3340 if (streq_ptr(i
->load_state
, "error")) {
3341 on
= ansi_highlight_red();
3342 off
= ansi_normal();
3346 path
= i
->source_path
? i
->source_path
: i
->fragment_path
;
3349 printf(" Loaded: %s%s%s (Reason: %s)\n",
3350 on
, strna(i
->load_state
), off
, i
->load_error
);
3351 else if (path
&& !isempty(i
->unit_file_state
) && !isempty(i
->unit_file_preset
))
3352 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
3353 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
, i
->unit_file_preset
);
3354 else if (path
&& !isempty(i
->unit_file_state
))
3355 printf(" Loaded: %s%s%s (%s; %s)\n",
3356 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
);
3358 printf(" Loaded: %s%s%s (%s)\n",
3359 on
, strna(i
->load_state
), off
, path
);
3361 printf(" Loaded: %s%s%s\n",
3362 on
, strna(i
->load_state
), off
);
3364 if (!strv_isempty(i
->dropin_paths
)) {
3365 _cleanup_free_
char *dir
= NULL
;
3369 STRV_FOREACH(dropin
, i
->dropin_paths
) {
3370 if (! dir
|| last
) {
3371 printf(dir
? " " : " Drop-In: ");
3375 if (path_get_parent(*dropin
, &dir
) < 0) {
3380 printf("%s\n %s", dir
,
3381 draw_special_char(DRAW_TREE_RIGHT
));
3384 last
= ! (*(dropin
+ 1) && startswith(*(dropin
+ 1), dir
));
3386 printf("%s%s", basename(*dropin
), last
? "\n" : ", ");
3390 ss
= streq_ptr(i
->active_state
, i
->sub_state
) ? NULL
: i
->sub_state
;
3392 printf(" Active: %s%s (%s)%s",
3393 active_on
, strna(i
->active_state
), ss
, active_off
);
3395 printf(" Active: %s%s%s",
3396 active_on
, strna(i
->active_state
), active_off
);
3398 if (!isempty(i
->result
) && !streq(i
->result
, "success"))
3399 printf(" (Result: %s)", i
->result
);
3401 timestamp
= (streq_ptr(i
->active_state
, "active") ||
3402 streq_ptr(i
->active_state
, "reloading")) ? i
->active_enter_timestamp
:
3403 (streq_ptr(i
->active_state
, "inactive") ||
3404 streq_ptr(i
->active_state
, "failed")) ? i
->inactive_enter_timestamp
:
3405 streq_ptr(i
->active_state
, "activating") ? i
->inactive_exit_timestamp
:
3406 i
->active_exit_timestamp
;
3408 s1
= format_timestamp_relative(since1
, sizeof(since1
), timestamp
);
3409 s2
= format_timestamp(since2
, sizeof(since2
), timestamp
);
3412 printf(" since %s; %s\n", s2
, s1
);
3414 printf(" since %s\n", s2
);
3418 if (!i
->condition_result
&& i
->condition_timestamp
> 0) {
3419 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->condition_timestamp
);
3420 s2
= format_timestamp(since2
, sizeof(since2
), i
->condition_timestamp
);
3422 printf("Condition: start %scondition failed%s at %s%s%s\n",
3423 ansi_highlight_yellow(), ansi_normal(),
3424 s2
, s1
? "; " : "", s1
? s1
: "");
3425 if (i
->failed_condition_trigger
)
3426 printf(" none of the trigger conditions were met\n");
3427 else if (i
->failed_condition
)
3428 printf(" %s=%s%s was not met\n",
3429 i
->failed_condition
,
3430 i
->failed_condition_negate
? "!" : "",
3431 i
->failed_condition_parameter
);
3434 if (!i
->assert_result
&& i
->assert_timestamp
> 0) {
3435 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->assert_timestamp
);
3436 s2
= format_timestamp(since2
, sizeof(since2
), i
->assert_timestamp
);
3438 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
3439 ansi_highlight_red(), ansi_normal(),
3440 s2
, s1
? "; " : "", s1
? s1
: "");
3441 if (i
->failed_assert_trigger
)
3442 printf(" none of the trigger assertions were met\n");
3443 else if (i
->failed_assert
)
3444 printf(" %s=%s%s was not met\n",
3446 i
->failed_assert_negate
? "!" : "",
3447 i
->failed_assert_parameter
);
3451 printf(" Device: %s\n", i
->sysfs_path
);
3453 printf(" Where: %s\n", i
->where
);
3455 printf(" What: %s\n", i
->what
);
3457 STRV_FOREACH(t
, i
->documentation
)
3458 printf(" %*s %s\n", 9, t
== i
->documentation
? "Docs:" : "", *t
);
3460 STRV_FOREACH_PAIR(t
, t2
, i
->listen
)
3461 printf(" %*s %s (%s)\n", 9, t
== i
->listen
? "Listen:" : "", *t2
, *t
);
3464 printf(" Accepted: %u; Connected: %u\n", i
->n_accepted
, i
->n_connections
);
3466 LIST_FOREACH(exec
, p
, i
->exec
) {
3467 _cleanup_free_
char *argv
= NULL
;
3470 /* Only show exited processes here */
3474 argv
= strv_join(p
->argv
, " ");
3475 printf(" Process: "PID_FMT
" %s=%s ", p
->pid
, p
->name
, strna(argv
));
3477 good
= is_clean_exit_lsb(p
->code
, p
->status
, NULL
);
3479 on
= ansi_highlight_red();
3480 off
= ansi_normal();
3484 printf("%s(code=%s, ", on
, sigchld_code_to_string(p
->code
));
3486 if (p
->code
== CLD_EXITED
) {
3489 printf("status=%i", p
->status
);
3491 c
= exit_status_to_string(p
->status
, EXIT_STATUS_SYSTEMD
);
3496 printf("signal=%s", signal_to_string(p
->status
));
3498 printf(")%s\n", off
);
3500 if (i
->main_pid
== p
->pid
&&
3501 i
->start_timestamp
== p
->start_timestamp
&&
3502 i
->exit_timestamp
== p
->start_timestamp
)
3503 /* Let's not show this twice */
3506 if (p
->pid
== i
->control_pid
)
3510 if (i
->main_pid
> 0 || i
->control_pid
> 0) {
3511 if (i
->main_pid
> 0) {
3512 printf(" Main PID: "PID_FMT
, i
->main_pid
);
3515 _cleanup_free_
char *comm
= NULL
;
3516 get_process_comm(i
->main_pid
, &comm
);
3518 printf(" (%s)", comm
);
3519 } else if (i
->exit_code
> 0) {
3520 printf(" (code=%s, ", sigchld_code_to_string(i
->exit_code
));
3522 if (i
->exit_code
== CLD_EXITED
) {
3525 printf("status=%i", i
->exit_status
);
3527 c
= exit_status_to_string(i
->exit_status
, EXIT_STATUS_SYSTEMD
);
3532 printf("signal=%s", signal_to_string(i
->exit_status
));
3536 if (i
->control_pid
> 0)
3540 if (i
->control_pid
> 0) {
3541 _cleanup_free_
char *c
= NULL
;
3543 printf(" %8s: "PID_FMT
, i
->main_pid
? "" : " Control", i
->control_pid
);
3545 get_process_comm(i
->control_pid
, &c
);
3554 printf(" Status: \"%s\"\n", i
->status_text
);
3555 if (i
->status_errno
> 0)
3556 printf(" Error: %i (%s)\n", i
->status_errno
, strerror(i
->status_errno
));
3558 if (i
->tasks_current
!= (uint64_t) -1) {
3559 printf(" Tasks: %" PRIu64
, i
->tasks_current
);
3561 if (i
->tasks_max
!= (uint64_t) -1)
3562 printf(" (limit: %" PRIi64
")\n", i
->tasks_max
);
3567 if (i
->memory_current
!= (uint64_t) -1) {
3568 char buf
[FORMAT_BYTES_MAX
];
3570 printf(" Memory: %s", format_bytes(buf
, sizeof(buf
), i
->memory_current
));
3572 if (i
->memory_limit
!= (uint64_t) -1)
3573 printf(" (limit: %s)\n", format_bytes(buf
, sizeof(buf
), i
->memory_limit
));
3578 if (i
->cpu_usage_nsec
!= (uint64_t) -1) {
3579 char buf
[FORMAT_TIMESPAN_MAX
];
3580 printf(" CPU: %s\n", format_timespan(buf
, sizeof(buf
), i
->cpu_usage_nsec
/ NSEC_PER_USEC
, USEC_PER_MSEC
));
3583 if (i
->control_group
&&
3584 (i
->main_pid
> 0 || i
->control_pid
> 0 ||
3585 (!IN_SET(arg_transport
, BUS_TRANSPORT_LOCAL
, BUS_TRANSPORT_MACHINE
) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
) == 0))) {
3588 printf(" CGroup: %s\n", i
->control_group
);
3590 if (IN_SET(arg_transport
,
3591 BUS_TRANSPORT_LOCAL
,
3592 BUS_TRANSPORT_MACHINE
)) {
3595 static const char prefix
[] = " ";
3598 if (c
> sizeof(prefix
) - 1)
3599 c
-= sizeof(prefix
) - 1;
3603 if (i
->main_pid
> 0)
3604 extra
[k
++] = i
->main_pid
;
3606 if (i
->control_pid
> 0)
3607 extra
[k
++] = i
->control_pid
;
3609 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, prefix
, c
, false, extra
, k
, get_output_flags());
3613 if (i
->id
&& arg_transport
== BUS_TRANSPORT_LOCAL
)
3614 show_journal_by_unit(
3619 i
->inactive_exit_timestamp_monotonic
,
3622 get_output_flags() | OUTPUT_BEGIN_NEWLINE
,
3623 SD_JOURNAL_LOCAL_ONLY
,
3624 arg_scope
== UNIT_FILE_SYSTEM
,
3627 if (i
->need_daemon_reload
)
3628 warn_unit_file_changed(i
->id
);
3631 static void show_unit_help(UnitStatusInfo
*i
) {
3636 if (!i
->documentation
) {
3637 log_info("Documentation for %s not known.", i
->id
);
3641 STRV_FOREACH(p
, i
->documentation
)
3642 if (startswith(*p
, "man:"))
3643 show_man_page(*p
+ 4, false);
3645 log_info("Can't show: %s", *p
);
3648 static int status_property(const char *name
, sd_bus_message
*m
, UnitStatusInfo
*i
, const char *contents
) {
3655 switch (contents
[0]) {
3657 case SD_BUS_TYPE_STRING
: {
3660 r
= sd_bus_message_read(m
, "s", &s
);
3662 return bus_log_parse_error(r
);
3665 if (streq(name
, "Id"))
3667 else if (streq(name
, "LoadState"))
3669 else if (streq(name
, "ActiveState"))
3670 i
->active_state
= s
;
3671 else if (streq(name
, "SubState"))
3673 else if (streq(name
, "Description"))
3675 else if (streq(name
, "FragmentPath"))
3676 i
->fragment_path
= s
;
3677 else if (streq(name
, "SourcePath"))
3680 else if (streq(name
, "DefaultControlGroup")) {
3682 e
= startswith(s
, SYSTEMD_CGROUP_CONTROLLER
":");
3684 i
->control_group
= e
;
3687 else if (streq(name
, "ControlGroup"))
3688 i
->control_group
= s
;
3689 else if (streq(name
, "StatusText"))
3691 else if (streq(name
, "PIDFile"))
3693 else if (streq(name
, "SysFSPath"))
3695 else if (streq(name
, "Where"))
3697 else if (streq(name
, "What"))
3699 else if (streq(name
, "Following"))
3701 else if (streq(name
, "UnitFileState"))
3702 i
->unit_file_state
= s
;
3703 else if (streq(name
, "UnitFilePreset"))
3704 i
->unit_file_preset
= s
;
3705 else if (streq(name
, "Result"))
3712 case SD_BUS_TYPE_BOOLEAN
: {
3715 r
= sd_bus_message_read(m
, "b", &b
);
3717 return bus_log_parse_error(r
);
3719 if (streq(name
, "Accept"))
3721 else if (streq(name
, "NeedDaemonReload"))
3722 i
->need_daemon_reload
= b
;
3723 else if (streq(name
, "ConditionResult"))
3724 i
->condition_result
= b
;
3725 else if (streq(name
, "AssertResult"))
3726 i
->assert_result
= b
;
3731 case SD_BUS_TYPE_UINT32
: {
3734 r
= sd_bus_message_read(m
, "u", &u
);
3736 return bus_log_parse_error(r
);
3738 if (streq(name
, "MainPID")) {
3740 i
->main_pid
= (pid_t
) u
;
3743 } else if (streq(name
, "ControlPID"))
3744 i
->control_pid
= (pid_t
) u
;
3745 else if (streq(name
, "ExecMainPID")) {
3747 i
->main_pid
= (pid_t
) u
;
3748 } else if (streq(name
, "NAccepted"))
3750 else if (streq(name
, "NConnections"))
3751 i
->n_connections
= u
;
3756 case SD_BUS_TYPE_INT32
: {
3759 r
= sd_bus_message_read(m
, "i", &j
);
3761 return bus_log_parse_error(r
);
3763 if (streq(name
, "ExecMainCode"))
3764 i
->exit_code
= (int) j
;
3765 else if (streq(name
, "ExecMainStatus"))
3766 i
->exit_status
= (int) j
;
3767 else if (streq(name
, "StatusErrno"))
3768 i
->status_errno
= (int) j
;
3773 case SD_BUS_TYPE_UINT64
: {
3776 r
= sd_bus_message_read(m
, "t", &u
);
3778 return bus_log_parse_error(r
);
3780 if (streq(name
, "ExecMainStartTimestamp"))
3781 i
->start_timestamp
= (usec_t
) u
;
3782 else if (streq(name
, "ExecMainExitTimestamp"))
3783 i
->exit_timestamp
= (usec_t
) u
;
3784 else if (streq(name
, "ActiveEnterTimestamp"))
3785 i
->active_enter_timestamp
= (usec_t
) u
;
3786 else if (streq(name
, "InactiveEnterTimestamp"))
3787 i
->inactive_enter_timestamp
= (usec_t
) u
;
3788 else if (streq(name
, "InactiveExitTimestamp"))
3789 i
->inactive_exit_timestamp
= (usec_t
) u
;
3790 else if (streq(name
, "InactiveExitTimestampMonotonic"))
3791 i
->inactive_exit_timestamp_monotonic
= (usec_t
) u
;
3792 else if (streq(name
, "ActiveExitTimestamp"))
3793 i
->active_exit_timestamp
= (usec_t
) u
;
3794 else if (streq(name
, "ConditionTimestamp"))
3795 i
->condition_timestamp
= (usec_t
) u
;
3796 else if (streq(name
, "AssertTimestamp"))
3797 i
->assert_timestamp
= (usec_t
) u
;
3798 else if (streq(name
, "MemoryCurrent"))
3799 i
->memory_current
= u
;
3800 else if (streq(name
, "MemoryLimit"))
3801 i
->memory_limit
= u
;
3802 else if (streq(name
, "TasksCurrent"))
3803 i
->tasks_current
= u
;
3804 else if (streq(name
, "TasksMax"))
3806 else if (streq(name
, "CPUUsageNSec"))
3807 i
->cpu_usage_nsec
= u
;
3812 case SD_BUS_TYPE_ARRAY
:
3814 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
3815 _cleanup_free_ ExecStatusInfo
*info
= NULL
;
3817 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
3819 return bus_log_parse_error(r
);
3821 info
= new0(ExecStatusInfo
, 1);
3825 while ((r
= exec_status_info_deserialize(m
, info
)) > 0) {
3827 info
->name
= strdup(name
);
3831 LIST_PREPEND(exec
, i
->exec
, info
);
3833 info
= new0(ExecStatusInfo
, 1);
3839 return bus_log_parse_error(r
);
3841 r
= sd_bus_message_exit_container(m
);
3843 return bus_log_parse_error(r
);
3847 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
3848 const char *type
, *path
;
3850 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
3852 return bus_log_parse_error(r
);
3854 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0) {
3856 r
= strv_extend(&i
->listen
, type
);
3860 r
= strv_extend(&i
->listen
, path
);
3865 return bus_log_parse_error(r
);
3867 r
= sd_bus_message_exit_container(m
);
3869 return bus_log_parse_error(r
);
3873 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "DropInPaths")) {
3875 r
= sd_bus_message_read_strv(m
, &i
->dropin_paths
);
3877 return bus_log_parse_error(r
);
3879 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Documentation")) {
3881 r
= sd_bus_message_read_strv(m
, &i
->documentation
);
3883 return bus_log_parse_error(r
);
3885 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Conditions")) {
3886 const char *cond
, *param
;
3887 int trigger
, negate
;
3890 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
3892 return bus_log_parse_error(r
);
3894 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
3895 log_debug("%s %d %d %s %d", cond
, trigger
, negate
, param
, state
);
3896 if (state
< 0 && (!trigger
|| !i
->failed_condition
)) {
3897 i
->failed_condition
= cond
;
3898 i
->failed_condition_trigger
= trigger
;
3899 i
->failed_condition_negate
= negate
;
3900 i
->failed_condition_parameter
= param
;
3904 return bus_log_parse_error(r
);
3906 r
= sd_bus_message_exit_container(m
);
3908 return bus_log_parse_error(r
);
3910 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Asserts")) {
3911 const char *cond
, *param
;
3912 int trigger
, negate
;
3915 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
3917 return bus_log_parse_error(r
);
3919 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
3920 log_debug("%s %d %d %s %d", cond
, trigger
, negate
, param
, state
);
3921 if (state
< 0 && (!trigger
|| !i
->failed_assert
)) {
3922 i
->failed_assert
= cond
;
3923 i
->failed_assert_trigger
= trigger
;
3924 i
->failed_assert_negate
= negate
;
3925 i
->failed_assert_parameter
= param
;
3929 return bus_log_parse_error(r
);
3931 r
= sd_bus_message_exit_container(m
);
3933 return bus_log_parse_error(r
);
3940 case SD_BUS_TYPE_STRUCT_BEGIN
:
3942 if (streq(name
, "LoadError")) {
3943 const char *n
, *message
;
3945 r
= sd_bus_message_read(m
, "(ss)", &n
, &message
);
3947 return bus_log_parse_error(r
);
3949 if (!isempty(message
))
3950 i
->load_error
= message
;
3963 r
= sd_bus_message_skip(m
, contents
);
3965 return bus_log_parse_error(r
);
3970 static int print_property(const char *name
, sd_bus_message
*m
, const char *contents
) {
3976 /* This is a low-level property printer, see
3977 * print_status_info() for the nicer output */
3979 if (arg_properties
&& !strv_find(arg_properties
, name
)) {
3980 /* skip what we didn't read */
3981 r
= sd_bus_message_skip(m
, contents
);
3985 switch (contents
[0]) {
3987 case SD_BUS_TYPE_STRUCT_BEGIN
:
3989 if (contents
[1] == SD_BUS_TYPE_UINT32
&& streq(name
, "Job")) {
3992 r
= sd_bus_message_read(m
, "(uo)", &u
, NULL
);
3994 return bus_log_parse_error(r
);
3997 printf("%s=%"PRIu32
"\n", name
, u
);
3999 printf("%s=\n", name
);
4003 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Unit")) {
4006 r
= sd_bus_message_read(m
, "(so)", &s
, NULL
);
4008 return bus_log_parse_error(r
);
4010 if (arg_all
|| !isempty(s
))
4011 printf("%s=%s\n", name
, s
);
4015 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "LoadError")) {
4016 const char *a
= NULL
, *b
= NULL
;
4018 r
= sd_bus_message_read(m
, "(ss)", &a
, &b
);
4020 return bus_log_parse_error(r
);
4022 if (arg_all
|| !isempty(a
) || !isempty(b
))
4023 printf("%s=%s \"%s\"\n", name
, strempty(a
), strempty(b
));
4026 } else if (streq_ptr(name
, "SystemCallFilter")) {
4027 _cleanup_strv_free_
char **l
= NULL
;
4030 r
= sd_bus_message_enter_container(m
, 'r', "bas");
4032 return bus_log_parse_error(r
);
4034 r
= sd_bus_message_read(m
, "b", &whitelist
);
4036 return bus_log_parse_error(r
);
4038 r
= sd_bus_message_read_strv(m
, &l
);
4040 return bus_log_parse_error(r
);
4042 r
= sd_bus_message_exit_container(m
);
4044 return bus_log_parse_error(r
);
4046 if (arg_all
|| whitelist
|| !strv_isempty(l
)) {
4050 fputs(name
, stdout
);
4056 STRV_FOREACH(i
, l
) {
4064 fputc('\n', stdout
);
4072 case SD_BUS_TYPE_ARRAY
:
4074 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "EnvironmentFiles")) {
4078 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sb)");
4080 return bus_log_parse_error(r
);
4082 while ((r
= sd_bus_message_read(m
, "(sb)", &path
, &ignore
)) > 0)
4083 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path
, yes_no(ignore
));
4086 return bus_log_parse_error(r
);
4088 r
= sd_bus_message_exit_container(m
);
4090 return bus_log_parse_error(r
);
4094 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Paths")) {
4095 const char *type
, *path
;
4097 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4099 return bus_log_parse_error(r
);
4101 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4102 printf("%s=%s\n", type
, path
);
4104 return bus_log_parse_error(r
);
4106 r
= sd_bus_message_exit_container(m
);
4108 return bus_log_parse_error(r
);
4112 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
4113 const char *type
, *path
;
4115 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4117 return bus_log_parse_error(r
);
4119 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4120 printf("Listen%s=%s\n", type
, path
);
4122 return bus_log_parse_error(r
);
4124 r
= sd_bus_message_exit_container(m
);
4126 return bus_log_parse_error(r
);
4130 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Timers")) {
4132 uint64_t value
, next_elapse
;
4134 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(stt)");
4136 return bus_log_parse_error(r
);
4138 while ((r
= sd_bus_message_read(m
, "(stt)", &base
, &value
, &next_elapse
)) > 0) {
4139 char timespan1
[FORMAT_TIMESPAN_MAX
], timespan2
[FORMAT_TIMESPAN_MAX
];
4141 printf("%s={ value=%s ; next_elapse=%s }\n",
4143 format_timespan(timespan1
, sizeof(timespan1
), value
, 0),
4144 format_timespan(timespan2
, sizeof(timespan2
), next_elapse
, 0));
4147 return bus_log_parse_error(r
);
4149 r
= sd_bus_message_exit_container(m
);
4151 return bus_log_parse_error(r
);
4155 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
4156 ExecStatusInfo info
= {};
4158 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4160 return bus_log_parse_error(r
);
4162 while ((r
= exec_status_info_deserialize(m
, &info
)) > 0) {
4163 char timestamp1
[FORMAT_TIMESTAMP_MAX
], timestamp2
[FORMAT_TIMESTAMP_MAX
];
4164 _cleanup_free_
char *tt
;
4166 tt
= strv_join(info
.argv
, " ");
4168 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",
4172 yes_no(info
.ignore
),
4173 strna(format_timestamp(timestamp1
, sizeof(timestamp1
), info
.start_timestamp
)),
4174 strna(format_timestamp(timestamp2
, sizeof(timestamp2
), info
.exit_timestamp
)),
4176 sigchld_code_to_string(info
.code
),
4178 info
.code
== CLD_EXITED
? "" : "/",
4179 strempty(info
.code
== CLD_EXITED
? NULL
: signal_to_string(info
.status
)));
4182 strv_free(info
.argv
);
4186 r
= sd_bus_message_exit_container(m
);
4188 return bus_log_parse_error(r
);
4192 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "DeviceAllow")) {
4193 const char *path
, *rwm
;
4195 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4197 return bus_log_parse_error(r
);
4199 while ((r
= sd_bus_message_read(m
, "(ss)", &path
, &rwm
)) > 0)
4200 printf("%s=%s %s\n", name
, strna(path
), strna(rwm
));
4202 return bus_log_parse_error(r
);
4204 r
= sd_bus_message_exit_container(m
);
4206 return bus_log_parse_error(r
);
4210 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "BlockIODeviceWeight")) {
4214 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4216 return bus_log_parse_error(r
);
4218 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &weight
)) > 0)
4219 printf("%s=%s %" PRIu64
"\n", name
, strna(path
), weight
);
4221 return bus_log_parse_error(r
);
4223 r
= sd_bus_message_exit_container(m
);
4225 return bus_log_parse_error(r
);
4229 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& (streq(name
, "BlockIOReadBandwidth") || streq(name
, "BlockIOWriteBandwidth"))) {
4233 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4235 return bus_log_parse_error(r
);
4237 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &bandwidth
)) > 0)
4238 printf("%s=%s %" PRIu64
"\n", name
, strna(path
), bandwidth
);
4240 return bus_log_parse_error(r
);
4242 r
= sd_bus_message_exit_container(m
);
4244 return bus_log_parse_error(r
);
4252 r
= bus_print_property(name
, m
, arg_all
);
4254 return bus_log_parse_error(r
);
4257 r
= sd_bus_message_skip(m
, contents
);
4259 return bus_log_parse_error(r
);
4262 printf("%s=[unprintable]\n", name
);
4268 static int show_one(
4272 bool show_properties
,
4276 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4277 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4278 UnitStatusInfo info
= {
4279 .memory_current
= (uint64_t) -1,
4280 .memory_limit
= (uint64_t) -1,
4281 .cpu_usage_nsec
= (uint64_t) -1,
4282 .tasks_current
= (uint64_t) -1,
4283 .tasks_max
= (uint64_t) -1,
4291 log_debug("Showing one %s", path
);
4293 r
= sd_bus_call_method(
4295 "org.freedesktop.systemd1",
4297 "org.freedesktop.DBus.Properties",
4303 return log_error_errno(r
, "Failed to get properties: %s", bus_error_message(&error
, r
));
4305 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
4307 return bus_log_parse_error(r
);
4314 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
4315 const char *name
, *contents
;
4317 r
= sd_bus_message_read(reply
, "s", &name
);
4319 return bus_log_parse_error(r
);
4321 r
= sd_bus_message_peek_type(reply
, NULL
, &contents
);
4323 return bus_log_parse_error(r
);
4325 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, contents
);
4327 return bus_log_parse_error(r
);
4329 if (show_properties
)
4330 r
= print_property(name
, reply
, contents
);
4332 r
= status_property(name
, reply
, &info
, contents
);
4336 r
= sd_bus_message_exit_container(reply
);
4338 return bus_log_parse_error(r
);
4340 r
= sd_bus_message_exit_container(reply
);
4342 return bus_log_parse_error(r
);
4345 return bus_log_parse_error(r
);
4347 r
= sd_bus_message_exit_container(reply
);
4349 return bus_log_parse_error(r
);
4353 if (!show_properties
) {
4354 if (streq(verb
, "help"))
4355 show_unit_help(&info
);
4357 print_status_info(&info
, ellipsized
);
4360 strv_free(info
.documentation
);
4361 strv_free(info
.dropin_paths
);
4362 strv_free(info
.listen
);
4364 if (!streq_ptr(info
.active_state
, "active") &&
4365 !streq_ptr(info
.active_state
, "reloading") &&
4366 streq(verb
, "status")) {
4367 /* According to LSB: "program not running" */
4368 /* 0: program is running or service is OK
4369 * 1: program is dead and /run PID file exists
4370 * 2: program is dead and /run/lock lock file exists
4371 * 3: program is not running
4372 * 4: program or service status is unknown
4374 if (info
.pid_file
&& access(info
.pid_file
, F_OK
) == 0)
4380 while ((p
= info
.exec
)) {
4381 LIST_REMOVE(exec
, info
.exec
, p
);
4382 exec_status_info_free(p
);
4388 static int get_unit_dbus_path_by_pid(
4393 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4394 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4398 r
= sd_bus_call_method(
4400 "org.freedesktop.systemd1",
4401 "/org/freedesktop/systemd1",
4402 "org.freedesktop.systemd1.Manager",
4408 log_error("Failed to get unit for PID %"PRIu32
": %s", pid
, bus_error_message(&error
, r
));
4412 r
= sd_bus_message_read(reply
, "o", &u
);
4414 return bus_log_parse_error(r
);
4424 static int show_all(
4427 bool show_properties
,
4431 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4432 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
4437 r
= get_unit_list(bus
, NULL
, NULL
, &unit_infos
, 0, &reply
);
4441 pager_open_if_enabled();
4445 qsort_safe(unit_infos
, c
, sizeof(UnitInfo
), compare_unit_info
);
4447 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
4448 _cleanup_free_
char *p
= NULL
;
4450 p
= unit_dbus_path_from_name(u
->id
);
4454 r
= show_one(verb
, bus
, p
, show_properties
, new_line
, ellipsized
);
4457 else if (r
> 0 && ret
== 0)
4464 static int show_system_status(sd_bus
*bus
) {
4465 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], since2
[FORMAT_TIMESTAMP_MAX
];
4466 _cleanup_free_
char *hn
= NULL
;
4467 _cleanup_(machine_info_clear
) struct machine_info mi
= {};
4468 const char *on
, *off
;
4471 hn
= gethostname_malloc();
4475 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, &mi
);
4477 return log_error_errno(r
, "Failed to read server status: %m");
4479 if (streq_ptr(mi
.state
, "degraded")) {
4480 on
= ansi_highlight_red();
4481 off
= ansi_normal();
4482 } else if (!streq_ptr(mi
.state
, "running")) {
4483 on
= ansi_highlight_yellow();
4484 off
= ansi_normal();
4488 printf("%s%s%s %s\n", on
, draw_special_char(DRAW_BLACK_CIRCLE
), off
, arg_host
? arg_host
: hn
);
4490 printf(" State: %s%s%s\n",
4491 on
, strna(mi
.state
), off
);
4493 printf(" Jobs: %u queued\n", mi
.n_jobs
);
4494 printf(" Failed: %u units\n", mi
.n_failed_units
);
4496 printf(" Since: %s; %s\n",
4497 format_timestamp(since2
, sizeof(since2
), mi
.timestamp
),
4498 format_timestamp_relative(since1
, sizeof(since1
), mi
.timestamp
));
4500 printf(" CGroup: %s\n", mi
.control_group
?: "/");
4501 if (IN_SET(arg_transport
,
4502 BUS_TRANSPORT_LOCAL
,
4503 BUS_TRANSPORT_MACHINE
)) {
4504 static const char prefix
[] = " ";
4508 if (c
> sizeof(prefix
) - 1)
4509 c
-= sizeof(prefix
) - 1;
4513 show_cgroup(SYSTEMD_CGROUP_CONTROLLER
, strempty(mi
.control_group
), prefix
, c
, false, get_output_flags());
4519 static int show(sd_bus
*bus
, char **args
) {
4520 bool show_properties
, show_status
, new_line
= false;
4521 bool ellipsized
= false;
4527 show_properties
= streq(args
[0], "show");
4528 show_status
= streq(args
[0], "status");
4530 if (show_properties
)
4531 pager_open_if_enabled();
4534 /* Increase max number of open files to 16K if we can, we
4535 * might needs this when browsing journal files, which might
4536 * be split up into many files. */
4537 setrlimit_closest(RLIMIT_NOFILE
, &RLIMIT_MAKE_CONST(16384));
4539 /* If no argument is specified inspect the manager itself */
4541 if (show_properties
&& strv_length(args
) <= 1)
4542 return show_one(args
[0], bus
, "/org/freedesktop/systemd1", show_properties
, &new_line
, &ellipsized
);
4544 if (show_status
&& strv_length(args
) <= 1) {
4546 pager_open_if_enabled();
4547 show_system_status(bus
);
4551 ret
= show_all(args
[0], bus
, false, &new_line
, &ellipsized
);
4553 _cleanup_free_
char **patterns
= NULL
;
4556 STRV_FOREACH(name
, args
+ 1) {
4557 _cleanup_free_
char *unit
= NULL
;
4560 if (safe_atou32(*name
, &id
) < 0) {
4561 if (strv_push(&patterns
, *name
) < 0)
4565 } else if (show_properties
) {
4566 /* Interpret as job id */
4567 if (asprintf(&unit
, "/org/freedesktop/systemd1/job/%u", id
) < 0)
4571 /* Interpret as PID */
4572 r
= get_unit_dbus_path_by_pid(bus
, id
, &unit
);
4579 r
= show_one(args
[0], bus
, unit
, show_properties
,
4580 &new_line
, &ellipsized
);
4583 else if (r
> 0 && ret
== 0)
4587 if (!strv_isempty(patterns
)) {
4588 _cleanup_strv_free_
char **names
= NULL
;
4590 r
= expand_names(bus
, patterns
, NULL
, &names
);
4592 log_error_errno(r
, "Failed to expand names: %m");
4594 STRV_FOREACH(name
, names
) {
4595 _cleanup_free_
char *unit
;
4597 unit
= unit_dbus_path_from_name(*name
);
4601 r
= show_one(args
[0], bus
, unit
, show_properties
,
4602 &new_line
, &ellipsized
);
4605 else if (r
> 0 && ret
== 0)
4611 if (ellipsized
&& !arg_quiet
)
4612 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4617 static int init_home_and_lookup_paths(char **user_home
, char **user_runtime
, LookupPaths
*lp
) {
4621 assert(user_runtime
);
4624 if (arg_scope
== UNIT_FILE_USER
) {
4625 r
= user_config_home(user_home
);
4627 return log_error_errno(r
, "Failed to query XDG_CONFIG_HOME: %m");
4629 return log_error_errno(ENOTDIR
, "Cannot find units: $XDG_CONFIG_HOME and $HOME are not set.");
4631 r
= user_runtime_dir(user_runtime
);
4633 return log_error_errno(r
, "Failed to query XDG_CONFIG_HOME: %m");
4635 return log_error_errno(ENOTDIR
, "Cannot find units: $XDG_RUNTIME_DIR is not set.");
4638 r
= lookup_paths_init_from_scope(lp
, arg_scope
, arg_root
);
4640 return log_error_errno(r
, "Failed to query unit lookup paths: %m");
4645 static int cat_file(const char *filename
, bool newline
) {
4646 _cleanup_close_
int fd
;
4648 fd
= open(filename
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
4652 printf("%s%s# %s%s\n",
4653 newline
? "\n" : "",
4654 ansi_highlight_blue(),
4659 return copy_bytes(fd
, STDOUT_FILENO
, (uint64_t) -1, false);
4662 static int cat(sd_bus
*bus
, char **args
) {
4663 _cleanup_free_
char *user_home
= NULL
;
4664 _cleanup_free_
char *user_runtime
= NULL
;
4665 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
4666 _cleanup_strv_free_
char **names
= NULL
;
4668 bool first
= true, avoid_bus_cache
;
4673 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
4674 log_error("Cannot remotely cat units");
4678 r
= init_home_and_lookup_paths(&user_home
, &user_runtime
, &lp
);
4682 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
4684 return log_error_errno(r
, "Failed to expand names: %m");
4686 avoid_bus_cache
= !bus
|| avoid_bus();
4688 pager_open_if_enabled();
4690 STRV_FOREACH(name
, names
) {
4691 _cleanup_free_
char *fragment_path
= NULL
;
4692 _cleanup_strv_free_
char **dropin_paths
= NULL
;
4695 r
= unit_find_paths(bus
, *name
, avoid_bus_cache
, &lp
, &fragment_path
, &dropin_paths
);
4706 if (fragment_path
) {
4707 r
= cat_file(fragment_path
, false);
4709 return log_warning_errno(r
, "Failed to cat %s: %m", fragment_path
);
4712 STRV_FOREACH(path
, dropin_paths
) {
4713 r
= cat_file(*path
, path
== dropin_paths
);
4715 return log_warning_errno(r
, "Failed to cat %s: %m", *path
);
4722 static int set_property(sd_bus
*bus
, char **args
) {
4723 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
4724 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4725 _cleanup_free_
char *n
= NULL
;
4729 polkit_agent_open_if_enabled();
4731 r
= sd_bus_message_new_method_call(
4734 "org.freedesktop.systemd1",
4735 "/org/freedesktop/systemd1",
4736 "org.freedesktop.systemd1.Manager",
4737 "SetUnitProperties");
4739 return bus_log_create_error(r
);
4741 r
= unit_name_mangle(args
[1], UNIT_NAME_NOGLOB
, &n
);
4743 return log_error_errno(r
, "Failed to mangle unit name: %m");
4745 r
= sd_bus_message_append(m
, "sb", n
, arg_runtime
);
4747 return bus_log_create_error(r
);
4749 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, "(sv)");
4751 return bus_log_create_error(r
);
4753 STRV_FOREACH(i
, args
+ 2) {
4754 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_STRUCT
, "sv");
4756 return bus_log_create_error(r
);
4758 r
= bus_append_unit_property_assignment(m
, *i
);
4762 r
= sd_bus_message_close_container(m
);
4764 return bus_log_create_error(r
);
4767 r
= sd_bus_message_close_container(m
);
4769 return bus_log_create_error(r
);
4771 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
4773 log_error("Failed to set unit properties on %s: %s", n
, bus_error_message(&error
, r
));
4780 static int snapshot(sd_bus
*bus
, char **args
) {
4781 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4782 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4783 _cleanup_free_
char *n
= NULL
, *id
= NULL
;
4787 polkit_agent_open_if_enabled();
4789 if (strv_length(args
) > 1) {
4790 r
= unit_name_mangle_with_suffix(args
[1], UNIT_NAME_NOGLOB
, ".snapshot", &n
);
4792 return log_error_errno(r
, "Failed to generate unit name: %m");
4799 r
= sd_bus_call_method(
4801 "org.freedesktop.systemd1",
4802 "/org/freedesktop/systemd1",
4803 "org.freedesktop.systemd1.Manager",
4809 log_error("Failed to create snapshot: %s", bus_error_message(&error
, r
));
4813 r
= sd_bus_message_read(reply
, "o", &path
);
4815 return bus_log_parse_error(r
);
4817 r
= sd_bus_get_property_string(
4819 "org.freedesktop.systemd1",
4821 "org.freedesktop.systemd1.Unit",
4826 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error
, r
));
4836 static int delete_snapshot(sd_bus
*bus
, char **args
) {
4837 _cleanup_strv_free_
char **names
= NULL
;
4843 polkit_agent_open_if_enabled();
4845 r
= expand_names(bus
, args
+ 1, ".snapshot", &names
);
4847 log_error_errno(r
, "Failed to expand names: %m");
4849 STRV_FOREACH(name
, names
) {
4850 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4853 q
= sd_bus_call_method(
4855 "org.freedesktop.systemd1",
4856 "/org/freedesktop/systemd1",
4857 "org.freedesktop.systemd1.Manager",
4863 log_error("Failed to remove snapshot %s: %s", *name
, bus_error_message(&error
, q
));
4872 static int daemon_reload(sd_bus
*bus
, char **args
) {
4873 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4877 polkit_agent_open_if_enabled();
4879 if (arg_action
== ACTION_RELOAD
)
4881 else if (arg_action
== ACTION_REEXEC
)
4882 method
= "Reexecute";
4884 assert(arg_action
== ACTION_SYSTEMCTL
);
4887 streq(args
[0], "clear-jobs") ||
4888 streq(args
[0], "cancel") ? "ClearJobs" :
4889 streq(args
[0], "daemon-reexec") ? "Reexecute" :
4890 streq(args
[0], "reset-failed") ? "ResetFailed" :
4891 streq(args
[0], "halt") ? "Halt" :
4892 streq(args
[0], "poweroff") ? "PowerOff" :
4893 streq(args
[0], "reboot") ? "Reboot" :
4894 streq(args
[0], "kexec") ? "KExec" :
4895 streq(args
[0], "exit") ? "Exit" :
4896 /* "daemon-reload" */ "Reload";
4899 r
= sd_bus_call_method(
4901 "org.freedesktop.systemd1",
4902 "/org/freedesktop/systemd1",
4903 "org.freedesktop.systemd1.Manager",
4908 if (r
== -ENOENT
&& arg_action
!= ACTION_SYSTEMCTL
)
4909 /* There's always a fallback possible for
4910 * legacy actions. */
4912 else if ((r
== -ETIMEDOUT
|| r
== -ECONNRESET
) && streq(method
, "Reexecute"))
4913 /* On reexecution, we expect a disconnect, not a
4917 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
4919 return r
< 0 ? r
: 0;
4922 static int reset_failed(sd_bus
*bus
, char **args
) {
4923 _cleanup_strv_free_
char **names
= NULL
;
4927 if (strv_length(args
) <= 1)
4928 return daemon_reload(bus
, args
);
4930 polkit_agent_open_if_enabled();
4932 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
4934 log_error_errno(r
, "Failed to expand names: %m");
4936 STRV_FOREACH(name
, names
) {
4937 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4939 q
= sd_bus_call_method(
4941 "org.freedesktop.systemd1",
4942 "/org/freedesktop/systemd1",
4943 "org.freedesktop.systemd1.Manager",
4949 log_error("Failed to reset failed state of unit %s: %s", *name
, bus_error_message(&error
, q
));
4958 static int show_environment(sd_bus
*bus
, char **args
) {
4959 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4960 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4964 pager_open_if_enabled();
4966 r
= sd_bus_get_property(
4968 "org.freedesktop.systemd1",
4969 "/org/freedesktop/systemd1",
4970 "org.freedesktop.systemd1.Manager",
4976 log_error("Failed to get environment: %s", bus_error_message(&error
, r
));
4980 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
4982 return bus_log_parse_error(r
);
4984 while ((r
= sd_bus_message_read_basic(reply
, SD_BUS_TYPE_STRING
, &text
)) > 0)
4987 return bus_log_parse_error(r
);
4989 r
= sd_bus_message_exit_container(reply
);
4991 return bus_log_parse_error(r
);
4996 static int switch_root(sd_bus
*bus
, char **args
) {
4997 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4998 _cleanup_free_
char *cmdline_init
= NULL
;
4999 const char *root
, *init
;
5003 l
= strv_length(args
);
5004 if (l
< 2 || l
> 3) {
5005 log_error("Wrong number of arguments.");
5014 r
= parse_env_file("/proc/cmdline", WHITESPACE
,
5015 "init", &cmdline_init
,
5018 log_debug_errno(r
, "Failed to parse /proc/cmdline: %m");
5020 init
= cmdline_init
;
5027 const char *root_systemd_path
= NULL
, *root_init_path
= NULL
;
5029 root_systemd_path
= strjoina(root
, "/" SYSTEMD_BINARY_PATH
);
5030 root_init_path
= strjoina(root
, "/", init
);
5032 /* If the passed init is actually the same as the
5033 * systemd binary, then let's suppress it. */
5034 if (files_same(root_init_path
, root_systemd_path
) > 0)
5038 log_debug("Switching root - root: %s; init: %s", root
, strna(init
));
5040 r
= sd_bus_call_method(
5042 "org.freedesktop.systemd1",
5043 "/org/freedesktop/systemd1",
5044 "org.freedesktop.systemd1.Manager",
5050 log_error("Failed to switch root: %s", bus_error_message(&error
, r
));
5057 static int set_environment(sd_bus
*bus
, char **args
) {
5058 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5059 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
5066 polkit_agent_open_if_enabled();
5068 method
= streq(args
[0], "set-environment")
5070 : "UnsetEnvironment";
5072 r
= sd_bus_message_new_method_call(
5075 "org.freedesktop.systemd1",
5076 "/org/freedesktop/systemd1",
5077 "org.freedesktop.systemd1.Manager",
5080 return bus_log_create_error(r
);
5082 r
= sd_bus_message_append_strv(m
, args
+ 1);
5084 return bus_log_create_error(r
);
5086 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5088 log_error("Failed to set environment: %s", bus_error_message(&error
, r
));
5095 static int import_environment(sd_bus
*bus
, char **args
) {
5096 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5097 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
5103 polkit_agent_open_if_enabled();
5105 r
= sd_bus_message_new_method_call(
5108 "org.freedesktop.systemd1",
5109 "/org/freedesktop/systemd1",
5110 "org.freedesktop.systemd1.Manager",
5113 return bus_log_create_error(r
);
5115 if (strv_isempty(args
+ 1))
5116 r
= sd_bus_message_append_strv(m
, environ
);
5120 r
= sd_bus_message_open_container(m
, 'a', "s");
5122 return bus_log_create_error(r
);
5124 STRV_FOREACH(a
, args
+ 1) {
5126 if (!env_name_is_valid(*a
)) {
5127 log_error("Not a valid environment variable name: %s", *a
);
5131 STRV_FOREACH(b
, environ
) {
5134 eq
= startswith(*b
, *a
);
5135 if (eq
&& *eq
== '=') {
5137 r
= sd_bus_message_append(m
, "s", *b
);
5139 return bus_log_create_error(r
);
5146 r
= sd_bus_message_close_container(m
);
5149 return bus_log_create_error(r
);
5151 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5153 log_error("Failed to import environment: %s", bus_error_message(&error
, r
));
5160 static int enable_sysv_units(const char *verb
, char **args
) {
5163 #if defined(HAVE_SYSV_COMPAT)
5165 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
5167 if (arg_scope
!= UNIT_FILE_SYSTEM
)
5170 if (!STR_IN_SET(verb
,
5176 /* Processes all SysV units, and reshuffles the array so that
5177 * afterwards only the native units remain */
5179 r
= lookup_paths_init(&paths
, MANAGER_SYSTEM
, false, arg_root
, NULL
, NULL
, NULL
);
5186 _cleanup_free_
char *p
= NULL
, *q
= NULL
, *l
= NULL
;
5187 bool found_native
= false, found_sysv
;
5189 const char *argv
[6] = { ROOTLIBEXECDIR
"/systemd-sysv-install", NULL
, NULL
, NULL
, NULL
};
5197 if (!endswith(name
, ".service"))
5200 if (path_is_absolute(name
))
5203 STRV_FOREACH(k
, paths
.unit_path
) {
5204 _cleanup_free_
char *path
= NULL
;
5206 path
= path_join(arg_root
, *k
, name
);
5210 found_native
= access(path
, F_OK
) >= 0;
5215 /* If we have both a native unit and a SysV script,
5216 * enable/disable them both (below); for is-enabled, prefer the
5218 if (found_native
&& streq(verb
, "is-enabled"))
5221 p
= path_join(arg_root
, SYSTEM_SYSVINIT_PATH
, name
);
5225 p
[strlen(p
) - strlen(".service")] = 0;
5226 found_sysv
= access(p
, F_OK
) >= 0;
5231 log_info("Synchronizing state of %s with SysV init with %s...", name
, argv
[0]);
5233 log_info("%s is not a native service, redirecting to systemd-sysv-install", name
);
5235 if (!isempty(arg_root
))
5236 argv
[c
++] = q
= strappend("--root=", arg_root
);
5239 argv
[c
++] = basename(p
);
5242 l
= strv_join((char**)argv
, " ");
5246 log_info("Executing %s", l
);
5250 return log_error_errno(errno
, "Failed to fork: %m");
5251 else if (pid
== 0) {
5254 (void) reset_all_signal_handlers();
5255 (void) reset_signal_mask();
5257 execv(argv
[0], (char**) argv
);
5258 log_error("Failed to execute %s: %m", argv
[0]);
5259 _exit(EXIT_FAILURE
);
5262 j
= wait_for_terminate(pid
, &status
);
5264 log_error_errno(r
, "Failed to wait for child: %m");
5268 if (status
.si_code
== CLD_EXITED
) {
5269 if (streq(verb
, "is-enabled")) {
5270 if (status
.si_status
== 0) {
5279 } else if (status
.si_status
!= 0)
5287 /* Remove this entry, so that we don't try enabling it as native unit */
5290 assert(args
[f
] == name
);
5291 strv_remove(args
, name
);
5298 static int mangle_names(char **original_names
, char ***mangled_names
) {
5299 char **i
, **l
, **name
;
5302 l
= i
= new(char*, strv_length(original_names
) + 1);
5306 STRV_FOREACH(name
, original_names
) {
5308 /* When enabling units qualified path names are OK,
5309 * too, hence allow them explicitly. */
5311 if (is_path(*name
)) {
5318 r
= unit_name_mangle(*name
, UNIT_NAME_NOGLOB
, i
);
5321 return log_error_errno(r
, "Failed to mangle unit name: %m");
5334 static int enable_unit(sd_bus
*bus
, char **args
) {
5335 _cleanup_strv_free_
char **names
= NULL
;
5336 const char *verb
= args
[0];
5337 UnitFileChange
*changes
= NULL
;
5338 unsigned n_changes
= 0;
5339 int carries_install_info
= -1;
5345 r
= mangle_names(args
+1, &names
);
5349 r
= enable_sysv_units(verb
, names
);
5353 /* If the operation was fully executed by the SysV compat,
5354 * let's finish early */
5355 if (strv_isempty(names
))
5358 if (!bus
|| avoid_bus()) {
5359 if (streq(verb
, "enable")) {
5360 r
= unit_file_enable(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5361 carries_install_info
= r
;
5362 } else if (streq(verb
, "disable"))
5363 r
= unit_file_disable(arg_scope
, arg_runtime
, arg_root
, names
, &changes
, &n_changes
);
5364 else if (streq(verb
, "reenable")) {
5365 r
= unit_file_reenable(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5366 carries_install_info
= r
;
5367 } else if (streq(verb
, "link"))
5368 r
= unit_file_link(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5369 else if (streq(verb
, "preset")) {
5370 r
= unit_file_preset(arg_scope
, arg_runtime
, arg_root
, names
, arg_preset_mode
, arg_force
, &changes
, &n_changes
);
5371 carries_install_info
= r
;
5372 } else if (streq(verb
, "mask"))
5373 r
= unit_file_mask(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5374 else if (streq(verb
, "unmask"))
5375 r
= unit_file_unmask(arg_scope
, arg_runtime
, arg_root
, names
, &changes
, &n_changes
);
5377 assert_not_reached("Unknown verb");
5380 log_error_errno(r
, "Operation failed: %m");
5385 dump_unit_file_changes(changes
, n_changes
);
5389 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
, *m
= NULL
;
5390 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5391 int expect_carries_install_info
= false;
5392 bool send_force
= true, send_preset_mode
= false;
5395 polkit_agent_open_if_enabled();
5397 if (streq(verb
, "enable")) {
5398 method
= "EnableUnitFiles";
5399 expect_carries_install_info
= true;
5400 } else if (streq(verb
, "disable")) {
5401 method
= "DisableUnitFiles";
5403 } else if (streq(verb
, "reenable")) {
5404 method
= "ReenableUnitFiles";
5405 expect_carries_install_info
= true;
5406 } else if (streq(verb
, "link"))
5407 method
= "LinkUnitFiles";
5408 else if (streq(verb
, "preset")) {
5410 if (arg_preset_mode
!= UNIT_FILE_PRESET_FULL
) {
5411 method
= "PresetUnitFilesWithMode";
5412 send_preset_mode
= true;
5414 method
= "PresetUnitFiles";
5416 expect_carries_install_info
= true;
5417 } else if (streq(verb
, "mask"))
5418 method
= "MaskUnitFiles";
5419 else if (streq(verb
, "unmask")) {
5420 method
= "UnmaskUnitFiles";
5423 assert_not_reached("Unknown verb");
5425 r
= sd_bus_message_new_method_call(
5428 "org.freedesktop.systemd1",
5429 "/org/freedesktop/systemd1",
5430 "org.freedesktop.systemd1.Manager",
5433 return bus_log_create_error(r
);
5435 r
= sd_bus_message_append_strv(m
, names
);
5437 return bus_log_create_error(r
);
5439 if (send_preset_mode
) {
5440 r
= sd_bus_message_append(m
, "s", unit_file_preset_mode_to_string(arg_preset_mode
));
5442 return bus_log_create_error(r
);
5445 r
= sd_bus_message_append(m
, "b", arg_runtime
);
5447 return bus_log_create_error(r
);
5450 r
= sd_bus_message_append(m
, "b", arg_force
);
5452 return bus_log_create_error(r
);
5455 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
5457 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
5461 if (expect_carries_install_info
) {
5462 r
= sd_bus_message_read(reply
, "b", &carries_install_info
);
5464 return bus_log_parse_error(r
);
5467 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
5471 /* Try to reload if enabled */
5473 r
= daemon_reload(bus
, args
);
5478 if (carries_install_info
== 0)
5479 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5480 "using systemctl.\n"
5481 "Possible reasons for having this kind of units are:\n"
5482 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5483 " .wants/ or .requires/ directory.\n"
5484 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5485 " a requirement dependency on it.\n"
5486 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5487 " D-Bus, udev, scripted systemctl call, ...).\n");
5489 if (arg_now
&& n_changes
> 0 && STR_IN_SET(args
[0], "enable", "disable", "mask")) {
5490 char *new_args
[n_changes
+ 2];
5493 new_args
[0] = streq(args
[0], "enable") ? (char *)"start" : (char *)"stop";
5494 for (i
= 0; i
< n_changes
; i
++)
5495 new_args
[i
+ 1] = basename(changes
[i
].path
);
5496 new_args
[i
+ 1] = NULL
;
5498 r
= start_unit(bus
, new_args
);
5502 unit_file_changes_free(changes
, n_changes
);
5507 static int add_dependency(sd_bus
*bus
, char **args
) {
5508 _cleanup_strv_free_
char **names
= NULL
;
5509 _cleanup_free_
char *target
= NULL
;
5510 const char *verb
= args
[0];
5517 r
= unit_name_mangle_with_suffix(args
[1], UNIT_NAME_NOGLOB
, ".target", &target
);
5519 return log_error_errno(r
, "Failed to mangle unit name: %m");
5521 r
= mangle_names(args
+2, &names
);
5525 if (streq(verb
, "add-wants"))
5527 else if (streq(verb
, "add-requires"))
5528 dep
= UNIT_REQUIRES
;
5530 assert_not_reached("Unknown verb");
5532 if (!bus
|| avoid_bus()) {
5533 UnitFileChange
*changes
= NULL
;
5534 unsigned n_changes
= 0;
5536 r
= unit_file_add_dependency(arg_scope
, arg_runtime
, arg_root
, names
, target
, dep
, arg_force
, &changes
, &n_changes
);
5539 return log_error_errno(r
, "Can't add dependency: %m");
5542 dump_unit_file_changes(changes
, n_changes
);
5544 unit_file_changes_free(changes
, n_changes
);
5547 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
, *m
= NULL
;
5548 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5550 polkit_agent_open_if_enabled();
5552 r
= sd_bus_message_new_method_call(
5555 "org.freedesktop.systemd1",
5556 "/org/freedesktop/systemd1",
5557 "org.freedesktop.systemd1.Manager",
5558 "AddDependencyUnitFiles");
5560 return bus_log_create_error(r
);
5562 r
= sd_bus_message_append_strv(m
, names
);
5564 return bus_log_create_error(r
);
5566 r
= sd_bus_message_append(m
, "ssbb", target
, unit_dependency_to_string(dep
), arg_runtime
, arg_force
);
5568 return bus_log_create_error(r
);
5570 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
5572 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
5576 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, NULL
, NULL
);
5581 r
= daemon_reload(bus
, args
);
5589 static int preset_all(sd_bus
*bus
, char **args
) {
5590 UnitFileChange
*changes
= NULL
;
5591 unsigned n_changes
= 0;
5594 if (!bus
|| avoid_bus()) {
5596 r
= unit_file_preset_all(arg_scope
, arg_runtime
, arg_root
, arg_preset_mode
, arg_force
, &changes
, &n_changes
);
5598 log_error_errno(r
, "Operation failed: %m");
5603 dump_unit_file_changes(changes
, n_changes
);
5608 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5609 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
5611 polkit_agent_open_if_enabled();
5613 r
= sd_bus_call_method(
5615 "org.freedesktop.systemd1",
5616 "/org/freedesktop/systemd1",
5617 "org.freedesktop.systemd1.Manager",
5618 "PresetAllUnitFiles",
5622 unit_file_preset_mode_to_string(arg_preset_mode
),
5626 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
5630 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, NULL
, NULL
);
5635 r
= daemon_reload(bus
, args
);
5641 unit_file_changes_free(changes
, n_changes
);
5646 static int unit_is_enabled(sd_bus
*bus
, char **args
) {
5648 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5649 _cleanup_strv_free_
char **names
= NULL
;
5654 r
= mangle_names(args
+1, &names
);
5658 r
= enable_sysv_units(args
[0], names
);
5664 if (!bus
|| avoid_bus()) {
5666 STRV_FOREACH(name
, names
) {
5667 UnitFileState state
;
5669 state
= unit_file_get_state(arg_scope
, arg_root
, *name
);
5671 return log_error_errno(state
, "Failed to get unit file state for %s: %m", *name
);
5675 UNIT_FILE_ENABLED_RUNTIME
,
5677 UNIT_FILE_INDIRECT
))
5681 puts(unit_file_state_to_string(state
));
5685 STRV_FOREACH(name
, names
) {
5686 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
5689 r
= sd_bus_call_method(
5691 "org.freedesktop.systemd1",
5692 "/org/freedesktop/systemd1",
5693 "org.freedesktop.systemd1.Manager",
5699 log_error("Failed to get unit file state for %s: %s", *name
, bus_error_message(&error
, r
));
5703 r
= sd_bus_message_read(reply
, "s", &s
);
5705 return bus_log_parse_error(r
);
5707 if (STR_IN_SET(s
, "enabled", "enabled-runtime", "static", "indirect"))
5718 static int is_system_running(sd_bus
*bus
, char **args
) {
5719 _cleanup_free_
char *state
= NULL
;
5722 if (arg_transport
== BUS_TRANSPORT_LOCAL
&& !sd_booted()) {
5725 return EXIT_FAILURE
;
5728 r
= sd_bus_get_property_string(
5730 "org.freedesktop.systemd1",
5731 "/org/freedesktop/systemd1",
5732 "org.freedesktop.systemd1.Manager",
5745 return streq(state
, "running") ? EXIT_SUCCESS
: EXIT_FAILURE
;
5748 static int create_edit_temp_file(const char *new_path
, const char *original_path
, char **ret_tmp_fn
) {
5753 assert(original_path
);
5756 r
= tempfn_random(new_path
, NULL
, &t
);
5758 return log_error_errno(r
, "Failed to determine temporary filename for \"%s\": %m", new_path
);
5760 r
= mkdir_parents(new_path
, 0755);
5762 log_error_errno(r
, "Failed to create directories for \"%s\": %m", new_path
);
5767 r
= copy_file(original_path
, t
, 0, 0644, 0);
5771 log_error_errno(r
, "Failed to create temporary file \"%s\": %m", t
);
5776 log_error_errno(r
, "Failed to copy \"%s\" to \"%s\": %m", original_path
, t
);
5786 static int get_file_to_edit(const char *name
, const char *user_home
, const char *user_runtime
, char **ret_path
) {
5787 _cleanup_free_
char *path
= NULL
, *path2
= NULL
, *run
= NULL
;
5789 switch (arg_scope
) {
5790 case UNIT_FILE_SYSTEM
:
5791 path
= path_join(arg_root
, SYSTEM_CONFIG_UNIT_PATH
, name
);
5793 run
= path_join(arg_root
, "/run/systemd/system/", name
);
5795 case UNIT_FILE_GLOBAL
:
5796 path
= path_join(arg_root
, USER_CONFIG_UNIT_PATH
, name
);
5798 run
= path_join(arg_root
, "/run/systemd/user/", name
);
5800 case UNIT_FILE_USER
:
5802 assert(user_runtime
);
5804 path
= path_join(arg_root
, user_home
, name
);
5806 path2
= path_join(arg_root
, USER_CONFIG_UNIT_PATH
, name
);
5809 run
= path_join(arg_root
, user_runtime
, name
);
5813 assert_not_reached("Invalid scope");
5815 if (!path
|| (arg_runtime
&& !run
))
5819 if (access(path
, F_OK
) >= 0)
5820 return log_error_errno(EEXIST
, "Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.",
5822 if (path2
&& access(path2
, F_OK
) >= 0)
5823 return log_error_errno(EEXIST
, "Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.",
5835 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
) {
5836 char *tmp_new_path
, *ending
;
5841 assert(ret_new_path
);
5842 assert(ret_tmp_path
);
5844 ending
= strjoina(unit_name
, ".d/override.conf");
5845 r
= get_file_to_edit(ending
, user_home
, user_runtime
, &tmp_new_path
);
5849 r
= create_edit_temp_file(tmp_new_path
, tmp_new_path
, &tmp_tmp_path
);
5855 *ret_new_path
= tmp_new_path
;
5856 *ret_tmp_path
= tmp_tmp_path
;
5861 static int unit_file_create_copy(
5862 const char *unit_name
,
5863 const char *fragment_path
,
5864 const char *user_home
,
5865 const char *user_runtime
,
5866 char **ret_new_path
,
5867 char **ret_tmp_path
) {
5873 assert(fragment_path
);
5875 assert(ret_new_path
);
5876 assert(ret_tmp_path
);
5878 r
= get_file_to_edit(unit_name
, user_home
, user_runtime
, &tmp_new_path
);
5882 if (!path_equal(fragment_path
, tmp_new_path
) && access(tmp_new_path
, F_OK
) == 0) {
5885 r
= ask_char(&response
, "yn", "\"%s\" already exists. Overwrite with \"%s\"? [(y)es, (n)o] ", tmp_new_path
, fragment_path
);
5890 if (response
!= 'y') {
5891 log_warning("%s ignored", unit_name
);
5897 r
= create_edit_temp_file(tmp_new_path
, fragment_path
, &tmp_tmp_path
);
5899 log_error_errno(r
, "Failed to create temporary file for \"%s\": %m", tmp_new_path
);
5904 *ret_new_path
= tmp_new_path
;
5905 *ret_tmp_path
= tmp_tmp_path
;
5910 static int run_editor(char **paths
) {
5918 log_error_errno(errno
, "Failed to fork: %m");
5924 char *editor
, **editor_args
= NULL
;
5925 char **tmp_path
, **original_path
, *p
;
5926 unsigned n_editor_args
= 0, i
= 1;
5929 (void) reset_all_signal_handlers();
5930 (void) reset_signal_mask();
5932 argc
= strv_length(paths
)/2 + 1;
5934 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
5935 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
5936 * we try to execute well known editors
5938 editor
= getenv("SYSTEMD_EDITOR");
5940 editor
= getenv("EDITOR");
5942 editor
= getenv("VISUAL");
5944 if (!isempty(editor
)) {
5945 editor_args
= strv_split(editor
, WHITESPACE
);
5948 _exit(EXIT_FAILURE
);
5950 n_editor_args
= strv_length(editor_args
);
5951 argc
+= n_editor_args
- 1;
5953 args
= newa(const char*, argc
+ 1);
5955 if (n_editor_args
> 0) {
5956 args
[0] = editor_args
[0];
5957 for (; i
< n_editor_args
; i
++)
5958 args
[i
] = editor_args
[i
];
5961 STRV_FOREACH_PAIR(original_path
, tmp_path
, paths
) {
5962 args
[i
] = *tmp_path
;
5967 if (n_editor_args
> 0)
5968 execvp(args
[0], (char* const*) args
);
5970 FOREACH_STRING(p
, "editor", "nano", "vim", "vi") {
5972 execvp(p
, (char* const*) args
);
5973 /* We do not fail if the editor doesn't exist
5974 * because we want to try each one of them before
5977 if (errno
!= ENOENT
) {
5978 log_error("Failed to execute %s: %m", editor
);
5979 _exit(EXIT_FAILURE
);
5983 log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR, $EDITOR or $VISUAL.");
5984 _exit(EXIT_FAILURE
);
5987 r
= wait_for_terminate_and_warn("editor", pid
, true);
5989 return log_error_errno(r
, "Failed to wait for child: %m");
5994 static int find_paths_to_edit(sd_bus
*bus
, char **names
, char ***paths
) {
5995 _cleanup_free_
char *user_home
= NULL
;
5996 _cleanup_free_
char *user_runtime
= NULL
;
5997 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
5998 bool avoid_bus_cache
;
6005 r
= init_home_and_lookup_paths(&user_home
, &user_runtime
, &lp
);
6009 avoid_bus_cache
= !bus
|| avoid_bus();
6011 STRV_FOREACH(name
, names
) {
6012 _cleanup_free_
char *path
= NULL
;
6013 char *new_path
, *tmp_path
;
6015 r
= unit_find_paths(bus
, *name
, avoid_bus_cache
, &lp
, &path
, NULL
);
6021 // FIXME: support units with path==NULL (no FragmentPath)
6022 log_error("No fragment exists for %s.", *name
);
6027 r
= unit_file_create_copy(*name
, path
, user_home
, user_runtime
, &new_path
, &tmp_path
);
6029 r
= unit_file_create_dropin(*name
, user_home
, user_runtime
, &new_path
, &tmp_path
);
6033 r
= strv_push_pair(paths
, new_path
, tmp_path
);
6041 static int edit(sd_bus
*bus
, char **args
) {
6042 _cleanup_strv_free_
char **names
= NULL
;
6043 _cleanup_strv_free_
char **paths
= NULL
;
6044 char **original
, **tmp
;
6050 log_error("Cannot edit units if not on a tty");
6054 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
6055 log_error("Cannot remotely edit units");
6059 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
6061 return log_error_errno(r
, "Failed to expand names: %m");
6063 r
= find_paths_to_edit(bus
, names
, &paths
);
6067 if (strv_isempty(paths
))
6070 r
= run_editor(paths
);
6074 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
6075 /* If the temporary file is empty we ignore it.
6076 * It's useful if the user wants to cancel its modification
6078 if (null_or_empty_path(*tmp
)) {
6079 log_warning("Editing \"%s\" canceled: temporary file is empty", *original
);
6082 r
= rename(*tmp
, *original
);
6084 r
= log_error_errno(errno
, "Failed to rename \"%s\" to \"%s\": %m", *tmp
, *original
);
6089 if (!arg_no_reload
&& bus
&& !avoid_bus())
6090 r
= daemon_reload(bus
, args
);
6093 STRV_FOREACH_PAIR(original
, tmp
, paths
)
6094 unlink_noerrno(*tmp
);
6099 static void systemctl_help(void) {
6101 pager_open_if_enabled();
6103 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
6104 "Query or send control commands to the systemd manager.\n\n"
6105 " -h --help Show this help\n"
6106 " --version Show package version\n"
6107 " --system Connect to system manager\n"
6108 " --user Connect to user service manager\n"
6109 " -H --host=[USER@]HOST\n"
6110 " Operate on remote host\n"
6111 " -M --machine=CONTAINER\n"
6112 " Operate on local container\n"
6113 " -t --type=TYPE List units of a particular type\n"
6114 " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n"
6115 " -p --property=NAME Show only properties by this name\n"
6116 " -a --all Show all loaded units/properties, including dead/empty\n"
6117 " ones. To list all units installed on the system, use\n"
6118 " the 'list-unit-files' command instead.\n"
6119 " -l --full Don't ellipsize unit names on output\n"
6120 " -r --recursive Show unit list of host and local containers\n"
6121 " --reverse Show reverse dependencies with 'list-dependencies'\n"
6122 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
6123 " queueing a new job\n"
6124 " --show-types When showing sockets, explicitly show their type\n"
6125 " -i --ignore-inhibitors\n"
6126 " When shutting down or sleeping, ignore inhibitors\n"
6127 " --kill-who=WHO Who to send signal to\n"
6128 " -s --signal=SIGNAL Which signal to send\n"
6129 " --now Start or stop unit in addition to enabling or disabling it\n"
6130 " -q --quiet Suppress output\n"
6131 " --no-block Do not wait until operation finished\n"
6132 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6133 " --no-reload Don't reload daemon after en-/dis-abling unit files\n"
6134 " --no-legend Do not print a legend (column headers and hints)\n"
6135 " --no-pager Do not pipe output into a pager\n"
6136 " --no-ask-password\n"
6137 " Do not ask for system passwords\n"
6138 " --global Enable/disable unit files globally\n"
6139 " --runtime Enable unit files only temporarily until next reboot\n"
6140 " -f --force When enabling unit files, override existing symlinks\n"
6141 " When shutting down, execute action immediately\n"
6142 " --preset-mode= Apply only enable, only disable, or all presets\n"
6143 " --root=PATH Enable unit files in the specified root directory\n"
6144 " -n --lines=INTEGER Number of journal entries to show\n"
6145 " -o --output=STRING Change journal output mode (short, short-iso,\n"
6146 " short-precise, short-monotonic, verbose,\n"
6147 " export, json, json-pretty, json-sse, cat)\n"
6148 " --firmware-setup Tell the firmware to show the setup menu on next boot\n"
6149 " --plain Print unit dependencies as a list instead of a tree\n\n"
6151 " list-units [PATTERN...] List loaded units\n"
6152 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
6153 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
6154 " start NAME... Start (activate) one or more units\n"
6155 " stop NAME... Stop (deactivate) one or more units\n"
6156 " reload NAME... Reload one or more units\n"
6157 " restart NAME... Start or restart one or more units\n"
6158 " try-restart NAME... Restart one or more units if active\n"
6159 " reload-or-restart NAME... Reload one or more units if possible,\n"
6160 " otherwise start or restart\n"
6161 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
6162 " otherwise restart if active\n"
6163 " isolate NAME Start one unit and stop all others\n"
6164 " kill NAME... Send signal to processes of a unit\n"
6165 " is-active PATTERN... Check whether units are active\n"
6166 " is-failed PATTERN... Check whether units are failed\n"
6167 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
6168 " show [PATTERN...|JOB...] Show properties of one or more\n"
6169 " units/jobs or the manager\n"
6170 " cat PATTERN... Show files and drop-ins of one or more units\n"
6171 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
6172 " help PATTERN...|PID... Show manual for one or more units\n"
6173 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
6175 " list-dependencies [NAME] Recursively show units which are required\n"
6176 " or wanted by this unit or by which this\n"
6177 " unit is required or wanted\n\n"
6178 "Unit File Commands:\n"
6179 " list-unit-files [PATTERN...] List installed unit files\n"
6180 " enable NAME... Enable one or more unit files\n"
6181 " disable NAME... Disable one or more unit files\n"
6182 " reenable NAME... Reenable one or more unit files\n"
6183 " preset NAME... Enable/disable one or more unit files\n"
6184 " based on preset configuration\n"
6185 " preset-all Enable/disable all unit files based on\n"
6186 " preset configuration\n"
6187 " is-enabled NAME... Check whether unit files are enabled\n"
6188 " mask NAME... Mask one or more units\n"
6189 " unmask NAME... Unmask one or more units\n"
6190 " link PATH... Link one or more units files into\n"
6191 " the search path\n"
6192 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
6193 " on specified one or more units\n"
6194 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
6195 " on specified one or more units\n"
6196 " edit NAME... Edit one or more unit files\n"
6197 " get-default Get the name of the default target\n"
6198 " set-default NAME Set the default target\n\n"
6199 "Machine Commands:\n"
6200 " list-machines [PATTERN...] List local containers and host\n\n"
6202 " list-jobs [PATTERN...] List jobs\n"
6203 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
6204 "Snapshot Commands:\n"
6205 " snapshot [NAME] Create a snapshot\n"
6206 " delete NAME... Remove one or more snapshots\n\n"
6207 "Environment Commands:\n"
6208 " show-environment Dump environment\n"
6209 " set-environment NAME=VALUE... Set one or more environment variables\n"
6210 " unset-environment NAME... Unset one or more environment variables\n"
6211 " import-environment [NAME...] Import all or some environment variables\n\n"
6212 "Manager Lifecycle Commands:\n"
6213 " daemon-reload Reload systemd manager configuration\n"
6214 " daemon-reexec Reexecute systemd manager\n\n"
6215 "System Commands:\n"
6216 " is-system-running Check whether system is fully running\n"
6217 " default Enter system default mode\n"
6218 " rescue Enter system rescue mode\n"
6219 " emergency Enter system emergency mode\n"
6220 " halt Shut down and halt the system\n"
6221 " poweroff Shut down and power-off the system\n"
6222 " reboot [ARG] Shut down and reboot the system\n"
6223 " kexec Shut down and reboot the system with kexec\n"
6224 " exit [EXIT_CODE] Request user instance or container exit\n"
6225 " switch-root ROOT [INIT] Change to a different root file system\n"
6226 " suspend Suspend the system\n"
6227 " hibernate Hibernate the system\n"
6228 " hybrid-sleep Hibernate and suspend the system\n",
6229 program_invocation_short_name
);
6232 static void halt_help(void) {
6233 printf("%s [OPTIONS...]%s\n\n"
6234 "%s the system.\n\n"
6235 " --help Show this help\n"
6236 " --halt Halt the machine\n"
6237 " -p --poweroff Switch off the machine\n"
6238 " --reboot Reboot the machine\n"
6239 " -f --force Force immediate halt/power-off/reboot\n"
6240 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
6241 " -d --no-wtmp Don't write wtmp record\n"
6242 " --no-wall Don't send wall message before halt/power-off/reboot\n",
6243 program_invocation_short_name
,
6244 arg_action
== ACTION_REBOOT
? " [ARG]" : "",
6245 arg_action
== ACTION_REBOOT
? "Reboot" :
6246 arg_action
== ACTION_POWEROFF
? "Power off" :
6250 static void shutdown_help(void) {
6251 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
6252 "Shut down the system.\n\n"
6253 " --help Show this help\n"
6254 " -H --halt Halt the machine\n"
6255 " -P --poweroff Power-off the machine\n"
6256 " -r --reboot Reboot the machine\n"
6257 " -h Equivalent to --poweroff, overridden by --halt\n"
6258 " -k Don't halt/power-off/reboot, just send warnings\n"
6259 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6260 " -c Cancel a pending shutdown\n",
6261 program_invocation_short_name
);
6264 static void telinit_help(void) {
6265 printf("%s [OPTIONS...] {COMMAND}\n\n"
6266 "Send control commands to the init daemon.\n\n"
6267 " --help Show this help\n"
6268 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
6270 " 0 Power-off the machine\n"
6271 " 6 Reboot the machine\n"
6272 " 2, 3, 4, 5 Start runlevelX.target unit\n"
6273 " 1, s, S Enter rescue mode\n"
6274 " q, Q Reload init daemon configuration\n"
6275 " u, U Reexecute init daemon\n",
6276 program_invocation_short_name
);
6279 static void runlevel_help(void) {
6280 printf("%s [OPTIONS...]\n\n"
6281 "Prints the previous and current runlevel of the init system.\n\n"
6282 " --help Show this help\n",
6283 program_invocation_short_name
);
6286 static void help_types(void) {
6291 puts("Available unit types:");
6292 for (i
= 0; i
< _UNIT_TYPE_MAX
; i
++) {
6293 t
= unit_type_to_string(i
);
6299 static int systemctl_parse_argv(int argc
, char *argv
[]) {
6308 ARG_IGNORE_DEPENDENCIES
,
6320 ARG_NO_ASK_PASSWORD
,
6333 static const struct option options
[] = {
6334 { "help", no_argument
, NULL
, 'h' },
6335 { "version", no_argument
, NULL
, ARG_VERSION
},
6336 { "type", required_argument
, NULL
, 't' },
6337 { "property", required_argument
, NULL
, 'p' },
6338 { "all", no_argument
, NULL
, 'a' },
6339 { "reverse", no_argument
, NULL
, ARG_REVERSE
},
6340 { "after", no_argument
, NULL
, ARG_AFTER
},
6341 { "before", no_argument
, NULL
, ARG_BEFORE
},
6342 { "show-types", no_argument
, NULL
, ARG_SHOW_TYPES
},
6343 { "failed", no_argument
, NULL
, ARG_FAILED
}, /* compatibility only */
6344 { "full", no_argument
, NULL
, 'l' },
6345 { "job-mode", required_argument
, NULL
, ARG_JOB_MODE
},
6346 { "fail", no_argument
, NULL
, ARG_FAIL
}, /* compatibility only */
6347 { "irreversible", no_argument
, NULL
, ARG_IRREVERSIBLE
}, /* compatibility only */
6348 { "ignore-dependencies", no_argument
, NULL
, ARG_IGNORE_DEPENDENCIES
}, /* compatibility only */
6349 { "ignore-inhibitors", no_argument
, NULL
, 'i' },
6350 { "user", no_argument
, NULL
, ARG_USER
},
6351 { "system", no_argument
, NULL
, ARG_SYSTEM
},
6352 { "global", no_argument
, NULL
, ARG_GLOBAL
},
6353 { "no-block", no_argument
, NULL
, ARG_NO_BLOCK
},
6354 { "no-legend", no_argument
, NULL
, ARG_NO_LEGEND
},
6355 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
6356 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6357 { "quiet", no_argument
, NULL
, 'q' },
6358 { "root", required_argument
, NULL
, ARG_ROOT
},
6359 { "force", no_argument
, NULL
, ARG_FORCE
},
6360 { "no-reload", no_argument
, NULL
, ARG_NO_RELOAD
},
6361 { "kill-who", required_argument
, NULL
, ARG_KILL_WHO
},
6362 { "signal", required_argument
, NULL
, 's' },
6363 { "no-ask-password", no_argument
, NULL
, ARG_NO_ASK_PASSWORD
},
6364 { "host", required_argument
, NULL
, 'H' },
6365 { "machine", required_argument
, NULL
, 'M' },
6366 { "runtime", no_argument
, NULL
, ARG_RUNTIME
},
6367 { "lines", required_argument
, NULL
, 'n' },
6368 { "output", required_argument
, NULL
, 'o' },
6369 { "plain", no_argument
, NULL
, ARG_PLAIN
},
6370 { "state", required_argument
, NULL
, ARG_STATE
},
6371 { "recursive", no_argument
, NULL
, 'r' },
6372 { "preset-mode", required_argument
, NULL
, ARG_PRESET_MODE
},
6373 { "firmware-setup", no_argument
, NULL
, ARG_FIRMWARE_SETUP
},
6374 { "now", no_argument
, NULL
, ARG_NOW
},
6375 { "message", required_argument
, NULL
, ARG_MESSAGE
},
6384 /* we default to allowing interactive authorization only in systemctl (not in the legacy commands) */
6385 arg_ask_password
= true;
6387 while ((c
= getopt_long(argc
, argv
, "ht:p:alqfs:H:M:n:o:ir", options
, NULL
)) >= 0)
6399 const char *word
, *state
;
6402 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
6403 _cleanup_free_
char *type
;
6405 type
= strndup(word
, size
);
6409 if (streq(type
, "help")) {
6414 if (unit_type_from_string(type
) >= 0) {
6415 if (strv_push(&arg_types
, type
))
6421 /* It's much nicer to use --state= for
6422 * load states, but let's support this
6423 * in --types= too for compatibility
6424 * with old versions */
6425 if (unit_load_state_from_string(optarg
) >= 0) {
6426 if (strv_push(&arg_states
, type
) < 0)
6432 log_error("Unknown unit type or load state '%s'.", type
);
6433 log_info("Use -t help to see a list of allowed values.");
6441 /* Make sure that if the empty property list
6442 was specified, we won't show any properties. */
6443 if (isempty(optarg
) && !arg_properties
) {
6444 arg_properties
= new0(char*, 1);
6445 if (!arg_properties
)
6448 const char *word
, *state
;
6451 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
6454 prop
= strndup(word
, size
);
6458 if (strv_consume(&arg_properties
, prop
) < 0)
6463 /* If the user asked for a particular
6464 * property, show it to him, even if it is
6476 arg_dependency
= DEPENDENCY_REVERSE
;
6480 arg_dependency
= DEPENDENCY_AFTER
;
6484 arg_dependency
= DEPENDENCY_BEFORE
;
6487 case ARG_SHOW_TYPES
:
6488 arg_show_types
= true;
6492 arg_job_mode
= optarg
;
6496 arg_job_mode
= "fail";
6499 case ARG_IRREVERSIBLE
:
6500 arg_job_mode
= "replace-irreversibly";
6503 case ARG_IGNORE_DEPENDENCIES
:
6504 arg_job_mode
= "ignore-dependencies";
6508 arg_scope
= UNIT_FILE_USER
;
6512 arg_scope
= UNIT_FILE_SYSTEM
;
6516 arg_scope
= UNIT_FILE_GLOBAL
;
6520 arg_no_block
= true;
6524 arg_no_legend
= true;
6528 arg_no_pager
= true;
6544 if (strv_extend(&arg_states
, "failed") < 0)
6562 arg_no_reload
= true;
6566 arg_kill_who
= optarg
;
6570 if ((arg_signal
= signal_from_string_try_harder(optarg
)) < 0) {
6571 log_error("Failed to parse signal string %s.", optarg
);
6576 case ARG_NO_ASK_PASSWORD
:
6577 arg_ask_password
= false;
6581 arg_transport
= BUS_TRANSPORT_REMOTE
;
6586 arg_transport
= BUS_TRANSPORT_MACHINE
;
6595 if (safe_atou(optarg
, &arg_lines
) < 0) {
6596 log_error("Failed to parse lines '%s'", optarg
);
6602 arg_output
= output_mode_from_string(optarg
);
6603 if (arg_output
< 0) {
6604 log_error("Unknown output '%s'.", optarg
);
6610 arg_ignore_inhibitors
= true;
6617 case ARG_FIRMWARE_SETUP
:
6618 arg_firmware_setup
= true;
6622 const char *word
, *state
;
6625 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
6628 s
= strndup(word
, size
);
6632 if (strv_consume(&arg_states
, s
) < 0)
6639 if (geteuid() != 0) {
6640 log_error("--recursive requires root privileges.");
6644 arg_recursive
= true;
6647 case ARG_PRESET_MODE
:
6649 arg_preset_mode
= unit_file_preset_mode_from_string(optarg
);
6650 if (arg_preset_mode
< 0) {
6651 log_error("Failed to parse preset mode: %s.", optarg
);
6662 if (strv_extend(&arg_wall
, optarg
) < 0)
6670 assert_not_reached("Unhandled option");
6673 if (arg_transport
!= BUS_TRANSPORT_LOCAL
&& arg_scope
!= UNIT_FILE_SYSTEM
) {
6674 log_error("Cannot access user instance remotely.");
6681 static int halt_parse_argv(int argc
, char *argv
[]) {
6690 static const struct option options
[] = {
6691 { "help", no_argument
, NULL
, ARG_HELP
},
6692 { "halt", no_argument
, NULL
, ARG_HALT
},
6693 { "poweroff", no_argument
, NULL
, 'p' },
6694 { "reboot", no_argument
, NULL
, ARG_REBOOT
},
6695 { "force", no_argument
, NULL
, 'f' },
6696 { "wtmp-only", no_argument
, NULL
, 'w' },
6697 { "no-wtmp", no_argument
, NULL
, 'd' },
6698 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6707 if (utmp_get_runlevel(&runlevel
, NULL
) >= 0)
6708 if (runlevel
== '0' || runlevel
== '6')
6711 while ((c
= getopt_long(argc
, argv
, "pfwdnih", options
, NULL
)) >= 0)
6719 arg_action
= ACTION_HALT
;
6723 if (arg_action
!= ACTION_REBOOT
)
6724 arg_action
= ACTION_POWEROFF
;
6728 arg_action
= ACTION_REBOOT
;
6750 /* Compatibility nops */
6757 assert_not_reached("Unhandled option");
6760 if (arg_action
== ACTION_REBOOT
&& (argc
== optind
|| argc
== optind
+ 1)) {
6761 r
= update_reboot_param_file(argc
== optind
+ 1 ? argv
[optind
] : NULL
);
6764 } else if (optind
< argc
) {
6765 log_error("Too many arguments.");
6772 static int parse_time_spec(const char *t
, usec_t
*_u
) {
6776 if (streq(t
, "now"))
6778 else if (!strchr(t
, ':')) {
6781 if (safe_atou64(t
, &u
) < 0)
6784 *_u
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
* u
;
6793 hour
= strtol(t
, &e
, 10);
6794 if (errno
> 0 || *e
!= ':' || hour
< 0 || hour
> 23)
6797 minute
= strtol(e
+1, &e
, 10);
6798 if (errno
> 0 || *e
!= 0 || minute
< 0 || minute
> 59)
6801 n
= now(CLOCK_REALTIME
);
6802 s
= (time_t) (n
/ USEC_PER_SEC
);
6804 assert_se(localtime_r(&s
, &tm
));
6806 tm
.tm_hour
= (int) hour
;
6807 tm
.tm_min
= (int) minute
;
6810 assert_se(s
= mktime(&tm
));
6812 *_u
= (usec_t
) s
* USEC_PER_SEC
;
6815 *_u
+= USEC_PER_DAY
;
6821 static int shutdown_parse_argv(int argc
, char *argv
[]) {
6828 static const struct option options
[] = {
6829 { "help", no_argument
, NULL
, ARG_HELP
},
6830 { "halt", no_argument
, NULL
, 'H' },
6831 { "poweroff", no_argument
, NULL
, 'P' },
6832 { "reboot", no_argument
, NULL
, 'r' },
6833 { "kexec", no_argument
, NULL
, 'K' }, /* not documented extension */
6834 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6843 while ((c
= getopt_long(argc
, argv
, "HPrhkKt:afFc", options
, NULL
)) >= 0)
6851 arg_action
= ACTION_HALT
;
6855 arg_action
= ACTION_POWEROFF
;
6860 arg_action
= ACTION_KEXEC
;
6862 arg_action
= ACTION_REBOOT
;
6866 arg_action
= ACTION_KEXEC
;
6870 if (arg_action
!= ACTION_HALT
)
6871 arg_action
= ACTION_POWEROFF
;
6886 /* Compatibility nops */
6890 arg_action
= ACTION_CANCEL_SHUTDOWN
;
6897 assert_not_reached("Unhandled option");
6900 if (argc
> optind
&& arg_action
!= ACTION_CANCEL_SHUTDOWN
) {
6901 r
= parse_time_spec(argv
[optind
], &arg_when
);
6903 log_error("Failed to parse time specification: %s", argv
[optind
]);
6907 arg_when
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
;
6909 if (argc
> optind
&& arg_action
== ACTION_CANCEL_SHUTDOWN
)
6910 /* No time argument for shutdown cancel */
6911 arg_wall
= argv
+ optind
;
6912 else if (argc
> optind
+ 1)
6913 /* We skip the time argument */
6914 arg_wall
= argv
+ optind
+ 1;
6921 static int telinit_parse_argv(int argc
, char *argv
[]) {
6928 static const struct option options
[] = {
6929 { "help", no_argument
, NULL
, ARG_HELP
},
6930 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6934 static const struct {
6938 { '0', ACTION_POWEROFF
},
6939 { '6', ACTION_REBOOT
},
6940 { '1', ACTION_RESCUE
},
6941 { '2', ACTION_RUNLEVEL2
},
6942 { '3', ACTION_RUNLEVEL3
},
6943 { '4', ACTION_RUNLEVEL4
},
6944 { '5', ACTION_RUNLEVEL5
},
6945 { 's', ACTION_RESCUE
},
6946 { 'S', ACTION_RESCUE
},
6947 { 'q', ACTION_RELOAD
},
6948 { 'Q', ACTION_RELOAD
},
6949 { 'u', ACTION_REEXEC
},
6950 { 'U', ACTION_REEXEC
}
6959 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
6974 assert_not_reached("Unhandled option");
6977 if (optind
>= argc
) {
6978 log_error("%s: required argument missing.",
6979 program_invocation_short_name
);
6983 if (optind
+ 1 < argc
) {
6984 log_error("Too many arguments.");
6988 if (strlen(argv
[optind
]) != 1) {
6989 log_error("Expected single character argument.");
6993 for (i
= 0; i
< ELEMENTSOF(table
); i
++)
6994 if (table
[i
].from
== argv
[optind
][0])
6997 if (i
>= ELEMENTSOF(table
)) {
6998 log_error("Unknown command '%s'.", argv
[optind
]);
7002 arg_action
= table
[i
].to
;
7009 static int runlevel_parse_argv(int argc
, char *argv
[]) {
7015 static const struct option options
[] = {
7016 { "help", no_argument
, NULL
, ARG_HELP
},
7025 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
7036 assert_not_reached("Unhandled option");
7039 if (optind
< argc
) {
7040 log_error("Too many arguments.");
7047 static int parse_argv(int argc
, char *argv
[]) {
7051 if (program_invocation_short_name
) {
7053 if (strstr(program_invocation_short_name
, "halt")) {
7054 arg_action
= ACTION_HALT
;
7055 return halt_parse_argv(argc
, argv
);
7056 } else if (strstr(program_invocation_short_name
, "poweroff")) {
7057 arg_action
= ACTION_POWEROFF
;
7058 return halt_parse_argv(argc
, argv
);
7059 } else if (strstr(program_invocation_short_name
, "reboot")) {
7061 arg_action
= ACTION_KEXEC
;
7063 arg_action
= ACTION_REBOOT
;
7064 return halt_parse_argv(argc
, argv
);
7065 } else if (strstr(program_invocation_short_name
, "shutdown")) {
7066 arg_action
= ACTION_POWEROFF
;
7067 return shutdown_parse_argv(argc
, argv
);
7068 } else if (strstr(program_invocation_short_name
, "init")) {
7070 if (sd_booted() > 0) {
7071 arg_action
= _ACTION_INVALID
;
7072 return telinit_parse_argv(argc
, argv
);
7074 /* Hmm, so some other init system is
7075 * running, we need to forward this
7076 * request to it. For now we simply
7077 * guess that it is Upstart. */
7079 execv(TELINIT
, argv
);
7081 log_error("Couldn't find an alternative telinit implementation to spawn.");
7085 } else if (strstr(program_invocation_short_name
, "runlevel")) {
7086 arg_action
= ACTION_RUNLEVEL
;
7087 return runlevel_parse_argv(argc
, argv
);
7091 arg_action
= ACTION_SYSTEMCTL
;
7092 return systemctl_parse_argv(argc
, argv
);
7095 _pure_
static int action_to_runlevel(void) {
7097 static const char table
[_ACTION_MAX
] = {
7098 [ACTION_HALT
] = '0',
7099 [ACTION_POWEROFF
] = '0',
7100 [ACTION_REBOOT
] = '6',
7101 [ACTION_RUNLEVEL2
] = '2',
7102 [ACTION_RUNLEVEL3
] = '3',
7103 [ACTION_RUNLEVEL4
] = '4',
7104 [ACTION_RUNLEVEL5
] = '5',
7105 [ACTION_RESCUE
] = '1'
7108 assert(arg_action
< _ACTION_MAX
);
7110 return table
[arg_action
];
7113 static int talk_initctl(void) {
7115 struct init_request request
= {
7116 .magic
= INIT_MAGIC
,
7118 .cmd
= INIT_CMD_RUNLVL
7121 _cleanup_close_
int fd
= -1;
7125 rl
= action_to_runlevel();
7129 request
.runlevel
= rl
;
7131 fd
= open(INIT_FIFO
, O_WRONLY
|O_NDELAY
|O_CLOEXEC
|O_NOCTTY
);
7133 if (errno
== ENOENT
)
7136 log_error_errno(errno
, "Failed to open "INIT_FIFO
": %m");
7140 r
= loop_write(fd
, &request
, sizeof(request
), false);
7142 return log_error_errno(r
, "Failed to write to "INIT_FIFO
": %m");
7147 static int systemctl_main(sd_bus
*bus
, int argc
, char *argv
[], int bus_error
) {
7149 static const struct {
7157 int (* const dispatch
)(sd_bus
*bus
, char **args
);
7163 { "list-units", MORE
, 0, list_units
},
7164 { "list-unit-files", MORE
, 1, list_unit_files
, NOBUS
},
7165 { "list-sockets", MORE
, 1, list_sockets
},
7166 { "list-timers", MORE
, 1, list_timers
},
7167 { "list-jobs", MORE
, 1, list_jobs
},
7168 { "list-machines", MORE
, 1, list_machines
},
7169 { "clear-jobs", EQUAL
, 1, daemon_reload
},
7170 { "cancel", MORE
, 2, cancel_job
},
7171 { "start", MORE
, 2, start_unit
},
7172 { "stop", MORE
, 2, start_unit
},
7173 { "condstop", MORE
, 2, start_unit
}, /* For compatibility with ALTLinux */
7174 { "reload", MORE
, 2, start_unit
},
7175 { "restart", MORE
, 2, start_unit
},
7176 { "try-restart", MORE
, 2, start_unit
},
7177 { "reload-or-restart", MORE
, 2, start_unit
},
7178 { "reload-or-try-restart", MORE
, 2, start_unit
},
7179 { "force-reload", MORE
, 2, start_unit
}, /* For compatibility with SysV */
7180 { "condreload", MORE
, 2, start_unit
}, /* For compatibility with ALTLinux */
7181 { "condrestart", MORE
, 2, start_unit
}, /* For compatibility with RH */
7182 { "isolate", EQUAL
, 2, start_unit
},
7183 { "kill", MORE
, 2, kill_unit
},
7184 { "is-active", MORE
, 2, check_unit_active
},
7185 { "check", MORE
, 2, check_unit_active
},
7186 { "is-failed", MORE
, 2, check_unit_failed
},
7187 { "show", MORE
, 1, show
},
7188 { "cat", MORE
, 2, cat
, NOBUS
},
7189 { "status", MORE
, 1, show
},
7190 { "help", MORE
, 2, show
},
7191 { "snapshot", LESS
, 2, snapshot
},
7192 { "delete", MORE
, 2, delete_snapshot
},
7193 { "daemon-reload", EQUAL
, 1, daemon_reload
},
7194 { "daemon-reexec", EQUAL
, 1, daemon_reload
},
7195 { "show-environment", EQUAL
, 1, show_environment
},
7196 { "set-environment", MORE
, 2, set_environment
},
7197 { "unset-environment", MORE
, 2, set_environment
},
7198 { "import-environment", MORE
, 1, import_environment
},
7199 { "halt", EQUAL
, 1, start_special
, FORCE
},
7200 { "poweroff", EQUAL
, 1, start_special
, FORCE
},
7201 { "reboot", MORE
, 1, start_special
, FORCE
},
7202 { "kexec", EQUAL
, 1, start_special
},
7203 { "suspend", EQUAL
, 1, start_special
},
7204 { "hibernate", EQUAL
, 1, start_special
},
7205 { "hybrid-sleep", EQUAL
, 1, start_special
},
7206 { "default", EQUAL
, 1, start_special
},
7207 { "rescue", EQUAL
, 1, start_special
},
7208 { "emergency", EQUAL
, 1, start_special
},
7209 { "exit", LESS
, 2, start_special
},
7210 { "reset-failed", MORE
, 1, reset_failed
},
7211 { "enable", MORE
, 2, enable_unit
, NOBUS
},
7212 { "disable", MORE
, 2, enable_unit
, NOBUS
},
7213 { "is-enabled", MORE
, 2, unit_is_enabled
, NOBUS
},
7214 { "reenable", MORE
, 2, enable_unit
, NOBUS
},
7215 { "preset", MORE
, 2, enable_unit
, NOBUS
},
7216 { "preset-all", EQUAL
, 1, preset_all
, NOBUS
},
7217 { "mask", MORE
, 2, enable_unit
, NOBUS
},
7218 { "unmask", MORE
, 2, enable_unit
, NOBUS
},
7219 { "link", MORE
, 2, enable_unit
, NOBUS
},
7220 { "switch-root", MORE
, 2, switch_root
},
7221 { "list-dependencies", LESS
, 2, list_dependencies
},
7222 { "set-default", EQUAL
, 2, set_default
, NOBUS
},
7223 { "get-default", EQUAL
, 1, get_default
, NOBUS
},
7224 { "set-property", MORE
, 3, set_property
},
7225 { "is-system-running", EQUAL
, 1, is_system_running
},
7226 { "add-wants", MORE
, 3, add_dependency
, NOBUS
},
7227 { "add-requires", MORE
, 3, add_dependency
, NOBUS
},
7228 { "edit", MORE
, 2, edit
, NOBUS
},
7237 left
= argc
- optind
;
7239 /* Special rule: no arguments (left == 0) means "list-units" */
7241 if (streq(argv
[optind
], "help") && !argv
[optind
+1]) {
7242 log_error("This command expects one or more "
7243 "unit names. Did you mean --help?");
7247 for (; verb
->verb
; verb
++)
7248 if (streq(argv
[optind
], verb
->verb
))
7251 log_error("Unknown operation '%s'.", argv
[optind
]);
7256 switch (verb
->argc_cmp
) {
7259 if (left
!= verb
->argc
) {
7260 log_error("Invalid number of arguments.");
7267 if (left
< verb
->argc
) {
7268 log_error("Too few arguments.");
7275 if (left
> verb
->argc
) {
7276 log_error("Too many arguments.");
7283 assert_not_reached("Unknown comparison operator.");
7286 /* Require a bus connection for all operations but
7288 if (verb
->bus
== NOBUS
) {
7289 if (!bus
&& !avoid_bus()) {
7290 log_error_errno(bus_error
, "Failed to get D-Bus connection: %m");
7295 if (running_in_chroot() > 0) {
7296 log_info("Running in chroot, ignoring request.");
7300 if ((verb
->bus
!= FORCE
|| arg_force
<= 0) && !bus
) {
7301 log_error_errno(bus_error
, "Failed to get D-Bus connection: %m");
7306 return verb
->dispatch(bus
, argv
+ optind
);
7309 static int reload_with_fallback(sd_bus
*bus
) {
7312 /* First, try systemd via D-Bus. */
7313 if (daemon_reload(bus
, NULL
) >= 0)
7317 /* Nothing else worked, so let's try signals */
7318 assert(arg_action
== ACTION_RELOAD
|| arg_action
== ACTION_REEXEC
);
7320 if (kill(1, arg_action
== ACTION_RELOAD
? SIGHUP
: SIGTERM
) < 0)
7321 return log_error_errno(errno
, "kill() failed: %m");
7326 static int start_with_fallback(sd_bus
*bus
) {
7329 /* First, try systemd via D-Bus. */
7330 if (start_unit(bus
, NULL
) >= 0)
7334 /* Nothing else worked, so let's try
7336 if (talk_initctl() > 0)
7339 log_error("Failed to talk to init daemon.");
7343 static int halt_now(enum action a
) {
7345 /* The kernel will automaticall flush ATA disks and suchlike
7346 * on reboot(), but the file systems need to be synce'd
7347 * explicitly in advance. */
7350 /* Make sure C-A-D is handled by the kernel from this point
7352 reboot(RB_ENABLE_CAD
);
7357 log_info("Halting.");
7358 reboot(RB_HALT_SYSTEM
);
7361 case ACTION_POWEROFF
:
7362 log_info("Powering off.");
7363 reboot(RB_POWER_OFF
);
7367 case ACTION_REBOOT
: {
7368 _cleanup_free_
char *param
= NULL
;
7370 if (read_one_line_file(REBOOT_PARAM_FILE
, ¶m
) >= 0) {
7371 log_info("Rebooting with argument '%s'.", param
);
7372 syscall(SYS_reboot
, LINUX_REBOOT_MAGIC1
, LINUX_REBOOT_MAGIC2
,
7373 LINUX_REBOOT_CMD_RESTART2
, param
);
7376 log_info("Rebooting.");
7377 reboot(RB_AUTOBOOT
);
7382 assert_not_reached("Unknown action.");
7386 static int logind_schedule_shutdown(void) {
7389 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
7390 _cleanup_bus_flush_close_unref_ sd_bus
*b
= NULL
;
7391 char date
[FORMAT_TIMESTAMP_MAX
];
7395 assert(geteuid() == 0);
7398 log_error("Unable to perform operation without bus connection.");
7402 r
= sd_bus_open_system(&b
);
7404 return log_error_errno(r
, "Unable to open system bus: %m");
7406 (void) logind_set_wall_message(b
);
7408 switch (arg_action
) {
7412 case ACTION_POWEROFF
:
7413 action
= "poweroff";
7424 action
= strjoina("dry-", action
);
7426 r
= sd_bus_call_method(
7428 "org.freedesktop.login1",
7429 "/org/freedesktop/login1",
7430 "org.freedesktop.login1.Manager",
7438 return log_warning_errno(r
, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s", bus_error_message(&error
, r
));
7440 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.", format_timestamp(date
, sizeof(date
), arg_when
));
7443 log_error("Cannot schedule shutdown without logind support, proceeding with immediate shutdown.");
7448 static int halt_main(sd_bus
*bus
) {
7451 r
= logind_check_inhibitors(bus
, arg_action
);
7455 if (geteuid() != 0) {
7459 log_error("Must be root.");
7463 /* Try logind if we are a normal user and no special
7464 * mode applies. Maybe PolicyKit allows us to shutdown
7466 if (IN_SET(arg_action
,
7469 r
= logind_reboot(bus
, arg_action
);
7472 if (IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
7473 /* requested operation is not supported or already in progress */
7475 /* on all other errors, try low-level operation */
7480 r
= logind_schedule_shutdown();
7485 if (!arg_dry
&& !arg_force
)
7486 return start_with_fallback(bus
);
7488 assert(geteuid() == 0);
7491 if (sd_booted() > 0)
7492 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
7494 r
= utmp_put_shutdown();
7496 log_warning_errno(r
, "Failed to write utmp record: %m");
7503 r
= halt_now(arg_action
);
7504 log_error_errno(r
, "Failed to reboot: %m");
7509 static int runlevel_main(void) {
7510 int r
, runlevel
, previous
;
7512 r
= utmp_get_runlevel(&runlevel
, &previous
);
7519 previous
<= 0 ? 'N' : previous
,
7520 runlevel
<= 0 ? 'N' : runlevel
);
7525 static int logind_cancel_shutdown(void) {
7527 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
7528 _cleanup_bus_flush_close_unref_ sd_bus
*b
= NULL
;
7532 log_error("Unable to perform operation without bus connection.");
7536 r
= sd_bus_open_system(&b
);
7538 return log_error_errno(r
, "Unable to open system bus: %m");
7540 (void) logind_set_wall_message(b
);
7542 r
= sd_bus_call_method(
7544 "org.freedesktop.login1",
7545 "/org/freedesktop/login1",
7546 "org.freedesktop.login1.Manager",
7547 "CancelScheduledShutdown",
7551 return log_warning_errno(r
, "Failed to talk to logind, shutdown hasn't been cancelled: %s", bus_error_message(&error
, r
));
7555 log_error("Not compiled with logind support, cannot cancel scheduled shutdowns.");
7560 int main(int argc
, char*argv
[]) {
7561 _cleanup_bus_flush_close_unref_ sd_bus
*bus
= NULL
;
7564 setlocale(LC_ALL
, "");
7565 log_parse_environment();
7568 /* Explicitly not on_tty() to avoid setting cached value.
7569 * This becomes relevant for piping output which might be
7571 original_stdout_is_tty
= isatty(STDOUT_FILENO
);
7573 r
= parse_argv(argc
, argv
);
7577 if (running_in_chroot() > 0 && arg_action
!= ACTION_SYSTEMCTL
) {
7578 log_info("Running in chroot, ignoring request.");
7584 r
= bus_open_transport_systemd(arg_transport
, arg_host
, arg_scope
!= UNIT_FILE_SYSTEM
, &bus
);
7587 sd_bus_set_allow_interactive_authorization(bus
, arg_ask_password
);
7589 /* systemctl_main() will print an error message for the bus
7590 * connection, but only if it needs to */
7592 switch (arg_action
) {
7594 case ACTION_SYSTEMCTL
:
7595 r
= systemctl_main(bus
, argc
, argv
, r
);
7599 case ACTION_POWEROFF
:
7605 case ACTION_RUNLEVEL2
:
7606 case ACTION_RUNLEVEL3
:
7607 case ACTION_RUNLEVEL4
:
7608 case ACTION_RUNLEVEL5
:
7610 case ACTION_EMERGENCY
:
7611 case ACTION_DEFAULT
:
7612 r
= start_with_fallback(bus
);
7617 r
= reload_with_fallback(bus
);
7620 case ACTION_CANCEL_SHUTDOWN
:
7621 r
= logind_cancel_shutdown();
7624 case ACTION_RUNLEVEL
:
7625 r
= runlevel_main();
7628 case _ACTION_INVALID
:
7630 assert_not_reached("Unknown action");
7635 ask_password_agent_close();
7636 polkit_agent_close();
7638 strv_free(arg_types
);
7639 strv_free(arg_states
);
7640 strv_free(arg_properties
);
7642 sd_bus_default_flush_close();
7644 return r
< 0 ? EXIT_FAILURE
: r
;