1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
7 Copyright 2013 Marc-Antoine Perennou
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
26 #include <linux/reboot.h>
32 #include <sys/reboot.h>
33 #include <sys/socket.h>
37 #include "sd-daemon.h"
40 #include "bus-common-errors.h"
41 #include "bus-error.h"
42 #include "bus-message.h"
44 #include "cgroup-show.h"
45 #include "cgroup-util.h"
50 #include "exit-status.h"
52 #include "formats-util.h"
53 #include "hostname-util.h"
58 #include "logs-show.h"
62 #include "path-lookup.h"
63 #include "path-util.h"
64 #include "process-util.h"
66 #include "signal-util.h"
67 #include "socket-util.h"
68 #include "spawn-ask-password-agent.h"
69 #include "spawn-polkit-agent.h"
72 #include "terminal-util.h"
73 #include "unit-name.h"
75 #include "utmp-wtmp.h"
77 static char **arg_types
= NULL
;
78 static char **arg_states
= NULL
;
79 static char **arg_properties
= NULL
;
80 static bool arg_all
= false;
81 static enum dependency
{
87 } arg_dependency
= DEPENDENCY_FORWARD
;
88 static const char *arg_job_mode
= "replace";
89 static UnitFileScope arg_scope
= UNIT_FILE_SYSTEM
;
90 static bool arg_no_block
= false;
91 static bool arg_no_legend
= false;
92 static bool arg_no_pager
= false;
93 static bool arg_no_wtmp
= false;
94 static bool arg_no_wall
= false;
95 static bool arg_no_reload
= false;
96 static bool arg_show_types
= false;
97 static bool arg_ignore_inhibitors
= false;
98 static bool arg_dry
= false;
99 static bool arg_quiet
= false;
100 static bool arg_full
= false;
101 static bool arg_recursive
= false;
102 static int arg_force
= 0;
103 static bool arg_ask_password
= false;
104 static bool arg_runtime
= false;
105 static UnitFilePresetMode arg_preset_mode
= UNIT_FILE_PRESET_FULL
;
106 static char **arg_wall
= NULL
;
107 static const char *arg_kill_who
= NULL
;
108 static int arg_signal
= SIGTERM
;
109 static const char *arg_root
= NULL
;
110 static usec_t arg_when
= 0;
132 ACTION_CANCEL_SHUTDOWN
,
134 } arg_action
= ACTION_SYSTEMCTL
;
135 static BusTransport arg_transport
= BUS_TRANSPORT_LOCAL
;
136 static const char *arg_host
= NULL
;
137 static unsigned arg_lines
= 10;
138 static OutputMode arg_output
= OUTPUT_SHORT
;
139 static bool arg_plain
= false;
140 static bool arg_firmware_setup
= false;
141 static bool arg_now
= false;
143 static int daemon_reload(char **args
);
144 static int halt_now(enum action a
);
145 static int check_one_unit(sd_bus
*bus
, const char *name
, const char *good_states
, bool quiet
);
147 static bool original_stdout_is_tty
;
149 typedef enum BusFocus
{
150 BUS_FULL
, /* The full bus indicated via --system or --user */
151 BUS_MANAGER
, /* The manager itself, possibly directly, possibly via the bus */
155 static sd_bus
*busses
[_BUS_FOCUS_MAX
] = {};
157 static int acquire_bus(BusFocus focus
, sd_bus
**ret
) {
160 assert(focus
< _BUS_FOCUS_MAX
);
163 /* We only go directly to the manager, if we are using a local transport */
164 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
167 if (!busses
[focus
]) {
170 user
= arg_scope
!= UNIT_FILE_SYSTEM
;
172 if (focus
== BUS_MANAGER
)
173 r
= bus_connect_transport_systemd(arg_transport
, arg_host
, user
, &busses
[focus
]);
175 r
= bus_connect_transport(arg_transport
, arg_host
, user
, &busses
[focus
]);
177 return log_error_errno(r
, "Failed to connect to bus: %m");
179 (void) sd_bus_set_allow_interactive_authorization(busses
[focus
], arg_ask_password
);
182 *ret
= busses
[focus
];
186 static void release_busses(void) {
189 for (w
= 0; w
< _BUS_FOCUS_MAX
; w
++)
190 busses
[w
] = sd_bus_flush_close_unref(busses
[w
]);
193 static void pager_open_if_enabled(void) {
201 static void ask_password_agent_open_if_enabled(void) {
203 /* Open the password agent as a child process if necessary */
205 if (!arg_ask_password
)
208 if (arg_scope
!= UNIT_FILE_SYSTEM
)
211 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
214 ask_password_agent_open();
217 static void polkit_agent_open_if_enabled(void) {
219 /* Open the polkit agent as a child process if necessary */
221 if (!arg_ask_password
)
224 if (arg_scope
!= UNIT_FILE_SYSTEM
)
227 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
233 static OutputFlags
get_output_flags(void) {
235 arg_all
* OUTPUT_SHOW_ALL
|
236 arg_full
* OUTPUT_FULL_WIDTH
|
237 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH
|
238 on_tty() * OUTPUT_COLOR
|
239 !arg_quiet
* OUTPUT_WARN_CUTOFF
;
242 static int translate_bus_error_to_exit_status(int r
, const sd_bus_error
*error
) {
245 if (!sd_bus_error_is_set(error
))
248 if (sd_bus_error_has_name(error
, SD_BUS_ERROR_ACCESS_DENIED
) ||
249 sd_bus_error_has_name(error
, BUS_ERROR_ONLY_BY_DEPENDENCY
) ||
250 sd_bus_error_has_name(error
, BUS_ERROR_NO_ISOLATION
) ||
251 sd_bus_error_has_name(error
, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE
))
252 return EXIT_NOPERMISSION
;
254 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
))
255 return EXIT_NOTINSTALLED
;
257 if (sd_bus_error_has_name(error
, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE
) ||
258 sd_bus_error_has_name(error
, SD_BUS_ERROR_NOT_SUPPORTED
))
259 return EXIT_NOTIMPLEMENTED
;
261 if (sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
))
262 return EXIT_NOTCONFIGURED
;
270 static bool install_client_side(void) {
272 /* Decides when to execute enable/disable/... operations
273 * client-side rather than server-side. */
275 if (running_in_chroot() > 0)
278 if (sd_booted() <= 0)
281 if (!isempty(arg_root
))
284 if (arg_scope
== UNIT_FILE_GLOBAL
)
290 static int compare_unit_info(const void *a
, const void *b
) {
291 const UnitInfo
*u
= a
, *v
= b
;
295 /* First, order by machine */
296 if (!u
->machine
&& v
->machine
)
298 if (u
->machine
&& !v
->machine
)
300 if (u
->machine
&& v
->machine
) {
301 r
= strcasecmp(u
->machine
, v
->machine
);
306 /* Second, order by unit type */
307 d1
= strrchr(u
->id
, '.');
308 d2
= strrchr(v
->id
, '.');
310 r
= strcasecmp(d1
, d2
);
315 /* Third, order by name */
316 return strcasecmp(u
->id
, v
->id
);
319 static bool output_show_unit(const UnitInfo
*u
, char **patterns
) {
320 if (!strv_fnmatch_or_empty(patterns
, u
->id
, FNM_NOESCAPE
))
326 dot
= strrchr(u
->id
, '.');
330 if (!strv_find(arg_types
, dot
+1))
340 if (streq(u
->active_state
, "inactive") || u
->following
[0])
346 static int output_units_list(const UnitInfo
*unit_infos
, unsigned c
) {
347 unsigned circle_len
= 0, id_len
, max_id_len
, load_len
, active_len
, sub_len
, job_len
, desc_len
;
349 unsigned n_shown
= 0;
352 max_id_len
= strlen("UNIT");
353 load_len
= strlen("LOAD");
354 active_len
= strlen("ACTIVE");
355 sub_len
= strlen("SUB");
356 job_len
= strlen("JOB");
359 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
360 max_id_len
= MAX(max_id_len
, strlen(u
->id
) + (u
->machine
? strlen(u
->machine
)+1 : 0));
361 load_len
= MAX(load_len
, strlen(u
->load_state
));
362 active_len
= MAX(active_len
, strlen(u
->active_state
));
363 sub_len
= MAX(sub_len
, strlen(u
->sub_state
));
365 if (u
->job_id
!= 0) {
366 job_len
= MAX(job_len
, strlen(u
->job_type
));
370 if (!arg_no_legend
&&
371 (streq(u
->active_state
, "failed") ||
372 STR_IN_SET(u
->load_state
, "error", "not-found", "masked")))
376 if (!arg_full
&& original_stdout_is_tty
) {
379 id_len
= MIN(max_id_len
, 25u);
380 basic_len
= circle_len
+ 5 + id_len
+ 5 + active_len
+ sub_len
;
383 basic_len
+= job_len
+ 1;
385 if (basic_len
< (unsigned) columns()) {
386 unsigned extra_len
, incr
;
387 extra_len
= columns() - basic_len
;
389 /* Either UNIT already got 25, or is fully satisfied.
390 * Grant up to 25 to DESC now. */
391 incr
= MIN(extra_len
, 25u);
395 /* split the remaining space between UNIT and DESC,
396 * but do not give UNIT more than it needs. */
398 incr
= MIN(extra_len
/ 2, max_id_len
- id_len
);
400 desc_len
+= extra_len
- incr
;
406 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
407 _cleanup_free_
char *e
= NULL
, *j
= NULL
;
408 const char *on_loaded
= "", *off_loaded
= "";
409 const char *on_active
= "", *off_active
= "";
410 const char *on_circle
= "", *off_circle
= "";
414 if (!n_shown
&& !arg_no_legend
) {
419 printf("%-*s %-*s %-*s %-*s ",
422 active_len
, "ACTIVE",
426 printf("%-*s ", job_len
, "JOB");
428 if (!arg_full
&& arg_no_pager
)
429 printf("%.*s\n", desc_len
, "DESCRIPTION");
431 printf("%s\n", "DESCRIPTION");
436 if (STR_IN_SET(u
->load_state
, "error", "not-found", "masked") && !arg_plain
) {
437 on_loaded
= ansi_highlight_red();
438 on_circle
= ansi_highlight_yellow();
439 off_loaded
= off_circle
= ansi_normal();
441 } else if (streq(u
->active_state
, "failed") && !arg_plain
) {
442 on_circle
= on_active
= ansi_highlight_red();
443 off_circle
= off_active
= ansi_normal();
448 j
= strjoin(u
->machine
, ":", u
->id
, NULL
);
457 e
= ellipsize(id
, id_len
, 33);
465 printf("%s%s%s ", on_circle
, circle
? draw_special_char(DRAW_BLACK_CIRCLE
) : " ", off_circle
);
467 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
468 on_active
, id_len
, id
, off_active
,
469 on_loaded
, load_len
, u
->load_state
, off_loaded
,
470 on_active
, active_len
, u
->active_state
,
471 sub_len
, u
->sub_state
, off_active
,
472 job_count
? job_len
+ 1 : 0, u
->job_id
? u
->job_type
: "");
475 printf("%.*s\n", desc_len
, u
->description
);
477 printf("%s\n", u
->description
);
480 if (!arg_no_legend
) {
481 const char *on
, *off
;
485 "LOAD = Reflects whether the unit definition was properly loaded.\n"
486 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
487 "SUB = The low-level unit activation state, values depend on unit type.");
488 puts(job_count
? "JOB = Pending job for the unit.\n" : "");
489 on
= ansi_highlight();
492 on
= ansi_highlight_red();
497 printf("%s%u loaded units listed.%s\n"
498 "To show all installed unit files use 'systemctl list-unit-files'.\n",
501 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
502 "To show all installed unit files use 'systemctl list-unit-files'.\n",
509 static int get_unit_list(
513 UnitInfo
**unit_infos
,
515 sd_bus_message
**_reply
) {
517 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
518 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
519 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
528 r
= sd_bus_message_new_method_call(
531 "org.freedesktop.systemd1",
532 "/org/freedesktop/systemd1",
533 "org.freedesktop.systemd1.Manager",
534 "ListUnitsFiltered");
537 return bus_log_create_error(r
);
539 r
= sd_bus_message_append_strv(m
, arg_states
);
541 return bus_log_create_error(r
);
543 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
545 return log_error_errno(r
, "Failed to list units: %s", bus_error_message(&error
, r
));
547 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssssouso)");
549 return bus_log_parse_error(r
);
551 while ((r
= bus_parse_unit_info(reply
, &u
)) > 0) {
554 if (!output_show_unit(&u
, patterns
))
557 if (!GREEDY_REALLOC(*unit_infos
, size
, c
+1))
560 (*unit_infos
)[c
++] = u
;
563 return bus_log_parse_error(r
);
565 r
= sd_bus_message_exit_container(reply
);
567 return bus_log_parse_error(r
);
575 static void message_set_freep(Set
**set
) {
578 while ((m
= set_steal_first(*set
)))
579 sd_bus_message_unref(m
);
584 static int get_unit_list_recursive(
587 UnitInfo
**_unit_infos
,
591 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
592 _cleanup_(message_set_freep
) Set
*replies
;
593 sd_bus_message
*reply
;
601 replies
= set_new(NULL
);
605 c
= get_unit_list(bus
, NULL
, patterns
, &unit_infos
, 0, &reply
);
609 r
= set_put(replies
, reply
);
611 sd_bus_message_unref(reply
);
616 _cleanup_strv_free_
char **machines
= NULL
;
619 r
= sd_get_machine_names(&machines
);
621 return log_error_errno(r
, "Failed to get machine names: %m");
623 STRV_FOREACH(i
, machines
) {
624 _cleanup_bus_flush_close_unref_ sd_bus
*container
= NULL
;
627 r
= sd_bus_open_system_machine(&container
, *i
);
629 log_warning_errno(r
, "Failed to connect to container %s, ignoring: %m", *i
);
633 k
= get_unit_list(container
, *i
, patterns
, &unit_infos
, c
, &reply
);
639 r
= set_put(replies
, reply
);
641 sd_bus_message_unref(reply
);
646 *_machines
= machines
;
651 *_unit_infos
= unit_infos
;
660 static int list_units(char **args
) {
661 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
662 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
663 _cleanup_strv_free_
char **machines
= NULL
;
667 pager_open_if_enabled();
669 r
= acquire_bus(BUS_MANAGER
, &bus
);
673 r
= get_unit_list_recursive(bus
, strv_skip(args
, 1), &unit_infos
, &replies
, &machines
);
677 qsort_safe(unit_infos
, r
, sizeof(UnitInfo
), compare_unit_info
);
678 return output_units_list(unit_infos
, r
);
681 static int get_triggered_units(
686 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
693 r
= sd_bus_get_property_strv(
695 "org.freedesktop.systemd1",
697 "org.freedesktop.systemd1.Unit",
702 return log_error_errno(r
, "Failed to determine triggers: %s", bus_error_message(&error
, r
));
707 static int get_listening(
709 const char* unit_path
,
712 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
713 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
714 const char *type
, *path
;
717 r
= sd_bus_get_property(
719 "org.freedesktop.systemd1",
721 "org.freedesktop.systemd1.Socket",
727 return log_error_errno(r
, "Failed to get list of listening sockets: %s", bus_error_message(&error
, r
));
729 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
731 return bus_log_parse_error(r
);
733 while ((r
= sd_bus_message_read(reply
, "(ss)", &type
, &path
)) > 0) {
735 r
= strv_extend(listening
, type
);
739 r
= strv_extend(listening
, path
);
746 return bus_log_parse_error(r
);
748 r
= sd_bus_message_exit_container(reply
);
750 return bus_log_parse_error(r
);
762 /* Note: triggered is a list here, although it almost certainly
763 * will always be one unit. Nevertheless, dbus API allows for multiple
764 * values, so let's follow that. */
767 /* The strv above is shared. free is set only in the first one. */
771 static int socket_info_compare(const struct socket_info
*a
, const struct socket_info
*b
) {
777 if (!a
->machine
&& b
->machine
)
779 if (a
->machine
&& !b
->machine
)
781 if (a
->machine
&& b
->machine
) {
782 o
= strcasecmp(a
->machine
, b
->machine
);
787 o
= strcmp(a
->path
, b
->path
);
789 o
= strcmp(a
->type
, b
->type
);
794 static int output_sockets_list(struct socket_info
*socket_infos
, unsigned cs
) {
795 struct socket_info
*s
;
796 unsigned pathlen
= strlen("LISTEN"),
797 typelen
= strlen("TYPE") * arg_show_types
,
798 socklen
= strlen("UNIT"),
799 servlen
= strlen("ACTIVATES");
800 const char *on
, *off
;
802 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
806 socklen
= MAX(socklen
, strlen(s
->id
));
808 typelen
= MAX(typelen
, strlen(s
->type
));
809 pathlen
= MAX(pathlen
, strlen(s
->path
) + (s
->machine
? strlen(s
->machine
)+1 : 0));
811 STRV_FOREACH(a
, s
->triggered
)
812 tmp
+= strlen(*a
) + 2*(a
!= s
->triggered
);
813 servlen
= MAX(servlen
, tmp
);
818 printf("%-*s %-*.*s%-*s %s\n",
820 typelen
+ arg_show_types
, typelen
+ arg_show_types
, "TYPE ",
824 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
825 _cleanup_free_
char *j
= NULL
;
830 j
= strjoin(s
->machine
, ":", s
->path
, NULL
);
838 printf("%-*s %-*s %-*s",
839 pathlen
, path
, typelen
, s
->type
, socklen
, s
->id
);
842 pathlen
, path
, socklen
, s
->id
);
843 STRV_FOREACH(a
, s
->triggered
)
845 a
== s
->triggered
? "" : ",", *a
);
849 on
= ansi_highlight();
854 on
= ansi_highlight_red();
858 if (!arg_no_legend
) {
859 printf("%s%u sockets listed.%s\n", on
, cs
, off
);
861 printf("Pass --all to see loaded but inactive sockets, too.\n");
867 static int list_sockets(char **args
) {
868 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
869 _cleanup_strv_free_
char **machines
= NULL
;
870 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
871 _cleanup_free_
struct socket_info
*socket_infos
= NULL
;
873 struct socket_info
*s
;
879 pager_open_if_enabled();
881 r
= acquire_bus(BUS_MANAGER
, &bus
);
885 n
= get_unit_list_recursive(bus
, strv_skip(args
, 1), &unit_infos
, &replies
, &machines
);
889 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
890 _cleanup_strv_free_
char **listening
= NULL
, **triggered
= NULL
;
893 if (!endswith(u
->id
, ".socket"))
896 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
900 c
= get_listening(bus
, u
->unit_path
, &listening
);
906 if (!GREEDY_REALLOC(socket_infos
, size
, cs
+ c
)) {
911 for (i
= 0; i
< c
; i
++)
912 socket_infos
[cs
+ i
] = (struct socket_info
) {
913 .machine
= u
->machine
,
915 .type
= listening
[i
*2],
916 .path
= listening
[i
*2 + 1],
917 .triggered
= triggered
,
918 .own_triggered
= i
==0,
921 /* from this point on we will cleanup those socket_infos */
924 listening
= triggered
= NULL
; /* avoid cleanup */
927 qsort_safe(socket_infos
, cs
, sizeof(struct socket_info
),
928 (__compar_fn_t
) socket_info_compare
);
930 output_sockets_list(socket_infos
, cs
);
933 assert(cs
== 0 || socket_infos
);
934 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
937 if (s
->own_triggered
)
938 strv_free(s
->triggered
);
944 static int get_next_elapse(
947 dual_timestamp
*next
) {
949 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
957 r
= sd_bus_get_property_trivial(
959 "org.freedesktop.systemd1",
961 "org.freedesktop.systemd1.Timer",
962 "NextElapseUSecMonotonic",
967 return log_error_errno(r
, "Failed to get next elapsation time: %s", bus_error_message(&error
, r
));
969 r
= sd_bus_get_property_trivial(
971 "org.freedesktop.systemd1",
973 "org.freedesktop.systemd1.Timer",
974 "NextElapseUSecRealtime",
979 return log_error_errno(r
, "Failed to get next elapsation time: %s", bus_error_message(&error
, r
));
985 static int get_last_trigger(
990 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
997 r
= sd_bus_get_property_trivial(
999 "org.freedesktop.systemd1",
1001 "org.freedesktop.systemd1.Timer",
1007 return log_error_errno(r
, "Failed to get last trigger time: %s", bus_error_message(&error
, r
));
1013 const char* machine
;
1016 usec_t last_trigger
;
1020 static int timer_info_compare(const struct timer_info
*a
, const struct timer_info
*b
) {
1026 if (!a
->machine
&& b
->machine
)
1028 if (a
->machine
&& !b
->machine
)
1030 if (a
->machine
&& b
->machine
) {
1031 o
= strcasecmp(a
->machine
, b
->machine
);
1036 if (a
->next_elapse
< b
->next_elapse
)
1038 if (a
->next_elapse
> b
->next_elapse
)
1041 return strcmp(a
->id
, b
->id
);
1044 static int output_timers_list(struct timer_info
*timer_infos
, unsigned n
) {
1045 struct timer_info
*t
;
1047 nextlen
= strlen("NEXT"),
1048 leftlen
= strlen("LEFT"),
1049 lastlen
= strlen("LAST"),
1050 passedlen
= strlen("PASSED"),
1051 unitlen
= strlen("UNIT"),
1052 activatelen
= strlen("ACTIVATES");
1054 const char *on
, *off
;
1056 assert(timer_infos
|| n
== 0);
1058 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1062 if (t
->next_elapse
> 0) {
1063 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1065 format_timestamp(tstamp
, sizeof(tstamp
), t
->next_elapse
);
1066 nextlen
= MAX(nextlen
, strlen(tstamp
) + 1);
1068 format_timestamp_relative(trel
, sizeof(trel
), t
->next_elapse
);
1069 leftlen
= MAX(leftlen
, strlen(trel
));
1072 if (t
->last_trigger
> 0) {
1073 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1075 format_timestamp(tstamp
, sizeof(tstamp
), t
->last_trigger
);
1076 lastlen
= MAX(lastlen
, strlen(tstamp
) + 1);
1078 format_timestamp_relative(trel
, sizeof(trel
), t
->last_trigger
);
1079 passedlen
= MAX(passedlen
, strlen(trel
));
1082 unitlen
= MAX(unitlen
, strlen(t
->id
) + (t
->machine
? strlen(t
->machine
)+1 : 0));
1084 STRV_FOREACH(a
, t
->triggered
)
1085 ul
+= strlen(*a
) + 2*(a
!= t
->triggered
);
1087 activatelen
= MAX(activatelen
, ul
);
1092 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1096 passedlen
, "PASSED",
1100 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1101 _cleanup_free_
char *j
= NULL
;
1103 char tstamp1
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel1
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1104 char tstamp2
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel2
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1107 format_timestamp(tstamp1
, sizeof(tstamp1
), t
->next_elapse
);
1108 format_timestamp_relative(trel1
, sizeof(trel1
), t
->next_elapse
);
1110 format_timestamp(tstamp2
, sizeof(tstamp2
), t
->last_trigger
);
1111 format_timestamp_relative(trel2
, sizeof(trel2
), t
->last_trigger
);
1114 j
= strjoin(t
->machine
, ":", t
->id
, NULL
);
1121 printf("%-*s %-*s %-*s %-*s %-*s",
1122 nextlen
, tstamp1
, leftlen
, trel1
, lastlen
, tstamp2
, passedlen
, trel2
, unitlen
, unit
);
1124 STRV_FOREACH(a
, t
->triggered
)
1126 a
== t
->triggered
? "" : ",", *a
);
1130 on
= ansi_highlight();
1131 off
= ansi_normal();
1135 on
= ansi_highlight_red();
1136 off
= ansi_normal();
1139 if (!arg_no_legend
) {
1140 printf("%s%u timers listed.%s\n", on
, n
, off
);
1142 printf("Pass --all to see loaded but inactive timers, too.\n");
1148 static usec_t
calc_next_elapse(dual_timestamp
*nw
, dual_timestamp
*next
) {
1154 if (next
->monotonic
!= USEC_INFINITY
&& next
->monotonic
> 0) {
1157 if (next
->monotonic
> nw
->monotonic
)
1158 converted
= nw
->realtime
+ (next
->monotonic
- nw
->monotonic
);
1160 converted
= nw
->realtime
- (nw
->monotonic
- next
->monotonic
);
1162 if (next
->realtime
!= USEC_INFINITY
&& next
->realtime
> 0)
1163 next_elapse
= MIN(converted
, next
->realtime
);
1165 next_elapse
= converted
;
1168 next_elapse
= next
->realtime
;
1173 static int list_timers(char **args
) {
1174 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
1175 _cleanup_strv_free_
char **machines
= NULL
;
1176 _cleanup_free_
struct timer_info
*timer_infos
= NULL
;
1177 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
1178 struct timer_info
*t
;
1186 pager_open_if_enabled();
1188 r
= acquire_bus(BUS_MANAGER
, &bus
);
1192 n
= get_unit_list_recursive(bus
, strv_skip(args
, 1), &unit_infos
, &replies
, &machines
);
1196 dual_timestamp_get(&nw
);
1198 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
1199 _cleanup_strv_free_
char **triggered
= NULL
;
1200 dual_timestamp next
= DUAL_TIMESTAMP_NULL
;
1203 if (!endswith(u
->id
, ".timer"))
1206 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
1210 r
= get_next_elapse(bus
, u
->unit_path
, &next
);
1214 get_last_trigger(bus
, u
->unit_path
, &last
);
1216 if (!GREEDY_REALLOC(timer_infos
, size
, c
+1)) {
1221 m
= calc_next_elapse(&nw
, &next
);
1223 timer_infos
[c
++] = (struct timer_info
) {
1224 .machine
= u
->machine
,
1227 .last_trigger
= last
,
1228 .triggered
= triggered
,
1231 triggered
= NULL
; /* avoid cleanup */
1234 qsort_safe(timer_infos
, c
, sizeof(struct timer_info
),
1235 (__compar_fn_t
) timer_info_compare
);
1237 output_timers_list(timer_infos
, c
);
1240 for (t
= timer_infos
; t
< timer_infos
+ c
; t
++)
1241 strv_free(t
->triggered
);
1246 static int compare_unit_file_list(const void *a
, const void *b
) {
1247 const char *d1
, *d2
;
1248 const UnitFileList
*u
= a
, *v
= b
;
1250 d1
= strrchr(u
->path
, '.');
1251 d2
= strrchr(v
->path
, '.');
1256 r
= strcasecmp(d1
, d2
);
1261 return strcasecmp(basename(u
->path
), basename(v
->path
));
1264 static bool output_show_unit_file(const UnitFileList
*u
, char **patterns
) {
1265 if (!strv_fnmatch_or_empty(patterns
, basename(u
->path
), FNM_NOESCAPE
))
1268 if (!strv_isempty(arg_types
)) {
1271 dot
= strrchr(u
->path
, '.');
1275 if (!strv_find(arg_types
, dot
+1))
1279 if (!strv_isempty(arg_states
) &&
1280 !strv_find(arg_states
, unit_file_state_to_string(u
->state
)))
1286 static void output_unit_file_list(const UnitFileList
*units
, unsigned c
) {
1287 unsigned max_id_len
, id_cols
, state_cols
;
1288 const UnitFileList
*u
;
1290 max_id_len
= strlen("UNIT FILE");
1291 state_cols
= strlen("STATE");
1293 for (u
= units
; u
< units
+ c
; u
++) {
1294 max_id_len
= MAX(max_id_len
, strlen(basename(u
->path
)));
1295 state_cols
= MAX(state_cols
, strlen(unit_file_state_to_string(u
->state
)));
1299 unsigned basic_cols
;
1301 id_cols
= MIN(max_id_len
, 25u);
1302 basic_cols
= 1 + id_cols
+ state_cols
;
1303 if (basic_cols
< (unsigned) columns())
1304 id_cols
+= MIN(columns() - basic_cols
, max_id_len
- id_cols
);
1306 id_cols
= max_id_len
;
1309 printf("%-*s %-*s\n",
1310 id_cols
, "UNIT FILE",
1311 state_cols
, "STATE");
1313 for (u
= units
; u
< units
+ c
; u
++) {
1314 _cleanup_free_
char *e
= NULL
;
1315 const char *on
, *off
;
1318 if (IN_SET(u
->state
,
1320 UNIT_FILE_MASKED_RUNTIME
,
1322 UNIT_FILE_INVALID
)) {
1323 on
= ansi_highlight_red();
1324 off
= ansi_normal();
1325 } else if (u
->state
== UNIT_FILE_ENABLED
) {
1326 on
= ansi_highlight_green();
1327 off
= ansi_normal();
1331 id
= basename(u
->path
);
1333 e
= arg_full
? NULL
: ellipsize(id
, id_cols
, 33);
1335 printf("%-*s %s%-*s%s\n",
1336 id_cols
, e
? e
: id
,
1337 on
, state_cols
, unit_file_state_to_string(u
->state
), off
);
1341 printf("\n%u unit files listed.\n", c
);
1344 static int list_unit_files(char **args
) {
1345 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1346 _cleanup_free_ UnitFileList
*units
= NULL
;
1354 pager_open_if_enabled();
1356 if (install_client_side()) {
1362 h
= hashmap_new(&string_hash_ops
);
1366 r
= unit_file_get_list(arg_scope
, arg_root
, h
);
1368 unit_file_list_free(h
);
1369 return log_error_errno(r
, "Failed to get unit file list: %m");
1372 n_units
= hashmap_size(h
);
1374 units
= new(UnitFileList
, n_units
);
1375 if (!units
&& n_units
> 0) {
1376 unit_file_list_free(h
);
1380 HASHMAP_FOREACH(u
, h
, i
) {
1381 if (!output_show_unit_file(u
, strv_skip(args
, 1)))
1388 assert(c
<= n_units
);
1391 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1394 r
= acquire_bus(BUS_MANAGER
, &bus
);
1398 r
= sd_bus_call_method(
1400 "org.freedesktop.systemd1",
1401 "/org/freedesktop/systemd1",
1402 "org.freedesktop.systemd1.Manager",
1408 return log_error_errno(r
, "Failed to list unit files: %s", bus_error_message(&error
, r
));
1410 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
1412 return bus_log_parse_error(r
);
1414 while ((r
= sd_bus_message_read(reply
, "(ss)", &path
, &state
)) > 0) {
1416 if (!GREEDY_REALLOC(units
, size
, c
+ 1))
1419 units
[c
] = (struct UnitFileList
) {
1421 unit_file_state_from_string(state
)
1424 if (output_show_unit_file(&units
[c
], strv_skip(args
, 1)))
1429 return bus_log_parse_error(r
);
1431 r
= sd_bus_message_exit_container(reply
);
1433 return bus_log_parse_error(r
);
1436 qsort_safe(units
, c
, sizeof(UnitFileList
), compare_unit_file_list
);
1437 output_unit_file_list(units
, c
);
1439 if (install_client_side()) {
1440 for (unit
= units
; unit
< units
+ c
; unit
++)
1447 static int list_dependencies_print(const char *name
, int level
, unsigned int branches
, bool last
) {
1448 _cleanup_free_
char *n
= NULL
;
1449 size_t max_len
= MAX(columns(),20u);
1455 for (i
= level
- 1; i
>= 0; i
--) {
1457 if (len
> max_len
- 3 && !arg_full
) {
1458 printf("%s...\n",max_len
% 2 ? "" : " ");
1461 printf("%s", draw_special_char(branches
& (1 << i
) ? DRAW_TREE_VERTICAL
: DRAW_TREE_SPACE
));
1465 if (len
> max_len
- 3 && !arg_full
) {
1466 printf("%s...\n",max_len
% 2 ? "" : " ");
1470 printf("%s", draw_special_char(last
? DRAW_TREE_RIGHT
: DRAW_TREE_BRANCH
));
1474 printf("%s\n", name
);
1478 n
= ellipsize(name
, max_len
-len
, 100);
1486 static int list_dependencies_get_dependencies(sd_bus
*bus
, const char *name
, char ***deps
) {
1488 static const char *dependencies
[_DEPENDENCY_MAX
] = {
1489 [DEPENDENCY_FORWARD
] = "Requires\0"
1490 "RequiresOverridable\0"
1492 "RequisiteOverridable\0"
1496 [DEPENDENCY_REVERSE
] = "RequiredBy\0"
1497 "RequiredByOverridable\0"
1499 "RequisiteOfOverridable\0"
1503 [DEPENDENCY_AFTER
] = "After\0",
1504 [DEPENDENCY_BEFORE
] = "Before\0",
1507 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1508 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1509 _cleanup_strv_free_
char **ret
= NULL
;
1510 _cleanup_free_
char *path
= NULL
;
1516 assert_cc(ELEMENTSOF(dependencies
) == _DEPENDENCY_MAX
);
1518 path
= unit_dbus_path_from_name(name
);
1522 r
= sd_bus_call_method(
1524 "org.freedesktop.systemd1",
1526 "org.freedesktop.DBus.Properties",
1530 "s", "org.freedesktop.systemd1.Unit");
1532 return log_error_errno(r
, "Failed to get properties of %s: %s", name
, bus_error_message(&error
, r
));
1534 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
1536 return bus_log_parse_error(r
);
1538 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
1541 r
= sd_bus_message_read(reply
, "s", &prop
);
1543 return bus_log_parse_error(r
);
1545 if (!nulstr_contains(dependencies
[arg_dependency
], prop
)) {
1546 r
= sd_bus_message_skip(reply
, "v");
1548 return bus_log_parse_error(r
);
1551 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, "as");
1553 return bus_log_parse_error(r
);
1555 r
= bus_message_read_strv_extend(reply
, &ret
);
1557 return bus_log_parse_error(r
);
1559 r
= sd_bus_message_exit_container(reply
);
1561 return bus_log_parse_error(r
);
1564 r
= sd_bus_message_exit_container(reply
);
1566 return bus_log_parse_error(r
);
1570 return bus_log_parse_error(r
);
1572 r
= sd_bus_message_exit_container(reply
);
1574 return bus_log_parse_error(r
);
1582 static int list_dependencies_compare(const void *_a
, const void *_b
) {
1583 const char **a
= (const char**) _a
, **b
= (const char**) _b
;
1585 if (unit_name_to_type(*a
) == UNIT_TARGET
&& unit_name_to_type(*b
) != UNIT_TARGET
)
1587 if (unit_name_to_type(*a
) != UNIT_TARGET
&& unit_name_to_type(*b
) == UNIT_TARGET
)
1590 return strcasecmp(*a
, *b
);
1593 static int list_dependencies_one(
1598 unsigned int branches
) {
1600 _cleanup_strv_free_
char **deps
= NULL
;
1608 r
= strv_extend(units
, name
);
1612 r
= list_dependencies_get_dependencies(bus
, name
, &deps
);
1616 qsort_safe(deps
, strv_length(deps
), sizeof (char*), list_dependencies_compare
);
1618 STRV_FOREACH(c
, deps
) {
1619 if (strv_contains(*units
, *c
)) {
1621 r
= list_dependencies_print("...", level
+ 1, (branches
<< 1) | (c
[1] == NULL
? 0 : 1), 1);
1634 state
= check_one_unit(bus
, *c
, "activating\0active\0reloading\0", true);
1635 on
= state
> 0 ? ansi_highlight_green() : ansi_highlight_red();
1636 printf("%s%s%s ", on
, draw_special_char(DRAW_BLACK_CIRCLE
), ansi_normal());
1639 r
= list_dependencies_print(*c
, level
, branches
, c
[1] == NULL
);
1643 if (arg_all
|| unit_name_to_type(*c
) == UNIT_TARGET
) {
1644 r
= list_dependencies_one(bus
, *c
, level
+ 1, units
, (branches
<< 1) | (c
[1] == NULL
? 0 : 1));
1651 strv_remove(*units
, name
);
1656 static int list_dependencies(char **args
) {
1657 _cleanup_strv_free_
char **units
= NULL
;
1658 _cleanup_free_
char *unit
= NULL
;
1664 r
= unit_name_mangle(args
[1], UNIT_NAME_NOGLOB
, &unit
);
1666 return log_error_errno(r
, "Failed to mangle unit name: %m");
1670 u
= SPECIAL_DEFAULT_TARGET
;
1672 pager_open_if_enabled();
1674 r
= acquire_bus(BUS_MANAGER
, &bus
);
1680 return list_dependencies_one(bus
, u
, 0, &units
, 0);
1683 struct machine_info
{
1687 char *control_group
;
1688 uint32_t n_failed_units
;
1693 static const struct bus_properties_map machine_info_property_map
[] = {
1694 { "SystemState", "s", NULL
, offsetof(struct machine_info
, state
) },
1695 { "NJobs", "u", NULL
, offsetof(struct machine_info
, n_jobs
) },
1696 { "NFailedUnits", "u", NULL
, offsetof(struct machine_info
, n_failed_units
) },
1697 { "ControlGroup", "s", NULL
, offsetof(struct machine_info
, control_group
) },
1698 { "UserspaceTimestamp", "t", NULL
, offsetof(struct machine_info
, timestamp
) },
1702 static void machine_info_clear(struct machine_info
*info
) {
1706 free(info
->control_group
);
1711 static void free_machines_list(struct machine_info
*machine_infos
, int n
) {
1717 for (i
= 0; i
< n
; i
++)
1718 machine_info_clear(&machine_infos
[i
]);
1720 free(machine_infos
);
1723 static int compare_machine_info(const void *a
, const void *b
) {
1724 const struct machine_info
*u
= a
, *v
= b
;
1726 if (u
->is_host
!= v
->is_host
)
1727 return u
->is_host
> v
->is_host
? -1 : 1;
1729 return strcasecmp(u
->name
, v
->name
);
1732 static int get_machine_properties(sd_bus
*bus
, struct machine_info
*mi
) {
1733 _cleanup_bus_flush_close_unref_ sd_bus
*container
= NULL
;
1739 r
= sd_bus_open_system_machine(&container
, mi
->name
);
1746 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, mi
);
1753 static bool output_show_machine(const char *name
, char **patterns
) {
1754 return strv_fnmatch_or_empty(patterns
, name
, FNM_NOESCAPE
);
1757 static int get_machine_list(
1759 struct machine_info
**_machine_infos
,
1762 struct machine_info
*machine_infos
= NULL
;
1763 _cleanup_strv_free_
char **m
= NULL
;
1764 _cleanup_free_
char *hn
= NULL
;
1769 hn
= gethostname_malloc();
1773 if (output_show_machine(hn
, patterns
)) {
1774 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1))
1777 machine_infos
[c
].is_host
= true;
1778 machine_infos
[c
].name
= hn
;
1781 get_machine_properties(bus
, &machine_infos
[c
]);
1785 r
= sd_get_machine_names(&m
);
1787 return log_error_errno(r
, "Failed to get machine list: %m");
1789 STRV_FOREACH(i
, m
) {
1790 _cleanup_free_
char *class = NULL
;
1792 if (!output_show_machine(*i
, patterns
))
1795 sd_machine_get_class(*i
, &class);
1796 if (!streq_ptr(class, "container"))
1799 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1)) {
1800 free_machines_list(machine_infos
, c
);
1804 machine_infos
[c
].is_host
= false;
1805 machine_infos
[c
].name
= strdup(*i
);
1806 if (!machine_infos
[c
].name
) {
1807 free_machines_list(machine_infos
, c
);
1811 get_machine_properties(NULL
, &machine_infos
[c
]);
1815 *_machine_infos
= machine_infos
;
1819 static void output_machines_list(struct machine_info
*machine_infos
, unsigned n
) {
1820 struct machine_info
*m
;
1823 namelen
= sizeof("NAME") - 1,
1824 statelen
= sizeof("STATE") - 1,
1825 failedlen
= sizeof("FAILED") - 1,
1826 jobslen
= sizeof("JOBS") - 1;
1828 assert(machine_infos
|| n
== 0);
1830 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
1831 namelen
= MAX(namelen
, strlen(m
->name
) + (m
->is_host
? sizeof(" (host)") - 1 : 0));
1832 statelen
= MAX(statelen
, m
->state
? strlen(m
->state
) : 0);
1833 failedlen
= MAX(failedlen
, DECIMAL_STR_WIDTH(m
->n_failed_units
));
1834 jobslen
= MAX(jobslen
, DECIMAL_STR_WIDTH(m
->n_jobs
));
1836 if (!arg_plain
&& !streq_ptr(m
->state
, "running"))
1840 if (!arg_no_legend
) {
1844 printf("%-*s %-*s %-*s %-*s\n",
1847 failedlen
, "FAILED",
1851 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
1852 const char *on_state
= "", *off_state
= "";
1853 const char *on_failed
= "", *off_failed
= "";
1854 bool circle
= false;
1856 if (streq_ptr(m
->state
, "degraded")) {
1857 on_state
= ansi_highlight_red();
1858 off_state
= ansi_normal();
1860 } else if (!streq_ptr(m
->state
, "running")) {
1861 on_state
= ansi_highlight_yellow();
1862 off_state
= ansi_normal();
1866 if (m
->n_failed_units
> 0) {
1867 on_failed
= ansi_highlight_red();
1868 off_failed
= ansi_normal();
1870 on_failed
= off_failed
= "";
1873 printf("%s%s%s ", on_state
, circle
? draw_special_char(DRAW_BLACK_CIRCLE
) : " ", off_state
);
1876 printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
1877 (int) (namelen
- (sizeof(" (host)")-1)), strna(m
->name
),
1878 on_state
, statelen
, strna(m
->state
), off_state
,
1879 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
1880 jobslen
, m
->n_jobs
);
1882 printf("%-*s %s%-*s%s %s%*u%s %*u\n",
1883 namelen
, strna(m
->name
),
1884 on_state
, statelen
, strna(m
->state
), off_state
,
1885 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
1886 jobslen
, m
->n_jobs
);
1890 printf("\n%u machines listed.\n", n
);
1893 static int list_machines(char **args
) {
1894 struct machine_info
*machine_infos
= NULL
;
1898 if (geteuid() != 0) {
1899 log_error("Must be root.");
1903 pager_open_if_enabled();
1905 r
= acquire_bus(BUS_MANAGER
, &bus
);
1909 r
= get_machine_list(bus
, &machine_infos
, strv_skip(args
, 1));
1913 qsort_safe(machine_infos
, r
, sizeof(struct machine_info
), compare_machine_info
);
1914 output_machines_list(machine_infos
, r
);
1915 free_machines_list(machine_infos
, r
);
1920 static int get_default(char **args
) {
1921 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1922 _cleanup_free_
char *_path
= NULL
;
1926 if (install_client_side()) {
1927 r
= unit_file_get_default(arg_scope
, arg_root
, &_path
);
1929 return log_error_errno(r
, "Failed to get default target: %m");
1933 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1936 r
= acquire_bus(BUS_MANAGER
, &bus
);
1940 r
= sd_bus_call_method(
1942 "org.freedesktop.systemd1",
1943 "/org/freedesktop/systemd1",
1944 "org.freedesktop.systemd1.Manager",
1950 return log_error_errno(r
, "Failed to get default target: %s", bus_error_message(&error
, r
));
1952 r
= sd_bus_message_read(reply
, "s", &path
);
1954 return bus_log_parse_error(r
);
1958 printf("%s\n", path
);
1963 static void dump_unit_file_changes(const UnitFileChange
*changes
, unsigned n_changes
) {
1966 assert(changes
|| n_changes
== 0);
1968 for (i
= 0; i
< n_changes
; i
++) {
1969 if (changes
[i
].type
== UNIT_FILE_SYMLINK
)
1970 log_info("Created symlink from %s to %s.", changes
[i
].path
, changes
[i
].source
);
1972 log_info("Removed symlink %s.", changes
[i
].path
);
1976 static int set_default(char **args
) {
1977 _cleanup_free_
char *unit
= NULL
;
1980 r
= unit_name_mangle_with_suffix(args
[1], UNIT_NAME_NOGLOB
, ".target", &unit
);
1982 return log_error_errno(r
, "Failed to mangle unit name: %m");
1984 if (install_client_side()) {
1985 UnitFileChange
*changes
= NULL
;
1986 unsigned n_changes
= 0;
1988 r
= unit_file_set_default(arg_scope
, arg_root
, unit
, true, &changes
, &n_changes
);
1990 return log_error_errno(r
, "Failed to set default target: %m");
1993 dump_unit_file_changes(changes
, n_changes
);
1995 unit_file_changes_free(changes
, n_changes
);
1998 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1999 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2002 polkit_agent_open_if_enabled();
2004 r
= acquire_bus(BUS_MANAGER
, &bus
);
2008 r
= sd_bus_call_method(
2010 "org.freedesktop.systemd1",
2011 "/org/freedesktop/systemd1",
2012 "org.freedesktop.systemd1.Manager",
2018 return log_error_errno(r
, "Failed to set default target: %s", bus_error_message(&error
, r
));
2020 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, NULL
, NULL
);
2024 /* Try to reload if enabled */
2026 r
= daemon_reload(args
);
2036 const char *name
, *type
, *state
;
2039 static void output_jobs_list(const struct job_info
* jobs
, unsigned n
, bool skipped
) {
2040 unsigned id_len
, unit_len
, type_len
, state_len
;
2041 const struct job_info
*j
;
2042 const char *on
, *off
;
2043 bool shorten
= false;
2045 assert(n
== 0 || jobs
);
2048 if (!arg_no_legend
) {
2049 on
= ansi_highlight_green();
2050 off
= ansi_normal();
2052 printf("%sNo jobs %s.%s\n", on
, skipped
? "listed" : "running", off
);
2057 pager_open_if_enabled();
2059 id_len
= strlen("JOB");
2060 unit_len
= strlen("UNIT");
2061 type_len
= strlen("TYPE");
2062 state_len
= strlen("STATE");
2064 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2065 uint32_t id
= j
->id
;
2066 assert(j
->name
&& j
->type
&& j
->state
);
2068 id_len
= MAX(id_len
, DECIMAL_STR_WIDTH(id
));
2069 unit_len
= MAX(unit_len
, strlen(j
->name
));
2070 type_len
= MAX(type_len
, strlen(j
->type
));
2071 state_len
= MAX(state_len
, strlen(j
->state
));
2074 if (!arg_full
&& id_len
+ 1 + unit_len
+ type_len
+ 1 + state_len
> columns()) {
2075 unit_len
= MAX(33u, columns() - id_len
- type_len
- state_len
- 3);
2080 printf("%*s %-*s %-*s %-*s\n",
2084 state_len
, "STATE");
2086 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2087 _cleanup_free_
char *e
= NULL
;
2089 if (streq(j
->state
, "running")) {
2090 on
= ansi_highlight();
2091 off
= ansi_normal();
2095 e
= shorten
? ellipsize(j
->name
, unit_len
, 33) : NULL
;
2096 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2098 on
, unit_len
, e
? e
: j
->name
, off
,
2100 on
, state_len
, j
->state
, off
);
2103 if (!arg_no_legend
) {
2104 on
= ansi_highlight();
2105 off
= ansi_normal();
2107 printf("\n%s%u jobs listed%s.\n", on
, n
, off
);
2111 static bool output_show_job(struct job_info
*job
, char **patterns
) {
2112 return strv_fnmatch_or_empty(patterns
, job
->name
, FNM_NOESCAPE
);
2115 static int list_jobs(char **args
) {
2116 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2117 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2118 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2119 _cleanup_free_
struct job_info
*jobs
= NULL
;
2125 bool skipped
= false;
2127 pager_open_if_enabled();
2129 r
= acquire_bus(BUS_MANAGER
, &bus
);
2133 r
= sd_bus_call_method(
2135 "org.freedesktop.systemd1",
2136 "/org/freedesktop/systemd1",
2137 "org.freedesktop.systemd1.Manager",
2143 return log_error_errno(r
, "Failed to list jobs: %s", bus_error_message(&error
, r
));
2145 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2147 return bus_log_parse_error(r
);
2149 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0) {
2150 struct job_info job
= { id
, name
, type
, state
};
2152 if (!output_show_job(&job
, strv_skip(args
, 1))) {
2157 if (!GREEDY_REALLOC(jobs
, size
, c
+ 1))
2163 return bus_log_parse_error(r
);
2165 r
= sd_bus_message_exit_container(reply
);
2167 return bus_log_parse_error(r
);
2169 output_jobs_list(jobs
, c
, skipped
);
2173 static int cancel_job(char **args
) {
2178 if (strv_length(args
) <= 1)
2179 return daemon_reload(args
);
2181 polkit_agent_open_if_enabled();
2183 r
= acquire_bus(BUS_MANAGER
, &bus
);
2187 STRV_FOREACH(name
, args
+1) {
2188 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2192 q
= safe_atou32(*name
, &id
);
2194 return log_error_errno(q
, "Failed to parse job id \"%s\": %m", *name
);
2196 q
= sd_bus_call_method(
2198 "org.freedesktop.systemd1",
2199 "/org/freedesktop/systemd1",
2200 "org.freedesktop.systemd1.Manager",
2206 log_error_errno(q
, "Failed to cancel job %"PRIu32
": %s", id
, bus_error_message(&error
, q
));
2215 static int need_daemon_reload(sd_bus
*bus
, const char *unit
) {
2216 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2220 /* We ignore all errors here, since this is used to show a
2223 /* We don't use unit_dbus_path_from_name() directly since we
2224 * don't want to load the unit if it isn't loaded. */
2226 r
= sd_bus_call_method(
2228 "org.freedesktop.systemd1",
2229 "/org/freedesktop/systemd1",
2230 "org.freedesktop.systemd1.Manager",
2238 r
= sd_bus_message_read(reply
, "o", &path
);
2242 r
= sd_bus_get_property_trivial(
2244 "org.freedesktop.systemd1",
2246 "org.freedesktop.systemd1.Unit",
2256 static void warn_unit_file_changed(const char *name
) {
2257 log_warning("%sWarning:%s %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
2258 ansi_highlight_red(),
2261 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user");
2264 static int unit_file_find_path(LookupPaths
*lp
, const char *unit_name
, char **unit_path
) {
2271 STRV_FOREACH(p
, lp
->unit_path
) {
2272 _cleanup_free_
char *path
;
2274 path
= path_join(arg_root
, *p
, unit_name
);
2278 if (access(path
, F_OK
) == 0) {
2288 static int unit_find_paths(
2290 const char *unit_name
,
2292 char **fragment_path
,
2293 char ***dropin_paths
) {
2295 _cleanup_free_
char *path
= NULL
;
2296 _cleanup_strv_free_
char **dropins
= NULL
;
2300 * Finds where the unit is defined on disk. Returns 0 if the unit
2301 * is not found. Returns 1 if it is found, and sets
2302 * - the path to the unit in *path, if it exists on disk,
2303 * - and a strv of existing drop-ins in *dropins,
2304 * if the arg is not NULL and any dropins were found.
2308 assert(fragment_path
);
2311 if (!install_client_side() && !unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
2312 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2313 _cleanup_bus_message_unref_ sd_bus_message
*unit_load_error
= NULL
;
2314 _cleanup_free_
char *unit
= NULL
;
2315 char *unit_load_error_name
, *unit_load_error_message
;
2317 unit
= unit_dbus_path_from_name(unit_name
);
2321 if (need_daemon_reload(bus
, unit_name
) > 0)
2322 warn_unit_file_changed(unit_name
);
2324 r
= sd_bus_get_property(
2326 "org.freedesktop.systemd1",
2328 "org.freedesktop.systemd1.Unit",
2334 return log_error_errno(r
, "Failed to get LoadError: %s", bus_error_message(&error
, r
));
2336 r
= sd_bus_message_read(
2339 &unit_load_error_name
,
2340 &unit_load_error_message
);
2342 return bus_log_parse_error(r
);
2344 if (!isempty(unit_load_error_name
)) {
2345 log_error("Unit %s is not loaded: %s", unit_name
, unit_load_error_message
);
2349 r
= sd_bus_get_property_string(
2351 "org.freedesktop.systemd1",
2353 "org.freedesktop.systemd1.Unit",
2358 return log_error_errno(r
, "Failed to get FragmentPath: %s", bus_error_message(&error
, r
));
2361 r
= sd_bus_get_property_strv(
2363 "org.freedesktop.systemd1",
2365 "org.freedesktop.systemd1.Unit",
2370 return log_error_errno(r
, "Failed to get DropInPaths: %s", bus_error_message(&error
, r
));
2373 _cleanup_set_free_ Set
*names
;
2375 names
= set_new(NULL
);
2379 r
= set_put(names
, unit_name
);
2381 return log_error_errno(r
, "Failed to add unit name: %m");
2383 r
= unit_file_find_path(lp
, unit_name
, &path
);
2388 _cleanup_free_
char *template = NULL
;
2390 r
= unit_name_template(unit_name
, &template);
2391 if (r
< 0 && r
!= -EINVAL
)
2392 return log_error_errno(r
, "Failed to determine template name: %m");
2394 r
= unit_file_find_path(lp
, template, &path
);
2401 r
= unit_file_find_dropin_paths(lp
->unit_path
, NULL
, names
, &dropins
);
2409 if (!isempty(path
)) {
2410 *fragment_path
= path
;
2415 if (dropin_paths
&& !strv_isempty(dropins
)) {
2416 *dropin_paths
= dropins
;
2422 log_error("No files found for %s.", unit_name
);
2427 static int check_one_unit(sd_bus
*bus
, const char *name
, const char *good_states
, bool quiet
) {
2428 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2429 _cleanup_free_
char *n
= NULL
, *state
= NULL
;
2435 r
= unit_name_mangle(name
, UNIT_NAME_NOGLOB
, &n
);
2437 return log_error_errno(r
, "Failed to mangle unit name: %m");
2439 /* We don't use unit_dbus_path_from_name() directly since we
2440 * don't want to load the unit if it isn't loaded. */
2442 r
= sd_bus_call_method(
2444 "org.freedesktop.systemd1",
2445 "/org/freedesktop/systemd1",
2446 "org.freedesktop.systemd1.Manager",
2457 r
= sd_bus_message_read(reply
, "o", &path
);
2459 return bus_log_parse_error(r
);
2461 r
= sd_bus_get_property_string(
2463 "org.freedesktop.systemd1",
2465 "org.freedesktop.systemd1.Unit",
2478 return nulstr_contains(good_states
, state
);
2481 static int check_triggering_units(
2485 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2486 _cleanup_free_
char *path
= NULL
, *n
= NULL
, *state
= NULL
;
2487 _cleanup_strv_free_
char **triggered_by
= NULL
;
2488 bool print_warning_label
= true;
2492 r
= unit_name_mangle(name
, UNIT_NAME_NOGLOB
, &n
);
2494 return log_error_errno(r
, "Failed to mangle unit name: %m");
2496 path
= unit_dbus_path_from_name(n
);
2500 r
= sd_bus_get_property_string(
2502 "org.freedesktop.systemd1",
2504 "org.freedesktop.systemd1.Unit",
2509 return log_error_errno(r
, "Failed to get load state of %s: %s", n
, bus_error_message(&error
, r
));
2511 if (streq(state
, "masked"))
2514 r
= sd_bus_get_property_strv(
2516 "org.freedesktop.systemd1",
2518 "org.freedesktop.systemd1.Unit",
2523 return log_error_errno(r
, "Failed to get triggered by array of %s: %s", n
, bus_error_message(&error
, r
));
2525 STRV_FOREACH(i
, triggered_by
) {
2526 r
= check_one_unit(bus
, *i
, "active\0reloading\0", true);
2528 return log_error_errno(r
, "Failed to check unit: %m");
2533 if (print_warning_label
) {
2534 log_warning("Warning: Stopping %s, but it can still be activated by:", n
);
2535 print_warning_label
= false;
2538 log_warning(" %s", *i
);
2544 static const struct {
2547 } unit_actions
[] = {
2548 { "start", "StartUnit" },
2549 { "stop", "StopUnit" },
2550 { "condstop", "StopUnit" },
2551 { "reload", "ReloadUnit" },
2552 { "restart", "RestartUnit" },
2553 { "try-restart", "TryRestartUnit" },
2554 { "condrestart", "TryRestartUnit" },
2555 { "reload-or-restart", "ReloadOrRestartUnit" },
2556 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2557 { "condreload", "ReloadOrTryRestartUnit" },
2558 { "force-reload", "ReloadOrTryRestartUnit" }
2561 static const char *verb_to_method(const char *verb
) {
2564 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2565 if (streq_ptr(unit_actions
[i
].verb
, verb
))
2566 return unit_actions
[i
].method
;
2571 static const char *method_to_verb(const char *method
) {
2574 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2575 if (streq_ptr(unit_actions
[i
].method
, method
))
2576 return unit_actions
[i
].verb
;
2581 static int start_unit_one(
2586 sd_bus_error
*error
,
2587 BusWaitForJobs
*w
) {
2589 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2598 log_debug("Calling manager for %s on %s, %s", method
, name
, mode
);
2600 r
= sd_bus_call_method(
2602 "org.freedesktop.systemd1",
2603 "/org/freedesktop/systemd1",
2604 "org.freedesktop.systemd1.Manager",
2612 if (r
== -ENOENT
&& arg_action
!= ACTION_SYSTEMCTL
)
2613 /* There's always a fallback possible for
2614 * legacy actions. */
2615 return -EADDRNOTAVAIL
;
2617 verb
= method_to_verb(method
);
2619 return log_error_errno(r
, "Failed to %s %s: %s", verb
, name
, bus_error_message(error
, r
));
2622 r
= sd_bus_message_read(reply
, "o", &path
);
2624 return bus_log_parse_error(r
);
2626 if (need_daemon_reload(bus
, name
) > 0)
2627 warn_unit_file_changed(name
);
2630 log_debug("Adding %s to the set", path
);
2631 r
= bus_wait_for_jobs_add(w
, path
);
2639 static int expand_names(sd_bus
*bus
, char **names
, const char* suffix
, char ***ret
) {
2640 _cleanup_strv_free_
char **mangled
= NULL
, **globs
= NULL
;
2647 STRV_FOREACH(name
, names
) {
2651 r
= unit_name_mangle_with_suffix(*name
, UNIT_NAME_GLOB
, suffix
, &t
);
2653 r
= unit_name_mangle(*name
, UNIT_NAME_GLOB
, &t
);
2655 return log_error_errno(r
, "Failed to mangle name: %m");
2657 if (string_is_glob(t
))
2658 r
= strv_consume(&globs
, t
);
2660 r
= strv_consume(&mangled
, t
);
2665 /* Query the manager only if any of the names are a glob, since
2666 * this is fairly expensive */
2667 if (!strv_isempty(globs
)) {
2668 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2669 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
2671 r
= get_unit_list(bus
, NULL
, globs
, &unit_infos
, 0, &reply
);
2675 for (i
= 0; i
< r
; i
++)
2676 if (strv_extend(&mangled
, unit_infos
[i
].id
) < 0)
2681 mangled
= NULL
; /* do not free */
2686 static const struct {
2690 } action_table
[_ACTION_MAX
] = {
2691 [ACTION_HALT
] = { SPECIAL_HALT_TARGET
, "halt", "replace-irreversibly" },
2692 [ACTION_POWEROFF
] = { SPECIAL_POWEROFF_TARGET
, "poweroff", "replace-irreversibly" },
2693 [ACTION_REBOOT
] = { SPECIAL_REBOOT_TARGET
, "reboot", "replace-irreversibly" },
2694 [ACTION_KEXEC
] = { SPECIAL_KEXEC_TARGET
, "kexec", "replace-irreversibly" },
2695 [ACTION_RUNLEVEL2
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2696 [ACTION_RUNLEVEL3
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2697 [ACTION_RUNLEVEL4
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2698 [ACTION_RUNLEVEL5
] = { SPECIAL_GRAPHICAL_TARGET
, NULL
, "isolate" },
2699 [ACTION_RESCUE
] = { SPECIAL_RESCUE_TARGET
, "rescue", "isolate" },
2700 [ACTION_EMERGENCY
] = { SPECIAL_EMERGENCY_TARGET
, "emergency", "isolate" },
2701 [ACTION_DEFAULT
] = { SPECIAL_DEFAULT_TARGET
, "default", "isolate" },
2702 [ACTION_EXIT
] = { SPECIAL_EXIT_TARGET
, "exit", "replace-irreversibly" },
2703 [ACTION_SUSPEND
] = { SPECIAL_SUSPEND_TARGET
, "suspend", "replace-irreversibly" },
2704 [ACTION_HIBERNATE
] = { SPECIAL_HIBERNATE_TARGET
, "hibernate", "replace-irreversibly" },
2705 [ACTION_HYBRID_SLEEP
] = { SPECIAL_HYBRID_SLEEP_TARGET
, "hybrid-sleep", "replace-irreversibly" },
2708 static enum action
verb_to_action(const char *verb
) {
2711 for (i
= _ACTION_INVALID
; i
< _ACTION_MAX
; i
++)
2712 if (streq_ptr(action_table
[i
].verb
, verb
))
2715 return _ACTION_INVALID
;
2718 static int start_unit(char **args
) {
2719 _cleanup_(bus_wait_for_jobs_freep
) BusWaitForJobs
*w
= NULL
;
2720 const char *method
, *mode
, *one_name
, *suffix
= NULL
;
2721 _cleanup_strv_free_
char **names
= NULL
;
2726 ask_password_agent_open_if_enabled();
2727 polkit_agent_open_if_enabled();
2729 r
= acquire_bus(BUS_MANAGER
, &bus
);
2733 if (arg_action
== ACTION_SYSTEMCTL
) {
2735 method
= verb_to_method(args
[0]);
2736 action
= verb_to_action(args
[0]);
2738 if (streq(args
[0], "isolate")) {
2742 mode
= action_table
[action
].mode
?: arg_job_mode
;
2744 one_name
= action_table
[action
].target
;
2746 assert(arg_action
< ELEMENTSOF(action_table
));
2747 assert(action_table
[arg_action
].target
);
2749 method
= "StartUnit";
2751 mode
= action_table
[arg_action
].mode
;
2752 one_name
= action_table
[arg_action
].target
;
2756 names
= strv_new(one_name
, NULL
);
2758 r
= expand_names(bus
, strv_skip(args
, 1), suffix
, &names
);
2760 return log_error_errno(r
, "Failed to expand names: %m");
2763 if (!arg_no_block
) {
2764 r
= bus_wait_for_jobs_new(bus
, &w
);
2766 return log_error_errno(r
, "Could not watch jobs: %m");
2769 STRV_FOREACH(name
, names
) {
2770 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2773 q
= start_unit_one(bus
, method
, *name
, mode
, &error
, w
);
2774 if (r
>= 0 && q
< 0)
2775 r
= translate_bus_error_to_exit_status(q
, &error
);
2778 if (!arg_no_block
) {
2781 q
= bus_wait_for_jobs(w
, arg_quiet
);
2785 /* When stopping units, warn if they can still be triggered by
2786 * another active unit (socket, path, timer) */
2787 if (!arg_quiet
&& streq(method
, "StopUnit"))
2788 STRV_FOREACH(name
, names
)
2789 check_triggering_units(bus
, *name
);
2795 static int logind_set_wall_message(void) {
2797 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2799 _cleanup_free_
char *m
= NULL
;
2802 r
= acquire_bus(BUS_FULL
, &bus
);
2806 m
= strv_join(arg_wall
, " ");
2810 r
= sd_bus_call_method(
2812 "org.freedesktop.login1",
2813 "/org/freedesktop/login1",
2814 "org.freedesktop.login1.Manager",
2823 return log_warning_errno(r
, "Failed to set wall message, ignoring: %s", bus_error_message(&error
, r
));
2829 /* Ask systemd-logind, which might grant access to unprivileged users
2830 * through PolicyKit */
2831 static int logind_reboot(enum action a
) {
2833 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2834 const char *method
, *description
;
2838 polkit_agent_open_if_enabled();
2839 (void) logind_set_wall_message();
2841 r
= acquire_bus(BUS_FULL
, &bus
);
2849 description
= "reboot system";
2852 case ACTION_POWEROFF
:
2853 method
= "PowerOff";
2854 description
= "power off system";
2857 case ACTION_SUSPEND
:
2859 description
= "suspend system";
2862 case ACTION_HIBERNATE
:
2863 method
= "Hibernate";
2864 description
= "hibernate system";
2867 case ACTION_HYBRID_SLEEP
:
2868 method
= "HybridSleep";
2869 description
= "put system into hybrid sleep";
2876 r
= sd_bus_call_method(
2878 "org.freedesktop.login1",
2879 "/org/freedesktop/login1",
2880 "org.freedesktop.login1.Manager",
2884 "b", arg_ask_password
);
2886 return log_error_errno(r
, "Failed to %s via logind: %s", description
, bus_error_message(&error
, r
));
2894 static int logind_check_inhibitors(enum action a
) {
2896 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2897 _cleanup_strv_free_
char **sessions
= NULL
;
2898 const char *what
, *who
, *why
, *mode
;
2905 if (arg_ignore_inhibitors
|| arg_force
> 0)
2917 r
= acquire_bus(BUS_FULL
, &bus
);
2921 r
= sd_bus_call_method(
2923 "org.freedesktop.login1",
2924 "/org/freedesktop/login1",
2925 "org.freedesktop.login1.Manager",
2931 /* If logind is not around, then there are no inhibitors... */
2934 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssuu)");
2936 return bus_log_parse_error(r
);
2938 while ((r
= sd_bus_message_read(reply
, "(ssssuu)", &what
, &who
, &why
, &mode
, &uid
, &pid
)) > 0) {
2939 _cleanup_free_
char *comm
= NULL
, *user
= NULL
;
2940 _cleanup_strv_free_
char **sv
= NULL
;
2942 if (!streq(mode
, "block"))
2945 sv
= strv_split(what
, ":");
2949 if ((pid_t
) pid
< 0)
2950 return log_error_errno(ERANGE
, "Bad PID %"PRIu32
": %m", pid
);
2952 if (!strv_contains(sv
,
2957 ACTION_KEXEC
) ? "shutdown" : "sleep"))
2960 get_process_comm(pid
, &comm
);
2961 user
= uid_to_name(uid
);
2963 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT
" \"%s\", user %s), reason is \"%s\".",
2964 who
, (pid_t
) pid
, strna(comm
), strna(user
), why
);
2969 return bus_log_parse_error(r
);
2971 r
= sd_bus_message_exit_container(reply
);
2973 return bus_log_parse_error(r
);
2975 /* Check for current sessions */
2976 sd_get_sessions(&sessions
);
2977 STRV_FOREACH(s
, sessions
) {
2978 _cleanup_free_
char *type
= NULL
, *tty
= NULL
, *seat
= NULL
, *user
= NULL
, *service
= NULL
, *class = NULL
;
2980 if (sd_session_get_uid(*s
, &uid
) < 0 || uid
== getuid())
2983 if (sd_session_get_class(*s
, &class) < 0 || !streq(class, "user"))
2986 if (sd_session_get_type(*s
, &type
) < 0 || (!streq(type
, "x11") && !streq(type
, "tty")))
2989 sd_session_get_tty(*s
, &tty
);
2990 sd_session_get_seat(*s
, &seat
);
2991 sd_session_get_service(*s
, &service
);
2992 user
= uid_to_name(uid
);
2994 log_warning("User %s is logged in on %s.", strna(user
), isempty(tty
) ? (isempty(seat
) ? strna(service
) : seat
) : tty
);
3001 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
3002 action_table
[a
].verb
);
3010 static int logind_prepare_firmware_setup(void) {
3012 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
3016 r
= acquire_bus(BUS_FULL
, &bus
);
3020 r
= sd_bus_call_method(
3022 "org.freedesktop.login1",
3023 "/org/freedesktop/login1",
3024 "org.freedesktop.login1.Manager",
3025 "SetRebootToFirmwareSetup",
3030 return log_error_errno(r
, "Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error
, r
));
3034 log_error("Cannot remotely indicate to EFI to boot into setup mode.");
3039 static int prepare_firmware_setup(void) {
3042 if (!arg_firmware_setup
)
3045 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
3047 r
= efi_set_reboot_to_firmware(true);
3049 log_debug_errno(r
, "Cannot indicate to EFI to boot into setup mode, will retry via logind: %m");
3054 return logind_prepare_firmware_setup();
3057 static int start_special(char **args
) {
3063 a
= verb_to_action(args
[0]);
3065 r
= logind_check_inhibitors(a
);
3069 if (arg_force
>= 2 && geteuid() != 0) {
3070 log_error("Must be root.");
3074 r
= prepare_firmware_setup();
3078 if (a
== ACTION_REBOOT
&& args
[1]) {
3079 r
= update_reboot_param_file(args
[1]);
3082 } else if (a
== ACTION_EXIT
&& strv_length(args
) > 1) {
3083 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
3084 /* If the exit code is not given on the command line, don't
3085 * reset it to zero: just keep it as it might have been set
3090 r
= safe_atou8(args
[1], &code
);
3092 log_error("Invalid exit code.");
3096 r
= acquire_bus(BUS_MANAGER
, &bus
);
3100 r
= sd_bus_call_method(
3102 "org.freedesktop.systemd1",
3103 "/org/freedesktop/systemd1",
3104 "org.freedesktop.systemd1.Manager",
3110 return log_error_errno(r
, "Failed to execute operation: %s", bus_error_message(&error
, r
));
3113 if (arg_force
>= 2 &&
3120 if (arg_force
>= 1 &&
3127 return daemon_reload(args
);
3129 /* first try logind, to allow authentication with polkit */
3130 if (geteuid() != 0 &&
3136 ACTION_HYBRID_SLEEP
)) {
3137 r
= logind_reboot(a
);
3140 if (IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
3141 /* requested operation is not supported or already in progress */
3143 /* on all other errors, try low-level operation */
3146 return start_unit(args
);
3149 static int check_unit_generic(int code
, const char *good_states
, char **args
) {
3150 _cleanup_strv_free_
char **names
= NULL
;
3155 r
= acquire_bus(BUS_MANAGER
, &bus
);
3159 r
= expand_names(bus
, args
, NULL
, &names
);
3161 return log_error_errno(r
, "Failed to expand names: %m");
3163 STRV_FOREACH(name
, names
) {
3166 state
= check_one_unit(bus
, *name
, good_states
, arg_quiet
);
3176 static int check_unit_active(char **args
) {
3177 /* According to LSB: 3, "program is not running" */
3178 return check_unit_generic(3, "active\0reloading\0", strv_skip(args
, 1));
3181 static int check_unit_failed(char **args
) {
3182 return check_unit_generic(1, "failed\0", strv_skip(args
, 1));
3185 static int kill_unit(char **args
) {
3186 _cleanup_strv_free_
char **names
= NULL
;
3187 char *kill_who
= NULL
, **name
;
3191 polkit_agent_open_if_enabled();
3193 r
= acquire_bus(BUS_MANAGER
, &bus
);
3198 arg_kill_who
= "all";
3200 /* --fail was specified */
3201 if (streq(arg_job_mode
, "fail"))
3202 kill_who
= strjoina(arg_kill_who
, "-fail", NULL
);
3204 r
= expand_names(bus
, strv_skip(args
, 1), NULL
, &names
);
3206 return log_error_errno(r
, "Failed to expand names: %m");
3208 STRV_FOREACH(name
, names
) {
3209 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
3211 q
= sd_bus_call_method(
3213 "org.freedesktop.systemd1",
3214 "/org/freedesktop/systemd1",
3215 "org.freedesktop.systemd1.Manager",
3219 "ssi", *names
, kill_who
? kill_who
: arg_kill_who
, arg_signal
);
3221 log_error_errno(q
, "Failed to kill unit %s: %s", *names
, bus_error_message(&error
, q
));
3230 typedef struct ExecStatusInfo
{
3238 usec_t start_timestamp
;
3239 usec_t exit_timestamp
;
3244 LIST_FIELDS(struct ExecStatusInfo
, exec
);
3247 static void exec_status_info_free(ExecStatusInfo
*i
) {
3256 static int exec_status_info_deserialize(sd_bus_message
*m
, ExecStatusInfo
*i
) {
3257 uint64_t start_timestamp
, exit_timestamp
, start_timestamp_monotonic
, exit_timestamp_monotonic
;
3260 int32_t code
, status
;
3266 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_STRUCT
, "sasbttttuii");
3268 return bus_log_parse_error(r
);
3272 r
= sd_bus_message_read(m
, "s", &path
);
3274 return bus_log_parse_error(r
);
3276 i
->path
= strdup(path
);
3280 r
= sd_bus_message_read_strv(m
, &i
->argv
);
3282 return bus_log_parse_error(r
);
3284 r
= sd_bus_message_read(m
,
3287 &start_timestamp
, &start_timestamp_monotonic
,
3288 &exit_timestamp
, &exit_timestamp_monotonic
,
3292 return bus_log_parse_error(r
);
3295 i
->start_timestamp
= (usec_t
) start_timestamp
;
3296 i
->exit_timestamp
= (usec_t
) exit_timestamp
;
3297 i
->pid
= (pid_t
) pid
;
3301 r
= sd_bus_message_exit_container(m
);
3303 return bus_log_parse_error(r
);
3308 typedef struct UnitStatusInfo
{
3310 const char *load_state
;
3311 const char *active_state
;
3312 const char *sub_state
;
3313 const char *unit_file_state
;
3314 const char *unit_file_preset
;
3316 const char *description
;
3317 const char *following
;
3319 char **documentation
;
3321 const char *fragment_path
;
3322 const char *source_path
;
3323 const char *control_group
;
3325 char **dropin_paths
;
3327 const char *load_error
;
3330 usec_t inactive_exit_timestamp
;
3331 usec_t inactive_exit_timestamp_monotonic
;
3332 usec_t active_enter_timestamp
;
3333 usec_t active_exit_timestamp
;
3334 usec_t inactive_enter_timestamp
;
3336 bool need_daemon_reload
;
3341 const char *status_text
;
3342 const char *pid_file
;
3346 usec_t start_timestamp
;
3347 usec_t exit_timestamp
;
3349 int exit_code
, exit_status
;
3351 usec_t condition_timestamp
;
3352 bool condition_result
;
3353 bool failed_condition_trigger
;
3354 bool failed_condition_negate
;
3355 const char *failed_condition
;
3356 const char *failed_condition_parameter
;
3358 usec_t assert_timestamp
;
3360 bool failed_assert_trigger
;
3361 bool failed_assert_negate
;
3362 const char *failed_assert
;
3363 const char *failed_assert_parameter
;
3366 unsigned n_accepted
;
3367 unsigned n_connections
;
3370 /* Pairs of type, path */
3374 const char *sysfs_path
;
3376 /* Mount, Automount */
3383 uint64_t memory_current
;
3384 uint64_t memory_limit
;
3385 uint64_t cpu_usage_nsec
;
3386 uint64_t tasks_current
;
3389 LIST_HEAD(ExecStatusInfo
, exec
);
3392 static void print_status_info(
3397 const char *active_on
, *active_off
, *on
, *off
, *ss
;
3399 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], *s1
;
3400 char since2
[FORMAT_TIMESTAMP_MAX
], *s2
;
3406 /* This shows pretty information about a unit. See
3407 * print_property() for a low-level property printer */
3409 if (streq_ptr(i
->active_state
, "failed")) {
3410 active_on
= ansi_highlight_red();
3411 active_off
= ansi_normal();
3412 } else if (streq_ptr(i
->active_state
, "active") || streq_ptr(i
->active_state
, "reloading")) {
3413 active_on
= ansi_highlight_green();
3414 active_off
= ansi_normal();
3416 active_on
= active_off
= "";
3418 printf("%s%s%s %s", active_on
, draw_special_char(DRAW_BLACK_CIRCLE
), active_off
, strna(i
->id
));
3420 if (i
->description
&& !streq_ptr(i
->id
, i
->description
))
3421 printf(" - %s", i
->description
);
3426 printf(" Follow: unit currently follows state of %s\n", i
->following
);
3428 if (streq_ptr(i
->load_state
, "error")) {
3429 on
= ansi_highlight_red();
3430 off
= ansi_normal();
3434 path
= i
->source_path
? i
->source_path
: i
->fragment_path
;
3437 printf(" Loaded: %s%s%s (Reason: %s)\n",
3438 on
, strna(i
->load_state
), off
, i
->load_error
);
3439 else if (path
&& !isempty(i
->unit_file_state
) && !isempty(i
->unit_file_preset
))
3440 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
3441 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
, i
->unit_file_preset
);
3442 else if (path
&& !isempty(i
->unit_file_state
))
3443 printf(" Loaded: %s%s%s (%s; %s)\n",
3444 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
);
3446 printf(" Loaded: %s%s%s (%s)\n",
3447 on
, strna(i
->load_state
), off
, path
);
3449 printf(" Loaded: %s%s%s\n",
3450 on
, strna(i
->load_state
), off
);
3452 if (!strv_isempty(i
->dropin_paths
)) {
3453 _cleanup_free_
char *dir
= NULL
;
3457 STRV_FOREACH(dropin
, i
->dropin_paths
) {
3458 if (! dir
|| last
) {
3459 printf(dir
? " " : " Drop-In: ");
3463 if (path_get_parent(*dropin
, &dir
) < 0) {
3468 printf("%s\n %s", dir
,
3469 draw_special_char(DRAW_TREE_RIGHT
));
3472 last
= ! (*(dropin
+ 1) && startswith(*(dropin
+ 1), dir
));
3474 printf("%s%s", basename(*dropin
), last
? "\n" : ", ");
3478 ss
= streq_ptr(i
->active_state
, i
->sub_state
) ? NULL
: i
->sub_state
;
3480 printf(" Active: %s%s (%s)%s",
3481 active_on
, strna(i
->active_state
), ss
, active_off
);
3483 printf(" Active: %s%s%s",
3484 active_on
, strna(i
->active_state
), active_off
);
3486 if (!isempty(i
->result
) && !streq(i
->result
, "success"))
3487 printf(" (Result: %s)", i
->result
);
3489 timestamp
= (streq_ptr(i
->active_state
, "active") ||
3490 streq_ptr(i
->active_state
, "reloading")) ? i
->active_enter_timestamp
:
3491 (streq_ptr(i
->active_state
, "inactive") ||
3492 streq_ptr(i
->active_state
, "failed")) ? i
->inactive_enter_timestamp
:
3493 streq_ptr(i
->active_state
, "activating") ? i
->inactive_exit_timestamp
:
3494 i
->active_exit_timestamp
;
3496 s1
= format_timestamp_relative(since1
, sizeof(since1
), timestamp
);
3497 s2
= format_timestamp(since2
, sizeof(since2
), timestamp
);
3500 printf(" since %s; %s\n", s2
, s1
);
3502 printf(" since %s\n", s2
);
3506 if (!i
->condition_result
&& i
->condition_timestamp
> 0) {
3507 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->condition_timestamp
);
3508 s2
= format_timestamp(since2
, sizeof(since2
), i
->condition_timestamp
);
3510 printf("Condition: start %scondition failed%s at %s%s%s\n",
3511 ansi_highlight_yellow(), ansi_normal(),
3512 s2
, s1
? "; " : "", s1
? s1
: "");
3513 if (i
->failed_condition_trigger
)
3514 printf(" none of the trigger conditions were met\n");
3515 else if (i
->failed_condition
)
3516 printf(" %s=%s%s was not met\n",
3517 i
->failed_condition
,
3518 i
->failed_condition_negate
? "!" : "",
3519 i
->failed_condition_parameter
);
3522 if (!i
->assert_result
&& i
->assert_timestamp
> 0) {
3523 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->assert_timestamp
);
3524 s2
= format_timestamp(since2
, sizeof(since2
), i
->assert_timestamp
);
3526 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
3527 ansi_highlight_red(), ansi_normal(),
3528 s2
, s1
? "; " : "", s1
? s1
: "");
3529 if (i
->failed_assert_trigger
)
3530 printf(" none of the trigger assertions were met\n");
3531 else if (i
->failed_assert
)
3532 printf(" %s=%s%s was not met\n",
3534 i
->failed_assert_negate
? "!" : "",
3535 i
->failed_assert_parameter
);
3539 printf(" Device: %s\n", i
->sysfs_path
);
3541 printf(" Where: %s\n", i
->where
);
3543 printf(" What: %s\n", i
->what
);
3545 STRV_FOREACH(t
, i
->documentation
)
3546 printf(" %*s %s\n", 9, t
== i
->documentation
? "Docs:" : "", *t
);
3548 STRV_FOREACH_PAIR(t
, t2
, i
->listen
)
3549 printf(" %*s %s (%s)\n", 9, t
== i
->listen
? "Listen:" : "", *t2
, *t
);
3552 printf(" Accepted: %u; Connected: %u\n", i
->n_accepted
, i
->n_connections
);
3554 LIST_FOREACH(exec
, p
, i
->exec
) {
3555 _cleanup_free_
char *argv
= NULL
;
3558 /* Only show exited processes here */
3562 argv
= strv_join(p
->argv
, " ");
3563 printf(" Process: "PID_FMT
" %s=%s ", p
->pid
, p
->name
, strna(argv
));
3565 good
= is_clean_exit_lsb(p
->code
, p
->status
, NULL
);
3567 on
= ansi_highlight_red();
3568 off
= ansi_normal();
3572 printf("%s(code=%s, ", on
, sigchld_code_to_string(p
->code
));
3574 if (p
->code
== CLD_EXITED
) {
3577 printf("status=%i", p
->status
);
3579 c
= exit_status_to_string(p
->status
, EXIT_STATUS_SYSTEMD
);
3584 printf("signal=%s", signal_to_string(p
->status
));
3586 printf(")%s\n", off
);
3588 if (i
->main_pid
== p
->pid
&&
3589 i
->start_timestamp
== p
->start_timestamp
&&
3590 i
->exit_timestamp
== p
->start_timestamp
)
3591 /* Let's not show this twice */
3594 if (p
->pid
== i
->control_pid
)
3598 if (i
->main_pid
> 0 || i
->control_pid
> 0) {
3599 if (i
->main_pid
> 0) {
3600 printf(" Main PID: "PID_FMT
, i
->main_pid
);
3603 _cleanup_free_
char *comm
= NULL
;
3604 get_process_comm(i
->main_pid
, &comm
);
3606 printf(" (%s)", comm
);
3607 } else if (i
->exit_code
> 0) {
3608 printf(" (code=%s, ", sigchld_code_to_string(i
->exit_code
));
3610 if (i
->exit_code
== CLD_EXITED
) {
3613 printf("status=%i", i
->exit_status
);
3615 c
= exit_status_to_string(i
->exit_status
, EXIT_STATUS_SYSTEMD
);
3620 printf("signal=%s", signal_to_string(i
->exit_status
));
3624 if (i
->control_pid
> 0)
3628 if (i
->control_pid
> 0) {
3629 _cleanup_free_
char *c
= NULL
;
3631 printf(" %8s: "PID_FMT
, i
->main_pid
? "" : " Control", i
->control_pid
);
3633 get_process_comm(i
->control_pid
, &c
);
3642 printf(" Status: \"%s\"\n", i
->status_text
);
3643 if (i
->status_errno
> 0)
3644 printf(" Error: %i (%s)\n", i
->status_errno
, strerror(i
->status_errno
));
3646 if (i
->tasks_current
!= (uint64_t) -1) {
3647 printf(" Tasks: %" PRIu64
, i
->tasks_current
);
3649 if (i
->tasks_max
!= (uint64_t) -1)
3650 printf(" (limit: %" PRIi64
")\n", i
->tasks_max
);
3655 if (i
->memory_current
!= (uint64_t) -1) {
3656 char buf
[FORMAT_BYTES_MAX
];
3658 printf(" Memory: %s", format_bytes(buf
, sizeof(buf
), i
->memory_current
));
3660 if (i
->memory_limit
!= (uint64_t) -1)
3661 printf(" (limit: %s)\n", format_bytes(buf
, sizeof(buf
), i
->memory_limit
));
3666 if (i
->cpu_usage_nsec
!= (uint64_t) -1) {
3667 char buf
[FORMAT_TIMESPAN_MAX
];
3668 printf(" CPU: %s\n", format_timespan(buf
, sizeof(buf
), i
->cpu_usage_nsec
/ NSEC_PER_USEC
, USEC_PER_MSEC
));
3671 if (i
->control_group
&&
3672 (i
->main_pid
> 0 || i
->control_pid
> 0 ||
3673 (!IN_SET(arg_transport
, BUS_TRANSPORT_LOCAL
, BUS_TRANSPORT_MACHINE
) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
) == 0))) {
3676 printf(" CGroup: %s\n", i
->control_group
);
3678 if (IN_SET(arg_transport
,
3679 BUS_TRANSPORT_LOCAL
,
3680 BUS_TRANSPORT_MACHINE
)) {
3683 static const char prefix
[] = " ";
3686 if (c
> sizeof(prefix
) - 1)
3687 c
-= sizeof(prefix
) - 1;
3691 if (i
->main_pid
> 0)
3692 extra
[k
++] = i
->main_pid
;
3694 if (i
->control_pid
> 0)
3695 extra
[k
++] = i
->control_pid
;
3697 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, prefix
, c
, false, extra
, k
, get_output_flags());
3701 if (i
->id
&& arg_transport
== BUS_TRANSPORT_LOCAL
)
3702 show_journal_by_unit(
3707 i
->inactive_exit_timestamp_monotonic
,
3710 get_output_flags() | OUTPUT_BEGIN_NEWLINE
,
3711 SD_JOURNAL_LOCAL_ONLY
,
3712 arg_scope
== UNIT_FILE_SYSTEM
,
3715 if (i
->need_daemon_reload
)
3716 warn_unit_file_changed(i
->id
);
3719 static void show_unit_help(UnitStatusInfo
*i
) {
3724 if (!i
->documentation
) {
3725 log_info("Documentation for %s not known.", i
->id
);
3729 STRV_FOREACH(p
, i
->documentation
)
3730 if (startswith(*p
, "man:"))
3731 show_man_page(*p
+ 4, false);
3733 log_info("Can't show: %s", *p
);
3736 static int status_property(const char *name
, sd_bus_message
*m
, UnitStatusInfo
*i
, const char *contents
) {
3743 switch (contents
[0]) {
3745 case SD_BUS_TYPE_STRING
: {
3748 r
= sd_bus_message_read(m
, "s", &s
);
3750 return bus_log_parse_error(r
);
3753 if (streq(name
, "Id"))
3755 else if (streq(name
, "LoadState"))
3757 else if (streq(name
, "ActiveState"))
3758 i
->active_state
= s
;
3759 else if (streq(name
, "SubState"))
3761 else if (streq(name
, "Description"))
3763 else if (streq(name
, "FragmentPath"))
3764 i
->fragment_path
= s
;
3765 else if (streq(name
, "SourcePath"))
3768 else if (streq(name
, "DefaultControlGroup")) {
3770 e
= startswith(s
, SYSTEMD_CGROUP_CONTROLLER
":");
3772 i
->control_group
= e
;
3775 else if (streq(name
, "ControlGroup"))
3776 i
->control_group
= s
;
3777 else if (streq(name
, "StatusText"))
3779 else if (streq(name
, "PIDFile"))
3781 else if (streq(name
, "SysFSPath"))
3783 else if (streq(name
, "Where"))
3785 else if (streq(name
, "What"))
3787 else if (streq(name
, "Following"))
3789 else if (streq(name
, "UnitFileState"))
3790 i
->unit_file_state
= s
;
3791 else if (streq(name
, "UnitFilePreset"))
3792 i
->unit_file_preset
= s
;
3793 else if (streq(name
, "Result"))
3800 case SD_BUS_TYPE_BOOLEAN
: {
3803 r
= sd_bus_message_read(m
, "b", &b
);
3805 return bus_log_parse_error(r
);
3807 if (streq(name
, "Accept"))
3809 else if (streq(name
, "NeedDaemonReload"))
3810 i
->need_daemon_reload
= b
;
3811 else if (streq(name
, "ConditionResult"))
3812 i
->condition_result
= b
;
3813 else if (streq(name
, "AssertResult"))
3814 i
->assert_result
= b
;
3819 case SD_BUS_TYPE_UINT32
: {
3822 r
= sd_bus_message_read(m
, "u", &u
);
3824 return bus_log_parse_error(r
);
3826 if (streq(name
, "MainPID")) {
3828 i
->main_pid
= (pid_t
) u
;
3831 } else if (streq(name
, "ControlPID"))
3832 i
->control_pid
= (pid_t
) u
;
3833 else if (streq(name
, "ExecMainPID")) {
3835 i
->main_pid
= (pid_t
) u
;
3836 } else if (streq(name
, "NAccepted"))
3838 else if (streq(name
, "NConnections"))
3839 i
->n_connections
= u
;
3844 case SD_BUS_TYPE_INT32
: {
3847 r
= sd_bus_message_read(m
, "i", &j
);
3849 return bus_log_parse_error(r
);
3851 if (streq(name
, "ExecMainCode"))
3852 i
->exit_code
= (int) j
;
3853 else if (streq(name
, "ExecMainStatus"))
3854 i
->exit_status
= (int) j
;
3855 else if (streq(name
, "StatusErrno"))
3856 i
->status_errno
= (int) j
;
3861 case SD_BUS_TYPE_UINT64
: {
3864 r
= sd_bus_message_read(m
, "t", &u
);
3866 return bus_log_parse_error(r
);
3868 if (streq(name
, "ExecMainStartTimestamp"))
3869 i
->start_timestamp
= (usec_t
) u
;
3870 else if (streq(name
, "ExecMainExitTimestamp"))
3871 i
->exit_timestamp
= (usec_t
) u
;
3872 else if (streq(name
, "ActiveEnterTimestamp"))
3873 i
->active_enter_timestamp
= (usec_t
) u
;
3874 else if (streq(name
, "InactiveEnterTimestamp"))
3875 i
->inactive_enter_timestamp
= (usec_t
) u
;
3876 else if (streq(name
, "InactiveExitTimestamp"))
3877 i
->inactive_exit_timestamp
= (usec_t
) u
;
3878 else if (streq(name
, "InactiveExitTimestampMonotonic"))
3879 i
->inactive_exit_timestamp_monotonic
= (usec_t
) u
;
3880 else if (streq(name
, "ActiveExitTimestamp"))
3881 i
->active_exit_timestamp
= (usec_t
) u
;
3882 else if (streq(name
, "ConditionTimestamp"))
3883 i
->condition_timestamp
= (usec_t
) u
;
3884 else if (streq(name
, "AssertTimestamp"))
3885 i
->assert_timestamp
= (usec_t
) u
;
3886 else if (streq(name
, "MemoryCurrent"))
3887 i
->memory_current
= u
;
3888 else if (streq(name
, "MemoryLimit"))
3889 i
->memory_limit
= u
;
3890 else if (streq(name
, "TasksCurrent"))
3891 i
->tasks_current
= u
;
3892 else if (streq(name
, "TasksMax"))
3894 else if (streq(name
, "CPUUsageNSec"))
3895 i
->cpu_usage_nsec
= u
;
3900 case SD_BUS_TYPE_ARRAY
:
3902 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
3903 _cleanup_free_ ExecStatusInfo
*info
= NULL
;
3905 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
3907 return bus_log_parse_error(r
);
3909 info
= new0(ExecStatusInfo
, 1);
3913 while ((r
= exec_status_info_deserialize(m
, info
)) > 0) {
3915 info
->name
= strdup(name
);
3919 LIST_PREPEND(exec
, i
->exec
, info
);
3921 info
= new0(ExecStatusInfo
, 1);
3927 return bus_log_parse_error(r
);
3929 r
= sd_bus_message_exit_container(m
);
3931 return bus_log_parse_error(r
);
3935 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
3936 const char *type
, *path
;
3938 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
3940 return bus_log_parse_error(r
);
3942 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0) {
3944 r
= strv_extend(&i
->listen
, type
);
3948 r
= strv_extend(&i
->listen
, path
);
3953 return bus_log_parse_error(r
);
3955 r
= sd_bus_message_exit_container(m
);
3957 return bus_log_parse_error(r
);
3961 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "DropInPaths")) {
3963 r
= sd_bus_message_read_strv(m
, &i
->dropin_paths
);
3965 return bus_log_parse_error(r
);
3967 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Documentation")) {
3969 r
= sd_bus_message_read_strv(m
, &i
->documentation
);
3971 return bus_log_parse_error(r
);
3973 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Conditions")) {
3974 const char *cond
, *param
;
3975 int trigger
, negate
;
3978 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
3980 return bus_log_parse_error(r
);
3982 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
3983 log_debug("%s %d %d %s %d", cond
, trigger
, negate
, param
, state
);
3984 if (state
< 0 && (!trigger
|| !i
->failed_condition
)) {
3985 i
->failed_condition
= cond
;
3986 i
->failed_condition_trigger
= trigger
;
3987 i
->failed_condition_negate
= negate
;
3988 i
->failed_condition_parameter
= param
;
3992 return bus_log_parse_error(r
);
3994 r
= sd_bus_message_exit_container(m
);
3996 return bus_log_parse_error(r
);
3998 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Asserts")) {
3999 const char *cond
, *param
;
4000 int trigger
, negate
;
4003 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
4005 return bus_log_parse_error(r
);
4007 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
4008 log_debug("%s %d %d %s %d", cond
, trigger
, negate
, param
, state
);
4009 if (state
< 0 && (!trigger
|| !i
->failed_assert
)) {
4010 i
->failed_assert
= cond
;
4011 i
->failed_assert_trigger
= trigger
;
4012 i
->failed_assert_negate
= negate
;
4013 i
->failed_assert_parameter
= param
;
4017 return bus_log_parse_error(r
);
4019 r
= sd_bus_message_exit_container(m
);
4021 return bus_log_parse_error(r
);
4028 case SD_BUS_TYPE_STRUCT_BEGIN
:
4030 if (streq(name
, "LoadError")) {
4031 const char *n
, *message
;
4033 r
= sd_bus_message_read(m
, "(ss)", &n
, &message
);
4035 return bus_log_parse_error(r
);
4037 if (!isempty(message
))
4038 i
->load_error
= message
;
4051 r
= sd_bus_message_skip(m
, contents
);
4053 return bus_log_parse_error(r
);
4058 static int print_property(const char *name
, sd_bus_message
*m
, const char *contents
) {
4064 /* This is a low-level property printer, see
4065 * print_status_info() for the nicer output */
4067 if (arg_properties
&& !strv_find(arg_properties
, name
)) {
4068 /* skip what we didn't read */
4069 r
= sd_bus_message_skip(m
, contents
);
4073 switch (contents
[0]) {
4075 case SD_BUS_TYPE_STRUCT_BEGIN
:
4077 if (contents
[1] == SD_BUS_TYPE_UINT32
&& streq(name
, "Job")) {
4080 r
= sd_bus_message_read(m
, "(uo)", &u
, NULL
);
4082 return bus_log_parse_error(r
);
4085 printf("%s=%"PRIu32
"\n", name
, u
);
4087 printf("%s=\n", name
);
4091 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Unit")) {
4094 r
= sd_bus_message_read(m
, "(so)", &s
, NULL
);
4096 return bus_log_parse_error(r
);
4098 if (arg_all
|| !isempty(s
))
4099 printf("%s=%s\n", name
, s
);
4103 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "LoadError")) {
4104 const char *a
= NULL
, *b
= NULL
;
4106 r
= sd_bus_message_read(m
, "(ss)", &a
, &b
);
4108 return bus_log_parse_error(r
);
4110 if (arg_all
|| !isempty(a
) || !isempty(b
))
4111 printf("%s=%s \"%s\"\n", name
, strempty(a
), strempty(b
));
4114 } else if (streq_ptr(name
, "SystemCallFilter")) {
4115 _cleanup_strv_free_
char **l
= NULL
;
4118 r
= sd_bus_message_enter_container(m
, 'r', "bas");
4120 return bus_log_parse_error(r
);
4122 r
= sd_bus_message_read(m
, "b", &whitelist
);
4124 return bus_log_parse_error(r
);
4126 r
= sd_bus_message_read_strv(m
, &l
);
4128 return bus_log_parse_error(r
);
4130 r
= sd_bus_message_exit_container(m
);
4132 return bus_log_parse_error(r
);
4134 if (arg_all
|| whitelist
|| !strv_isempty(l
)) {
4138 fputs(name
, stdout
);
4144 STRV_FOREACH(i
, l
) {
4152 fputc('\n', stdout
);
4160 case SD_BUS_TYPE_ARRAY
:
4162 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "EnvironmentFiles")) {
4166 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sb)");
4168 return bus_log_parse_error(r
);
4170 while ((r
= sd_bus_message_read(m
, "(sb)", &path
, &ignore
)) > 0)
4171 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path
, yes_no(ignore
));
4174 return bus_log_parse_error(r
);
4176 r
= sd_bus_message_exit_container(m
);
4178 return bus_log_parse_error(r
);
4182 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Paths")) {
4183 const char *type
, *path
;
4185 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4187 return bus_log_parse_error(r
);
4189 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4190 printf("%s=%s\n", type
, path
);
4192 return bus_log_parse_error(r
);
4194 r
= sd_bus_message_exit_container(m
);
4196 return bus_log_parse_error(r
);
4200 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
4201 const char *type
, *path
;
4203 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4205 return bus_log_parse_error(r
);
4207 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4208 printf("Listen%s=%s\n", type
, path
);
4210 return bus_log_parse_error(r
);
4212 r
= sd_bus_message_exit_container(m
);
4214 return bus_log_parse_error(r
);
4218 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Timers")) {
4220 uint64_t value
, next_elapse
;
4222 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(stt)");
4224 return bus_log_parse_error(r
);
4226 while ((r
= sd_bus_message_read(m
, "(stt)", &base
, &value
, &next_elapse
)) > 0) {
4227 char timespan1
[FORMAT_TIMESPAN_MAX
], timespan2
[FORMAT_TIMESPAN_MAX
];
4229 printf("%s={ value=%s ; next_elapse=%s }\n",
4231 format_timespan(timespan1
, sizeof(timespan1
), value
, 0),
4232 format_timespan(timespan2
, sizeof(timespan2
), next_elapse
, 0));
4235 return bus_log_parse_error(r
);
4237 r
= sd_bus_message_exit_container(m
);
4239 return bus_log_parse_error(r
);
4243 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
4244 ExecStatusInfo info
= {};
4246 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4248 return bus_log_parse_error(r
);
4250 while ((r
= exec_status_info_deserialize(m
, &info
)) > 0) {
4251 char timestamp1
[FORMAT_TIMESTAMP_MAX
], timestamp2
[FORMAT_TIMESTAMP_MAX
];
4252 _cleanup_free_
char *tt
;
4254 tt
= strv_join(info
.argv
, " ");
4256 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",
4260 yes_no(info
.ignore
),
4261 strna(format_timestamp(timestamp1
, sizeof(timestamp1
), info
.start_timestamp
)),
4262 strna(format_timestamp(timestamp2
, sizeof(timestamp2
), info
.exit_timestamp
)),
4264 sigchld_code_to_string(info
.code
),
4266 info
.code
== CLD_EXITED
? "" : "/",
4267 strempty(info
.code
== CLD_EXITED
? NULL
: signal_to_string(info
.status
)));
4270 strv_free(info
.argv
);
4274 r
= sd_bus_message_exit_container(m
);
4276 return bus_log_parse_error(r
);
4280 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "DeviceAllow")) {
4281 const char *path
, *rwm
;
4283 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4285 return bus_log_parse_error(r
);
4287 while ((r
= sd_bus_message_read(m
, "(ss)", &path
, &rwm
)) > 0)
4288 printf("%s=%s %s\n", name
, strna(path
), strna(rwm
));
4290 return bus_log_parse_error(r
);
4292 r
= sd_bus_message_exit_container(m
);
4294 return bus_log_parse_error(r
);
4298 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "BlockIODeviceWeight")) {
4302 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4304 return bus_log_parse_error(r
);
4306 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &weight
)) > 0)
4307 printf("%s=%s %" PRIu64
"\n", name
, strna(path
), weight
);
4309 return bus_log_parse_error(r
);
4311 r
= sd_bus_message_exit_container(m
);
4313 return bus_log_parse_error(r
);
4317 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& (streq(name
, "BlockIOReadBandwidth") || streq(name
, "BlockIOWriteBandwidth"))) {
4321 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4323 return bus_log_parse_error(r
);
4325 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &bandwidth
)) > 0)
4326 printf("%s=%s %" PRIu64
"\n", name
, strna(path
), bandwidth
);
4328 return bus_log_parse_error(r
);
4330 r
= sd_bus_message_exit_container(m
);
4332 return bus_log_parse_error(r
);
4340 r
= bus_print_property(name
, m
, arg_all
);
4342 return bus_log_parse_error(r
);
4345 r
= sd_bus_message_skip(m
, contents
);
4347 return bus_log_parse_error(r
);
4350 printf("%s=[unprintable]\n", name
);
4356 static int show_one(
4360 bool show_properties
,
4364 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4365 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4366 UnitStatusInfo info
= {
4367 .memory_current
= (uint64_t) -1,
4368 .memory_limit
= (uint64_t) -1,
4369 .cpu_usage_nsec
= (uint64_t) -1,
4370 .tasks_current
= (uint64_t) -1,
4371 .tasks_max
= (uint64_t) -1,
4379 log_debug("Showing one %s", path
);
4381 r
= sd_bus_call_method(
4383 "org.freedesktop.systemd1",
4385 "org.freedesktop.DBus.Properties",
4391 return log_error_errno(r
, "Failed to get properties: %s", bus_error_message(&error
, r
));
4393 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
4395 return bus_log_parse_error(r
);
4402 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
4403 const char *name
, *contents
;
4405 r
= sd_bus_message_read(reply
, "s", &name
);
4407 return bus_log_parse_error(r
);
4409 r
= sd_bus_message_peek_type(reply
, NULL
, &contents
);
4411 return bus_log_parse_error(r
);
4413 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, contents
);
4415 return bus_log_parse_error(r
);
4417 if (show_properties
)
4418 r
= print_property(name
, reply
, contents
);
4420 r
= status_property(name
, reply
, &info
, contents
);
4424 r
= sd_bus_message_exit_container(reply
);
4426 return bus_log_parse_error(r
);
4428 r
= sd_bus_message_exit_container(reply
);
4430 return bus_log_parse_error(r
);
4433 return bus_log_parse_error(r
);
4435 r
= sd_bus_message_exit_container(reply
);
4437 return bus_log_parse_error(r
);
4441 if (!show_properties
) {
4442 if (streq(verb
, "help"))
4443 show_unit_help(&info
);
4445 print_status_info(&info
, ellipsized
);
4448 strv_free(info
.documentation
);
4449 strv_free(info
.dropin_paths
);
4450 strv_free(info
.listen
);
4452 if (!streq_ptr(info
.active_state
, "active") &&
4453 !streq_ptr(info
.active_state
, "reloading") &&
4454 streq(verb
, "status")) {
4455 /* According to LSB: "program not running" */
4456 /* 0: program is running or service is OK
4457 * 1: program is dead and /run PID file exists
4458 * 2: program is dead and /run/lock lock file exists
4459 * 3: program is not running
4460 * 4: program or service status is unknown
4462 if (info
.pid_file
&& access(info
.pid_file
, F_OK
) == 0)
4468 while ((p
= info
.exec
)) {
4469 LIST_REMOVE(exec
, info
.exec
, p
);
4470 exec_status_info_free(p
);
4476 static int get_unit_dbus_path_by_pid(
4481 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4482 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4486 r
= sd_bus_call_method(
4488 "org.freedesktop.systemd1",
4489 "/org/freedesktop/systemd1",
4490 "org.freedesktop.systemd1.Manager",
4496 return log_error_errno(r
, "Failed to get unit for PID %"PRIu32
": %s", pid
, bus_error_message(&error
, r
));
4498 r
= sd_bus_message_read(reply
, "o", &u
);
4500 return bus_log_parse_error(r
);
4510 static int show_all(
4513 bool show_properties
,
4517 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4518 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
4523 r
= get_unit_list(bus
, NULL
, NULL
, &unit_infos
, 0, &reply
);
4527 pager_open_if_enabled();
4531 qsort_safe(unit_infos
, c
, sizeof(UnitInfo
), compare_unit_info
);
4533 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
4534 _cleanup_free_
char *p
= NULL
;
4536 p
= unit_dbus_path_from_name(u
->id
);
4540 r
= show_one(verb
, bus
, p
, show_properties
, new_line
, ellipsized
);
4543 else if (r
> 0 && ret
== 0)
4550 static int show_system_status(sd_bus
*bus
) {
4551 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], since2
[FORMAT_TIMESTAMP_MAX
];
4552 _cleanup_free_
char *hn
= NULL
;
4553 _cleanup_(machine_info_clear
) struct machine_info mi
= {};
4554 const char *on
, *off
;
4557 hn
= gethostname_malloc();
4561 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, &mi
);
4563 return log_error_errno(r
, "Failed to read server status: %m");
4565 if (streq_ptr(mi
.state
, "degraded")) {
4566 on
= ansi_highlight_red();
4567 off
= ansi_normal();
4568 } else if (!streq_ptr(mi
.state
, "running")) {
4569 on
= ansi_highlight_yellow();
4570 off
= ansi_normal();
4574 printf("%s%s%s %s\n", on
, draw_special_char(DRAW_BLACK_CIRCLE
), off
, arg_host
? arg_host
: hn
);
4576 printf(" State: %s%s%s\n",
4577 on
, strna(mi
.state
), off
);
4579 printf(" Jobs: %u queued\n", mi
.n_jobs
);
4580 printf(" Failed: %u units\n", mi
.n_failed_units
);
4582 printf(" Since: %s; %s\n",
4583 format_timestamp(since2
, sizeof(since2
), mi
.timestamp
),
4584 format_timestamp_relative(since1
, sizeof(since1
), mi
.timestamp
));
4586 printf(" CGroup: %s\n", mi
.control_group
?: "/");
4587 if (IN_SET(arg_transport
,
4588 BUS_TRANSPORT_LOCAL
,
4589 BUS_TRANSPORT_MACHINE
)) {
4590 static const char prefix
[] = " ";
4594 if (c
> sizeof(prefix
) - 1)
4595 c
-= sizeof(prefix
) - 1;
4599 show_cgroup(SYSTEMD_CGROUP_CONTROLLER
, strempty(mi
.control_group
), prefix
, c
, false, get_output_flags());
4605 static int show(char **args
) {
4606 bool show_properties
, show_status
, new_line
= false;
4607 bool ellipsized
= false;
4613 show_properties
= streq(args
[0], "show");
4614 show_status
= streq(args
[0], "status");
4616 if (show_properties
)
4617 pager_open_if_enabled();
4620 /* Increase max number of open files to 16K if we can, we
4621 * might needs this when browsing journal files, which might
4622 * be split up into many files. */
4623 setrlimit_closest(RLIMIT_NOFILE
, &RLIMIT_MAKE_CONST(16384));
4625 r
= acquire_bus(BUS_MANAGER
, &bus
);
4629 /* If no argument is specified inspect the manager itself */
4630 if (show_properties
&& strv_length(args
) <= 1)
4631 return show_one(args
[0], bus
, "/org/freedesktop/systemd1", show_properties
, &new_line
, &ellipsized
);
4633 if (show_status
&& strv_length(args
) <= 1) {
4635 pager_open_if_enabled();
4636 show_system_status(bus
);
4640 ret
= show_all(args
[0], bus
, false, &new_line
, &ellipsized
);
4642 _cleanup_free_
char **patterns
= NULL
;
4645 STRV_FOREACH(name
, strv_skip(args
, 1)) {
4646 _cleanup_free_
char *unit
= NULL
;
4649 if (safe_atou32(*name
, &id
) < 0) {
4650 if (strv_push(&patterns
, *name
) < 0)
4654 } else if (show_properties
) {
4655 /* Interpret as job id */
4656 if (asprintf(&unit
, "/org/freedesktop/systemd1/job/%u", id
) < 0)
4660 /* Interpret as PID */
4661 r
= get_unit_dbus_path_by_pid(bus
, id
, &unit
);
4668 r
= show_one(args
[0], bus
, unit
, show_properties
,
4669 &new_line
, &ellipsized
);
4672 else if (r
> 0 && ret
== 0)
4676 if (!strv_isempty(patterns
)) {
4677 _cleanup_strv_free_
char **names
= NULL
;
4679 r
= expand_names(bus
, patterns
, NULL
, &names
);
4681 return log_error_errno(r
, "Failed to expand names: %m");
4683 STRV_FOREACH(name
, names
) {
4684 _cleanup_free_
char *unit
;
4686 unit
= unit_dbus_path_from_name(*name
);
4690 r
= show_one(args
[0], bus
, unit
, show_properties
,
4691 &new_line
, &ellipsized
);
4694 else if (r
> 0 && ret
== 0)
4700 if (ellipsized
&& !arg_quiet
)
4701 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4706 static int init_home_and_lookup_paths(char **user_home
, char **user_runtime
, LookupPaths
*lp
) {
4710 assert(user_runtime
);
4713 if (arg_scope
== UNIT_FILE_USER
) {
4714 r
= user_config_home(user_home
);
4716 return log_error_errno(r
, "Failed to query XDG_CONFIG_HOME: %m");
4718 return log_error_errno(ENOTDIR
, "Cannot find units: $XDG_CONFIG_HOME and $HOME are not set.");
4720 r
= user_runtime_dir(user_runtime
);
4722 return log_error_errno(r
, "Failed to query XDG_CONFIG_HOME: %m");
4724 return log_error_errno(ENOTDIR
, "Cannot find units: $XDG_RUNTIME_DIR is not set.");
4727 r
= lookup_paths_init_from_scope(lp
, arg_scope
, arg_root
);
4729 return log_error_errno(r
, "Failed to query unit lookup paths: %m");
4734 static int cat_file(const char *filename
, bool newline
) {
4735 _cleanup_close_
int fd
;
4737 fd
= open(filename
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
4741 printf("%s%s# %s%s\n",
4742 newline
? "\n" : "",
4743 ansi_highlight_blue(),
4748 return copy_bytes(fd
, STDOUT_FILENO
, (uint64_t) -1, false);
4751 static int cat(char **args
) {
4752 _cleanup_free_
char *user_home
= NULL
;
4753 _cleanup_free_
char *user_runtime
= NULL
;
4754 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
4755 _cleanup_strv_free_
char **names
= NULL
;
4761 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
4762 log_error("Cannot remotely cat units.");
4766 r
= init_home_and_lookup_paths(&user_home
, &user_runtime
, &lp
);
4770 r
= acquire_bus(BUS_MANAGER
, &bus
);
4774 r
= expand_names(bus
, strv_skip(args
, 1), NULL
, &names
);
4776 return log_error_errno(r
, "Failed to expand names: %m");
4778 pager_open_if_enabled();
4780 STRV_FOREACH(name
, names
) {
4781 _cleanup_free_
char *fragment_path
= NULL
;
4782 _cleanup_strv_free_
char **dropin_paths
= NULL
;
4785 r
= unit_find_paths(bus
, *name
, &lp
, &fragment_path
, &dropin_paths
);
4796 if (fragment_path
) {
4797 r
= cat_file(fragment_path
, false);
4799 return log_warning_errno(r
, "Failed to cat %s: %m", fragment_path
);
4802 STRV_FOREACH(path
, dropin_paths
) {
4803 r
= cat_file(*path
, path
== dropin_paths
);
4805 return log_warning_errno(r
, "Failed to cat %s: %m", *path
);
4812 static int set_property(char **args
) {
4813 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
4814 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4815 _cleanup_free_
char *n
= NULL
;
4820 polkit_agent_open_if_enabled();
4822 r
= acquire_bus(BUS_MANAGER
, &bus
);
4826 r
= sd_bus_message_new_method_call(
4829 "org.freedesktop.systemd1",
4830 "/org/freedesktop/systemd1",
4831 "org.freedesktop.systemd1.Manager",
4832 "SetUnitProperties");
4834 return bus_log_create_error(r
);
4836 r
= unit_name_mangle(args
[1], UNIT_NAME_NOGLOB
, &n
);
4838 return log_error_errno(r
, "Failed to mangle unit name: %m");
4840 r
= sd_bus_message_append(m
, "sb", n
, arg_runtime
);
4842 return bus_log_create_error(r
);
4844 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, "(sv)");
4846 return bus_log_create_error(r
);
4848 STRV_FOREACH(i
, args
+ 2) {
4849 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_STRUCT
, "sv");
4851 return bus_log_create_error(r
);
4853 r
= bus_append_unit_property_assignment(m
, *i
);
4857 r
= sd_bus_message_close_container(m
);
4859 return bus_log_create_error(r
);
4862 r
= sd_bus_message_close_container(m
);
4864 return bus_log_create_error(r
);
4866 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
4868 return log_error_errno(r
, "Failed to set unit properties on %s: %s", n
, bus_error_message(&error
, r
));
4873 static int snapshot(char **args
) {
4874 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4875 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4876 _cleanup_free_
char *n
= NULL
, *id
= NULL
;
4881 polkit_agent_open_if_enabled();
4883 if (strv_length(args
) > 1) {
4884 r
= unit_name_mangle_with_suffix(args
[1], UNIT_NAME_NOGLOB
, ".snapshot", &n
);
4886 return log_error_errno(r
, "Failed to generate unit name: %m");
4893 r
= acquire_bus(BUS_MANAGER
, &bus
);
4897 r
= sd_bus_call_method(
4899 "org.freedesktop.systemd1",
4900 "/org/freedesktop/systemd1",
4901 "org.freedesktop.systemd1.Manager",
4907 return log_error_errno(r
, "Failed to create snapshot: %s", bus_error_message(&error
, r
));
4909 r
= sd_bus_message_read(reply
, "o", &path
);
4911 return bus_log_parse_error(r
);
4913 r
= sd_bus_get_property_string(
4915 "org.freedesktop.systemd1",
4917 "org.freedesktop.systemd1.Unit",
4922 return log_error_errno(r
, "Failed to get ID of snapshot: %s", bus_error_message(&error
, r
));
4930 static int delete_snapshot(char **args
) {
4931 _cleanup_strv_free_
char **names
= NULL
;
4936 polkit_agent_open_if_enabled();
4938 r
= acquire_bus(BUS_MANAGER
, &bus
);
4942 r
= expand_names(bus
, strv_skip(args
, 1), ".snapshot", &names
);
4944 return log_error_errno(r
, "Failed to expand names: %m");
4946 STRV_FOREACH(name
, names
) {
4947 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4950 q
= sd_bus_call_method(
4952 "org.freedesktop.systemd1",
4953 "/org/freedesktop/systemd1",
4954 "org.freedesktop.systemd1.Manager",
4960 log_error_errno(q
, "Failed to remove snapshot %s: %s", *name
, bus_error_message(&error
, q
));
4969 static int daemon_reload(char **args
) {
4970 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4975 polkit_agent_open_if_enabled();
4977 r
= acquire_bus(BUS_MANAGER
, &bus
);
4981 if (arg_action
== ACTION_RELOAD
)
4983 else if (arg_action
== ACTION_REEXEC
)
4984 method
= "Reexecute";
4986 assert(arg_action
== ACTION_SYSTEMCTL
);
4989 streq(args
[0], "clear-jobs") ||
4990 streq(args
[0], "cancel") ? "ClearJobs" :
4991 streq(args
[0], "daemon-reexec") ? "Reexecute" :
4992 streq(args
[0], "reset-failed") ? "ResetFailed" :
4993 streq(args
[0], "halt") ? "Halt" :
4994 streq(args
[0], "poweroff") ? "PowerOff" :
4995 streq(args
[0], "reboot") ? "Reboot" :
4996 streq(args
[0], "kexec") ? "KExec" :
4997 streq(args
[0], "exit") ? "Exit" :
4998 /* "daemon-reload" */ "Reload";
5001 r
= sd_bus_call_method(
5003 "org.freedesktop.systemd1",
5004 "/org/freedesktop/systemd1",
5005 "org.freedesktop.systemd1.Manager",
5010 if (r
== -ENOENT
&& arg_action
!= ACTION_SYSTEMCTL
)
5011 /* There's always a fallback possible for
5012 * legacy actions. */
5014 else if ((r
== -ETIMEDOUT
|| r
== -ECONNRESET
) && streq(method
, "Reexecute"))
5015 /* On reexecution, we expect a disconnect, not a
5019 return log_error_errno(r
, "Failed to execute operation: %s", bus_error_message(&error
, r
));
5021 return r
< 0 ? r
: 0;
5024 static int reset_failed(char **args
) {
5025 _cleanup_strv_free_
char **names
= NULL
;
5030 if (strv_length(args
) <= 1)
5031 return daemon_reload(args
);
5033 polkit_agent_open_if_enabled();
5035 r
= acquire_bus(BUS_MANAGER
, &bus
);
5039 r
= expand_names(bus
, strv_skip(args
, 1), NULL
, &names
);
5041 return log_error_errno(r
, "Failed to expand names: %m");
5043 STRV_FOREACH(name
, names
) {
5044 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5046 q
= sd_bus_call_method(
5048 "org.freedesktop.systemd1",
5049 "/org/freedesktop/systemd1",
5050 "org.freedesktop.systemd1.Manager",
5056 log_error_errno(q
, "Failed to reset failed state of unit %s: %s", *name
, bus_error_message(&error
, q
));
5065 static int show_environment(char **args
) {
5066 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5067 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
5072 pager_open_if_enabled();
5074 r
= acquire_bus(BUS_MANAGER
, &bus
);
5078 r
= sd_bus_get_property(
5080 "org.freedesktop.systemd1",
5081 "/org/freedesktop/systemd1",
5082 "org.freedesktop.systemd1.Manager",
5088 return log_error_errno(r
, "Failed to get environment: %s", bus_error_message(&error
, r
));
5090 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
5092 return bus_log_parse_error(r
);
5094 while ((r
= sd_bus_message_read_basic(reply
, SD_BUS_TYPE_STRING
, &text
)) > 0)
5097 return bus_log_parse_error(r
);
5099 r
= sd_bus_message_exit_container(reply
);
5101 return bus_log_parse_error(r
);
5106 static int switch_root(char **args
) {
5107 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5108 _cleanup_free_
char *cmdline_init
= NULL
;
5109 const char *root
, *init
;
5114 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
5115 log_error("Cannot switch root remotely.");
5119 l
= strv_length(args
);
5120 if (l
< 2 || l
> 3) {
5121 log_error("Wrong number of arguments.");
5130 r
= parse_env_file("/proc/cmdline", WHITESPACE
,
5131 "init", &cmdline_init
,
5134 log_debug_errno(r
, "Failed to parse /proc/cmdline: %m");
5136 init
= cmdline_init
;
5143 const char *root_systemd_path
= NULL
, *root_init_path
= NULL
;
5145 root_systemd_path
= strjoina(root
, "/" SYSTEMD_BINARY_PATH
);
5146 root_init_path
= strjoina(root
, "/", init
);
5148 /* If the passed init is actually the same as the
5149 * systemd binary, then let's suppress it. */
5150 if (files_same(root_init_path
, root_systemd_path
) > 0)
5154 r
= acquire_bus(BUS_MANAGER
, &bus
);
5158 log_debug("Switching root - root: %s; init: %s", root
, strna(init
));
5160 r
= sd_bus_call_method(
5162 "org.freedesktop.systemd1",
5163 "/org/freedesktop/systemd1",
5164 "org.freedesktop.systemd1.Manager",
5170 return log_error_errno(r
, "Failed to switch root: %s", bus_error_message(&error
, r
));
5175 static int set_environment(char **args
) {
5176 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5177 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
5184 polkit_agent_open_if_enabled();
5186 r
= acquire_bus(BUS_MANAGER
, &bus
);
5190 method
= streq(args
[0], "set-environment")
5192 : "UnsetEnvironment";
5194 r
= sd_bus_message_new_method_call(
5197 "org.freedesktop.systemd1",
5198 "/org/freedesktop/systemd1",
5199 "org.freedesktop.systemd1.Manager",
5202 return bus_log_create_error(r
);
5204 r
= sd_bus_message_append_strv(m
, strv_skip(args
, 1));
5206 return bus_log_create_error(r
);
5208 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5210 return log_error_errno(r
, "Failed to set environment: %s", bus_error_message(&error
, r
));
5215 static int import_environment(char **args
) {
5216 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5217 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
5221 polkit_agent_open_if_enabled();
5223 r
= acquire_bus(BUS_MANAGER
, &bus
);
5227 r
= sd_bus_message_new_method_call(
5230 "org.freedesktop.systemd1",
5231 "/org/freedesktop/systemd1",
5232 "org.freedesktop.systemd1.Manager",
5235 return bus_log_create_error(r
);
5237 if (strv_isempty(strv_skip(args
, 1)))
5238 r
= sd_bus_message_append_strv(m
, environ
);
5242 r
= sd_bus_message_open_container(m
, 'a', "s");
5244 return bus_log_create_error(r
);
5246 STRV_FOREACH(a
, strv_skip(args
, 1)) {
5248 if (!env_name_is_valid(*a
)) {
5249 log_error("Not a valid environment variable name: %s", *a
);
5253 STRV_FOREACH(b
, environ
) {
5256 eq
= startswith(*b
, *a
);
5257 if (eq
&& *eq
== '=') {
5259 r
= sd_bus_message_append(m
, "s", *b
);
5261 return bus_log_create_error(r
);
5268 r
= sd_bus_message_close_container(m
);
5271 return bus_log_create_error(r
);
5273 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5275 return log_error_errno(r
, "Failed to import environment: %s", bus_error_message(&error
, r
));
5280 static int enable_sysv_units(const char *verb
, char **args
) {
5283 #if defined(HAVE_SYSV_COMPAT)
5285 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
5287 if (arg_scope
!= UNIT_FILE_SYSTEM
)
5290 if (!STR_IN_SET(verb
,
5296 /* Processes all SysV units, and reshuffles the array so that
5297 * afterwards only the native units remain */
5299 r
= lookup_paths_init(&paths
, MANAGER_SYSTEM
, false, arg_root
, NULL
, NULL
, NULL
);
5306 _cleanup_free_
char *p
= NULL
, *q
= NULL
, *l
= NULL
;
5307 bool found_native
= false, found_sysv
;
5309 const char *argv
[6] = { ROOTLIBEXECDIR
"/systemd-sysv-install", NULL
, NULL
, NULL
, NULL
};
5317 if (!endswith(name
, ".service"))
5320 if (path_is_absolute(name
))
5323 STRV_FOREACH(k
, paths
.unit_path
) {
5324 _cleanup_free_
char *path
= NULL
;
5326 path
= path_join(arg_root
, *k
, name
);
5330 found_native
= access(path
, F_OK
) >= 0;
5335 /* If we have both a native unit and a SysV script,
5336 * enable/disable them both (below); for is-enabled, prefer the
5338 if (found_native
&& streq(verb
, "is-enabled"))
5341 p
= path_join(arg_root
, SYSTEM_SYSVINIT_PATH
, name
);
5345 p
[strlen(p
) - strlen(".service")] = 0;
5346 found_sysv
= access(p
, F_OK
) >= 0;
5351 log_info("Synchronizing state of %s with SysV init with %s...", name
, argv
[0]);
5353 log_info("%s is not a native service, redirecting to systemd-sysv-install", name
);
5355 if (!isempty(arg_root
))
5356 argv
[c
++] = q
= strappend("--root=", arg_root
);
5359 argv
[c
++] = basename(p
);
5362 l
= strv_join((char**)argv
, " ");
5366 log_info("Executing %s", l
);
5370 return log_error_errno(errno
, "Failed to fork: %m");
5371 else if (pid
== 0) {
5374 (void) reset_all_signal_handlers();
5375 (void) reset_signal_mask();
5377 execv(argv
[0], (char**) argv
);
5378 log_error_errno(r
, "Failed to execute %s: %m", argv
[0]);
5379 _exit(EXIT_FAILURE
);
5382 j
= wait_for_terminate(pid
, &status
);
5384 log_error_errno(j
, "Failed to wait for child: %m");
5388 if (status
.si_code
== CLD_EXITED
) {
5389 if (streq(verb
, "is-enabled")) {
5390 if (status
.si_status
== 0) {
5399 } else if (status
.si_status
!= 0)
5407 /* Remove this entry, so that we don't try enabling it as native unit */
5410 assert(args
[f
] == name
);
5411 strv_remove(args
, name
);
5418 static int mangle_names(char **original_names
, char ***mangled_names
) {
5419 char **i
, **l
, **name
;
5422 l
= i
= new(char*, strv_length(original_names
) + 1);
5426 STRV_FOREACH(name
, original_names
) {
5428 /* When enabling units qualified path names are OK,
5429 * too, hence allow them explicitly. */
5431 if (is_path(*name
)) {
5438 r
= unit_name_mangle(*name
, UNIT_NAME_NOGLOB
, i
);
5441 return log_error_errno(r
, "Failed to mangle unit name: %m");
5454 static int enable_unit(char **args
) {
5455 _cleanup_strv_free_
char **names
= NULL
;
5456 const char *verb
= args
[0];
5457 UnitFileChange
*changes
= NULL
;
5458 unsigned n_changes
= 0;
5459 int carries_install_info
= -1;
5465 r
= mangle_names(args
+1, &names
);
5469 r
= enable_sysv_units(verb
, names
);
5473 /* If the operation was fully executed by the SysV compat,
5474 * let's finish early */
5475 if (strv_isempty(names
))
5478 if (install_client_side()) {
5479 if (streq(verb
, "enable")) {
5480 r
= unit_file_enable(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5481 carries_install_info
= r
;
5482 } else if (streq(verb
, "disable"))
5483 r
= unit_file_disable(arg_scope
, arg_runtime
, arg_root
, names
, &changes
, &n_changes
);
5484 else if (streq(verb
, "reenable")) {
5485 r
= unit_file_reenable(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5486 carries_install_info
= r
;
5487 } else if (streq(verb
, "link"))
5488 r
= unit_file_link(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5489 else if (streq(verb
, "preset")) {
5490 r
= unit_file_preset(arg_scope
, arg_runtime
, arg_root
, names
, arg_preset_mode
, arg_force
, &changes
, &n_changes
);
5491 carries_install_info
= r
;
5492 } else if (streq(verb
, "mask"))
5493 r
= unit_file_mask(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5494 else if (streq(verb
, "unmask"))
5495 r
= unit_file_unmask(arg_scope
, arg_runtime
, arg_root
, names
, &changes
, &n_changes
);
5497 assert_not_reached("Unknown verb");
5500 log_error_errno(r
, "Operation failed: %m");
5505 dump_unit_file_changes(changes
, n_changes
);
5509 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
, *m
= NULL
;
5510 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5511 int expect_carries_install_info
= false;
5512 bool send_force
= true, send_preset_mode
= false;
5516 polkit_agent_open_if_enabled();
5518 r
= acquire_bus(BUS_MANAGER
, &bus
);
5522 if (streq(verb
, "enable")) {
5523 method
= "EnableUnitFiles";
5524 expect_carries_install_info
= true;
5525 } else if (streq(verb
, "disable")) {
5526 method
= "DisableUnitFiles";
5528 } else if (streq(verb
, "reenable")) {
5529 method
= "ReenableUnitFiles";
5530 expect_carries_install_info
= true;
5531 } else if (streq(verb
, "link"))
5532 method
= "LinkUnitFiles";
5533 else if (streq(verb
, "preset")) {
5535 if (arg_preset_mode
!= UNIT_FILE_PRESET_FULL
) {
5536 method
= "PresetUnitFilesWithMode";
5537 send_preset_mode
= true;
5539 method
= "PresetUnitFiles";
5541 expect_carries_install_info
= true;
5542 } else if (streq(verb
, "mask"))
5543 method
= "MaskUnitFiles";
5544 else if (streq(verb
, "unmask")) {
5545 method
= "UnmaskUnitFiles";
5548 assert_not_reached("Unknown verb");
5550 r
= sd_bus_message_new_method_call(
5553 "org.freedesktop.systemd1",
5554 "/org/freedesktop/systemd1",
5555 "org.freedesktop.systemd1.Manager",
5558 return bus_log_create_error(r
);
5560 r
= sd_bus_message_append_strv(m
, names
);
5562 return bus_log_create_error(r
);
5564 if (send_preset_mode
) {
5565 r
= sd_bus_message_append(m
, "s", unit_file_preset_mode_to_string(arg_preset_mode
));
5567 return bus_log_create_error(r
);
5570 r
= sd_bus_message_append(m
, "b", arg_runtime
);
5572 return bus_log_create_error(r
);
5575 r
= sd_bus_message_append(m
, "b", arg_force
);
5577 return bus_log_create_error(r
);
5580 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
5582 return log_error_errno(r
, "Failed to execute operation: %s", bus_error_message(&error
, r
));
5584 if (expect_carries_install_info
) {
5585 r
= sd_bus_message_read(reply
, "b", &carries_install_info
);
5587 return bus_log_parse_error(r
);
5590 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
5594 /* Try to reload if enabled */
5596 r
= daemon_reload(args
);
5601 if (carries_install_info
== 0)
5602 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5603 "using systemctl.\n"
5604 "Possible reasons for having this kind of units are:\n"
5605 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5606 " .wants/ or .requires/ directory.\n"
5607 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5608 " a requirement dependency on it.\n"
5609 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5610 " D-Bus, udev, scripted systemctl call, ...).\n");
5612 if (arg_now
&& n_changes
> 0 && STR_IN_SET(args
[0], "enable", "disable", "mask")) {
5613 char *new_args
[n_changes
+ 2];
5617 r
= acquire_bus(BUS_MANAGER
, &bus
);
5621 new_args
[0] = (char*) (streq(args
[0], "enable") ? "start" : "stop");
5622 for (i
= 0; i
< n_changes
; i
++)
5623 new_args
[i
+ 1] = basename(changes
[i
].path
);
5624 new_args
[i
+ 1] = NULL
;
5626 r
= start_unit(new_args
);
5630 unit_file_changes_free(changes
, n_changes
);
5635 static int add_dependency(char **args
) {
5636 _cleanup_strv_free_
char **names
= NULL
;
5637 _cleanup_free_
char *target
= NULL
;
5638 const char *verb
= args
[0];
5645 r
= unit_name_mangle_with_suffix(args
[1], UNIT_NAME_NOGLOB
, ".target", &target
);
5647 return log_error_errno(r
, "Failed to mangle unit name: %m");
5649 r
= mangle_names(args
+2, &names
);
5653 if (streq(verb
, "add-wants"))
5655 else if (streq(verb
, "add-requires"))
5656 dep
= UNIT_REQUIRES
;
5658 assert_not_reached("Unknown verb");
5660 if (install_client_side()) {
5661 UnitFileChange
*changes
= NULL
;
5662 unsigned n_changes
= 0;
5664 r
= unit_file_add_dependency(arg_scope
, arg_runtime
, arg_root
, names
, target
, dep
, arg_force
, &changes
, &n_changes
);
5667 return log_error_errno(r
, "Can't add dependency: %m");
5670 dump_unit_file_changes(changes
, n_changes
);
5672 unit_file_changes_free(changes
, n_changes
);
5675 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
, *m
= NULL
;
5676 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5679 polkit_agent_open_if_enabled();
5681 r
= acquire_bus(BUS_MANAGER
, &bus
);
5685 r
= sd_bus_message_new_method_call(
5688 "org.freedesktop.systemd1",
5689 "/org/freedesktop/systemd1",
5690 "org.freedesktop.systemd1.Manager",
5691 "AddDependencyUnitFiles");
5693 return bus_log_create_error(r
);
5695 r
= sd_bus_message_append_strv(m
, names
);
5697 return bus_log_create_error(r
);
5699 r
= sd_bus_message_append(m
, "ssbb", target
, unit_dependency_to_string(dep
), arg_runtime
, arg_force
);
5701 return bus_log_create_error(r
);
5703 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
5705 return log_error_errno(r
, "Failed to execute operation: %s", bus_error_message(&error
, r
));
5707 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, NULL
, NULL
);
5712 r
= daemon_reload(args
);
5720 static int preset_all(char **args
) {
5721 UnitFileChange
*changes
= NULL
;
5722 unsigned n_changes
= 0;
5725 if (install_client_side()) {
5727 r
= unit_file_preset_all(arg_scope
, arg_runtime
, arg_root
, arg_preset_mode
, arg_force
, &changes
, &n_changes
);
5729 log_error_errno(r
, "Operation failed: %m");
5734 dump_unit_file_changes(changes
, n_changes
);
5739 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5740 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
5743 polkit_agent_open_if_enabled();
5745 r
= acquire_bus(BUS_MANAGER
, &bus
);
5749 r
= sd_bus_call_method(
5751 "org.freedesktop.systemd1",
5752 "/org/freedesktop/systemd1",
5753 "org.freedesktop.systemd1.Manager",
5754 "PresetAllUnitFiles",
5758 unit_file_preset_mode_to_string(arg_preset_mode
),
5762 return log_error_errno(r
, "Failed to execute operation: %s", bus_error_message(&error
, r
));
5764 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, NULL
, NULL
);
5769 r
= daemon_reload(args
);
5775 unit_file_changes_free(changes
, n_changes
);
5780 static int unit_is_enabled(char **args
) {
5782 _cleanup_strv_free_
char **names
= NULL
;
5787 r
= mangle_names(args
+1, &names
);
5791 r
= enable_sysv_units(args
[0], names
);
5797 if (install_client_side()) {
5799 STRV_FOREACH(name
, names
) {
5800 UnitFileState state
;
5802 state
= unit_file_get_state(arg_scope
, arg_root
, *name
);
5804 return log_error_errno(state
, "Failed to get unit file state for %s: %m", *name
);
5808 UNIT_FILE_ENABLED_RUNTIME
,
5810 UNIT_FILE_INDIRECT
))
5814 puts(unit_file_state_to_string(state
));
5818 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5821 r
= acquire_bus(BUS_MANAGER
, &bus
);
5825 STRV_FOREACH(name
, names
) {
5826 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
5829 r
= sd_bus_call_method(
5831 "org.freedesktop.systemd1",
5832 "/org/freedesktop/systemd1",
5833 "org.freedesktop.systemd1.Manager",
5839 return log_error_errno(r
, "Failed to get unit file state for %s: %s", *name
, bus_error_message(&error
, r
));
5841 r
= sd_bus_message_read(reply
, "s", &s
);
5843 return bus_log_parse_error(r
);
5845 if (STR_IN_SET(s
, "enabled", "enabled-runtime", "static", "indirect"))
5856 static int is_system_running(char **args
) {
5857 _cleanup_free_
char *state
= NULL
;
5861 if (arg_transport
== BUS_TRANSPORT_LOCAL
&& !sd_booted()) {
5864 return EXIT_FAILURE
;
5867 r
= acquire_bus(BUS_MANAGER
, &bus
);
5871 r
= sd_bus_get_property_string(
5873 "org.freedesktop.systemd1",
5874 "/org/freedesktop/systemd1",
5875 "org.freedesktop.systemd1.Manager",
5888 return streq(state
, "running") ? EXIT_SUCCESS
: EXIT_FAILURE
;
5891 static int create_edit_temp_file(const char *new_path
, const char *original_path
, char **ret_tmp_fn
) {
5896 assert(original_path
);
5899 r
= tempfn_random(new_path
, NULL
, &t
);
5901 return log_error_errno(r
, "Failed to determine temporary filename for \"%s\": %m", new_path
);
5903 r
= mkdir_parents(new_path
, 0755);
5906 return log_error_errno(r
, "Failed to create directories for \"%s\": %m", new_path
);
5909 r
= copy_file(original_path
, t
, 0, 0644, 0);
5913 log_error_errno(r
, "Failed to create temporary file \"%s\": %m", t
);
5918 log_error_errno(r
, "Failed to copy \"%s\" to \"%s\": %m", original_path
, t
);
5928 static int get_file_to_edit(const char *name
, const char *user_home
, const char *user_runtime
, char **ret_path
) {
5929 _cleanup_free_
char *path
= NULL
, *path2
= NULL
, *run
= NULL
;
5931 switch (arg_scope
) {
5932 case UNIT_FILE_SYSTEM
:
5933 path
= path_join(arg_root
, SYSTEM_CONFIG_UNIT_PATH
, name
);
5935 run
= path_join(arg_root
, "/run/systemd/system/", name
);
5937 case UNIT_FILE_GLOBAL
:
5938 path
= path_join(arg_root
, USER_CONFIG_UNIT_PATH
, name
);
5940 run
= path_join(arg_root
, "/run/systemd/user/", name
);
5942 case UNIT_FILE_USER
:
5944 assert(user_runtime
);
5946 path
= path_join(arg_root
, user_home
, name
);
5948 path2
= path_join(arg_root
, USER_CONFIG_UNIT_PATH
, name
);
5951 run
= path_join(arg_root
, user_runtime
, name
);
5955 assert_not_reached("Invalid scope");
5957 if (!path
|| (arg_runtime
&& !run
))
5961 if (access(path
, F_OK
) >= 0) {
5962 log_error("Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.", run
, path
);
5966 if (path2
&& access(path2
, F_OK
) >= 0) {
5967 log_error("Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.", run
, path2
);
5981 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
) {
5982 char *tmp_new_path
, *ending
;
5987 assert(ret_new_path
);
5988 assert(ret_tmp_path
);
5990 ending
= strjoina(unit_name
, ".d/override.conf");
5991 r
= get_file_to_edit(ending
, user_home
, user_runtime
, &tmp_new_path
);
5995 r
= create_edit_temp_file(tmp_new_path
, tmp_new_path
, &tmp_tmp_path
);
6001 *ret_new_path
= tmp_new_path
;
6002 *ret_tmp_path
= tmp_tmp_path
;
6007 static int unit_file_create_copy(
6008 const char *unit_name
,
6009 const char *fragment_path
,
6010 const char *user_home
,
6011 const char *user_runtime
,
6012 char **ret_new_path
,
6013 char **ret_tmp_path
) {
6019 assert(fragment_path
);
6021 assert(ret_new_path
);
6022 assert(ret_tmp_path
);
6024 r
= get_file_to_edit(unit_name
, user_home
, user_runtime
, &tmp_new_path
);
6028 if (!path_equal(fragment_path
, tmp_new_path
) && access(tmp_new_path
, F_OK
) == 0) {
6031 r
= ask_char(&response
, "yn", "\"%s\" already exists. Overwrite with \"%s\"? [(y)es, (n)o] ", tmp_new_path
, fragment_path
);
6036 if (response
!= 'y') {
6037 log_warning("%s ignored", unit_name
);
6043 r
= create_edit_temp_file(tmp_new_path
, fragment_path
, &tmp_tmp_path
);
6045 log_error_errno(r
, "Failed to create temporary file for \"%s\": %m", tmp_new_path
);
6050 *ret_new_path
= tmp_new_path
;
6051 *ret_tmp_path
= tmp_tmp_path
;
6056 static int run_editor(char **paths
) {
6064 return log_error_errno(errno
, "Failed to fork: %m");
6068 char *editor
, **editor_args
= NULL
;
6069 char **tmp_path
, **original_path
, *p
;
6070 unsigned n_editor_args
= 0, i
= 1;
6073 (void) reset_all_signal_handlers();
6074 (void) reset_signal_mask();
6076 argc
= strv_length(paths
)/2 + 1;
6078 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
6079 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
6080 * we try to execute well known editors
6082 editor
= getenv("SYSTEMD_EDITOR");
6084 editor
= getenv("EDITOR");
6086 editor
= getenv("VISUAL");
6088 if (!isempty(editor
)) {
6089 editor_args
= strv_split(editor
, WHITESPACE
);
6092 _exit(EXIT_FAILURE
);
6094 n_editor_args
= strv_length(editor_args
);
6095 argc
+= n_editor_args
- 1;
6097 args
= newa(const char*, argc
+ 1);
6099 if (n_editor_args
> 0) {
6100 args
[0] = editor_args
[0];
6101 for (; i
< n_editor_args
; i
++)
6102 args
[i
] = editor_args
[i
];
6105 STRV_FOREACH_PAIR(original_path
, tmp_path
, paths
) {
6106 args
[i
] = *tmp_path
;
6111 if (n_editor_args
> 0)
6112 execvp(args
[0], (char* const*) args
);
6114 FOREACH_STRING(p
, "editor", "nano", "vim", "vi") {
6116 execvp(p
, (char* const*) args
);
6117 /* We do not fail if the editor doesn't exist
6118 * because we want to try each one of them before
6121 if (errno
!= ENOENT
) {
6122 log_error_errno(errno
, "Failed to execute %s: %m", editor
);
6123 _exit(EXIT_FAILURE
);
6127 log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR, $EDITOR or $VISUAL.");
6128 _exit(EXIT_FAILURE
);
6131 r
= wait_for_terminate_and_warn("editor", pid
, true);
6133 return log_error_errno(r
, "Failed to wait for child: %m");
6138 static int find_paths_to_edit(sd_bus
*bus
, char **names
, char ***paths
) {
6139 _cleanup_free_
char *user_home
= NULL
;
6140 _cleanup_free_
char *user_runtime
= NULL
;
6141 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
6148 r
= init_home_and_lookup_paths(&user_home
, &user_runtime
, &lp
);
6152 STRV_FOREACH(name
, names
) {
6153 _cleanup_free_
char *path
= NULL
;
6154 char *new_path
, *tmp_path
;
6156 r
= unit_find_paths(bus
, *name
, &lp
, &path
, NULL
);
6162 // FIXME: support units with path==NULL (no FragmentPath)
6163 log_error("No fragment exists for %s.", *name
);
6168 r
= unit_file_create_copy(*name
, path
, user_home
, user_runtime
, &new_path
, &tmp_path
);
6170 r
= unit_file_create_dropin(*name
, user_home
, user_runtime
, &new_path
, &tmp_path
);
6174 r
= strv_push_pair(paths
, new_path
, tmp_path
);
6182 static int edit(char **args
) {
6183 _cleanup_strv_free_
char **names
= NULL
;
6184 _cleanup_strv_free_
char **paths
= NULL
;
6185 char **original
, **tmp
;
6190 log_error("Cannot edit units if not on a tty.");
6194 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
6195 log_error("Cannot edit units remotely.");
6199 r
= acquire_bus(BUS_MANAGER
, &bus
);
6203 r
= expand_names(bus
, strv_skip(args
, 1), NULL
, &names
);
6205 return log_error_errno(r
, "Failed to expand names: %m");
6207 r
= find_paths_to_edit(bus
, names
, &paths
);
6211 if (strv_isempty(paths
))
6214 r
= run_editor(paths
);
6218 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
6219 /* If the temporary file is empty we ignore it.
6220 * It's useful if the user wants to cancel its modification
6222 if (null_or_empty_path(*tmp
)) {
6223 log_warning("Editing \"%s\" canceled: temporary file is empty", *original
);
6226 r
= rename(*tmp
, *original
);
6228 r
= log_error_errno(errno
, "Failed to rename \"%s\" to \"%s\": %m", *tmp
, *original
);
6233 if (!arg_no_reload
&& bus
&& !install_client_side())
6234 r
= daemon_reload(args
);
6237 STRV_FOREACH_PAIR(original
, tmp
, paths
)
6238 unlink_noerrno(*tmp
);
6243 static void systemctl_help(void) {
6245 pager_open_if_enabled();
6247 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
6248 "Query or send control commands to the systemd manager.\n\n"
6249 " -h --help Show this help\n"
6250 " --version Show package version\n"
6251 " --system Connect to system manager\n"
6252 " --user Connect to user service manager\n"
6253 " -H --host=[USER@]HOST\n"
6254 " Operate on remote host\n"
6255 " -M --machine=CONTAINER\n"
6256 " Operate on local container\n"
6257 " -t --type=TYPE List units of a particular type\n"
6258 " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n"
6259 " -p --property=NAME Show only properties by this name\n"
6260 " -a --all Show all loaded units/properties, including dead/empty\n"
6261 " ones. To list all units installed on the system, use\n"
6262 " the 'list-unit-files' command instead.\n"
6263 " -l --full Don't ellipsize unit names on output\n"
6264 " -r --recursive Show unit list of host and local containers\n"
6265 " --reverse Show reverse dependencies with 'list-dependencies'\n"
6266 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
6267 " queueing a new job\n"
6268 " --show-types When showing sockets, explicitly show their type\n"
6269 " -i --ignore-inhibitors\n"
6270 " When shutting down or sleeping, ignore inhibitors\n"
6271 " --kill-who=WHO Who to send signal to\n"
6272 " -s --signal=SIGNAL Which signal to send\n"
6273 " --now Start or stop unit in addition to enabling or disabling it\n"
6274 " -q --quiet Suppress output\n"
6275 " --no-block Do not wait until operation finished\n"
6276 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6277 " --no-reload Don't reload daemon after en-/dis-abling unit files\n"
6278 " --no-legend Do not print a legend (column headers and hints)\n"
6279 " --no-pager Do not pipe output into a pager\n"
6280 " --no-ask-password\n"
6281 " Do not ask for system passwords\n"
6282 " --global Enable/disable unit files globally\n"
6283 " --runtime Enable unit files only temporarily until next reboot\n"
6284 " -f --force When enabling unit files, override existing symlinks\n"
6285 " When shutting down, execute action immediately\n"
6286 " --preset-mode= Apply only enable, only disable, or all presets\n"
6287 " --root=PATH Enable unit files in the specified root directory\n"
6288 " -n --lines=INTEGER Number of journal entries to show\n"
6289 " -o --output=STRING Change journal output mode (short, short-iso,\n"
6290 " short-precise, short-monotonic, verbose,\n"
6291 " export, json, json-pretty, json-sse, cat)\n"
6292 " --firmware-setup Tell the firmware to show the setup menu on next boot\n"
6293 " --plain Print unit dependencies as a list instead of a tree\n\n"
6295 " list-units [PATTERN...] List loaded units\n"
6296 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
6297 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
6298 " start NAME... Start (activate) one or more units\n"
6299 " stop NAME... Stop (deactivate) one or more units\n"
6300 " reload NAME... Reload one or more units\n"
6301 " restart NAME... Start or restart one or more units\n"
6302 " try-restart NAME... Restart one or more units if active\n"
6303 " reload-or-restart NAME... Reload one or more units if possible,\n"
6304 " otherwise start or restart\n"
6305 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
6306 " otherwise restart if active\n"
6307 " isolate NAME Start one unit and stop all others\n"
6308 " kill NAME... Send signal to processes of a unit\n"
6309 " is-active PATTERN... Check whether units are active\n"
6310 " is-failed PATTERN... Check whether units are failed\n"
6311 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
6312 " show [PATTERN...|JOB...] Show properties of one or more\n"
6313 " units/jobs or the manager\n"
6314 " cat PATTERN... Show files and drop-ins of one or more units\n"
6315 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
6316 " help PATTERN...|PID... Show manual for one or more units\n"
6317 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
6319 " list-dependencies [NAME] Recursively show units which are required\n"
6320 " or wanted by this unit or by which this\n"
6321 " unit is required or wanted\n\n"
6322 "Unit File Commands:\n"
6323 " list-unit-files [PATTERN...] List installed unit files\n"
6324 " enable NAME... Enable one or more unit files\n"
6325 " disable NAME... Disable one or more unit files\n"
6326 " reenable NAME... Reenable one or more unit files\n"
6327 " preset NAME... Enable/disable one or more unit files\n"
6328 " based on preset configuration\n"
6329 " preset-all Enable/disable all unit files based on\n"
6330 " preset configuration\n"
6331 " is-enabled NAME... Check whether unit files are enabled\n"
6332 " mask NAME... Mask one or more units\n"
6333 " unmask NAME... Unmask one or more units\n"
6334 " link PATH... Link one or more units files into\n"
6335 " the search path\n"
6336 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
6337 " on specified one or more units\n"
6338 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
6339 " on specified one or more units\n"
6340 " edit NAME... Edit one or more unit files\n"
6341 " get-default Get the name of the default target\n"
6342 " set-default NAME Set the default target\n\n"
6343 "Machine Commands:\n"
6344 " list-machines [PATTERN...] List local containers and host\n\n"
6346 " list-jobs [PATTERN...] List jobs\n"
6347 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
6348 "Snapshot Commands:\n"
6349 " snapshot [NAME] Create a snapshot\n"
6350 " delete NAME... Remove one or more snapshots\n\n"
6351 "Environment Commands:\n"
6352 " show-environment Dump environment\n"
6353 " set-environment NAME=VALUE... Set one or more environment variables\n"
6354 " unset-environment NAME... Unset one or more environment variables\n"
6355 " import-environment [NAME...] Import all or some environment variables\n\n"
6356 "Manager Lifecycle Commands:\n"
6357 " daemon-reload Reload systemd manager configuration\n"
6358 " daemon-reexec Reexecute systemd manager\n\n"
6359 "System Commands:\n"
6360 " is-system-running Check whether system is fully running\n"
6361 " default Enter system default mode\n"
6362 " rescue Enter system rescue mode\n"
6363 " emergency Enter system emergency mode\n"
6364 " halt Shut down and halt the system\n"
6365 " poweroff Shut down and power-off the system\n"
6366 " reboot [ARG] Shut down and reboot the system\n"
6367 " kexec Shut down and reboot the system with kexec\n"
6368 " exit [EXIT_CODE] Request user instance or container exit\n"
6369 " switch-root ROOT [INIT] Change to a different root file system\n"
6370 " suspend Suspend the system\n"
6371 " hibernate Hibernate the system\n"
6372 " hybrid-sleep Hibernate and suspend the system\n",
6373 program_invocation_short_name
);
6376 static void halt_help(void) {
6377 printf("%s [OPTIONS...]%s\n\n"
6378 "%s the system.\n\n"
6379 " --help Show this help\n"
6380 " --halt Halt the machine\n"
6381 " -p --poweroff Switch off the machine\n"
6382 " --reboot Reboot the machine\n"
6383 " -f --force Force immediate halt/power-off/reboot\n"
6384 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
6385 " -d --no-wtmp Don't write wtmp record\n"
6386 " --no-wall Don't send wall message before halt/power-off/reboot\n",
6387 program_invocation_short_name
,
6388 arg_action
== ACTION_REBOOT
? " [ARG]" : "",
6389 arg_action
== ACTION_REBOOT
? "Reboot" :
6390 arg_action
== ACTION_POWEROFF
? "Power off" :
6394 static void shutdown_help(void) {
6395 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
6396 "Shut down the system.\n\n"
6397 " --help Show this help\n"
6398 " -H --halt Halt the machine\n"
6399 " -P --poweroff Power-off the machine\n"
6400 " -r --reboot Reboot the machine\n"
6401 " -h Equivalent to --poweroff, overridden by --halt\n"
6402 " -k Don't halt/power-off/reboot, just send warnings\n"
6403 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6404 " -c Cancel a pending shutdown\n",
6405 program_invocation_short_name
);
6408 static void telinit_help(void) {
6409 printf("%s [OPTIONS...] {COMMAND}\n\n"
6410 "Send control commands to the init daemon.\n\n"
6411 " --help Show this help\n"
6412 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
6414 " 0 Power-off the machine\n"
6415 " 6 Reboot the machine\n"
6416 " 2, 3, 4, 5 Start runlevelX.target unit\n"
6417 " 1, s, S Enter rescue mode\n"
6418 " q, Q Reload init daemon configuration\n"
6419 " u, U Reexecute init daemon\n",
6420 program_invocation_short_name
);
6423 static void runlevel_help(void) {
6424 printf("%s [OPTIONS...]\n\n"
6425 "Prints the previous and current runlevel of the init system.\n\n"
6426 " --help Show this help\n",
6427 program_invocation_short_name
);
6430 static void help_types(void) {
6435 puts("Available unit types:");
6436 for (i
= 0; i
< _UNIT_TYPE_MAX
; i
++) {
6437 t
= unit_type_to_string(i
);
6443 static int systemctl_parse_argv(int argc
, char *argv
[]) {
6452 ARG_IGNORE_DEPENDENCIES
,
6464 ARG_NO_ASK_PASSWORD
,
6477 static const struct option options
[] = {
6478 { "help", no_argument
, NULL
, 'h' },
6479 { "version", no_argument
, NULL
, ARG_VERSION
},
6480 { "type", required_argument
, NULL
, 't' },
6481 { "property", required_argument
, NULL
, 'p' },
6482 { "all", no_argument
, NULL
, 'a' },
6483 { "reverse", no_argument
, NULL
, ARG_REVERSE
},
6484 { "after", no_argument
, NULL
, ARG_AFTER
},
6485 { "before", no_argument
, NULL
, ARG_BEFORE
},
6486 { "show-types", no_argument
, NULL
, ARG_SHOW_TYPES
},
6487 { "failed", no_argument
, NULL
, ARG_FAILED
}, /* compatibility only */
6488 { "full", no_argument
, NULL
, 'l' },
6489 { "job-mode", required_argument
, NULL
, ARG_JOB_MODE
},
6490 { "fail", no_argument
, NULL
, ARG_FAIL
}, /* compatibility only */
6491 { "irreversible", no_argument
, NULL
, ARG_IRREVERSIBLE
}, /* compatibility only */
6492 { "ignore-dependencies", no_argument
, NULL
, ARG_IGNORE_DEPENDENCIES
}, /* compatibility only */
6493 { "ignore-inhibitors", no_argument
, NULL
, 'i' },
6494 { "user", no_argument
, NULL
, ARG_USER
},
6495 { "system", no_argument
, NULL
, ARG_SYSTEM
},
6496 { "global", no_argument
, NULL
, ARG_GLOBAL
},
6497 { "no-block", no_argument
, NULL
, ARG_NO_BLOCK
},
6498 { "no-legend", no_argument
, NULL
, ARG_NO_LEGEND
},
6499 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
6500 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6501 { "quiet", no_argument
, NULL
, 'q' },
6502 { "root", required_argument
, NULL
, ARG_ROOT
},
6503 { "force", no_argument
, NULL
, ARG_FORCE
},
6504 { "no-reload", no_argument
, NULL
, ARG_NO_RELOAD
},
6505 { "kill-who", required_argument
, NULL
, ARG_KILL_WHO
},
6506 { "signal", required_argument
, NULL
, 's' },
6507 { "no-ask-password", no_argument
, NULL
, ARG_NO_ASK_PASSWORD
},
6508 { "host", required_argument
, NULL
, 'H' },
6509 { "machine", required_argument
, NULL
, 'M' },
6510 { "runtime", no_argument
, NULL
, ARG_RUNTIME
},
6511 { "lines", required_argument
, NULL
, 'n' },
6512 { "output", required_argument
, NULL
, 'o' },
6513 { "plain", no_argument
, NULL
, ARG_PLAIN
},
6514 { "state", required_argument
, NULL
, ARG_STATE
},
6515 { "recursive", no_argument
, NULL
, 'r' },
6516 { "preset-mode", required_argument
, NULL
, ARG_PRESET_MODE
},
6517 { "firmware-setup", no_argument
, NULL
, ARG_FIRMWARE_SETUP
},
6518 { "now", no_argument
, NULL
, ARG_NOW
},
6519 { "message", required_argument
, NULL
, ARG_MESSAGE
},
6528 /* we default to allowing interactive authorization only in systemctl (not in the legacy commands) */
6529 arg_ask_password
= true;
6531 while ((c
= getopt_long(argc
, argv
, "ht:p:alqfs:H:M:n:o:ir", options
, NULL
)) >= 0)
6543 const char *word
, *state
;
6546 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
6547 _cleanup_free_
char *type
;
6549 type
= strndup(word
, size
);
6553 if (streq(type
, "help")) {
6558 if (unit_type_from_string(type
) >= 0) {
6559 if (strv_push(&arg_types
, type
))
6565 /* It's much nicer to use --state= for
6566 * load states, but let's support this
6567 * in --types= too for compatibility
6568 * with old versions */
6569 if (unit_load_state_from_string(optarg
) >= 0) {
6570 if (strv_push(&arg_states
, type
) < 0)
6576 log_error("Unknown unit type or load state '%s'.", type
);
6577 log_info("Use -t help to see a list of allowed values.");
6585 /* Make sure that if the empty property list
6586 was specified, we won't show any properties. */
6587 if (isempty(optarg
) && !arg_properties
) {
6588 arg_properties
= new0(char*, 1);
6589 if (!arg_properties
)
6592 const char *word
, *state
;
6595 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
6598 prop
= strndup(word
, size
);
6602 if (strv_consume(&arg_properties
, prop
) < 0)
6607 /* If the user asked for a particular
6608 * property, show it to him, even if it is
6620 arg_dependency
= DEPENDENCY_REVERSE
;
6624 arg_dependency
= DEPENDENCY_AFTER
;
6628 arg_dependency
= DEPENDENCY_BEFORE
;
6631 case ARG_SHOW_TYPES
:
6632 arg_show_types
= true;
6636 arg_job_mode
= optarg
;
6640 arg_job_mode
= "fail";
6643 case ARG_IRREVERSIBLE
:
6644 arg_job_mode
= "replace-irreversibly";
6647 case ARG_IGNORE_DEPENDENCIES
:
6648 arg_job_mode
= "ignore-dependencies";
6652 arg_scope
= UNIT_FILE_USER
;
6656 arg_scope
= UNIT_FILE_SYSTEM
;
6660 arg_scope
= UNIT_FILE_GLOBAL
;
6664 arg_no_block
= true;
6668 arg_no_legend
= true;
6672 arg_no_pager
= true;
6688 if (strv_extend(&arg_states
, "failed") < 0)
6706 arg_no_reload
= true;
6710 arg_kill_who
= optarg
;
6714 arg_signal
= signal_from_string_try_harder(optarg
);
6715 if (arg_signal
< 0) {
6716 log_error("Failed to parse signal string %s.", optarg
);
6721 case ARG_NO_ASK_PASSWORD
:
6722 arg_ask_password
= false;
6726 arg_transport
= BUS_TRANSPORT_REMOTE
;
6731 arg_transport
= BUS_TRANSPORT_MACHINE
;
6740 if (safe_atou(optarg
, &arg_lines
) < 0) {
6741 log_error("Failed to parse lines '%s'", optarg
);
6747 arg_output
= output_mode_from_string(optarg
);
6748 if (arg_output
< 0) {
6749 log_error("Unknown output '%s'.", optarg
);
6755 arg_ignore_inhibitors
= true;
6762 case ARG_FIRMWARE_SETUP
:
6763 arg_firmware_setup
= true;
6767 const char *word
, *state
;
6770 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
6773 s
= strndup(word
, size
);
6777 if (strv_consume(&arg_states
, s
) < 0)
6784 if (geteuid() != 0) {
6785 log_error("--recursive requires root privileges.");
6789 arg_recursive
= true;
6792 case ARG_PRESET_MODE
:
6794 arg_preset_mode
= unit_file_preset_mode_from_string(optarg
);
6795 if (arg_preset_mode
< 0) {
6796 log_error("Failed to parse preset mode: %s.", optarg
);
6807 if (strv_extend(&arg_wall
, optarg
) < 0)
6815 assert_not_reached("Unhandled option");
6818 if (arg_transport
!= BUS_TRANSPORT_LOCAL
&& arg_scope
!= UNIT_FILE_SYSTEM
) {
6819 log_error("Cannot access user instance remotely.");
6826 static int halt_parse_argv(int argc
, char *argv
[]) {
6835 static const struct option options
[] = {
6836 { "help", no_argument
, NULL
, ARG_HELP
},
6837 { "halt", no_argument
, NULL
, ARG_HALT
},
6838 { "poweroff", no_argument
, NULL
, 'p' },
6839 { "reboot", no_argument
, NULL
, ARG_REBOOT
},
6840 { "force", no_argument
, NULL
, 'f' },
6841 { "wtmp-only", no_argument
, NULL
, 'w' },
6842 { "no-wtmp", no_argument
, NULL
, 'd' },
6843 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6852 if (utmp_get_runlevel(&runlevel
, NULL
) >= 0)
6853 if (runlevel
== '0' || runlevel
== '6')
6856 while ((c
= getopt_long(argc
, argv
, "pfwdnih", options
, NULL
)) >= 0)
6864 arg_action
= ACTION_HALT
;
6868 if (arg_action
!= ACTION_REBOOT
)
6869 arg_action
= ACTION_POWEROFF
;
6873 arg_action
= ACTION_REBOOT
;
6895 /* Compatibility nops */
6902 assert_not_reached("Unhandled option");
6905 if (arg_action
== ACTION_REBOOT
&& (argc
== optind
|| argc
== optind
+ 1)) {
6906 r
= update_reboot_param_file(argc
== optind
+ 1 ? argv
[optind
] : NULL
);
6909 } else if (optind
< argc
) {
6910 log_error("Too many arguments.");
6917 static int parse_shutdown_time_spec(const char *t
, usec_t
*_u
) {
6921 if (streq(t
, "now"))
6923 else if (!strchr(t
, ':')) {
6926 if (safe_atou64(t
, &u
) < 0)
6929 *_u
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
* u
;
6938 hour
= strtol(t
, &e
, 10);
6939 if (errno
> 0 || *e
!= ':' || hour
< 0 || hour
> 23)
6942 minute
= strtol(e
+1, &e
, 10);
6943 if (errno
> 0 || *e
!= 0 || minute
< 0 || minute
> 59)
6946 n
= now(CLOCK_REALTIME
);
6947 s
= (time_t) (n
/ USEC_PER_SEC
);
6949 assert_se(localtime_r(&s
, &tm
));
6951 tm
.tm_hour
= (int) hour
;
6952 tm
.tm_min
= (int) minute
;
6955 assert_se(s
= mktime(&tm
));
6957 *_u
= (usec_t
) s
* USEC_PER_SEC
;
6960 *_u
+= USEC_PER_DAY
;
6966 static int shutdown_parse_argv(int argc
, char *argv
[]) {
6973 static const struct option options
[] = {
6974 { "help", no_argument
, NULL
, ARG_HELP
},
6975 { "halt", no_argument
, NULL
, 'H' },
6976 { "poweroff", no_argument
, NULL
, 'P' },
6977 { "reboot", no_argument
, NULL
, 'r' },
6978 { "kexec", no_argument
, NULL
, 'K' }, /* not documented extension */
6979 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6989 while ((c
= getopt_long(argc
, argv
, "HPrhkKt:afFc", options
, NULL
)) >= 0)
6997 arg_action
= ACTION_HALT
;
7001 arg_action
= ACTION_POWEROFF
;
7006 arg_action
= ACTION_KEXEC
;
7008 arg_action
= ACTION_REBOOT
;
7012 arg_action
= ACTION_KEXEC
;
7016 if (arg_action
!= ACTION_HALT
)
7017 arg_action
= ACTION_POWEROFF
;
7032 /* Compatibility nops */
7036 arg_action
= ACTION_CANCEL_SHUTDOWN
;
7043 assert_not_reached("Unhandled option");
7046 if (argc
> optind
&& arg_action
!= ACTION_CANCEL_SHUTDOWN
) {
7047 r
= parse_shutdown_time_spec(argv
[optind
], &arg_when
);
7049 log_error("Failed to parse time specification: %s", argv
[optind
]);
7053 arg_when
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
;
7055 if (argc
> optind
&& arg_action
== ACTION_CANCEL_SHUTDOWN
)
7056 /* No time argument for shutdown cancel */
7057 wall
= argv
+ optind
;
7058 else if (argc
> optind
+ 1)
7059 /* We skip the time argument */
7060 wall
= argv
+ optind
+ 1;
7063 arg_wall
= strv_copy(wall
);
7073 static int telinit_parse_argv(int argc
, char *argv
[]) {
7080 static const struct option options
[] = {
7081 { "help", no_argument
, NULL
, ARG_HELP
},
7082 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7086 static const struct {
7090 { '0', ACTION_POWEROFF
},
7091 { '6', ACTION_REBOOT
},
7092 { '1', ACTION_RESCUE
},
7093 { '2', ACTION_RUNLEVEL2
},
7094 { '3', ACTION_RUNLEVEL3
},
7095 { '4', ACTION_RUNLEVEL4
},
7096 { '5', ACTION_RUNLEVEL5
},
7097 { 's', ACTION_RESCUE
},
7098 { 'S', ACTION_RESCUE
},
7099 { 'q', ACTION_RELOAD
},
7100 { 'Q', ACTION_RELOAD
},
7101 { 'u', ACTION_REEXEC
},
7102 { 'U', ACTION_REEXEC
}
7111 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
7126 assert_not_reached("Unhandled option");
7129 if (optind
>= argc
) {
7130 log_error("%s: required argument missing.", program_invocation_short_name
);
7134 if (optind
+ 1 < argc
) {
7135 log_error("Too many arguments.");
7139 if (strlen(argv
[optind
]) != 1) {
7140 log_error("Expected single character argument.");
7144 for (i
= 0; i
< ELEMENTSOF(table
); i
++)
7145 if (table
[i
].from
== argv
[optind
][0])
7148 if (i
>= ELEMENTSOF(table
)) {
7149 log_error("Unknown command '%s'.", argv
[optind
]);
7153 arg_action
= table
[i
].to
;
7160 static int runlevel_parse_argv(int argc
, char *argv
[]) {
7166 static const struct option options
[] = {
7167 { "help", no_argument
, NULL
, ARG_HELP
},
7176 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
7187 assert_not_reached("Unhandled option");
7190 if (optind
< argc
) {
7191 log_error("Too many arguments.");
7198 static int parse_argv(int argc
, char *argv
[]) {
7202 if (program_invocation_short_name
) {
7204 if (strstr(program_invocation_short_name
, "halt")) {
7205 arg_action
= ACTION_HALT
;
7206 return halt_parse_argv(argc
, argv
);
7207 } else if (strstr(program_invocation_short_name
, "poweroff")) {
7208 arg_action
= ACTION_POWEROFF
;
7209 return halt_parse_argv(argc
, argv
);
7210 } else if (strstr(program_invocation_short_name
, "reboot")) {
7212 arg_action
= ACTION_KEXEC
;
7214 arg_action
= ACTION_REBOOT
;
7215 return halt_parse_argv(argc
, argv
);
7216 } else if (strstr(program_invocation_short_name
, "shutdown")) {
7217 arg_action
= ACTION_POWEROFF
;
7218 return shutdown_parse_argv(argc
, argv
);
7219 } else if (strstr(program_invocation_short_name
, "init")) {
7221 if (sd_booted() > 0) {
7222 arg_action
= _ACTION_INVALID
;
7223 return telinit_parse_argv(argc
, argv
);
7225 /* Hmm, so some other init system is
7226 * running, we need to forward this
7227 * request to it. For now we simply
7228 * guess that it is Upstart. */
7230 execv(TELINIT
, argv
);
7232 log_error("Couldn't find an alternative telinit implementation to spawn.");
7236 } else if (strstr(program_invocation_short_name
, "runlevel")) {
7237 arg_action
= ACTION_RUNLEVEL
;
7238 return runlevel_parse_argv(argc
, argv
);
7242 arg_action
= ACTION_SYSTEMCTL
;
7243 return systemctl_parse_argv(argc
, argv
);
7246 _pure_
static int action_to_runlevel(void) {
7248 static const char table
[_ACTION_MAX
] = {
7249 [ACTION_HALT
] = '0',
7250 [ACTION_POWEROFF
] = '0',
7251 [ACTION_REBOOT
] = '6',
7252 [ACTION_RUNLEVEL2
] = '2',
7253 [ACTION_RUNLEVEL3
] = '3',
7254 [ACTION_RUNLEVEL4
] = '4',
7255 [ACTION_RUNLEVEL5
] = '5',
7256 [ACTION_RESCUE
] = '1'
7259 assert(arg_action
< _ACTION_MAX
);
7261 return table
[arg_action
];
7264 static int talk_initctl(void) {
7265 #ifdef HAVE_SYSV_COMPAT
7266 struct init_request request
= {
7267 .magic
= INIT_MAGIC
,
7269 .cmd
= INIT_CMD_RUNLVL
7272 _cleanup_close_
int fd
= -1;
7276 rl
= action_to_runlevel();
7280 request
.runlevel
= rl
;
7282 fd
= open(INIT_FIFO
, O_WRONLY
|O_NDELAY
|O_CLOEXEC
|O_NOCTTY
);
7284 if (errno
== ENOENT
)
7287 return log_error_errno(errno
, "Failed to open "INIT_FIFO
": %m");
7290 r
= loop_write(fd
, &request
, sizeof(request
), false);
7292 return log_error_errno(r
, "Failed to write to "INIT_FIFO
": %m");
7300 static int systemctl_main(int argc
, char *argv
[], int bus_error
) {
7302 static const struct {
7310 int (* const dispatch
)(char **args
);
7312 { "list-units", MORE
, 0, list_units
},
7313 { "list-unit-files", MORE
, 1, list_unit_files
},
7314 { "list-sockets", MORE
, 1, list_sockets
},
7315 { "list-timers", MORE
, 1, list_timers
},
7316 { "list-jobs", MORE
, 1, list_jobs
},
7317 { "list-machines", MORE
, 1, list_machines
},
7318 { "clear-jobs", EQUAL
, 1, daemon_reload
},
7319 { "cancel", MORE
, 2, cancel_job
},
7320 { "start", MORE
, 2, start_unit
},
7321 { "stop", MORE
, 2, start_unit
},
7322 { "condstop", MORE
, 2, start_unit
}, /* For compatibility with ALTLinux */
7323 { "reload", MORE
, 2, start_unit
},
7324 { "restart", MORE
, 2, start_unit
},
7325 { "try-restart", MORE
, 2, start_unit
},
7326 { "reload-or-restart", MORE
, 2, start_unit
},
7327 { "reload-or-try-restart", MORE
, 2, start_unit
},
7328 { "force-reload", MORE
, 2, start_unit
}, /* For compatibility with SysV */
7329 { "condreload", MORE
, 2, start_unit
}, /* For compatibility with ALTLinux */
7330 { "condrestart", MORE
, 2, start_unit
}, /* For compatibility with RH */
7331 { "isolate", EQUAL
, 2, start_unit
},
7332 { "kill", MORE
, 2, kill_unit
},
7333 { "is-active", MORE
, 2, check_unit_active
},
7334 { "check", MORE
, 2, check_unit_active
},
7335 { "is-failed", MORE
, 2, check_unit_failed
},
7336 { "show", MORE
, 1, show
},
7337 { "cat", MORE
, 2, cat
, },
7338 { "status", MORE
, 1, show
},
7339 { "help", MORE
, 2, show
},
7340 { "snapshot", LESS
, 2, snapshot
},
7341 { "delete", MORE
, 2, delete_snapshot
},
7342 { "daemon-reload", EQUAL
, 1, daemon_reload
},
7343 { "daemon-reexec", EQUAL
, 1, daemon_reload
},
7344 { "show-environment", EQUAL
, 1, show_environment
},
7345 { "set-environment", MORE
, 2, set_environment
},
7346 { "unset-environment", MORE
, 2, set_environment
},
7347 { "import-environment", MORE
, 1, import_environment
},
7348 { "halt", EQUAL
, 1, start_special
, },
7349 { "poweroff", EQUAL
, 1, start_special
, },
7350 { "reboot", MORE
, 1, start_special
, },
7351 { "kexec", EQUAL
, 1, start_special
},
7352 { "suspend", EQUAL
, 1, start_special
},
7353 { "hibernate", EQUAL
, 1, start_special
},
7354 { "hybrid-sleep", EQUAL
, 1, start_special
},
7355 { "default", EQUAL
, 1, start_special
},
7356 { "rescue", EQUAL
, 1, start_special
},
7357 { "emergency", EQUAL
, 1, start_special
},
7358 { "exit", LESS
, 2, start_special
},
7359 { "reset-failed", MORE
, 1, reset_failed
},
7360 { "enable", MORE
, 2, enable_unit
, },
7361 { "disable", MORE
, 2, enable_unit
, },
7362 { "is-enabled", MORE
, 2, unit_is_enabled
, },
7363 { "reenable", MORE
, 2, enable_unit
, },
7364 { "preset", MORE
, 2, enable_unit
, },
7365 { "preset-all", EQUAL
, 1, preset_all
, },
7366 { "mask", MORE
, 2, enable_unit
, },
7367 { "unmask", MORE
, 2, enable_unit
, },
7368 { "link", MORE
, 2, enable_unit
, },
7369 { "switch-root", MORE
, 2, switch_root
},
7370 { "list-dependencies", LESS
, 2, list_dependencies
},
7371 { "set-default", EQUAL
, 2, set_default
, },
7372 { "get-default", EQUAL
, 1, get_default
, },
7373 { "set-property", MORE
, 3, set_property
},
7374 { "is-system-running", EQUAL
, 1, is_system_running
},
7375 { "add-wants", MORE
, 3, add_dependency
, },
7376 { "add-requires", MORE
, 3, add_dependency
, },
7377 { "edit", MORE
, 2, edit
, },
7386 left
= argc
- optind
;
7388 /* Special rule: no arguments (left == 0) means "list-units" */
7390 if (streq(argv
[optind
], "help") && !argv
[optind
+1]) {
7391 log_error("This command expects one or more unit names. Did you mean --help?");
7395 for (; verb
->verb
; verb
++)
7396 if (streq(argv
[optind
], verb
->verb
))
7399 log_error("Unknown operation '%s'.", argv
[optind
]);
7404 switch (verb
->argc_cmp
) {
7407 if (left
!= verb
->argc
) {
7408 log_error("Invalid number of arguments.");
7415 if (left
< verb
->argc
) {
7416 log_error("Too few arguments.");
7423 if (left
> verb
->argc
) {
7424 log_error("Too many arguments.");
7431 assert_not_reached("Unknown comparison operator.");
7434 return verb
->dispatch(argv
+ optind
);
7437 static int reload_with_fallback(void) {
7439 /* First, try systemd via D-Bus. */
7440 if (daemon_reload(NULL
) >= 0)
7443 /* Nothing else worked, so let's try signals */
7444 assert(arg_action
== ACTION_RELOAD
|| arg_action
== ACTION_REEXEC
);
7446 if (kill(1, arg_action
== ACTION_RELOAD
? SIGHUP
: SIGTERM
) < 0)
7447 return log_error_errno(errno
, "kill() failed: %m");
7452 static int start_with_fallback(void) {
7454 /* First, try systemd via D-Bus. */
7455 if (start_unit(NULL
) >= 0)
7458 /* Nothing else worked, so let's try
7460 if (talk_initctl() > 0)
7463 log_error("Failed to talk to init daemon.");
7467 static int halt_now(enum action a
) {
7469 /* The kernel will automaticall flush ATA disks and suchlike
7470 * on reboot(), but the file systems need to be synce'd
7471 * explicitly in advance. */
7474 /* Make sure C-A-D is handled by the kernel from this point
7476 reboot(RB_ENABLE_CAD
);
7481 log_info("Halting.");
7482 reboot(RB_HALT_SYSTEM
);
7485 case ACTION_POWEROFF
:
7486 log_info("Powering off.");
7487 reboot(RB_POWER_OFF
);
7491 case ACTION_REBOOT
: {
7492 _cleanup_free_
char *param
= NULL
;
7494 if (read_one_line_file(REBOOT_PARAM_FILE
, ¶m
) >= 0) {
7495 log_info("Rebooting with argument '%s'.", param
);
7496 syscall(SYS_reboot
, LINUX_REBOOT_MAGIC1
, LINUX_REBOOT_MAGIC2
, LINUX_REBOOT_CMD_RESTART2
, param
);
7499 log_info("Rebooting.");
7500 reboot(RB_AUTOBOOT
);
7505 assert_not_reached("Unknown action.");
7509 static int logind_schedule_shutdown(void) {
7512 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
7513 char date
[FORMAT_TIMESTAMP_MAX
];
7518 (void) logind_set_wall_message();
7520 r
= acquire_bus(BUS_FULL
, &bus
);
7524 switch (arg_action
) {
7528 case ACTION_POWEROFF
:
7529 action
= "poweroff";
7540 action
= strjoina("dry-", action
);
7542 r
= sd_bus_call_method(
7544 "org.freedesktop.login1",
7545 "/org/freedesktop/login1",
7546 "org.freedesktop.login1.Manager",
7554 return log_warning_errno(r
, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s", bus_error_message(&error
, r
));
7556 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.", format_timestamp(date
, sizeof(date
), arg_when
));
7559 log_error("Cannot schedule shutdown without logind support, proceeding with immediate shutdown.");
7564 static int halt_main(void) {
7567 r
= logind_check_inhibitors(arg_action
);
7571 if (geteuid() != 0) {
7575 log_error("Must be root.");
7579 /* Try logind if we are a normal user and no special
7580 * mode applies. Maybe PolicyKit allows us to shutdown
7582 if (IN_SET(arg_action
,
7585 r
= logind_reboot(arg_action
);
7588 if (IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
7589 /* requested operation is not supported or already in progress */
7591 /* on all other errors, try low-level operation */
7596 r
= logind_schedule_shutdown();
7601 if (!arg_dry
&& !arg_force
)
7602 return start_with_fallback();
7604 assert(geteuid() == 0);
7607 if (sd_booted() > 0)
7608 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
7610 r
= utmp_put_shutdown();
7612 log_warning_errno(r
, "Failed to write utmp record: %m");
7619 r
= halt_now(arg_action
);
7621 return log_error_errno(r
, "Failed to reboot: %m");
7624 static int runlevel_main(void) {
7625 int r
, runlevel
, previous
;
7627 r
= utmp_get_runlevel(&runlevel
, &previous
);
7634 previous
<= 0 ? 'N' : previous
,
7635 runlevel
<= 0 ? 'N' : runlevel
);
7640 static int logind_cancel_shutdown(void) {
7642 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
7646 r
= acquire_bus(BUS_FULL
, &bus
);
7650 (void) logind_set_wall_message();
7652 r
= sd_bus_call_method(
7654 "org.freedesktop.login1",
7655 "/org/freedesktop/login1",
7656 "org.freedesktop.login1.Manager",
7657 "CancelScheduledShutdown",
7661 return log_warning_errno(r
, "Failed to talk to logind, shutdown hasn't been cancelled: %s", bus_error_message(&error
, r
));
7665 log_error("Not compiled with logind support, cannot cancel scheduled shutdowns.");
7670 int main(int argc
, char*argv
[]) {
7673 setlocale(LC_ALL
, "");
7674 log_parse_environment();
7677 /* Explicitly not on_tty() to avoid setting cached value.
7678 * This becomes relevant for piping output which might be
7680 original_stdout_is_tty
= isatty(STDOUT_FILENO
);
7682 r
= parse_argv(argc
, argv
);
7686 if (running_in_chroot() > 0 && arg_action
!= ACTION_SYSTEMCTL
) {
7687 log_info("Running in chroot, ignoring request.");
7692 /* systemctl_main() will print an error message for the bus
7693 * connection, but only if it needs to */
7695 switch (arg_action
) {
7697 case ACTION_SYSTEMCTL
:
7698 r
= systemctl_main(argc
, argv
, r
);
7702 case ACTION_POWEROFF
:
7708 case ACTION_RUNLEVEL2
:
7709 case ACTION_RUNLEVEL3
:
7710 case ACTION_RUNLEVEL4
:
7711 case ACTION_RUNLEVEL5
:
7713 case ACTION_EMERGENCY
:
7714 case ACTION_DEFAULT
:
7715 r
= start_with_fallback();
7720 r
= reload_with_fallback();
7723 case ACTION_CANCEL_SHUTDOWN
:
7724 r
= logind_cancel_shutdown();
7727 case ACTION_RUNLEVEL
:
7728 r
= runlevel_main();
7731 case _ACTION_INVALID
:
7733 assert_not_reached("Unknown action");
7738 ask_password_agent_close();
7739 polkit_agent_close();
7741 strv_free(arg_types
);
7742 strv_free(arg_states
);
7743 strv_free(arg_properties
);
7745 strv_free(arg_wall
);
7749 return r
< 0 ? EXIT_FAILURE
: r
;