1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
7 Copyright 2013 Marc-Antoine Perennou
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include <sys/reboot.h>
24 #include <linux/reboot.h>
33 #include <sys/socket.h>
36 #include "sd-daemon.h"
43 #include "utmp-wtmp.h"
46 #include "path-util.h"
48 #include "cgroup-show.h"
49 #include "cgroup-util.h"
51 #include "path-lookup.h"
52 #include "exit-status.h"
54 #include "unit-name.h"
56 #include "spawn-ask-password-agent.h"
57 #include "spawn-polkit-agent.h"
59 #include "logs-show.h"
60 #include "socket-util.h"
65 #include "bus-message.h"
66 #include "bus-error.h"
67 #include "bus-common-errors.h"
71 #include "formats-util.h"
72 #include "process-util.h"
73 #include "terminal-util.h"
74 #include "hostname-util.h"
75 #include "signal-util.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
= true;
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 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 char** strv_skip_first(char **strv
) {
150 if (strv_length(strv
) > 0)
155 static void pager_open_if_enabled(void) {
163 static void ask_password_agent_open_if_enabled(void) {
165 /* Open the password agent as a child process if necessary */
167 if (!arg_ask_password
)
170 if (arg_scope
!= UNIT_FILE_SYSTEM
)
173 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
176 ask_password_agent_open();
179 static void polkit_agent_open_if_enabled(void) {
181 /* Open the polkit agent as a child process if necessary */
183 if (!arg_ask_password
)
186 if (arg_scope
!= UNIT_FILE_SYSTEM
)
189 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
195 static OutputFlags
get_output_flags(void) {
197 arg_all
* OUTPUT_SHOW_ALL
|
198 arg_full
* OUTPUT_FULL_WIDTH
|
199 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH
|
200 on_tty() * OUTPUT_COLOR
|
201 !arg_quiet
* OUTPUT_WARN_CUTOFF
;
204 static int translate_bus_error_to_exit_status(int r
, const sd_bus_error
*error
) {
207 if (!sd_bus_error_is_set(error
))
210 if (sd_bus_error_has_name(error
, SD_BUS_ERROR_ACCESS_DENIED
) ||
211 sd_bus_error_has_name(error
, BUS_ERROR_ONLY_BY_DEPENDENCY
) ||
212 sd_bus_error_has_name(error
, BUS_ERROR_NO_ISOLATION
) ||
213 sd_bus_error_has_name(error
, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE
))
214 return EXIT_NOPERMISSION
;
216 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
))
217 return EXIT_NOTINSTALLED
;
219 if (sd_bus_error_has_name(error
, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE
) ||
220 sd_bus_error_has_name(error
, SD_BUS_ERROR_NOT_SUPPORTED
))
221 return EXIT_NOTIMPLEMENTED
;
223 if (sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
))
224 return EXIT_NOTCONFIGURED
;
232 static void warn_wall(enum action a
) {
233 static const char *table
[_ACTION_MAX
] = {
234 [ACTION_HALT
] = "The system is going down for system halt NOW!",
235 [ACTION_REBOOT
] = "The system is going down for reboot NOW!",
236 [ACTION_POWEROFF
] = "The system is going down for power-off NOW!",
237 [ACTION_KEXEC
] = "The system is going down for kexec reboot NOW!",
238 [ACTION_RESCUE
] = "The system is going down to rescue mode NOW!",
239 [ACTION_EMERGENCY
] = "The system is going down to emergency mode NOW!",
240 [ACTION_CANCEL_SHUTDOWN
] = "The system shutdown has been cancelled NOW!"
247 _cleanup_free_
char *p
;
249 p
= strv_join(arg_wall
, " ");
256 utmp_wall(p
, NULL
, NULL
, NULL
, NULL
);
264 utmp_wall(table
[a
], NULL
, NULL
, NULL
, NULL
);
267 static bool avoid_bus(void) {
269 if (running_in_chroot() > 0)
272 if (sd_booted() <= 0)
275 if (!isempty(arg_root
))
278 if (arg_scope
== UNIT_FILE_GLOBAL
)
284 static int compare_unit_info(const void *a
, const void *b
) {
285 const UnitInfo
*u
= a
, *v
= b
;
289 /* First, order by machine */
290 if (!u
->machine
&& v
->machine
)
292 if (u
->machine
&& !v
->machine
)
294 if (u
->machine
&& v
->machine
) {
295 r
= strcasecmp(u
->machine
, v
->machine
);
300 /* Second, order by unit type */
301 d1
= strrchr(u
->id
, '.');
302 d2
= strrchr(v
->id
, '.');
304 r
= strcasecmp(d1
, d2
);
309 /* Third, order by name */
310 return strcasecmp(u
->id
, v
->id
);
313 static bool output_show_unit(const UnitInfo
*u
, char **patterns
) {
314 if (!strv_fnmatch_or_empty(patterns
, u
->id
, FNM_NOESCAPE
))
320 dot
= strrchr(u
->id
, '.');
324 if (!strv_find(arg_types
, dot
+1))
334 if (streq(u
->active_state
, "inactive") || u
->following
[0])
340 static int output_units_list(const UnitInfo
*unit_infos
, unsigned c
) {
341 unsigned circle_len
= 0, id_len
, max_id_len
, load_len
, active_len
, sub_len
, job_len
, desc_len
;
343 unsigned n_shown
= 0;
346 max_id_len
= strlen("UNIT");
347 load_len
= strlen("LOAD");
348 active_len
= strlen("ACTIVE");
349 sub_len
= strlen("SUB");
350 job_len
= strlen("JOB");
353 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
354 max_id_len
= MAX(max_id_len
, strlen(u
->id
) + (u
->machine
? strlen(u
->machine
)+1 : 0));
355 load_len
= MAX(load_len
, strlen(u
->load_state
));
356 active_len
= MAX(active_len
, strlen(u
->active_state
));
357 sub_len
= MAX(sub_len
, strlen(u
->sub_state
));
359 if (u
->job_id
!= 0) {
360 job_len
= MAX(job_len
, strlen(u
->job_type
));
364 if (!arg_no_legend
&&
365 (streq(u
->active_state
, "failed") ||
366 STR_IN_SET(u
->load_state
, "error", "not-found", "masked")))
370 if (!arg_full
&& original_stdout_is_tty
) {
373 id_len
= MIN(max_id_len
, 25u);
374 basic_len
= circle_len
+ 5 + id_len
+ 5 + active_len
+ sub_len
;
377 basic_len
+= job_len
+ 1;
379 if (basic_len
< (unsigned) columns()) {
380 unsigned extra_len
, incr
;
381 extra_len
= columns() - basic_len
;
383 /* Either UNIT already got 25, or is fully satisfied.
384 * Grant up to 25 to DESC now. */
385 incr
= MIN(extra_len
, 25u);
389 /* split the remaining space between UNIT and DESC,
390 * but do not give UNIT more than it needs. */
392 incr
= MIN(extra_len
/ 2, max_id_len
- id_len
);
394 desc_len
+= extra_len
- incr
;
400 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
401 _cleanup_free_
char *e
= NULL
, *j
= NULL
;
402 const char *on_loaded
= "", *off_loaded
= "";
403 const char *on_active
= "", *off_active
= "";
404 const char *on_circle
= "", *off_circle
= "";
408 if (!n_shown
&& !arg_no_legend
) {
413 printf("%-*s %-*s %-*s %-*s ",
416 active_len
, "ACTIVE",
420 printf("%-*s ", job_len
, "JOB");
422 if (!arg_full
&& arg_no_pager
)
423 printf("%.*s\n", desc_len
, "DESCRIPTION");
425 printf("%s\n", "DESCRIPTION");
430 if (STR_IN_SET(u
->load_state
, "error", "not-found", "masked") && !arg_plain
) {
431 on_loaded
= ansi_highlight_red();
432 on_circle
= ansi_highlight_yellow();
433 off_loaded
= off_circle
= ansi_highlight_off();
435 } else if (streq(u
->active_state
, "failed") && !arg_plain
) {
436 on_circle
= on_active
= ansi_highlight_red();
437 off_circle
= off_active
= ansi_highlight_off();
442 j
= strjoin(u
->machine
, ":", u
->id
, NULL
);
451 e
= ellipsize(id
, id_len
, 33);
459 printf("%s%s%s ", on_circle
, circle
? draw_special_char(DRAW_BLACK_CIRCLE
) : " ", off_circle
);
461 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
462 on_active
, id_len
, id
, off_active
,
463 on_loaded
, load_len
, u
->load_state
, off_loaded
,
464 on_active
, active_len
, u
->active_state
,
465 sub_len
, u
->sub_state
, off_active
,
466 job_count
? job_len
+ 1 : 0, u
->job_id
? u
->job_type
: "");
469 printf("%.*s\n", desc_len
, u
->description
);
471 printf("%s\n", u
->description
);
474 if (!arg_no_legend
) {
475 const char *on
, *off
;
479 "LOAD = Reflects whether the unit definition was properly loaded.\n"
480 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
481 "SUB = The low-level unit activation state, values depend on unit type.");
482 puts(job_count
? "JOB = Pending job for the unit.\n" : "");
483 on
= ansi_highlight();
484 off
= ansi_highlight_off();
486 on
= ansi_highlight_red();
487 off
= ansi_highlight_off();
491 printf("%s%u loaded units listed.%s\n"
492 "To show all installed unit files use 'systemctl list-unit-files'.\n",
495 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
496 "To show all installed unit files use 'systemctl list-unit-files'.\n",
503 static int get_unit_list(
507 UnitInfo
**unit_infos
,
509 sd_bus_message
**_reply
) {
511 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
512 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
513 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
522 r
= sd_bus_message_new_method_call(
525 "org.freedesktop.systemd1",
526 "/org/freedesktop/systemd1",
527 "org.freedesktop.systemd1.Manager",
528 "ListUnitsFiltered");
531 return bus_log_create_error(r
);
533 r
= sd_bus_message_append_strv(m
, arg_states
);
535 return bus_log_create_error(r
);
537 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
539 log_error("Failed to list units: %s", bus_error_message(&error
, r
));
543 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssssouso)");
545 return bus_log_parse_error(r
);
547 while ((r
= bus_parse_unit_info(reply
, &u
)) > 0) {
550 if (!output_show_unit(&u
, patterns
))
553 if (!GREEDY_REALLOC(*unit_infos
, size
, c
+1))
556 (*unit_infos
)[c
++] = u
;
559 return bus_log_parse_error(r
);
561 r
= sd_bus_message_exit_container(reply
);
563 return bus_log_parse_error(r
);
571 static void message_set_freep(Set
**set
) {
574 while ((m
= set_steal_first(*set
)))
575 sd_bus_message_unref(m
);
580 static int get_unit_list_recursive(
583 UnitInfo
**_unit_infos
,
587 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
588 _cleanup_(message_set_freep
) Set
*replies
;
589 sd_bus_message
*reply
;
597 replies
= set_new(NULL
);
601 c
= get_unit_list(bus
, NULL
, patterns
, &unit_infos
, 0, &reply
);
605 r
= set_put(replies
, reply
);
607 sd_bus_message_unref(reply
);
612 _cleanup_strv_free_
char **machines
= NULL
;
615 r
= sd_get_machine_names(&machines
);
619 STRV_FOREACH(i
, machines
) {
620 _cleanup_bus_close_unref_ sd_bus
*container
= NULL
;
623 r
= sd_bus_open_system_machine(&container
, *i
);
625 log_error_errno(r
, "Failed to connect to container %s: %m", *i
);
629 k
= get_unit_list(container
, *i
, patterns
, &unit_infos
, c
, &reply
);
635 r
= set_put(replies
, reply
);
637 sd_bus_message_unref(reply
);
642 *_machines
= machines
;
647 *_unit_infos
= unit_infos
;
656 static int list_units(sd_bus
*bus
, char **args
) {
657 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
658 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
659 _cleanup_strv_free_
char **machines
= NULL
;
662 pager_open_if_enabled();
664 r
= get_unit_list_recursive(bus
, strv_skip_first(args
), &unit_infos
, &replies
, &machines
);
668 qsort_safe(unit_infos
, r
, sizeof(UnitInfo
), compare_unit_info
);
669 return output_units_list(unit_infos
, r
);
672 static int get_triggered_units(
677 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
680 r
= sd_bus_get_property_strv(
682 "org.freedesktop.systemd1",
684 "org.freedesktop.systemd1.Unit",
690 log_error("Failed to determine triggers: %s", bus_error_message(&error
, r
));
695 static int get_listening(
697 const char* unit_path
,
700 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
701 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
702 const char *type
, *path
;
705 r
= sd_bus_get_property(
707 "org.freedesktop.systemd1",
709 "org.freedesktop.systemd1.Socket",
715 log_error("Failed to get list of listening sockets: %s", bus_error_message(&error
, r
));
719 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
721 return bus_log_parse_error(r
);
723 while ((r
= sd_bus_message_read(reply
, "(ss)", &type
, &path
)) > 0) {
725 r
= strv_extend(listening
, type
);
729 r
= strv_extend(listening
, path
);
736 return bus_log_parse_error(r
);
738 r
= sd_bus_message_exit_container(reply
);
740 return bus_log_parse_error(r
);
752 /* Note: triggered is a list here, although it almost certainly
753 * will always be one unit. Nevertheless, dbus API allows for multiple
754 * values, so let's follow that. */
757 /* The strv above is shared. free is set only in the first one. */
761 static int socket_info_compare(const struct socket_info
*a
, const struct socket_info
*b
) {
767 if (!a
->machine
&& b
->machine
)
769 if (a
->machine
&& !b
->machine
)
771 if (a
->machine
&& b
->machine
) {
772 o
= strcasecmp(a
->machine
, b
->machine
);
777 o
= strcmp(a
->path
, b
->path
);
779 o
= strcmp(a
->type
, b
->type
);
784 static int output_sockets_list(struct socket_info
*socket_infos
, unsigned cs
) {
785 struct socket_info
*s
;
786 unsigned pathlen
= strlen("LISTEN"),
787 typelen
= strlen("TYPE") * arg_show_types
,
788 socklen
= strlen("UNIT"),
789 servlen
= strlen("ACTIVATES");
790 const char *on
, *off
;
792 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
796 socklen
= MAX(socklen
, strlen(s
->id
));
798 typelen
= MAX(typelen
, strlen(s
->type
));
799 pathlen
= MAX(pathlen
, strlen(s
->path
) + (s
->machine
? strlen(s
->machine
)+1 : 0));
801 STRV_FOREACH(a
, s
->triggered
)
802 tmp
+= strlen(*a
) + 2*(a
!= s
->triggered
);
803 servlen
= MAX(servlen
, tmp
);
808 printf("%-*s %-*.*s%-*s %s\n",
810 typelen
+ arg_show_types
, typelen
+ arg_show_types
, "TYPE ",
814 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
815 _cleanup_free_
char *j
= NULL
;
820 j
= strjoin(s
->machine
, ":", s
->path
, NULL
);
828 printf("%-*s %-*s %-*s",
829 pathlen
, path
, typelen
, s
->type
, socklen
, s
->id
);
832 pathlen
, path
, socklen
, s
->id
);
833 STRV_FOREACH(a
, s
->triggered
)
835 a
== s
->triggered
? "" : ",", *a
);
839 on
= ansi_highlight();
840 off
= ansi_highlight_off();
844 on
= ansi_highlight_red();
845 off
= ansi_highlight_off();
848 if (!arg_no_legend
) {
849 printf("%s%u sockets listed.%s\n", on
, cs
, off
);
851 printf("Pass --all to see loaded but inactive sockets, too.\n");
857 static int list_sockets(sd_bus
*bus
, char **args
) {
858 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
859 _cleanup_strv_free_
char **machines
= NULL
;
860 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
861 _cleanup_free_
struct socket_info
*socket_infos
= NULL
;
863 struct socket_info
*s
;
868 pager_open_if_enabled();
870 n
= get_unit_list_recursive(bus
, strv_skip_first(args
), &unit_infos
, &replies
, &machines
);
874 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
875 _cleanup_strv_free_
char **listening
= NULL
, **triggered
= NULL
;
878 if (!endswith(u
->id
, ".socket"))
881 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
885 c
= get_listening(bus
, u
->unit_path
, &listening
);
891 if (!GREEDY_REALLOC(socket_infos
, size
, cs
+ c
)) {
896 for (i
= 0; i
< c
; i
++)
897 socket_infos
[cs
+ i
] = (struct socket_info
) {
898 .machine
= u
->machine
,
900 .type
= listening
[i
*2],
901 .path
= listening
[i
*2 + 1],
902 .triggered
= triggered
,
903 .own_triggered
= i
==0,
906 /* from this point on we will cleanup those socket_infos */
909 listening
= triggered
= NULL
; /* avoid cleanup */
912 qsort_safe(socket_infos
, cs
, sizeof(struct socket_info
),
913 (__compar_fn_t
) socket_info_compare
);
915 output_sockets_list(socket_infos
, cs
);
918 assert(cs
== 0 || socket_infos
);
919 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
922 if (s
->own_triggered
)
923 strv_free(s
->triggered
);
929 static int get_next_elapse(
932 dual_timestamp
*next
) {
934 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
942 r
= sd_bus_get_property_trivial(
944 "org.freedesktop.systemd1",
946 "org.freedesktop.systemd1.Timer",
947 "NextElapseUSecMonotonic",
952 log_error("Failed to get next elapsation time: %s", bus_error_message(&error
, r
));
956 r
= sd_bus_get_property_trivial(
958 "org.freedesktop.systemd1",
960 "org.freedesktop.systemd1.Timer",
961 "NextElapseUSecRealtime",
966 log_error("Failed to get next elapsation time: %s", bus_error_message(&error
, r
));
974 static int get_last_trigger(
979 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
986 r
= sd_bus_get_property_trivial(
988 "org.freedesktop.systemd1",
990 "org.freedesktop.systemd1.Timer",
996 log_error("Failed to get last trigger time: %s", bus_error_message(&error
, r
));
1004 const char* machine
;
1007 usec_t last_trigger
;
1011 static int timer_info_compare(const struct timer_info
*a
, const struct timer_info
*b
) {
1017 if (!a
->machine
&& b
->machine
)
1019 if (a
->machine
&& !b
->machine
)
1021 if (a
->machine
&& b
->machine
) {
1022 o
= strcasecmp(a
->machine
, b
->machine
);
1027 if (a
->next_elapse
< b
->next_elapse
)
1029 if (a
->next_elapse
> b
->next_elapse
)
1032 return strcmp(a
->id
, b
->id
);
1035 static int output_timers_list(struct timer_info
*timer_infos
, unsigned n
) {
1036 struct timer_info
*t
;
1038 nextlen
= strlen("NEXT"),
1039 leftlen
= strlen("LEFT"),
1040 lastlen
= strlen("LAST"),
1041 passedlen
= strlen("PASSED"),
1042 unitlen
= strlen("UNIT"),
1043 activatelen
= strlen("ACTIVATES");
1045 const char *on
, *off
;
1047 assert(timer_infos
|| n
== 0);
1049 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1053 if (t
->next_elapse
> 0) {
1054 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1056 format_timestamp(tstamp
, sizeof(tstamp
), t
->next_elapse
);
1057 nextlen
= MAX(nextlen
, strlen(tstamp
) + 1);
1059 format_timestamp_relative(trel
, sizeof(trel
), t
->next_elapse
);
1060 leftlen
= MAX(leftlen
, strlen(trel
));
1063 if (t
->last_trigger
> 0) {
1064 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1066 format_timestamp(tstamp
, sizeof(tstamp
), t
->last_trigger
);
1067 lastlen
= MAX(lastlen
, strlen(tstamp
) + 1);
1069 format_timestamp_relative(trel
, sizeof(trel
), t
->last_trigger
);
1070 passedlen
= MAX(passedlen
, strlen(trel
));
1073 unitlen
= MAX(unitlen
, strlen(t
->id
) + (t
->machine
? strlen(t
->machine
)+1 : 0));
1075 STRV_FOREACH(a
, t
->triggered
)
1076 ul
+= strlen(*a
) + 2*(a
!= t
->triggered
);
1078 activatelen
= MAX(activatelen
, ul
);
1083 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1087 passedlen
, "PASSED",
1091 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1092 _cleanup_free_
char *j
= NULL
;
1094 char tstamp1
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel1
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1095 char tstamp2
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel2
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1098 format_timestamp(tstamp1
, sizeof(tstamp1
), t
->next_elapse
);
1099 format_timestamp_relative(trel1
, sizeof(trel1
), t
->next_elapse
);
1101 format_timestamp(tstamp2
, sizeof(tstamp2
), t
->last_trigger
);
1102 format_timestamp_relative(trel2
, sizeof(trel2
), t
->last_trigger
);
1105 j
= strjoin(t
->machine
, ":", t
->id
, NULL
);
1112 printf("%-*s %-*s %-*s %-*s %-*s",
1113 nextlen
, tstamp1
, leftlen
, trel1
, lastlen
, tstamp2
, passedlen
, trel2
, unitlen
, unit
);
1115 STRV_FOREACH(a
, t
->triggered
)
1117 a
== t
->triggered
? "" : ",", *a
);
1121 on
= ansi_highlight();
1122 off
= ansi_highlight_off();
1126 on
= ansi_highlight_red();
1127 off
= ansi_highlight_off();
1130 if (!arg_no_legend
) {
1131 printf("%s%u timers listed.%s\n", on
, n
, off
);
1133 printf("Pass --all to see loaded but inactive timers, too.\n");
1139 static usec_t
calc_next_elapse(dual_timestamp
*nw
, dual_timestamp
*next
) {
1145 if (next
->monotonic
!= USEC_INFINITY
&& next
->monotonic
> 0) {
1148 if (next
->monotonic
> nw
->monotonic
)
1149 converted
= nw
->realtime
+ (next
->monotonic
- nw
->monotonic
);
1151 converted
= nw
->realtime
- (nw
->monotonic
- next
->monotonic
);
1153 if (next
->realtime
!= USEC_INFINITY
&& next
->realtime
> 0)
1154 next_elapse
= MIN(converted
, next
->realtime
);
1156 next_elapse
= converted
;
1159 next_elapse
= next
->realtime
;
1164 static int list_timers(sd_bus
*bus
, char **args
) {
1165 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
1166 _cleanup_strv_free_
char **machines
= NULL
;
1167 _cleanup_free_
struct timer_info
*timer_infos
= NULL
;
1168 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
1169 struct timer_info
*t
;
1176 pager_open_if_enabled();
1178 n
= get_unit_list_recursive(bus
, strv_skip_first(args
), &unit_infos
, &replies
, &machines
);
1182 dual_timestamp_get(&nw
);
1184 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
1185 _cleanup_strv_free_
char **triggered
= NULL
;
1186 dual_timestamp next
= {};
1189 if (!endswith(u
->id
, ".timer"))
1192 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
1196 r
= get_next_elapse(bus
, u
->unit_path
, &next
);
1200 get_last_trigger(bus
, u
->unit_path
, &last
);
1202 if (!GREEDY_REALLOC(timer_infos
, size
, c
+1)) {
1207 m
= calc_next_elapse(&nw
, &next
);
1209 timer_infos
[c
++] = (struct timer_info
) {
1210 .machine
= u
->machine
,
1213 .last_trigger
= last
,
1214 .triggered
= triggered
,
1217 triggered
= NULL
; /* avoid cleanup */
1220 qsort_safe(timer_infos
, c
, sizeof(struct timer_info
),
1221 (__compar_fn_t
) timer_info_compare
);
1223 output_timers_list(timer_infos
, c
);
1226 for (t
= timer_infos
; t
< timer_infos
+ c
; t
++)
1227 strv_free(t
->triggered
);
1232 static int compare_unit_file_list(const void *a
, const void *b
) {
1233 const char *d1
, *d2
;
1234 const UnitFileList
*u
= a
, *v
= b
;
1236 d1
= strrchr(u
->path
, '.');
1237 d2
= strrchr(v
->path
, '.');
1242 r
= strcasecmp(d1
, d2
);
1247 return strcasecmp(basename(u
->path
), basename(v
->path
));
1250 static bool output_show_unit_file(const UnitFileList
*u
, char **patterns
) {
1251 if (!strv_fnmatch_or_empty(patterns
, basename(u
->path
), FNM_NOESCAPE
))
1254 if (!strv_isempty(arg_types
)) {
1257 dot
= strrchr(u
->path
, '.');
1261 if (!strv_find(arg_types
, dot
+1))
1265 if (!strv_isempty(arg_states
) &&
1266 !strv_find(arg_states
, unit_file_state_to_string(u
->state
)))
1272 static void output_unit_file_list(const UnitFileList
*units
, unsigned c
) {
1273 unsigned max_id_len
, id_cols
, state_cols
;
1274 const UnitFileList
*u
;
1276 max_id_len
= strlen("UNIT FILE");
1277 state_cols
= strlen("STATE");
1279 for (u
= units
; u
< units
+ c
; u
++) {
1280 max_id_len
= MAX(max_id_len
, strlen(basename(u
->path
)));
1281 state_cols
= MAX(state_cols
, strlen(unit_file_state_to_string(u
->state
)));
1285 unsigned basic_cols
;
1287 id_cols
= MIN(max_id_len
, 25u);
1288 basic_cols
= 1 + id_cols
+ state_cols
;
1289 if (basic_cols
< (unsigned) columns())
1290 id_cols
+= MIN(columns() - basic_cols
, max_id_len
- id_cols
);
1292 id_cols
= max_id_len
;
1295 printf("%-*s %-*s\n",
1296 id_cols
, "UNIT FILE",
1297 state_cols
, "STATE");
1299 for (u
= units
; u
< units
+ c
; u
++) {
1300 _cleanup_free_
char *e
= NULL
;
1301 const char *on
, *off
;
1304 if (u
->state
== UNIT_FILE_MASKED
||
1305 u
->state
== UNIT_FILE_MASKED_RUNTIME
||
1306 u
->state
== UNIT_FILE_DISABLED
||
1307 u
->state
== UNIT_FILE_INVALID
) {
1308 on
= ansi_highlight_red();
1309 off
= ansi_highlight_off();
1310 } else if (u
->state
== UNIT_FILE_ENABLED
) {
1311 on
= ansi_highlight_green();
1312 off
= ansi_highlight_off();
1316 id
= basename(u
->path
);
1318 e
= arg_full
? NULL
: ellipsize(id
, id_cols
, 33);
1320 printf("%-*s %s%-*s%s\n",
1321 id_cols
, e
? e
: id
,
1322 on
, state_cols
, unit_file_state_to_string(u
->state
), off
);
1326 printf("\n%u unit files listed.\n", c
);
1329 static int list_unit_files(sd_bus
*bus
, char **args
) {
1330 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1331 _cleanup_free_ UnitFileList
*units
= NULL
;
1339 pager_open_if_enabled();
1347 h
= hashmap_new(&string_hash_ops
);
1351 r
= unit_file_get_list(arg_scope
, arg_root
, h
);
1353 unit_file_list_free(h
);
1354 log_error_errno(r
, "Failed to get unit file list: %m");
1358 n_units
= hashmap_size(h
);
1360 units
= new(UnitFileList
, n_units
);
1361 if (!units
&& n_units
> 0) {
1362 unit_file_list_free(h
);
1366 HASHMAP_FOREACH(u
, h
, i
) {
1367 if (!output_show_unit_file(u
, strv_skip_first(args
)))
1374 assert(c
<= n_units
);
1377 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1379 r
= sd_bus_call_method(
1381 "org.freedesktop.systemd1",
1382 "/org/freedesktop/systemd1",
1383 "org.freedesktop.systemd1.Manager",
1389 log_error("Failed to list unit files: %s", bus_error_message(&error
, r
));
1393 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
1395 return bus_log_parse_error(r
);
1397 while ((r
= sd_bus_message_read(reply
, "(ss)", &path
, &state
)) > 0) {
1399 if (!GREEDY_REALLOC(units
, size
, c
+ 1))
1402 units
[c
] = (struct UnitFileList
) {
1404 unit_file_state_from_string(state
)
1407 if (output_show_unit_file(&units
[c
], strv_skip_first(args
)))
1412 return bus_log_parse_error(r
);
1414 r
= sd_bus_message_exit_container(reply
);
1416 return bus_log_parse_error(r
);
1419 qsort_safe(units
, c
, sizeof(UnitFileList
), compare_unit_file_list
);
1420 output_unit_file_list(units
, c
);
1423 for (unit
= units
; unit
< units
+ c
; unit
++)
1430 static int list_dependencies_print(const char *name
, int level
, unsigned int branches
, bool last
) {
1431 _cleanup_free_
char *n
= NULL
;
1432 size_t max_len
= MAX(columns(),20u);
1438 for (i
= level
- 1; i
>= 0; i
--) {
1440 if (len
> max_len
- 3 && !arg_full
) {
1441 printf("%s...\n",max_len
% 2 ? "" : " ");
1444 printf("%s", draw_special_char(branches
& (1 << i
) ? DRAW_TREE_VERTICAL
: DRAW_TREE_SPACE
));
1448 if (len
> max_len
- 3 && !arg_full
) {
1449 printf("%s...\n",max_len
% 2 ? "" : " ");
1453 printf("%s", draw_special_char(last
? DRAW_TREE_RIGHT
: DRAW_TREE_BRANCH
));
1457 printf("%s\n", name
);
1461 n
= ellipsize(name
, max_len
-len
, 100);
1469 static int list_dependencies_get_dependencies(sd_bus
*bus
, const char *name
, char ***deps
) {
1471 static const char *dependencies
[_DEPENDENCY_MAX
] = {
1472 [DEPENDENCY_FORWARD
] = "Requires\0"
1473 "RequiresOverridable\0"
1475 "RequisiteOverridable\0"
1478 [DEPENDENCY_REVERSE
] = "RequiredBy\0"
1479 "RequiredByOverridable\0"
1483 [DEPENDENCY_AFTER
] = "After\0",
1484 [DEPENDENCY_BEFORE
] = "Before\0",
1487 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1488 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1489 _cleanup_strv_free_
char **ret
= NULL
;
1490 _cleanup_free_
char *path
= NULL
;
1496 assert_cc(ELEMENTSOF(dependencies
) == _DEPENDENCY_MAX
);
1498 path
= unit_dbus_path_from_name(name
);
1502 r
= sd_bus_call_method(
1504 "org.freedesktop.systemd1",
1506 "org.freedesktop.DBus.Properties",
1510 "s", "org.freedesktop.systemd1.Unit");
1512 log_error("Failed to get properties of %s: %s", name
, bus_error_message(&error
, r
));
1516 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
1518 return bus_log_parse_error(r
);
1520 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
1523 r
= sd_bus_message_read(reply
, "s", &prop
);
1525 return bus_log_parse_error(r
);
1527 if (!nulstr_contains(dependencies
[arg_dependency
], prop
)) {
1528 r
= sd_bus_message_skip(reply
, "v");
1530 return bus_log_parse_error(r
);
1533 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, "as");
1535 return bus_log_parse_error(r
);
1537 r
= bus_message_read_strv_extend(reply
, &ret
);
1539 return bus_log_parse_error(r
);
1541 r
= sd_bus_message_exit_container(reply
);
1543 return bus_log_parse_error(r
);
1546 r
= sd_bus_message_exit_container(reply
);
1548 return bus_log_parse_error(r
);
1552 return bus_log_parse_error(r
);
1554 r
= sd_bus_message_exit_container(reply
);
1556 return bus_log_parse_error(r
);
1564 static int list_dependencies_compare(const void *_a
, const void *_b
) {
1565 const char **a
= (const char**) _a
, **b
= (const char**) _b
;
1567 if (unit_name_to_type(*a
) == UNIT_TARGET
&& unit_name_to_type(*b
) != UNIT_TARGET
)
1569 if (unit_name_to_type(*a
) != UNIT_TARGET
&& unit_name_to_type(*b
) == UNIT_TARGET
)
1572 return strcasecmp(*a
, *b
);
1575 static int list_dependencies_one(
1580 unsigned int branches
) {
1582 _cleanup_strv_free_
char **deps
= NULL
;
1590 r
= strv_extend(units
, name
);
1594 r
= list_dependencies_get_dependencies(bus
, name
, &deps
);
1598 qsort_safe(deps
, strv_length(deps
), sizeof (char*), list_dependencies_compare
);
1600 STRV_FOREACH(c
, deps
) {
1601 if (strv_contains(*units
, *c
)) {
1603 r
= list_dependencies_print("...", level
+ 1, (branches
<< 1) | (c
[1] == NULL
? 0 : 1), 1);
1616 state
= check_one_unit(bus
, *c
, "activating\0active\0reloading\0", true);
1617 on
= state
> 0 ? ansi_highlight_green() : ansi_highlight_red();
1618 printf("%s%s%s ", on
, draw_special_char(DRAW_BLACK_CIRCLE
), ansi_highlight_off());
1621 r
= list_dependencies_print(*c
, level
, branches
, c
[1] == NULL
);
1625 if (arg_all
|| unit_name_to_type(*c
) == UNIT_TARGET
) {
1626 r
= list_dependencies_one(bus
, *c
, level
+ 1, units
, (branches
<< 1) | (c
[1] == NULL
? 0 : 1));
1633 strv_remove(*units
, name
);
1638 static int list_dependencies(sd_bus
*bus
, char **args
) {
1639 _cleanup_strv_free_
char **units
= NULL
;
1640 _cleanup_free_
char *unit
= NULL
;
1647 r
= unit_name_mangle(args
[1], UNIT_NAME_NOGLOB
, &unit
);
1649 return log_error_errno(r
, "Failed to mangle unit name: %m");
1653 u
= SPECIAL_DEFAULT_TARGET
;
1655 pager_open_if_enabled();
1659 return list_dependencies_one(bus
, u
, 0, &units
, 0);
1662 struct machine_info
{
1666 char *control_group
;
1667 uint32_t n_failed_units
;
1672 static const struct bus_properties_map machine_info_property_map
[] = {
1673 { "SystemState", "s", NULL
, offsetof(struct machine_info
, state
) },
1674 { "NJobs", "u", NULL
, offsetof(struct machine_info
, n_jobs
) },
1675 { "NFailedUnits", "u", NULL
, offsetof(struct machine_info
, n_failed_units
) },
1676 { "ControlGroup", "s", NULL
, offsetof(struct machine_info
, control_group
) },
1677 { "UserspaceTimestamp", "t", NULL
, offsetof(struct machine_info
, timestamp
) },
1681 static void free_machines_list(struct machine_info
*machine_infos
, int n
) {
1687 for (i
= 0; i
< n
; i
++) {
1688 free(machine_infos
[i
].name
);
1689 free(machine_infos
[i
].state
);
1690 free(machine_infos
[i
].control_group
);
1693 free(machine_infos
);
1696 static int compare_machine_info(const void *a
, const void *b
) {
1697 const struct machine_info
*u
= a
, *v
= b
;
1699 if (u
->is_host
!= v
->is_host
)
1700 return u
->is_host
> v
->is_host
? -1 : 1;
1702 return strcasecmp(u
->name
, v
->name
);
1705 static int get_machine_properties(sd_bus
*bus
, struct machine_info
*mi
) {
1706 _cleanup_bus_close_unref_ sd_bus
*container
= NULL
;
1712 r
= sd_bus_open_system_machine(&container
, mi
->name
);
1719 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, mi
);
1726 static bool output_show_machine(const char *name
, char **patterns
) {
1727 return strv_fnmatch_or_empty(patterns
, name
, FNM_NOESCAPE
);
1730 static int get_machine_list(
1732 struct machine_info
**_machine_infos
,
1735 struct machine_info
*machine_infos
= NULL
;
1736 _cleanup_strv_free_
char **m
= NULL
;
1737 _cleanup_free_
char *hn
= NULL
;
1742 hn
= gethostname_malloc();
1746 if (output_show_machine(hn
, patterns
)) {
1747 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1))
1750 machine_infos
[c
].is_host
= true;
1751 machine_infos
[c
].name
= hn
;
1754 get_machine_properties(bus
, &machine_infos
[c
]);
1758 sd_get_machine_names(&m
);
1759 STRV_FOREACH(i
, m
) {
1760 _cleanup_free_
char *class = NULL
;
1762 if (!output_show_machine(*i
, patterns
))
1765 sd_machine_get_class(*i
, &class);
1766 if (!streq_ptr(class, "container"))
1769 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1)) {
1770 free_machines_list(machine_infos
, c
);
1774 machine_infos
[c
].is_host
= false;
1775 machine_infos
[c
].name
= strdup(*i
);
1776 if (!machine_infos
[c
].name
) {
1777 free_machines_list(machine_infos
, c
);
1781 get_machine_properties(NULL
, &machine_infos
[c
]);
1785 *_machine_infos
= machine_infos
;
1789 static void output_machines_list(struct machine_info
*machine_infos
, unsigned n
) {
1790 struct machine_info
*m
;
1793 namelen
= sizeof("NAME") - 1,
1794 statelen
= sizeof("STATE") - 1,
1795 failedlen
= sizeof("FAILED") - 1,
1796 jobslen
= sizeof("JOBS") - 1;
1798 assert(machine_infos
|| n
== 0);
1800 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
1801 namelen
= MAX(namelen
, strlen(m
->name
) + (m
->is_host
? sizeof(" (host)") - 1 : 0));
1802 statelen
= MAX(statelen
, m
->state
? strlen(m
->state
) : 0);
1803 failedlen
= MAX(failedlen
, DECIMAL_STR_WIDTH(m
->n_failed_units
));
1804 jobslen
= MAX(jobslen
, DECIMAL_STR_WIDTH(m
->n_jobs
));
1806 if (!arg_plain
&& !streq_ptr(m
->state
, "running"))
1810 if (!arg_no_legend
) {
1814 printf("%-*s %-*s %-*s %-*s\n",
1817 failedlen
, "FAILED",
1821 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
1822 const char *on_state
= "", *off_state
= "";
1823 const char *on_failed
= "", *off_failed
= "";
1824 bool circle
= false;
1826 if (streq_ptr(m
->state
, "degraded")) {
1827 on_state
= ansi_highlight_red();
1828 off_state
= ansi_highlight_off();
1830 } else if (!streq_ptr(m
->state
, "running")) {
1831 on_state
= ansi_highlight_yellow();
1832 off_state
= ansi_highlight_off();
1836 if (m
->n_failed_units
> 0) {
1837 on_failed
= ansi_highlight_red();
1838 off_failed
= ansi_highlight_off();
1840 on_failed
= off_failed
= "";
1843 printf("%s%s%s ", on_state
, circle
? draw_special_char(DRAW_BLACK_CIRCLE
) : " ", off_state
);
1846 printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
1847 (int) (namelen
- (sizeof(" (host)")-1)), strna(m
->name
),
1848 on_state
, statelen
, strna(m
->state
), off_state
,
1849 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
1850 jobslen
, m
->n_jobs
);
1852 printf("%-*s %s%-*s%s %s%*u%s %*u\n",
1853 namelen
, strna(m
->name
),
1854 on_state
, statelen
, strna(m
->state
), off_state
,
1855 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
1856 jobslen
, m
->n_jobs
);
1860 printf("\n%u machines listed.\n", n
);
1863 static int list_machines(sd_bus
*bus
, char **args
) {
1864 struct machine_info
*machine_infos
= NULL
;
1869 if (geteuid() != 0) {
1870 log_error("Must be root.");
1874 pager_open_if_enabled();
1876 r
= get_machine_list(bus
, &machine_infos
, strv_skip_first(args
));
1880 qsort_safe(machine_infos
, r
, sizeof(struct machine_info
), compare_machine_info
);
1881 output_machines_list(machine_infos
, r
);
1882 free_machines_list(machine_infos
, r
);
1887 static int get_default(sd_bus
*bus
, char **args
) {
1888 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1889 _cleanup_free_
char *_path
= NULL
;
1893 if (!bus
|| avoid_bus()) {
1894 r
= unit_file_get_default(arg_scope
, arg_root
, &_path
);
1896 return log_error_errno(r
, "Failed to get default target: %m");
1900 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1902 r
= sd_bus_call_method(
1904 "org.freedesktop.systemd1",
1905 "/org/freedesktop/systemd1",
1906 "org.freedesktop.systemd1.Manager",
1912 log_error("Failed to get default target: %s", bus_error_message(&error
, -r
));
1916 r
= sd_bus_message_read(reply
, "s", &path
);
1918 return bus_log_parse_error(r
);
1922 printf("%s\n", path
);
1927 static void dump_unit_file_changes(const UnitFileChange
*changes
, unsigned n_changes
) {
1930 assert(changes
|| n_changes
== 0);
1932 for (i
= 0; i
< n_changes
; i
++) {
1933 if (changes
[i
].type
== UNIT_FILE_SYMLINK
)
1934 log_info("Created symlink from %s to %s.", changes
[i
].path
, changes
[i
].source
);
1936 log_info("Removed symlink %s.", changes
[i
].path
);
1940 static int set_default(sd_bus
*bus
, char **args
) {
1941 _cleanup_free_
char *unit
= NULL
;
1942 UnitFileChange
*changes
= NULL
;
1943 unsigned n_changes
= 0;
1946 r
= unit_name_mangle_with_suffix(args
[1], UNIT_NAME_NOGLOB
, ".target", &unit
);
1948 return log_error_errno(r
, "Failed to mangle unit name: %m");
1950 if (!bus
|| avoid_bus()) {
1951 r
= unit_file_set_default(arg_scope
, arg_root
, unit
, true, &changes
, &n_changes
);
1953 return log_error_errno(r
, "Failed to set default target: %m");
1956 dump_unit_file_changes(changes
, n_changes
);
1960 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1961 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1963 polkit_agent_open_if_enabled();
1965 r
= sd_bus_call_method(
1967 "org.freedesktop.systemd1",
1968 "/org/freedesktop/systemd1",
1969 "org.freedesktop.systemd1.Manager",
1975 log_error("Failed to set default target: %s", bus_error_message(&error
, -r
));
1979 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, NULL
, NULL
);
1983 /* Try to reload if enabled */
1985 r
= daemon_reload(bus
, args
);
1990 unit_file_changes_free(changes
, n_changes
);
1997 const char *name
, *type
, *state
;
2000 static void output_jobs_list(const struct job_info
* jobs
, unsigned n
, bool skipped
) {
2001 unsigned id_len
, unit_len
, type_len
, state_len
;
2002 const struct job_info
*j
;
2003 const char *on
, *off
;
2004 bool shorten
= false;
2006 assert(n
== 0 || jobs
);
2009 if (!arg_no_legend
) {
2010 on
= ansi_highlight_green();
2011 off
= ansi_highlight_off();
2013 printf("%sNo jobs %s.%s\n", on
, skipped
? "listed" : "running", off
);
2018 pager_open_if_enabled();
2020 id_len
= strlen("JOB");
2021 unit_len
= strlen("UNIT");
2022 type_len
= strlen("TYPE");
2023 state_len
= strlen("STATE");
2025 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2026 uint32_t id
= j
->id
;
2027 assert(j
->name
&& j
->type
&& j
->state
);
2029 id_len
= MAX(id_len
, DECIMAL_STR_WIDTH(id
));
2030 unit_len
= MAX(unit_len
, strlen(j
->name
));
2031 type_len
= MAX(type_len
, strlen(j
->type
));
2032 state_len
= MAX(state_len
, strlen(j
->state
));
2035 if (!arg_full
&& id_len
+ 1 + unit_len
+ type_len
+ 1 + state_len
> columns()) {
2036 unit_len
= MAX(33u, columns() - id_len
- type_len
- state_len
- 3);
2041 printf("%*s %-*s %-*s %-*s\n",
2045 state_len
, "STATE");
2047 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2048 _cleanup_free_
char *e
= NULL
;
2050 if (streq(j
->state
, "running")) {
2051 on
= ansi_highlight();
2052 off
= ansi_highlight_off();
2056 e
= shorten
? ellipsize(j
->name
, unit_len
, 33) : NULL
;
2057 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2059 on
, unit_len
, e
? e
: j
->name
, off
,
2061 on
, state_len
, j
->state
, off
);
2064 if (!arg_no_legend
) {
2065 on
= ansi_highlight();
2066 off
= ansi_highlight_off();
2068 printf("\n%s%u jobs listed%s.\n", on
, n
, off
);
2072 static bool output_show_job(struct job_info
*job
, char **patterns
) {
2073 return strv_fnmatch_or_empty(patterns
, job
->name
, FNM_NOESCAPE
);
2076 static int list_jobs(sd_bus
*bus
, char **args
) {
2077 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2078 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2079 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2080 _cleanup_free_
struct job_info
*jobs
= NULL
;
2085 bool skipped
= false;
2087 r
= sd_bus_call_method(
2089 "org.freedesktop.systemd1",
2090 "/org/freedesktop/systemd1",
2091 "org.freedesktop.systemd1.Manager",
2097 log_error("Failed to list jobs: %s", bus_error_message(&error
, r
));
2101 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2103 return bus_log_parse_error(r
);
2105 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0) {
2106 struct job_info job
= { id
, name
, type
, state
};
2108 if (!output_show_job(&job
, strv_skip_first(args
))) {
2113 if (!GREEDY_REALLOC(jobs
, size
, c
+ 1))
2119 return bus_log_parse_error(r
);
2121 r
= sd_bus_message_exit_container(reply
);
2123 return bus_log_parse_error(r
);
2125 output_jobs_list(jobs
, c
, skipped
);
2129 static int cancel_job(sd_bus
*bus
, char **args
) {
2135 if (strv_length(args
) <= 1)
2136 return daemon_reload(bus
, args
);
2138 polkit_agent_open_if_enabled();
2140 STRV_FOREACH(name
, args
+1) {
2141 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2145 q
= safe_atou32(*name
, &id
);
2147 return log_error_errno(q
, "Failed to parse job id \"%s\": %m", *name
);
2149 q
= sd_bus_call_method(
2151 "org.freedesktop.systemd1",
2152 "/org/freedesktop/systemd1",
2153 "org.freedesktop.systemd1.Manager",
2159 log_error("Failed to cancel job %"PRIu32
": %s", id
, bus_error_message(&error
, q
));
2168 static int need_daemon_reload(sd_bus
*bus
, const char *unit
) {
2169 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2173 /* We ignore all errors here, since this is used to show a
2176 /* We don't use unit_dbus_path_from_name() directly since we
2177 * don't want to load the unit if it isn't loaded. */
2179 r
= sd_bus_call_method(
2181 "org.freedesktop.systemd1",
2182 "/org/freedesktop/systemd1",
2183 "org.freedesktop.systemd1.Manager",
2191 r
= sd_bus_message_read(reply
, "o", &path
);
2195 r
= sd_bus_get_property_trivial(
2197 "org.freedesktop.systemd1",
2199 "org.freedesktop.systemd1.Unit",
2209 static void warn_unit_file_changed(const char *name
) {
2210 log_warning("%sWarning:%s %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
2211 ansi_highlight_red(),
2212 ansi_highlight_off(),
2214 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user");
2217 static int unit_file_find_path(LookupPaths
*lp
, const char *unit_name
, char **unit_path
) {
2224 STRV_FOREACH(p
, lp
->unit_path
) {
2225 _cleanup_free_
char *path
;
2227 path
= path_join(arg_root
, *p
, unit_name
);
2231 if (access(path
, F_OK
) == 0) {
2241 static int unit_find_paths(
2243 const char *unit_name
,
2244 bool avoid_bus_cache
,
2246 char **fragment_path
,
2247 char ***dropin_paths
) {
2249 _cleanup_free_
char *path
= NULL
;
2250 _cleanup_strv_free_
char **dropins
= NULL
;
2254 * Finds where the unit is defined on disk. Returns 0 if the unit
2255 * is not found. Returns 1 if it is found, and sets
2256 * - the path to the unit in *path, if it exists on disk,
2257 * - and a strv of existing drop-ins in *dropins,
2258 * if the arg is not NULL and any dropins were found.
2262 assert(fragment_path
);
2265 if (!avoid_bus_cache
&& !unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
2266 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2267 _cleanup_bus_message_unref_ sd_bus_message
*unit_load_error
= NULL
;
2268 _cleanup_free_
char *unit
= NULL
;
2269 char *unit_load_error_name
, *unit_load_error_message
;
2271 unit
= unit_dbus_path_from_name(unit_name
);
2275 if (need_daemon_reload(bus
, unit_name
) > 0)
2276 warn_unit_file_changed(unit_name
);
2278 r
= sd_bus_get_property(
2280 "org.freedesktop.systemd1",
2282 "org.freedesktop.systemd1.Unit",
2288 return log_error_errno(r
, "Failed to get LoadError: %s", bus_error_message(&error
, r
));
2290 r
= sd_bus_message_read(
2293 &unit_load_error_name
,
2294 &unit_load_error_message
);
2296 return bus_log_parse_error(r
);
2298 if (!isempty(unit_load_error_name
)) {
2299 log_error("Unit %s is not loaded: %s", unit_name
, unit_load_error_message
);
2303 r
= sd_bus_get_property_string(
2305 "org.freedesktop.systemd1",
2307 "org.freedesktop.systemd1.Unit",
2312 return log_error_errno(r
, "Failed to get FragmentPath: %s", bus_error_message(&error
, r
));
2315 r
= sd_bus_get_property_strv(
2317 "org.freedesktop.systemd1",
2319 "org.freedesktop.systemd1.Unit",
2324 return log_error_errno(r
, "Failed to get DropInPaths: %s", bus_error_message(&error
, r
));
2327 _cleanup_set_free_ Set
*names
;
2329 names
= set_new(NULL
);
2333 r
= set_put(names
, unit_name
);
2335 return log_error_errno(r
, "Failed to add unit name: %m");
2337 r
= unit_file_find_path(lp
, unit_name
, &path
);
2342 _cleanup_free_
char *template = NULL
;
2344 r
= unit_name_template(unit_name
, &template);
2345 if (r
< 0 && r
!= -EINVAL
)
2346 return log_error_errno(r
, "Failed to determine template name: %m");
2348 r
= unit_file_find_path(lp
, template, &path
);
2355 r
= unit_file_find_dropin_paths(lp
->unit_path
, NULL
, names
, &dropins
);
2363 if (!isempty(path
)) {
2364 *fragment_path
= path
;
2369 if (dropin_paths
&& !strv_isempty(dropins
)) {
2370 *dropin_paths
= dropins
;
2376 log_error("No files found for %s.", unit_name
);
2381 static int check_one_unit(sd_bus
*bus
, const char *name
, const char *good_states
, bool quiet
) {
2382 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2383 _cleanup_free_
char *n
= NULL
, *state
= NULL
;
2389 r
= unit_name_mangle(name
, UNIT_NAME_NOGLOB
, &n
);
2391 return log_error_errno(r
, "Failed to mangle unit name: %m");
2393 /* We don't use unit_dbus_path_from_name() directly since we
2394 * don't want to load the unit if it isn't loaded. */
2396 r
= sd_bus_call_method(
2398 "org.freedesktop.systemd1",
2399 "/org/freedesktop/systemd1",
2400 "org.freedesktop.systemd1.Manager",
2411 r
= sd_bus_message_read(reply
, "o", &path
);
2413 return bus_log_parse_error(r
);
2415 r
= sd_bus_get_property_string(
2417 "org.freedesktop.systemd1",
2419 "org.freedesktop.systemd1.Unit",
2432 return nulstr_contains(good_states
, state
);
2435 static int check_triggering_units(
2439 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2440 _cleanup_free_
char *path
= NULL
, *n
= NULL
, *state
= NULL
;
2441 _cleanup_strv_free_
char **triggered_by
= NULL
;
2442 bool print_warning_label
= true;
2446 r
= unit_name_mangle(name
, UNIT_NAME_NOGLOB
, &n
);
2448 return log_error_errno(r
, "Failed to mangle unit name: %m");
2450 path
= unit_dbus_path_from_name(n
);
2454 r
= sd_bus_get_property_string(
2456 "org.freedesktop.systemd1",
2458 "org.freedesktop.systemd1.Unit",
2463 log_error("Failed to get load state of %s: %s", n
, bus_error_message(&error
, r
));
2467 if (streq(state
, "masked"))
2470 r
= sd_bus_get_property_strv(
2472 "org.freedesktop.systemd1",
2474 "org.freedesktop.systemd1.Unit",
2479 log_error("Failed to get triggered by array of %s: %s", n
, bus_error_message(&error
, r
));
2483 STRV_FOREACH(i
, triggered_by
) {
2484 r
= check_one_unit(bus
, *i
, "active\0reloading\0", true);
2486 return log_error_errno(r
, "Failed to check unit: %m");
2491 if (print_warning_label
) {
2492 log_warning("Warning: Stopping %s, but it can still be activated by:", n
);
2493 print_warning_label
= false;
2496 log_warning(" %s", *i
);
2502 static const struct {
2505 } unit_actions
[] = {
2506 { "start", "StartUnit" },
2507 { "stop", "StopUnit" },
2508 { "condstop", "StopUnit" },
2509 { "reload", "ReloadUnit" },
2510 { "restart", "RestartUnit" },
2511 { "try-restart", "TryRestartUnit" },
2512 { "condrestart", "TryRestartUnit" },
2513 { "reload-or-restart", "ReloadOrRestartUnit" },
2514 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2515 { "condreload", "ReloadOrTryRestartUnit" },
2516 { "force-reload", "ReloadOrTryRestartUnit" }
2519 static const char *verb_to_method(const char *verb
) {
2522 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2523 if (streq_ptr(unit_actions
[i
].verb
, verb
))
2524 return unit_actions
[i
].method
;
2529 static const char *method_to_verb(const char *method
) {
2532 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2533 if (streq_ptr(unit_actions
[i
].method
, method
))
2534 return unit_actions
[i
].verb
;
2539 static int start_unit_one(
2544 sd_bus_error
*error
,
2545 BusWaitForJobs
*w
) {
2547 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2556 log_debug("Calling manager for %s on %s, %s", method
, name
, mode
);
2558 r
= sd_bus_call_method(
2560 "org.freedesktop.systemd1",
2561 "/org/freedesktop/systemd1",
2562 "org.freedesktop.systemd1.Manager",
2570 if (r
== -ENOENT
&& arg_action
!= ACTION_SYSTEMCTL
)
2571 /* There's always a fallback possible for
2572 * legacy actions. */
2573 return -EADDRNOTAVAIL
;
2575 verb
= method_to_verb(method
);
2577 log_error("Failed to %s %s: %s", verb
, name
, bus_error_message(error
, r
));
2581 r
= sd_bus_message_read(reply
, "o", &path
);
2583 return bus_log_parse_error(r
);
2585 if (need_daemon_reload(bus
, name
) > 0)
2586 warn_unit_file_changed(name
);
2589 log_debug("Adding %s to the set", path
);
2590 r
= bus_wait_for_jobs_add(w
, path
);
2598 static int expand_names(sd_bus
*bus
, char **names
, const char* suffix
, char ***ret
) {
2600 _cleanup_strv_free_
char **mangled
= NULL
, **globs
= NULL
;
2604 STRV_FOREACH(name
, names
) {
2608 r
= unit_name_mangle_with_suffix(*name
, UNIT_NAME_GLOB
, suffix
, &t
);
2610 r
= unit_name_mangle(*name
, UNIT_NAME_GLOB
, &t
);
2612 return log_error_errno(r
, "Failed to mangle name: %m");
2614 if (string_is_glob(t
))
2615 r
= strv_consume(&globs
, t
);
2617 r
= strv_consume(&mangled
, t
);
2622 /* Query the manager only if any of the names are a glob, since
2623 * this is fairly expensive */
2624 if (!strv_isempty(globs
)) {
2625 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2626 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
2629 return log_error_errno(EOPNOTSUPP
, "Unit name globbing without bus is not implemented.");
2631 r
= get_unit_list(bus
, NULL
, globs
, &unit_infos
, 0, &reply
);
2635 for (i
= 0; i
< r
; i
++)
2636 if (strv_extend(&mangled
, unit_infos
[i
].id
) < 0)
2641 mangled
= NULL
; /* do not free */
2646 static const struct {
2650 } action_table
[_ACTION_MAX
] = {
2651 [ACTION_HALT
] = { SPECIAL_HALT_TARGET
, "halt", "replace-irreversibly" },
2652 [ACTION_POWEROFF
] = { SPECIAL_POWEROFF_TARGET
, "poweroff", "replace-irreversibly" },
2653 [ACTION_REBOOT
] = { SPECIAL_REBOOT_TARGET
, "reboot", "replace-irreversibly" },
2654 [ACTION_KEXEC
] = { SPECIAL_KEXEC_TARGET
, "kexec", "replace-irreversibly" },
2655 [ACTION_RUNLEVEL2
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2656 [ACTION_RUNLEVEL3
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2657 [ACTION_RUNLEVEL4
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2658 [ACTION_RUNLEVEL5
] = { SPECIAL_GRAPHICAL_TARGET
, NULL
, "isolate" },
2659 [ACTION_RESCUE
] = { SPECIAL_RESCUE_TARGET
, "rescue", "isolate" },
2660 [ACTION_EMERGENCY
] = { SPECIAL_EMERGENCY_TARGET
, "emergency", "isolate" },
2661 [ACTION_DEFAULT
] = { SPECIAL_DEFAULT_TARGET
, "default", "isolate" },
2662 [ACTION_EXIT
] = { SPECIAL_EXIT_TARGET
, "exit", "replace-irreversibly" },
2663 [ACTION_SUSPEND
] = { SPECIAL_SUSPEND_TARGET
, "suspend", "replace-irreversibly" },
2664 [ACTION_HIBERNATE
] = { SPECIAL_HIBERNATE_TARGET
, "hibernate", "replace-irreversibly" },
2665 [ACTION_HYBRID_SLEEP
] = { SPECIAL_HYBRID_SLEEP_TARGET
, "hybrid-sleep", "replace-irreversibly" },
2668 static enum action
verb_to_action(const char *verb
) {
2671 for (i
= _ACTION_INVALID
; i
< _ACTION_MAX
; i
++)
2672 if (streq_ptr(action_table
[i
].verb
, verb
))
2675 return _ACTION_INVALID
;
2678 static int start_unit(sd_bus
*bus
, char **args
) {
2679 _cleanup_(bus_wait_for_jobs_freep
) BusWaitForJobs
*w
= NULL
;
2680 const char *method
, *mode
, *one_name
, *suffix
= NULL
;
2681 _cleanup_strv_free_
char **names
= NULL
;
2687 ask_password_agent_open_if_enabled();
2688 polkit_agent_open_if_enabled();
2690 if (arg_action
== ACTION_SYSTEMCTL
) {
2692 method
= verb_to_method(args
[0]);
2693 action
= verb_to_action(args
[0]);
2695 if (streq(args
[0], "isolate")) {
2699 mode
= action_table
[action
].mode
?: arg_job_mode
;
2701 one_name
= action_table
[action
].target
;
2703 assert(arg_action
< ELEMENTSOF(action_table
));
2704 assert(action_table
[arg_action
].target
);
2706 method
= "StartUnit";
2708 mode
= action_table
[arg_action
].mode
;
2709 one_name
= action_table
[arg_action
].target
;
2713 names
= strv_new(one_name
, NULL
);
2715 r
= expand_names(bus
, args
+ 1, suffix
, &names
);
2717 log_error_errno(r
, "Failed to expand names: %m");
2720 if (!arg_no_block
) {
2721 r
= bus_wait_for_jobs_new(bus
, &w
);
2723 return log_error_errno(r
, "Could not watch jobs: %m");
2726 STRV_FOREACH(name
, names
) {
2727 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2730 q
= start_unit_one(bus
, method
, *name
, mode
, &error
, w
);
2731 if (r
>= 0 && q
< 0)
2732 r
= translate_bus_error_to_exit_status(q
, &error
);
2735 if (!arg_no_block
) {
2738 q
= bus_wait_for_jobs(w
, arg_quiet
);
2742 /* When stopping units, warn if they can still be triggered by
2743 * another active unit (socket, path, timer) */
2744 if (!arg_quiet
&& streq(method
, "StopUnit"))
2745 STRV_FOREACH(name
, names
)
2746 check_triggering_units(bus
, *name
);
2752 /* Ask systemd-logind, which might grant access to unprivileged users
2753 * through PolicyKit */
2754 static int reboot_with_logind(sd_bus
*bus
, enum action a
) {
2756 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2763 polkit_agent_open_if_enabled();
2771 case ACTION_POWEROFF
:
2772 method
= "PowerOff";
2775 case ACTION_SUSPEND
:
2779 case ACTION_HIBERNATE
:
2780 method
= "Hibernate";
2783 case ACTION_HYBRID_SLEEP
:
2784 method
= "HybridSleep";
2791 r
= sd_bus_call_method(
2793 "org.freedesktop.login1",
2794 "/org/freedesktop/login1",
2795 "org.freedesktop.login1.Manager",
2799 "b", arg_ask_password
);
2801 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
2809 static int check_inhibitors(sd_bus
*bus
, enum action a
) {
2811 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2812 _cleanup_strv_free_
char **sessions
= NULL
;
2813 const char *what
, *who
, *why
, *mode
;
2822 if (arg_ignore_inhibitors
|| arg_force
> 0)
2834 r
= sd_bus_call_method(
2836 "org.freedesktop.login1",
2837 "/org/freedesktop/login1",
2838 "org.freedesktop.login1.Manager",
2844 /* If logind is not around, then there are no inhibitors... */
2847 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssuu)");
2849 return bus_log_parse_error(r
);
2851 while ((r
= sd_bus_message_read(reply
, "(ssssuu)", &what
, &who
, &why
, &mode
, &uid
, &pid
)) > 0) {
2852 _cleanup_free_
char *comm
= NULL
, *user
= NULL
;
2853 _cleanup_strv_free_
char **sv
= NULL
;
2855 if (!streq(mode
, "block"))
2858 sv
= strv_split(what
, ":");
2862 if ((pid_t
) pid
< 0)
2863 return log_error_errno(ERANGE
, "Bad PID %"PRIu32
": %m", pid
);
2865 if (!strv_contains(sv
,
2867 a
== ACTION_POWEROFF
||
2868 a
== ACTION_REBOOT
||
2869 a
== ACTION_KEXEC
? "shutdown" : "sleep"))
2872 get_process_comm(pid
, &comm
);
2873 user
= uid_to_name(uid
);
2875 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT
" \"%s\", user %s), reason is \"%s\".",
2876 who
, (pid_t
) pid
, strna(comm
), strna(user
), why
);
2881 return bus_log_parse_error(r
);
2883 r
= sd_bus_message_exit_container(reply
);
2885 return bus_log_parse_error(r
);
2887 /* Check for current sessions */
2888 sd_get_sessions(&sessions
);
2889 STRV_FOREACH(s
, sessions
) {
2890 _cleanup_free_
char *type
= NULL
, *tty
= NULL
, *seat
= NULL
, *user
= NULL
, *service
= NULL
, *class = NULL
;
2892 if (sd_session_get_uid(*s
, &uid
) < 0 || uid
== getuid())
2895 if (sd_session_get_class(*s
, &class) < 0 || !streq(class, "user"))
2898 if (sd_session_get_type(*s
, &type
) < 0 || (!streq(type
, "x11") && !streq(type
, "tty")))
2901 sd_session_get_tty(*s
, &tty
);
2902 sd_session_get_seat(*s
, &seat
);
2903 sd_session_get_service(*s
, &service
);
2904 user
= uid_to_name(uid
);
2906 log_warning("User %s is logged in on %s.", strna(user
), isempty(tty
) ? (isempty(seat
) ? strna(service
) : seat
) : tty
);
2913 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2914 action_table
[a
].verb
);
2922 static int prepare_firmware_setup(sd_bus
*bus
) {
2924 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2928 if (!arg_firmware_setup
)
2931 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
2933 r
= efi_set_reboot_to_firmware(true);
2935 log_debug_errno(r
, "Cannot indicate to EFI to boot into setup mode, will retry via logind: %m");
2941 r
= sd_bus_call_method(
2943 "org.freedesktop.login1",
2944 "/org/freedesktop/login1",
2945 "org.freedesktop.login1.Manager",
2946 "SetRebootToFirmwareSetup",
2951 log_error("Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error
, r
));
2957 log_error("Cannot remotely indicate to EFI to boot into setup mode.");
2962 static int start_special(sd_bus
*bus
, char **args
) {
2968 a
= verb_to_action(args
[0]);
2970 r
= check_inhibitors(bus
, a
);
2974 if (arg_force
>= 2 && geteuid() != 0) {
2975 log_error("Must be root.");
2979 r
= prepare_firmware_setup(bus
);
2983 if (a
== ACTION_REBOOT
&& args
[1]) {
2984 r
= update_reboot_param_file(args
[1]);
2989 if (arg_force
>= 2 &&
2990 (a
== ACTION_HALT
||
2991 a
== ACTION_POWEROFF
||
2992 a
== ACTION_REBOOT
))
2995 if (arg_force
>= 1 &&
2996 (a
== ACTION_HALT
||
2997 a
== ACTION_POWEROFF
||
2998 a
== ACTION_REBOOT
||
2999 a
== ACTION_KEXEC
||
3001 return daemon_reload(bus
, args
);
3003 /* first try logind, to allow authentication with polkit */
3004 if (geteuid() != 0 &&
3005 (a
== ACTION_POWEROFF
||
3006 a
== ACTION_REBOOT
||
3007 a
== ACTION_SUSPEND
||
3008 a
== ACTION_HIBERNATE
||
3009 a
== ACTION_HYBRID_SLEEP
)) {
3010 r
= reboot_with_logind(bus
, a
);
3011 if (r
>= 0 || IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
3015 r
= start_unit(bus
, args
);
3016 if (r
== EXIT_SUCCESS
)
3022 static int check_unit_generic(sd_bus
*bus
, int code
, const char *good_states
, char **args
) {
3023 _cleanup_strv_free_
char **names
= NULL
;
3030 r
= expand_names(bus
, args
, NULL
, &names
);
3032 return log_error_errno(r
, "Failed to expand names: %m");
3034 STRV_FOREACH(name
, names
) {
3037 state
= check_one_unit(bus
, *name
, good_states
, arg_quiet
);
3047 static int check_unit_active(sd_bus
*bus
, char **args
) {
3048 /* According to LSB: 3, "program is not running" */
3049 return check_unit_generic(bus
, 3, "active\0reloading\0", args
+ 1);
3052 static int check_unit_failed(sd_bus
*bus
, char **args
) {
3053 return check_unit_generic(bus
, 1, "failed\0", args
+ 1);
3056 static int kill_unit(sd_bus
*bus
, char **args
) {
3057 _cleanup_strv_free_
char **names
= NULL
;
3064 polkit_agent_open_if_enabled();
3067 arg_kill_who
= "all";
3069 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
3071 log_error_errno(r
, "Failed to expand names: %m");
3073 STRV_FOREACH(name
, names
) {
3074 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
3076 q
= sd_bus_call_method(
3078 "org.freedesktop.systemd1",
3079 "/org/freedesktop/systemd1",
3080 "org.freedesktop.systemd1.Manager",
3084 "ssi", *names
, arg_kill_who
, arg_signal
);
3086 log_error("Failed to kill unit %s: %s", *names
, bus_error_message(&error
, q
));
3095 typedef struct ExecStatusInfo
{
3103 usec_t start_timestamp
;
3104 usec_t exit_timestamp
;
3109 LIST_FIELDS(struct ExecStatusInfo
, exec
);
3112 static void exec_status_info_free(ExecStatusInfo
*i
) {
3121 static int exec_status_info_deserialize(sd_bus_message
*m
, ExecStatusInfo
*i
) {
3122 uint64_t start_timestamp
, exit_timestamp
, start_timestamp_monotonic
, exit_timestamp_monotonic
;
3125 int32_t code
, status
;
3131 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_STRUCT
, "sasbttttuii");
3133 return bus_log_parse_error(r
);
3137 r
= sd_bus_message_read(m
, "s", &path
);
3139 return bus_log_parse_error(r
);
3141 i
->path
= strdup(path
);
3145 r
= sd_bus_message_read_strv(m
, &i
->argv
);
3147 return bus_log_parse_error(r
);
3149 r
= sd_bus_message_read(m
,
3152 &start_timestamp
, &start_timestamp_monotonic
,
3153 &exit_timestamp
, &exit_timestamp_monotonic
,
3157 return bus_log_parse_error(r
);
3160 i
->start_timestamp
= (usec_t
) start_timestamp
;
3161 i
->exit_timestamp
= (usec_t
) exit_timestamp
;
3162 i
->pid
= (pid_t
) pid
;
3166 r
= sd_bus_message_exit_container(m
);
3168 return bus_log_parse_error(r
);
3173 typedef struct UnitStatusInfo
{
3175 const char *load_state
;
3176 const char *active_state
;
3177 const char *sub_state
;
3178 const char *unit_file_state
;
3179 const char *unit_file_preset
;
3181 const char *description
;
3182 const char *following
;
3184 char **documentation
;
3186 const char *fragment_path
;
3187 const char *source_path
;
3188 const char *control_group
;
3190 char **dropin_paths
;
3192 const char *load_error
;
3195 usec_t inactive_exit_timestamp
;
3196 usec_t inactive_exit_timestamp_monotonic
;
3197 usec_t active_enter_timestamp
;
3198 usec_t active_exit_timestamp
;
3199 usec_t inactive_enter_timestamp
;
3201 bool need_daemon_reload
;
3206 const char *status_text
;
3207 const char *pid_file
;
3211 usec_t start_timestamp
;
3212 usec_t exit_timestamp
;
3214 int exit_code
, exit_status
;
3216 usec_t condition_timestamp
;
3217 bool condition_result
;
3218 bool failed_condition_trigger
;
3219 bool failed_condition_negate
;
3220 const char *failed_condition
;
3221 const char *failed_condition_parameter
;
3223 usec_t assert_timestamp
;
3225 bool failed_assert_trigger
;
3226 bool failed_assert_negate
;
3227 const char *failed_assert
;
3228 const char *failed_assert_parameter
;
3231 unsigned n_accepted
;
3232 unsigned n_connections
;
3235 /* Pairs of type, path */
3239 const char *sysfs_path
;
3241 /* Mount, Automount */
3248 uint64_t memory_current
;
3249 uint64_t memory_limit
;
3250 uint64_t cpu_usage_nsec
;
3252 LIST_HEAD(ExecStatusInfo
, exec
);
3255 static void print_status_info(
3260 const char *active_on
, *active_off
, *on
, *off
, *ss
;
3262 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], *s1
;
3263 char since2
[FORMAT_TIMESTAMP_MAX
], *s2
;
3269 /* This shows pretty information about a unit. See
3270 * print_property() for a low-level property printer */
3272 if (streq_ptr(i
->active_state
, "failed")) {
3273 active_on
= ansi_highlight_red();
3274 active_off
= ansi_highlight_off();
3275 } else if (streq_ptr(i
->active_state
, "active") || streq_ptr(i
->active_state
, "reloading")) {
3276 active_on
= ansi_highlight_green();
3277 active_off
= ansi_highlight_off();
3279 active_on
= active_off
= "";
3281 printf("%s%s%s %s", active_on
, draw_special_char(DRAW_BLACK_CIRCLE
), active_off
, strna(i
->id
));
3283 if (i
->description
&& !streq_ptr(i
->id
, i
->description
))
3284 printf(" - %s", i
->description
);
3289 printf(" Follow: unit currently follows state of %s\n", i
->following
);
3291 if (streq_ptr(i
->load_state
, "error")) {
3292 on
= ansi_highlight_red();
3293 off
= ansi_highlight_off();
3297 path
= i
->source_path
? i
->source_path
: i
->fragment_path
;
3300 printf(" Loaded: %s%s%s (Reason: %s)\n",
3301 on
, strna(i
->load_state
), off
, i
->load_error
);
3302 else if (path
&& !isempty(i
->unit_file_state
) && !isempty(i
->unit_file_preset
))
3303 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
3304 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
, i
->unit_file_preset
);
3305 else if (path
&& !isempty(i
->unit_file_state
))
3306 printf(" Loaded: %s%s%s (%s; %s)\n",
3307 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
);
3309 printf(" Loaded: %s%s%s (%s)\n",
3310 on
, strna(i
->load_state
), off
, path
);
3312 printf(" Loaded: %s%s%s\n",
3313 on
, strna(i
->load_state
), off
);
3315 if (!strv_isempty(i
->dropin_paths
)) {
3316 _cleanup_free_
char *dir
= NULL
;
3320 STRV_FOREACH(dropin
, i
->dropin_paths
) {
3321 if (! dir
|| last
) {
3322 printf(dir
? " " : " Drop-In: ");
3327 if (path_get_parent(*dropin
, &dir
) < 0) {
3332 printf("%s\n %s", dir
,
3333 draw_special_char(DRAW_TREE_RIGHT
));
3336 last
= ! (*(dropin
+ 1) && startswith(*(dropin
+ 1), dir
));
3338 printf("%s%s", basename(*dropin
), last
? "\n" : ", ");
3342 ss
= streq_ptr(i
->active_state
, i
->sub_state
) ? NULL
: i
->sub_state
;
3344 printf(" Active: %s%s (%s)%s",
3345 active_on
, strna(i
->active_state
), ss
, active_off
);
3347 printf(" Active: %s%s%s",
3348 active_on
, strna(i
->active_state
), active_off
);
3350 if (!isempty(i
->result
) && !streq(i
->result
, "success"))
3351 printf(" (Result: %s)", i
->result
);
3353 timestamp
= (streq_ptr(i
->active_state
, "active") ||
3354 streq_ptr(i
->active_state
, "reloading")) ? i
->active_enter_timestamp
:
3355 (streq_ptr(i
->active_state
, "inactive") ||
3356 streq_ptr(i
->active_state
, "failed")) ? i
->inactive_enter_timestamp
:
3357 streq_ptr(i
->active_state
, "activating") ? i
->inactive_exit_timestamp
:
3358 i
->active_exit_timestamp
;
3360 s1
= format_timestamp_relative(since1
, sizeof(since1
), timestamp
);
3361 s2
= format_timestamp(since2
, sizeof(since2
), timestamp
);
3364 printf(" since %s; %s\n", s2
, s1
);
3366 printf(" since %s\n", s2
);
3370 if (!i
->condition_result
&& i
->condition_timestamp
> 0) {
3371 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->condition_timestamp
);
3372 s2
= format_timestamp(since2
, sizeof(since2
), i
->condition_timestamp
);
3374 printf("Condition: start %scondition failed%s at %s%s%s\n",
3375 ansi_highlight_yellow(), ansi_highlight_off(),
3376 s2
, s1
? "; " : "", s1
? s1
: "");
3377 if (i
->failed_condition_trigger
)
3378 printf(" none of the trigger conditions were met\n");
3379 else if (i
->failed_condition
)
3380 printf(" %s=%s%s was not met\n",
3381 i
->failed_condition
,
3382 i
->failed_condition_negate
? "!" : "",
3383 i
->failed_condition_parameter
);
3386 if (!i
->assert_result
&& i
->assert_timestamp
> 0) {
3387 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->assert_timestamp
);
3388 s2
= format_timestamp(since2
, sizeof(since2
), i
->assert_timestamp
);
3390 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
3391 ansi_highlight_red(), ansi_highlight_off(),
3392 s2
, s1
? "; " : "", s1
? s1
: "");
3393 if (i
->failed_assert_trigger
)
3394 printf(" none of the trigger assertions were met\n");
3395 else if (i
->failed_assert
)
3396 printf(" %s=%s%s was not met\n",
3398 i
->failed_assert_negate
? "!" : "",
3399 i
->failed_assert_parameter
);
3403 printf(" Device: %s\n", i
->sysfs_path
);
3405 printf(" Where: %s\n", i
->where
);
3407 printf(" What: %s\n", i
->what
);
3409 STRV_FOREACH(t
, i
->documentation
)
3410 printf(" %*s %s\n", 9, t
== i
->documentation
? "Docs:" : "", *t
);
3412 STRV_FOREACH_PAIR(t
, t2
, i
->listen
)
3413 printf(" %*s %s (%s)\n", 9, t
== i
->listen
? "Listen:" : "", *t2
, *t
);
3416 printf(" Accepted: %u; Connected: %u\n", i
->n_accepted
, i
->n_connections
);
3418 LIST_FOREACH(exec
, p
, i
->exec
) {
3419 _cleanup_free_
char *argv
= NULL
;
3422 /* Only show exited processes here */
3426 argv
= strv_join(p
->argv
, " ");
3427 printf(" Process: "PID_FMT
" %s=%s ", p
->pid
, p
->name
, strna(argv
));
3429 good
= is_clean_exit_lsb(p
->code
, p
->status
, NULL
);
3431 on
= ansi_highlight_red();
3432 off
= ansi_highlight_off();
3436 printf("%s(code=%s, ", on
, sigchld_code_to_string(p
->code
));
3438 if (p
->code
== CLD_EXITED
) {
3441 printf("status=%i", p
->status
);
3443 c
= exit_status_to_string(p
->status
, EXIT_STATUS_SYSTEMD
);
3448 printf("signal=%s", signal_to_string(p
->status
));
3450 printf(")%s\n", off
);
3452 if (i
->main_pid
== p
->pid
&&
3453 i
->start_timestamp
== p
->start_timestamp
&&
3454 i
->exit_timestamp
== p
->start_timestamp
)
3455 /* Let's not show this twice */
3458 if (p
->pid
== i
->control_pid
)
3462 if (i
->main_pid
> 0 || i
->control_pid
> 0) {
3463 if (i
->main_pid
> 0) {
3464 printf(" Main PID: "PID_FMT
, i
->main_pid
);
3467 _cleanup_free_
char *comm
= NULL
;
3468 get_process_comm(i
->main_pid
, &comm
);
3470 printf(" (%s)", comm
);
3471 } else if (i
->exit_code
> 0) {
3472 printf(" (code=%s, ", sigchld_code_to_string(i
->exit_code
));
3474 if (i
->exit_code
== CLD_EXITED
) {
3477 printf("status=%i", i
->exit_status
);
3479 c
= exit_status_to_string(i
->exit_status
, EXIT_STATUS_SYSTEMD
);
3484 printf("signal=%s", signal_to_string(i
->exit_status
));
3488 if (i
->control_pid
> 0)
3492 if (i
->control_pid
> 0) {
3493 _cleanup_free_
char *c
= NULL
;
3495 printf(" %8s: "PID_FMT
, i
->main_pid
? "" : " Control", i
->control_pid
);
3497 get_process_comm(i
->control_pid
, &c
);
3506 printf(" Status: \"%s\"\n", i
->status_text
);
3507 if (i
->status_errno
> 0)
3508 printf(" Error: %i (%s)\n", i
->status_errno
, strerror(i
->status_errno
));
3510 if (i
->memory_current
!= (uint64_t) -1) {
3511 char buf
[FORMAT_BYTES_MAX
];
3513 printf(" Memory: %s", format_bytes(buf
, sizeof(buf
), i
->memory_current
));
3515 if (i
->memory_limit
!= (uint64_t) -1)
3516 printf(" (limit: %s)\n", format_bytes(buf
, sizeof(buf
), i
->memory_limit
));
3521 if (i
->cpu_usage_nsec
!= (uint64_t) -1) {
3522 char buf
[FORMAT_TIMESPAN_MAX
];
3523 printf(" CPU: %s\n", format_timespan(buf
, sizeof(buf
), i
->cpu_usage_nsec
/ NSEC_PER_USEC
, USEC_PER_MSEC
));
3526 if (i
->control_group
&&
3527 (i
->main_pid
> 0 || i
->control_pid
> 0 ||
3528 ((arg_transport
!= BUS_TRANSPORT_LOCAL
&& arg_transport
!= BUS_TRANSPORT_MACHINE
) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, false) == 0))) {
3531 printf(" CGroup: %s\n", i
->control_group
);
3533 if (arg_transport
== BUS_TRANSPORT_LOCAL
|| arg_transport
== BUS_TRANSPORT_MACHINE
) {
3536 static const char prefix
[] = " ";
3539 if (c
> sizeof(prefix
) - 1)
3540 c
-= sizeof(prefix
) - 1;
3544 if (i
->main_pid
> 0)
3545 extra
[k
++] = i
->main_pid
;
3547 if (i
->control_pid
> 0)
3548 extra
[k
++] = i
->control_pid
;
3550 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, prefix
, c
, false, extra
, k
, get_output_flags());
3554 if (i
->id
&& arg_transport
== BUS_TRANSPORT_LOCAL
) {
3555 show_journal_by_unit(
3560 i
->inactive_exit_timestamp_monotonic
,
3563 get_output_flags() | OUTPUT_BEGIN_NEWLINE
,
3564 SD_JOURNAL_LOCAL_ONLY
,
3565 arg_scope
== UNIT_FILE_SYSTEM
,
3569 if (i
->need_daemon_reload
)
3570 warn_unit_file_changed(i
->id
);
3573 static void show_unit_help(UnitStatusInfo
*i
) {
3578 if (!i
->documentation
) {
3579 log_info("Documentation for %s not known.", i
->id
);
3583 STRV_FOREACH(p
, i
->documentation
)
3584 if (startswith(*p
, "man:"))
3585 show_man_page(*p
+ 4, false);
3587 log_info("Can't show: %s", *p
);
3590 static int status_property(const char *name
, sd_bus_message
*m
, UnitStatusInfo
*i
, const char *contents
) {
3597 switch (contents
[0]) {
3599 case SD_BUS_TYPE_STRING
: {
3602 r
= sd_bus_message_read(m
, "s", &s
);
3604 return bus_log_parse_error(r
);
3607 if (streq(name
, "Id"))
3609 else if (streq(name
, "LoadState"))
3611 else if (streq(name
, "ActiveState"))
3612 i
->active_state
= s
;
3613 else if (streq(name
, "SubState"))
3615 else if (streq(name
, "Description"))
3617 else if (streq(name
, "FragmentPath"))
3618 i
->fragment_path
= s
;
3619 else if (streq(name
, "SourcePath"))
3622 else if (streq(name
, "DefaultControlGroup")) {
3624 e
= startswith(s
, SYSTEMD_CGROUP_CONTROLLER
":");
3626 i
->control_group
= e
;
3629 else if (streq(name
, "ControlGroup"))
3630 i
->control_group
= s
;
3631 else if (streq(name
, "StatusText"))
3633 else if (streq(name
, "PIDFile"))
3635 else if (streq(name
, "SysFSPath"))
3637 else if (streq(name
, "Where"))
3639 else if (streq(name
, "What"))
3641 else if (streq(name
, "Following"))
3643 else if (streq(name
, "UnitFileState"))
3644 i
->unit_file_state
= s
;
3645 else if (streq(name
, "UnitFilePreset"))
3646 i
->unit_file_preset
= s
;
3647 else if (streq(name
, "Result"))
3654 case SD_BUS_TYPE_BOOLEAN
: {
3657 r
= sd_bus_message_read(m
, "b", &b
);
3659 return bus_log_parse_error(r
);
3661 if (streq(name
, "Accept"))
3663 else if (streq(name
, "NeedDaemonReload"))
3664 i
->need_daemon_reload
= b
;
3665 else if (streq(name
, "ConditionResult"))
3666 i
->condition_result
= b
;
3667 else if (streq(name
, "AssertResult"))
3668 i
->assert_result
= b
;
3673 case SD_BUS_TYPE_UINT32
: {
3676 r
= sd_bus_message_read(m
, "u", &u
);
3678 return bus_log_parse_error(r
);
3680 if (streq(name
, "MainPID")) {
3682 i
->main_pid
= (pid_t
) u
;
3685 } else if (streq(name
, "ControlPID"))
3686 i
->control_pid
= (pid_t
) u
;
3687 else if (streq(name
, "ExecMainPID")) {
3689 i
->main_pid
= (pid_t
) u
;
3690 } else if (streq(name
, "NAccepted"))
3692 else if (streq(name
, "NConnections"))
3693 i
->n_connections
= u
;
3698 case SD_BUS_TYPE_INT32
: {
3701 r
= sd_bus_message_read(m
, "i", &j
);
3703 return bus_log_parse_error(r
);
3705 if (streq(name
, "ExecMainCode"))
3706 i
->exit_code
= (int) j
;
3707 else if (streq(name
, "ExecMainStatus"))
3708 i
->exit_status
= (int) j
;
3709 else if (streq(name
, "StatusErrno"))
3710 i
->status_errno
= (int) j
;
3715 case SD_BUS_TYPE_UINT64
: {
3718 r
= sd_bus_message_read(m
, "t", &u
);
3720 return bus_log_parse_error(r
);
3722 if (streq(name
, "ExecMainStartTimestamp"))
3723 i
->start_timestamp
= (usec_t
) u
;
3724 else if (streq(name
, "ExecMainExitTimestamp"))
3725 i
->exit_timestamp
= (usec_t
) u
;
3726 else if (streq(name
, "ActiveEnterTimestamp"))
3727 i
->active_enter_timestamp
= (usec_t
) u
;
3728 else if (streq(name
, "InactiveEnterTimestamp"))
3729 i
->inactive_enter_timestamp
= (usec_t
) u
;
3730 else if (streq(name
, "InactiveExitTimestamp"))
3731 i
->inactive_exit_timestamp
= (usec_t
) u
;
3732 else if (streq(name
, "InactiveExitTimestampMonotonic"))
3733 i
->inactive_exit_timestamp_monotonic
= (usec_t
) u
;
3734 else if (streq(name
, "ActiveExitTimestamp"))
3735 i
->active_exit_timestamp
= (usec_t
) u
;
3736 else if (streq(name
, "ConditionTimestamp"))
3737 i
->condition_timestamp
= (usec_t
) u
;
3738 else if (streq(name
, "AssertTimestamp"))
3739 i
->assert_timestamp
= (usec_t
) u
;
3740 else if (streq(name
, "MemoryCurrent"))
3741 i
->memory_current
= u
;
3742 else if (streq(name
, "MemoryLimit"))
3743 i
->memory_limit
= u
;
3744 else if (streq(name
, "CPUUsageNSec"))
3745 i
->cpu_usage_nsec
= u
;
3750 case SD_BUS_TYPE_ARRAY
:
3752 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
3753 _cleanup_free_ ExecStatusInfo
*info
= NULL
;
3755 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
3757 return bus_log_parse_error(r
);
3759 info
= new0(ExecStatusInfo
, 1);
3763 while ((r
= exec_status_info_deserialize(m
, info
)) > 0) {
3765 info
->name
= strdup(name
);
3769 LIST_PREPEND(exec
, i
->exec
, info
);
3771 info
= new0(ExecStatusInfo
, 1);
3777 return bus_log_parse_error(r
);
3779 r
= sd_bus_message_exit_container(m
);
3781 return bus_log_parse_error(r
);
3785 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
3786 const char *type
, *path
;
3788 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
3790 return bus_log_parse_error(r
);
3792 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0) {
3794 r
= strv_extend(&i
->listen
, type
);
3798 r
= strv_extend(&i
->listen
, path
);
3803 return bus_log_parse_error(r
);
3805 r
= sd_bus_message_exit_container(m
);
3807 return bus_log_parse_error(r
);
3811 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "DropInPaths")) {
3813 r
= sd_bus_message_read_strv(m
, &i
->dropin_paths
);
3815 return bus_log_parse_error(r
);
3817 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Documentation")) {
3819 r
= sd_bus_message_read_strv(m
, &i
->documentation
);
3821 return bus_log_parse_error(r
);
3823 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Conditions")) {
3824 const char *cond
, *param
;
3825 int trigger
, negate
;
3828 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
3830 return bus_log_parse_error(r
);
3832 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
3833 log_debug("%s %d %d %s %d", cond
, trigger
, negate
, param
, state
);
3834 if (state
< 0 && (!trigger
|| !i
->failed_condition
)) {
3835 i
->failed_condition
= cond
;
3836 i
->failed_condition_trigger
= trigger
;
3837 i
->failed_condition_negate
= negate
;
3838 i
->failed_condition_parameter
= param
;
3842 return bus_log_parse_error(r
);
3844 r
= sd_bus_message_exit_container(m
);
3846 return bus_log_parse_error(r
);
3848 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Asserts")) {
3849 const char *cond
, *param
;
3850 int trigger
, negate
;
3853 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
3855 return bus_log_parse_error(r
);
3857 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
3858 log_debug("%s %d %d %s %d", cond
, trigger
, negate
, param
, state
);
3859 if (state
< 0 && (!trigger
|| !i
->failed_assert
)) {
3860 i
->failed_assert
= cond
;
3861 i
->failed_assert_trigger
= trigger
;
3862 i
->failed_assert_negate
= negate
;
3863 i
->failed_assert_parameter
= param
;
3867 return bus_log_parse_error(r
);
3869 r
= sd_bus_message_exit_container(m
);
3871 return bus_log_parse_error(r
);
3878 case SD_BUS_TYPE_STRUCT_BEGIN
:
3880 if (streq(name
, "LoadError")) {
3881 const char *n
, *message
;
3883 r
= sd_bus_message_read(m
, "(ss)", &n
, &message
);
3885 return bus_log_parse_error(r
);
3887 if (!isempty(message
))
3888 i
->load_error
= message
;
3901 r
= sd_bus_message_skip(m
, contents
);
3903 return bus_log_parse_error(r
);
3908 static int print_property(const char *name
, sd_bus_message
*m
, const char *contents
) {
3914 /* This is a low-level property printer, see
3915 * print_status_info() for the nicer output */
3917 if (arg_properties
&& !strv_find(arg_properties
, name
)) {
3918 /* skip what we didn't read */
3919 r
= sd_bus_message_skip(m
, contents
);
3923 switch (contents
[0]) {
3925 case SD_BUS_TYPE_STRUCT_BEGIN
:
3927 if (contents
[1] == SD_BUS_TYPE_UINT32
&& streq(name
, "Job")) {
3930 r
= sd_bus_message_read(m
, "(uo)", &u
, NULL
);
3932 return bus_log_parse_error(r
);
3935 printf("%s=%"PRIu32
"\n", name
, u
);
3937 printf("%s=\n", name
);
3941 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Unit")) {
3944 r
= sd_bus_message_read(m
, "(so)", &s
, NULL
);
3946 return bus_log_parse_error(r
);
3948 if (arg_all
|| !isempty(s
))
3949 printf("%s=%s\n", name
, s
);
3953 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "LoadError")) {
3954 const char *a
= NULL
, *b
= NULL
;
3956 r
= sd_bus_message_read(m
, "(ss)", &a
, &b
);
3958 return bus_log_parse_error(r
);
3960 if (arg_all
|| !isempty(a
) || !isempty(b
))
3961 printf("%s=%s \"%s\"\n", name
, strempty(a
), strempty(b
));
3964 } else if (streq_ptr(name
, "SystemCallFilter")) {
3965 _cleanup_strv_free_
char **l
= NULL
;
3968 r
= sd_bus_message_enter_container(m
, 'r', "bas");
3970 return bus_log_parse_error(r
);
3972 r
= sd_bus_message_read(m
, "b", &whitelist
);
3974 return bus_log_parse_error(r
);
3976 r
= sd_bus_message_read_strv(m
, &l
);
3978 return bus_log_parse_error(r
);
3980 r
= sd_bus_message_exit_container(m
);
3982 return bus_log_parse_error(r
);
3984 if (arg_all
|| whitelist
|| !strv_isempty(l
)) {
3988 fputs(name
, stdout
);
3994 STRV_FOREACH(i
, l
) {
4002 fputc('\n', stdout
);
4010 case SD_BUS_TYPE_ARRAY
:
4012 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "EnvironmentFiles")) {
4016 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sb)");
4018 return bus_log_parse_error(r
);
4020 while ((r
= sd_bus_message_read(m
, "(sb)", &path
, &ignore
)) > 0)
4021 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path
, yes_no(ignore
));
4024 return bus_log_parse_error(r
);
4026 r
= sd_bus_message_exit_container(m
);
4028 return bus_log_parse_error(r
);
4032 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Paths")) {
4033 const char *type
, *path
;
4035 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4037 return bus_log_parse_error(r
);
4039 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4040 printf("%s=%s\n", type
, path
);
4042 return bus_log_parse_error(r
);
4044 r
= sd_bus_message_exit_container(m
);
4046 return bus_log_parse_error(r
);
4050 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
4051 const char *type
, *path
;
4053 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4055 return bus_log_parse_error(r
);
4057 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4058 printf("Listen%s=%s\n", type
, path
);
4060 return bus_log_parse_error(r
);
4062 r
= sd_bus_message_exit_container(m
);
4064 return bus_log_parse_error(r
);
4068 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Timers")) {
4070 uint64_t value
, next_elapse
;
4072 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(stt)");
4074 return bus_log_parse_error(r
);
4076 while ((r
= sd_bus_message_read(m
, "(stt)", &base
, &value
, &next_elapse
)) > 0) {
4077 char timespan1
[FORMAT_TIMESPAN_MAX
], timespan2
[FORMAT_TIMESPAN_MAX
];
4079 printf("%s={ value=%s ; next_elapse=%s }\n",
4081 format_timespan(timespan1
, sizeof(timespan1
), value
, 0),
4082 format_timespan(timespan2
, sizeof(timespan2
), next_elapse
, 0));
4085 return bus_log_parse_error(r
);
4087 r
= sd_bus_message_exit_container(m
);
4089 return bus_log_parse_error(r
);
4093 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
4094 ExecStatusInfo info
= {};
4096 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4098 return bus_log_parse_error(r
);
4100 while ((r
= exec_status_info_deserialize(m
, &info
)) > 0) {
4101 char timestamp1
[FORMAT_TIMESTAMP_MAX
], timestamp2
[FORMAT_TIMESTAMP_MAX
];
4102 _cleanup_free_
char *tt
;
4104 tt
= strv_join(info
.argv
, " ");
4106 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",
4110 yes_no(info
.ignore
),
4111 strna(format_timestamp(timestamp1
, sizeof(timestamp1
), info
.start_timestamp
)),
4112 strna(format_timestamp(timestamp2
, sizeof(timestamp2
), info
.exit_timestamp
)),
4114 sigchld_code_to_string(info
.code
),
4116 info
.code
== CLD_EXITED
? "" : "/",
4117 strempty(info
.code
== CLD_EXITED
? NULL
: signal_to_string(info
.status
)));
4120 strv_free(info
.argv
);
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
, "DeviceAllow")) {
4131 const char *path
, *rwm
;
4133 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4135 return bus_log_parse_error(r
);
4137 while ((r
= sd_bus_message_read(m
, "(ss)", &path
, &rwm
)) > 0)
4138 printf("%s=%s %s\n", name
, strna(path
), strna(rwm
));
4140 return bus_log_parse_error(r
);
4142 r
= sd_bus_message_exit_container(m
);
4144 return bus_log_parse_error(r
);
4148 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "BlockIODeviceWeight")) {
4152 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4154 return bus_log_parse_error(r
);
4156 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &weight
)) > 0)
4157 printf("%s=%s %" PRIu64
"\n", name
, strna(path
), weight
);
4159 return bus_log_parse_error(r
);
4161 r
= sd_bus_message_exit_container(m
);
4163 return bus_log_parse_error(r
);
4167 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& (streq(name
, "BlockIOReadBandwidth") || streq(name
, "BlockIOWriteBandwidth"))) {
4171 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4173 return bus_log_parse_error(r
);
4175 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &bandwidth
)) > 0)
4176 printf("%s=%s %" PRIu64
"\n", name
, strna(path
), bandwidth
);
4178 return bus_log_parse_error(r
);
4180 r
= sd_bus_message_exit_container(m
);
4182 return bus_log_parse_error(r
);
4190 r
= bus_print_property(name
, m
, arg_all
);
4192 return bus_log_parse_error(r
);
4195 r
= sd_bus_message_skip(m
, contents
);
4197 return bus_log_parse_error(r
);
4200 printf("%s=[unprintable]\n", name
);
4206 static int show_one(
4210 bool show_properties
,
4214 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4215 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4216 UnitStatusInfo info
= {
4217 .memory_current
= (uint64_t) -1,
4218 .memory_limit
= (uint64_t) -1,
4219 .cpu_usage_nsec
= (uint64_t) -1,
4227 log_debug("Showing one %s", path
);
4229 r
= sd_bus_call_method(
4231 "org.freedesktop.systemd1",
4233 "org.freedesktop.DBus.Properties",
4239 log_error("Failed to get properties: %s", bus_error_message(&error
, r
));
4243 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
4245 return bus_log_parse_error(r
);
4252 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
4253 const char *name
, *contents
;
4255 r
= sd_bus_message_read(reply
, "s", &name
);
4257 return bus_log_parse_error(r
);
4259 r
= sd_bus_message_peek_type(reply
, NULL
, &contents
);
4261 return bus_log_parse_error(r
);
4263 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, contents
);
4265 return bus_log_parse_error(r
);
4267 if (show_properties
)
4268 r
= print_property(name
, reply
, contents
);
4270 r
= status_property(name
, reply
, &info
, contents
);
4274 r
= sd_bus_message_exit_container(reply
);
4276 return bus_log_parse_error(r
);
4278 r
= sd_bus_message_exit_container(reply
);
4280 return bus_log_parse_error(r
);
4283 return bus_log_parse_error(r
);
4285 r
= sd_bus_message_exit_container(reply
);
4287 return bus_log_parse_error(r
);
4291 if (!show_properties
) {
4292 if (streq(verb
, "help"))
4293 show_unit_help(&info
);
4295 print_status_info(&info
, ellipsized
);
4298 strv_free(info
.documentation
);
4299 strv_free(info
.dropin_paths
);
4300 strv_free(info
.listen
);
4302 if (!streq_ptr(info
.active_state
, "active") &&
4303 !streq_ptr(info
.active_state
, "reloading") &&
4304 streq(verb
, "status")) {
4305 /* According to LSB: "program not running" */
4306 /* 0: program is running or service is OK
4307 * 1: program is dead and /run PID file exists
4308 * 2: program is dead and /run/lock lock file exists
4309 * 3: program is not running
4310 * 4: program or service status is unknown
4312 if (info
.pid_file
&& access(info
.pid_file
, F_OK
) == 0)
4318 while ((p
= info
.exec
)) {
4319 LIST_REMOVE(exec
, info
.exec
, p
);
4320 exec_status_info_free(p
);
4326 static int get_unit_dbus_path_by_pid(
4331 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4332 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4336 r
= sd_bus_call_method(
4338 "org.freedesktop.systemd1",
4339 "/org/freedesktop/systemd1",
4340 "org.freedesktop.systemd1.Manager",
4346 log_error("Failed to get unit for PID %"PRIu32
": %s", pid
, bus_error_message(&error
, r
));
4350 r
= sd_bus_message_read(reply
, "o", &u
);
4352 return bus_log_parse_error(r
);
4362 static int show_all(
4365 bool show_properties
,
4369 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4370 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
4375 r
= get_unit_list(bus
, NULL
, NULL
, &unit_infos
, 0, &reply
);
4379 pager_open_if_enabled();
4383 qsort_safe(unit_infos
, c
, sizeof(UnitInfo
), compare_unit_info
);
4385 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
4386 _cleanup_free_
char *p
= NULL
;
4388 p
= unit_dbus_path_from_name(u
->id
);
4392 r
= show_one(verb
, bus
, p
, show_properties
, new_line
, ellipsized
);
4395 else if (r
> 0 && ret
== 0)
4402 static int show_system_status(sd_bus
*bus
) {
4403 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], since2
[FORMAT_TIMESTAMP_MAX
];
4404 _cleanup_free_
char *hn
= NULL
;
4405 struct machine_info mi
= {};
4406 const char *on
, *off
;
4409 hn
= gethostname_malloc();
4413 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, &mi
);
4415 return log_error_errno(r
, "Failed to read server status: %m");
4417 if (streq_ptr(mi
.state
, "degraded")) {
4418 on
= ansi_highlight_red();
4419 off
= ansi_highlight_off();
4420 } else if (!streq_ptr(mi
.state
, "running")) {
4421 on
= ansi_highlight_yellow();
4422 off
= ansi_highlight_off();
4426 printf("%s%s%s %s\n", on
, draw_special_char(DRAW_BLACK_CIRCLE
), off
, arg_host
? arg_host
: hn
);
4428 printf(" State: %s%s%s\n",
4429 on
, strna(mi
.state
), off
);
4431 printf(" Jobs: %u queued\n", mi
.n_jobs
);
4432 printf(" Failed: %u units\n", mi
.n_failed_units
);
4434 printf(" Since: %s; %s\n",
4435 format_timestamp(since2
, sizeof(since2
), mi
.timestamp
),
4436 format_timestamp_relative(since1
, sizeof(since1
), mi
.timestamp
));
4438 printf(" CGroup: %s\n", mi
.control_group
?: "/");
4439 if (arg_transport
== BUS_TRANSPORT_LOCAL
|| arg_transport
== BUS_TRANSPORT_MACHINE
) {
4440 static const char prefix
[] = " ";
4444 if (c
> sizeof(prefix
) - 1)
4445 c
-= sizeof(prefix
) - 1;
4449 show_cgroup(SYSTEMD_CGROUP_CONTROLLER
, strempty(mi
.control_group
), prefix
, c
, false, get_output_flags());
4453 free(mi
.control_group
);
4458 static int show(sd_bus
*bus
, char **args
) {
4459 bool show_properties
, show_status
, new_line
= false;
4460 bool ellipsized
= false;
4466 show_properties
= streq(args
[0], "show");
4467 show_status
= streq(args
[0], "status");
4469 if (show_properties
)
4470 pager_open_if_enabled();
4473 /* Increase max number of open files to 16K if we can, we
4474 * might needs this when browsing journal files, which might
4475 * be split up into many files. */
4476 setrlimit_closest(RLIMIT_NOFILE
, &RLIMIT_MAKE_CONST(16384));
4478 /* If no argument is specified inspect the manager itself */
4480 if (show_properties
&& strv_length(args
) <= 1)
4481 return show_one(args
[0], bus
, "/org/freedesktop/systemd1", show_properties
, &new_line
, &ellipsized
);
4483 if (show_status
&& strv_length(args
) <= 1) {
4485 pager_open_if_enabled();
4486 show_system_status(bus
);
4490 ret
= show_all(args
[0], bus
, false, &new_line
, &ellipsized
);
4492 _cleanup_free_
char **patterns
= NULL
;
4495 STRV_FOREACH(name
, args
+ 1) {
4496 _cleanup_free_
char *unit
= NULL
;
4499 if (safe_atou32(*name
, &id
) < 0) {
4500 if (strv_push(&patterns
, *name
) < 0)
4504 } else if (show_properties
) {
4505 /* Interpret as job id */
4506 if (asprintf(&unit
, "/org/freedesktop/systemd1/job/%u", id
) < 0)
4510 /* Interpret as PID */
4511 r
= get_unit_dbus_path_by_pid(bus
, id
, &unit
);
4518 r
= show_one(args
[0], bus
, unit
, show_properties
,
4519 &new_line
, &ellipsized
);
4522 else if (r
> 0 && ret
== 0)
4526 if (!strv_isempty(patterns
)) {
4527 _cleanup_strv_free_
char **names
= NULL
;
4529 r
= expand_names(bus
, patterns
, NULL
, &names
);
4531 log_error_errno(r
, "Failed to expand names: %m");
4533 STRV_FOREACH(name
, names
) {
4534 _cleanup_free_
char *unit
;
4536 unit
= unit_dbus_path_from_name(*name
);
4540 r
= show_one(args
[0], bus
, unit
, show_properties
,
4541 &new_line
, &ellipsized
);
4544 else if (r
> 0 && ret
== 0)
4550 if (ellipsized
&& !arg_quiet
)
4551 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4556 static int init_home_and_lookup_paths(char **user_home
, char **user_runtime
, LookupPaths
*lp
) {
4560 assert(user_runtime
);
4563 if (arg_scope
== UNIT_FILE_USER
) {
4564 r
= user_config_home(user_home
);
4566 return log_error_errno(r
, "Failed to query XDG_CONFIG_HOME: %m");
4568 return log_error_errno(ENOTDIR
, "Cannot find units: $XDG_CONFIG_HOME and $HOME are not set.");
4570 r
= user_runtime_dir(user_runtime
);
4572 return log_error_errno(r
, "Failed to query XDG_CONFIG_HOME: %m");
4574 return log_error_errno(ENOTDIR
, "Cannot find units: $XDG_RUNTIME_DIR is not set.");
4577 r
= lookup_paths_init_from_scope(lp
, arg_scope
, arg_root
);
4579 return log_error_errno(r
, "Failed to query unit lookup paths: %m");
4584 static int cat_file(const char *filename
, bool newline
) {
4585 _cleanup_close_
int fd
;
4587 fd
= open(filename
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
4591 printf("%s%s# %s%s\n",
4592 newline
? "\n" : "",
4593 ansi_highlight_blue(),
4595 ansi_highlight_off());
4598 return copy_bytes(fd
, STDOUT_FILENO
, (off_t
) -1, false);
4601 static int cat(sd_bus
*bus
, char **args
) {
4602 _cleanup_free_
char *user_home
= NULL
;
4603 _cleanup_free_
char *user_runtime
= NULL
;
4604 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
4605 _cleanup_strv_free_
char **names
= NULL
;
4607 bool first
= true, avoid_bus_cache
;
4612 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
4613 log_error("Cannot remotely cat units");
4617 r
= init_home_and_lookup_paths(&user_home
, &user_runtime
, &lp
);
4621 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
4623 return log_error_errno(r
, "Failed to expand names: %m");
4625 avoid_bus_cache
= !bus
|| avoid_bus();
4627 pager_open_if_enabled();
4629 STRV_FOREACH(name
, names
) {
4630 _cleanup_free_
char *fragment_path
= NULL
;
4631 _cleanup_strv_free_
char **dropin_paths
= NULL
;
4634 r
= unit_find_paths(bus
, *name
, avoid_bus_cache
, &lp
, &fragment_path
, &dropin_paths
);
4645 if (fragment_path
) {
4646 r
= cat_file(fragment_path
, false);
4648 return log_warning_errno(r
, "Failed to cat %s: %m", fragment_path
);
4651 STRV_FOREACH(path
, dropin_paths
) {
4652 r
= cat_file(*path
, path
== dropin_paths
);
4654 return log_warning_errno(r
, "Failed to cat %s: %m", *path
);
4661 static int set_property(sd_bus
*bus
, char **args
) {
4662 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
4663 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4664 _cleanup_free_
char *n
= NULL
;
4668 polkit_agent_open_if_enabled();
4670 r
= sd_bus_message_new_method_call(
4673 "org.freedesktop.systemd1",
4674 "/org/freedesktop/systemd1",
4675 "org.freedesktop.systemd1.Manager",
4676 "SetUnitProperties");
4678 return bus_log_create_error(r
);
4680 r
= unit_name_mangle(args
[1], UNIT_NAME_NOGLOB
, &n
);
4682 return log_error_errno(r
, "Failed to mangle unit name: %m");
4684 r
= sd_bus_message_append(m
, "sb", n
, arg_runtime
);
4686 return bus_log_create_error(r
);
4688 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, "(sv)");
4690 return bus_log_create_error(r
);
4692 STRV_FOREACH(i
, args
+ 2) {
4693 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_STRUCT
, "sv");
4695 return bus_log_create_error(r
);
4697 r
= bus_append_unit_property_assignment(m
, *i
);
4701 r
= sd_bus_message_close_container(m
);
4703 return bus_log_create_error(r
);
4706 r
= sd_bus_message_close_container(m
);
4708 return bus_log_create_error(r
);
4710 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
4712 log_error("Failed to set unit properties on %s: %s", n
, bus_error_message(&error
, r
));
4719 static int snapshot(sd_bus
*bus
, char **args
) {
4720 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4721 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4722 _cleanup_free_
char *n
= NULL
, *id
= NULL
;
4726 polkit_agent_open_if_enabled();
4728 if (strv_length(args
) > 1) {
4729 r
= unit_name_mangle_with_suffix(args
[1], UNIT_NAME_NOGLOB
, ".snapshot", &n
);
4731 return log_error_errno(r
, "Failed to generate unit name: %m");
4738 r
= sd_bus_call_method(
4740 "org.freedesktop.systemd1",
4741 "/org/freedesktop/systemd1",
4742 "org.freedesktop.systemd1.Manager",
4748 log_error("Failed to create snapshot: %s", bus_error_message(&error
, r
));
4752 r
= sd_bus_message_read(reply
, "o", &path
);
4754 return bus_log_parse_error(r
);
4756 r
= sd_bus_get_property_string(
4758 "org.freedesktop.systemd1",
4760 "org.freedesktop.systemd1.Unit",
4765 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error
, r
));
4775 static int delete_snapshot(sd_bus
*bus
, char **args
) {
4776 _cleanup_strv_free_
char **names
= NULL
;
4782 polkit_agent_open_if_enabled();
4784 r
= expand_names(bus
, args
+ 1, ".snapshot", &names
);
4786 log_error_errno(r
, "Failed to expand names: %m");
4788 STRV_FOREACH(name
, names
) {
4789 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4792 q
= sd_bus_call_method(
4794 "org.freedesktop.systemd1",
4795 "/org/freedesktop/systemd1",
4796 "org.freedesktop.systemd1.Manager",
4802 log_error("Failed to remove snapshot %s: %s", *name
, bus_error_message(&error
, q
));
4811 static int daemon_reload(sd_bus
*bus
, char **args
) {
4812 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4816 polkit_agent_open_if_enabled();
4818 if (arg_action
== ACTION_RELOAD
)
4820 else if (arg_action
== ACTION_REEXEC
)
4821 method
= "Reexecute";
4823 assert(arg_action
== ACTION_SYSTEMCTL
);
4826 streq(args
[0], "clear-jobs") ||
4827 streq(args
[0], "cancel") ? "ClearJobs" :
4828 streq(args
[0], "daemon-reexec") ? "Reexecute" :
4829 streq(args
[0], "reset-failed") ? "ResetFailed" :
4830 streq(args
[0], "halt") ? "Halt" :
4831 streq(args
[0], "poweroff") ? "PowerOff" :
4832 streq(args
[0], "reboot") ? "Reboot" :
4833 streq(args
[0], "kexec") ? "KExec" :
4834 streq(args
[0], "exit") ? "Exit" :
4835 /* "daemon-reload" */ "Reload";
4838 r
= sd_bus_call_method(
4840 "org.freedesktop.systemd1",
4841 "/org/freedesktop/systemd1",
4842 "org.freedesktop.systemd1.Manager",
4847 if (r
== -ENOENT
&& arg_action
!= ACTION_SYSTEMCTL
)
4848 /* There's always a fallback possible for
4849 * legacy actions. */
4851 else if ((r
== -ETIMEDOUT
|| r
== -ECONNRESET
) && streq(method
, "Reexecute"))
4852 /* On reexecution, we expect a disconnect, not a
4856 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
4858 return r
< 0 ? r
: 0;
4861 static int reset_failed(sd_bus
*bus
, char **args
) {
4862 _cleanup_strv_free_
char **names
= NULL
;
4866 if (strv_length(args
) <= 1)
4867 return daemon_reload(bus
, args
);
4869 polkit_agent_open_if_enabled();
4871 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
4873 log_error_errno(r
, "Failed to expand names: %m");
4875 STRV_FOREACH(name
, names
) {
4876 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4878 q
= sd_bus_call_method(
4880 "org.freedesktop.systemd1",
4881 "/org/freedesktop/systemd1",
4882 "org.freedesktop.systemd1.Manager",
4888 log_error("Failed to reset failed state of unit %s: %s", *name
, bus_error_message(&error
, q
));
4897 static int show_environment(sd_bus
*bus
, char **args
) {
4898 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4899 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4903 pager_open_if_enabled();
4905 r
= sd_bus_get_property(
4907 "org.freedesktop.systemd1",
4908 "/org/freedesktop/systemd1",
4909 "org.freedesktop.systemd1.Manager",
4915 log_error("Failed to get environment: %s", bus_error_message(&error
, r
));
4919 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
4921 return bus_log_parse_error(r
);
4923 while ((r
= sd_bus_message_read_basic(reply
, SD_BUS_TYPE_STRING
, &text
)) > 0)
4926 return bus_log_parse_error(r
);
4928 r
= sd_bus_message_exit_container(reply
);
4930 return bus_log_parse_error(r
);
4935 static int switch_root(sd_bus
*bus
, char **args
) {
4936 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4937 _cleanup_free_
char *cmdline_init
= NULL
;
4938 const char *root
, *init
;
4942 l
= strv_length(args
);
4943 if (l
< 2 || l
> 3) {
4944 log_error("Wrong number of arguments.");
4953 r
= parse_env_file("/proc/cmdline", WHITESPACE
,
4954 "init", &cmdline_init
,
4957 log_debug_errno(r
, "Failed to parse /proc/cmdline: %m");
4959 init
= cmdline_init
;
4966 const char *root_systemd_path
= NULL
, *root_init_path
= NULL
;
4968 root_systemd_path
= strjoina(root
, "/" SYSTEMD_BINARY_PATH
);
4969 root_init_path
= strjoina(root
, "/", init
);
4971 /* If the passed init is actually the same as the
4972 * systemd binary, then let's suppress it. */
4973 if (files_same(root_init_path
, root_systemd_path
) > 0)
4977 log_debug("Switching root - root: %s; init: %s", root
, strna(init
));
4979 r
= sd_bus_call_method(
4981 "org.freedesktop.systemd1",
4982 "/org/freedesktop/systemd1",
4983 "org.freedesktop.systemd1.Manager",
4989 log_error("Failed to switch root: %s", bus_error_message(&error
, r
));
4996 static int set_environment(sd_bus
*bus
, char **args
) {
4997 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4998 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
5005 polkit_agent_open_if_enabled();
5007 method
= streq(args
[0], "set-environment")
5009 : "UnsetEnvironment";
5011 r
= sd_bus_message_new_method_call(
5014 "org.freedesktop.systemd1",
5015 "/org/freedesktop/systemd1",
5016 "org.freedesktop.systemd1.Manager",
5019 return bus_log_create_error(r
);
5021 r
= sd_bus_message_append_strv(m
, args
+ 1);
5023 return bus_log_create_error(r
);
5025 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5027 log_error("Failed to set environment: %s", bus_error_message(&error
, r
));
5034 static int import_environment(sd_bus
*bus
, char **args
) {
5035 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5036 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
5042 polkit_agent_open_if_enabled();
5044 r
= sd_bus_message_new_method_call(
5047 "org.freedesktop.systemd1",
5048 "/org/freedesktop/systemd1",
5049 "org.freedesktop.systemd1.Manager",
5052 return bus_log_create_error(r
);
5054 if (strv_isempty(args
+ 1))
5055 r
= sd_bus_message_append_strv(m
, environ
);
5059 r
= sd_bus_message_open_container(m
, 'a', "s");
5061 return bus_log_create_error(r
);
5063 STRV_FOREACH(a
, args
+ 1) {
5065 if (!env_name_is_valid(*a
)) {
5066 log_error("Not a valid environment variable name: %s", *a
);
5070 STRV_FOREACH(b
, environ
) {
5073 eq
= startswith(*b
, *a
);
5074 if (eq
&& *eq
== '=') {
5076 r
= sd_bus_message_append(m
, "s", *b
);
5078 return bus_log_create_error(r
);
5085 r
= sd_bus_message_close_container(m
);
5088 return bus_log_create_error(r
);
5090 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5092 log_error("Failed to import environment: %s", bus_error_message(&error
, r
));
5099 static int enable_sysv_units(const char *verb
, char **args
) {
5102 #if defined(HAVE_SYSV_COMPAT)
5104 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
5106 if (arg_scope
!= UNIT_FILE_SYSTEM
)
5109 if (!streq(verb
, "enable") &&
5110 !streq(verb
, "disable") &&
5111 !streq(verb
, "is-enabled"))
5114 /* Processes all SysV units, and reshuffles the array so that
5115 * afterwards only the native units remain */
5117 r
= lookup_paths_init(&paths
, MANAGER_SYSTEM
, false, arg_root
, NULL
, NULL
, NULL
);
5124 _cleanup_free_
char *p
= NULL
, *q
= NULL
, *l
= NULL
;
5125 bool found_native
= false, found_sysv
;
5127 const char *argv
[6] = { ROOTLIBEXECDIR
"/systemd-sysv-install", NULL
, NULL
, NULL
, NULL
};
5135 if (!endswith(name
, ".service"))
5138 if (path_is_absolute(name
))
5141 STRV_FOREACH(k
, paths
.unit_path
) {
5142 _cleanup_free_
char *path
= NULL
;
5144 path
= path_join(arg_root
, *k
, name
);
5148 found_native
= access(path
, F_OK
) >= 0;
5153 /* If we have both a native unit and a SysV script,
5154 * enable/disable them both (below); for is-enabled, prefer the
5156 if (found_native
&& streq(verb
, "is-enabled"))
5159 p
= path_join(arg_root
, SYSTEM_SYSVINIT_PATH
, name
);
5163 p
[strlen(p
) - strlen(".service")] = 0;
5164 found_sysv
= access(p
, F_OK
) >= 0;
5169 log_info("Synchronizing state of %s with SysV init with %s...", name
, argv
[0]);
5171 log_info("%s is not a native service, redirecting to systemd-sysv-install", name
);
5173 if (!isempty(arg_root
))
5174 argv
[c
++] = q
= strappend("--root=", arg_root
);
5177 argv
[c
++] = basename(p
);
5180 l
= strv_join((char**)argv
, " ");
5184 log_info("Executing %s", l
);
5188 return log_error_errno(errno
, "Failed to fork: %m");
5189 else if (pid
== 0) {
5192 execv(argv
[0], (char**) argv
);
5193 log_error("Failed to execute %s: %m", argv
[0]);
5194 _exit(EXIT_FAILURE
);
5197 j
= wait_for_terminate(pid
, &status
);
5199 log_error_errno(r
, "Failed to wait for child: %m");
5203 if (status
.si_code
== CLD_EXITED
) {
5204 if (streq(verb
, "is-enabled")) {
5205 if (status
.si_status
== 0) {
5214 } else if (status
.si_status
!= 0)
5222 /* Remove this entry, so that we don't try enabling it as native unit */
5225 assert(args
[f
] == name
);
5226 strv_remove(args
, name
);
5233 static int mangle_names(char **original_names
, char ***mangled_names
) {
5234 char **i
, **l
, **name
;
5237 l
= i
= new(char*, strv_length(original_names
) + 1);
5241 STRV_FOREACH(name
, original_names
) {
5243 /* When enabling units qualified path names are OK,
5244 * too, hence allow them explicitly. */
5246 if (is_path(*name
)) {
5253 r
= unit_name_mangle(*name
, UNIT_NAME_NOGLOB
, i
);
5256 return log_error_errno(r
, "Failed to mangle unit name: %m");
5269 static int enable_unit(sd_bus
*bus
, char **args
) {
5270 _cleanup_strv_free_
char **names
= NULL
;
5271 const char *verb
= args
[0];
5272 UnitFileChange
*changes
= NULL
;
5273 unsigned n_changes
= 0;
5274 int carries_install_info
= -1;
5280 r
= mangle_names(args
+1, &names
);
5284 r
= enable_sysv_units(verb
, names
);
5288 /* If the operation was fully executed by the SysV compat,
5289 * let's finish early */
5290 if (strv_isempty(names
))
5293 if (!bus
|| avoid_bus()) {
5294 if (streq(verb
, "enable")) {
5295 r
= unit_file_enable(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5296 carries_install_info
= r
;
5297 } else if (streq(verb
, "disable"))
5298 r
= unit_file_disable(arg_scope
, arg_runtime
, arg_root
, names
, &changes
, &n_changes
);
5299 else if (streq(verb
, "reenable")) {
5300 r
= unit_file_reenable(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5301 carries_install_info
= r
;
5302 } else if (streq(verb
, "link"))
5303 r
= unit_file_link(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5304 else if (streq(verb
, "preset")) {
5305 r
= unit_file_preset(arg_scope
, arg_runtime
, arg_root
, names
, arg_preset_mode
, arg_force
, &changes
, &n_changes
);
5306 carries_install_info
= r
;
5307 } else if (streq(verb
, "mask"))
5308 r
= unit_file_mask(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5309 else if (streq(verb
, "unmask"))
5310 r
= unit_file_unmask(arg_scope
, arg_runtime
, arg_root
, names
, &changes
, &n_changes
);
5312 assert_not_reached("Unknown verb");
5315 log_error_errno(r
, "Operation failed: %m");
5320 dump_unit_file_changes(changes
, n_changes
);
5324 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
, *m
= NULL
;
5325 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5326 int expect_carries_install_info
= false;
5327 bool send_force
= true, send_preset_mode
= false;
5330 polkit_agent_open_if_enabled();
5332 if (streq(verb
, "enable")) {
5333 method
= "EnableUnitFiles";
5334 expect_carries_install_info
= true;
5335 } else if (streq(verb
, "disable")) {
5336 method
= "DisableUnitFiles";
5338 } else if (streq(verb
, "reenable")) {
5339 method
= "ReenableUnitFiles";
5340 expect_carries_install_info
= true;
5341 } else if (streq(verb
, "link"))
5342 method
= "LinkUnitFiles";
5343 else if (streq(verb
, "preset")) {
5345 if (arg_preset_mode
!= UNIT_FILE_PRESET_FULL
) {
5346 method
= "PresetUnitFilesWithMode";
5347 send_preset_mode
= true;
5349 method
= "PresetUnitFiles";
5351 expect_carries_install_info
= true;
5352 } else if (streq(verb
, "mask"))
5353 method
= "MaskUnitFiles";
5354 else if (streq(verb
, "unmask")) {
5355 method
= "UnmaskUnitFiles";
5358 assert_not_reached("Unknown verb");
5360 r
= sd_bus_message_new_method_call(
5363 "org.freedesktop.systemd1",
5364 "/org/freedesktop/systemd1",
5365 "org.freedesktop.systemd1.Manager",
5368 return bus_log_create_error(r
);
5370 r
= sd_bus_message_append_strv(m
, names
);
5372 return bus_log_create_error(r
);
5374 if (send_preset_mode
) {
5375 r
= sd_bus_message_append(m
, "s", unit_file_preset_mode_to_string(arg_preset_mode
));
5377 return bus_log_create_error(r
);
5380 r
= sd_bus_message_append(m
, "b", arg_runtime
);
5382 return bus_log_create_error(r
);
5385 r
= sd_bus_message_append(m
, "b", arg_force
);
5387 return bus_log_create_error(r
);
5390 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
5392 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
5396 if (expect_carries_install_info
) {
5397 r
= sd_bus_message_read(reply
, "b", &carries_install_info
);
5399 return bus_log_parse_error(r
);
5402 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
5406 /* Try to reload if enabled */
5408 r
= daemon_reload(bus
, args
);
5413 if (carries_install_info
== 0)
5414 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5415 "using systemctl.\n"
5416 "Possible reasons for having this kind of units are:\n"
5417 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5418 " .wants/ or .requires/ directory.\n"
5419 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5420 " a requirement dependency on it.\n"
5421 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5422 " D-Bus, udev, scripted systemctl call, ...).\n");
5424 if (arg_now
&& n_changes
> 0 && STR_IN_SET(args
[0], "enable", "disable", "mask")) {
5425 char *new_args
[n_changes
+ 2];
5428 new_args
[0] = streq(args
[0], "enable") ? (char *)"start" : (char *)"stop";
5429 for (i
= 0; i
< n_changes
; i
++)
5430 new_args
[i
+ 1] = basename(changes
[i
].path
);
5431 new_args
[i
+ 1] = NULL
;
5433 r
= start_unit(bus
, new_args
);
5437 unit_file_changes_free(changes
, n_changes
);
5442 static int add_dependency(sd_bus
*bus
, char **args
) {
5443 _cleanup_strv_free_
char **names
= NULL
;
5444 _cleanup_free_
char *target
= NULL
;
5445 const char *verb
= args
[0];
5452 r
= unit_name_mangle_with_suffix(args
[1], UNIT_NAME_NOGLOB
, ".target", &target
);
5454 return log_error_errno(r
, "Failed to mangle unit name: %m");
5456 r
= mangle_names(args
+2, &names
);
5460 if (streq(verb
, "add-wants"))
5462 else if (streq(verb
, "add-requires"))
5463 dep
= UNIT_REQUIRES
;
5465 assert_not_reached("Unknown verb");
5467 if (!bus
|| avoid_bus()) {
5468 UnitFileChange
*changes
= NULL
;
5469 unsigned n_changes
= 0;
5471 r
= unit_file_add_dependency(arg_scope
, arg_runtime
, arg_root
, names
, target
, dep
, arg_force
, &changes
, &n_changes
);
5474 return log_error_errno(r
, "Can't add dependency: %m");
5477 dump_unit_file_changes(changes
, n_changes
);
5479 unit_file_changes_free(changes
, n_changes
);
5482 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
, *m
= NULL
;
5483 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5485 polkit_agent_open_if_enabled();
5487 r
= sd_bus_message_new_method_call(
5490 "org.freedesktop.systemd1",
5491 "/org/freedesktop/systemd1",
5492 "org.freedesktop.systemd1.Manager",
5493 "AddDependencyUnitFiles");
5495 return bus_log_create_error(r
);
5497 r
= sd_bus_message_append_strv(m
, names
);
5499 return bus_log_create_error(r
);
5501 r
= sd_bus_message_append(m
, "ssbb", target
, unit_dependency_to_string(dep
), arg_runtime
, arg_force
);
5503 return bus_log_create_error(r
);
5505 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
5507 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
5511 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, NULL
, NULL
);
5516 r
= daemon_reload(bus
, args
);
5524 static int preset_all(sd_bus
*bus
, char **args
) {
5525 UnitFileChange
*changes
= NULL
;
5526 unsigned n_changes
= 0;
5529 if (!bus
|| avoid_bus()) {
5531 r
= unit_file_preset_all(arg_scope
, arg_runtime
, arg_root
, arg_preset_mode
, arg_force
, &changes
, &n_changes
);
5533 log_error_errno(r
, "Operation failed: %m");
5538 dump_unit_file_changes(changes
, n_changes
);
5543 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5544 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
5546 polkit_agent_open_if_enabled();
5548 r
= sd_bus_call_method(
5550 "org.freedesktop.systemd1",
5551 "/org/freedesktop/systemd1",
5552 "org.freedesktop.systemd1.Manager",
5553 "PresetAllUnitFiles",
5557 unit_file_preset_mode_to_string(arg_preset_mode
),
5561 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
5565 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, NULL
, NULL
);
5570 r
= daemon_reload(bus
, args
);
5576 unit_file_changes_free(changes
, n_changes
);
5581 static int unit_is_enabled(sd_bus
*bus
, char **args
) {
5583 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5584 _cleanup_strv_free_
char **names
= NULL
;
5589 r
= mangle_names(args
+1, &names
);
5593 r
= enable_sysv_units(args
[0], names
);
5599 if (!bus
|| avoid_bus()) {
5601 STRV_FOREACH(name
, names
) {
5602 UnitFileState state
;
5604 state
= unit_file_get_state(arg_scope
, arg_root
, *name
);
5606 return log_error_errno(state
, "Failed to get unit file state for %s: %m", *name
);
5608 if (state
== UNIT_FILE_ENABLED
||
5609 state
== UNIT_FILE_ENABLED_RUNTIME
||
5610 state
== UNIT_FILE_STATIC
||
5611 state
== UNIT_FILE_INDIRECT
)
5615 puts(unit_file_state_to_string(state
));
5619 STRV_FOREACH(name
, names
) {
5620 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
5623 r
= sd_bus_call_method(
5625 "org.freedesktop.systemd1",
5626 "/org/freedesktop/systemd1",
5627 "org.freedesktop.systemd1.Manager",
5633 log_error("Failed to get unit file state for %s: %s", *name
, bus_error_message(&error
, r
));
5637 r
= sd_bus_message_read(reply
, "s", &s
);
5639 return bus_log_parse_error(r
);
5641 if (STR_IN_SET(s
, "enabled", "enabled-runtime", "static", "indirect"))
5652 static int is_system_running(sd_bus
*bus
, char **args
) {
5653 _cleanup_free_
char *state
= NULL
;
5656 r
= sd_bus_get_property_string(
5658 "org.freedesktop.systemd1",
5659 "/org/freedesktop/systemd1",
5660 "org.freedesktop.systemd1.Manager",
5673 return streq(state
, "running") ? EXIT_SUCCESS
: EXIT_FAILURE
;
5676 static int create_edit_temp_file(const char *new_path
, const char *original_path
, char **ret_tmp_fn
) {
5681 assert(original_path
);
5684 r
= tempfn_random(new_path
, &t
);
5686 return log_error_errno(r
, "Failed to determine temporary filename for \"%s\": %m", new_path
);
5688 r
= mkdir_parents(new_path
, 0755);
5690 log_error_errno(r
, "Failed to create directories for \"%s\": %m", new_path
);
5695 r
= copy_file(original_path
, t
, 0, 0644, 0);
5699 log_error_errno(r
, "Failed to create temporary file \"%s\": %m", t
);
5704 log_error_errno(r
, "Failed to copy \"%s\" to \"%s\": %m", original_path
, t
);
5714 static int get_file_to_edit(const char *name
, const char *user_home
, const char *user_runtime
, char **ret_path
) {
5715 _cleanup_free_
char *path
= NULL
, *path2
= NULL
, *run
= NULL
;
5717 switch (arg_scope
) {
5718 case UNIT_FILE_SYSTEM
:
5719 path
= path_join(arg_root
, SYSTEM_CONFIG_UNIT_PATH
, name
);
5721 run
= path_join(arg_root
, "/run/systemd/system/", name
);
5723 case UNIT_FILE_GLOBAL
:
5724 path
= path_join(arg_root
, USER_CONFIG_UNIT_PATH
, name
);
5726 run
= path_join(arg_root
, "/run/systemd/user/", name
);
5728 case UNIT_FILE_USER
:
5730 assert(user_runtime
);
5732 path
= path_join(arg_root
, user_home
, name
);
5734 path2
= path_join(arg_root
, USER_CONFIG_UNIT_PATH
, name
);
5737 run
= path_join(arg_root
, user_runtime
, name
);
5741 assert_not_reached("Invalid scope");
5743 if (!path
|| (arg_runtime
&& !run
))
5747 if (access(path
, F_OK
) >= 0)
5748 return log_error_errno(EEXIST
, "Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.",
5750 if (path2
&& access(path2
, F_OK
) >= 0)
5751 return log_error_errno(EEXIST
, "Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.",
5763 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
) {
5764 char *tmp_new_path
, *ending
;
5769 assert(ret_new_path
);
5770 assert(ret_tmp_path
);
5772 ending
= strjoina(unit_name
, ".d/override.conf");
5773 r
= get_file_to_edit(ending
, user_home
, user_runtime
, &tmp_new_path
);
5777 r
= create_edit_temp_file(tmp_new_path
, tmp_new_path
, &tmp_tmp_path
);
5783 *ret_new_path
= tmp_new_path
;
5784 *ret_tmp_path
= tmp_tmp_path
;
5789 static int unit_file_create_copy(
5790 const char *unit_name
,
5791 const char *fragment_path
,
5792 const char *user_home
,
5793 const char *user_runtime
,
5794 char **ret_new_path
,
5795 char **ret_tmp_path
) {
5801 assert(fragment_path
);
5803 assert(ret_new_path
);
5804 assert(ret_tmp_path
);
5806 r
= get_file_to_edit(unit_name
, user_home
, user_runtime
, &tmp_new_path
);
5810 if (!path_equal(fragment_path
, tmp_new_path
) && access(tmp_new_path
, F_OK
) == 0) {
5813 r
= ask_char(&response
, "yn", "\"%s\" already exists. Overwrite with \"%s\"? [(y)es, (n)o] ", tmp_new_path
, fragment_path
);
5818 if (response
!= 'y') {
5819 log_warning("%s ignored", unit_name
);
5825 r
= create_edit_temp_file(tmp_new_path
, fragment_path
, &tmp_tmp_path
);
5827 log_error_errno(r
, "Failed to create temporary file for \"%s\": %m", tmp_new_path
);
5832 *ret_new_path
= tmp_new_path
;
5833 *ret_tmp_path
= tmp_tmp_path
;
5838 static int run_editor(char **paths
) {
5846 log_error_errno(errno
, "Failed to fork: %m");
5853 char **tmp_path
, **original_path
, *p
;
5857 argc
= strv_length(paths
)/2 + 1;
5858 args
= newa(const char*, argc
+ 1);
5861 STRV_FOREACH_PAIR(original_path
, tmp_path
, paths
) {
5862 args
[i
] = *tmp_path
;
5867 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
5868 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
5869 * we try to execute well known editors
5871 editor
= getenv("SYSTEMD_EDITOR");
5873 editor
= getenv("EDITOR");
5875 editor
= getenv("VISUAL");
5877 if (!isempty(editor
)) {
5879 execvp(editor
, (char* const*) args
);
5882 FOREACH_STRING(p
, "nano", "vim", "vi") {
5884 execvp(p
, (char* const*) args
);
5885 /* We do not fail if the editor doesn't exist
5886 * because we want to try each one of them before
5889 if (errno
!= ENOENT
) {
5890 log_error("Failed to execute %s: %m", editor
);
5891 _exit(EXIT_FAILURE
);
5895 log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR, $EDITOR or $VISUAL.");
5896 _exit(EXIT_FAILURE
);
5899 r
= wait_for_terminate_and_warn("editor", pid
, true);
5901 return log_error_errno(r
, "Failed to wait for child: %m");
5906 static int find_paths_to_edit(sd_bus
*bus
, char **names
, char ***paths
) {
5907 _cleanup_free_
char *user_home
= NULL
;
5908 _cleanup_free_
char *user_runtime
= NULL
;
5909 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
5910 bool avoid_bus_cache
;
5917 r
= init_home_and_lookup_paths(&user_home
, &user_runtime
, &lp
);
5921 avoid_bus_cache
= !bus
|| avoid_bus();
5923 STRV_FOREACH(name
, names
) {
5924 _cleanup_free_
char *path
= NULL
;
5925 char *new_path
, *tmp_path
;
5927 r
= unit_find_paths(bus
, *name
, avoid_bus_cache
, &lp
, &path
, NULL
);
5933 // FIXME: support units with path==NULL (no FragmentPath)
5934 log_error("No fragment exists for %s.", *name
);
5939 r
= unit_file_create_copy(*name
, path
, user_home
, user_runtime
, &new_path
, &tmp_path
);
5941 r
= unit_file_create_dropin(*name
, user_home
, user_runtime
, &new_path
, &tmp_path
);
5945 r
= strv_push_pair(paths
, new_path
, tmp_path
);
5953 static int edit(sd_bus
*bus
, char **args
) {
5954 _cleanup_strv_free_
char **names
= NULL
;
5955 _cleanup_strv_free_
char **paths
= NULL
;
5956 char **original
, **tmp
;
5962 log_error("Cannot edit units if not on a tty");
5966 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
5967 log_error("Cannot remotely edit units");
5971 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
5973 return log_error_errno(r
, "Failed to expand names: %m");
5975 r
= find_paths_to_edit(bus
, names
, &paths
);
5979 if (strv_isempty(paths
))
5982 r
= run_editor(paths
);
5986 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
5987 /* If the temporary file is empty we ignore it.
5988 * It's useful if the user wants to cancel its modification
5990 if (null_or_empty_path(*tmp
)) {
5991 log_warning("Editing \"%s\" canceled: temporary file is empty", *original
);
5994 r
= rename(*tmp
, *original
);
5996 r
= log_error_errno(errno
, "Failed to rename \"%s\" to \"%s\": %m", *tmp
, *original
);
6001 if (!arg_no_reload
&& bus
&& !avoid_bus())
6002 r
= daemon_reload(bus
, args
);
6005 STRV_FOREACH_PAIR(original
, tmp
, paths
)
6006 unlink_noerrno(*tmp
);
6011 static void systemctl_help(void) {
6013 pager_open_if_enabled();
6015 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
6016 "Query or send control commands to the systemd manager.\n\n"
6017 " -h --help Show this help\n"
6018 " --version Show package version\n"
6019 " --system Connect to system manager\n"
6020 " --user Connect to user service manager\n"
6021 " -H --host=[USER@]HOST\n"
6022 " Operate on remote host\n"
6023 " -M --machine=CONTAINER\n"
6024 " Operate on local container\n"
6025 " -t --type=TYPE List units of a particular type\n"
6026 " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n"
6027 " -p --property=NAME Show only properties by this name\n"
6028 " -a --all Show all loaded units/properties, including dead/empty\n"
6029 " ones. To list all units installed on the system, use\n"
6030 " the 'list-unit-files' command instead.\n"
6031 " -l --full Don't ellipsize unit names on output\n"
6032 " -r --recursive Show unit list of host and local containers\n"
6033 " --reverse Show reverse dependencies with 'list-dependencies'\n"
6034 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
6035 " queueing a new job\n"
6036 " --show-types When showing sockets, explicitly show their type\n"
6037 " -i --ignore-inhibitors\n"
6038 " When shutting down or sleeping, ignore inhibitors\n"
6039 " --kill-who=WHO Who to send signal to\n"
6040 " -s --signal=SIGNAL Which signal to send\n"
6041 " --now Start or stop unit in addition to enabling or disabling it\n"
6042 " -q --quiet Suppress output\n"
6043 " --no-block Do not wait until operation finished\n"
6044 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6045 " --no-reload Don't reload daemon after en-/dis-abling unit files\n"
6046 " --no-legend Do not print a legend (column headers and hints)\n"
6047 " --no-pager Do not pipe output into a pager\n"
6048 " --no-ask-password\n"
6049 " Do not ask for system passwords\n"
6050 " --global Enable/disable unit files globally\n"
6051 " --runtime Enable unit files only temporarily until next reboot\n"
6052 " -f --force When enabling unit files, override existing symlinks\n"
6053 " When shutting down, execute action immediately\n"
6054 " --preset-mode= Apply only enable, only disable, or all presets\n"
6055 " --root=PATH Enable unit files in the specified root directory\n"
6056 " -n --lines=INTEGER Number of journal entries to show\n"
6057 " -o --output=STRING Change journal output mode (short, short-iso,\n"
6058 " short-precise, short-monotonic, verbose,\n"
6059 " export, json, json-pretty, json-sse, cat)\n"
6060 " --firmware-setup Tell the firmware to show the setup menu on next boot\n"
6061 " --plain Print unit dependencies as a list instead of a tree\n\n"
6063 " list-units [PATTERN...] List loaded units\n"
6064 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
6065 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
6066 " start NAME... Start (activate) one or more units\n"
6067 " stop NAME... Stop (deactivate) one or more units\n"
6068 " reload NAME... Reload one or more units\n"
6069 " restart NAME... Start or restart one or more units\n"
6070 " try-restart NAME... Restart one or more units if active\n"
6071 " reload-or-restart NAME... Reload one or more units if possible,\n"
6072 " otherwise start or restart\n"
6073 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
6074 " otherwise restart if active\n"
6075 " isolate NAME Start one unit and stop all others\n"
6076 " kill NAME... Send signal to processes of a unit\n"
6077 " is-active PATTERN... Check whether units are active\n"
6078 " is-failed PATTERN... Check whether units are failed\n"
6079 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
6080 " show [PATTERN...|JOB...] Show properties of one or more\n"
6081 " units/jobs or the manager\n"
6082 " cat PATTERN... Show files and drop-ins of one or more units\n"
6083 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
6084 " help PATTERN...|PID... Show manual for one or more units\n"
6085 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
6087 " list-dependencies [NAME] Recursively show units which are required\n"
6088 " or wanted by this unit or by which this\n"
6089 " unit is required or wanted\n\n"
6090 "Unit File Commands:\n"
6091 " list-unit-files [PATTERN...] List installed unit files\n"
6092 " enable NAME... Enable one or more unit files\n"
6093 " disable NAME... Disable one or more unit files\n"
6094 " reenable NAME... Reenable one or more unit files\n"
6095 " preset NAME... Enable/disable one or more unit files\n"
6096 " based on preset configuration\n"
6097 " preset-all Enable/disable all unit files based on\n"
6098 " preset configuration\n"
6099 " is-enabled NAME... Check whether unit files are enabled\n"
6100 " mask NAME... Mask one or more units\n"
6101 " unmask NAME... Unmask one or more units\n"
6102 " link PATH... Link one or more units files into\n"
6103 " the search path\n"
6104 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
6105 " on specified one or more units\n"
6106 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
6107 " on specified one or more units\n"
6108 " edit NAME... Edit one or more unit files\n"
6109 " get-default Get the name of the default target\n"
6110 " set-default NAME Set the default target\n\n"
6111 "Machine Commands:\n"
6112 " list-machines [PATTERN...] List local containers and host\n\n"
6114 " list-jobs [PATTERN...] List jobs\n"
6115 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
6116 "Snapshot Commands:\n"
6117 " snapshot [NAME] Create a snapshot\n"
6118 " delete NAME... Remove one or more snapshots\n\n"
6119 "Environment Commands:\n"
6120 " show-environment Dump environment\n"
6121 " set-environment NAME=VALUE... Set one or more environment variables\n"
6122 " unset-environment NAME... Unset one or more environment variables\n"
6123 " import-environment [NAME...] Import all or some environment variables\n\n"
6124 "Manager Lifecycle Commands:\n"
6125 " daemon-reload Reload systemd manager configuration\n"
6126 " daemon-reexec Reexecute systemd manager\n\n"
6127 "System Commands:\n"
6128 " is-system-running Check whether system is fully running\n"
6129 " default Enter system default mode\n"
6130 " rescue Enter system rescue mode\n"
6131 " emergency Enter system emergency mode\n"
6132 " halt Shut down and halt the system\n"
6133 " poweroff Shut down and power-off the system\n"
6134 " reboot [ARG] Shut down and reboot the system\n"
6135 " kexec Shut down and reboot the system with kexec\n"
6136 " exit Request user instance exit\n"
6137 " switch-root ROOT [INIT] Change to a different root file system\n"
6138 " suspend Suspend the system\n"
6139 " hibernate Hibernate the system\n"
6140 " hybrid-sleep Hibernate and suspend the system\n",
6141 program_invocation_short_name
);
6144 static void halt_help(void) {
6145 printf("%s [OPTIONS...]%s\n\n"
6146 "%s the system.\n\n"
6147 " --help Show this help\n"
6148 " --halt Halt the machine\n"
6149 " -p --poweroff Switch off the machine\n"
6150 " --reboot Reboot the machine\n"
6151 " -f --force Force immediate halt/power-off/reboot\n"
6152 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
6153 " -d --no-wtmp Don't write wtmp record\n"
6154 " --no-wall Don't send wall message before halt/power-off/reboot\n",
6155 program_invocation_short_name
,
6156 arg_action
== ACTION_REBOOT
? " [ARG]" : "",
6157 arg_action
== ACTION_REBOOT
? "Reboot" :
6158 arg_action
== ACTION_POWEROFF
? "Power off" :
6162 static void shutdown_help(void) {
6163 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
6164 "Shut down the system.\n\n"
6165 " --help Show this help\n"
6166 " -H --halt Halt the machine\n"
6167 " -P --poweroff Power-off the machine\n"
6168 " -r --reboot Reboot the machine\n"
6169 " -h Equivalent to --poweroff, overridden by --halt\n"
6170 " -k Don't halt/power-off/reboot, just send warnings\n"
6171 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6172 " -c Cancel a pending shutdown\n",
6173 program_invocation_short_name
);
6176 static void telinit_help(void) {
6177 printf("%s [OPTIONS...] {COMMAND}\n\n"
6178 "Send control commands to the init daemon.\n\n"
6179 " --help Show this help\n"
6180 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
6182 " 0 Power-off the machine\n"
6183 " 6 Reboot the machine\n"
6184 " 2, 3, 4, 5 Start runlevelX.target unit\n"
6185 " 1, s, S Enter rescue mode\n"
6186 " q, Q Reload init daemon configuration\n"
6187 " u, U Reexecute init daemon\n",
6188 program_invocation_short_name
);
6191 static void runlevel_help(void) {
6192 printf("%s [OPTIONS...]\n\n"
6193 "Prints the previous and current runlevel of the init system.\n\n"
6194 " --help Show this help\n",
6195 program_invocation_short_name
);
6198 static void help_types(void) {
6203 puts("Available unit types:");
6204 for (i
= 0; i
< _UNIT_TYPE_MAX
; i
++) {
6205 t
= unit_type_to_string(i
);
6211 static int systemctl_parse_argv(int argc
, char *argv
[]) {
6220 ARG_IGNORE_DEPENDENCIES
,
6232 ARG_NO_ASK_PASSWORD
,
6244 static const struct option options
[] = {
6245 { "help", no_argument
, NULL
, 'h' },
6246 { "version", no_argument
, NULL
, ARG_VERSION
},
6247 { "type", required_argument
, NULL
, 't' },
6248 { "property", required_argument
, NULL
, 'p' },
6249 { "all", no_argument
, NULL
, 'a' },
6250 { "reverse", no_argument
, NULL
, ARG_REVERSE
},
6251 { "after", no_argument
, NULL
, ARG_AFTER
},
6252 { "before", no_argument
, NULL
, ARG_BEFORE
},
6253 { "show-types", no_argument
, NULL
, ARG_SHOW_TYPES
},
6254 { "failed", no_argument
, NULL
, ARG_FAILED
}, /* compatibility only */
6255 { "full", no_argument
, NULL
, 'l' },
6256 { "job-mode", required_argument
, NULL
, ARG_JOB_MODE
},
6257 { "fail", no_argument
, NULL
, ARG_FAIL
}, /* compatibility only */
6258 { "irreversible", no_argument
, NULL
, ARG_IRREVERSIBLE
}, /* compatibility only */
6259 { "ignore-dependencies", no_argument
, NULL
, ARG_IGNORE_DEPENDENCIES
}, /* compatibility only */
6260 { "ignore-inhibitors", no_argument
, NULL
, 'i' },
6261 { "user", no_argument
, NULL
, ARG_USER
},
6262 { "system", no_argument
, NULL
, ARG_SYSTEM
},
6263 { "global", no_argument
, NULL
, ARG_GLOBAL
},
6264 { "no-block", no_argument
, NULL
, ARG_NO_BLOCK
},
6265 { "no-legend", no_argument
, NULL
, ARG_NO_LEGEND
},
6266 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
6267 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6268 { "quiet", no_argument
, NULL
, 'q' },
6269 { "root", required_argument
, NULL
, ARG_ROOT
},
6270 { "force", no_argument
, NULL
, ARG_FORCE
},
6271 { "no-reload", no_argument
, NULL
, ARG_NO_RELOAD
},
6272 { "kill-who", required_argument
, NULL
, ARG_KILL_WHO
},
6273 { "signal", required_argument
, NULL
, 's' },
6274 { "no-ask-password", no_argument
, NULL
, ARG_NO_ASK_PASSWORD
},
6275 { "host", required_argument
, NULL
, 'H' },
6276 { "machine", required_argument
, NULL
, 'M' },
6277 { "runtime", no_argument
, NULL
, ARG_RUNTIME
},
6278 { "lines", required_argument
, NULL
, 'n' },
6279 { "output", required_argument
, NULL
, 'o' },
6280 { "plain", no_argument
, NULL
, ARG_PLAIN
},
6281 { "state", required_argument
, NULL
, ARG_STATE
},
6282 { "recursive", no_argument
, NULL
, 'r' },
6283 { "preset-mode", required_argument
, NULL
, ARG_PRESET_MODE
},
6284 { "firmware-setup", no_argument
, NULL
, ARG_FIRMWARE_SETUP
},
6285 { "now", no_argument
, NULL
, ARG_NOW
},
6294 while ((c
= getopt_long(argc
, argv
, "ht:p:alqfs:H:M:n:o:ir", options
, NULL
)) >= 0)
6303 puts(PACKAGE_STRING
);
6304 puts(SYSTEMD_FEATURES
);
6308 const char *word
, *state
;
6311 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
6312 _cleanup_free_
char *type
;
6314 type
= strndup(word
, size
);
6318 if (streq(type
, "help")) {
6323 if (unit_type_from_string(type
) >= 0) {
6324 if (strv_push(&arg_types
, type
))
6330 /* It's much nicer to use --state= for
6331 * load states, but let's support this
6332 * in --types= too for compatibility
6333 * with old versions */
6334 if (unit_load_state_from_string(optarg
) >= 0) {
6335 if (strv_push(&arg_states
, type
) < 0)
6341 log_error("Unknown unit type or load state '%s'.", type
);
6342 log_info("Use -t help to see a list of allowed values.");
6350 /* Make sure that if the empty property list
6351 was specified, we won't show any properties. */
6352 if (isempty(optarg
) && !arg_properties
) {
6353 arg_properties
= new0(char*, 1);
6354 if (!arg_properties
)
6357 const char *word
, *state
;
6360 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
6363 prop
= strndup(word
, size
);
6367 if (strv_consume(&arg_properties
, prop
) < 0)
6372 /* If the user asked for a particular
6373 * property, show it to him, even if it is
6385 arg_dependency
= DEPENDENCY_REVERSE
;
6389 arg_dependency
= DEPENDENCY_AFTER
;
6393 arg_dependency
= DEPENDENCY_BEFORE
;
6396 case ARG_SHOW_TYPES
:
6397 arg_show_types
= true;
6401 arg_job_mode
= optarg
;
6405 arg_job_mode
= "fail";
6408 case ARG_IRREVERSIBLE
:
6409 arg_job_mode
= "replace-irreversibly";
6412 case ARG_IGNORE_DEPENDENCIES
:
6413 arg_job_mode
= "ignore-dependencies";
6417 arg_scope
= UNIT_FILE_USER
;
6421 arg_scope
= UNIT_FILE_SYSTEM
;
6425 arg_scope
= UNIT_FILE_GLOBAL
;
6429 arg_no_block
= true;
6433 arg_no_legend
= true;
6437 arg_no_pager
= true;
6453 if (strv_extend(&arg_states
, "failed") < 0)
6471 arg_no_reload
= true;
6475 arg_kill_who
= optarg
;
6479 if ((arg_signal
= signal_from_string_try_harder(optarg
)) < 0) {
6480 log_error("Failed to parse signal string %s.", optarg
);
6485 case ARG_NO_ASK_PASSWORD
:
6486 arg_ask_password
= false;
6490 arg_transport
= BUS_TRANSPORT_REMOTE
;
6495 arg_transport
= BUS_TRANSPORT_MACHINE
;
6504 if (safe_atou(optarg
, &arg_lines
) < 0) {
6505 log_error("Failed to parse lines '%s'", optarg
);
6511 arg_output
= output_mode_from_string(optarg
);
6512 if (arg_output
< 0) {
6513 log_error("Unknown output '%s'.", optarg
);
6519 arg_ignore_inhibitors
= true;
6526 case ARG_FIRMWARE_SETUP
:
6527 arg_firmware_setup
= true;
6531 const char *word
, *state
;
6534 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
6537 s
= strndup(word
, size
);
6541 if (strv_consume(&arg_states
, s
) < 0)
6548 if (geteuid() != 0) {
6549 log_error("--recursive requires root privileges.");
6553 arg_recursive
= true;
6556 case ARG_PRESET_MODE
:
6558 arg_preset_mode
= unit_file_preset_mode_from_string(optarg
);
6559 if (arg_preset_mode
< 0) {
6560 log_error("Failed to parse preset mode: %s.", optarg
);
6574 assert_not_reached("Unhandled option");
6577 if (arg_transport
!= BUS_TRANSPORT_LOCAL
&& arg_scope
!= UNIT_FILE_SYSTEM
) {
6578 log_error("Cannot access user instance remotely.");
6585 static int halt_parse_argv(int argc
, char *argv
[]) {
6594 static const struct option options
[] = {
6595 { "help", no_argument
, NULL
, ARG_HELP
},
6596 { "halt", no_argument
, NULL
, ARG_HALT
},
6597 { "poweroff", no_argument
, NULL
, 'p' },
6598 { "reboot", no_argument
, NULL
, ARG_REBOOT
},
6599 { "force", no_argument
, NULL
, 'f' },
6600 { "wtmp-only", no_argument
, NULL
, 'w' },
6601 { "no-wtmp", no_argument
, NULL
, 'd' },
6602 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6611 if (utmp_get_runlevel(&runlevel
, NULL
) >= 0)
6612 if (runlevel
== '0' || runlevel
== '6')
6615 while ((c
= getopt_long(argc
, argv
, "pfwdnih", options
, NULL
)) >= 0)
6623 arg_action
= ACTION_HALT
;
6627 if (arg_action
!= ACTION_REBOOT
)
6628 arg_action
= ACTION_POWEROFF
;
6632 arg_action
= ACTION_REBOOT
;
6654 /* Compatibility nops */
6661 assert_not_reached("Unhandled option");
6664 if (arg_action
== ACTION_REBOOT
&& (argc
== optind
|| argc
== optind
+ 1)) {
6665 r
= update_reboot_param_file(argc
== optind
+ 1 ? argv
[optind
] : NULL
);
6668 } else if (optind
< argc
) {
6669 log_error("Too many arguments.");
6676 static int parse_time_spec(const char *t
, usec_t
*_u
) {
6680 if (streq(t
, "now"))
6682 else if (!strchr(t
, ':')) {
6685 if (safe_atou64(t
, &u
) < 0)
6688 *_u
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
* u
;
6697 hour
= strtol(t
, &e
, 10);
6698 if (errno
> 0 || *e
!= ':' || hour
< 0 || hour
> 23)
6701 minute
= strtol(e
+1, &e
, 10);
6702 if (errno
> 0 || *e
!= 0 || minute
< 0 || minute
> 59)
6705 n
= now(CLOCK_REALTIME
);
6706 s
= (time_t) (n
/ USEC_PER_SEC
);
6708 assert_se(localtime_r(&s
, &tm
));
6710 tm
.tm_hour
= (int) hour
;
6711 tm
.tm_min
= (int) minute
;
6714 assert_se(s
= mktime(&tm
));
6716 *_u
= (usec_t
) s
* USEC_PER_SEC
;
6719 *_u
+= USEC_PER_DAY
;
6725 static int shutdown_parse_argv(int argc
, char *argv
[]) {
6732 static const struct option options
[] = {
6733 { "help", no_argument
, NULL
, ARG_HELP
},
6734 { "halt", no_argument
, NULL
, 'H' },
6735 { "poweroff", no_argument
, NULL
, 'P' },
6736 { "reboot", no_argument
, NULL
, 'r' },
6737 { "kexec", no_argument
, NULL
, 'K' }, /* not documented extension */
6738 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6747 while ((c
= getopt_long(argc
, argv
, "HPrhkKt:afFc", options
, NULL
)) >= 0)
6755 arg_action
= ACTION_HALT
;
6759 arg_action
= ACTION_POWEROFF
;
6764 arg_action
= ACTION_KEXEC
;
6766 arg_action
= ACTION_REBOOT
;
6770 arg_action
= ACTION_KEXEC
;
6774 if (arg_action
!= ACTION_HALT
)
6775 arg_action
= ACTION_POWEROFF
;
6790 /* Compatibility nops */
6794 arg_action
= ACTION_CANCEL_SHUTDOWN
;
6801 assert_not_reached("Unhandled option");
6804 if (argc
> optind
&& arg_action
!= ACTION_CANCEL_SHUTDOWN
) {
6805 r
= parse_time_spec(argv
[optind
], &arg_when
);
6807 log_error("Failed to parse time specification: %s", argv
[optind
]);
6811 arg_when
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
;
6813 if (argc
> optind
&& arg_action
== ACTION_CANCEL_SHUTDOWN
)
6814 /* No time argument for shutdown cancel */
6815 arg_wall
= argv
+ optind
;
6816 else if (argc
> optind
+ 1)
6817 /* We skip the time argument */
6818 arg_wall
= argv
+ optind
+ 1;
6825 static int telinit_parse_argv(int argc
, char *argv
[]) {
6832 static const struct option options
[] = {
6833 { "help", no_argument
, NULL
, ARG_HELP
},
6834 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6838 static const struct {
6842 { '0', ACTION_POWEROFF
},
6843 { '6', ACTION_REBOOT
},
6844 { '1', ACTION_RESCUE
},
6845 { '2', ACTION_RUNLEVEL2
},
6846 { '3', ACTION_RUNLEVEL3
},
6847 { '4', ACTION_RUNLEVEL4
},
6848 { '5', ACTION_RUNLEVEL5
},
6849 { 's', ACTION_RESCUE
},
6850 { 'S', ACTION_RESCUE
},
6851 { 'q', ACTION_RELOAD
},
6852 { 'Q', ACTION_RELOAD
},
6853 { 'u', ACTION_REEXEC
},
6854 { 'U', ACTION_REEXEC
}
6863 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
6878 assert_not_reached("Unhandled option");
6881 if (optind
>= argc
) {
6882 log_error("%s: required argument missing.",
6883 program_invocation_short_name
);
6887 if (optind
+ 1 < argc
) {
6888 log_error("Too many arguments.");
6892 if (strlen(argv
[optind
]) != 1) {
6893 log_error("Expected single character argument.");
6897 for (i
= 0; i
< ELEMENTSOF(table
); i
++)
6898 if (table
[i
].from
== argv
[optind
][0])
6901 if (i
>= ELEMENTSOF(table
)) {
6902 log_error("Unknown command '%s'.", argv
[optind
]);
6906 arg_action
= table
[i
].to
;
6913 static int runlevel_parse_argv(int argc
, char *argv
[]) {
6919 static const struct option options
[] = {
6920 { "help", no_argument
, NULL
, ARG_HELP
},
6929 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
6940 assert_not_reached("Unhandled option");
6943 if (optind
< argc
) {
6944 log_error("Too many arguments.");
6951 static int parse_argv(int argc
, char *argv
[]) {
6955 if (program_invocation_short_name
) {
6957 if (strstr(program_invocation_short_name
, "halt")) {
6958 arg_action
= ACTION_HALT
;
6959 return halt_parse_argv(argc
, argv
);
6960 } else if (strstr(program_invocation_short_name
, "poweroff")) {
6961 arg_action
= ACTION_POWEROFF
;
6962 return halt_parse_argv(argc
, argv
);
6963 } else if (strstr(program_invocation_short_name
, "reboot")) {
6965 arg_action
= ACTION_KEXEC
;
6967 arg_action
= ACTION_REBOOT
;
6968 return halt_parse_argv(argc
, argv
);
6969 } else if (strstr(program_invocation_short_name
, "shutdown")) {
6970 arg_action
= ACTION_POWEROFF
;
6971 return shutdown_parse_argv(argc
, argv
);
6972 } else if (strstr(program_invocation_short_name
, "init")) {
6974 if (sd_booted() > 0) {
6975 arg_action
= _ACTION_INVALID
;
6976 return telinit_parse_argv(argc
, argv
);
6978 /* Hmm, so some other init system is
6979 * running, we need to forward this
6980 * request to it. For now we simply
6981 * guess that it is Upstart. */
6983 execv(TELINIT
, argv
);
6985 log_error("Couldn't find an alternative telinit implementation to spawn.");
6989 } else if (strstr(program_invocation_short_name
, "runlevel")) {
6990 arg_action
= ACTION_RUNLEVEL
;
6991 return runlevel_parse_argv(argc
, argv
);
6995 arg_action
= ACTION_SYSTEMCTL
;
6996 return systemctl_parse_argv(argc
, argv
);
6999 _pure_
static int action_to_runlevel(void) {
7001 static const char table
[_ACTION_MAX
] = {
7002 [ACTION_HALT
] = '0',
7003 [ACTION_POWEROFF
] = '0',
7004 [ACTION_REBOOT
] = '6',
7005 [ACTION_RUNLEVEL2
] = '2',
7006 [ACTION_RUNLEVEL3
] = '3',
7007 [ACTION_RUNLEVEL4
] = '4',
7008 [ACTION_RUNLEVEL5
] = '5',
7009 [ACTION_RESCUE
] = '1'
7012 assert(arg_action
< _ACTION_MAX
);
7014 return table
[arg_action
];
7017 static int talk_initctl(void) {
7019 struct init_request request
= {
7020 .magic
= INIT_MAGIC
,
7022 .cmd
= INIT_CMD_RUNLVL
7025 _cleanup_close_
int fd
= -1;
7029 rl
= action_to_runlevel();
7033 request
.runlevel
= rl
;
7035 fd
= open(INIT_FIFO
, O_WRONLY
|O_NDELAY
|O_CLOEXEC
|O_NOCTTY
);
7037 if (errno
== ENOENT
)
7040 log_error_errno(errno
, "Failed to open "INIT_FIFO
": %m");
7044 r
= loop_write(fd
, &request
, sizeof(request
), false);
7046 return log_error_errno(r
, "Failed to write to "INIT_FIFO
": %m");
7051 static int systemctl_main(sd_bus
*bus
, int argc
, char *argv
[], int bus_error
) {
7053 static const struct {
7061 int (* const dispatch
)(sd_bus
*bus
, char **args
);
7067 { "list-units", MORE
, 0, list_units
},
7068 { "list-unit-files", MORE
, 1, list_unit_files
, NOBUS
},
7069 { "list-sockets", MORE
, 1, list_sockets
},
7070 { "list-timers", MORE
, 1, list_timers
},
7071 { "list-jobs", MORE
, 1, list_jobs
},
7072 { "list-machines", MORE
, 1, list_machines
},
7073 { "clear-jobs", EQUAL
, 1, daemon_reload
},
7074 { "cancel", MORE
, 2, cancel_job
},
7075 { "start", MORE
, 2, start_unit
},
7076 { "stop", MORE
, 2, start_unit
},
7077 { "condstop", MORE
, 2, start_unit
}, /* For compatibility with ALTLinux */
7078 { "reload", MORE
, 2, start_unit
},
7079 { "restart", MORE
, 2, start_unit
},
7080 { "try-restart", MORE
, 2, start_unit
},
7081 { "reload-or-restart", MORE
, 2, start_unit
},
7082 { "reload-or-try-restart", MORE
, 2, start_unit
},
7083 { "force-reload", MORE
, 2, start_unit
}, /* For compatibility with SysV */
7084 { "condreload", MORE
, 2, start_unit
}, /* For compatibility with ALTLinux */
7085 { "condrestart", MORE
, 2, start_unit
}, /* For compatibility with RH */
7086 { "isolate", EQUAL
, 2, start_unit
},
7087 { "kill", MORE
, 2, kill_unit
},
7088 { "is-active", MORE
, 2, check_unit_active
},
7089 { "check", MORE
, 2, check_unit_active
},
7090 { "is-failed", MORE
, 2, check_unit_failed
},
7091 { "show", MORE
, 1, show
},
7092 { "cat", MORE
, 2, cat
, NOBUS
},
7093 { "status", MORE
, 1, show
},
7094 { "help", MORE
, 2, show
},
7095 { "snapshot", LESS
, 2, snapshot
},
7096 { "delete", MORE
, 2, delete_snapshot
},
7097 { "daemon-reload", EQUAL
, 1, daemon_reload
},
7098 { "daemon-reexec", EQUAL
, 1, daemon_reload
},
7099 { "show-environment", EQUAL
, 1, show_environment
},
7100 { "set-environment", MORE
, 2, set_environment
},
7101 { "unset-environment", MORE
, 2, set_environment
},
7102 { "import-environment", MORE
, 1, import_environment
},
7103 { "halt", EQUAL
, 1, start_special
, FORCE
},
7104 { "poweroff", EQUAL
, 1, start_special
, FORCE
},
7105 { "reboot", MORE
, 1, start_special
, FORCE
},
7106 { "kexec", EQUAL
, 1, start_special
},
7107 { "suspend", EQUAL
, 1, start_special
},
7108 { "hibernate", EQUAL
, 1, start_special
},
7109 { "hybrid-sleep", EQUAL
, 1, start_special
},
7110 { "default", EQUAL
, 1, start_special
},
7111 { "rescue", EQUAL
, 1, start_special
},
7112 { "emergency", EQUAL
, 1, start_special
},
7113 { "exit", EQUAL
, 1, start_special
},
7114 { "reset-failed", MORE
, 1, reset_failed
},
7115 { "enable", MORE
, 2, enable_unit
, NOBUS
},
7116 { "disable", MORE
, 2, enable_unit
, NOBUS
},
7117 { "is-enabled", MORE
, 2, unit_is_enabled
, NOBUS
},
7118 { "reenable", MORE
, 2, enable_unit
, NOBUS
},
7119 { "preset", MORE
, 2, enable_unit
, NOBUS
},
7120 { "preset-all", EQUAL
, 1, preset_all
, NOBUS
},
7121 { "mask", MORE
, 2, enable_unit
, NOBUS
},
7122 { "unmask", MORE
, 2, enable_unit
, NOBUS
},
7123 { "link", MORE
, 2, enable_unit
, NOBUS
},
7124 { "switch-root", MORE
, 2, switch_root
},
7125 { "list-dependencies", LESS
, 2, list_dependencies
},
7126 { "set-default", EQUAL
, 2, set_default
, NOBUS
},
7127 { "get-default", EQUAL
, 1, get_default
, NOBUS
},
7128 { "set-property", MORE
, 3, set_property
},
7129 { "is-system-running", EQUAL
, 1, is_system_running
},
7130 { "add-wants", MORE
, 3, add_dependency
, NOBUS
},
7131 { "add-requires", MORE
, 3, add_dependency
, NOBUS
},
7132 { "edit", MORE
, 2, edit
, NOBUS
},
7141 left
= argc
- optind
;
7143 /* Special rule: no arguments (left == 0) means "list-units" */
7145 if (streq(argv
[optind
], "help") && !argv
[optind
+1]) {
7146 log_error("This command expects one or more "
7147 "unit names. Did you mean --help?");
7151 for (; verb
->verb
; verb
++)
7152 if (streq(argv
[optind
], verb
->verb
))
7155 log_error("Unknown operation '%s'.", argv
[optind
]);
7160 switch (verb
->argc_cmp
) {
7163 if (left
!= verb
->argc
) {
7164 log_error("Invalid number of arguments.");
7171 if (left
< verb
->argc
) {
7172 log_error("Too few arguments.");
7179 if (left
> verb
->argc
) {
7180 log_error("Too many arguments.");
7187 assert_not_reached("Unknown comparison operator.");
7190 /* Require a bus connection for all operations but
7192 if (verb
->bus
== NOBUS
) {
7193 if (!bus
&& !avoid_bus()) {
7194 log_error_errno(bus_error
, "Failed to get D-Bus connection: %m");
7199 if (running_in_chroot() > 0) {
7200 log_info("Running in chroot, ignoring request.");
7204 if ((verb
->bus
!= FORCE
|| arg_force
<= 0) && !bus
) {
7205 log_error_errno(bus_error
, "Failed to get D-Bus connection: %m");
7210 return verb
->dispatch(bus
, argv
+ optind
);
7213 static int reload_with_fallback(sd_bus
*bus
) {
7216 /* First, try systemd via D-Bus. */
7217 if (daemon_reload(bus
, NULL
) >= 0)
7221 /* Nothing else worked, so let's try signals */
7222 assert(arg_action
== ACTION_RELOAD
|| arg_action
== ACTION_REEXEC
);
7224 if (kill(1, arg_action
== ACTION_RELOAD
? SIGHUP
: SIGTERM
) < 0)
7225 return log_error_errno(errno
, "kill() failed: %m");
7230 static int start_with_fallback(sd_bus
*bus
) {
7233 /* First, try systemd via D-Bus. */
7234 if (start_unit(bus
, NULL
) >= 0)
7238 /* Nothing else worked, so let's try
7240 if (talk_initctl() > 0)
7243 log_error("Failed to talk to init daemon.");
7247 warn_wall(arg_action
);
7251 static int halt_now(enum action a
) {
7253 /* The kernel will automaticall flush ATA disks and suchlike
7254 * on reboot(), but the file systems need to be synce'd
7255 * explicitly in advance. */
7258 /* Make sure C-A-D is handled by the kernel from this point
7260 reboot(RB_ENABLE_CAD
);
7265 log_info("Halting.");
7266 reboot(RB_HALT_SYSTEM
);
7269 case ACTION_POWEROFF
:
7270 log_info("Powering off.");
7271 reboot(RB_POWER_OFF
);
7274 case ACTION_REBOOT
: {
7275 _cleanup_free_
char *param
= NULL
;
7277 if (read_one_line_file(REBOOT_PARAM_FILE
, ¶m
) >= 0) {
7278 log_info("Rebooting with argument '%s'.", param
);
7279 syscall(SYS_reboot
, LINUX_REBOOT_MAGIC1
, LINUX_REBOOT_MAGIC2
,
7280 LINUX_REBOOT_CMD_RESTART2
, param
);
7283 log_info("Rebooting.");
7284 reboot(RB_AUTOBOOT
);
7289 assert_not_reached("Unknown action.");
7293 static int halt_main(sd_bus
*bus
) {
7296 r
= check_inhibitors(bus
, arg_action
);
7300 if (geteuid() != 0) {
7301 /* Try logind if we are a normal user and no special
7302 * mode applies. Maybe PolicyKit allows us to shutdown
7305 if (arg_when
<= 0 &&
7308 (arg_action
== ACTION_POWEROFF
||
7309 arg_action
== ACTION_REBOOT
)) {
7310 r
= reboot_with_logind(bus
, arg_action
);
7315 log_error("Must be root.");
7320 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
7321 _cleanup_bus_close_unref_ sd_bus
*b
= NULL
;
7322 _cleanup_free_
char *m
= NULL
;
7325 log_error("Unable to perform operation without bus connection.");
7329 r
= sd_bus_open_system(&b
);
7331 return log_error_errno(r
, "Unable to open system bus: %m");
7333 m
= strv_join(arg_wall
, " ");
7337 r
= sd_bus_set_property(
7339 "org.freedesktop.login1",
7340 "/org/freedesktop/login1",
7341 "org.freedesktop.login1.Manager",
7346 log_warning_errno(r
, "Failed to set WallMessage property in logind: %s",
7347 bus_error_message(&error
, r
));
7348 sd_bus_error_free(&error
);
7351 r
= sd_bus_set_property(
7353 "org.freedesktop.login1",
7354 "/org/freedesktop/login1",
7355 "org.freedesktop.login1.Manager",
7356 "EnableWallMessages",
7360 log_warning_errno(r
, "Failed to set EnableWallMessages property in logind: %s",
7361 bus_error_message(&error
, r
));
7362 sd_bus_error_free(&error
);
7365 r
= sd_bus_call_method(
7367 "org.freedesktop.login1",
7368 "/org/freedesktop/login1",
7369 "org.freedesktop.login1.Manager",
7374 arg_action
== ACTION_HALT
? "halt" :
7375 arg_action
== ACTION_POWEROFF
? "poweroff" :
7376 arg_action
== ACTION_KEXEC
? "kexec" :
7380 log_warning_errno(r
, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s",
7381 bus_error_message(&error
, r
));
7383 char date
[FORMAT_TIMESTAMP_MAX
];
7385 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
7386 format_timestamp(date
, sizeof(date
), arg_when
));
7391 if (!arg_dry
&& !arg_force
)
7392 return start_with_fallback(bus
);
7395 if (sd_booted() > 0)
7396 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
7398 r
= utmp_put_shutdown();
7400 log_warning_errno(r
, "Failed to write utmp record: %m");
7407 r
= halt_now(arg_action
);
7408 log_error_errno(r
, "Failed to reboot: %m");
7413 static int runlevel_main(void) {
7414 int r
, runlevel
, previous
;
7416 r
= utmp_get_runlevel(&runlevel
, &previous
);
7423 previous
<= 0 ? 'N' : previous
,
7424 runlevel
<= 0 ? 'N' : runlevel
);
7429 int main(int argc
, char*argv
[]) {
7430 _cleanup_bus_close_unref_ sd_bus
*bus
= NULL
;
7433 setlocale(LC_ALL
, "");
7434 log_parse_environment();
7437 /* Explicitly not on_tty() to avoid setting cached value.
7438 * This becomes relevant for piping output which might be
7440 original_stdout_is_tty
= isatty(STDOUT_FILENO
);
7442 r
= parse_argv(argc
, argv
);
7446 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
7447 * let's shortcut this */
7448 if (arg_action
== ACTION_RUNLEVEL
) {
7449 r
= runlevel_main();
7453 if (running_in_chroot() > 0 && arg_action
!= ACTION_SYSTEMCTL
) {
7454 log_info("Running in chroot, ignoring request.");
7460 r
= bus_open_transport_systemd(arg_transport
, arg_host
, arg_scope
!= UNIT_FILE_SYSTEM
, &bus
);
7463 sd_bus_set_allow_interactive_authorization(bus
, arg_ask_password
);
7465 /* systemctl_main() will print an error message for the bus
7466 * connection, but only if it needs to */
7468 switch (arg_action
) {
7470 case ACTION_SYSTEMCTL
:
7471 r
= systemctl_main(bus
, argc
, argv
, r
);
7475 case ACTION_POWEROFF
:
7481 case ACTION_RUNLEVEL2
:
7482 case ACTION_RUNLEVEL3
:
7483 case ACTION_RUNLEVEL4
:
7484 case ACTION_RUNLEVEL5
:
7486 case ACTION_EMERGENCY
:
7487 case ACTION_DEFAULT
:
7488 r
= start_with_fallback(bus
);
7493 r
= reload_with_fallback(bus
);
7496 case ACTION_CANCEL_SHUTDOWN
: {
7497 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
7498 _cleanup_bus_close_unref_ sd_bus
*b
= NULL
;
7499 _cleanup_free_
char *m
= NULL
;
7502 log_error("Unable to perform operation without bus connection.");
7506 r
= sd_bus_open_system(&b
);
7508 return log_error_errno(r
, "Unable to open system bus: %m");
7511 m
= strv_join(arg_wall
, " ");
7518 r
= sd_bus_set_property(
7520 "org.freedesktop.login1",
7521 "/org/freedesktop/login1",
7522 "org.freedesktop.login1.Manager",
7527 log_warning_errno(r
, "Failed to set WallMessage property in logind: %s",
7528 bus_error_message(&error
, r
));
7529 sd_bus_error_free(&error
);
7532 r
= sd_bus_set_property(
7534 "org.freedesktop.login1",
7535 "/org/freedesktop/login1",
7536 "org.freedesktop.login1.Manager",
7537 "EnableWallMessages",
7541 log_warning_errno(r
, "Failed to set EnableWallMessages property in logind: %s",
7542 bus_error_message(&error
, r
));
7543 sd_bus_error_free(&error
);
7546 r
= sd_bus_call_method(
7548 "org.freedesktop.login1",
7549 "/org/freedesktop/login1",
7550 "org.freedesktop.login1.Manager",
7551 "CancelScheduledShutdown",
7555 log_warning_errno(r
, "Failed to talk to logind, shutdown hasn't been cancelled: %s",
7556 bus_error_message(&error
, r
));
7560 case ACTION_RUNLEVEL
:
7561 case _ACTION_INVALID
:
7563 assert_not_reached("Unknown action");
7568 ask_password_agent_close();
7569 polkit_agent_close();
7571 strv_free(arg_types
);
7572 strv_free(arg_states
);
7573 strv_free(arg_properties
);
7575 return r
< 0 ? EXIT_FAILURE
: r
;