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
) {
2180 if (strv_length(args
) <= 1)
2181 return daemon_reload(args
);
2183 polkit_agent_open_if_enabled();
2185 r
= acquire_bus(BUS_MANAGER
, &bus
);
2189 STRV_FOREACH(name
, args
+1) {
2190 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2194 q
= safe_atou32(*name
, &id
);
2196 return log_error_errno(q
, "Failed to parse job id \"%s\": %m", *name
);
2198 q
= sd_bus_call_method(
2200 "org.freedesktop.systemd1",
2201 "/org/freedesktop/systemd1",
2202 "org.freedesktop.systemd1.Manager",
2208 log_error_errno(q
, "Failed to cancel job %"PRIu32
": %s", id
, bus_error_message(&error
, q
));
2217 static int need_daemon_reload(sd_bus
*bus
, const char *unit
) {
2218 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2222 /* We ignore all errors here, since this is used to show a
2225 /* We don't use unit_dbus_path_from_name() directly since we
2226 * don't want to load the unit if it isn't loaded. */
2228 r
= sd_bus_call_method(
2230 "org.freedesktop.systemd1",
2231 "/org/freedesktop/systemd1",
2232 "org.freedesktop.systemd1.Manager",
2240 r
= sd_bus_message_read(reply
, "o", &path
);
2244 r
= sd_bus_get_property_trivial(
2246 "org.freedesktop.systemd1",
2248 "org.freedesktop.systemd1.Unit",
2258 static void warn_unit_file_changed(const char *name
) {
2259 log_warning("%sWarning:%s %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
2260 ansi_highlight_red(),
2263 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user");
2266 static int unit_file_find_path(LookupPaths
*lp
, const char *unit_name
, char **unit_path
) {
2273 STRV_FOREACH(p
, lp
->unit_path
) {
2274 _cleanup_free_
char *path
;
2276 path
= path_join(arg_root
, *p
, unit_name
);
2280 if (access(path
, F_OK
) == 0) {
2290 static int unit_find_paths(
2292 const char *unit_name
,
2294 char **fragment_path
,
2295 char ***dropin_paths
) {
2297 _cleanup_free_
char *path
= NULL
;
2298 _cleanup_strv_free_
char **dropins
= NULL
;
2302 * Finds where the unit is defined on disk. Returns 0 if the unit
2303 * is not found. Returns 1 if it is found, and sets
2304 * - the path to the unit in *path, if it exists on disk,
2305 * - and a strv of existing drop-ins in *dropins,
2306 * if the arg is not NULL and any dropins were found.
2310 assert(fragment_path
);
2313 if (!install_client_side() && !unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
2314 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2315 _cleanup_bus_message_unref_ sd_bus_message
*unit_load_error
= NULL
;
2316 _cleanup_free_
char *unit
= NULL
;
2317 char *unit_load_error_name
, *unit_load_error_message
;
2319 unit
= unit_dbus_path_from_name(unit_name
);
2323 if (need_daemon_reload(bus
, unit_name
) > 0)
2324 warn_unit_file_changed(unit_name
);
2326 r
= sd_bus_get_property(
2328 "org.freedesktop.systemd1",
2330 "org.freedesktop.systemd1.Unit",
2336 return log_error_errno(r
, "Failed to get LoadError: %s", bus_error_message(&error
, r
));
2338 r
= sd_bus_message_read(
2341 &unit_load_error_name
,
2342 &unit_load_error_message
);
2344 return bus_log_parse_error(r
);
2346 if (!isempty(unit_load_error_name
)) {
2347 log_error("Unit %s is not loaded: %s", unit_name
, unit_load_error_message
);
2351 r
= sd_bus_get_property_string(
2353 "org.freedesktop.systemd1",
2355 "org.freedesktop.systemd1.Unit",
2360 return log_error_errno(r
, "Failed to get FragmentPath: %s", bus_error_message(&error
, r
));
2363 r
= sd_bus_get_property_strv(
2365 "org.freedesktop.systemd1",
2367 "org.freedesktop.systemd1.Unit",
2372 return log_error_errno(r
, "Failed to get DropInPaths: %s", bus_error_message(&error
, r
));
2375 _cleanup_set_free_ Set
*names
;
2377 names
= set_new(NULL
);
2381 r
= set_put(names
, unit_name
);
2383 return log_error_errno(r
, "Failed to add unit name: %m");
2385 r
= unit_file_find_path(lp
, unit_name
, &path
);
2390 _cleanup_free_
char *template = NULL
;
2392 r
= unit_name_template(unit_name
, &template);
2393 if (r
< 0 && r
!= -EINVAL
)
2394 return log_error_errno(r
, "Failed to determine template name: %m");
2396 r
= unit_file_find_path(lp
, template, &path
);
2403 r
= unit_file_find_dropin_paths(lp
->unit_path
, NULL
, names
, &dropins
);
2411 if (!isempty(path
)) {
2412 *fragment_path
= path
;
2417 if (dropin_paths
&& !strv_isempty(dropins
)) {
2418 *dropin_paths
= dropins
;
2424 log_error("No files found for %s.", unit_name
);
2429 static int check_one_unit(sd_bus
*bus
, const char *name
, const char *good_states
, bool quiet
) {
2430 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2431 _cleanup_free_
char *n
= NULL
, *state
= NULL
;
2437 r
= unit_name_mangle(name
, UNIT_NAME_NOGLOB
, &n
);
2439 return log_error_errno(r
, "Failed to mangle unit name: %m");
2441 /* We don't use unit_dbus_path_from_name() directly since we
2442 * don't want to load the unit if it isn't loaded. */
2444 r
= sd_bus_call_method(
2446 "org.freedesktop.systemd1",
2447 "/org/freedesktop/systemd1",
2448 "org.freedesktop.systemd1.Manager",
2459 r
= sd_bus_message_read(reply
, "o", &path
);
2461 return bus_log_parse_error(r
);
2463 r
= sd_bus_get_property_string(
2465 "org.freedesktop.systemd1",
2467 "org.freedesktop.systemd1.Unit",
2480 return nulstr_contains(good_states
, state
);
2483 static int check_triggering_units(
2487 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2488 _cleanup_free_
char *path
= NULL
, *n
= NULL
, *state
= NULL
;
2489 _cleanup_strv_free_
char **triggered_by
= NULL
;
2490 bool print_warning_label
= true;
2494 r
= unit_name_mangle(name
, UNIT_NAME_NOGLOB
, &n
);
2496 return log_error_errno(r
, "Failed to mangle unit name: %m");
2498 path
= unit_dbus_path_from_name(n
);
2502 r
= sd_bus_get_property_string(
2504 "org.freedesktop.systemd1",
2506 "org.freedesktop.systemd1.Unit",
2511 return log_error_errno(r
, "Failed to get load state of %s: %s", n
, bus_error_message(&error
, r
));
2513 if (streq(state
, "masked"))
2516 r
= sd_bus_get_property_strv(
2518 "org.freedesktop.systemd1",
2520 "org.freedesktop.systemd1.Unit",
2525 return log_error_errno(r
, "Failed to get triggered by array of %s: %s", n
, bus_error_message(&error
, r
));
2527 STRV_FOREACH(i
, triggered_by
) {
2528 r
= check_one_unit(bus
, *i
, "active\0reloading\0", true);
2530 return log_error_errno(r
, "Failed to check unit: %m");
2535 if (print_warning_label
) {
2536 log_warning("Warning: Stopping %s, but it can still be activated by:", n
);
2537 print_warning_label
= false;
2540 log_warning(" %s", *i
);
2546 static const struct {
2549 } unit_actions
[] = {
2550 { "start", "StartUnit" },
2551 { "stop", "StopUnit" },
2552 { "condstop", "StopUnit" },
2553 { "reload", "ReloadUnit" },
2554 { "restart", "RestartUnit" },
2555 { "try-restart", "TryRestartUnit" },
2556 { "condrestart", "TryRestartUnit" },
2557 { "reload-or-restart", "ReloadOrRestartUnit" },
2558 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2559 { "condreload", "ReloadOrTryRestartUnit" },
2560 { "force-reload", "ReloadOrTryRestartUnit" }
2563 static const char *verb_to_method(const char *verb
) {
2566 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2567 if (streq_ptr(unit_actions
[i
].verb
, verb
))
2568 return unit_actions
[i
].method
;
2573 static const char *method_to_verb(const char *method
) {
2576 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2577 if (streq_ptr(unit_actions
[i
].method
, method
))
2578 return unit_actions
[i
].verb
;
2583 static int start_unit_one(
2588 sd_bus_error
*error
,
2589 BusWaitForJobs
*w
) {
2591 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2600 log_debug("Calling manager for %s on %s, %s", method
, name
, mode
);
2602 r
= sd_bus_call_method(
2604 "org.freedesktop.systemd1",
2605 "/org/freedesktop/systemd1",
2606 "org.freedesktop.systemd1.Manager",
2614 if (r
== -ENOENT
&& arg_action
!= ACTION_SYSTEMCTL
)
2615 /* There's always a fallback possible for
2616 * legacy actions. */
2617 return -EADDRNOTAVAIL
;
2619 verb
= method_to_verb(method
);
2621 return log_error_errno(r
, "Failed to %s %s: %s", verb
, name
, bus_error_message(error
, r
));
2624 r
= sd_bus_message_read(reply
, "o", &path
);
2626 return bus_log_parse_error(r
);
2628 if (need_daemon_reload(bus
, name
) > 0)
2629 warn_unit_file_changed(name
);
2632 log_debug("Adding %s to the set", path
);
2633 r
= bus_wait_for_jobs_add(w
, path
);
2641 static int expand_names(sd_bus
*bus
, char **names
, const char* suffix
, char ***ret
) {
2642 _cleanup_strv_free_
char **mangled
= NULL
, **globs
= NULL
;
2649 STRV_FOREACH(name
, names
) {
2653 r
= unit_name_mangle_with_suffix(*name
, UNIT_NAME_GLOB
, suffix
, &t
);
2655 r
= unit_name_mangle(*name
, UNIT_NAME_GLOB
, &t
);
2657 return log_error_errno(r
, "Failed to mangle name: %m");
2659 if (string_is_glob(t
))
2660 r
= strv_consume(&globs
, t
);
2662 r
= strv_consume(&mangled
, t
);
2667 /* Query the manager only if any of the names are a glob, since
2668 * this is fairly expensive */
2669 if (!strv_isempty(globs
)) {
2670 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2671 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
2673 r
= get_unit_list(bus
, NULL
, globs
, &unit_infos
, 0, &reply
);
2677 for (i
= 0; i
< r
; i
++)
2678 if (strv_extend(&mangled
, unit_infos
[i
].id
) < 0)
2683 mangled
= NULL
; /* do not free */
2688 static const struct {
2692 } action_table
[_ACTION_MAX
] = {
2693 [ACTION_HALT
] = { SPECIAL_HALT_TARGET
, "halt", "replace-irreversibly" },
2694 [ACTION_POWEROFF
] = { SPECIAL_POWEROFF_TARGET
, "poweroff", "replace-irreversibly" },
2695 [ACTION_REBOOT
] = { SPECIAL_REBOOT_TARGET
, "reboot", "replace-irreversibly" },
2696 [ACTION_KEXEC
] = { SPECIAL_KEXEC_TARGET
, "kexec", "replace-irreversibly" },
2697 [ACTION_RUNLEVEL2
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2698 [ACTION_RUNLEVEL3
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2699 [ACTION_RUNLEVEL4
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2700 [ACTION_RUNLEVEL5
] = { SPECIAL_GRAPHICAL_TARGET
, NULL
, "isolate" },
2701 [ACTION_RESCUE
] = { SPECIAL_RESCUE_TARGET
, "rescue", "isolate" },
2702 [ACTION_EMERGENCY
] = { SPECIAL_EMERGENCY_TARGET
, "emergency", "isolate" },
2703 [ACTION_DEFAULT
] = { SPECIAL_DEFAULT_TARGET
, "default", "isolate" },
2704 [ACTION_EXIT
] = { SPECIAL_EXIT_TARGET
, "exit", "replace-irreversibly" },
2705 [ACTION_SUSPEND
] = { SPECIAL_SUSPEND_TARGET
, "suspend", "replace-irreversibly" },
2706 [ACTION_HIBERNATE
] = { SPECIAL_HIBERNATE_TARGET
, "hibernate", "replace-irreversibly" },
2707 [ACTION_HYBRID_SLEEP
] = { SPECIAL_HYBRID_SLEEP_TARGET
, "hybrid-sleep", "replace-irreversibly" },
2710 static enum action
verb_to_action(const char *verb
) {
2713 for (i
= _ACTION_INVALID
; i
< _ACTION_MAX
; i
++)
2714 if (streq_ptr(action_table
[i
].verb
, verb
))
2717 return _ACTION_INVALID
;
2720 static int start_unit(char **args
) {
2721 _cleanup_(bus_wait_for_jobs_freep
) BusWaitForJobs
*w
= NULL
;
2722 const char *method
, *mode
, *one_name
, *suffix
= NULL
;
2723 _cleanup_strv_free_
char **names
= NULL
;
2728 ask_password_agent_open_if_enabled();
2729 polkit_agent_open_if_enabled();
2731 r
= acquire_bus(BUS_MANAGER
, &bus
);
2735 if (arg_action
== ACTION_SYSTEMCTL
) {
2737 method
= verb_to_method(args
[0]);
2738 action
= verb_to_action(args
[0]);
2740 if (streq(args
[0], "isolate")) {
2744 mode
= action_table
[action
].mode
?: arg_job_mode
;
2746 one_name
= action_table
[action
].target
;
2748 assert(arg_action
< ELEMENTSOF(action_table
));
2749 assert(action_table
[arg_action
].target
);
2751 method
= "StartUnit";
2753 mode
= action_table
[arg_action
].mode
;
2754 one_name
= action_table
[arg_action
].target
;
2758 names
= strv_new(one_name
, NULL
);
2760 r
= expand_names(bus
, strv_skip(args
, 1), suffix
, &names
);
2762 return log_error_errno(r
, "Failed to expand names: %m");
2765 if (!arg_no_block
) {
2766 r
= bus_wait_for_jobs_new(bus
, &w
);
2768 return log_error_errno(r
, "Could not watch jobs: %m");
2771 STRV_FOREACH(name
, names
) {
2772 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2775 q
= start_unit_one(bus
, method
, *name
, mode
, &error
, w
);
2776 if (r
>= 0 && q
< 0)
2777 r
= translate_bus_error_to_exit_status(q
, &error
);
2780 if (!arg_no_block
) {
2783 q
= bus_wait_for_jobs(w
, arg_quiet
);
2787 /* When stopping units, warn if they can still be triggered by
2788 * another active unit (socket, path, timer) */
2789 if (!arg_quiet
&& streq(method
, "StopUnit"))
2790 STRV_FOREACH(name
, names
)
2791 check_triggering_units(bus
, *name
);
2797 static int logind_set_wall_message(void) {
2799 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2801 _cleanup_free_
char *m
= NULL
;
2804 r
= acquire_bus(BUS_FULL
, &bus
);
2808 m
= strv_join(arg_wall
, " ");
2812 r
= sd_bus_call_method(
2814 "org.freedesktop.login1",
2815 "/org/freedesktop/login1",
2816 "org.freedesktop.login1.Manager",
2825 return log_warning_errno(r
, "Failed to set wall message, ignoring: %s", bus_error_message(&error
, r
));
2831 /* Ask systemd-logind, which might grant access to unprivileged users
2832 * through PolicyKit */
2833 static int logind_reboot(enum action a
) {
2835 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2836 const char *method
, *description
;
2840 polkit_agent_open_if_enabled();
2841 (void) logind_set_wall_message();
2843 r
= acquire_bus(BUS_FULL
, &bus
);
2851 description
= "reboot system";
2854 case ACTION_POWEROFF
:
2855 method
= "PowerOff";
2856 description
= "power off system";
2859 case ACTION_SUSPEND
:
2861 description
= "suspend system";
2864 case ACTION_HIBERNATE
:
2865 method
= "Hibernate";
2866 description
= "hibernate system";
2869 case ACTION_HYBRID_SLEEP
:
2870 method
= "HybridSleep";
2871 description
= "put system into hybrid sleep";
2878 r
= sd_bus_call_method(
2880 "org.freedesktop.login1",
2881 "/org/freedesktop/login1",
2882 "org.freedesktop.login1.Manager",
2886 "b", arg_ask_password
);
2888 return log_error_errno(r
, "Failed to %s via logind: %s", description
, bus_error_message(&error
, r
));
2896 static int logind_check_inhibitors(enum action a
) {
2898 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2899 _cleanup_strv_free_
char **sessions
= NULL
;
2900 const char *what
, *who
, *why
, *mode
;
2907 if (arg_ignore_inhibitors
|| arg_force
> 0)
2919 r
= acquire_bus(BUS_FULL
, &bus
);
2923 r
= sd_bus_call_method(
2925 "org.freedesktop.login1",
2926 "/org/freedesktop/login1",
2927 "org.freedesktop.login1.Manager",
2933 /* If logind is not around, then there are no inhibitors... */
2936 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssuu)");
2938 return bus_log_parse_error(r
);
2940 while ((r
= sd_bus_message_read(reply
, "(ssssuu)", &what
, &who
, &why
, &mode
, &uid
, &pid
)) > 0) {
2941 _cleanup_free_
char *comm
= NULL
, *user
= NULL
;
2942 _cleanup_strv_free_
char **sv
= NULL
;
2944 if (!streq(mode
, "block"))
2947 sv
= strv_split(what
, ":");
2951 if ((pid_t
) pid
< 0)
2952 return log_error_errno(ERANGE
, "Bad PID %"PRIu32
": %m", pid
);
2954 if (!strv_contains(sv
,
2959 ACTION_KEXEC
) ? "shutdown" : "sleep"))
2962 get_process_comm(pid
, &comm
);
2963 user
= uid_to_name(uid
);
2965 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT
" \"%s\", user %s), reason is \"%s\".",
2966 who
, (pid_t
) pid
, strna(comm
), strna(user
), why
);
2971 return bus_log_parse_error(r
);
2973 r
= sd_bus_message_exit_container(reply
);
2975 return bus_log_parse_error(r
);
2977 /* Check for current sessions */
2978 sd_get_sessions(&sessions
);
2979 STRV_FOREACH(s
, sessions
) {
2980 _cleanup_free_
char *type
= NULL
, *tty
= NULL
, *seat
= NULL
, *user
= NULL
, *service
= NULL
, *class = NULL
;
2982 if (sd_session_get_uid(*s
, &uid
) < 0 || uid
== getuid())
2985 if (sd_session_get_class(*s
, &class) < 0 || !streq(class, "user"))
2988 if (sd_session_get_type(*s
, &type
) < 0 || (!streq(type
, "x11") && !streq(type
, "tty")))
2991 sd_session_get_tty(*s
, &tty
);
2992 sd_session_get_seat(*s
, &seat
);
2993 sd_session_get_service(*s
, &service
);
2994 user
= uid_to_name(uid
);
2996 log_warning("User %s is logged in on %s.", strna(user
), isempty(tty
) ? (isempty(seat
) ? strna(service
) : seat
) : tty
);
3003 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
3004 action_table
[a
].verb
);
3012 static int logind_prepare_firmware_setup(void) {
3014 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
3018 r
= acquire_bus(BUS_FULL
, &bus
);
3022 r
= sd_bus_call_method(
3024 "org.freedesktop.login1",
3025 "/org/freedesktop/login1",
3026 "org.freedesktop.login1.Manager",
3027 "SetRebootToFirmwareSetup",
3032 return log_error_errno(r
, "Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error
, r
));
3036 log_error("Cannot remotely indicate to EFI to boot into setup mode.");
3041 static int prepare_firmware_setup(void) {
3044 if (!arg_firmware_setup
)
3047 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
3049 r
= efi_set_reboot_to_firmware(true);
3051 log_debug_errno(r
, "Cannot indicate to EFI to boot into setup mode, will retry via logind: %m");
3056 return logind_prepare_firmware_setup();
3059 static int start_special(char **args
) {
3065 a
= verb_to_action(args
[0]);
3067 r
= logind_check_inhibitors(a
);
3071 if (arg_force
>= 2 && geteuid() != 0) {
3072 log_error("Must be root.");
3076 r
= prepare_firmware_setup();
3080 if (a
== ACTION_REBOOT
&& args
[1]) {
3081 r
= update_reboot_param_file(args
[1]);
3084 } else if (a
== ACTION_EXIT
&& strv_length(args
) > 1) {
3085 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
3086 /* If the exit code is not given on the command line, don't
3087 * reset it to zero: just keep it as it might have been set
3092 r
= safe_atou8(args
[1], &code
);
3094 log_error("Invalid exit code.");
3098 r
= acquire_bus(BUS_MANAGER
, &bus
);
3102 r
= sd_bus_call_method(
3104 "org.freedesktop.systemd1",
3105 "/org/freedesktop/systemd1",
3106 "org.freedesktop.systemd1.Manager",
3112 return log_error_errno(r
, "Failed to execute operation: %s", bus_error_message(&error
, r
));
3115 if (arg_force
>= 2 &&
3122 if (arg_force
>= 1 &&
3129 return daemon_reload(args
);
3131 /* first try logind, to allow authentication with polkit */
3132 if (geteuid() != 0 &&
3138 ACTION_HYBRID_SLEEP
)) {
3139 r
= logind_reboot(a
);
3142 if (IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
3143 /* requested operation is not supported or already in progress */
3145 /* on all other errors, try low-level operation */
3148 return start_unit(args
);
3151 static int check_unit_generic(int code
, const char *good_states
, char **args
) {
3152 _cleanup_strv_free_
char **names
= NULL
;
3159 r
= acquire_bus(BUS_MANAGER
, &bus
);
3163 r
= expand_names(bus
, args
, NULL
, &names
);
3165 return log_error_errno(r
, "Failed to expand names: %m");
3167 STRV_FOREACH(name
, names
) {
3170 state
= check_one_unit(bus
, *name
, good_states
, arg_quiet
);
3180 static int check_unit_active(char **args
) {
3181 /* According to LSB: 3, "program is not running" */
3182 return check_unit_generic(3, "active\0reloading\0", strv_skip(args
, 1));
3185 static int check_unit_failed(char **args
) {
3186 return check_unit_generic(1, "failed\0", strv_skip(args
, 1));
3189 static int kill_unit(char **args
) {
3190 _cleanup_strv_free_
char **names
= NULL
;
3191 char *kill_who
= NULL
, **name
;
3197 polkit_agent_open_if_enabled();
3199 r
= acquire_bus(BUS_MANAGER
, &bus
);
3204 arg_kill_who
= "all";
3206 /* --fail was specified */
3207 if (streq(arg_job_mode
, "fail"))
3208 kill_who
= strjoina(arg_kill_who
, "-fail", NULL
);
3210 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
3212 return log_error_errno(r
, "Failed to expand names: %m");
3214 STRV_FOREACH(name
, names
) {
3215 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
3217 q
= sd_bus_call_method(
3219 "org.freedesktop.systemd1",
3220 "/org/freedesktop/systemd1",
3221 "org.freedesktop.systemd1.Manager",
3225 "ssi", *names
, kill_who
? kill_who
: arg_kill_who
, arg_signal
);
3227 log_error_errno(q
, "Failed to kill unit %s: %s", *names
, bus_error_message(&error
, q
));
3236 typedef struct ExecStatusInfo
{
3244 usec_t start_timestamp
;
3245 usec_t exit_timestamp
;
3250 LIST_FIELDS(struct ExecStatusInfo
, exec
);
3253 static void exec_status_info_free(ExecStatusInfo
*i
) {
3262 static int exec_status_info_deserialize(sd_bus_message
*m
, ExecStatusInfo
*i
) {
3263 uint64_t start_timestamp
, exit_timestamp
, start_timestamp_monotonic
, exit_timestamp_monotonic
;
3266 int32_t code
, status
;
3272 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_STRUCT
, "sasbttttuii");
3274 return bus_log_parse_error(r
);
3278 r
= sd_bus_message_read(m
, "s", &path
);
3280 return bus_log_parse_error(r
);
3282 i
->path
= strdup(path
);
3286 r
= sd_bus_message_read_strv(m
, &i
->argv
);
3288 return bus_log_parse_error(r
);
3290 r
= sd_bus_message_read(m
,
3293 &start_timestamp
, &start_timestamp_monotonic
,
3294 &exit_timestamp
, &exit_timestamp_monotonic
,
3298 return bus_log_parse_error(r
);
3301 i
->start_timestamp
= (usec_t
) start_timestamp
;
3302 i
->exit_timestamp
= (usec_t
) exit_timestamp
;
3303 i
->pid
= (pid_t
) pid
;
3307 r
= sd_bus_message_exit_container(m
);
3309 return bus_log_parse_error(r
);
3314 typedef struct UnitStatusInfo
{
3316 const char *load_state
;
3317 const char *active_state
;
3318 const char *sub_state
;
3319 const char *unit_file_state
;
3320 const char *unit_file_preset
;
3322 const char *description
;
3323 const char *following
;
3325 char **documentation
;
3327 const char *fragment_path
;
3328 const char *source_path
;
3329 const char *control_group
;
3331 char **dropin_paths
;
3333 const char *load_error
;
3336 usec_t inactive_exit_timestamp
;
3337 usec_t inactive_exit_timestamp_monotonic
;
3338 usec_t active_enter_timestamp
;
3339 usec_t active_exit_timestamp
;
3340 usec_t inactive_enter_timestamp
;
3342 bool need_daemon_reload
;
3347 const char *status_text
;
3348 const char *pid_file
;
3352 usec_t start_timestamp
;
3353 usec_t exit_timestamp
;
3355 int exit_code
, exit_status
;
3357 usec_t condition_timestamp
;
3358 bool condition_result
;
3359 bool failed_condition_trigger
;
3360 bool failed_condition_negate
;
3361 const char *failed_condition
;
3362 const char *failed_condition_parameter
;
3364 usec_t assert_timestamp
;
3366 bool failed_assert_trigger
;
3367 bool failed_assert_negate
;
3368 const char *failed_assert
;
3369 const char *failed_assert_parameter
;
3372 unsigned n_accepted
;
3373 unsigned n_connections
;
3376 /* Pairs of type, path */
3380 const char *sysfs_path
;
3382 /* Mount, Automount */
3389 uint64_t memory_current
;
3390 uint64_t memory_limit
;
3391 uint64_t cpu_usage_nsec
;
3392 uint64_t tasks_current
;
3395 LIST_HEAD(ExecStatusInfo
, exec
);
3398 static void print_status_info(
3403 const char *active_on
, *active_off
, *on
, *off
, *ss
;
3405 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], *s1
;
3406 char since2
[FORMAT_TIMESTAMP_MAX
], *s2
;
3412 /* This shows pretty information about a unit. See
3413 * print_property() for a low-level property printer */
3415 if (streq_ptr(i
->active_state
, "failed")) {
3416 active_on
= ansi_highlight_red();
3417 active_off
= ansi_normal();
3418 } else if (streq_ptr(i
->active_state
, "active") || streq_ptr(i
->active_state
, "reloading")) {
3419 active_on
= ansi_highlight_green();
3420 active_off
= ansi_normal();
3422 active_on
= active_off
= "";
3424 printf("%s%s%s %s", active_on
, draw_special_char(DRAW_BLACK_CIRCLE
), active_off
, strna(i
->id
));
3426 if (i
->description
&& !streq_ptr(i
->id
, i
->description
))
3427 printf(" - %s", i
->description
);
3432 printf(" Follow: unit currently follows state of %s\n", i
->following
);
3434 if (streq_ptr(i
->load_state
, "error")) {
3435 on
= ansi_highlight_red();
3436 off
= ansi_normal();
3440 path
= i
->source_path
? i
->source_path
: i
->fragment_path
;
3443 printf(" Loaded: %s%s%s (Reason: %s)\n",
3444 on
, strna(i
->load_state
), off
, i
->load_error
);
3445 else if (path
&& !isempty(i
->unit_file_state
) && !isempty(i
->unit_file_preset
))
3446 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
3447 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
, i
->unit_file_preset
);
3448 else if (path
&& !isempty(i
->unit_file_state
))
3449 printf(" Loaded: %s%s%s (%s; %s)\n",
3450 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
);
3452 printf(" Loaded: %s%s%s (%s)\n",
3453 on
, strna(i
->load_state
), off
, path
);
3455 printf(" Loaded: %s%s%s\n",
3456 on
, strna(i
->load_state
), off
);
3458 if (!strv_isempty(i
->dropin_paths
)) {
3459 _cleanup_free_
char *dir
= NULL
;
3463 STRV_FOREACH(dropin
, i
->dropin_paths
) {
3464 if (! dir
|| last
) {
3465 printf(dir
? " " : " Drop-In: ");
3469 if (path_get_parent(*dropin
, &dir
) < 0) {
3474 printf("%s\n %s", dir
,
3475 draw_special_char(DRAW_TREE_RIGHT
));
3478 last
= ! (*(dropin
+ 1) && startswith(*(dropin
+ 1), dir
));
3480 printf("%s%s", basename(*dropin
), last
? "\n" : ", ");
3484 ss
= streq_ptr(i
->active_state
, i
->sub_state
) ? NULL
: i
->sub_state
;
3486 printf(" Active: %s%s (%s)%s",
3487 active_on
, strna(i
->active_state
), ss
, active_off
);
3489 printf(" Active: %s%s%s",
3490 active_on
, strna(i
->active_state
), active_off
);
3492 if (!isempty(i
->result
) && !streq(i
->result
, "success"))
3493 printf(" (Result: %s)", i
->result
);
3495 timestamp
= (streq_ptr(i
->active_state
, "active") ||
3496 streq_ptr(i
->active_state
, "reloading")) ? i
->active_enter_timestamp
:
3497 (streq_ptr(i
->active_state
, "inactive") ||
3498 streq_ptr(i
->active_state
, "failed")) ? i
->inactive_enter_timestamp
:
3499 streq_ptr(i
->active_state
, "activating") ? i
->inactive_exit_timestamp
:
3500 i
->active_exit_timestamp
;
3502 s1
= format_timestamp_relative(since1
, sizeof(since1
), timestamp
);
3503 s2
= format_timestamp(since2
, sizeof(since2
), timestamp
);
3506 printf(" since %s; %s\n", s2
, s1
);
3508 printf(" since %s\n", s2
);
3512 if (!i
->condition_result
&& i
->condition_timestamp
> 0) {
3513 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->condition_timestamp
);
3514 s2
= format_timestamp(since2
, sizeof(since2
), i
->condition_timestamp
);
3516 printf("Condition: start %scondition failed%s at %s%s%s\n",
3517 ansi_highlight_yellow(), ansi_normal(),
3518 s2
, s1
? "; " : "", s1
? s1
: "");
3519 if (i
->failed_condition_trigger
)
3520 printf(" none of the trigger conditions were met\n");
3521 else if (i
->failed_condition
)
3522 printf(" %s=%s%s was not met\n",
3523 i
->failed_condition
,
3524 i
->failed_condition_negate
? "!" : "",
3525 i
->failed_condition_parameter
);
3528 if (!i
->assert_result
&& i
->assert_timestamp
> 0) {
3529 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->assert_timestamp
);
3530 s2
= format_timestamp(since2
, sizeof(since2
), i
->assert_timestamp
);
3532 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
3533 ansi_highlight_red(), ansi_normal(),
3534 s2
, s1
? "; " : "", s1
? s1
: "");
3535 if (i
->failed_assert_trigger
)
3536 printf(" none of the trigger assertions were met\n");
3537 else if (i
->failed_assert
)
3538 printf(" %s=%s%s was not met\n",
3540 i
->failed_assert_negate
? "!" : "",
3541 i
->failed_assert_parameter
);
3545 printf(" Device: %s\n", i
->sysfs_path
);
3547 printf(" Where: %s\n", i
->where
);
3549 printf(" What: %s\n", i
->what
);
3551 STRV_FOREACH(t
, i
->documentation
)
3552 printf(" %*s %s\n", 9, t
== i
->documentation
? "Docs:" : "", *t
);
3554 STRV_FOREACH_PAIR(t
, t2
, i
->listen
)
3555 printf(" %*s %s (%s)\n", 9, t
== i
->listen
? "Listen:" : "", *t2
, *t
);
3558 printf(" Accepted: %u; Connected: %u\n", i
->n_accepted
, i
->n_connections
);
3560 LIST_FOREACH(exec
, p
, i
->exec
) {
3561 _cleanup_free_
char *argv
= NULL
;
3564 /* Only show exited processes here */
3568 argv
= strv_join(p
->argv
, " ");
3569 printf(" Process: "PID_FMT
" %s=%s ", p
->pid
, p
->name
, strna(argv
));
3571 good
= is_clean_exit_lsb(p
->code
, p
->status
, NULL
);
3573 on
= ansi_highlight_red();
3574 off
= ansi_normal();
3578 printf("%s(code=%s, ", on
, sigchld_code_to_string(p
->code
));
3580 if (p
->code
== CLD_EXITED
) {
3583 printf("status=%i", p
->status
);
3585 c
= exit_status_to_string(p
->status
, EXIT_STATUS_SYSTEMD
);
3590 printf("signal=%s", signal_to_string(p
->status
));
3592 printf(")%s\n", off
);
3594 if (i
->main_pid
== p
->pid
&&
3595 i
->start_timestamp
== p
->start_timestamp
&&
3596 i
->exit_timestamp
== p
->start_timestamp
)
3597 /* Let's not show this twice */
3600 if (p
->pid
== i
->control_pid
)
3604 if (i
->main_pid
> 0 || i
->control_pid
> 0) {
3605 if (i
->main_pid
> 0) {
3606 printf(" Main PID: "PID_FMT
, i
->main_pid
);
3609 _cleanup_free_
char *comm
= NULL
;
3610 get_process_comm(i
->main_pid
, &comm
);
3612 printf(" (%s)", comm
);
3613 } else if (i
->exit_code
> 0) {
3614 printf(" (code=%s, ", sigchld_code_to_string(i
->exit_code
));
3616 if (i
->exit_code
== CLD_EXITED
) {
3619 printf("status=%i", i
->exit_status
);
3621 c
= exit_status_to_string(i
->exit_status
, EXIT_STATUS_SYSTEMD
);
3626 printf("signal=%s", signal_to_string(i
->exit_status
));
3630 if (i
->control_pid
> 0)
3634 if (i
->control_pid
> 0) {
3635 _cleanup_free_
char *c
= NULL
;
3637 printf(" %8s: "PID_FMT
, i
->main_pid
? "" : " Control", i
->control_pid
);
3639 get_process_comm(i
->control_pid
, &c
);
3648 printf(" Status: \"%s\"\n", i
->status_text
);
3649 if (i
->status_errno
> 0)
3650 printf(" Error: %i (%s)\n", i
->status_errno
, strerror(i
->status_errno
));
3652 if (i
->tasks_current
!= (uint64_t) -1) {
3653 printf(" Tasks: %" PRIu64
, i
->tasks_current
);
3655 if (i
->tasks_max
!= (uint64_t) -1)
3656 printf(" (limit: %" PRIi64
")\n", i
->tasks_max
);
3661 if (i
->memory_current
!= (uint64_t) -1) {
3662 char buf
[FORMAT_BYTES_MAX
];
3664 printf(" Memory: %s", format_bytes(buf
, sizeof(buf
), i
->memory_current
));
3666 if (i
->memory_limit
!= (uint64_t) -1)
3667 printf(" (limit: %s)\n", format_bytes(buf
, sizeof(buf
), i
->memory_limit
));
3672 if (i
->cpu_usage_nsec
!= (uint64_t) -1) {
3673 char buf
[FORMAT_TIMESPAN_MAX
];
3674 printf(" CPU: %s\n", format_timespan(buf
, sizeof(buf
), i
->cpu_usage_nsec
/ NSEC_PER_USEC
, USEC_PER_MSEC
));
3677 if (i
->control_group
&&
3678 (i
->main_pid
> 0 || i
->control_pid
> 0 ||
3679 (!IN_SET(arg_transport
, BUS_TRANSPORT_LOCAL
, BUS_TRANSPORT_MACHINE
) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
) == 0))) {
3682 printf(" CGroup: %s\n", i
->control_group
);
3684 if (IN_SET(arg_transport
,
3685 BUS_TRANSPORT_LOCAL
,
3686 BUS_TRANSPORT_MACHINE
)) {
3689 static const char prefix
[] = " ";
3692 if (c
> sizeof(prefix
) - 1)
3693 c
-= sizeof(prefix
) - 1;
3697 if (i
->main_pid
> 0)
3698 extra
[k
++] = i
->main_pid
;
3700 if (i
->control_pid
> 0)
3701 extra
[k
++] = i
->control_pid
;
3703 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, prefix
, c
, false, extra
, k
, get_output_flags());
3707 if (i
->id
&& arg_transport
== BUS_TRANSPORT_LOCAL
)
3708 show_journal_by_unit(
3713 i
->inactive_exit_timestamp_monotonic
,
3716 get_output_flags() | OUTPUT_BEGIN_NEWLINE
,
3717 SD_JOURNAL_LOCAL_ONLY
,
3718 arg_scope
== UNIT_FILE_SYSTEM
,
3721 if (i
->need_daemon_reload
)
3722 warn_unit_file_changed(i
->id
);
3725 static void show_unit_help(UnitStatusInfo
*i
) {
3730 if (!i
->documentation
) {
3731 log_info("Documentation for %s not known.", i
->id
);
3735 STRV_FOREACH(p
, i
->documentation
)
3736 if (startswith(*p
, "man:"))
3737 show_man_page(*p
+ 4, false);
3739 log_info("Can't show: %s", *p
);
3742 static int status_property(const char *name
, sd_bus_message
*m
, UnitStatusInfo
*i
, const char *contents
) {
3749 switch (contents
[0]) {
3751 case SD_BUS_TYPE_STRING
: {
3754 r
= sd_bus_message_read(m
, "s", &s
);
3756 return bus_log_parse_error(r
);
3759 if (streq(name
, "Id"))
3761 else if (streq(name
, "LoadState"))
3763 else if (streq(name
, "ActiveState"))
3764 i
->active_state
= s
;
3765 else if (streq(name
, "SubState"))
3767 else if (streq(name
, "Description"))
3769 else if (streq(name
, "FragmentPath"))
3770 i
->fragment_path
= s
;
3771 else if (streq(name
, "SourcePath"))
3774 else if (streq(name
, "DefaultControlGroup")) {
3776 e
= startswith(s
, SYSTEMD_CGROUP_CONTROLLER
":");
3778 i
->control_group
= e
;
3781 else if (streq(name
, "ControlGroup"))
3782 i
->control_group
= s
;
3783 else if (streq(name
, "StatusText"))
3785 else if (streq(name
, "PIDFile"))
3787 else if (streq(name
, "SysFSPath"))
3789 else if (streq(name
, "Where"))
3791 else if (streq(name
, "What"))
3793 else if (streq(name
, "Following"))
3795 else if (streq(name
, "UnitFileState"))
3796 i
->unit_file_state
= s
;
3797 else if (streq(name
, "UnitFilePreset"))
3798 i
->unit_file_preset
= s
;
3799 else if (streq(name
, "Result"))
3806 case SD_BUS_TYPE_BOOLEAN
: {
3809 r
= sd_bus_message_read(m
, "b", &b
);
3811 return bus_log_parse_error(r
);
3813 if (streq(name
, "Accept"))
3815 else if (streq(name
, "NeedDaemonReload"))
3816 i
->need_daemon_reload
= b
;
3817 else if (streq(name
, "ConditionResult"))
3818 i
->condition_result
= b
;
3819 else if (streq(name
, "AssertResult"))
3820 i
->assert_result
= b
;
3825 case SD_BUS_TYPE_UINT32
: {
3828 r
= sd_bus_message_read(m
, "u", &u
);
3830 return bus_log_parse_error(r
);
3832 if (streq(name
, "MainPID")) {
3834 i
->main_pid
= (pid_t
) u
;
3837 } else if (streq(name
, "ControlPID"))
3838 i
->control_pid
= (pid_t
) u
;
3839 else if (streq(name
, "ExecMainPID")) {
3841 i
->main_pid
= (pid_t
) u
;
3842 } else if (streq(name
, "NAccepted"))
3844 else if (streq(name
, "NConnections"))
3845 i
->n_connections
= u
;
3850 case SD_BUS_TYPE_INT32
: {
3853 r
= sd_bus_message_read(m
, "i", &j
);
3855 return bus_log_parse_error(r
);
3857 if (streq(name
, "ExecMainCode"))
3858 i
->exit_code
= (int) j
;
3859 else if (streq(name
, "ExecMainStatus"))
3860 i
->exit_status
= (int) j
;
3861 else if (streq(name
, "StatusErrno"))
3862 i
->status_errno
= (int) j
;
3867 case SD_BUS_TYPE_UINT64
: {
3870 r
= sd_bus_message_read(m
, "t", &u
);
3872 return bus_log_parse_error(r
);
3874 if (streq(name
, "ExecMainStartTimestamp"))
3875 i
->start_timestamp
= (usec_t
) u
;
3876 else if (streq(name
, "ExecMainExitTimestamp"))
3877 i
->exit_timestamp
= (usec_t
) u
;
3878 else if (streq(name
, "ActiveEnterTimestamp"))
3879 i
->active_enter_timestamp
= (usec_t
) u
;
3880 else if (streq(name
, "InactiveEnterTimestamp"))
3881 i
->inactive_enter_timestamp
= (usec_t
) u
;
3882 else if (streq(name
, "InactiveExitTimestamp"))
3883 i
->inactive_exit_timestamp
= (usec_t
) u
;
3884 else if (streq(name
, "InactiveExitTimestampMonotonic"))
3885 i
->inactive_exit_timestamp_monotonic
= (usec_t
) u
;
3886 else if (streq(name
, "ActiveExitTimestamp"))
3887 i
->active_exit_timestamp
= (usec_t
) u
;
3888 else if (streq(name
, "ConditionTimestamp"))
3889 i
->condition_timestamp
= (usec_t
) u
;
3890 else if (streq(name
, "AssertTimestamp"))
3891 i
->assert_timestamp
= (usec_t
) u
;
3892 else if (streq(name
, "MemoryCurrent"))
3893 i
->memory_current
= u
;
3894 else if (streq(name
, "MemoryLimit"))
3895 i
->memory_limit
= u
;
3896 else if (streq(name
, "TasksCurrent"))
3897 i
->tasks_current
= u
;
3898 else if (streq(name
, "TasksMax"))
3900 else if (streq(name
, "CPUUsageNSec"))
3901 i
->cpu_usage_nsec
= u
;
3906 case SD_BUS_TYPE_ARRAY
:
3908 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
3909 _cleanup_free_ ExecStatusInfo
*info
= NULL
;
3911 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
3913 return bus_log_parse_error(r
);
3915 info
= new0(ExecStatusInfo
, 1);
3919 while ((r
= exec_status_info_deserialize(m
, info
)) > 0) {
3921 info
->name
= strdup(name
);
3925 LIST_PREPEND(exec
, i
->exec
, info
);
3927 info
= new0(ExecStatusInfo
, 1);
3933 return bus_log_parse_error(r
);
3935 r
= sd_bus_message_exit_container(m
);
3937 return bus_log_parse_error(r
);
3941 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
3942 const char *type
, *path
;
3944 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
3946 return bus_log_parse_error(r
);
3948 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0) {
3950 r
= strv_extend(&i
->listen
, type
);
3954 r
= strv_extend(&i
->listen
, path
);
3959 return bus_log_parse_error(r
);
3961 r
= sd_bus_message_exit_container(m
);
3963 return bus_log_parse_error(r
);
3967 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "DropInPaths")) {
3969 r
= sd_bus_message_read_strv(m
, &i
->dropin_paths
);
3971 return bus_log_parse_error(r
);
3973 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Documentation")) {
3975 r
= sd_bus_message_read_strv(m
, &i
->documentation
);
3977 return bus_log_parse_error(r
);
3979 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Conditions")) {
3980 const char *cond
, *param
;
3981 int trigger
, negate
;
3984 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
3986 return bus_log_parse_error(r
);
3988 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
3989 log_debug("%s %d %d %s %d", cond
, trigger
, negate
, param
, state
);
3990 if (state
< 0 && (!trigger
|| !i
->failed_condition
)) {
3991 i
->failed_condition
= cond
;
3992 i
->failed_condition_trigger
= trigger
;
3993 i
->failed_condition_negate
= negate
;
3994 i
->failed_condition_parameter
= param
;
3998 return bus_log_parse_error(r
);
4000 r
= sd_bus_message_exit_container(m
);
4002 return bus_log_parse_error(r
);
4004 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Asserts")) {
4005 const char *cond
, *param
;
4006 int trigger
, negate
;
4009 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
4011 return bus_log_parse_error(r
);
4013 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
4014 log_debug("%s %d %d %s %d", cond
, trigger
, negate
, param
, state
);
4015 if (state
< 0 && (!trigger
|| !i
->failed_assert
)) {
4016 i
->failed_assert
= cond
;
4017 i
->failed_assert_trigger
= trigger
;
4018 i
->failed_assert_negate
= negate
;
4019 i
->failed_assert_parameter
= param
;
4023 return bus_log_parse_error(r
);
4025 r
= sd_bus_message_exit_container(m
);
4027 return bus_log_parse_error(r
);
4034 case SD_BUS_TYPE_STRUCT_BEGIN
:
4036 if (streq(name
, "LoadError")) {
4037 const char *n
, *message
;
4039 r
= sd_bus_message_read(m
, "(ss)", &n
, &message
);
4041 return bus_log_parse_error(r
);
4043 if (!isempty(message
))
4044 i
->load_error
= message
;
4057 r
= sd_bus_message_skip(m
, contents
);
4059 return bus_log_parse_error(r
);
4064 static int print_property(const char *name
, sd_bus_message
*m
, const char *contents
) {
4070 /* This is a low-level property printer, see
4071 * print_status_info() for the nicer output */
4073 if (arg_properties
&& !strv_find(arg_properties
, name
)) {
4074 /* skip what we didn't read */
4075 r
= sd_bus_message_skip(m
, contents
);
4079 switch (contents
[0]) {
4081 case SD_BUS_TYPE_STRUCT_BEGIN
:
4083 if (contents
[1] == SD_BUS_TYPE_UINT32
&& streq(name
, "Job")) {
4086 r
= sd_bus_message_read(m
, "(uo)", &u
, NULL
);
4088 return bus_log_parse_error(r
);
4091 printf("%s=%"PRIu32
"\n", name
, u
);
4093 printf("%s=\n", name
);
4097 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Unit")) {
4100 r
= sd_bus_message_read(m
, "(so)", &s
, NULL
);
4102 return bus_log_parse_error(r
);
4104 if (arg_all
|| !isempty(s
))
4105 printf("%s=%s\n", name
, s
);
4109 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "LoadError")) {
4110 const char *a
= NULL
, *b
= NULL
;
4112 r
= sd_bus_message_read(m
, "(ss)", &a
, &b
);
4114 return bus_log_parse_error(r
);
4116 if (arg_all
|| !isempty(a
) || !isempty(b
))
4117 printf("%s=%s \"%s\"\n", name
, strempty(a
), strempty(b
));
4120 } else if (streq_ptr(name
, "SystemCallFilter")) {
4121 _cleanup_strv_free_
char **l
= NULL
;
4124 r
= sd_bus_message_enter_container(m
, 'r', "bas");
4126 return bus_log_parse_error(r
);
4128 r
= sd_bus_message_read(m
, "b", &whitelist
);
4130 return bus_log_parse_error(r
);
4132 r
= sd_bus_message_read_strv(m
, &l
);
4134 return bus_log_parse_error(r
);
4136 r
= sd_bus_message_exit_container(m
);
4138 return bus_log_parse_error(r
);
4140 if (arg_all
|| whitelist
|| !strv_isempty(l
)) {
4144 fputs(name
, stdout
);
4150 STRV_FOREACH(i
, l
) {
4158 fputc('\n', stdout
);
4166 case SD_BUS_TYPE_ARRAY
:
4168 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "EnvironmentFiles")) {
4172 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sb)");
4174 return bus_log_parse_error(r
);
4176 while ((r
= sd_bus_message_read(m
, "(sb)", &path
, &ignore
)) > 0)
4177 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path
, yes_no(ignore
));
4180 return bus_log_parse_error(r
);
4182 r
= sd_bus_message_exit_container(m
);
4184 return bus_log_parse_error(r
);
4188 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Paths")) {
4189 const char *type
, *path
;
4191 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4193 return bus_log_parse_error(r
);
4195 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4196 printf("%s=%s\n", type
, path
);
4198 return bus_log_parse_error(r
);
4200 r
= sd_bus_message_exit_container(m
);
4202 return bus_log_parse_error(r
);
4206 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
4207 const char *type
, *path
;
4209 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4211 return bus_log_parse_error(r
);
4213 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4214 printf("Listen%s=%s\n", type
, path
);
4216 return bus_log_parse_error(r
);
4218 r
= sd_bus_message_exit_container(m
);
4220 return bus_log_parse_error(r
);
4224 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Timers")) {
4226 uint64_t value
, next_elapse
;
4228 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(stt)");
4230 return bus_log_parse_error(r
);
4232 while ((r
= sd_bus_message_read(m
, "(stt)", &base
, &value
, &next_elapse
)) > 0) {
4233 char timespan1
[FORMAT_TIMESPAN_MAX
], timespan2
[FORMAT_TIMESPAN_MAX
];
4235 printf("%s={ value=%s ; next_elapse=%s }\n",
4237 format_timespan(timespan1
, sizeof(timespan1
), value
, 0),
4238 format_timespan(timespan2
, sizeof(timespan2
), next_elapse
, 0));
4241 return bus_log_parse_error(r
);
4243 r
= sd_bus_message_exit_container(m
);
4245 return bus_log_parse_error(r
);
4249 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
4250 ExecStatusInfo info
= {};
4252 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4254 return bus_log_parse_error(r
);
4256 while ((r
= exec_status_info_deserialize(m
, &info
)) > 0) {
4257 char timestamp1
[FORMAT_TIMESTAMP_MAX
], timestamp2
[FORMAT_TIMESTAMP_MAX
];
4258 _cleanup_free_
char *tt
;
4260 tt
= strv_join(info
.argv
, " ");
4262 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",
4266 yes_no(info
.ignore
),
4267 strna(format_timestamp(timestamp1
, sizeof(timestamp1
), info
.start_timestamp
)),
4268 strna(format_timestamp(timestamp2
, sizeof(timestamp2
), info
.exit_timestamp
)),
4270 sigchld_code_to_string(info
.code
),
4272 info
.code
== CLD_EXITED
? "" : "/",
4273 strempty(info
.code
== CLD_EXITED
? NULL
: signal_to_string(info
.status
)));
4276 strv_free(info
.argv
);
4280 r
= sd_bus_message_exit_container(m
);
4282 return bus_log_parse_error(r
);
4286 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "DeviceAllow")) {
4287 const char *path
, *rwm
;
4289 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4291 return bus_log_parse_error(r
);
4293 while ((r
= sd_bus_message_read(m
, "(ss)", &path
, &rwm
)) > 0)
4294 printf("%s=%s %s\n", name
, strna(path
), strna(rwm
));
4296 return bus_log_parse_error(r
);
4298 r
= sd_bus_message_exit_container(m
);
4300 return bus_log_parse_error(r
);
4304 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "BlockIODeviceWeight")) {
4308 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4310 return bus_log_parse_error(r
);
4312 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &weight
)) > 0)
4313 printf("%s=%s %" PRIu64
"\n", name
, strna(path
), weight
);
4315 return bus_log_parse_error(r
);
4317 r
= sd_bus_message_exit_container(m
);
4319 return bus_log_parse_error(r
);
4323 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& (streq(name
, "BlockIOReadBandwidth") || streq(name
, "BlockIOWriteBandwidth"))) {
4327 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4329 return bus_log_parse_error(r
);
4331 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &bandwidth
)) > 0)
4332 printf("%s=%s %" PRIu64
"\n", name
, strna(path
), bandwidth
);
4334 return bus_log_parse_error(r
);
4336 r
= sd_bus_message_exit_container(m
);
4338 return bus_log_parse_error(r
);
4346 r
= bus_print_property(name
, m
, arg_all
);
4348 return bus_log_parse_error(r
);
4351 r
= sd_bus_message_skip(m
, contents
);
4353 return bus_log_parse_error(r
);
4356 printf("%s=[unprintable]\n", name
);
4362 static int show_one(
4366 bool show_properties
,
4370 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4371 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4372 UnitStatusInfo info
= {
4373 .memory_current
= (uint64_t) -1,
4374 .memory_limit
= (uint64_t) -1,
4375 .cpu_usage_nsec
= (uint64_t) -1,
4376 .tasks_current
= (uint64_t) -1,
4377 .tasks_max
= (uint64_t) -1,
4385 log_debug("Showing one %s", path
);
4387 r
= sd_bus_call_method(
4389 "org.freedesktop.systemd1",
4391 "org.freedesktop.DBus.Properties",
4397 return log_error_errno(r
, "Failed to get properties: %s", bus_error_message(&error
, r
));
4399 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
4401 return bus_log_parse_error(r
);
4408 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
4409 const char *name
, *contents
;
4411 r
= sd_bus_message_read(reply
, "s", &name
);
4413 return bus_log_parse_error(r
);
4415 r
= sd_bus_message_peek_type(reply
, NULL
, &contents
);
4417 return bus_log_parse_error(r
);
4419 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, contents
);
4421 return bus_log_parse_error(r
);
4423 if (show_properties
)
4424 r
= print_property(name
, reply
, contents
);
4426 r
= status_property(name
, reply
, &info
, contents
);
4430 r
= sd_bus_message_exit_container(reply
);
4432 return bus_log_parse_error(r
);
4434 r
= sd_bus_message_exit_container(reply
);
4436 return bus_log_parse_error(r
);
4439 return bus_log_parse_error(r
);
4441 r
= sd_bus_message_exit_container(reply
);
4443 return bus_log_parse_error(r
);
4447 if (!show_properties
) {
4448 if (streq(verb
, "help"))
4449 show_unit_help(&info
);
4451 print_status_info(&info
, ellipsized
);
4454 strv_free(info
.documentation
);
4455 strv_free(info
.dropin_paths
);
4456 strv_free(info
.listen
);
4458 if (!streq_ptr(info
.active_state
, "active") &&
4459 !streq_ptr(info
.active_state
, "reloading") &&
4460 streq(verb
, "status")) {
4461 /* According to LSB: "program not running" */
4462 /* 0: program is running or service is OK
4463 * 1: program is dead and /run PID file exists
4464 * 2: program is dead and /run/lock lock file exists
4465 * 3: program is not running
4466 * 4: program or service status is unknown
4468 if (info
.pid_file
&& access(info
.pid_file
, F_OK
) == 0)
4474 while ((p
= info
.exec
)) {
4475 LIST_REMOVE(exec
, info
.exec
, p
);
4476 exec_status_info_free(p
);
4482 static int get_unit_dbus_path_by_pid(
4487 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4488 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4492 r
= sd_bus_call_method(
4494 "org.freedesktop.systemd1",
4495 "/org/freedesktop/systemd1",
4496 "org.freedesktop.systemd1.Manager",
4502 return log_error_errno(r
, "Failed to get unit for PID %"PRIu32
": %s", pid
, bus_error_message(&error
, r
));
4504 r
= sd_bus_message_read(reply
, "o", &u
);
4506 return bus_log_parse_error(r
);
4516 static int show_all(
4519 bool show_properties
,
4523 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4524 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
4529 r
= get_unit_list(bus
, NULL
, NULL
, &unit_infos
, 0, &reply
);
4533 pager_open_if_enabled();
4537 qsort_safe(unit_infos
, c
, sizeof(UnitInfo
), compare_unit_info
);
4539 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
4540 _cleanup_free_
char *p
= NULL
;
4542 p
= unit_dbus_path_from_name(u
->id
);
4546 r
= show_one(verb
, bus
, p
, show_properties
, new_line
, ellipsized
);
4549 else if (r
> 0 && ret
== 0)
4556 static int show_system_status(sd_bus
*bus
) {
4557 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], since2
[FORMAT_TIMESTAMP_MAX
];
4558 _cleanup_free_
char *hn
= NULL
;
4559 _cleanup_(machine_info_clear
) struct machine_info mi
= {};
4560 const char *on
, *off
;
4563 hn
= gethostname_malloc();
4567 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, &mi
);
4569 return log_error_errno(r
, "Failed to read server status: %m");
4571 if (streq_ptr(mi
.state
, "degraded")) {
4572 on
= ansi_highlight_red();
4573 off
= ansi_normal();
4574 } else if (!streq_ptr(mi
.state
, "running")) {
4575 on
= ansi_highlight_yellow();
4576 off
= ansi_normal();
4580 printf("%s%s%s %s\n", on
, draw_special_char(DRAW_BLACK_CIRCLE
), off
, arg_host
? arg_host
: hn
);
4582 printf(" State: %s%s%s\n",
4583 on
, strna(mi
.state
), off
);
4585 printf(" Jobs: %u queued\n", mi
.n_jobs
);
4586 printf(" Failed: %u units\n", mi
.n_failed_units
);
4588 printf(" Since: %s; %s\n",
4589 format_timestamp(since2
, sizeof(since2
), mi
.timestamp
),
4590 format_timestamp_relative(since1
, sizeof(since1
), mi
.timestamp
));
4592 printf(" CGroup: %s\n", mi
.control_group
?: "/");
4593 if (IN_SET(arg_transport
,
4594 BUS_TRANSPORT_LOCAL
,
4595 BUS_TRANSPORT_MACHINE
)) {
4596 static const char prefix
[] = " ";
4600 if (c
> sizeof(prefix
) - 1)
4601 c
-= sizeof(prefix
) - 1;
4605 show_cgroup(SYSTEMD_CGROUP_CONTROLLER
, strempty(mi
.control_group
), prefix
, c
, false, get_output_flags());
4611 static int show(char **args
) {
4612 bool show_properties
, show_status
, new_line
= false;
4613 bool ellipsized
= false;
4619 show_properties
= streq(args
[0], "show");
4620 show_status
= streq(args
[0], "status");
4622 if (show_properties
)
4623 pager_open_if_enabled();
4626 /* Increase max number of open files to 16K if we can, we
4627 * might needs this when browsing journal files, which might
4628 * be split up into many files. */
4629 setrlimit_closest(RLIMIT_NOFILE
, &RLIMIT_MAKE_CONST(16384));
4631 r
= acquire_bus(BUS_MANAGER
, &bus
);
4635 /* If no argument is specified inspect the manager itself */
4636 if (show_properties
&& strv_length(args
) <= 1)
4637 return show_one(args
[0], bus
, "/org/freedesktop/systemd1", show_properties
, &new_line
, &ellipsized
);
4639 if (show_status
&& strv_length(args
) <= 1) {
4641 pager_open_if_enabled();
4642 show_system_status(bus
);
4646 ret
= show_all(args
[0], bus
, false, &new_line
, &ellipsized
);
4648 _cleanup_free_
char **patterns
= NULL
;
4651 STRV_FOREACH(name
, args
+ 1) {
4652 _cleanup_free_
char *unit
= NULL
;
4655 if (safe_atou32(*name
, &id
) < 0) {
4656 if (strv_push(&patterns
, *name
) < 0)
4660 } else if (show_properties
) {
4661 /* Interpret as job id */
4662 if (asprintf(&unit
, "/org/freedesktop/systemd1/job/%u", id
) < 0)
4666 /* Interpret as PID */
4667 r
= get_unit_dbus_path_by_pid(bus
, id
, &unit
);
4674 r
= show_one(args
[0], bus
, unit
, show_properties
,
4675 &new_line
, &ellipsized
);
4678 else if (r
> 0 && ret
== 0)
4682 if (!strv_isempty(patterns
)) {
4683 _cleanup_strv_free_
char **names
= NULL
;
4685 r
= expand_names(bus
, patterns
, NULL
, &names
);
4687 return log_error_errno(r
, "Failed to expand names: %m");
4689 STRV_FOREACH(name
, names
) {
4690 _cleanup_free_
char *unit
;
4692 unit
= unit_dbus_path_from_name(*name
);
4696 r
= show_one(args
[0], bus
, unit
, show_properties
,
4697 &new_line
, &ellipsized
);
4700 else if (r
> 0 && ret
== 0)
4706 if (ellipsized
&& !arg_quiet
)
4707 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4712 static int init_home_and_lookup_paths(char **user_home
, char **user_runtime
, LookupPaths
*lp
) {
4716 assert(user_runtime
);
4719 if (arg_scope
== UNIT_FILE_USER
) {
4720 r
= user_config_home(user_home
);
4722 return log_error_errno(r
, "Failed to query XDG_CONFIG_HOME: %m");
4724 return log_error_errno(ENOTDIR
, "Cannot find units: $XDG_CONFIG_HOME and $HOME are not set.");
4726 r
= user_runtime_dir(user_runtime
);
4728 return log_error_errno(r
, "Failed to query XDG_CONFIG_HOME: %m");
4730 return log_error_errno(ENOTDIR
, "Cannot find units: $XDG_RUNTIME_DIR is not set.");
4733 r
= lookup_paths_init_from_scope(lp
, arg_scope
, arg_root
);
4735 return log_error_errno(r
, "Failed to query unit lookup paths: %m");
4740 static int cat_file(const char *filename
, bool newline
) {
4741 _cleanup_close_
int fd
;
4743 fd
= open(filename
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
4747 printf("%s%s# %s%s\n",
4748 newline
? "\n" : "",
4749 ansi_highlight_blue(),
4754 return copy_bytes(fd
, STDOUT_FILENO
, (uint64_t) -1, false);
4757 static int cat(char **args
) {
4758 _cleanup_free_
char *user_home
= NULL
;
4759 _cleanup_free_
char *user_runtime
= NULL
;
4760 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
4761 _cleanup_strv_free_
char **names
= NULL
;
4769 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
4770 log_error("Cannot remotely cat units.");
4774 r
= init_home_and_lookup_paths(&user_home
, &user_runtime
, &lp
);
4778 r
= acquire_bus(BUS_MANAGER
, &bus
);
4782 r
= expand_names(bus
, strv_skip(args
, 1), NULL
, &names
);
4784 return log_error_errno(r
, "Failed to expand names: %m");
4786 pager_open_if_enabled();
4788 STRV_FOREACH(name
, names
) {
4789 _cleanup_free_
char *fragment_path
= NULL
;
4790 _cleanup_strv_free_
char **dropin_paths
= NULL
;
4793 r
= unit_find_paths(bus
, *name
, &lp
, &fragment_path
, &dropin_paths
);
4804 if (fragment_path
) {
4805 r
= cat_file(fragment_path
, false);
4807 return log_warning_errno(r
, "Failed to cat %s: %m", fragment_path
);
4810 STRV_FOREACH(path
, dropin_paths
) {
4811 r
= cat_file(*path
, path
== dropin_paths
);
4813 return log_warning_errno(r
, "Failed to cat %s: %m", *path
);
4820 static int set_property(char **args
) {
4821 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
4822 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4823 _cleanup_free_
char *n
= NULL
;
4828 polkit_agent_open_if_enabled();
4830 r
= acquire_bus(BUS_MANAGER
, &bus
);
4834 r
= sd_bus_message_new_method_call(
4837 "org.freedesktop.systemd1",
4838 "/org/freedesktop/systemd1",
4839 "org.freedesktop.systemd1.Manager",
4840 "SetUnitProperties");
4842 return bus_log_create_error(r
);
4844 r
= unit_name_mangle(args
[1], UNIT_NAME_NOGLOB
, &n
);
4846 return log_error_errno(r
, "Failed to mangle unit name: %m");
4848 r
= sd_bus_message_append(m
, "sb", n
, arg_runtime
);
4850 return bus_log_create_error(r
);
4852 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, "(sv)");
4854 return bus_log_create_error(r
);
4856 STRV_FOREACH(i
, args
+ 2) {
4857 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_STRUCT
, "sv");
4859 return bus_log_create_error(r
);
4861 r
= bus_append_unit_property_assignment(m
, *i
);
4865 r
= sd_bus_message_close_container(m
);
4867 return bus_log_create_error(r
);
4870 r
= sd_bus_message_close_container(m
);
4872 return bus_log_create_error(r
);
4874 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
4876 return log_error_errno(r
, "Failed to set unit properties on %s: %s", n
, bus_error_message(&error
, r
));
4881 static int snapshot(char **args
) {
4882 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4883 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4884 _cleanup_free_
char *n
= NULL
, *id
= NULL
;
4889 polkit_agent_open_if_enabled();
4891 if (strv_length(args
) > 1) {
4892 r
= unit_name_mangle_with_suffix(args
[1], UNIT_NAME_NOGLOB
, ".snapshot", &n
);
4894 return log_error_errno(r
, "Failed to generate unit name: %m");
4901 r
= acquire_bus(BUS_MANAGER
, &bus
);
4905 r
= sd_bus_call_method(
4907 "org.freedesktop.systemd1",
4908 "/org/freedesktop/systemd1",
4909 "org.freedesktop.systemd1.Manager",
4915 return log_error_errno(r
, "Failed to create snapshot: %s", bus_error_message(&error
, r
));
4917 r
= sd_bus_message_read(reply
, "o", &path
);
4919 return bus_log_parse_error(r
);
4921 r
= sd_bus_get_property_string(
4923 "org.freedesktop.systemd1",
4925 "org.freedesktop.systemd1.Unit",
4930 return log_error_errno(r
, "Failed to get ID of snapshot: %s", bus_error_message(&error
, r
));
4938 static int delete_snapshot(char **args
) {
4939 _cleanup_strv_free_
char **names
= NULL
;
4946 polkit_agent_open_if_enabled();
4948 r
= acquire_bus(BUS_MANAGER
, &bus
);
4952 r
= expand_names(bus
, strv_skip(args
, 1), ".snapshot", &names
);
4954 return log_error_errno(r
, "Failed to expand names: %m");
4956 STRV_FOREACH(name
, names
) {
4957 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4960 q
= sd_bus_call_method(
4962 "org.freedesktop.systemd1",
4963 "/org/freedesktop/systemd1",
4964 "org.freedesktop.systemd1.Manager",
4970 log_error_errno(q
, "Failed to remove snapshot %s: %s", *name
, bus_error_message(&error
, q
));
4979 static int daemon_reload(char **args
) {
4980 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4985 polkit_agent_open_if_enabled();
4987 r
= acquire_bus(BUS_MANAGER
, &bus
);
4991 if (arg_action
== ACTION_RELOAD
)
4993 else if (arg_action
== ACTION_REEXEC
)
4994 method
= "Reexecute";
4996 assert(arg_action
== ACTION_SYSTEMCTL
);
4999 streq(args
[0], "clear-jobs") ||
5000 streq(args
[0], "cancel") ? "ClearJobs" :
5001 streq(args
[0], "daemon-reexec") ? "Reexecute" :
5002 streq(args
[0], "reset-failed") ? "ResetFailed" :
5003 streq(args
[0], "halt") ? "Halt" :
5004 streq(args
[0], "poweroff") ? "PowerOff" :
5005 streq(args
[0], "reboot") ? "Reboot" :
5006 streq(args
[0], "kexec") ? "KExec" :
5007 streq(args
[0], "exit") ? "Exit" :
5008 /* "daemon-reload" */ "Reload";
5011 r
= sd_bus_call_method(
5013 "org.freedesktop.systemd1",
5014 "/org/freedesktop/systemd1",
5015 "org.freedesktop.systemd1.Manager",
5020 if (r
== -ENOENT
&& arg_action
!= ACTION_SYSTEMCTL
)
5021 /* There's always a fallback possible for
5022 * legacy actions. */
5024 else if ((r
== -ETIMEDOUT
|| r
== -ECONNRESET
) && streq(method
, "Reexecute"))
5025 /* On reexecution, we expect a disconnect, not a
5029 return log_error_errno(r
, "Failed to execute operation: %s", bus_error_message(&error
, r
));
5031 return r
< 0 ? r
: 0;
5034 static int reset_failed(char **args
) {
5035 _cleanup_strv_free_
char **names
= NULL
;
5040 if (strv_length(args
) <= 1)
5041 return daemon_reload(args
);
5043 polkit_agent_open_if_enabled();
5045 r
= acquire_bus(BUS_MANAGER
, &bus
);
5049 r
= expand_names(bus
, strv_skip(args
, 1), NULL
, &names
);
5051 return log_error_errno(r
, "Failed to expand names: %m");
5053 STRV_FOREACH(name
, names
) {
5054 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5056 q
= sd_bus_call_method(
5058 "org.freedesktop.systemd1",
5059 "/org/freedesktop/systemd1",
5060 "org.freedesktop.systemd1.Manager",
5066 log_error_errno(q
, "Failed to reset failed state of unit %s: %s", *name
, bus_error_message(&error
, q
));
5075 static int show_environment(char **args
) {
5076 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5077 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
5082 pager_open_if_enabled();
5084 r
= acquire_bus(BUS_MANAGER
, &bus
);
5088 r
= sd_bus_get_property(
5090 "org.freedesktop.systemd1",
5091 "/org/freedesktop/systemd1",
5092 "org.freedesktop.systemd1.Manager",
5098 return log_error_errno(r
, "Failed to get environment: %s", bus_error_message(&error
, r
));
5100 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
5102 return bus_log_parse_error(r
);
5104 while ((r
= sd_bus_message_read_basic(reply
, SD_BUS_TYPE_STRING
, &text
)) > 0)
5107 return bus_log_parse_error(r
);
5109 r
= sd_bus_message_exit_container(reply
);
5111 return bus_log_parse_error(r
);
5116 static int switch_root(char **args
) {
5117 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5118 _cleanup_free_
char *cmdline_init
= NULL
;
5119 const char *root
, *init
;
5124 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
5125 log_error("Cannot switch root remotely.");
5129 l
= strv_length(args
);
5130 if (l
< 2 || l
> 3) {
5131 log_error("Wrong number of arguments.");
5140 r
= parse_env_file("/proc/cmdline", WHITESPACE
,
5141 "init", &cmdline_init
,
5144 log_debug_errno(r
, "Failed to parse /proc/cmdline: %m");
5146 init
= cmdline_init
;
5153 const char *root_systemd_path
= NULL
, *root_init_path
= NULL
;
5155 root_systemd_path
= strjoina(root
, "/" SYSTEMD_BINARY_PATH
);
5156 root_init_path
= strjoina(root
, "/", init
);
5158 /* If the passed init is actually the same as the
5159 * systemd binary, then let's suppress it. */
5160 if (files_same(root_init_path
, root_systemd_path
) > 0)
5164 r
= acquire_bus(BUS_MANAGER
, &bus
);
5168 log_debug("Switching root - root: %s; init: %s", root
, strna(init
));
5170 r
= sd_bus_call_method(
5172 "org.freedesktop.systemd1",
5173 "/org/freedesktop/systemd1",
5174 "org.freedesktop.systemd1.Manager",
5180 return log_error_errno(r
, "Failed to switch root: %s", bus_error_message(&error
, r
));
5185 static int set_environment(char **args
) {
5186 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5187 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
5194 polkit_agent_open_if_enabled();
5196 r
= acquire_bus(BUS_MANAGER
, &bus
);
5200 method
= streq(args
[0], "set-environment")
5202 : "UnsetEnvironment";
5204 r
= sd_bus_message_new_method_call(
5207 "org.freedesktop.systemd1",
5208 "/org/freedesktop/systemd1",
5209 "org.freedesktop.systemd1.Manager",
5212 return bus_log_create_error(r
);
5214 r
= sd_bus_message_append_strv(m
, args
+ 1);
5216 return bus_log_create_error(r
);
5218 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5220 return log_error_errno(r
, "Failed to set environment: %s", bus_error_message(&error
, r
));
5225 static int import_environment(char **args
) {
5226 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5227 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
5233 polkit_agent_open_if_enabled();
5235 r
= acquire_bus(BUS_MANAGER
, &bus
);
5239 r
= sd_bus_message_new_method_call(
5242 "org.freedesktop.systemd1",
5243 "/org/freedesktop/systemd1",
5244 "org.freedesktop.systemd1.Manager",
5247 return bus_log_create_error(r
);
5249 if (strv_isempty(args
+ 1))
5250 r
= sd_bus_message_append_strv(m
, environ
);
5254 r
= sd_bus_message_open_container(m
, 'a', "s");
5256 return bus_log_create_error(r
);
5258 STRV_FOREACH(a
, args
+ 1) {
5260 if (!env_name_is_valid(*a
)) {
5261 log_error("Not a valid environment variable name: %s", *a
);
5265 STRV_FOREACH(b
, environ
) {
5268 eq
= startswith(*b
, *a
);
5269 if (eq
&& *eq
== '=') {
5271 r
= sd_bus_message_append(m
, "s", *b
);
5273 return bus_log_create_error(r
);
5280 r
= sd_bus_message_close_container(m
);
5283 return bus_log_create_error(r
);
5285 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5287 return log_error_errno(r
, "Failed to import environment: %s", bus_error_message(&error
, r
));
5292 static int enable_sysv_units(const char *verb
, char **args
) {
5295 #if defined(HAVE_SYSV_COMPAT)
5297 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
5299 if (arg_scope
!= UNIT_FILE_SYSTEM
)
5302 if (!STR_IN_SET(verb
,
5308 /* Processes all SysV units, and reshuffles the array so that
5309 * afterwards only the native units remain */
5311 r
= lookup_paths_init(&paths
, MANAGER_SYSTEM
, false, arg_root
, NULL
, NULL
, NULL
);
5318 _cleanup_free_
char *p
= NULL
, *q
= NULL
, *l
= NULL
;
5319 bool found_native
= false, found_sysv
;
5321 const char *argv
[6] = { ROOTLIBEXECDIR
"/systemd-sysv-install", NULL
, NULL
, NULL
, NULL
};
5329 if (!endswith(name
, ".service"))
5332 if (path_is_absolute(name
))
5335 STRV_FOREACH(k
, paths
.unit_path
) {
5336 _cleanup_free_
char *path
= NULL
;
5338 path
= path_join(arg_root
, *k
, name
);
5342 found_native
= access(path
, F_OK
) >= 0;
5347 /* If we have both a native unit and a SysV script,
5348 * enable/disable them both (below); for is-enabled, prefer the
5350 if (found_native
&& streq(verb
, "is-enabled"))
5353 p
= path_join(arg_root
, SYSTEM_SYSVINIT_PATH
, name
);
5357 p
[strlen(p
) - strlen(".service")] = 0;
5358 found_sysv
= access(p
, F_OK
) >= 0;
5363 log_info("Synchronizing state of %s with SysV init with %s...", name
, argv
[0]);
5365 log_info("%s is not a native service, redirecting to systemd-sysv-install", name
);
5367 if (!isempty(arg_root
))
5368 argv
[c
++] = q
= strappend("--root=", arg_root
);
5371 argv
[c
++] = basename(p
);
5374 l
= strv_join((char**)argv
, " ");
5378 log_info("Executing %s", l
);
5382 return log_error_errno(errno
, "Failed to fork: %m");
5383 else if (pid
== 0) {
5386 (void) reset_all_signal_handlers();
5387 (void) reset_signal_mask();
5389 execv(argv
[0], (char**) argv
);
5390 log_error_errno(r
, "Failed to execute %s: %m", argv
[0]);
5391 _exit(EXIT_FAILURE
);
5394 j
= wait_for_terminate(pid
, &status
);
5396 log_error_errno(j
, "Failed to wait for child: %m");
5400 if (status
.si_code
== CLD_EXITED
) {
5401 if (streq(verb
, "is-enabled")) {
5402 if (status
.si_status
== 0) {
5411 } else if (status
.si_status
!= 0)
5419 /* Remove this entry, so that we don't try enabling it as native unit */
5422 assert(args
[f
] == name
);
5423 strv_remove(args
, name
);
5430 static int mangle_names(char **original_names
, char ***mangled_names
) {
5431 char **i
, **l
, **name
;
5434 l
= i
= new(char*, strv_length(original_names
) + 1);
5438 STRV_FOREACH(name
, original_names
) {
5440 /* When enabling units qualified path names are OK,
5441 * too, hence allow them explicitly. */
5443 if (is_path(*name
)) {
5450 r
= unit_name_mangle(*name
, UNIT_NAME_NOGLOB
, i
);
5453 return log_error_errno(r
, "Failed to mangle unit name: %m");
5466 static int enable_unit(char **args
) {
5467 _cleanup_strv_free_
char **names
= NULL
;
5468 const char *verb
= args
[0];
5469 UnitFileChange
*changes
= NULL
;
5470 unsigned n_changes
= 0;
5471 int carries_install_info
= -1;
5477 r
= mangle_names(args
+1, &names
);
5481 r
= enable_sysv_units(verb
, names
);
5485 /* If the operation was fully executed by the SysV compat,
5486 * let's finish early */
5487 if (strv_isempty(names
))
5490 if (install_client_side()) {
5491 if (streq(verb
, "enable")) {
5492 r
= unit_file_enable(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5493 carries_install_info
= r
;
5494 } else if (streq(verb
, "disable"))
5495 r
= unit_file_disable(arg_scope
, arg_runtime
, arg_root
, names
, &changes
, &n_changes
);
5496 else if (streq(verb
, "reenable")) {
5497 r
= unit_file_reenable(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5498 carries_install_info
= r
;
5499 } else if (streq(verb
, "link"))
5500 r
= unit_file_link(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5501 else if (streq(verb
, "preset")) {
5502 r
= unit_file_preset(arg_scope
, arg_runtime
, arg_root
, names
, arg_preset_mode
, arg_force
, &changes
, &n_changes
);
5503 carries_install_info
= r
;
5504 } else if (streq(verb
, "mask"))
5505 r
= unit_file_mask(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5506 else if (streq(verb
, "unmask"))
5507 r
= unit_file_unmask(arg_scope
, arg_runtime
, arg_root
, names
, &changes
, &n_changes
);
5509 assert_not_reached("Unknown verb");
5512 log_error_errno(r
, "Operation failed: %m");
5517 dump_unit_file_changes(changes
, n_changes
);
5521 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
, *m
= NULL
;
5522 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5523 int expect_carries_install_info
= false;
5524 bool send_force
= true, send_preset_mode
= false;
5528 polkit_agent_open_if_enabled();
5530 r
= acquire_bus(BUS_MANAGER
, &bus
);
5534 if (streq(verb
, "enable")) {
5535 method
= "EnableUnitFiles";
5536 expect_carries_install_info
= true;
5537 } else if (streq(verb
, "disable")) {
5538 method
= "DisableUnitFiles";
5540 } else if (streq(verb
, "reenable")) {
5541 method
= "ReenableUnitFiles";
5542 expect_carries_install_info
= true;
5543 } else if (streq(verb
, "link"))
5544 method
= "LinkUnitFiles";
5545 else if (streq(verb
, "preset")) {
5547 if (arg_preset_mode
!= UNIT_FILE_PRESET_FULL
) {
5548 method
= "PresetUnitFilesWithMode";
5549 send_preset_mode
= true;
5551 method
= "PresetUnitFiles";
5553 expect_carries_install_info
= true;
5554 } else if (streq(verb
, "mask"))
5555 method
= "MaskUnitFiles";
5556 else if (streq(verb
, "unmask")) {
5557 method
= "UnmaskUnitFiles";
5560 assert_not_reached("Unknown verb");
5562 r
= sd_bus_message_new_method_call(
5565 "org.freedesktop.systemd1",
5566 "/org/freedesktop/systemd1",
5567 "org.freedesktop.systemd1.Manager",
5570 return bus_log_create_error(r
);
5572 r
= sd_bus_message_append_strv(m
, names
);
5574 return bus_log_create_error(r
);
5576 if (send_preset_mode
) {
5577 r
= sd_bus_message_append(m
, "s", unit_file_preset_mode_to_string(arg_preset_mode
));
5579 return bus_log_create_error(r
);
5582 r
= sd_bus_message_append(m
, "b", arg_runtime
);
5584 return bus_log_create_error(r
);
5587 r
= sd_bus_message_append(m
, "b", arg_force
);
5589 return bus_log_create_error(r
);
5592 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
5594 return log_error_errno(r
, "Failed to execute operation: %s", bus_error_message(&error
, r
));
5596 if (expect_carries_install_info
) {
5597 r
= sd_bus_message_read(reply
, "b", &carries_install_info
);
5599 return bus_log_parse_error(r
);
5602 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
5606 /* Try to reload if enabled */
5608 r
= daemon_reload(args
);
5613 if (carries_install_info
== 0)
5614 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5615 "using systemctl.\n"
5616 "Possible reasons for having this kind of units are:\n"
5617 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5618 " .wants/ or .requires/ directory.\n"
5619 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5620 " a requirement dependency on it.\n"
5621 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5622 " D-Bus, udev, scripted systemctl call, ...).\n");
5624 if (arg_now
&& n_changes
> 0 && STR_IN_SET(args
[0], "enable", "disable", "mask")) {
5625 char *new_args
[n_changes
+ 2];
5629 r
= acquire_bus(BUS_MANAGER
, &bus
);
5633 new_args
[0] = (char*) (streq(args
[0], "enable") ? "start" : "stop");
5634 for (i
= 0; i
< n_changes
; i
++)
5635 new_args
[i
+ 1] = basename(changes
[i
].path
);
5636 new_args
[i
+ 1] = NULL
;
5638 r
= start_unit(new_args
);
5642 unit_file_changes_free(changes
, n_changes
);
5647 static int add_dependency(char **args
) {
5648 _cleanup_strv_free_
char **names
= NULL
;
5649 _cleanup_free_
char *target
= NULL
;
5650 const char *verb
= args
[0];
5657 r
= unit_name_mangle_with_suffix(args
[1], UNIT_NAME_NOGLOB
, ".target", &target
);
5659 return log_error_errno(r
, "Failed to mangle unit name: %m");
5661 r
= mangle_names(args
+2, &names
);
5665 if (streq(verb
, "add-wants"))
5667 else if (streq(verb
, "add-requires"))
5668 dep
= UNIT_REQUIRES
;
5670 assert_not_reached("Unknown verb");
5672 if (install_client_side()) {
5673 UnitFileChange
*changes
= NULL
;
5674 unsigned n_changes
= 0;
5676 r
= unit_file_add_dependency(arg_scope
, arg_runtime
, arg_root
, names
, target
, dep
, arg_force
, &changes
, &n_changes
);
5679 return log_error_errno(r
, "Can't add dependency: %m");
5682 dump_unit_file_changes(changes
, n_changes
);
5684 unit_file_changes_free(changes
, n_changes
);
5687 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
, *m
= NULL
;
5688 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5691 polkit_agent_open_if_enabled();
5693 r
= acquire_bus(BUS_MANAGER
, &bus
);
5697 r
= sd_bus_message_new_method_call(
5700 "org.freedesktop.systemd1",
5701 "/org/freedesktop/systemd1",
5702 "org.freedesktop.systemd1.Manager",
5703 "AddDependencyUnitFiles");
5705 return bus_log_create_error(r
);
5707 r
= sd_bus_message_append_strv(m
, names
);
5709 return bus_log_create_error(r
);
5711 r
= sd_bus_message_append(m
, "ssbb", target
, unit_dependency_to_string(dep
), arg_runtime
, arg_force
);
5713 return bus_log_create_error(r
);
5715 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
5717 return log_error_errno(r
, "Failed to execute operation: %s", bus_error_message(&error
, r
));
5719 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, NULL
, NULL
);
5724 r
= daemon_reload(args
);
5732 static int preset_all(char **args
) {
5733 UnitFileChange
*changes
= NULL
;
5734 unsigned n_changes
= 0;
5737 if (install_client_side()) {
5739 r
= unit_file_preset_all(arg_scope
, arg_runtime
, arg_root
, arg_preset_mode
, arg_force
, &changes
, &n_changes
);
5741 log_error_errno(r
, "Operation failed: %m");
5746 dump_unit_file_changes(changes
, n_changes
);
5751 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5752 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
5755 polkit_agent_open_if_enabled();
5757 r
= acquire_bus(BUS_MANAGER
, &bus
);
5761 r
= sd_bus_call_method(
5763 "org.freedesktop.systemd1",
5764 "/org/freedesktop/systemd1",
5765 "org.freedesktop.systemd1.Manager",
5766 "PresetAllUnitFiles",
5770 unit_file_preset_mode_to_string(arg_preset_mode
),
5774 return log_error_errno(r
, "Failed to execute operation: %s", bus_error_message(&error
, r
));
5776 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, NULL
, NULL
);
5781 r
= daemon_reload(args
);
5787 unit_file_changes_free(changes
, n_changes
);
5792 static int unit_is_enabled(char **args
) {
5794 _cleanup_strv_free_
char **names
= NULL
;
5799 r
= mangle_names(args
+1, &names
);
5803 r
= enable_sysv_units(args
[0], names
);
5809 if (install_client_side()) {
5811 STRV_FOREACH(name
, names
) {
5812 UnitFileState state
;
5814 state
= unit_file_get_state(arg_scope
, arg_root
, *name
);
5816 return log_error_errno(state
, "Failed to get unit file state for %s: %m", *name
);
5820 UNIT_FILE_ENABLED_RUNTIME
,
5822 UNIT_FILE_INDIRECT
))
5826 puts(unit_file_state_to_string(state
));
5830 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5833 r
= acquire_bus(BUS_MANAGER
, &bus
);
5837 STRV_FOREACH(name
, names
) {
5838 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
5841 r
= sd_bus_call_method(
5843 "org.freedesktop.systemd1",
5844 "/org/freedesktop/systemd1",
5845 "org.freedesktop.systemd1.Manager",
5851 return log_error_errno(r
, "Failed to get unit file state for %s: %s", *name
, bus_error_message(&error
, r
));
5853 r
= sd_bus_message_read(reply
, "s", &s
);
5855 return bus_log_parse_error(r
);
5857 if (STR_IN_SET(s
, "enabled", "enabled-runtime", "static", "indirect"))
5868 static int is_system_running(char **args
) {
5869 _cleanup_free_
char *state
= NULL
;
5873 if (arg_transport
== BUS_TRANSPORT_LOCAL
&& !sd_booted()) {
5876 return EXIT_FAILURE
;
5879 r
= acquire_bus(BUS_MANAGER
, &bus
);
5883 r
= sd_bus_get_property_string(
5885 "org.freedesktop.systemd1",
5886 "/org/freedesktop/systemd1",
5887 "org.freedesktop.systemd1.Manager",
5900 return streq(state
, "running") ? EXIT_SUCCESS
: EXIT_FAILURE
;
5903 static int create_edit_temp_file(const char *new_path
, const char *original_path
, char **ret_tmp_fn
) {
5908 assert(original_path
);
5911 r
= tempfn_random(new_path
, NULL
, &t
);
5913 return log_error_errno(r
, "Failed to determine temporary filename for \"%s\": %m", new_path
);
5915 r
= mkdir_parents(new_path
, 0755);
5918 return log_error_errno(r
, "Failed to create directories for \"%s\": %m", new_path
);
5921 r
= copy_file(original_path
, t
, 0, 0644, 0);
5925 log_error_errno(r
, "Failed to create temporary file \"%s\": %m", t
);
5930 log_error_errno(r
, "Failed to copy \"%s\" to \"%s\": %m", original_path
, t
);
5940 static int get_file_to_edit(const char *name
, const char *user_home
, const char *user_runtime
, char **ret_path
) {
5941 _cleanup_free_
char *path
= NULL
, *path2
= NULL
, *run
= NULL
;
5943 switch (arg_scope
) {
5944 case UNIT_FILE_SYSTEM
:
5945 path
= path_join(arg_root
, SYSTEM_CONFIG_UNIT_PATH
, name
);
5947 run
= path_join(arg_root
, "/run/systemd/system/", name
);
5949 case UNIT_FILE_GLOBAL
:
5950 path
= path_join(arg_root
, USER_CONFIG_UNIT_PATH
, name
);
5952 run
= path_join(arg_root
, "/run/systemd/user/", name
);
5954 case UNIT_FILE_USER
:
5956 assert(user_runtime
);
5958 path
= path_join(arg_root
, user_home
, name
);
5960 path2
= path_join(arg_root
, USER_CONFIG_UNIT_PATH
, name
);
5963 run
= path_join(arg_root
, user_runtime
, name
);
5967 assert_not_reached("Invalid scope");
5969 if (!path
|| (arg_runtime
&& !run
))
5973 if (access(path
, F_OK
) >= 0) {
5974 log_error("Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.", run
, path
);
5978 if (path2
&& access(path2
, F_OK
) >= 0) {
5979 log_error("Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.", run
, path2
);
5993 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
) {
5994 char *tmp_new_path
, *ending
;
5999 assert(ret_new_path
);
6000 assert(ret_tmp_path
);
6002 ending
= strjoina(unit_name
, ".d/override.conf");
6003 r
= get_file_to_edit(ending
, user_home
, user_runtime
, &tmp_new_path
);
6007 r
= create_edit_temp_file(tmp_new_path
, tmp_new_path
, &tmp_tmp_path
);
6013 *ret_new_path
= tmp_new_path
;
6014 *ret_tmp_path
= tmp_tmp_path
;
6019 static int unit_file_create_copy(
6020 const char *unit_name
,
6021 const char *fragment_path
,
6022 const char *user_home
,
6023 const char *user_runtime
,
6024 char **ret_new_path
,
6025 char **ret_tmp_path
) {
6031 assert(fragment_path
);
6033 assert(ret_new_path
);
6034 assert(ret_tmp_path
);
6036 r
= get_file_to_edit(unit_name
, user_home
, user_runtime
, &tmp_new_path
);
6040 if (!path_equal(fragment_path
, tmp_new_path
) && access(tmp_new_path
, F_OK
) == 0) {
6043 r
= ask_char(&response
, "yn", "\"%s\" already exists. Overwrite with \"%s\"? [(y)es, (n)o] ", tmp_new_path
, fragment_path
);
6048 if (response
!= 'y') {
6049 log_warning("%s ignored", unit_name
);
6055 r
= create_edit_temp_file(tmp_new_path
, fragment_path
, &tmp_tmp_path
);
6057 log_error_errno(r
, "Failed to create temporary file for \"%s\": %m", tmp_new_path
);
6062 *ret_new_path
= tmp_new_path
;
6063 *ret_tmp_path
= tmp_tmp_path
;
6068 static int run_editor(char **paths
) {
6076 return log_error_errno(errno
, "Failed to fork: %m");
6080 char *editor
, **editor_args
= NULL
;
6081 char **tmp_path
, **original_path
, *p
;
6082 unsigned n_editor_args
= 0, i
= 1;
6085 (void) reset_all_signal_handlers();
6086 (void) reset_signal_mask();
6088 argc
= strv_length(paths
)/2 + 1;
6090 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
6091 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
6092 * we try to execute well known editors
6094 editor
= getenv("SYSTEMD_EDITOR");
6096 editor
= getenv("EDITOR");
6098 editor
= getenv("VISUAL");
6100 if (!isempty(editor
)) {
6101 editor_args
= strv_split(editor
, WHITESPACE
);
6104 _exit(EXIT_FAILURE
);
6106 n_editor_args
= strv_length(editor_args
);
6107 argc
+= n_editor_args
- 1;
6109 args
= newa(const char*, argc
+ 1);
6111 if (n_editor_args
> 0) {
6112 args
[0] = editor_args
[0];
6113 for (; i
< n_editor_args
; i
++)
6114 args
[i
] = editor_args
[i
];
6117 STRV_FOREACH_PAIR(original_path
, tmp_path
, paths
) {
6118 args
[i
] = *tmp_path
;
6123 if (n_editor_args
> 0)
6124 execvp(args
[0], (char* const*) args
);
6126 FOREACH_STRING(p
, "editor", "nano", "vim", "vi") {
6128 execvp(p
, (char* const*) args
);
6129 /* We do not fail if the editor doesn't exist
6130 * because we want to try each one of them before
6133 if (errno
!= ENOENT
) {
6134 log_error_errno(errno
, "Failed to execute %s: %m", editor
);
6135 _exit(EXIT_FAILURE
);
6139 log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR, $EDITOR or $VISUAL.");
6140 _exit(EXIT_FAILURE
);
6143 r
= wait_for_terminate_and_warn("editor", pid
, true);
6145 return log_error_errno(r
, "Failed to wait for child: %m");
6150 static int find_paths_to_edit(sd_bus
*bus
, char **names
, char ***paths
) {
6151 _cleanup_free_
char *user_home
= NULL
;
6152 _cleanup_free_
char *user_runtime
= NULL
;
6153 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
6160 r
= init_home_and_lookup_paths(&user_home
, &user_runtime
, &lp
);
6164 STRV_FOREACH(name
, names
) {
6165 _cleanup_free_
char *path
= NULL
;
6166 char *new_path
, *tmp_path
;
6168 r
= unit_find_paths(bus
, *name
, &lp
, &path
, NULL
);
6174 // FIXME: support units with path==NULL (no FragmentPath)
6175 log_error("No fragment exists for %s.", *name
);
6180 r
= unit_file_create_copy(*name
, path
, user_home
, user_runtime
, &new_path
, &tmp_path
);
6182 r
= unit_file_create_dropin(*name
, user_home
, user_runtime
, &new_path
, &tmp_path
);
6186 r
= strv_push_pair(paths
, new_path
, tmp_path
);
6194 static int edit(char **args
) {
6195 _cleanup_strv_free_
char **names
= NULL
;
6196 _cleanup_strv_free_
char **paths
= NULL
;
6197 char **original
, **tmp
;
6204 log_error("Cannot edit units if not on a tty.");
6208 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
6209 log_error("Cannot edit units remotely.");
6213 r
= acquire_bus(BUS_MANAGER
, &bus
);
6217 r
= expand_names(bus
, strv_skip(args
, 1), NULL
, &names
);
6219 return log_error_errno(r
, "Failed to expand names: %m");
6221 r
= find_paths_to_edit(bus
, names
, &paths
);
6225 if (strv_isempty(paths
))
6228 r
= run_editor(paths
);
6232 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
6233 /* If the temporary file is empty we ignore it.
6234 * It's useful if the user wants to cancel its modification
6236 if (null_or_empty_path(*tmp
)) {
6237 log_warning("Editing \"%s\" canceled: temporary file is empty", *original
);
6240 r
= rename(*tmp
, *original
);
6242 r
= log_error_errno(errno
, "Failed to rename \"%s\" to \"%s\": %m", *tmp
, *original
);
6247 if (!arg_no_reload
&& bus
&& !install_client_side())
6248 r
= daemon_reload(args
);
6251 STRV_FOREACH_PAIR(original
, tmp
, paths
)
6252 unlink_noerrno(*tmp
);
6257 static void systemctl_help(void) {
6259 pager_open_if_enabled();
6261 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
6262 "Query or send control commands to the systemd manager.\n\n"
6263 " -h --help Show this help\n"
6264 " --version Show package version\n"
6265 " --system Connect to system manager\n"
6266 " --user Connect to user service manager\n"
6267 " -H --host=[USER@]HOST\n"
6268 " Operate on remote host\n"
6269 " -M --machine=CONTAINER\n"
6270 " Operate on local container\n"
6271 " -t --type=TYPE List units of a particular type\n"
6272 " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n"
6273 " -p --property=NAME Show only properties by this name\n"
6274 " -a --all Show all loaded units/properties, including dead/empty\n"
6275 " ones. To list all units installed on the system, use\n"
6276 " the 'list-unit-files' command instead.\n"
6277 " -l --full Don't ellipsize unit names on output\n"
6278 " -r --recursive Show unit list of host and local containers\n"
6279 " --reverse Show reverse dependencies with 'list-dependencies'\n"
6280 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
6281 " queueing a new job\n"
6282 " --show-types When showing sockets, explicitly show their type\n"
6283 " -i --ignore-inhibitors\n"
6284 " When shutting down or sleeping, ignore inhibitors\n"
6285 " --kill-who=WHO Who to send signal to\n"
6286 " -s --signal=SIGNAL Which signal to send\n"
6287 " --now Start or stop unit in addition to enabling or disabling it\n"
6288 " -q --quiet Suppress output\n"
6289 " --no-block Do not wait until operation finished\n"
6290 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6291 " --no-reload Don't reload daemon after en-/dis-abling unit files\n"
6292 " --no-legend Do not print a legend (column headers and hints)\n"
6293 " --no-pager Do not pipe output into a pager\n"
6294 " --no-ask-password\n"
6295 " Do not ask for system passwords\n"
6296 " --global Enable/disable unit files globally\n"
6297 " --runtime Enable unit files only temporarily until next reboot\n"
6298 " -f --force When enabling unit files, override existing symlinks\n"
6299 " When shutting down, execute action immediately\n"
6300 " --preset-mode= Apply only enable, only disable, or all presets\n"
6301 " --root=PATH Enable unit files in the specified root directory\n"
6302 " -n --lines=INTEGER Number of journal entries to show\n"
6303 " -o --output=STRING Change journal output mode (short, short-iso,\n"
6304 " short-precise, short-monotonic, verbose,\n"
6305 " export, json, json-pretty, json-sse, cat)\n"
6306 " --firmware-setup Tell the firmware to show the setup menu on next boot\n"
6307 " --plain Print unit dependencies as a list instead of a tree\n\n"
6309 " list-units [PATTERN...] List loaded units\n"
6310 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
6311 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
6312 " start NAME... Start (activate) one or more units\n"
6313 " stop NAME... Stop (deactivate) one or more units\n"
6314 " reload NAME... Reload one or more units\n"
6315 " restart NAME... Start or restart one or more units\n"
6316 " try-restart NAME... Restart one or more units if active\n"
6317 " reload-or-restart NAME... Reload one or more units if possible,\n"
6318 " otherwise start or restart\n"
6319 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
6320 " otherwise restart if active\n"
6321 " isolate NAME Start one unit and stop all others\n"
6322 " kill NAME... Send signal to processes of a unit\n"
6323 " is-active PATTERN... Check whether units are active\n"
6324 " is-failed PATTERN... Check whether units are failed\n"
6325 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
6326 " show [PATTERN...|JOB...] Show properties of one or more\n"
6327 " units/jobs or the manager\n"
6328 " cat PATTERN... Show files and drop-ins of one or more units\n"
6329 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
6330 " help PATTERN...|PID... Show manual for one or more units\n"
6331 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
6333 " list-dependencies [NAME] Recursively show units which are required\n"
6334 " or wanted by this unit or by which this\n"
6335 " unit is required or wanted\n\n"
6336 "Unit File Commands:\n"
6337 " list-unit-files [PATTERN...] List installed unit files\n"
6338 " enable NAME... Enable one or more unit files\n"
6339 " disable NAME... Disable one or more unit files\n"
6340 " reenable NAME... Reenable one or more unit files\n"
6341 " preset NAME... Enable/disable one or more unit files\n"
6342 " based on preset configuration\n"
6343 " preset-all Enable/disable all unit files based on\n"
6344 " preset configuration\n"
6345 " is-enabled NAME... Check whether unit files are enabled\n"
6346 " mask NAME... Mask one or more units\n"
6347 " unmask NAME... Unmask one or more units\n"
6348 " link PATH... Link one or more units files into\n"
6349 " the search path\n"
6350 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
6351 " on specified one or more units\n"
6352 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
6353 " on specified one or more units\n"
6354 " edit NAME... Edit one or more unit files\n"
6355 " get-default Get the name of the default target\n"
6356 " set-default NAME Set the default target\n\n"
6357 "Machine Commands:\n"
6358 " list-machines [PATTERN...] List local containers and host\n\n"
6360 " list-jobs [PATTERN...] List jobs\n"
6361 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
6362 "Snapshot Commands:\n"
6363 " snapshot [NAME] Create a snapshot\n"
6364 " delete NAME... Remove one or more snapshots\n\n"
6365 "Environment Commands:\n"
6366 " show-environment Dump environment\n"
6367 " set-environment NAME=VALUE... Set one or more environment variables\n"
6368 " unset-environment NAME... Unset one or more environment variables\n"
6369 " import-environment [NAME...] Import all or some environment variables\n\n"
6370 "Manager Lifecycle Commands:\n"
6371 " daemon-reload Reload systemd manager configuration\n"
6372 " daemon-reexec Reexecute systemd manager\n\n"
6373 "System Commands:\n"
6374 " is-system-running Check whether system is fully running\n"
6375 " default Enter system default mode\n"
6376 " rescue Enter system rescue mode\n"
6377 " emergency Enter system emergency mode\n"
6378 " halt Shut down and halt the system\n"
6379 " poweroff Shut down and power-off the system\n"
6380 " reboot [ARG] Shut down and reboot the system\n"
6381 " kexec Shut down and reboot the system with kexec\n"
6382 " exit [EXIT_CODE] Request user instance or container exit\n"
6383 " switch-root ROOT [INIT] Change to a different root file system\n"
6384 " suspend Suspend the system\n"
6385 " hibernate Hibernate the system\n"
6386 " hybrid-sleep Hibernate and suspend the system\n",
6387 program_invocation_short_name
);
6390 static void halt_help(void) {
6391 printf("%s [OPTIONS...]%s\n\n"
6392 "%s the system.\n\n"
6393 " --help Show this help\n"
6394 " --halt Halt the machine\n"
6395 " -p --poweroff Switch off the machine\n"
6396 " --reboot Reboot the machine\n"
6397 " -f --force Force immediate halt/power-off/reboot\n"
6398 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
6399 " -d --no-wtmp Don't write wtmp record\n"
6400 " --no-wall Don't send wall message before halt/power-off/reboot\n",
6401 program_invocation_short_name
,
6402 arg_action
== ACTION_REBOOT
? " [ARG]" : "",
6403 arg_action
== ACTION_REBOOT
? "Reboot" :
6404 arg_action
== ACTION_POWEROFF
? "Power off" :
6408 static void shutdown_help(void) {
6409 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
6410 "Shut down the system.\n\n"
6411 " --help Show this help\n"
6412 " -H --halt Halt the machine\n"
6413 " -P --poweroff Power-off the machine\n"
6414 " -r --reboot Reboot the machine\n"
6415 " -h Equivalent to --poweroff, overridden by --halt\n"
6416 " -k Don't halt/power-off/reboot, just send warnings\n"
6417 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6418 " -c Cancel a pending shutdown\n",
6419 program_invocation_short_name
);
6422 static void telinit_help(void) {
6423 printf("%s [OPTIONS...] {COMMAND}\n\n"
6424 "Send control commands to the init daemon.\n\n"
6425 " --help Show this help\n"
6426 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
6428 " 0 Power-off the machine\n"
6429 " 6 Reboot the machine\n"
6430 " 2, 3, 4, 5 Start runlevelX.target unit\n"
6431 " 1, s, S Enter rescue mode\n"
6432 " q, Q Reload init daemon configuration\n"
6433 " u, U Reexecute init daemon\n",
6434 program_invocation_short_name
);
6437 static void runlevel_help(void) {
6438 printf("%s [OPTIONS...]\n\n"
6439 "Prints the previous and current runlevel of the init system.\n\n"
6440 " --help Show this help\n",
6441 program_invocation_short_name
);
6444 static void help_types(void) {
6449 puts("Available unit types:");
6450 for (i
= 0; i
< _UNIT_TYPE_MAX
; i
++) {
6451 t
= unit_type_to_string(i
);
6457 static int systemctl_parse_argv(int argc
, char *argv
[]) {
6466 ARG_IGNORE_DEPENDENCIES
,
6478 ARG_NO_ASK_PASSWORD
,
6491 static const struct option options
[] = {
6492 { "help", no_argument
, NULL
, 'h' },
6493 { "version", no_argument
, NULL
, ARG_VERSION
},
6494 { "type", required_argument
, NULL
, 't' },
6495 { "property", required_argument
, NULL
, 'p' },
6496 { "all", no_argument
, NULL
, 'a' },
6497 { "reverse", no_argument
, NULL
, ARG_REVERSE
},
6498 { "after", no_argument
, NULL
, ARG_AFTER
},
6499 { "before", no_argument
, NULL
, ARG_BEFORE
},
6500 { "show-types", no_argument
, NULL
, ARG_SHOW_TYPES
},
6501 { "failed", no_argument
, NULL
, ARG_FAILED
}, /* compatibility only */
6502 { "full", no_argument
, NULL
, 'l' },
6503 { "job-mode", required_argument
, NULL
, ARG_JOB_MODE
},
6504 { "fail", no_argument
, NULL
, ARG_FAIL
}, /* compatibility only */
6505 { "irreversible", no_argument
, NULL
, ARG_IRREVERSIBLE
}, /* compatibility only */
6506 { "ignore-dependencies", no_argument
, NULL
, ARG_IGNORE_DEPENDENCIES
}, /* compatibility only */
6507 { "ignore-inhibitors", no_argument
, NULL
, 'i' },
6508 { "user", no_argument
, NULL
, ARG_USER
},
6509 { "system", no_argument
, NULL
, ARG_SYSTEM
},
6510 { "global", no_argument
, NULL
, ARG_GLOBAL
},
6511 { "no-block", no_argument
, NULL
, ARG_NO_BLOCK
},
6512 { "no-legend", no_argument
, NULL
, ARG_NO_LEGEND
},
6513 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
6514 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6515 { "quiet", no_argument
, NULL
, 'q' },
6516 { "root", required_argument
, NULL
, ARG_ROOT
},
6517 { "force", no_argument
, NULL
, ARG_FORCE
},
6518 { "no-reload", no_argument
, NULL
, ARG_NO_RELOAD
},
6519 { "kill-who", required_argument
, NULL
, ARG_KILL_WHO
},
6520 { "signal", required_argument
, NULL
, 's' },
6521 { "no-ask-password", no_argument
, NULL
, ARG_NO_ASK_PASSWORD
},
6522 { "host", required_argument
, NULL
, 'H' },
6523 { "machine", required_argument
, NULL
, 'M' },
6524 { "runtime", no_argument
, NULL
, ARG_RUNTIME
},
6525 { "lines", required_argument
, NULL
, 'n' },
6526 { "output", required_argument
, NULL
, 'o' },
6527 { "plain", no_argument
, NULL
, ARG_PLAIN
},
6528 { "state", required_argument
, NULL
, ARG_STATE
},
6529 { "recursive", no_argument
, NULL
, 'r' },
6530 { "preset-mode", required_argument
, NULL
, ARG_PRESET_MODE
},
6531 { "firmware-setup", no_argument
, NULL
, ARG_FIRMWARE_SETUP
},
6532 { "now", no_argument
, NULL
, ARG_NOW
},
6533 { "message", required_argument
, NULL
, ARG_MESSAGE
},
6542 /* we default to allowing interactive authorization only in systemctl (not in the legacy commands) */
6543 arg_ask_password
= true;
6545 while ((c
= getopt_long(argc
, argv
, "ht:p:alqfs:H:M:n:o:ir", options
, NULL
)) >= 0)
6557 const char *word
, *state
;
6560 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
6561 _cleanup_free_
char *type
;
6563 type
= strndup(word
, size
);
6567 if (streq(type
, "help")) {
6572 if (unit_type_from_string(type
) >= 0) {
6573 if (strv_push(&arg_types
, type
))
6579 /* It's much nicer to use --state= for
6580 * load states, but let's support this
6581 * in --types= too for compatibility
6582 * with old versions */
6583 if (unit_load_state_from_string(optarg
) >= 0) {
6584 if (strv_push(&arg_states
, type
) < 0)
6590 log_error("Unknown unit type or load state '%s'.", type
);
6591 log_info("Use -t help to see a list of allowed values.");
6599 /* Make sure that if the empty property list
6600 was specified, we won't show any properties. */
6601 if (isempty(optarg
) && !arg_properties
) {
6602 arg_properties
= new0(char*, 1);
6603 if (!arg_properties
)
6606 const char *word
, *state
;
6609 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
6612 prop
= strndup(word
, size
);
6616 if (strv_consume(&arg_properties
, prop
) < 0)
6621 /* If the user asked for a particular
6622 * property, show it to him, even if it is
6634 arg_dependency
= DEPENDENCY_REVERSE
;
6638 arg_dependency
= DEPENDENCY_AFTER
;
6642 arg_dependency
= DEPENDENCY_BEFORE
;
6645 case ARG_SHOW_TYPES
:
6646 arg_show_types
= true;
6650 arg_job_mode
= optarg
;
6654 arg_job_mode
= "fail";
6657 case ARG_IRREVERSIBLE
:
6658 arg_job_mode
= "replace-irreversibly";
6661 case ARG_IGNORE_DEPENDENCIES
:
6662 arg_job_mode
= "ignore-dependencies";
6666 arg_scope
= UNIT_FILE_USER
;
6670 arg_scope
= UNIT_FILE_SYSTEM
;
6674 arg_scope
= UNIT_FILE_GLOBAL
;
6678 arg_no_block
= true;
6682 arg_no_legend
= true;
6686 arg_no_pager
= true;
6702 if (strv_extend(&arg_states
, "failed") < 0)
6720 arg_no_reload
= true;
6724 arg_kill_who
= optarg
;
6728 arg_signal
= signal_from_string_try_harder(optarg
);
6729 if (arg_signal
< 0) {
6730 log_error("Failed to parse signal string %s.", optarg
);
6735 case ARG_NO_ASK_PASSWORD
:
6736 arg_ask_password
= false;
6740 arg_transport
= BUS_TRANSPORT_REMOTE
;
6745 arg_transport
= BUS_TRANSPORT_MACHINE
;
6754 if (safe_atou(optarg
, &arg_lines
) < 0) {
6755 log_error("Failed to parse lines '%s'", optarg
);
6761 arg_output
= output_mode_from_string(optarg
);
6762 if (arg_output
< 0) {
6763 log_error("Unknown output '%s'.", optarg
);
6769 arg_ignore_inhibitors
= true;
6776 case ARG_FIRMWARE_SETUP
:
6777 arg_firmware_setup
= true;
6781 const char *word
, *state
;
6784 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
6787 s
= strndup(word
, size
);
6791 if (strv_consume(&arg_states
, s
) < 0)
6798 if (geteuid() != 0) {
6799 log_error("--recursive requires root privileges.");
6803 arg_recursive
= true;
6806 case ARG_PRESET_MODE
:
6808 arg_preset_mode
= unit_file_preset_mode_from_string(optarg
);
6809 if (arg_preset_mode
< 0) {
6810 log_error("Failed to parse preset mode: %s.", optarg
);
6821 if (strv_extend(&arg_wall
, optarg
) < 0)
6829 assert_not_reached("Unhandled option");
6832 if (arg_transport
!= BUS_TRANSPORT_LOCAL
&& arg_scope
!= UNIT_FILE_SYSTEM
) {
6833 log_error("Cannot access user instance remotely.");
6840 static int halt_parse_argv(int argc
, char *argv
[]) {
6849 static const struct option options
[] = {
6850 { "help", no_argument
, NULL
, ARG_HELP
},
6851 { "halt", no_argument
, NULL
, ARG_HALT
},
6852 { "poweroff", no_argument
, NULL
, 'p' },
6853 { "reboot", no_argument
, NULL
, ARG_REBOOT
},
6854 { "force", no_argument
, NULL
, 'f' },
6855 { "wtmp-only", no_argument
, NULL
, 'w' },
6856 { "no-wtmp", no_argument
, NULL
, 'd' },
6857 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6866 if (utmp_get_runlevel(&runlevel
, NULL
) >= 0)
6867 if (runlevel
== '0' || runlevel
== '6')
6870 while ((c
= getopt_long(argc
, argv
, "pfwdnih", options
, NULL
)) >= 0)
6878 arg_action
= ACTION_HALT
;
6882 if (arg_action
!= ACTION_REBOOT
)
6883 arg_action
= ACTION_POWEROFF
;
6887 arg_action
= ACTION_REBOOT
;
6909 /* Compatibility nops */
6916 assert_not_reached("Unhandled option");
6919 if (arg_action
== ACTION_REBOOT
&& (argc
== optind
|| argc
== optind
+ 1)) {
6920 r
= update_reboot_param_file(argc
== optind
+ 1 ? argv
[optind
] : NULL
);
6923 } else if (optind
< argc
) {
6924 log_error("Too many arguments.");
6931 static int parse_shutdown_time_spec(const char *t
, usec_t
*_u
) {
6935 if (streq(t
, "now"))
6937 else if (!strchr(t
, ':')) {
6940 if (safe_atou64(t
, &u
) < 0)
6943 *_u
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
* u
;
6952 hour
= strtol(t
, &e
, 10);
6953 if (errno
> 0 || *e
!= ':' || hour
< 0 || hour
> 23)
6956 minute
= strtol(e
+1, &e
, 10);
6957 if (errno
> 0 || *e
!= 0 || minute
< 0 || minute
> 59)
6960 n
= now(CLOCK_REALTIME
);
6961 s
= (time_t) (n
/ USEC_PER_SEC
);
6963 assert_se(localtime_r(&s
, &tm
));
6965 tm
.tm_hour
= (int) hour
;
6966 tm
.tm_min
= (int) minute
;
6969 assert_se(s
= mktime(&tm
));
6971 *_u
= (usec_t
) s
* USEC_PER_SEC
;
6974 *_u
+= USEC_PER_DAY
;
6980 static int shutdown_parse_argv(int argc
, char *argv
[]) {
6987 static const struct option options
[] = {
6988 { "help", no_argument
, NULL
, ARG_HELP
},
6989 { "halt", no_argument
, NULL
, 'H' },
6990 { "poweroff", no_argument
, NULL
, 'P' },
6991 { "reboot", no_argument
, NULL
, 'r' },
6992 { "kexec", no_argument
, NULL
, 'K' }, /* not documented extension */
6993 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7003 while ((c
= getopt_long(argc
, argv
, "HPrhkKt:afFc", options
, NULL
)) >= 0)
7011 arg_action
= ACTION_HALT
;
7015 arg_action
= ACTION_POWEROFF
;
7020 arg_action
= ACTION_KEXEC
;
7022 arg_action
= ACTION_REBOOT
;
7026 arg_action
= ACTION_KEXEC
;
7030 if (arg_action
!= ACTION_HALT
)
7031 arg_action
= ACTION_POWEROFF
;
7046 /* Compatibility nops */
7050 arg_action
= ACTION_CANCEL_SHUTDOWN
;
7057 assert_not_reached("Unhandled option");
7060 if (argc
> optind
&& arg_action
!= ACTION_CANCEL_SHUTDOWN
) {
7061 r
= parse_shutdown_time_spec(argv
[optind
], &arg_when
);
7063 log_error("Failed to parse time specification: %s", argv
[optind
]);
7067 arg_when
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
;
7069 if (argc
> optind
&& arg_action
== ACTION_CANCEL_SHUTDOWN
)
7070 /* No time argument for shutdown cancel */
7071 wall
= argv
+ optind
;
7072 else if (argc
> optind
+ 1)
7073 /* We skip the time argument */
7074 wall
= argv
+ optind
+ 1;
7077 arg_wall
= strv_copy(wall
);
7087 static int telinit_parse_argv(int argc
, char *argv
[]) {
7094 static const struct option options
[] = {
7095 { "help", no_argument
, NULL
, ARG_HELP
},
7096 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7100 static const struct {
7104 { '0', ACTION_POWEROFF
},
7105 { '6', ACTION_REBOOT
},
7106 { '1', ACTION_RESCUE
},
7107 { '2', ACTION_RUNLEVEL2
},
7108 { '3', ACTION_RUNLEVEL3
},
7109 { '4', ACTION_RUNLEVEL4
},
7110 { '5', ACTION_RUNLEVEL5
},
7111 { 's', ACTION_RESCUE
},
7112 { 'S', ACTION_RESCUE
},
7113 { 'q', ACTION_RELOAD
},
7114 { 'Q', ACTION_RELOAD
},
7115 { 'u', ACTION_REEXEC
},
7116 { 'U', ACTION_REEXEC
}
7125 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
7140 assert_not_reached("Unhandled option");
7143 if (optind
>= argc
) {
7144 log_error("%s: required argument missing.", program_invocation_short_name
);
7148 if (optind
+ 1 < argc
) {
7149 log_error("Too many arguments.");
7153 if (strlen(argv
[optind
]) != 1) {
7154 log_error("Expected single character argument.");
7158 for (i
= 0; i
< ELEMENTSOF(table
); i
++)
7159 if (table
[i
].from
== argv
[optind
][0])
7162 if (i
>= ELEMENTSOF(table
)) {
7163 log_error("Unknown command '%s'.", argv
[optind
]);
7167 arg_action
= table
[i
].to
;
7174 static int runlevel_parse_argv(int argc
, char *argv
[]) {
7180 static const struct option options
[] = {
7181 { "help", no_argument
, NULL
, ARG_HELP
},
7190 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
7201 assert_not_reached("Unhandled option");
7204 if (optind
< argc
) {
7205 log_error("Too many arguments.");
7212 static int parse_argv(int argc
, char *argv
[]) {
7216 if (program_invocation_short_name
) {
7218 if (strstr(program_invocation_short_name
, "halt")) {
7219 arg_action
= ACTION_HALT
;
7220 return halt_parse_argv(argc
, argv
);
7221 } else if (strstr(program_invocation_short_name
, "poweroff")) {
7222 arg_action
= ACTION_POWEROFF
;
7223 return halt_parse_argv(argc
, argv
);
7224 } else if (strstr(program_invocation_short_name
, "reboot")) {
7226 arg_action
= ACTION_KEXEC
;
7228 arg_action
= ACTION_REBOOT
;
7229 return halt_parse_argv(argc
, argv
);
7230 } else if (strstr(program_invocation_short_name
, "shutdown")) {
7231 arg_action
= ACTION_POWEROFF
;
7232 return shutdown_parse_argv(argc
, argv
);
7233 } else if (strstr(program_invocation_short_name
, "init")) {
7235 if (sd_booted() > 0) {
7236 arg_action
= _ACTION_INVALID
;
7237 return telinit_parse_argv(argc
, argv
);
7239 /* Hmm, so some other init system is
7240 * running, we need to forward this
7241 * request to it. For now we simply
7242 * guess that it is Upstart. */
7244 execv(TELINIT
, argv
);
7246 log_error("Couldn't find an alternative telinit implementation to spawn.");
7250 } else if (strstr(program_invocation_short_name
, "runlevel")) {
7251 arg_action
= ACTION_RUNLEVEL
;
7252 return runlevel_parse_argv(argc
, argv
);
7256 arg_action
= ACTION_SYSTEMCTL
;
7257 return systemctl_parse_argv(argc
, argv
);
7260 _pure_
static int action_to_runlevel(void) {
7262 static const char table
[_ACTION_MAX
] = {
7263 [ACTION_HALT
] = '0',
7264 [ACTION_POWEROFF
] = '0',
7265 [ACTION_REBOOT
] = '6',
7266 [ACTION_RUNLEVEL2
] = '2',
7267 [ACTION_RUNLEVEL3
] = '3',
7268 [ACTION_RUNLEVEL4
] = '4',
7269 [ACTION_RUNLEVEL5
] = '5',
7270 [ACTION_RESCUE
] = '1'
7273 assert(arg_action
< _ACTION_MAX
);
7275 return table
[arg_action
];
7278 static int talk_initctl(void) {
7279 #ifdef HAVE_SYSV_COMPAT
7280 struct init_request request
= {
7281 .magic
= INIT_MAGIC
,
7283 .cmd
= INIT_CMD_RUNLVL
7286 _cleanup_close_
int fd
= -1;
7290 rl
= action_to_runlevel();
7294 request
.runlevel
= rl
;
7296 fd
= open(INIT_FIFO
, O_WRONLY
|O_NDELAY
|O_CLOEXEC
|O_NOCTTY
);
7298 if (errno
== ENOENT
)
7301 return log_error_errno(errno
, "Failed to open "INIT_FIFO
": %m");
7304 r
= loop_write(fd
, &request
, sizeof(request
), false);
7306 return log_error_errno(r
, "Failed to write to "INIT_FIFO
": %m");
7314 static int systemctl_main(int argc
, char *argv
[], int bus_error
) {
7316 static const struct {
7324 int (* const dispatch
)(char **args
);
7326 { "list-units", MORE
, 0, list_units
},
7327 { "list-unit-files", MORE
, 1, list_unit_files
},
7328 { "list-sockets", MORE
, 1, list_sockets
},
7329 { "list-timers", MORE
, 1, list_timers
},
7330 { "list-jobs", MORE
, 1, list_jobs
},
7331 { "list-machines", MORE
, 1, list_machines
},
7332 { "clear-jobs", EQUAL
, 1, daemon_reload
},
7333 { "cancel", MORE
, 2, cancel_job
},
7334 { "start", MORE
, 2, start_unit
},
7335 { "stop", MORE
, 2, start_unit
},
7336 { "condstop", MORE
, 2, start_unit
}, /* For compatibility with ALTLinux */
7337 { "reload", MORE
, 2, start_unit
},
7338 { "restart", MORE
, 2, start_unit
},
7339 { "try-restart", MORE
, 2, start_unit
},
7340 { "reload-or-restart", MORE
, 2, start_unit
},
7341 { "reload-or-try-restart", MORE
, 2, start_unit
},
7342 { "force-reload", MORE
, 2, start_unit
}, /* For compatibility with SysV */
7343 { "condreload", MORE
, 2, start_unit
}, /* For compatibility with ALTLinux */
7344 { "condrestart", MORE
, 2, start_unit
}, /* For compatibility with RH */
7345 { "isolate", EQUAL
, 2, start_unit
},
7346 { "kill", MORE
, 2, kill_unit
},
7347 { "is-active", MORE
, 2, check_unit_active
},
7348 { "check", MORE
, 2, check_unit_active
},
7349 { "is-failed", MORE
, 2, check_unit_failed
},
7350 { "show", MORE
, 1, show
},
7351 { "cat", MORE
, 2, cat
, },
7352 { "status", MORE
, 1, show
},
7353 { "help", MORE
, 2, show
},
7354 { "snapshot", LESS
, 2, snapshot
},
7355 { "delete", MORE
, 2, delete_snapshot
},
7356 { "daemon-reload", EQUAL
, 1, daemon_reload
},
7357 { "daemon-reexec", EQUAL
, 1, daemon_reload
},
7358 { "show-environment", EQUAL
, 1, show_environment
},
7359 { "set-environment", MORE
, 2, set_environment
},
7360 { "unset-environment", MORE
, 2, set_environment
},
7361 { "import-environment", MORE
, 1, import_environment
},
7362 { "halt", EQUAL
, 1, start_special
, },
7363 { "poweroff", EQUAL
, 1, start_special
, },
7364 { "reboot", MORE
, 1, start_special
, },
7365 { "kexec", EQUAL
, 1, start_special
},
7366 { "suspend", EQUAL
, 1, start_special
},
7367 { "hibernate", EQUAL
, 1, start_special
},
7368 { "hybrid-sleep", EQUAL
, 1, start_special
},
7369 { "default", EQUAL
, 1, start_special
},
7370 { "rescue", EQUAL
, 1, start_special
},
7371 { "emergency", EQUAL
, 1, start_special
},
7372 { "exit", LESS
, 2, start_special
},
7373 { "reset-failed", MORE
, 1, reset_failed
},
7374 { "enable", MORE
, 2, enable_unit
, },
7375 { "disable", MORE
, 2, enable_unit
, },
7376 { "is-enabled", MORE
, 2, unit_is_enabled
, },
7377 { "reenable", MORE
, 2, enable_unit
, },
7378 { "preset", MORE
, 2, enable_unit
, },
7379 { "preset-all", EQUAL
, 1, preset_all
, },
7380 { "mask", MORE
, 2, enable_unit
, },
7381 { "unmask", MORE
, 2, enable_unit
, },
7382 { "link", MORE
, 2, enable_unit
, },
7383 { "switch-root", MORE
, 2, switch_root
},
7384 { "list-dependencies", LESS
, 2, list_dependencies
},
7385 { "set-default", EQUAL
, 2, set_default
, },
7386 { "get-default", EQUAL
, 1, get_default
, },
7387 { "set-property", MORE
, 3, set_property
},
7388 { "is-system-running", EQUAL
, 1, is_system_running
},
7389 { "add-wants", MORE
, 3, add_dependency
, },
7390 { "add-requires", MORE
, 3, add_dependency
, },
7391 { "edit", MORE
, 2, edit
, },
7400 left
= argc
- optind
;
7402 /* Special rule: no arguments (left == 0) means "list-units" */
7404 if (streq(argv
[optind
], "help") && !argv
[optind
+1]) {
7405 log_error("This command expects one or more unit names. Did you mean --help?");
7409 for (; verb
->verb
; verb
++)
7410 if (streq(argv
[optind
], verb
->verb
))
7413 log_error("Unknown operation '%s'.", argv
[optind
]);
7418 switch (verb
->argc_cmp
) {
7421 if (left
!= verb
->argc
) {
7422 log_error("Invalid number of arguments.");
7429 if (left
< verb
->argc
) {
7430 log_error("Too few arguments.");
7437 if (left
> verb
->argc
) {
7438 log_error("Too many arguments.");
7445 assert_not_reached("Unknown comparison operator.");
7448 return verb
->dispatch(argv
+ optind
);
7451 static int reload_with_fallback(void) {
7453 /* First, try systemd via D-Bus. */
7454 if (daemon_reload(NULL
) >= 0)
7457 /* Nothing else worked, so let's try signals */
7458 assert(arg_action
== ACTION_RELOAD
|| arg_action
== ACTION_REEXEC
);
7460 if (kill(1, arg_action
== ACTION_RELOAD
? SIGHUP
: SIGTERM
) < 0)
7461 return log_error_errno(errno
, "kill() failed: %m");
7466 static int start_with_fallback(void) {
7468 /* First, try systemd via D-Bus. */
7469 if (start_unit(NULL
) >= 0)
7472 /* Nothing else worked, so let's try
7474 if (talk_initctl() > 0)
7477 log_error("Failed to talk to init daemon.");
7481 static int halt_now(enum action a
) {
7483 /* The kernel will automaticall flush ATA disks and suchlike
7484 * on reboot(), but the file systems need to be synce'd
7485 * explicitly in advance. */
7488 /* Make sure C-A-D is handled by the kernel from this point
7490 reboot(RB_ENABLE_CAD
);
7495 log_info("Halting.");
7496 reboot(RB_HALT_SYSTEM
);
7499 case ACTION_POWEROFF
:
7500 log_info("Powering off.");
7501 reboot(RB_POWER_OFF
);
7505 case ACTION_REBOOT
: {
7506 _cleanup_free_
char *param
= NULL
;
7508 if (read_one_line_file(REBOOT_PARAM_FILE
, ¶m
) >= 0) {
7509 log_info("Rebooting with argument '%s'.", param
);
7510 syscall(SYS_reboot
, LINUX_REBOOT_MAGIC1
, LINUX_REBOOT_MAGIC2
, LINUX_REBOOT_CMD_RESTART2
, param
);
7513 log_info("Rebooting.");
7514 reboot(RB_AUTOBOOT
);
7519 assert_not_reached("Unknown action.");
7523 static int logind_schedule_shutdown(void) {
7526 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
7527 char date
[FORMAT_TIMESTAMP_MAX
];
7532 (void) logind_set_wall_message();
7534 r
= acquire_bus(BUS_FULL
, &bus
);
7538 switch (arg_action
) {
7542 case ACTION_POWEROFF
:
7543 action
= "poweroff";
7554 action
= strjoina("dry-", action
);
7556 r
= sd_bus_call_method(
7558 "org.freedesktop.login1",
7559 "/org/freedesktop/login1",
7560 "org.freedesktop.login1.Manager",
7568 return log_warning_errno(r
, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s", bus_error_message(&error
, r
));
7570 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.", format_timestamp(date
, sizeof(date
), arg_when
));
7573 log_error("Cannot schedule shutdown without logind support, proceeding with immediate shutdown.");
7578 static int halt_main(void) {
7581 r
= logind_check_inhibitors(arg_action
);
7585 if (geteuid() != 0) {
7589 log_error("Must be root.");
7593 /* Try logind if we are a normal user and no special
7594 * mode applies. Maybe PolicyKit allows us to shutdown
7596 if (IN_SET(arg_action
,
7599 r
= logind_reboot(arg_action
);
7602 if (IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
7603 /* requested operation is not supported or already in progress */
7605 /* on all other errors, try low-level operation */
7610 r
= logind_schedule_shutdown();
7615 if (!arg_dry
&& !arg_force
)
7616 return start_with_fallback();
7618 assert(geteuid() == 0);
7621 if (sd_booted() > 0)
7622 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
7624 r
= utmp_put_shutdown();
7626 log_warning_errno(r
, "Failed to write utmp record: %m");
7633 r
= halt_now(arg_action
);
7635 return log_error_errno(r
, "Failed to reboot: %m");
7638 static int runlevel_main(void) {
7639 int r
, runlevel
, previous
;
7641 r
= utmp_get_runlevel(&runlevel
, &previous
);
7648 previous
<= 0 ? 'N' : previous
,
7649 runlevel
<= 0 ? 'N' : runlevel
);
7654 static int logind_cancel_shutdown(void) {
7656 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
7660 r
= acquire_bus(BUS_FULL
, &bus
);
7664 (void) logind_set_wall_message();
7666 r
= sd_bus_call_method(
7668 "org.freedesktop.login1",
7669 "/org/freedesktop/login1",
7670 "org.freedesktop.login1.Manager",
7671 "CancelScheduledShutdown",
7675 return log_warning_errno(r
, "Failed to talk to logind, shutdown hasn't been cancelled: %s", bus_error_message(&error
, r
));
7679 log_error("Not compiled with logind support, cannot cancel scheduled shutdowns.");
7684 int main(int argc
, char*argv
[]) {
7687 setlocale(LC_ALL
, "");
7688 log_parse_environment();
7691 /* Explicitly not on_tty() to avoid setting cached value.
7692 * This becomes relevant for piping output which might be
7694 original_stdout_is_tty
= isatty(STDOUT_FILENO
);
7696 r
= parse_argv(argc
, argv
);
7700 if (running_in_chroot() > 0 && arg_action
!= ACTION_SYSTEMCTL
) {
7701 log_info("Running in chroot, ignoring request.");
7706 /* systemctl_main() will print an error message for the bus
7707 * connection, but only if it needs to */
7709 switch (arg_action
) {
7711 case ACTION_SYSTEMCTL
:
7712 r
= systemctl_main(argc
, argv
, r
);
7716 case ACTION_POWEROFF
:
7722 case ACTION_RUNLEVEL2
:
7723 case ACTION_RUNLEVEL3
:
7724 case ACTION_RUNLEVEL4
:
7725 case ACTION_RUNLEVEL5
:
7727 case ACTION_EMERGENCY
:
7728 case ACTION_DEFAULT
:
7729 r
= start_with_fallback();
7734 r
= reload_with_fallback();
7737 case ACTION_CANCEL_SHUTDOWN
:
7738 r
= logind_cancel_shutdown();
7741 case ACTION_RUNLEVEL
:
7742 r
= runlevel_main();
7745 case _ACTION_INVALID
:
7747 assert_not_reached("Unknown action");
7752 ask_password_agent_close();
7753 polkit_agent_close();
7755 strv_free(arg_types
);
7756 strv_free(arg_states
);
7757 strv_free(arg_properties
);
7759 strv_free(arg_wall
);
7763 return r
< 0 ? EXIT_FAILURE
: r
;