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 machine_info_clear(struct machine_info
*info
) {
1685 free(info
->control_group
);
1690 static void free_machines_list(struct machine_info
*machine_infos
, int n
) {
1696 for (i
= 0; i
< n
; i
++)
1697 machine_info_clear(&machine_infos
[i
]);
1699 free(machine_infos
);
1702 static int compare_machine_info(const void *a
, const void *b
) {
1703 const struct machine_info
*u
= a
, *v
= b
;
1705 if (u
->is_host
!= v
->is_host
)
1706 return u
->is_host
> v
->is_host
? -1 : 1;
1708 return strcasecmp(u
->name
, v
->name
);
1711 static int get_machine_properties(sd_bus
*bus
, struct machine_info
*mi
) {
1712 _cleanup_bus_close_unref_ sd_bus
*container
= NULL
;
1718 r
= sd_bus_open_system_machine(&container
, mi
->name
);
1725 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, mi
);
1732 static bool output_show_machine(const char *name
, char **patterns
) {
1733 return strv_fnmatch_or_empty(patterns
, name
, FNM_NOESCAPE
);
1736 static int get_machine_list(
1738 struct machine_info
**_machine_infos
,
1741 struct machine_info
*machine_infos
= NULL
;
1742 _cleanup_strv_free_
char **m
= NULL
;
1743 _cleanup_free_
char *hn
= NULL
;
1748 hn
= gethostname_malloc();
1752 if (output_show_machine(hn
, patterns
)) {
1753 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1))
1756 machine_infos
[c
].is_host
= true;
1757 machine_infos
[c
].name
= hn
;
1760 get_machine_properties(bus
, &machine_infos
[c
]);
1764 sd_get_machine_names(&m
);
1765 STRV_FOREACH(i
, m
) {
1766 _cleanup_free_
char *class = NULL
;
1768 if (!output_show_machine(*i
, patterns
))
1771 sd_machine_get_class(*i
, &class);
1772 if (!streq_ptr(class, "container"))
1775 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1)) {
1776 free_machines_list(machine_infos
, c
);
1780 machine_infos
[c
].is_host
= false;
1781 machine_infos
[c
].name
= strdup(*i
);
1782 if (!machine_infos
[c
].name
) {
1783 free_machines_list(machine_infos
, c
);
1787 get_machine_properties(NULL
, &machine_infos
[c
]);
1791 *_machine_infos
= machine_infos
;
1795 static void output_machines_list(struct machine_info
*machine_infos
, unsigned n
) {
1796 struct machine_info
*m
;
1799 namelen
= sizeof("NAME") - 1,
1800 statelen
= sizeof("STATE") - 1,
1801 failedlen
= sizeof("FAILED") - 1,
1802 jobslen
= sizeof("JOBS") - 1;
1804 assert(machine_infos
|| n
== 0);
1806 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
1807 namelen
= MAX(namelen
, strlen(m
->name
) + (m
->is_host
? sizeof(" (host)") - 1 : 0));
1808 statelen
= MAX(statelen
, m
->state
? strlen(m
->state
) : 0);
1809 failedlen
= MAX(failedlen
, DECIMAL_STR_WIDTH(m
->n_failed_units
));
1810 jobslen
= MAX(jobslen
, DECIMAL_STR_WIDTH(m
->n_jobs
));
1812 if (!arg_plain
&& !streq_ptr(m
->state
, "running"))
1816 if (!arg_no_legend
) {
1820 printf("%-*s %-*s %-*s %-*s\n",
1823 failedlen
, "FAILED",
1827 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
1828 const char *on_state
= "", *off_state
= "";
1829 const char *on_failed
= "", *off_failed
= "";
1830 bool circle
= false;
1832 if (streq_ptr(m
->state
, "degraded")) {
1833 on_state
= ansi_highlight_red();
1834 off_state
= ansi_highlight_off();
1836 } else if (!streq_ptr(m
->state
, "running")) {
1837 on_state
= ansi_highlight_yellow();
1838 off_state
= ansi_highlight_off();
1842 if (m
->n_failed_units
> 0) {
1843 on_failed
= ansi_highlight_red();
1844 off_failed
= ansi_highlight_off();
1846 on_failed
= off_failed
= "";
1849 printf("%s%s%s ", on_state
, circle
? draw_special_char(DRAW_BLACK_CIRCLE
) : " ", off_state
);
1852 printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
1853 (int) (namelen
- (sizeof(" (host)")-1)), 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
);
1858 printf("%-*s %s%-*s%s %s%*u%s %*u\n",
1859 namelen
, strna(m
->name
),
1860 on_state
, statelen
, strna(m
->state
), off_state
,
1861 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
1862 jobslen
, m
->n_jobs
);
1866 printf("\n%u machines listed.\n", n
);
1869 static int list_machines(sd_bus
*bus
, char **args
) {
1870 struct machine_info
*machine_infos
= NULL
;
1875 if (geteuid() != 0) {
1876 log_error("Must be root.");
1880 pager_open_if_enabled();
1882 r
= get_machine_list(bus
, &machine_infos
, strv_skip_first(args
));
1886 qsort_safe(machine_infos
, r
, sizeof(struct machine_info
), compare_machine_info
);
1887 output_machines_list(machine_infos
, r
);
1888 free_machines_list(machine_infos
, r
);
1893 static int get_default(sd_bus
*bus
, char **args
) {
1894 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1895 _cleanup_free_
char *_path
= NULL
;
1899 if (!bus
|| avoid_bus()) {
1900 r
= unit_file_get_default(arg_scope
, arg_root
, &_path
);
1902 return log_error_errno(r
, "Failed to get default target: %m");
1906 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1908 r
= sd_bus_call_method(
1910 "org.freedesktop.systemd1",
1911 "/org/freedesktop/systemd1",
1912 "org.freedesktop.systemd1.Manager",
1918 log_error("Failed to get default target: %s", bus_error_message(&error
, -r
));
1922 r
= sd_bus_message_read(reply
, "s", &path
);
1924 return bus_log_parse_error(r
);
1928 printf("%s\n", path
);
1933 static void dump_unit_file_changes(const UnitFileChange
*changes
, unsigned n_changes
) {
1936 assert(changes
|| n_changes
== 0);
1938 for (i
= 0; i
< n_changes
; i
++) {
1939 if (changes
[i
].type
== UNIT_FILE_SYMLINK
)
1940 log_info("Created symlink from %s to %s.", changes
[i
].path
, changes
[i
].source
);
1942 log_info("Removed symlink %s.", changes
[i
].path
);
1946 static int set_default(sd_bus
*bus
, char **args
) {
1947 _cleanup_free_
char *unit
= NULL
;
1948 UnitFileChange
*changes
= NULL
;
1949 unsigned n_changes
= 0;
1952 r
= unit_name_mangle_with_suffix(args
[1], UNIT_NAME_NOGLOB
, ".target", &unit
);
1954 return log_error_errno(r
, "Failed to mangle unit name: %m");
1956 if (!bus
|| avoid_bus()) {
1957 r
= unit_file_set_default(arg_scope
, arg_root
, unit
, true, &changes
, &n_changes
);
1959 return log_error_errno(r
, "Failed to set default target: %m");
1962 dump_unit_file_changes(changes
, n_changes
);
1966 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1967 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1969 polkit_agent_open_if_enabled();
1971 r
= sd_bus_call_method(
1973 "org.freedesktop.systemd1",
1974 "/org/freedesktop/systemd1",
1975 "org.freedesktop.systemd1.Manager",
1981 log_error("Failed to set default target: %s", bus_error_message(&error
, -r
));
1985 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, NULL
, NULL
);
1989 /* Try to reload if enabled */
1991 r
= daemon_reload(bus
, args
);
1996 unit_file_changes_free(changes
, n_changes
);
2003 const char *name
, *type
, *state
;
2006 static void output_jobs_list(const struct job_info
* jobs
, unsigned n
, bool skipped
) {
2007 unsigned id_len
, unit_len
, type_len
, state_len
;
2008 const struct job_info
*j
;
2009 const char *on
, *off
;
2010 bool shorten
= false;
2012 assert(n
== 0 || jobs
);
2015 if (!arg_no_legend
) {
2016 on
= ansi_highlight_green();
2017 off
= ansi_highlight_off();
2019 printf("%sNo jobs %s.%s\n", on
, skipped
? "listed" : "running", off
);
2024 pager_open_if_enabled();
2026 id_len
= strlen("JOB");
2027 unit_len
= strlen("UNIT");
2028 type_len
= strlen("TYPE");
2029 state_len
= strlen("STATE");
2031 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2032 uint32_t id
= j
->id
;
2033 assert(j
->name
&& j
->type
&& j
->state
);
2035 id_len
= MAX(id_len
, DECIMAL_STR_WIDTH(id
));
2036 unit_len
= MAX(unit_len
, strlen(j
->name
));
2037 type_len
= MAX(type_len
, strlen(j
->type
));
2038 state_len
= MAX(state_len
, strlen(j
->state
));
2041 if (!arg_full
&& id_len
+ 1 + unit_len
+ type_len
+ 1 + state_len
> columns()) {
2042 unit_len
= MAX(33u, columns() - id_len
- type_len
- state_len
- 3);
2047 printf("%*s %-*s %-*s %-*s\n",
2051 state_len
, "STATE");
2053 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2054 _cleanup_free_
char *e
= NULL
;
2056 if (streq(j
->state
, "running")) {
2057 on
= ansi_highlight();
2058 off
= ansi_highlight_off();
2062 e
= shorten
? ellipsize(j
->name
, unit_len
, 33) : NULL
;
2063 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2065 on
, unit_len
, e
? e
: j
->name
, off
,
2067 on
, state_len
, j
->state
, off
);
2070 if (!arg_no_legend
) {
2071 on
= ansi_highlight();
2072 off
= ansi_highlight_off();
2074 printf("\n%s%u jobs listed%s.\n", on
, n
, off
);
2078 static bool output_show_job(struct job_info
*job
, char **patterns
) {
2079 return strv_fnmatch_or_empty(patterns
, job
->name
, FNM_NOESCAPE
);
2082 static int list_jobs(sd_bus
*bus
, char **args
) {
2083 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2084 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2085 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2086 _cleanup_free_
struct job_info
*jobs
= NULL
;
2091 bool skipped
= false;
2093 r
= sd_bus_call_method(
2095 "org.freedesktop.systemd1",
2096 "/org/freedesktop/systemd1",
2097 "org.freedesktop.systemd1.Manager",
2103 log_error("Failed to list jobs: %s", bus_error_message(&error
, r
));
2107 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2109 return bus_log_parse_error(r
);
2111 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0) {
2112 struct job_info job
= { id
, name
, type
, state
};
2114 if (!output_show_job(&job
, strv_skip_first(args
))) {
2119 if (!GREEDY_REALLOC(jobs
, size
, c
+ 1))
2125 return bus_log_parse_error(r
);
2127 r
= sd_bus_message_exit_container(reply
);
2129 return bus_log_parse_error(r
);
2131 output_jobs_list(jobs
, c
, skipped
);
2135 static int cancel_job(sd_bus
*bus
, char **args
) {
2141 if (strv_length(args
) <= 1)
2142 return daemon_reload(bus
, args
);
2144 polkit_agent_open_if_enabled();
2146 STRV_FOREACH(name
, args
+1) {
2147 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2151 q
= safe_atou32(*name
, &id
);
2153 return log_error_errno(q
, "Failed to parse job id \"%s\": %m", *name
);
2155 q
= sd_bus_call_method(
2157 "org.freedesktop.systemd1",
2158 "/org/freedesktop/systemd1",
2159 "org.freedesktop.systemd1.Manager",
2165 log_error("Failed to cancel job %"PRIu32
": %s", id
, bus_error_message(&error
, q
));
2174 static int need_daemon_reload(sd_bus
*bus
, const char *unit
) {
2175 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2179 /* We ignore all errors here, since this is used to show a
2182 /* We don't use unit_dbus_path_from_name() directly since we
2183 * don't want to load the unit if it isn't loaded. */
2185 r
= sd_bus_call_method(
2187 "org.freedesktop.systemd1",
2188 "/org/freedesktop/systemd1",
2189 "org.freedesktop.systemd1.Manager",
2197 r
= sd_bus_message_read(reply
, "o", &path
);
2201 r
= sd_bus_get_property_trivial(
2203 "org.freedesktop.systemd1",
2205 "org.freedesktop.systemd1.Unit",
2215 static void warn_unit_file_changed(const char *name
) {
2216 log_warning("%sWarning:%s %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
2217 ansi_highlight_red(),
2218 ansi_highlight_off(),
2220 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user");
2223 static int unit_file_find_path(LookupPaths
*lp
, const char *unit_name
, char **unit_path
) {
2230 STRV_FOREACH(p
, lp
->unit_path
) {
2231 _cleanup_free_
char *path
;
2233 path
= path_join(arg_root
, *p
, unit_name
);
2237 if (access(path
, F_OK
) == 0) {
2247 static int unit_find_paths(
2249 const char *unit_name
,
2250 bool avoid_bus_cache
,
2252 char **fragment_path
,
2253 char ***dropin_paths
) {
2255 _cleanup_free_
char *path
= NULL
;
2256 _cleanup_strv_free_
char **dropins
= NULL
;
2260 * Finds where the unit is defined on disk. Returns 0 if the unit
2261 * is not found. Returns 1 if it is found, and sets
2262 * - the path to the unit in *path, if it exists on disk,
2263 * - and a strv of existing drop-ins in *dropins,
2264 * if the arg is not NULL and any dropins were found.
2268 assert(fragment_path
);
2271 if (!avoid_bus_cache
&& !unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
2272 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2273 _cleanup_bus_message_unref_ sd_bus_message
*unit_load_error
= NULL
;
2274 _cleanup_free_
char *unit
= NULL
;
2275 char *unit_load_error_name
, *unit_load_error_message
;
2277 unit
= unit_dbus_path_from_name(unit_name
);
2281 if (need_daemon_reload(bus
, unit_name
) > 0)
2282 warn_unit_file_changed(unit_name
);
2284 r
= sd_bus_get_property(
2286 "org.freedesktop.systemd1",
2288 "org.freedesktop.systemd1.Unit",
2294 return log_error_errno(r
, "Failed to get LoadError: %s", bus_error_message(&error
, r
));
2296 r
= sd_bus_message_read(
2299 &unit_load_error_name
,
2300 &unit_load_error_message
);
2302 return bus_log_parse_error(r
);
2304 if (!isempty(unit_load_error_name
)) {
2305 log_error("Unit %s is not loaded: %s", unit_name
, unit_load_error_message
);
2309 r
= sd_bus_get_property_string(
2311 "org.freedesktop.systemd1",
2313 "org.freedesktop.systemd1.Unit",
2318 return log_error_errno(r
, "Failed to get FragmentPath: %s", bus_error_message(&error
, r
));
2321 r
= sd_bus_get_property_strv(
2323 "org.freedesktop.systemd1",
2325 "org.freedesktop.systemd1.Unit",
2330 return log_error_errno(r
, "Failed to get DropInPaths: %s", bus_error_message(&error
, r
));
2333 _cleanup_set_free_ Set
*names
;
2335 names
= set_new(NULL
);
2339 r
= set_put(names
, unit_name
);
2341 return log_error_errno(r
, "Failed to add unit name: %m");
2343 r
= unit_file_find_path(lp
, unit_name
, &path
);
2348 _cleanup_free_
char *template = NULL
;
2350 r
= unit_name_template(unit_name
, &template);
2351 if (r
< 0 && r
!= -EINVAL
)
2352 return log_error_errno(r
, "Failed to determine template name: %m");
2354 r
= unit_file_find_path(lp
, template, &path
);
2361 r
= unit_file_find_dropin_paths(lp
->unit_path
, NULL
, names
, &dropins
);
2369 if (!isempty(path
)) {
2370 *fragment_path
= path
;
2375 if (dropin_paths
&& !strv_isempty(dropins
)) {
2376 *dropin_paths
= dropins
;
2382 log_error("No files found for %s.", unit_name
);
2387 static int check_one_unit(sd_bus
*bus
, const char *name
, const char *good_states
, bool quiet
) {
2388 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2389 _cleanup_free_
char *n
= NULL
, *state
= NULL
;
2395 r
= unit_name_mangle(name
, UNIT_NAME_NOGLOB
, &n
);
2397 return log_error_errno(r
, "Failed to mangle unit name: %m");
2399 /* We don't use unit_dbus_path_from_name() directly since we
2400 * don't want to load the unit if it isn't loaded. */
2402 r
= sd_bus_call_method(
2404 "org.freedesktop.systemd1",
2405 "/org/freedesktop/systemd1",
2406 "org.freedesktop.systemd1.Manager",
2417 r
= sd_bus_message_read(reply
, "o", &path
);
2419 return bus_log_parse_error(r
);
2421 r
= sd_bus_get_property_string(
2423 "org.freedesktop.systemd1",
2425 "org.freedesktop.systemd1.Unit",
2438 return nulstr_contains(good_states
, state
);
2441 static int check_triggering_units(
2445 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2446 _cleanup_free_
char *path
= NULL
, *n
= NULL
, *state
= NULL
;
2447 _cleanup_strv_free_
char **triggered_by
= NULL
;
2448 bool print_warning_label
= true;
2452 r
= unit_name_mangle(name
, UNIT_NAME_NOGLOB
, &n
);
2454 return log_error_errno(r
, "Failed to mangle unit name: %m");
2456 path
= unit_dbus_path_from_name(n
);
2460 r
= sd_bus_get_property_string(
2462 "org.freedesktop.systemd1",
2464 "org.freedesktop.systemd1.Unit",
2469 log_error("Failed to get load state of %s: %s", n
, bus_error_message(&error
, r
));
2473 if (streq(state
, "masked"))
2476 r
= sd_bus_get_property_strv(
2478 "org.freedesktop.systemd1",
2480 "org.freedesktop.systemd1.Unit",
2485 log_error("Failed to get triggered by array of %s: %s", n
, bus_error_message(&error
, r
));
2489 STRV_FOREACH(i
, triggered_by
) {
2490 r
= check_one_unit(bus
, *i
, "active\0reloading\0", true);
2492 return log_error_errno(r
, "Failed to check unit: %m");
2497 if (print_warning_label
) {
2498 log_warning("Warning: Stopping %s, but it can still be activated by:", n
);
2499 print_warning_label
= false;
2502 log_warning(" %s", *i
);
2508 static const struct {
2511 } unit_actions
[] = {
2512 { "start", "StartUnit" },
2513 { "stop", "StopUnit" },
2514 { "condstop", "StopUnit" },
2515 { "reload", "ReloadUnit" },
2516 { "restart", "RestartUnit" },
2517 { "try-restart", "TryRestartUnit" },
2518 { "condrestart", "TryRestartUnit" },
2519 { "reload-or-restart", "ReloadOrRestartUnit" },
2520 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2521 { "condreload", "ReloadOrTryRestartUnit" },
2522 { "force-reload", "ReloadOrTryRestartUnit" }
2525 static const char *verb_to_method(const char *verb
) {
2528 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2529 if (streq_ptr(unit_actions
[i
].verb
, verb
))
2530 return unit_actions
[i
].method
;
2535 static const char *method_to_verb(const char *method
) {
2538 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2539 if (streq_ptr(unit_actions
[i
].method
, method
))
2540 return unit_actions
[i
].verb
;
2545 static int start_unit_one(
2550 sd_bus_error
*error
,
2551 BusWaitForJobs
*w
) {
2553 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2562 log_debug("Calling manager for %s on %s, %s", method
, name
, mode
);
2564 r
= sd_bus_call_method(
2566 "org.freedesktop.systemd1",
2567 "/org/freedesktop/systemd1",
2568 "org.freedesktop.systemd1.Manager",
2576 if (r
== -ENOENT
&& arg_action
!= ACTION_SYSTEMCTL
)
2577 /* There's always a fallback possible for
2578 * legacy actions. */
2579 return -EADDRNOTAVAIL
;
2581 verb
= method_to_verb(method
);
2583 log_error("Failed to %s %s: %s", verb
, name
, bus_error_message(error
, r
));
2587 r
= sd_bus_message_read(reply
, "o", &path
);
2589 return bus_log_parse_error(r
);
2591 if (need_daemon_reload(bus
, name
) > 0)
2592 warn_unit_file_changed(name
);
2595 log_debug("Adding %s to the set", path
);
2596 r
= bus_wait_for_jobs_add(w
, path
);
2604 static int expand_names(sd_bus
*bus
, char **names
, const char* suffix
, char ***ret
) {
2606 _cleanup_strv_free_
char **mangled
= NULL
, **globs
= NULL
;
2610 STRV_FOREACH(name
, names
) {
2614 r
= unit_name_mangle_with_suffix(*name
, UNIT_NAME_GLOB
, suffix
, &t
);
2616 r
= unit_name_mangle(*name
, UNIT_NAME_GLOB
, &t
);
2618 return log_error_errno(r
, "Failed to mangle name: %m");
2620 if (string_is_glob(t
))
2621 r
= strv_consume(&globs
, t
);
2623 r
= strv_consume(&mangled
, t
);
2628 /* Query the manager only if any of the names are a glob, since
2629 * this is fairly expensive */
2630 if (!strv_isempty(globs
)) {
2631 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2632 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
2635 return log_error_errno(EOPNOTSUPP
, "Unit name globbing without bus is not implemented.");
2637 r
= get_unit_list(bus
, NULL
, globs
, &unit_infos
, 0, &reply
);
2641 for (i
= 0; i
< r
; i
++)
2642 if (strv_extend(&mangled
, unit_infos
[i
].id
) < 0)
2647 mangled
= NULL
; /* do not free */
2652 static const struct {
2656 } action_table
[_ACTION_MAX
] = {
2657 [ACTION_HALT
] = { SPECIAL_HALT_TARGET
, "halt", "replace-irreversibly" },
2658 [ACTION_POWEROFF
] = { SPECIAL_POWEROFF_TARGET
, "poweroff", "replace-irreversibly" },
2659 [ACTION_REBOOT
] = { SPECIAL_REBOOT_TARGET
, "reboot", "replace-irreversibly" },
2660 [ACTION_KEXEC
] = { SPECIAL_KEXEC_TARGET
, "kexec", "replace-irreversibly" },
2661 [ACTION_RUNLEVEL2
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2662 [ACTION_RUNLEVEL3
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2663 [ACTION_RUNLEVEL4
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2664 [ACTION_RUNLEVEL5
] = { SPECIAL_GRAPHICAL_TARGET
, NULL
, "isolate" },
2665 [ACTION_RESCUE
] = { SPECIAL_RESCUE_TARGET
, "rescue", "isolate" },
2666 [ACTION_EMERGENCY
] = { SPECIAL_EMERGENCY_TARGET
, "emergency", "isolate" },
2667 [ACTION_DEFAULT
] = { SPECIAL_DEFAULT_TARGET
, "default", "isolate" },
2668 [ACTION_EXIT
] = { SPECIAL_EXIT_TARGET
, "exit", "replace-irreversibly" },
2669 [ACTION_SUSPEND
] = { SPECIAL_SUSPEND_TARGET
, "suspend", "replace-irreversibly" },
2670 [ACTION_HIBERNATE
] = { SPECIAL_HIBERNATE_TARGET
, "hibernate", "replace-irreversibly" },
2671 [ACTION_HYBRID_SLEEP
] = { SPECIAL_HYBRID_SLEEP_TARGET
, "hybrid-sleep", "replace-irreversibly" },
2674 static enum action
verb_to_action(const char *verb
) {
2677 for (i
= _ACTION_INVALID
; i
< _ACTION_MAX
; i
++)
2678 if (streq_ptr(action_table
[i
].verb
, verb
))
2681 return _ACTION_INVALID
;
2684 static int start_unit(sd_bus
*bus
, char **args
) {
2685 _cleanup_(bus_wait_for_jobs_freep
) BusWaitForJobs
*w
= NULL
;
2686 const char *method
, *mode
, *one_name
, *suffix
= NULL
;
2687 _cleanup_strv_free_
char **names
= NULL
;
2693 ask_password_agent_open_if_enabled();
2694 polkit_agent_open_if_enabled();
2696 if (arg_action
== ACTION_SYSTEMCTL
) {
2698 method
= verb_to_method(args
[0]);
2699 action
= verb_to_action(args
[0]);
2701 if (streq(args
[0], "isolate")) {
2705 mode
= action_table
[action
].mode
?: arg_job_mode
;
2707 one_name
= action_table
[action
].target
;
2709 assert(arg_action
< ELEMENTSOF(action_table
));
2710 assert(action_table
[arg_action
].target
);
2712 method
= "StartUnit";
2714 mode
= action_table
[arg_action
].mode
;
2715 one_name
= action_table
[arg_action
].target
;
2719 names
= strv_new(one_name
, NULL
);
2721 r
= expand_names(bus
, args
+ 1, suffix
, &names
);
2723 log_error_errno(r
, "Failed to expand names: %m");
2726 if (!arg_no_block
) {
2727 r
= bus_wait_for_jobs_new(bus
, &w
);
2729 return log_error_errno(r
, "Could not watch jobs: %m");
2732 STRV_FOREACH(name
, names
) {
2733 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2736 q
= start_unit_one(bus
, method
, *name
, mode
, &error
, w
);
2737 if (r
>= 0 && q
< 0)
2738 r
= translate_bus_error_to_exit_status(q
, &error
);
2741 if (!arg_no_block
) {
2744 q
= bus_wait_for_jobs(w
, arg_quiet
);
2748 /* When stopping units, warn if they can still be triggered by
2749 * another active unit (socket, path, timer) */
2750 if (!arg_quiet
&& streq(method
, "StopUnit"))
2751 STRV_FOREACH(name
, names
)
2752 check_triggering_units(bus
, *name
);
2758 /* Ask systemd-logind, which might grant access to unprivileged users
2759 * through PolicyKit */
2760 static int reboot_with_logind(sd_bus
*bus
, enum action a
) {
2762 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2769 polkit_agent_open_if_enabled();
2777 case ACTION_POWEROFF
:
2778 method
= "PowerOff";
2781 case ACTION_SUSPEND
:
2785 case ACTION_HIBERNATE
:
2786 method
= "Hibernate";
2789 case ACTION_HYBRID_SLEEP
:
2790 method
= "HybridSleep";
2797 r
= sd_bus_call_method(
2799 "org.freedesktop.login1",
2800 "/org/freedesktop/login1",
2801 "org.freedesktop.login1.Manager",
2805 "b", arg_ask_password
);
2807 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
2815 static int check_inhibitors(sd_bus
*bus
, enum action a
) {
2817 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2818 _cleanup_strv_free_
char **sessions
= NULL
;
2819 const char *what
, *who
, *why
, *mode
;
2828 if (arg_ignore_inhibitors
|| arg_force
> 0)
2840 r
= sd_bus_call_method(
2842 "org.freedesktop.login1",
2843 "/org/freedesktop/login1",
2844 "org.freedesktop.login1.Manager",
2850 /* If logind is not around, then there are no inhibitors... */
2853 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssuu)");
2855 return bus_log_parse_error(r
);
2857 while ((r
= sd_bus_message_read(reply
, "(ssssuu)", &what
, &who
, &why
, &mode
, &uid
, &pid
)) > 0) {
2858 _cleanup_free_
char *comm
= NULL
, *user
= NULL
;
2859 _cleanup_strv_free_
char **sv
= NULL
;
2861 if (!streq(mode
, "block"))
2864 sv
= strv_split(what
, ":");
2868 if ((pid_t
) pid
< 0)
2869 return log_error_errno(ERANGE
, "Bad PID %"PRIu32
": %m", pid
);
2871 if (!strv_contains(sv
,
2873 a
== ACTION_POWEROFF
||
2874 a
== ACTION_REBOOT
||
2875 a
== ACTION_KEXEC
? "shutdown" : "sleep"))
2878 get_process_comm(pid
, &comm
);
2879 user
= uid_to_name(uid
);
2881 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT
" \"%s\", user %s), reason is \"%s\".",
2882 who
, (pid_t
) pid
, strna(comm
), strna(user
), why
);
2887 return bus_log_parse_error(r
);
2889 r
= sd_bus_message_exit_container(reply
);
2891 return bus_log_parse_error(r
);
2893 /* Check for current sessions */
2894 sd_get_sessions(&sessions
);
2895 STRV_FOREACH(s
, sessions
) {
2896 _cleanup_free_
char *type
= NULL
, *tty
= NULL
, *seat
= NULL
, *user
= NULL
, *service
= NULL
, *class = NULL
;
2898 if (sd_session_get_uid(*s
, &uid
) < 0 || uid
== getuid())
2901 if (sd_session_get_class(*s
, &class) < 0 || !streq(class, "user"))
2904 if (sd_session_get_type(*s
, &type
) < 0 || (!streq(type
, "x11") && !streq(type
, "tty")))
2907 sd_session_get_tty(*s
, &tty
);
2908 sd_session_get_seat(*s
, &seat
);
2909 sd_session_get_service(*s
, &service
);
2910 user
= uid_to_name(uid
);
2912 log_warning("User %s is logged in on %s.", strna(user
), isempty(tty
) ? (isempty(seat
) ? strna(service
) : seat
) : tty
);
2919 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2920 action_table
[a
].verb
);
2928 static int prepare_firmware_setup(sd_bus
*bus
) {
2930 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2934 if (!arg_firmware_setup
)
2937 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
2939 r
= efi_set_reboot_to_firmware(true);
2941 log_debug_errno(r
, "Cannot indicate to EFI to boot into setup mode, will retry via logind: %m");
2947 r
= sd_bus_call_method(
2949 "org.freedesktop.login1",
2950 "/org/freedesktop/login1",
2951 "org.freedesktop.login1.Manager",
2952 "SetRebootToFirmwareSetup",
2957 log_error("Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error
, r
));
2963 log_error("Cannot remotely indicate to EFI to boot into setup mode.");
2968 static int start_special(sd_bus
*bus
, char **args
) {
2974 a
= verb_to_action(args
[0]);
2976 r
= check_inhibitors(bus
, a
);
2980 if (arg_force
>= 2 && geteuid() != 0) {
2981 log_error("Must be root.");
2985 r
= prepare_firmware_setup(bus
);
2989 if (a
== ACTION_REBOOT
&& args
[1]) {
2990 r
= update_reboot_param_file(args
[1]);
2995 if (arg_force
>= 2 &&
2996 (a
== ACTION_HALT
||
2997 a
== ACTION_POWEROFF
||
2998 a
== ACTION_REBOOT
))
3001 if (arg_force
>= 1 &&
3002 (a
== ACTION_HALT
||
3003 a
== ACTION_POWEROFF
||
3004 a
== ACTION_REBOOT
||
3005 a
== ACTION_KEXEC
||
3007 return daemon_reload(bus
, args
);
3009 /* first try logind, to allow authentication with polkit */
3010 if (geteuid() != 0 &&
3011 (a
== ACTION_POWEROFF
||
3012 a
== ACTION_REBOOT
||
3013 a
== ACTION_SUSPEND
||
3014 a
== ACTION_HIBERNATE
||
3015 a
== ACTION_HYBRID_SLEEP
)) {
3016 r
= reboot_with_logind(bus
, a
);
3017 if (r
>= 0 || IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
3021 r
= start_unit(bus
, args
);
3022 if (r
== EXIT_SUCCESS
)
3028 static int check_unit_generic(sd_bus
*bus
, int code
, const char *good_states
, char **args
) {
3029 _cleanup_strv_free_
char **names
= NULL
;
3036 r
= expand_names(bus
, args
, NULL
, &names
);
3038 return log_error_errno(r
, "Failed to expand names: %m");
3040 STRV_FOREACH(name
, names
) {
3043 state
= check_one_unit(bus
, *name
, good_states
, arg_quiet
);
3053 static int check_unit_active(sd_bus
*bus
, char **args
) {
3054 /* According to LSB: 3, "program is not running" */
3055 return check_unit_generic(bus
, 3, "active\0reloading\0", args
+ 1);
3058 static int check_unit_failed(sd_bus
*bus
, char **args
) {
3059 return check_unit_generic(bus
, 1, "failed\0", args
+ 1);
3062 static int kill_unit(sd_bus
*bus
, char **args
) {
3063 _cleanup_strv_free_
char **names
= NULL
;
3070 polkit_agent_open_if_enabled();
3073 arg_kill_who
= "all";
3075 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
3077 log_error_errno(r
, "Failed to expand names: %m");
3079 STRV_FOREACH(name
, names
) {
3080 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
3082 q
= sd_bus_call_method(
3084 "org.freedesktop.systemd1",
3085 "/org/freedesktop/systemd1",
3086 "org.freedesktop.systemd1.Manager",
3090 "ssi", *names
, arg_kill_who
, arg_signal
);
3092 log_error("Failed to kill unit %s: %s", *names
, bus_error_message(&error
, q
));
3101 typedef struct ExecStatusInfo
{
3109 usec_t start_timestamp
;
3110 usec_t exit_timestamp
;
3115 LIST_FIELDS(struct ExecStatusInfo
, exec
);
3118 static void exec_status_info_free(ExecStatusInfo
*i
) {
3127 static int exec_status_info_deserialize(sd_bus_message
*m
, ExecStatusInfo
*i
) {
3128 uint64_t start_timestamp
, exit_timestamp
, start_timestamp_monotonic
, exit_timestamp_monotonic
;
3131 int32_t code
, status
;
3137 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_STRUCT
, "sasbttttuii");
3139 return bus_log_parse_error(r
);
3143 r
= sd_bus_message_read(m
, "s", &path
);
3145 return bus_log_parse_error(r
);
3147 i
->path
= strdup(path
);
3151 r
= sd_bus_message_read_strv(m
, &i
->argv
);
3153 return bus_log_parse_error(r
);
3155 r
= sd_bus_message_read(m
,
3158 &start_timestamp
, &start_timestamp_monotonic
,
3159 &exit_timestamp
, &exit_timestamp_monotonic
,
3163 return bus_log_parse_error(r
);
3166 i
->start_timestamp
= (usec_t
) start_timestamp
;
3167 i
->exit_timestamp
= (usec_t
) exit_timestamp
;
3168 i
->pid
= (pid_t
) pid
;
3172 r
= sd_bus_message_exit_container(m
);
3174 return bus_log_parse_error(r
);
3179 typedef struct UnitStatusInfo
{
3181 const char *load_state
;
3182 const char *active_state
;
3183 const char *sub_state
;
3184 const char *unit_file_state
;
3185 const char *unit_file_preset
;
3187 const char *description
;
3188 const char *following
;
3190 char **documentation
;
3192 const char *fragment_path
;
3193 const char *source_path
;
3194 const char *control_group
;
3196 char **dropin_paths
;
3198 const char *load_error
;
3201 usec_t inactive_exit_timestamp
;
3202 usec_t inactive_exit_timestamp_monotonic
;
3203 usec_t active_enter_timestamp
;
3204 usec_t active_exit_timestamp
;
3205 usec_t inactive_enter_timestamp
;
3207 bool need_daemon_reload
;
3212 const char *status_text
;
3213 const char *pid_file
;
3217 usec_t start_timestamp
;
3218 usec_t exit_timestamp
;
3220 int exit_code
, exit_status
;
3222 usec_t condition_timestamp
;
3223 bool condition_result
;
3224 bool failed_condition_trigger
;
3225 bool failed_condition_negate
;
3226 const char *failed_condition
;
3227 const char *failed_condition_parameter
;
3229 usec_t assert_timestamp
;
3231 bool failed_assert_trigger
;
3232 bool failed_assert_negate
;
3233 const char *failed_assert
;
3234 const char *failed_assert_parameter
;
3237 unsigned n_accepted
;
3238 unsigned n_connections
;
3241 /* Pairs of type, path */
3245 const char *sysfs_path
;
3247 /* Mount, Automount */
3254 uint64_t memory_current
;
3255 uint64_t memory_limit
;
3256 uint64_t cpu_usage_nsec
;
3258 LIST_HEAD(ExecStatusInfo
, exec
);
3261 static void print_status_info(
3266 const char *active_on
, *active_off
, *on
, *off
, *ss
;
3268 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], *s1
;
3269 char since2
[FORMAT_TIMESTAMP_MAX
], *s2
;
3275 /* This shows pretty information about a unit. See
3276 * print_property() for a low-level property printer */
3278 if (streq_ptr(i
->active_state
, "failed")) {
3279 active_on
= ansi_highlight_red();
3280 active_off
= ansi_highlight_off();
3281 } else if (streq_ptr(i
->active_state
, "active") || streq_ptr(i
->active_state
, "reloading")) {
3282 active_on
= ansi_highlight_green();
3283 active_off
= ansi_highlight_off();
3285 active_on
= active_off
= "";
3287 printf("%s%s%s %s", active_on
, draw_special_char(DRAW_BLACK_CIRCLE
), active_off
, strna(i
->id
));
3289 if (i
->description
&& !streq_ptr(i
->id
, i
->description
))
3290 printf(" - %s", i
->description
);
3295 printf(" Follow: unit currently follows state of %s\n", i
->following
);
3297 if (streq_ptr(i
->load_state
, "error")) {
3298 on
= ansi_highlight_red();
3299 off
= ansi_highlight_off();
3303 path
= i
->source_path
? i
->source_path
: i
->fragment_path
;
3306 printf(" Loaded: %s%s%s (Reason: %s)\n",
3307 on
, strna(i
->load_state
), off
, i
->load_error
);
3308 else if (path
&& !isempty(i
->unit_file_state
) && !isempty(i
->unit_file_preset
))
3309 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
3310 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
, i
->unit_file_preset
);
3311 else if (path
&& !isempty(i
->unit_file_state
))
3312 printf(" Loaded: %s%s%s (%s; %s)\n",
3313 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
);
3315 printf(" Loaded: %s%s%s (%s)\n",
3316 on
, strna(i
->load_state
), off
, path
);
3318 printf(" Loaded: %s%s%s\n",
3319 on
, strna(i
->load_state
), off
);
3321 if (!strv_isempty(i
->dropin_paths
)) {
3322 _cleanup_free_
char *dir
= NULL
;
3326 STRV_FOREACH(dropin
, i
->dropin_paths
) {
3327 if (! dir
|| last
) {
3328 printf(dir
? " " : " Drop-In: ");
3333 if (path_get_parent(*dropin
, &dir
) < 0) {
3338 printf("%s\n %s", dir
,
3339 draw_special_char(DRAW_TREE_RIGHT
));
3342 last
= ! (*(dropin
+ 1) && startswith(*(dropin
+ 1), dir
));
3344 printf("%s%s", basename(*dropin
), last
? "\n" : ", ");
3348 ss
= streq_ptr(i
->active_state
, i
->sub_state
) ? NULL
: i
->sub_state
;
3350 printf(" Active: %s%s (%s)%s",
3351 active_on
, strna(i
->active_state
), ss
, active_off
);
3353 printf(" Active: %s%s%s",
3354 active_on
, strna(i
->active_state
), active_off
);
3356 if (!isempty(i
->result
) && !streq(i
->result
, "success"))
3357 printf(" (Result: %s)", i
->result
);
3359 timestamp
= (streq_ptr(i
->active_state
, "active") ||
3360 streq_ptr(i
->active_state
, "reloading")) ? i
->active_enter_timestamp
:
3361 (streq_ptr(i
->active_state
, "inactive") ||
3362 streq_ptr(i
->active_state
, "failed")) ? i
->inactive_enter_timestamp
:
3363 streq_ptr(i
->active_state
, "activating") ? i
->inactive_exit_timestamp
:
3364 i
->active_exit_timestamp
;
3366 s1
= format_timestamp_relative(since1
, sizeof(since1
), timestamp
);
3367 s2
= format_timestamp(since2
, sizeof(since2
), timestamp
);
3370 printf(" since %s; %s\n", s2
, s1
);
3372 printf(" since %s\n", s2
);
3376 if (!i
->condition_result
&& i
->condition_timestamp
> 0) {
3377 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->condition_timestamp
);
3378 s2
= format_timestamp(since2
, sizeof(since2
), i
->condition_timestamp
);
3380 printf("Condition: start %scondition failed%s at %s%s%s\n",
3381 ansi_highlight_yellow(), ansi_highlight_off(),
3382 s2
, s1
? "; " : "", s1
? s1
: "");
3383 if (i
->failed_condition_trigger
)
3384 printf(" none of the trigger conditions were met\n");
3385 else if (i
->failed_condition
)
3386 printf(" %s=%s%s was not met\n",
3387 i
->failed_condition
,
3388 i
->failed_condition_negate
? "!" : "",
3389 i
->failed_condition_parameter
);
3392 if (!i
->assert_result
&& i
->assert_timestamp
> 0) {
3393 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->assert_timestamp
);
3394 s2
= format_timestamp(since2
, sizeof(since2
), i
->assert_timestamp
);
3396 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
3397 ansi_highlight_red(), ansi_highlight_off(),
3398 s2
, s1
? "; " : "", s1
? s1
: "");
3399 if (i
->failed_assert_trigger
)
3400 printf(" none of the trigger assertions were met\n");
3401 else if (i
->failed_assert
)
3402 printf(" %s=%s%s was not met\n",
3404 i
->failed_assert_negate
? "!" : "",
3405 i
->failed_assert_parameter
);
3409 printf(" Device: %s\n", i
->sysfs_path
);
3411 printf(" Where: %s\n", i
->where
);
3413 printf(" What: %s\n", i
->what
);
3415 STRV_FOREACH(t
, i
->documentation
)
3416 printf(" %*s %s\n", 9, t
== i
->documentation
? "Docs:" : "", *t
);
3418 STRV_FOREACH_PAIR(t
, t2
, i
->listen
)
3419 printf(" %*s %s (%s)\n", 9, t
== i
->listen
? "Listen:" : "", *t2
, *t
);
3422 printf(" Accepted: %u; Connected: %u\n", i
->n_accepted
, i
->n_connections
);
3424 LIST_FOREACH(exec
, p
, i
->exec
) {
3425 _cleanup_free_
char *argv
= NULL
;
3428 /* Only show exited processes here */
3432 argv
= strv_join(p
->argv
, " ");
3433 printf(" Process: "PID_FMT
" %s=%s ", p
->pid
, p
->name
, strna(argv
));
3435 good
= is_clean_exit_lsb(p
->code
, p
->status
, NULL
);
3437 on
= ansi_highlight_red();
3438 off
= ansi_highlight_off();
3442 printf("%s(code=%s, ", on
, sigchld_code_to_string(p
->code
));
3444 if (p
->code
== CLD_EXITED
) {
3447 printf("status=%i", p
->status
);
3449 c
= exit_status_to_string(p
->status
, EXIT_STATUS_SYSTEMD
);
3454 printf("signal=%s", signal_to_string(p
->status
));
3456 printf(")%s\n", off
);
3458 if (i
->main_pid
== p
->pid
&&
3459 i
->start_timestamp
== p
->start_timestamp
&&
3460 i
->exit_timestamp
== p
->start_timestamp
)
3461 /* Let's not show this twice */
3464 if (p
->pid
== i
->control_pid
)
3468 if (i
->main_pid
> 0 || i
->control_pid
> 0) {
3469 if (i
->main_pid
> 0) {
3470 printf(" Main PID: "PID_FMT
, i
->main_pid
);
3473 _cleanup_free_
char *comm
= NULL
;
3474 get_process_comm(i
->main_pid
, &comm
);
3476 printf(" (%s)", comm
);
3477 } else if (i
->exit_code
> 0) {
3478 printf(" (code=%s, ", sigchld_code_to_string(i
->exit_code
));
3480 if (i
->exit_code
== CLD_EXITED
) {
3483 printf("status=%i", i
->exit_status
);
3485 c
= exit_status_to_string(i
->exit_status
, EXIT_STATUS_SYSTEMD
);
3490 printf("signal=%s", signal_to_string(i
->exit_status
));
3494 if (i
->control_pid
> 0)
3498 if (i
->control_pid
> 0) {
3499 _cleanup_free_
char *c
= NULL
;
3501 printf(" %8s: "PID_FMT
, i
->main_pid
? "" : " Control", i
->control_pid
);
3503 get_process_comm(i
->control_pid
, &c
);
3512 printf(" Status: \"%s\"\n", i
->status_text
);
3513 if (i
->status_errno
> 0)
3514 printf(" Error: %i (%s)\n", i
->status_errno
, strerror(i
->status_errno
));
3516 if (i
->memory_current
!= (uint64_t) -1) {
3517 char buf
[FORMAT_BYTES_MAX
];
3519 printf(" Memory: %s", format_bytes(buf
, sizeof(buf
), i
->memory_current
));
3521 if (i
->memory_limit
!= (uint64_t) -1)
3522 printf(" (limit: %s)\n", format_bytes(buf
, sizeof(buf
), i
->memory_limit
));
3527 if (i
->cpu_usage_nsec
!= (uint64_t) -1) {
3528 char buf
[FORMAT_TIMESPAN_MAX
];
3529 printf(" CPU: %s\n", format_timespan(buf
, sizeof(buf
), i
->cpu_usage_nsec
/ NSEC_PER_USEC
, USEC_PER_MSEC
));
3532 if (i
->control_group
&&
3533 (i
->main_pid
> 0 || i
->control_pid
> 0 ||
3534 ((arg_transport
!= BUS_TRANSPORT_LOCAL
&& arg_transport
!= BUS_TRANSPORT_MACHINE
) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, false) == 0))) {
3537 printf(" CGroup: %s\n", i
->control_group
);
3539 if (arg_transport
== BUS_TRANSPORT_LOCAL
|| arg_transport
== BUS_TRANSPORT_MACHINE
) {
3542 static const char prefix
[] = " ";
3545 if (c
> sizeof(prefix
) - 1)
3546 c
-= sizeof(prefix
) - 1;
3550 if (i
->main_pid
> 0)
3551 extra
[k
++] = i
->main_pid
;
3553 if (i
->control_pid
> 0)
3554 extra
[k
++] = i
->control_pid
;
3556 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, prefix
, c
, false, extra
, k
, get_output_flags());
3560 if (i
->id
&& arg_transport
== BUS_TRANSPORT_LOCAL
) {
3561 show_journal_by_unit(
3566 i
->inactive_exit_timestamp_monotonic
,
3569 get_output_flags() | OUTPUT_BEGIN_NEWLINE
,
3570 SD_JOURNAL_LOCAL_ONLY
,
3571 arg_scope
== UNIT_FILE_SYSTEM
,
3575 if (i
->need_daemon_reload
)
3576 warn_unit_file_changed(i
->id
);
3579 static void show_unit_help(UnitStatusInfo
*i
) {
3584 if (!i
->documentation
) {
3585 log_info("Documentation for %s not known.", i
->id
);
3589 STRV_FOREACH(p
, i
->documentation
)
3590 if (startswith(*p
, "man:"))
3591 show_man_page(*p
+ 4, false);
3593 log_info("Can't show: %s", *p
);
3596 static int status_property(const char *name
, sd_bus_message
*m
, UnitStatusInfo
*i
, const char *contents
) {
3603 switch (contents
[0]) {
3605 case SD_BUS_TYPE_STRING
: {
3608 r
= sd_bus_message_read(m
, "s", &s
);
3610 return bus_log_parse_error(r
);
3613 if (streq(name
, "Id"))
3615 else if (streq(name
, "LoadState"))
3617 else if (streq(name
, "ActiveState"))
3618 i
->active_state
= s
;
3619 else if (streq(name
, "SubState"))
3621 else if (streq(name
, "Description"))
3623 else if (streq(name
, "FragmentPath"))
3624 i
->fragment_path
= s
;
3625 else if (streq(name
, "SourcePath"))
3628 else if (streq(name
, "DefaultControlGroup")) {
3630 e
= startswith(s
, SYSTEMD_CGROUP_CONTROLLER
":");
3632 i
->control_group
= e
;
3635 else if (streq(name
, "ControlGroup"))
3636 i
->control_group
= s
;
3637 else if (streq(name
, "StatusText"))
3639 else if (streq(name
, "PIDFile"))
3641 else if (streq(name
, "SysFSPath"))
3643 else if (streq(name
, "Where"))
3645 else if (streq(name
, "What"))
3647 else if (streq(name
, "Following"))
3649 else if (streq(name
, "UnitFileState"))
3650 i
->unit_file_state
= s
;
3651 else if (streq(name
, "UnitFilePreset"))
3652 i
->unit_file_preset
= s
;
3653 else if (streq(name
, "Result"))
3660 case SD_BUS_TYPE_BOOLEAN
: {
3663 r
= sd_bus_message_read(m
, "b", &b
);
3665 return bus_log_parse_error(r
);
3667 if (streq(name
, "Accept"))
3669 else if (streq(name
, "NeedDaemonReload"))
3670 i
->need_daemon_reload
= b
;
3671 else if (streq(name
, "ConditionResult"))
3672 i
->condition_result
= b
;
3673 else if (streq(name
, "AssertResult"))
3674 i
->assert_result
= b
;
3679 case SD_BUS_TYPE_UINT32
: {
3682 r
= sd_bus_message_read(m
, "u", &u
);
3684 return bus_log_parse_error(r
);
3686 if (streq(name
, "MainPID")) {
3688 i
->main_pid
= (pid_t
) u
;
3691 } else if (streq(name
, "ControlPID"))
3692 i
->control_pid
= (pid_t
) u
;
3693 else if (streq(name
, "ExecMainPID")) {
3695 i
->main_pid
= (pid_t
) u
;
3696 } else if (streq(name
, "NAccepted"))
3698 else if (streq(name
, "NConnections"))
3699 i
->n_connections
= u
;
3704 case SD_BUS_TYPE_INT32
: {
3707 r
= sd_bus_message_read(m
, "i", &j
);
3709 return bus_log_parse_error(r
);
3711 if (streq(name
, "ExecMainCode"))
3712 i
->exit_code
= (int) j
;
3713 else if (streq(name
, "ExecMainStatus"))
3714 i
->exit_status
= (int) j
;
3715 else if (streq(name
, "StatusErrno"))
3716 i
->status_errno
= (int) j
;
3721 case SD_BUS_TYPE_UINT64
: {
3724 r
= sd_bus_message_read(m
, "t", &u
);
3726 return bus_log_parse_error(r
);
3728 if (streq(name
, "ExecMainStartTimestamp"))
3729 i
->start_timestamp
= (usec_t
) u
;
3730 else if (streq(name
, "ExecMainExitTimestamp"))
3731 i
->exit_timestamp
= (usec_t
) u
;
3732 else if (streq(name
, "ActiveEnterTimestamp"))
3733 i
->active_enter_timestamp
= (usec_t
) u
;
3734 else if (streq(name
, "InactiveEnterTimestamp"))
3735 i
->inactive_enter_timestamp
= (usec_t
) u
;
3736 else if (streq(name
, "InactiveExitTimestamp"))
3737 i
->inactive_exit_timestamp
= (usec_t
) u
;
3738 else if (streq(name
, "InactiveExitTimestampMonotonic"))
3739 i
->inactive_exit_timestamp_monotonic
= (usec_t
) u
;
3740 else if (streq(name
, "ActiveExitTimestamp"))
3741 i
->active_exit_timestamp
= (usec_t
) u
;
3742 else if (streq(name
, "ConditionTimestamp"))
3743 i
->condition_timestamp
= (usec_t
) u
;
3744 else if (streq(name
, "AssertTimestamp"))
3745 i
->assert_timestamp
= (usec_t
) u
;
3746 else if (streq(name
, "MemoryCurrent"))
3747 i
->memory_current
= u
;
3748 else if (streq(name
, "MemoryLimit"))
3749 i
->memory_limit
= u
;
3750 else if (streq(name
, "CPUUsageNSec"))
3751 i
->cpu_usage_nsec
= u
;
3756 case SD_BUS_TYPE_ARRAY
:
3758 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
3759 _cleanup_free_ ExecStatusInfo
*info
= NULL
;
3761 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
3763 return bus_log_parse_error(r
);
3765 info
= new0(ExecStatusInfo
, 1);
3769 while ((r
= exec_status_info_deserialize(m
, info
)) > 0) {
3771 info
->name
= strdup(name
);
3775 LIST_PREPEND(exec
, i
->exec
, info
);
3777 info
= new0(ExecStatusInfo
, 1);
3783 return bus_log_parse_error(r
);
3785 r
= sd_bus_message_exit_container(m
);
3787 return bus_log_parse_error(r
);
3791 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
3792 const char *type
, *path
;
3794 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
3796 return bus_log_parse_error(r
);
3798 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0) {
3800 r
= strv_extend(&i
->listen
, type
);
3804 r
= strv_extend(&i
->listen
, path
);
3809 return bus_log_parse_error(r
);
3811 r
= sd_bus_message_exit_container(m
);
3813 return bus_log_parse_error(r
);
3817 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "DropInPaths")) {
3819 r
= sd_bus_message_read_strv(m
, &i
->dropin_paths
);
3821 return bus_log_parse_error(r
);
3823 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Documentation")) {
3825 r
= sd_bus_message_read_strv(m
, &i
->documentation
);
3827 return bus_log_parse_error(r
);
3829 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Conditions")) {
3830 const char *cond
, *param
;
3831 int trigger
, negate
;
3834 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
3836 return bus_log_parse_error(r
);
3838 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
3839 log_debug("%s %d %d %s %d", cond
, trigger
, negate
, param
, state
);
3840 if (state
< 0 && (!trigger
|| !i
->failed_condition
)) {
3841 i
->failed_condition
= cond
;
3842 i
->failed_condition_trigger
= trigger
;
3843 i
->failed_condition_negate
= negate
;
3844 i
->failed_condition_parameter
= param
;
3848 return bus_log_parse_error(r
);
3850 r
= sd_bus_message_exit_container(m
);
3852 return bus_log_parse_error(r
);
3854 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Asserts")) {
3855 const char *cond
, *param
;
3856 int trigger
, negate
;
3859 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
3861 return bus_log_parse_error(r
);
3863 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
3864 log_debug("%s %d %d %s %d", cond
, trigger
, negate
, param
, state
);
3865 if (state
< 0 && (!trigger
|| !i
->failed_assert
)) {
3866 i
->failed_assert
= cond
;
3867 i
->failed_assert_trigger
= trigger
;
3868 i
->failed_assert_negate
= negate
;
3869 i
->failed_assert_parameter
= param
;
3873 return bus_log_parse_error(r
);
3875 r
= sd_bus_message_exit_container(m
);
3877 return bus_log_parse_error(r
);
3884 case SD_BUS_TYPE_STRUCT_BEGIN
:
3886 if (streq(name
, "LoadError")) {
3887 const char *n
, *message
;
3889 r
= sd_bus_message_read(m
, "(ss)", &n
, &message
);
3891 return bus_log_parse_error(r
);
3893 if (!isempty(message
))
3894 i
->load_error
= message
;
3907 r
= sd_bus_message_skip(m
, contents
);
3909 return bus_log_parse_error(r
);
3914 static int print_property(const char *name
, sd_bus_message
*m
, const char *contents
) {
3920 /* This is a low-level property printer, see
3921 * print_status_info() for the nicer output */
3923 if (arg_properties
&& !strv_find(arg_properties
, name
)) {
3924 /* skip what we didn't read */
3925 r
= sd_bus_message_skip(m
, contents
);
3929 switch (contents
[0]) {
3931 case SD_BUS_TYPE_STRUCT_BEGIN
:
3933 if (contents
[1] == SD_BUS_TYPE_UINT32
&& streq(name
, "Job")) {
3936 r
= sd_bus_message_read(m
, "(uo)", &u
, NULL
);
3938 return bus_log_parse_error(r
);
3941 printf("%s=%"PRIu32
"\n", name
, u
);
3943 printf("%s=\n", name
);
3947 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Unit")) {
3950 r
= sd_bus_message_read(m
, "(so)", &s
, NULL
);
3952 return bus_log_parse_error(r
);
3954 if (arg_all
|| !isempty(s
))
3955 printf("%s=%s\n", name
, s
);
3959 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "LoadError")) {
3960 const char *a
= NULL
, *b
= NULL
;
3962 r
= sd_bus_message_read(m
, "(ss)", &a
, &b
);
3964 return bus_log_parse_error(r
);
3966 if (arg_all
|| !isempty(a
) || !isempty(b
))
3967 printf("%s=%s \"%s\"\n", name
, strempty(a
), strempty(b
));
3970 } else if (streq_ptr(name
, "SystemCallFilter")) {
3971 _cleanup_strv_free_
char **l
= NULL
;
3974 r
= sd_bus_message_enter_container(m
, 'r', "bas");
3976 return bus_log_parse_error(r
);
3978 r
= sd_bus_message_read(m
, "b", &whitelist
);
3980 return bus_log_parse_error(r
);
3982 r
= sd_bus_message_read_strv(m
, &l
);
3984 return bus_log_parse_error(r
);
3986 r
= sd_bus_message_exit_container(m
);
3988 return bus_log_parse_error(r
);
3990 if (arg_all
|| whitelist
|| !strv_isempty(l
)) {
3994 fputs(name
, stdout
);
4000 STRV_FOREACH(i
, l
) {
4008 fputc('\n', stdout
);
4016 case SD_BUS_TYPE_ARRAY
:
4018 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "EnvironmentFiles")) {
4022 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sb)");
4024 return bus_log_parse_error(r
);
4026 while ((r
= sd_bus_message_read(m
, "(sb)", &path
, &ignore
)) > 0)
4027 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path
, yes_no(ignore
));
4030 return bus_log_parse_error(r
);
4032 r
= sd_bus_message_exit_container(m
);
4034 return bus_log_parse_error(r
);
4038 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Paths")) {
4039 const char *type
, *path
;
4041 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4043 return bus_log_parse_error(r
);
4045 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4046 printf("%s=%s\n", type
, path
);
4048 return bus_log_parse_error(r
);
4050 r
= sd_bus_message_exit_container(m
);
4052 return bus_log_parse_error(r
);
4056 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
4057 const char *type
, *path
;
4059 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4061 return bus_log_parse_error(r
);
4063 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4064 printf("Listen%s=%s\n", type
, path
);
4066 return bus_log_parse_error(r
);
4068 r
= sd_bus_message_exit_container(m
);
4070 return bus_log_parse_error(r
);
4074 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Timers")) {
4076 uint64_t value
, next_elapse
;
4078 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(stt)");
4080 return bus_log_parse_error(r
);
4082 while ((r
= sd_bus_message_read(m
, "(stt)", &base
, &value
, &next_elapse
)) > 0) {
4083 char timespan1
[FORMAT_TIMESPAN_MAX
], timespan2
[FORMAT_TIMESPAN_MAX
];
4085 printf("%s={ value=%s ; next_elapse=%s }\n",
4087 format_timespan(timespan1
, sizeof(timespan1
), value
, 0),
4088 format_timespan(timespan2
, sizeof(timespan2
), next_elapse
, 0));
4091 return bus_log_parse_error(r
);
4093 r
= sd_bus_message_exit_container(m
);
4095 return bus_log_parse_error(r
);
4099 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
4100 ExecStatusInfo info
= {};
4102 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4104 return bus_log_parse_error(r
);
4106 while ((r
= exec_status_info_deserialize(m
, &info
)) > 0) {
4107 char timestamp1
[FORMAT_TIMESTAMP_MAX
], timestamp2
[FORMAT_TIMESTAMP_MAX
];
4108 _cleanup_free_
char *tt
;
4110 tt
= strv_join(info
.argv
, " ");
4112 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",
4116 yes_no(info
.ignore
),
4117 strna(format_timestamp(timestamp1
, sizeof(timestamp1
), info
.start_timestamp
)),
4118 strna(format_timestamp(timestamp2
, sizeof(timestamp2
), info
.exit_timestamp
)),
4120 sigchld_code_to_string(info
.code
),
4122 info
.code
== CLD_EXITED
? "" : "/",
4123 strempty(info
.code
== CLD_EXITED
? NULL
: signal_to_string(info
.status
)));
4126 strv_free(info
.argv
);
4130 r
= sd_bus_message_exit_container(m
);
4132 return bus_log_parse_error(r
);
4136 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "DeviceAllow")) {
4137 const char *path
, *rwm
;
4139 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4141 return bus_log_parse_error(r
);
4143 while ((r
= sd_bus_message_read(m
, "(ss)", &path
, &rwm
)) > 0)
4144 printf("%s=%s %s\n", name
, strna(path
), strna(rwm
));
4146 return bus_log_parse_error(r
);
4148 r
= sd_bus_message_exit_container(m
);
4150 return bus_log_parse_error(r
);
4154 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "BlockIODeviceWeight")) {
4158 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4160 return bus_log_parse_error(r
);
4162 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &weight
)) > 0)
4163 printf("%s=%s %" PRIu64
"\n", name
, strna(path
), weight
);
4165 return bus_log_parse_error(r
);
4167 r
= sd_bus_message_exit_container(m
);
4169 return bus_log_parse_error(r
);
4173 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& (streq(name
, "BlockIOReadBandwidth") || streq(name
, "BlockIOWriteBandwidth"))) {
4177 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4179 return bus_log_parse_error(r
);
4181 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &bandwidth
)) > 0)
4182 printf("%s=%s %" PRIu64
"\n", name
, strna(path
), bandwidth
);
4184 return bus_log_parse_error(r
);
4186 r
= sd_bus_message_exit_container(m
);
4188 return bus_log_parse_error(r
);
4196 r
= bus_print_property(name
, m
, arg_all
);
4198 return bus_log_parse_error(r
);
4201 r
= sd_bus_message_skip(m
, contents
);
4203 return bus_log_parse_error(r
);
4206 printf("%s=[unprintable]\n", name
);
4212 static int show_one(
4216 bool show_properties
,
4220 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4221 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4222 UnitStatusInfo info
= {
4223 .memory_current
= (uint64_t) -1,
4224 .memory_limit
= (uint64_t) -1,
4225 .cpu_usage_nsec
= (uint64_t) -1,
4233 log_debug("Showing one %s", path
);
4235 r
= sd_bus_call_method(
4237 "org.freedesktop.systemd1",
4239 "org.freedesktop.DBus.Properties",
4245 log_error("Failed to get properties: %s", bus_error_message(&error
, r
));
4249 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
4251 return bus_log_parse_error(r
);
4258 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
4259 const char *name
, *contents
;
4261 r
= sd_bus_message_read(reply
, "s", &name
);
4263 return bus_log_parse_error(r
);
4265 r
= sd_bus_message_peek_type(reply
, NULL
, &contents
);
4267 return bus_log_parse_error(r
);
4269 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, contents
);
4271 return bus_log_parse_error(r
);
4273 if (show_properties
)
4274 r
= print_property(name
, reply
, contents
);
4276 r
= status_property(name
, reply
, &info
, contents
);
4280 r
= sd_bus_message_exit_container(reply
);
4282 return bus_log_parse_error(r
);
4284 r
= sd_bus_message_exit_container(reply
);
4286 return bus_log_parse_error(r
);
4289 return bus_log_parse_error(r
);
4291 r
= sd_bus_message_exit_container(reply
);
4293 return bus_log_parse_error(r
);
4297 if (!show_properties
) {
4298 if (streq(verb
, "help"))
4299 show_unit_help(&info
);
4301 print_status_info(&info
, ellipsized
);
4304 strv_free(info
.documentation
);
4305 strv_free(info
.dropin_paths
);
4306 strv_free(info
.listen
);
4308 if (!streq_ptr(info
.active_state
, "active") &&
4309 !streq_ptr(info
.active_state
, "reloading") &&
4310 streq(verb
, "status")) {
4311 /* According to LSB: "program not running" */
4312 /* 0: program is running or service is OK
4313 * 1: program is dead and /run PID file exists
4314 * 2: program is dead and /run/lock lock file exists
4315 * 3: program is not running
4316 * 4: program or service status is unknown
4318 if (info
.pid_file
&& access(info
.pid_file
, F_OK
) == 0)
4324 while ((p
= info
.exec
)) {
4325 LIST_REMOVE(exec
, info
.exec
, p
);
4326 exec_status_info_free(p
);
4332 static int get_unit_dbus_path_by_pid(
4337 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4338 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4342 r
= sd_bus_call_method(
4344 "org.freedesktop.systemd1",
4345 "/org/freedesktop/systemd1",
4346 "org.freedesktop.systemd1.Manager",
4352 log_error("Failed to get unit for PID %"PRIu32
": %s", pid
, bus_error_message(&error
, r
));
4356 r
= sd_bus_message_read(reply
, "o", &u
);
4358 return bus_log_parse_error(r
);
4368 static int show_all(
4371 bool show_properties
,
4375 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4376 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
4381 r
= get_unit_list(bus
, NULL
, NULL
, &unit_infos
, 0, &reply
);
4385 pager_open_if_enabled();
4389 qsort_safe(unit_infos
, c
, sizeof(UnitInfo
), compare_unit_info
);
4391 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
4392 _cleanup_free_
char *p
= NULL
;
4394 p
= unit_dbus_path_from_name(u
->id
);
4398 r
= show_one(verb
, bus
, p
, show_properties
, new_line
, ellipsized
);
4401 else if (r
> 0 && ret
== 0)
4408 static int show_system_status(sd_bus
*bus
) {
4409 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], since2
[FORMAT_TIMESTAMP_MAX
];
4410 _cleanup_free_
char *hn
= NULL
;
4411 _cleanup_(machine_info_clear
) struct machine_info mi
= {};
4412 const char *on
, *off
;
4415 hn
= gethostname_malloc();
4419 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, &mi
);
4421 return log_error_errno(r
, "Failed to read server status: %m");
4423 if (streq_ptr(mi
.state
, "degraded")) {
4424 on
= ansi_highlight_red();
4425 off
= ansi_highlight_off();
4426 } else if (!streq_ptr(mi
.state
, "running")) {
4427 on
= ansi_highlight_yellow();
4428 off
= ansi_highlight_off();
4432 printf("%s%s%s %s\n", on
, draw_special_char(DRAW_BLACK_CIRCLE
), off
, arg_host
? arg_host
: hn
);
4434 printf(" State: %s%s%s\n",
4435 on
, strna(mi
.state
), off
);
4437 printf(" Jobs: %u queued\n", mi
.n_jobs
);
4438 printf(" Failed: %u units\n", mi
.n_failed_units
);
4440 printf(" Since: %s; %s\n",
4441 format_timestamp(since2
, sizeof(since2
), mi
.timestamp
),
4442 format_timestamp_relative(since1
, sizeof(since1
), mi
.timestamp
));
4444 printf(" CGroup: %s\n", mi
.control_group
?: "/");
4445 if (arg_transport
== BUS_TRANSPORT_LOCAL
|| arg_transport
== BUS_TRANSPORT_MACHINE
) {
4446 static const char prefix
[] = " ";
4450 if (c
> sizeof(prefix
) - 1)
4451 c
-= sizeof(prefix
) - 1;
4455 show_cgroup(SYSTEMD_CGROUP_CONTROLLER
, strempty(mi
.control_group
), prefix
, c
, false, get_output_flags());
4461 static int show(sd_bus
*bus
, char **args
) {
4462 bool show_properties
, show_status
, new_line
= false;
4463 bool ellipsized
= false;
4469 show_properties
= streq(args
[0], "show");
4470 show_status
= streq(args
[0], "status");
4472 if (show_properties
)
4473 pager_open_if_enabled();
4476 /* Increase max number of open files to 16K if we can, we
4477 * might needs this when browsing journal files, which might
4478 * be split up into many files. */
4479 setrlimit_closest(RLIMIT_NOFILE
, &RLIMIT_MAKE_CONST(16384));
4481 /* If no argument is specified inspect the manager itself */
4483 if (show_properties
&& strv_length(args
) <= 1)
4484 return show_one(args
[0], bus
, "/org/freedesktop/systemd1", show_properties
, &new_line
, &ellipsized
);
4486 if (show_status
&& strv_length(args
) <= 1) {
4488 pager_open_if_enabled();
4489 show_system_status(bus
);
4493 ret
= show_all(args
[0], bus
, false, &new_line
, &ellipsized
);
4495 _cleanup_free_
char **patterns
= NULL
;
4498 STRV_FOREACH(name
, args
+ 1) {
4499 _cleanup_free_
char *unit
= NULL
;
4502 if (safe_atou32(*name
, &id
) < 0) {
4503 if (strv_push(&patterns
, *name
) < 0)
4507 } else if (show_properties
) {
4508 /* Interpret as job id */
4509 if (asprintf(&unit
, "/org/freedesktop/systemd1/job/%u", id
) < 0)
4513 /* Interpret as PID */
4514 r
= get_unit_dbus_path_by_pid(bus
, id
, &unit
);
4521 r
= show_one(args
[0], bus
, unit
, show_properties
,
4522 &new_line
, &ellipsized
);
4525 else if (r
> 0 && ret
== 0)
4529 if (!strv_isempty(patterns
)) {
4530 _cleanup_strv_free_
char **names
= NULL
;
4532 r
= expand_names(bus
, patterns
, NULL
, &names
);
4534 log_error_errno(r
, "Failed to expand names: %m");
4536 STRV_FOREACH(name
, names
) {
4537 _cleanup_free_
char *unit
;
4539 unit
= unit_dbus_path_from_name(*name
);
4543 r
= show_one(args
[0], bus
, unit
, show_properties
,
4544 &new_line
, &ellipsized
);
4547 else if (r
> 0 && ret
== 0)
4553 if (ellipsized
&& !arg_quiet
)
4554 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4559 static int init_home_and_lookup_paths(char **user_home
, char **user_runtime
, LookupPaths
*lp
) {
4563 assert(user_runtime
);
4566 if (arg_scope
== UNIT_FILE_USER
) {
4567 r
= user_config_home(user_home
);
4569 return log_error_errno(r
, "Failed to query XDG_CONFIG_HOME: %m");
4571 return log_error_errno(ENOTDIR
, "Cannot find units: $XDG_CONFIG_HOME and $HOME are not set.");
4573 r
= user_runtime_dir(user_runtime
);
4575 return log_error_errno(r
, "Failed to query XDG_CONFIG_HOME: %m");
4577 return log_error_errno(ENOTDIR
, "Cannot find units: $XDG_RUNTIME_DIR is not set.");
4580 r
= lookup_paths_init_from_scope(lp
, arg_scope
, arg_root
);
4582 return log_error_errno(r
, "Failed to query unit lookup paths: %m");
4587 static int cat_file(const char *filename
, bool newline
) {
4588 _cleanup_close_
int fd
;
4590 fd
= open(filename
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
4594 printf("%s%s# %s%s\n",
4595 newline
? "\n" : "",
4596 ansi_highlight_blue(),
4598 ansi_highlight_off());
4601 return copy_bytes(fd
, STDOUT_FILENO
, (off_t
) -1, false);
4604 static int cat(sd_bus
*bus
, char **args
) {
4605 _cleanup_free_
char *user_home
= NULL
;
4606 _cleanup_free_
char *user_runtime
= NULL
;
4607 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
4608 _cleanup_strv_free_
char **names
= NULL
;
4610 bool first
= true, avoid_bus_cache
;
4615 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
4616 log_error("Cannot remotely cat units");
4620 r
= init_home_and_lookup_paths(&user_home
, &user_runtime
, &lp
);
4624 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
4626 return log_error_errno(r
, "Failed to expand names: %m");
4628 avoid_bus_cache
= !bus
|| avoid_bus();
4630 pager_open_if_enabled();
4632 STRV_FOREACH(name
, names
) {
4633 _cleanup_free_
char *fragment_path
= NULL
;
4634 _cleanup_strv_free_
char **dropin_paths
= NULL
;
4637 r
= unit_find_paths(bus
, *name
, avoid_bus_cache
, &lp
, &fragment_path
, &dropin_paths
);
4648 if (fragment_path
) {
4649 r
= cat_file(fragment_path
, false);
4651 return log_warning_errno(r
, "Failed to cat %s: %m", fragment_path
);
4654 STRV_FOREACH(path
, dropin_paths
) {
4655 r
= cat_file(*path
, path
== dropin_paths
);
4657 return log_warning_errno(r
, "Failed to cat %s: %m", *path
);
4664 static int set_property(sd_bus
*bus
, char **args
) {
4665 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
4666 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4667 _cleanup_free_
char *n
= NULL
;
4671 polkit_agent_open_if_enabled();
4673 r
= sd_bus_message_new_method_call(
4676 "org.freedesktop.systemd1",
4677 "/org/freedesktop/systemd1",
4678 "org.freedesktop.systemd1.Manager",
4679 "SetUnitProperties");
4681 return bus_log_create_error(r
);
4683 r
= unit_name_mangle(args
[1], UNIT_NAME_NOGLOB
, &n
);
4685 return log_error_errno(r
, "Failed to mangle unit name: %m");
4687 r
= sd_bus_message_append(m
, "sb", n
, arg_runtime
);
4689 return bus_log_create_error(r
);
4691 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, "(sv)");
4693 return bus_log_create_error(r
);
4695 STRV_FOREACH(i
, args
+ 2) {
4696 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_STRUCT
, "sv");
4698 return bus_log_create_error(r
);
4700 r
= bus_append_unit_property_assignment(m
, *i
);
4704 r
= sd_bus_message_close_container(m
);
4706 return bus_log_create_error(r
);
4709 r
= sd_bus_message_close_container(m
);
4711 return bus_log_create_error(r
);
4713 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
4715 log_error("Failed to set unit properties on %s: %s", n
, bus_error_message(&error
, r
));
4722 static int snapshot(sd_bus
*bus
, char **args
) {
4723 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4724 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4725 _cleanup_free_
char *n
= NULL
, *id
= NULL
;
4729 polkit_agent_open_if_enabled();
4731 if (strv_length(args
) > 1) {
4732 r
= unit_name_mangle_with_suffix(args
[1], UNIT_NAME_NOGLOB
, ".snapshot", &n
);
4734 return log_error_errno(r
, "Failed to generate unit name: %m");
4741 r
= sd_bus_call_method(
4743 "org.freedesktop.systemd1",
4744 "/org/freedesktop/systemd1",
4745 "org.freedesktop.systemd1.Manager",
4751 log_error("Failed to create snapshot: %s", bus_error_message(&error
, r
));
4755 r
= sd_bus_message_read(reply
, "o", &path
);
4757 return bus_log_parse_error(r
);
4759 r
= sd_bus_get_property_string(
4761 "org.freedesktop.systemd1",
4763 "org.freedesktop.systemd1.Unit",
4768 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error
, r
));
4778 static int delete_snapshot(sd_bus
*bus
, char **args
) {
4779 _cleanup_strv_free_
char **names
= NULL
;
4785 polkit_agent_open_if_enabled();
4787 r
= expand_names(bus
, args
+ 1, ".snapshot", &names
);
4789 log_error_errno(r
, "Failed to expand names: %m");
4791 STRV_FOREACH(name
, names
) {
4792 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4795 q
= sd_bus_call_method(
4797 "org.freedesktop.systemd1",
4798 "/org/freedesktop/systemd1",
4799 "org.freedesktop.systemd1.Manager",
4805 log_error("Failed to remove snapshot %s: %s", *name
, bus_error_message(&error
, q
));
4814 static int daemon_reload(sd_bus
*bus
, char **args
) {
4815 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4819 polkit_agent_open_if_enabled();
4821 if (arg_action
== ACTION_RELOAD
)
4823 else if (arg_action
== ACTION_REEXEC
)
4824 method
= "Reexecute";
4826 assert(arg_action
== ACTION_SYSTEMCTL
);
4829 streq(args
[0], "clear-jobs") ||
4830 streq(args
[0], "cancel") ? "ClearJobs" :
4831 streq(args
[0], "daemon-reexec") ? "Reexecute" :
4832 streq(args
[0], "reset-failed") ? "ResetFailed" :
4833 streq(args
[0], "halt") ? "Halt" :
4834 streq(args
[0], "poweroff") ? "PowerOff" :
4835 streq(args
[0], "reboot") ? "Reboot" :
4836 streq(args
[0], "kexec") ? "KExec" :
4837 streq(args
[0], "exit") ? "Exit" :
4838 /* "daemon-reload" */ "Reload";
4841 r
= sd_bus_call_method(
4843 "org.freedesktop.systemd1",
4844 "/org/freedesktop/systemd1",
4845 "org.freedesktop.systemd1.Manager",
4850 if (r
== -ENOENT
&& arg_action
!= ACTION_SYSTEMCTL
)
4851 /* There's always a fallback possible for
4852 * legacy actions. */
4854 else if ((r
== -ETIMEDOUT
|| r
== -ECONNRESET
) && streq(method
, "Reexecute"))
4855 /* On reexecution, we expect a disconnect, not a
4859 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
4861 return r
< 0 ? r
: 0;
4864 static int reset_failed(sd_bus
*bus
, char **args
) {
4865 _cleanup_strv_free_
char **names
= NULL
;
4869 if (strv_length(args
) <= 1)
4870 return daemon_reload(bus
, args
);
4872 polkit_agent_open_if_enabled();
4874 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
4876 log_error_errno(r
, "Failed to expand names: %m");
4878 STRV_FOREACH(name
, names
) {
4879 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4881 q
= sd_bus_call_method(
4883 "org.freedesktop.systemd1",
4884 "/org/freedesktop/systemd1",
4885 "org.freedesktop.systemd1.Manager",
4891 log_error("Failed to reset failed state of unit %s: %s", *name
, bus_error_message(&error
, q
));
4900 static int show_environment(sd_bus
*bus
, char **args
) {
4901 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4902 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4906 pager_open_if_enabled();
4908 r
= sd_bus_get_property(
4910 "org.freedesktop.systemd1",
4911 "/org/freedesktop/systemd1",
4912 "org.freedesktop.systemd1.Manager",
4918 log_error("Failed to get environment: %s", bus_error_message(&error
, r
));
4922 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
4924 return bus_log_parse_error(r
);
4926 while ((r
= sd_bus_message_read_basic(reply
, SD_BUS_TYPE_STRING
, &text
)) > 0)
4929 return bus_log_parse_error(r
);
4931 r
= sd_bus_message_exit_container(reply
);
4933 return bus_log_parse_error(r
);
4938 static int switch_root(sd_bus
*bus
, char **args
) {
4939 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4940 _cleanup_free_
char *cmdline_init
= NULL
;
4941 const char *root
, *init
;
4945 l
= strv_length(args
);
4946 if (l
< 2 || l
> 3) {
4947 log_error("Wrong number of arguments.");
4956 r
= parse_env_file("/proc/cmdline", WHITESPACE
,
4957 "init", &cmdline_init
,
4960 log_debug_errno(r
, "Failed to parse /proc/cmdline: %m");
4962 init
= cmdline_init
;
4969 const char *root_systemd_path
= NULL
, *root_init_path
= NULL
;
4971 root_systemd_path
= strjoina(root
, "/" SYSTEMD_BINARY_PATH
);
4972 root_init_path
= strjoina(root
, "/", init
);
4974 /* If the passed init is actually the same as the
4975 * systemd binary, then let's suppress it. */
4976 if (files_same(root_init_path
, root_systemd_path
) > 0)
4980 log_debug("Switching root - root: %s; init: %s", root
, strna(init
));
4982 r
= sd_bus_call_method(
4984 "org.freedesktop.systemd1",
4985 "/org/freedesktop/systemd1",
4986 "org.freedesktop.systemd1.Manager",
4992 log_error("Failed to switch root: %s", bus_error_message(&error
, r
));
4999 static int set_environment(sd_bus
*bus
, char **args
) {
5000 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5001 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
5008 polkit_agent_open_if_enabled();
5010 method
= streq(args
[0], "set-environment")
5012 : "UnsetEnvironment";
5014 r
= sd_bus_message_new_method_call(
5017 "org.freedesktop.systemd1",
5018 "/org/freedesktop/systemd1",
5019 "org.freedesktop.systemd1.Manager",
5022 return bus_log_create_error(r
);
5024 r
= sd_bus_message_append_strv(m
, args
+ 1);
5026 return bus_log_create_error(r
);
5028 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5030 log_error("Failed to set environment: %s", bus_error_message(&error
, r
));
5037 static int import_environment(sd_bus
*bus
, char **args
) {
5038 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5039 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
5045 polkit_agent_open_if_enabled();
5047 r
= sd_bus_message_new_method_call(
5050 "org.freedesktop.systemd1",
5051 "/org/freedesktop/systemd1",
5052 "org.freedesktop.systemd1.Manager",
5055 return bus_log_create_error(r
);
5057 if (strv_isempty(args
+ 1))
5058 r
= sd_bus_message_append_strv(m
, environ
);
5062 r
= sd_bus_message_open_container(m
, 'a', "s");
5064 return bus_log_create_error(r
);
5066 STRV_FOREACH(a
, args
+ 1) {
5068 if (!env_name_is_valid(*a
)) {
5069 log_error("Not a valid environment variable name: %s", *a
);
5073 STRV_FOREACH(b
, environ
) {
5076 eq
= startswith(*b
, *a
);
5077 if (eq
&& *eq
== '=') {
5079 r
= sd_bus_message_append(m
, "s", *b
);
5081 return bus_log_create_error(r
);
5088 r
= sd_bus_message_close_container(m
);
5091 return bus_log_create_error(r
);
5093 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5095 log_error("Failed to import environment: %s", bus_error_message(&error
, r
));
5102 static int enable_sysv_units(const char *verb
, char **args
) {
5105 #if defined(HAVE_SYSV_COMPAT)
5107 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
5109 if (arg_scope
!= UNIT_FILE_SYSTEM
)
5112 if (!streq(verb
, "enable") &&
5113 !streq(verb
, "disable") &&
5114 !streq(verb
, "is-enabled"))
5117 /* Processes all SysV units, and reshuffles the array so that
5118 * afterwards only the native units remain */
5120 r
= lookup_paths_init(&paths
, MANAGER_SYSTEM
, false, arg_root
, NULL
, NULL
, NULL
);
5127 _cleanup_free_
char *p
= NULL
, *q
= NULL
, *l
= NULL
;
5128 bool found_native
= false, found_sysv
;
5130 const char *argv
[6] = { ROOTLIBEXECDIR
"/systemd-sysv-install", NULL
, NULL
, NULL
, NULL
};
5138 if (!endswith(name
, ".service"))
5141 if (path_is_absolute(name
))
5144 STRV_FOREACH(k
, paths
.unit_path
) {
5145 _cleanup_free_
char *path
= NULL
;
5147 path
= path_join(arg_root
, *k
, name
);
5151 found_native
= access(path
, F_OK
) >= 0;
5156 /* If we have both a native unit and a SysV script,
5157 * enable/disable them both (below); for is-enabled, prefer the
5159 if (found_native
&& streq(verb
, "is-enabled"))
5162 p
= path_join(arg_root
, SYSTEM_SYSVINIT_PATH
, name
);
5166 p
[strlen(p
) - strlen(".service")] = 0;
5167 found_sysv
= access(p
, F_OK
) >= 0;
5172 log_info("Synchronizing state of %s with SysV init with %s...", name
, argv
[0]);
5174 log_info("%s is not a native service, redirecting to systemd-sysv-install", name
);
5176 if (!isempty(arg_root
))
5177 argv
[c
++] = q
= strappend("--root=", arg_root
);
5180 argv
[c
++] = basename(p
);
5183 l
= strv_join((char**)argv
, " ");
5187 log_info("Executing %s", l
);
5191 return log_error_errno(errno
, "Failed to fork: %m");
5192 else if (pid
== 0) {
5195 (void) reset_all_signal_handlers();
5196 (void) reset_signal_mask();
5198 execv(argv
[0], (char**) argv
);
5199 log_error("Failed to execute %s: %m", argv
[0]);
5200 _exit(EXIT_FAILURE
);
5203 j
= wait_for_terminate(pid
, &status
);
5205 log_error_errno(r
, "Failed to wait for child: %m");
5209 if (status
.si_code
== CLD_EXITED
) {
5210 if (streq(verb
, "is-enabled")) {
5211 if (status
.si_status
== 0) {
5220 } else if (status
.si_status
!= 0)
5228 /* Remove this entry, so that we don't try enabling it as native unit */
5231 assert(args
[f
] == name
);
5232 strv_remove(args
, name
);
5239 static int mangle_names(char **original_names
, char ***mangled_names
) {
5240 char **i
, **l
, **name
;
5243 l
= i
= new(char*, strv_length(original_names
) + 1);
5247 STRV_FOREACH(name
, original_names
) {
5249 /* When enabling units qualified path names are OK,
5250 * too, hence allow them explicitly. */
5252 if (is_path(*name
)) {
5259 r
= unit_name_mangle(*name
, UNIT_NAME_NOGLOB
, i
);
5262 return log_error_errno(r
, "Failed to mangle unit name: %m");
5275 static int enable_unit(sd_bus
*bus
, char **args
) {
5276 _cleanup_strv_free_
char **names
= NULL
;
5277 const char *verb
= args
[0];
5278 UnitFileChange
*changes
= NULL
;
5279 unsigned n_changes
= 0;
5280 int carries_install_info
= -1;
5286 r
= mangle_names(args
+1, &names
);
5290 r
= enable_sysv_units(verb
, names
);
5294 /* If the operation was fully executed by the SysV compat,
5295 * let's finish early */
5296 if (strv_isempty(names
))
5299 if (!bus
|| avoid_bus()) {
5300 if (streq(verb
, "enable")) {
5301 r
= unit_file_enable(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5302 carries_install_info
= r
;
5303 } else if (streq(verb
, "disable"))
5304 r
= unit_file_disable(arg_scope
, arg_runtime
, arg_root
, names
, &changes
, &n_changes
);
5305 else if (streq(verb
, "reenable")) {
5306 r
= unit_file_reenable(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5307 carries_install_info
= r
;
5308 } else if (streq(verb
, "link"))
5309 r
= unit_file_link(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5310 else if (streq(verb
, "preset")) {
5311 r
= unit_file_preset(arg_scope
, arg_runtime
, arg_root
, names
, arg_preset_mode
, arg_force
, &changes
, &n_changes
);
5312 carries_install_info
= r
;
5313 } else if (streq(verb
, "mask"))
5314 r
= unit_file_mask(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5315 else if (streq(verb
, "unmask"))
5316 r
= unit_file_unmask(arg_scope
, arg_runtime
, arg_root
, names
, &changes
, &n_changes
);
5318 assert_not_reached("Unknown verb");
5321 log_error_errno(r
, "Operation failed: %m");
5326 dump_unit_file_changes(changes
, n_changes
);
5330 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
, *m
= NULL
;
5331 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5332 int expect_carries_install_info
= false;
5333 bool send_force
= true, send_preset_mode
= false;
5336 polkit_agent_open_if_enabled();
5338 if (streq(verb
, "enable")) {
5339 method
= "EnableUnitFiles";
5340 expect_carries_install_info
= true;
5341 } else if (streq(verb
, "disable")) {
5342 method
= "DisableUnitFiles";
5344 } else if (streq(verb
, "reenable")) {
5345 method
= "ReenableUnitFiles";
5346 expect_carries_install_info
= true;
5347 } else if (streq(verb
, "link"))
5348 method
= "LinkUnitFiles";
5349 else if (streq(verb
, "preset")) {
5351 if (arg_preset_mode
!= UNIT_FILE_PRESET_FULL
) {
5352 method
= "PresetUnitFilesWithMode";
5353 send_preset_mode
= true;
5355 method
= "PresetUnitFiles";
5357 expect_carries_install_info
= true;
5358 } else if (streq(verb
, "mask"))
5359 method
= "MaskUnitFiles";
5360 else if (streq(verb
, "unmask")) {
5361 method
= "UnmaskUnitFiles";
5364 assert_not_reached("Unknown verb");
5366 r
= sd_bus_message_new_method_call(
5369 "org.freedesktop.systemd1",
5370 "/org/freedesktop/systemd1",
5371 "org.freedesktop.systemd1.Manager",
5374 return bus_log_create_error(r
);
5376 r
= sd_bus_message_append_strv(m
, names
);
5378 return bus_log_create_error(r
);
5380 if (send_preset_mode
) {
5381 r
= sd_bus_message_append(m
, "s", unit_file_preset_mode_to_string(arg_preset_mode
));
5383 return bus_log_create_error(r
);
5386 r
= sd_bus_message_append(m
, "b", arg_runtime
);
5388 return bus_log_create_error(r
);
5391 r
= sd_bus_message_append(m
, "b", arg_force
);
5393 return bus_log_create_error(r
);
5396 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
5398 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
5402 if (expect_carries_install_info
) {
5403 r
= sd_bus_message_read(reply
, "b", &carries_install_info
);
5405 return bus_log_parse_error(r
);
5408 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
5412 /* Try to reload if enabled */
5414 r
= daemon_reload(bus
, args
);
5419 if (carries_install_info
== 0)
5420 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5421 "using systemctl.\n"
5422 "Possible reasons for having this kind of units are:\n"
5423 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5424 " .wants/ or .requires/ directory.\n"
5425 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5426 " a requirement dependency on it.\n"
5427 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5428 " D-Bus, udev, scripted systemctl call, ...).\n");
5430 if (arg_now
&& n_changes
> 0 && STR_IN_SET(args
[0], "enable", "disable", "mask")) {
5431 char *new_args
[n_changes
+ 2];
5434 new_args
[0] = streq(args
[0], "enable") ? (char *)"start" : (char *)"stop";
5435 for (i
= 0; i
< n_changes
; i
++)
5436 new_args
[i
+ 1] = basename(changes
[i
].path
);
5437 new_args
[i
+ 1] = NULL
;
5439 r
= start_unit(bus
, new_args
);
5443 unit_file_changes_free(changes
, n_changes
);
5448 static int add_dependency(sd_bus
*bus
, char **args
) {
5449 _cleanup_strv_free_
char **names
= NULL
;
5450 _cleanup_free_
char *target
= NULL
;
5451 const char *verb
= args
[0];
5458 r
= unit_name_mangle_with_suffix(args
[1], UNIT_NAME_NOGLOB
, ".target", &target
);
5460 return log_error_errno(r
, "Failed to mangle unit name: %m");
5462 r
= mangle_names(args
+2, &names
);
5466 if (streq(verb
, "add-wants"))
5468 else if (streq(verb
, "add-requires"))
5469 dep
= UNIT_REQUIRES
;
5471 assert_not_reached("Unknown verb");
5473 if (!bus
|| avoid_bus()) {
5474 UnitFileChange
*changes
= NULL
;
5475 unsigned n_changes
= 0;
5477 r
= unit_file_add_dependency(arg_scope
, arg_runtime
, arg_root
, names
, target
, dep
, arg_force
, &changes
, &n_changes
);
5480 return log_error_errno(r
, "Can't add dependency: %m");
5483 dump_unit_file_changes(changes
, n_changes
);
5485 unit_file_changes_free(changes
, n_changes
);
5488 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
, *m
= NULL
;
5489 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5491 polkit_agent_open_if_enabled();
5493 r
= sd_bus_message_new_method_call(
5496 "org.freedesktop.systemd1",
5497 "/org/freedesktop/systemd1",
5498 "org.freedesktop.systemd1.Manager",
5499 "AddDependencyUnitFiles");
5501 return bus_log_create_error(r
);
5503 r
= sd_bus_message_append_strv(m
, names
);
5505 return bus_log_create_error(r
);
5507 r
= sd_bus_message_append(m
, "ssbb", target
, unit_dependency_to_string(dep
), arg_runtime
, arg_force
);
5509 return bus_log_create_error(r
);
5511 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
5513 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
5517 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, NULL
, NULL
);
5522 r
= daemon_reload(bus
, args
);
5530 static int preset_all(sd_bus
*bus
, char **args
) {
5531 UnitFileChange
*changes
= NULL
;
5532 unsigned n_changes
= 0;
5535 if (!bus
|| avoid_bus()) {
5537 r
= unit_file_preset_all(arg_scope
, arg_runtime
, arg_root
, arg_preset_mode
, arg_force
, &changes
, &n_changes
);
5539 log_error_errno(r
, "Operation failed: %m");
5544 dump_unit_file_changes(changes
, n_changes
);
5549 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5550 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
5552 polkit_agent_open_if_enabled();
5554 r
= sd_bus_call_method(
5556 "org.freedesktop.systemd1",
5557 "/org/freedesktop/systemd1",
5558 "org.freedesktop.systemd1.Manager",
5559 "PresetAllUnitFiles",
5563 unit_file_preset_mode_to_string(arg_preset_mode
),
5567 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
5571 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, NULL
, NULL
);
5576 r
= daemon_reload(bus
, args
);
5582 unit_file_changes_free(changes
, n_changes
);
5587 static int unit_is_enabled(sd_bus
*bus
, char **args
) {
5589 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5590 _cleanup_strv_free_
char **names
= NULL
;
5595 r
= mangle_names(args
+1, &names
);
5599 r
= enable_sysv_units(args
[0], names
);
5605 if (!bus
|| avoid_bus()) {
5607 STRV_FOREACH(name
, names
) {
5608 UnitFileState state
;
5610 state
= unit_file_get_state(arg_scope
, arg_root
, *name
);
5612 return log_error_errno(state
, "Failed to get unit file state for %s: %m", *name
);
5614 if (state
== UNIT_FILE_ENABLED
||
5615 state
== UNIT_FILE_ENABLED_RUNTIME
||
5616 state
== UNIT_FILE_STATIC
||
5617 state
== UNIT_FILE_INDIRECT
)
5621 puts(unit_file_state_to_string(state
));
5625 STRV_FOREACH(name
, names
) {
5626 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
5629 r
= sd_bus_call_method(
5631 "org.freedesktop.systemd1",
5632 "/org/freedesktop/systemd1",
5633 "org.freedesktop.systemd1.Manager",
5639 log_error("Failed to get unit file state for %s: %s", *name
, bus_error_message(&error
, r
));
5643 r
= sd_bus_message_read(reply
, "s", &s
);
5645 return bus_log_parse_error(r
);
5647 if (STR_IN_SET(s
, "enabled", "enabled-runtime", "static", "indirect"))
5658 static int is_system_running(sd_bus
*bus
, char **args
) {
5659 _cleanup_free_
char *state
= NULL
;
5662 r
= sd_bus_get_property_string(
5664 "org.freedesktop.systemd1",
5665 "/org/freedesktop/systemd1",
5666 "org.freedesktop.systemd1.Manager",
5679 return streq(state
, "running") ? EXIT_SUCCESS
: EXIT_FAILURE
;
5682 static int create_edit_temp_file(const char *new_path
, const char *original_path
, char **ret_tmp_fn
) {
5687 assert(original_path
);
5690 r
= tempfn_random(new_path
, &t
);
5692 return log_error_errno(r
, "Failed to determine temporary filename for \"%s\": %m", new_path
);
5694 r
= mkdir_parents(new_path
, 0755);
5696 log_error_errno(r
, "Failed to create directories for \"%s\": %m", new_path
);
5701 r
= copy_file(original_path
, t
, 0, 0644, 0);
5705 log_error_errno(r
, "Failed to create temporary file \"%s\": %m", t
);
5710 log_error_errno(r
, "Failed to copy \"%s\" to \"%s\": %m", original_path
, t
);
5720 static int get_file_to_edit(const char *name
, const char *user_home
, const char *user_runtime
, char **ret_path
) {
5721 _cleanup_free_
char *path
= NULL
, *path2
= NULL
, *run
= NULL
;
5723 switch (arg_scope
) {
5724 case UNIT_FILE_SYSTEM
:
5725 path
= path_join(arg_root
, SYSTEM_CONFIG_UNIT_PATH
, name
);
5727 run
= path_join(arg_root
, "/run/systemd/system/", name
);
5729 case UNIT_FILE_GLOBAL
:
5730 path
= path_join(arg_root
, USER_CONFIG_UNIT_PATH
, name
);
5732 run
= path_join(arg_root
, "/run/systemd/user/", name
);
5734 case UNIT_FILE_USER
:
5736 assert(user_runtime
);
5738 path
= path_join(arg_root
, user_home
, name
);
5740 path2
= path_join(arg_root
, USER_CONFIG_UNIT_PATH
, name
);
5743 run
= path_join(arg_root
, user_runtime
, name
);
5747 assert_not_reached("Invalid scope");
5749 if (!path
|| (arg_runtime
&& !run
))
5753 if (access(path
, F_OK
) >= 0)
5754 return log_error_errno(EEXIST
, "Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.",
5756 if (path2
&& access(path2
, F_OK
) >= 0)
5757 return log_error_errno(EEXIST
, "Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.",
5769 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
) {
5770 char *tmp_new_path
, *ending
;
5775 assert(ret_new_path
);
5776 assert(ret_tmp_path
);
5778 ending
= strjoina(unit_name
, ".d/override.conf");
5779 r
= get_file_to_edit(ending
, user_home
, user_runtime
, &tmp_new_path
);
5783 r
= create_edit_temp_file(tmp_new_path
, tmp_new_path
, &tmp_tmp_path
);
5789 *ret_new_path
= tmp_new_path
;
5790 *ret_tmp_path
= tmp_tmp_path
;
5795 static int unit_file_create_copy(
5796 const char *unit_name
,
5797 const char *fragment_path
,
5798 const char *user_home
,
5799 const char *user_runtime
,
5800 char **ret_new_path
,
5801 char **ret_tmp_path
) {
5807 assert(fragment_path
);
5809 assert(ret_new_path
);
5810 assert(ret_tmp_path
);
5812 r
= get_file_to_edit(unit_name
, user_home
, user_runtime
, &tmp_new_path
);
5816 if (!path_equal(fragment_path
, tmp_new_path
) && access(tmp_new_path
, F_OK
) == 0) {
5819 r
= ask_char(&response
, "yn", "\"%s\" already exists. Overwrite with \"%s\"? [(y)es, (n)o] ", tmp_new_path
, fragment_path
);
5824 if (response
!= 'y') {
5825 log_warning("%s ignored", unit_name
);
5831 r
= create_edit_temp_file(tmp_new_path
, fragment_path
, &tmp_tmp_path
);
5833 log_error_errno(r
, "Failed to create temporary file for \"%s\": %m", tmp_new_path
);
5838 *ret_new_path
= tmp_new_path
;
5839 *ret_tmp_path
= tmp_tmp_path
;
5844 static int run_editor(char **paths
) {
5852 log_error_errno(errno
, "Failed to fork: %m");
5859 char **tmp_path
, **original_path
, *p
;
5863 (void) reset_all_signal_handlers();
5864 (void) reset_signal_mask();
5866 argc
= strv_length(paths
)/2 + 1;
5867 args
= newa(const char*, argc
+ 1);
5870 STRV_FOREACH_PAIR(original_path
, tmp_path
, paths
) {
5871 args
[i
] = *tmp_path
;
5876 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
5877 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
5878 * we try to execute well known editors
5880 editor
= getenv("SYSTEMD_EDITOR");
5882 editor
= getenv("EDITOR");
5884 editor
= getenv("VISUAL");
5886 if (!isempty(editor
)) {
5888 execvp(editor
, (char* const*) args
);
5891 FOREACH_STRING(p
, "editor", "nano", "vim", "vi") {
5893 execvp(p
, (char* const*) args
);
5894 /* We do not fail if the editor doesn't exist
5895 * because we want to try each one of them before
5898 if (errno
!= ENOENT
) {
5899 log_error("Failed to execute %s: %m", editor
);
5900 _exit(EXIT_FAILURE
);
5904 log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR, $EDITOR or $VISUAL.");
5905 _exit(EXIT_FAILURE
);
5908 r
= wait_for_terminate_and_warn("editor", pid
, true);
5910 return log_error_errno(r
, "Failed to wait for child: %m");
5915 static int find_paths_to_edit(sd_bus
*bus
, char **names
, char ***paths
) {
5916 _cleanup_free_
char *user_home
= NULL
;
5917 _cleanup_free_
char *user_runtime
= NULL
;
5918 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
5919 bool avoid_bus_cache
;
5926 r
= init_home_and_lookup_paths(&user_home
, &user_runtime
, &lp
);
5930 avoid_bus_cache
= !bus
|| avoid_bus();
5932 STRV_FOREACH(name
, names
) {
5933 _cleanup_free_
char *path
= NULL
;
5934 char *new_path
, *tmp_path
;
5936 r
= unit_find_paths(bus
, *name
, avoid_bus_cache
, &lp
, &path
, NULL
);
5942 // FIXME: support units with path==NULL (no FragmentPath)
5943 log_error("No fragment exists for %s.", *name
);
5948 r
= unit_file_create_copy(*name
, path
, user_home
, user_runtime
, &new_path
, &tmp_path
);
5950 r
= unit_file_create_dropin(*name
, user_home
, user_runtime
, &new_path
, &tmp_path
);
5954 r
= strv_push_pair(paths
, new_path
, tmp_path
);
5962 static int edit(sd_bus
*bus
, char **args
) {
5963 _cleanup_strv_free_
char **names
= NULL
;
5964 _cleanup_strv_free_
char **paths
= NULL
;
5965 char **original
, **tmp
;
5971 log_error("Cannot edit units if not on a tty");
5975 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
5976 log_error("Cannot remotely edit units");
5980 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
5982 return log_error_errno(r
, "Failed to expand names: %m");
5984 r
= find_paths_to_edit(bus
, names
, &paths
);
5988 if (strv_isempty(paths
))
5991 r
= run_editor(paths
);
5995 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
5996 /* If the temporary file is empty we ignore it.
5997 * It's useful if the user wants to cancel its modification
5999 if (null_or_empty_path(*tmp
)) {
6000 log_warning("Editing \"%s\" canceled: temporary file is empty", *original
);
6003 r
= rename(*tmp
, *original
);
6005 r
= log_error_errno(errno
, "Failed to rename \"%s\" to \"%s\": %m", *tmp
, *original
);
6010 if (!arg_no_reload
&& bus
&& !avoid_bus())
6011 r
= daemon_reload(bus
, args
);
6014 STRV_FOREACH_PAIR(original
, tmp
, paths
)
6015 unlink_noerrno(*tmp
);
6020 static void systemctl_help(void) {
6022 pager_open_if_enabled();
6024 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
6025 "Query or send control commands to the systemd manager.\n\n"
6026 " -h --help Show this help\n"
6027 " --version Show package version\n"
6028 " --system Connect to system manager\n"
6029 " --user Connect to user service manager\n"
6030 " -H --host=[USER@]HOST\n"
6031 " Operate on remote host\n"
6032 " -M --machine=CONTAINER\n"
6033 " Operate on local container\n"
6034 " -t --type=TYPE List units of a particular type\n"
6035 " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n"
6036 " -p --property=NAME Show only properties by this name\n"
6037 " -a --all Show all loaded units/properties, including dead/empty\n"
6038 " ones. To list all units installed on the system, use\n"
6039 " the 'list-unit-files' command instead.\n"
6040 " -l --full Don't ellipsize unit names on output\n"
6041 " -r --recursive Show unit list of host and local containers\n"
6042 " --reverse Show reverse dependencies with 'list-dependencies'\n"
6043 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
6044 " queueing a new job\n"
6045 " --show-types When showing sockets, explicitly show their type\n"
6046 " -i --ignore-inhibitors\n"
6047 " When shutting down or sleeping, ignore inhibitors\n"
6048 " --kill-who=WHO Who to send signal to\n"
6049 " -s --signal=SIGNAL Which signal to send\n"
6050 " --now Start or stop unit in addition to enabling or disabling it\n"
6051 " -q --quiet Suppress output\n"
6052 " --no-block Do not wait until operation finished\n"
6053 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6054 " --no-reload Don't reload daemon after en-/dis-abling unit files\n"
6055 " --no-legend Do not print a legend (column headers and hints)\n"
6056 " --no-pager Do not pipe output into a pager\n"
6057 " --no-ask-password\n"
6058 " Do not ask for system passwords\n"
6059 " --global Enable/disable unit files globally\n"
6060 " --runtime Enable unit files only temporarily until next reboot\n"
6061 " -f --force When enabling unit files, override existing symlinks\n"
6062 " When shutting down, execute action immediately\n"
6063 " --preset-mode= Apply only enable, only disable, or all presets\n"
6064 " --root=PATH Enable unit files in the specified root directory\n"
6065 " -n --lines=INTEGER Number of journal entries to show\n"
6066 " -o --output=STRING Change journal output mode (short, short-iso,\n"
6067 " short-precise, short-monotonic, verbose,\n"
6068 " export, json, json-pretty, json-sse, cat)\n"
6069 " --firmware-setup Tell the firmware to show the setup menu on next boot\n"
6070 " --plain Print unit dependencies as a list instead of a tree\n\n"
6072 " list-units [PATTERN...] List loaded units\n"
6073 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
6074 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
6075 " start NAME... Start (activate) one or more units\n"
6076 " stop NAME... Stop (deactivate) one or more units\n"
6077 " reload NAME... Reload one or more units\n"
6078 " restart NAME... Start or restart one or more units\n"
6079 " try-restart NAME... Restart one or more units if active\n"
6080 " reload-or-restart NAME... Reload one or more units if possible,\n"
6081 " otherwise start or restart\n"
6082 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
6083 " otherwise restart if active\n"
6084 " isolate NAME Start one unit and stop all others\n"
6085 " kill NAME... Send signal to processes of a unit\n"
6086 " is-active PATTERN... Check whether units are active\n"
6087 " is-failed PATTERN... Check whether units are failed\n"
6088 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
6089 " show [PATTERN...|JOB...] Show properties of one or more\n"
6090 " units/jobs or the manager\n"
6091 " cat PATTERN... Show files and drop-ins of one or more units\n"
6092 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
6093 " help PATTERN...|PID... Show manual for one or more units\n"
6094 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
6096 " list-dependencies [NAME] Recursively show units which are required\n"
6097 " or wanted by this unit or by which this\n"
6098 " unit is required or wanted\n\n"
6099 "Unit File Commands:\n"
6100 " list-unit-files [PATTERN...] List installed unit files\n"
6101 " enable NAME... Enable one or more unit files\n"
6102 " disable NAME... Disable one or more unit files\n"
6103 " reenable NAME... Reenable one or more unit files\n"
6104 " preset NAME... Enable/disable one or more unit files\n"
6105 " based on preset configuration\n"
6106 " preset-all Enable/disable all unit files based on\n"
6107 " preset configuration\n"
6108 " is-enabled NAME... Check whether unit files are enabled\n"
6109 " mask NAME... Mask one or more units\n"
6110 " unmask NAME... Unmask one or more units\n"
6111 " link PATH... Link one or more units files into\n"
6112 " the search path\n"
6113 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
6114 " on specified one or more units\n"
6115 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
6116 " on specified one or more units\n"
6117 " edit NAME... Edit one or more unit files\n"
6118 " get-default Get the name of the default target\n"
6119 " set-default NAME Set the default target\n\n"
6120 "Machine Commands:\n"
6121 " list-machines [PATTERN...] List local containers and host\n\n"
6123 " list-jobs [PATTERN...] List jobs\n"
6124 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
6125 "Snapshot Commands:\n"
6126 " snapshot [NAME] Create a snapshot\n"
6127 " delete NAME... Remove one or more snapshots\n\n"
6128 "Environment Commands:\n"
6129 " show-environment Dump environment\n"
6130 " set-environment NAME=VALUE... Set one or more environment variables\n"
6131 " unset-environment NAME... Unset one or more environment variables\n"
6132 " import-environment [NAME...] Import all or some environment variables\n\n"
6133 "Manager Lifecycle Commands:\n"
6134 " daemon-reload Reload systemd manager configuration\n"
6135 " daemon-reexec Reexecute systemd manager\n\n"
6136 "System Commands:\n"
6137 " is-system-running Check whether system is fully running\n"
6138 " default Enter system default mode\n"
6139 " rescue Enter system rescue mode\n"
6140 " emergency Enter system emergency mode\n"
6141 " halt Shut down and halt the system\n"
6142 " poweroff Shut down and power-off the system\n"
6143 " reboot [ARG] Shut down and reboot the system\n"
6144 " kexec Shut down and reboot the system with kexec\n"
6145 " exit Request user instance exit\n"
6146 " switch-root ROOT [INIT] Change to a different root file system\n"
6147 " suspend Suspend the system\n"
6148 " hibernate Hibernate the system\n"
6149 " hybrid-sleep Hibernate and suspend the system\n",
6150 program_invocation_short_name
);
6153 static void halt_help(void) {
6154 printf("%s [OPTIONS...]%s\n\n"
6155 "%s the system.\n\n"
6156 " --help Show this help\n"
6157 " --halt Halt the machine\n"
6158 " -p --poweroff Switch off the machine\n"
6159 " --reboot Reboot the machine\n"
6160 " -f --force Force immediate halt/power-off/reboot\n"
6161 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
6162 " -d --no-wtmp Don't write wtmp record\n"
6163 " --no-wall Don't send wall message before halt/power-off/reboot\n",
6164 program_invocation_short_name
,
6165 arg_action
== ACTION_REBOOT
? " [ARG]" : "",
6166 arg_action
== ACTION_REBOOT
? "Reboot" :
6167 arg_action
== ACTION_POWEROFF
? "Power off" :
6171 static void shutdown_help(void) {
6172 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
6173 "Shut down the system.\n\n"
6174 " --help Show this help\n"
6175 " -H --halt Halt the machine\n"
6176 " -P --poweroff Power-off the machine\n"
6177 " -r --reboot Reboot the machine\n"
6178 " -h Equivalent to --poweroff, overridden by --halt\n"
6179 " -k Don't halt/power-off/reboot, just send warnings\n"
6180 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6181 " -c Cancel a pending shutdown\n",
6182 program_invocation_short_name
);
6185 static void telinit_help(void) {
6186 printf("%s [OPTIONS...] {COMMAND}\n\n"
6187 "Send control commands to the init daemon.\n\n"
6188 " --help Show this help\n"
6189 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
6191 " 0 Power-off the machine\n"
6192 " 6 Reboot the machine\n"
6193 " 2, 3, 4, 5 Start runlevelX.target unit\n"
6194 " 1, s, S Enter rescue mode\n"
6195 " q, Q Reload init daemon configuration\n"
6196 " u, U Reexecute init daemon\n",
6197 program_invocation_short_name
);
6200 static void runlevel_help(void) {
6201 printf("%s [OPTIONS...]\n\n"
6202 "Prints the previous and current runlevel of the init system.\n\n"
6203 " --help Show this help\n",
6204 program_invocation_short_name
);
6207 static void help_types(void) {
6212 puts("Available unit types:");
6213 for (i
= 0; i
< _UNIT_TYPE_MAX
; i
++) {
6214 t
= unit_type_to_string(i
);
6220 static int systemctl_parse_argv(int argc
, char *argv
[]) {
6229 ARG_IGNORE_DEPENDENCIES
,
6241 ARG_NO_ASK_PASSWORD
,
6253 static const struct option options
[] = {
6254 { "help", no_argument
, NULL
, 'h' },
6255 { "version", no_argument
, NULL
, ARG_VERSION
},
6256 { "type", required_argument
, NULL
, 't' },
6257 { "property", required_argument
, NULL
, 'p' },
6258 { "all", no_argument
, NULL
, 'a' },
6259 { "reverse", no_argument
, NULL
, ARG_REVERSE
},
6260 { "after", no_argument
, NULL
, ARG_AFTER
},
6261 { "before", no_argument
, NULL
, ARG_BEFORE
},
6262 { "show-types", no_argument
, NULL
, ARG_SHOW_TYPES
},
6263 { "failed", no_argument
, NULL
, ARG_FAILED
}, /* compatibility only */
6264 { "full", no_argument
, NULL
, 'l' },
6265 { "job-mode", required_argument
, NULL
, ARG_JOB_MODE
},
6266 { "fail", no_argument
, NULL
, ARG_FAIL
}, /* compatibility only */
6267 { "irreversible", no_argument
, NULL
, ARG_IRREVERSIBLE
}, /* compatibility only */
6268 { "ignore-dependencies", no_argument
, NULL
, ARG_IGNORE_DEPENDENCIES
}, /* compatibility only */
6269 { "ignore-inhibitors", no_argument
, NULL
, 'i' },
6270 { "user", no_argument
, NULL
, ARG_USER
},
6271 { "system", no_argument
, NULL
, ARG_SYSTEM
},
6272 { "global", no_argument
, NULL
, ARG_GLOBAL
},
6273 { "no-block", no_argument
, NULL
, ARG_NO_BLOCK
},
6274 { "no-legend", no_argument
, NULL
, ARG_NO_LEGEND
},
6275 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
6276 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6277 { "quiet", no_argument
, NULL
, 'q' },
6278 { "root", required_argument
, NULL
, ARG_ROOT
},
6279 { "force", no_argument
, NULL
, ARG_FORCE
},
6280 { "no-reload", no_argument
, NULL
, ARG_NO_RELOAD
},
6281 { "kill-who", required_argument
, NULL
, ARG_KILL_WHO
},
6282 { "signal", required_argument
, NULL
, 's' },
6283 { "no-ask-password", no_argument
, NULL
, ARG_NO_ASK_PASSWORD
},
6284 { "host", required_argument
, NULL
, 'H' },
6285 { "machine", required_argument
, NULL
, 'M' },
6286 { "runtime", no_argument
, NULL
, ARG_RUNTIME
},
6287 { "lines", required_argument
, NULL
, 'n' },
6288 { "output", required_argument
, NULL
, 'o' },
6289 { "plain", no_argument
, NULL
, ARG_PLAIN
},
6290 { "state", required_argument
, NULL
, ARG_STATE
},
6291 { "recursive", no_argument
, NULL
, 'r' },
6292 { "preset-mode", required_argument
, NULL
, ARG_PRESET_MODE
},
6293 { "firmware-setup", no_argument
, NULL
, ARG_FIRMWARE_SETUP
},
6294 { "now", no_argument
, NULL
, ARG_NOW
},
6303 while ((c
= getopt_long(argc
, argv
, "ht:p:alqfs:H:M:n:o:ir", options
, NULL
)) >= 0)
6312 puts(PACKAGE_STRING
);
6313 puts(SYSTEMD_FEATURES
);
6317 const char *word
, *state
;
6320 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
6321 _cleanup_free_
char *type
;
6323 type
= strndup(word
, size
);
6327 if (streq(type
, "help")) {
6332 if (unit_type_from_string(type
) >= 0) {
6333 if (strv_push(&arg_types
, type
))
6339 /* It's much nicer to use --state= for
6340 * load states, but let's support this
6341 * in --types= too for compatibility
6342 * with old versions */
6343 if (unit_load_state_from_string(optarg
) >= 0) {
6344 if (strv_push(&arg_states
, type
) < 0)
6350 log_error("Unknown unit type or load state '%s'.", type
);
6351 log_info("Use -t help to see a list of allowed values.");
6359 /* Make sure that if the empty property list
6360 was specified, we won't show any properties. */
6361 if (isempty(optarg
) && !arg_properties
) {
6362 arg_properties
= new0(char*, 1);
6363 if (!arg_properties
)
6366 const char *word
, *state
;
6369 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
6372 prop
= strndup(word
, size
);
6376 if (strv_consume(&arg_properties
, prop
) < 0)
6381 /* If the user asked for a particular
6382 * property, show it to him, even if it is
6394 arg_dependency
= DEPENDENCY_REVERSE
;
6398 arg_dependency
= DEPENDENCY_AFTER
;
6402 arg_dependency
= DEPENDENCY_BEFORE
;
6405 case ARG_SHOW_TYPES
:
6406 arg_show_types
= true;
6410 arg_job_mode
= optarg
;
6414 arg_job_mode
= "fail";
6417 case ARG_IRREVERSIBLE
:
6418 arg_job_mode
= "replace-irreversibly";
6421 case ARG_IGNORE_DEPENDENCIES
:
6422 arg_job_mode
= "ignore-dependencies";
6426 arg_scope
= UNIT_FILE_USER
;
6430 arg_scope
= UNIT_FILE_SYSTEM
;
6434 arg_scope
= UNIT_FILE_GLOBAL
;
6438 arg_no_block
= true;
6442 arg_no_legend
= true;
6446 arg_no_pager
= true;
6462 if (strv_extend(&arg_states
, "failed") < 0)
6480 arg_no_reload
= true;
6484 arg_kill_who
= optarg
;
6488 if ((arg_signal
= signal_from_string_try_harder(optarg
)) < 0) {
6489 log_error("Failed to parse signal string %s.", optarg
);
6494 case ARG_NO_ASK_PASSWORD
:
6495 arg_ask_password
= false;
6499 arg_transport
= BUS_TRANSPORT_REMOTE
;
6504 arg_transport
= BUS_TRANSPORT_MACHINE
;
6513 if (safe_atou(optarg
, &arg_lines
) < 0) {
6514 log_error("Failed to parse lines '%s'", optarg
);
6520 arg_output
= output_mode_from_string(optarg
);
6521 if (arg_output
< 0) {
6522 log_error("Unknown output '%s'.", optarg
);
6528 arg_ignore_inhibitors
= true;
6535 case ARG_FIRMWARE_SETUP
:
6536 arg_firmware_setup
= true;
6540 const char *word
, *state
;
6543 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
6546 s
= strndup(word
, size
);
6550 if (strv_consume(&arg_states
, s
) < 0)
6557 if (geteuid() != 0) {
6558 log_error("--recursive requires root privileges.");
6562 arg_recursive
= true;
6565 case ARG_PRESET_MODE
:
6567 arg_preset_mode
= unit_file_preset_mode_from_string(optarg
);
6568 if (arg_preset_mode
< 0) {
6569 log_error("Failed to parse preset mode: %s.", optarg
);
6583 assert_not_reached("Unhandled option");
6586 if (arg_transport
!= BUS_TRANSPORT_LOCAL
&& arg_scope
!= UNIT_FILE_SYSTEM
) {
6587 log_error("Cannot access user instance remotely.");
6594 static int halt_parse_argv(int argc
, char *argv
[]) {
6603 static const struct option options
[] = {
6604 { "help", no_argument
, NULL
, ARG_HELP
},
6605 { "halt", no_argument
, NULL
, ARG_HALT
},
6606 { "poweroff", no_argument
, NULL
, 'p' },
6607 { "reboot", no_argument
, NULL
, ARG_REBOOT
},
6608 { "force", no_argument
, NULL
, 'f' },
6609 { "wtmp-only", no_argument
, NULL
, 'w' },
6610 { "no-wtmp", no_argument
, NULL
, 'd' },
6611 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6620 if (utmp_get_runlevel(&runlevel
, NULL
) >= 0)
6621 if (runlevel
== '0' || runlevel
== '6')
6624 while ((c
= getopt_long(argc
, argv
, "pfwdnih", options
, NULL
)) >= 0)
6632 arg_action
= ACTION_HALT
;
6636 if (arg_action
!= ACTION_REBOOT
)
6637 arg_action
= ACTION_POWEROFF
;
6641 arg_action
= ACTION_REBOOT
;
6663 /* Compatibility nops */
6670 assert_not_reached("Unhandled option");
6673 if (arg_action
== ACTION_REBOOT
&& (argc
== optind
|| argc
== optind
+ 1)) {
6674 r
= update_reboot_param_file(argc
== optind
+ 1 ? argv
[optind
] : NULL
);
6677 } else if (optind
< argc
) {
6678 log_error("Too many arguments.");
6685 static int parse_time_spec(const char *t
, usec_t
*_u
) {
6689 if (streq(t
, "now"))
6691 else if (!strchr(t
, ':')) {
6694 if (safe_atou64(t
, &u
) < 0)
6697 *_u
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
* u
;
6706 hour
= strtol(t
, &e
, 10);
6707 if (errno
> 0 || *e
!= ':' || hour
< 0 || hour
> 23)
6710 minute
= strtol(e
+1, &e
, 10);
6711 if (errno
> 0 || *e
!= 0 || minute
< 0 || minute
> 59)
6714 n
= now(CLOCK_REALTIME
);
6715 s
= (time_t) (n
/ USEC_PER_SEC
);
6717 assert_se(localtime_r(&s
, &tm
));
6719 tm
.tm_hour
= (int) hour
;
6720 tm
.tm_min
= (int) minute
;
6723 assert_se(s
= mktime(&tm
));
6725 *_u
= (usec_t
) s
* USEC_PER_SEC
;
6728 *_u
+= USEC_PER_DAY
;
6734 static int shutdown_parse_argv(int argc
, char *argv
[]) {
6741 static const struct option options
[] = {
6742 { "help", no_argument
, NULL
, ARG_HELP
},
6743 { "halt", no_argument
, NULL
, 'H' },
6744 { "poweroff", no_argument
, NULL
, 'P' },
6745 { "reboot", no_argument
, NULL
, 'r' },
6746 { "kexec", no_argument
, NULL
, 'K' }, /* not documented extension */
6747 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6756 while ((c
= getopt_long(argc
, argv
, "HPrhkKt:afFc", options
, NULL
)) >= 0)
6764 arg_action
= ACTION_HALT
;
6768 arg_action
= ACTION_POWEROFF
;
6773 arg_action
= ACTION_KEXEC
;
6775 arg_action
= ACTION_REBOOT
;
6779 arg_action
= ACTION_KEXEC
;
6783 if (arg_action
!= ACTION_HALT
)
6784 arg_action
= ACTION_POWEROFF
;
6799 /* Compatibility nops */
6803 arg_action
= ACTION_CANCEL_SHUTDOWN
;
6810 assert_not_reached("Unhandled option");
6813 if (argc
> optind
&& arg_action
!= ACTION_CANCEL_SHUTDOWN
) {
6814 r
= parse_time_spec(argv
[optind
], &arg_when
);
6816 log_error("Failed to parse time specification: %s", argv
[optind
]);
6820 arg_when
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
;
6822 if (argc
> optind
&& arg_action
== ACTION_CANCEL_SHUTDOWN
)
6823 /* No time argument for shutdown cancel */
6824 arg_wall
= argv
+ optind
;
6825 else if (argc
> optind
+ 1)
6826 /* We skip the time argument */
6827 arg_wall
= argv
+ optind
+ 1;
6834 static int telinit_parse_argv(int argc
, char *argv
[]) {
6841 static const struct option options
[] = {
6842 { "help", no_argument
, NULL
, ARG_HELP
},
6843 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6847 static const struct {
6851 { '0', ACTION_POWEROFF
},
6852 { '6', ACTION_REBOOT
},
6853 { '1', ACTION_RESCUE
},
6854 { '2', ACTION_RUNLEVEL2
},
6855 { '3', ACTION_RUNLEVEL3
},
6856 { '4', ACTION_RUNLEVEL4
},
6857 { '5', ACTION_RUNLEVEL5
},
6858 { 's', ACTION_RESCUE
},
6859 { 'S', ACTION_RESCUE
},
6860 { 'q', ACTION_RELOAD
},
6861 { 'Q', ACTION_RELOAD
},
6862 { 'u', ACTION_REEXEC
},
6863 { 'U', ACTION_REEXEC
}
6872 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
6887 assert_not_reached("Unhandled option");
6890 if (optind
>= argc
) {
6891 log_error("%s: required argument missing.",
6892 program_invocation_short_name
);
6896 if (optind
+ 1 < argc
) {
6897 log_error("Too many arguments.");
6901 if (strlen(argv
[optind
]) != 1) {
6902 log_error("Expected single character argument.");
6906 for (i
= 0; i
< ELEMENTSOF(table
); i
++)
6907 if (table
[i
].from
== argv
[optind
][0])
6910 if (i
>= ELEMENTSOF(table
)) {
6911 log_error("Unknown command '%s'.", argv
[optind
]);
6915 arg_action
= table
[i
].to
;
6922 static int runlevel_parse_argv(int argc
, char *argv
[]) {
6928 static const struct option options
[] = {
6929 { "help", no_argument
, NULL
, ARG_HELP
},
6938 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
6949 assert_not_reached("Unhandled option");
6952 if (optind
< argc
) {
6953 log_error("Too many arguments.");
6960 static int parse_argv(int argc
, char *argv
[]) {
6964 if (program_invocation_short_name
) {
6966 if (strstr(program_invocation_short_name
, "halt")) {
6967 arg_action
= ACTION_HALT
;
6968 return halt_parse_argv(argc
, argv
);
6969 } else if (strstr(program_invocation_short_name
, "poweroff")) {
6970 arg_action
= ACTION_POWEROFF
;
6971 return halt_parse_argv(argc
, argv
);
6972 } else if (strstr(program_invocation_short_name
, "reboot")) {
6974 arg_action
= ACTION_KEXEC
;
6976 arg_action
= ACTION_REBOOT
;
6977 return halt_parse_argv(argc
, argv
);
6978 } else if (strstr(program_invocation_short_name
, "shutdown")) {
6979 arg_action
= ACTION_POWEROFF
;
6980 return shutdown_parse_argv(argc
, argv
);
6981 } else if (strstr(program_invocation_short_name
, "init")) {
6983 if (sd_booted() > 0) {
6984 arg_action
= _ACTION_INVALID
;
6985 return telinit_parse_argv(argc
, argv
);
6987 /* Hmm, so some other init system is
6988 * running, we need to forward this
6989 * request to it. For now we simply
6990 * guess that it is Upstart. */
6992 execv(TELINIT
, argv
);
6994 log_error("Couldn't find an alternative telinit implementation to spawn.");
6998 } else if (strstr(program_invocation_short_name
, "runlevel")) {
6999 arg_action
= ACTION_RUNLEVEL
;
7000 return runlevel_parse_argv(argc
, argv
);
7004 arg_action
= ACTION_SYSTEMCTL
;
7005 return systemctl_parse_argv(argc
, argv
);
7008 _pure_
static int action_to_runlevel(void) {
7010 static const char table
[_ACTION_MAX
] = {
7011 [ACTION_HALT
] = '0',
7012 [ACTION_POWEROFF
] = '0',
7013 [ACTION_REBOOT
] = '6',
7014 [ACTION_RUNLEVEL2
] = '2',
7015 [ACTION_RUNLEVEL3
] = '3',
7016 [ACTION_RUNLEVEL4
] = '4',
7017 [ACTION_RUNLEVEL5
] = '5',
7018 [ACTION_RESCUE
] = '1'
7021 assert(arg_action
< _ACTION_MAX
);
7023 return table
[arg_action
];
7026 static int talk_initctl(void) {
7028 struct init_request request
= {
7029 .magic
= INIT_MAGIC
,
7031 .cmd
= INIT_CMD_RUNLVL
7034 _cleanup_close_
int fd
= -1;
7038 rl
= action_to_runlevel();
7042 request
.runlevel
= rl
;
7044 fd
= open(INIT_FIFO
, O_WRONLY
|O_NDELAY
|O_CLOEXEC
|O_NOCTTY
);
7046 if (errno
== ENOENT
)
7049 log_error_errno(errno
, "Failed to open "INIT_FIFO
": %m");
7053 r
= loop_write(fd
, &request
, sizeof(request
), false);
7055 return log_error_errno(r
, "Failed to write to "INIT_FIFO
": %m");
7060 static int systemctl_main(sd_bus
*bus
, int argc
, char *argv
[], int bus_error
) {
7062 static const struct {
7070 int (* const dispatch
)(sd_bus
*bus
, char **args
);
7076 { "list-units", MORE
, 0, list_units
},
7077 { "list-unit-files", MORE
, 1, list_unit_files
, NOBUS
},
7078 { "list-sockets", MORE
, 1, list_sockets
},
7079 { "list-timers", MORE
, 1, list_timers
},
7080 { "list-jobs", MORE
, 1, list_jobs
},
7081 { "list-machines", MORE
, 1, list_machines
},
7082 { "clear-jobs", EQUAL
, 1, daemon_reload
},
7083 { "cancel", MORE
, 2, cancel_job
},
7084 { "start", MORE
, 2, start_unit
},
7085 { "stop", MORE
, 2, start_unit
},
7086 { "condstop", MORE
, 2, start_unit
}, /* For compatibility with ALTLinux */
7087 { "reload", MORE
, 2, start_unit
},
7088 { "restart", MORE
, 2, start_unit
},
7089 { "try-restart", MORE
, 2, start_unit
},
7090 { "reload-or-restart", MORE
, 2, start_unit
},
7091 { "reload-or-try-restart", MORE
, 2, start_unit
},
7092 { "force-reload", MORE
, 2, start_unit
}, /* For compatibility with SysV */
7093 { "condreload", MORE
, 2, start_unit
}, /* For compatibility with ALTLinux */
7094 { "condrestart", MORE
, 2, start_unit
}, /* For compatibility with RH */
7095 { "isolate", EQUAL
, 2, start_unit
},
7096 { "kill", MORE
, 2, kill_unit
},
7097 { "is-active", MORE
, 2, check_unit_active
},
7098 { "check", MORE
, 2, check_unit_active
},
7099 { "is-failed", MORE
, 2, check_unit_failed
},
7100 { "show", MORE
, 1, show
},
7101 { "cat", MORE
, 2, cat
, NOBUS
},
7102 { "status", MORE
, 1, show
},
7103 { "help", MORE
, 2, show
},
7104 { "snapshot", LESS
, 2, snapshot
},
7105 { "delete", MORE
, 2, delete_snapshot
},
7106 { "daemon-reload", EQUAL
, 1, daemon_reload
},
7107 { "daemon-reexec", EQUAL
, 1, daemon_reload
},
7108 { "show-environment", EQUAL
, 1, show_environment
},
7109 { "set-environment", MORE
, 2, set_environment
},
7110 { "unset-environment", MORE
, 2, set_environment
},
7111 { "import-environment", MORE
, 1, import_environment
},
7112 { "halt", EQUAL
, 1, start_special
, FORCE
},
7113 { "poweroff", EQUAL
, 1, start_special
, FORCE
},
7114 { "reboot", MORE
, 1, start_special
, FORCE
},
7115 { "kexec", EQUAL
, 1, start_special
},
7116 { "suspend", EQUAL
, 1, start_special
},
7117 { "hibernate", EQUAL
, 1, start_special
},
7118 { "hybrid-sleep", EQUAL
, 1, start_special
},
7119 { "default", EQUAL
, 1, start_special
},
7120 { "rescue", EQUAL
, 1, start_special
},
7121 { "emergency", EQUAL
, 1, start_special
},
7122 { "exit", EQUAL
, 1, start_special
},
7123 { "reset-failed", MORE
, 1, reset_failed
},
7124 { "enable", MORE
, 2, enable_unit
, NOBUS
},
7125 { "disable", MORE
, 2, enable_unit
, NOBUS
},
7126 { "is-enabled", MORE
, 2, unit_is_enabled
, NOBUS
},
7127 { "reenable", MORE
, 2, enable_unit
, NOBUS
},
7128 { "preset", MORE
, 2, enable_unit
, NOBUS
},
7129 { "preset-all", EQUAL
, 1, preset_all
, NOBUS
},
7130 { "mask", MORE
, 2, enable_unit
, NOBUS
},
7131 { "unmask", MORE
, 2, enable_unit
, NOBUS
},
7132 { "link", MORE
, 2, enable_unit
, NOBUS
},
7133 { "switch-root", MORE
, 2, switch_root
},
7134 { "list-dependencies", LESS
, 2, list_dependencies
},
7135 { "set-default", EQUAL
, 2, set_default
, NOBUS
},
7136 { "get-default", EQUAL
, 1, get_default
, NOBUS
},
7137 { "set-property", MORE
, 3, set_property
},
7138 { "is-system-running", EQUAL
, 1, is_system_running
},
7139 { "add-wants", MORE
, 3, add_dependency
, NOBUS
},
7140 { "add-requires", MORE
, 3, add_dependency
, NOBUS
},
7141 { "edit", MORE
, 2, edit
, NOBUS
},
7150 left
= argc
- optind
;
7152 /* Special rule: no arguments (left == 0) means "list-units" */
7154 if (streq(argv
[optind
], "help") && !argv
[optind
+1]) {
7155 log_error("This command expects one or more "
7156 "unit names. Did you mean --help?");
7160 for (; verb
->verb
; verb
++)
7161 if (streq(argv
[optind
], verb
->verb
))
7164 log_error("Unknown operation '%s'.", argv
[optind
]);
7169 switch (verb
->argc_cmp
) {
7172 if (left
!= verb
->argc
) {
7173 log_error("Invalid number of arguments.");
7180 if (left
< verb
->argc
) {
7181 log_error("Too few arguments.");
7188 if (left
> verb
->argc
) {
7189 log_error("Too many arguments.");
7196 assert_not_reached("Unknown comparison operator.");
7199 /* Require a bus connection for all operations but
7201 if (verb
->bus
== NOBUS
) {
7202 if (!bus
&& !avoid_bus()) {
7203 log_error_errno(bus_error
, "Failed to get D-Bus connection: %m");
7208 if (running_in_chroot() > 0) {
7209 log_info("Running in chroot, ignoring request.");
7213 if ((verb
->bus
!= FORCE
|| arg_force
<= 0) && !bus
) {
7214 log_error_errno(bus_error
, "Failed to get D-Bus connection: %m");
7219 return verb
->dispatch(bus
, argv
+ optind
);
7222 static int reload_with_fallback(sd_bus
*bus
) {
7225 /* First, try systemd via D-Bus. */
7226 if (daemon_reload(bus
, NULL
) >= 0)
7230 /* Nothing else worked, so let's try signals */
7231 assert(arg_action
== ACTION_RELOAD
|| arg_action
== ACTION_REEXEC
);
7233 if (kill(1, arg_action
== ACTION_RELOAD
? SIGHUP
: SIGTERM
) < 0)
7234 return log_error_errno(errno
, "kill() failed: %m");
7239 static int start_with_fallback(sd_bus
*bus
) {
7242 /* First, try systemd via D-Bus. */
7243 if (start_unit(bus
, NULL
) >= 0)
7247 /* Nothing else worked, so let's try
7249 if (talk_initctl() > 0)
7252 log_error("Failed to talk to init daemon.");
7256 warn_wall(arg_action
);
7260 static int halt_now(enum action a
) {
7262 /* The kernel will automaticall flush ATA disks and suchlike
7263 * on reboot(), but the file systems need to be synce'd
7264 * explicitly in advance. */
7267 /* Make sure C-A-D is handled by the kernel from this point
7269 reboot(RB_ENABLE_CAD
);
7274 log_info("Halting.");
7275 reboot(RB_HALT_SYSTEM
);
7278 case ACTION_POWEROFF
:
7279 log_info("Powering off.");
7280 reboot(RB_POWER_OFF
);
7283 case ACTION_REBOOT
: {
7284 _cleanup_free_
char *param
= NULL
;
7286 if (read_one_line_file(REBOOT_PARAM_FILE
, ¶m
) >= 0) {
7287 log_info("Rebooting with argument '%s'.", param
);
7288 syscall(SYS_reboot
, LINUX_REBOOT_MAGIC1
, LINUX_REBOOT_MAGIC2
,
7289 LINUX_REBOOT_CMD_RESTART2
, param
);
7292 log_info("Rebooting.");
7293 reboot(RB_AUTOBOOT
);
7298 assert_not_reached("Unknown action.");
7302 static int halt_main(sd_bus
*bus
) {
7305 r
= check_inhibitors(bus
, arg_action
);
7309 if (geteuid() != 0) {
7310 /* Try logind if we are a normal user and no special
7311 * mode applies. Maybe PolicyKit allows us to shutdown
7314 if (arg_when
<= 0 &&
7317 (arg_action
== ACTION_POWEROFF
||
7318 arg_action
== ACTION_REBOOT
)) {
7319 r
= reboot_with_logind(bus
, arg_action
);
7324 log_error("Must be root.");
7329 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
7330 _cleanup_bus_close_unref_ sd_bus
*b
= NULL
;
7331 _cleanup_free_
char *m
= NULL
;
7334 log_error("Unable to perform operation without bus connection.");
7338 r
= sd_bus_open_system(&b
);
7340 return log_error_errno(r
, "Unable to open system bus: %m");
7342 m
= strv_join(arg_wall
, " ");
7346 r
= sd_bus_set_property(
7348 "org.freedesktop.login1",
7349 "/org/freedesktop/login1",
7350 "org.freedesktop.login1.Manager",
7355 log_warning_errno(r
, "Failed to set WallMessage property in logind: %s",
7356 bus_error_message(&error
, r
));
7357 sd_bus_error_free(&error
);
7360 r
= sd_bus_set_property(
7362 "org.freedesktop.login1",
7363 "/org/freedesktop/login1",
7364 "org.freedesktop.login1.Manager",
7365 "EnableWallMessages",
7369 log_warning_errno(r
, "Failed to set EnableWallMessages property in logind: %s",
7370 bus_error_message(&error
, r
));
7371 sd_bus_error_free(&error
);
7374 r
= sd_bus_call_method(
7376 "org.freedesktop.login1",
7377 "/org/freedesktop/login1",
7378 "org.freedesktop.login1.Manager",
7383 arg_action
== ACTION_HALT
? "halt" :
7384 arg_action
== ACTION_POWEROFF
? "poweroff" :
7385 arg_action
== ACTION_KEXEC
? "kexec" :
7389 log_warning_errno(r
, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s",
7390 bus_error_message(&error
, r
));
7392 char date
[FORMAT_TIMESTAMP_MAX
];
7394 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
7395 format_timestamp(date
, sizeof(date
), arg_when
));
7400 if (!arg_dry
&& !arg_force
)
7401 return start_with_fallback(bus
);
7404 if (sd_booted() > 0)
7405 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
7407 r
= utmp_put_shutdown();
7409 log_warning_errno(r
, "Failed to write utmp record: %m");
7416 r
= halt_now(arg_action
);
7417 log_error_errno(r
, "Failed to reboot: %m");
7422 static int runlevel_main(void) {
7423 int r
, runlevel
, previous
;
7425 r
= utmp_get_runlevel(&runlevel
, &previous
);
7432 previous
<= 0 ? 'N' : previous
,
7433 runlevel
<= 0 ? 'N' : runlevel
);
7438 int main(int argc
, char*argv
[]) {
7439 _cleanup_bus_close_unref_ sd_bus
*bus
= NULL
;
7442 setlocale(LC_ALL
, "");
7443 log_parse_environment();
7446 /* Explicitly not on_tty() to avoid setting cached value.
7447 * This becomes relevant for piping output which might be
7449 original_stdout_is_tty
= isatty(STDOUT_FILENO
);
7451 r
= parse_argv(argc
, argv
);
7455 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
7456 * let's shortcut this */
7457 if (arg_action
== ACTION_RUNLEVEL
) {
7458 r
= runlevel_main();
7462 if (running_in_chroot() > 0 && arg_action
!= ACTION_SYSTEMCTL
) {
7463 log_info("Running in chroot, ignoring request.");
7469 r
= bus_open_transport_systemd(arg_transport
, arg_host
, arg_scope
!= UNIT_FILE_SYSTEM
, &bus
);
7472 sd_bus_set_allow_interactive_authorization(bus
, arg_ask_password
);
7474 /* systemctl_main() will print an error message for the bus
7475 * connection, but only if it needs to */
7477 switch (arg_action
) {
7479 case ACTION_SYSTEMCTL
:
7480 r
= systemctl_main(bus
, argc
, argv
, r
);
7484 case ACTION_POWEROFF
:
7490 case ACTION_RUNLEVEL2
:
7491 case ACTION_RUNLEVEL3
:
7492 case ACTION_RUNLEVEL4
:
7493 case ACTION_RUNLEVEL5
:
7495 case ACTION_EMERGENCY
:
7496 case ACTION_DEFAULT
:
7497 r
= start_with_fallback(bus
);
7502 r
= reload_with_fallback(bus
);
7505 case ACTION_CANCEL_SHUTDOWN
: {
7506 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
7507 _cleanup_bus_close_unref_ sd_bus
*b
= NULL
;
7508 _cleanup_free_
char *m
= NULL
;
7511 log_error("Unable to perform operation without bus connection.");
7515 r
= sd_bus_open_system(&b
);
7517 return log_error_errno(r
, "Unable to open system bus: %m");
7520 m
= strv_join(arg_wall
, " ");
7527 r
= sd_bus_set_property(
7529 "org.freedesktop.login1",
7530 "/org/freedesktop/login1",
7531 "org.freedesktop.login1.Manager",
7536 log_warning_errno(r
, "Failed to set WallMessage property in logind: %s",
7537 bus_error_message(&error
, r
));
7538 sd_bus_error_free(&error
);
7541 r
= sd_bus_set_property(
7543 "org.freedesktop.login1",
7544 "/org/freedesktop/login1",
7545 "org.freedesktop.login1.Manager",
7546 "EnableWallMessages",
7550 log_warning_errno(r
, "Failed to set EnableWallMessages property in logind: %s",
7551 bus_error_message(&error
, r
));
7552 sd_bus_error_free(&error
);
7555 r
= sd_bus_call_method(
7557 "org.freedesktop.login1",
7558 "/org/freedesktop/login1",
7559 "org.freedesktop.login1.Manager",
7560 "CancelScheduledShutdown",
7564 log_warning_errno(r
, "Failed to talk to logind, shutdown hasn't been cancelled: %s",
7565 bus_error_message(&error
, r
));
7569 case ACTION_RUNLEVEL
:
7570 case _ACTION_INVALID
:
7572 assert_not_reached("Unknown action");
7577 ask_password_agent_close();
7578 polkit_agent_close();
7580 strv_free(arg_types
);
7581 strv_free(arg_states
);
7582 strv_free(arg_properties
);
7584 return r
< 0 ? EXIT_FAILURE
: r
;