2 This file is part of systemd.
4 Copyright 2010 Lennart Poettering
5 Copyright 2013 Marc-Antoine Perennou
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #include <linux/reboot.h>
30 #include <sys/reboot.h>
31 #include <sys/socket.h>
35 #include "sd-daemon.h"
38 #include "alloc-util.h"
39 #include "bus-common-errors.h"
40 #include "bus-error.h"
41 #include "bus-message.h"
42 #include "bus-unit-util.h"
44 #include "cgroup-show.h"
45 #include "cgroup-util.h"
50 #include "exit-status.h"
53 #include "formats-util.h"
55 #include "glob-util.h"
56 #include "hostname-util.h"
61 #include "locale-util.h"
63 #include "logs-show.h"
67 #include "parse-util.h"
68 #include "path-lookup.h"
69 #include "path-util.h"
70 #include "process-util.h"
71 #include "rlimit-util.h"
74 #include "signal-util.h"
75 #include "socket-util.h"
76 #include "spawn-ask-password-agent.h"
77 #include "spawn-polkit-agent.h"
79 #include "stat-util.h"
81 #include "terminal-util.h"
82 #include "unit-name.h"
83 #include "user-util.h"
85 #include "utmp-wtmp.h"
89 /* The init script exit status codes
90 0 program is running or service is OK
91 1 program is dead and /var/run pid file exists
92 2 program is dead and /var/lock lock file exists
93 3 program is not running
94 4 program or service status is unknown
95 5-99 reserved for future LSB use
96 100-149 reserved for distribution use
97 150-199 reserved for application use
101 EXIT_PROGRAM_RUNNING_OR_SERVICE_OK
= 0,
102 EXIT_PROGRAM_DEAD_AND_PID_EXISTS
= 1,
103 EXIT_PROGRAM_DEAD_AND_LOCK_FILE_EXISTS
= 2,
104 EXIT_PROGRAM_NOT_RUNNING
= 3,
105 EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN
= 4,
108 static char **arg_types
= NULL
;
109 static char **arg_states
= NULL
;
110 static char **arg_properties
= NULL
;
111 static bool arg_all
= false;
112 static enum dependency
{
118 } arg_dependency
= DEPENDENCY_FORWARD
;
119 static const char *arg_job_mode
= "replace";
120 static UnitFileScope arg_scope
= UNIT_FILE_SYSTEM
;
121 static bool arg_wait
= false;
122 static bool arg_no_block
= false;
123 static bool arg_no_legend
= false;
124 static bool arg_no_pager
= false;
125 static bool arg_no_wtmp
= false;
126 static bool arg_no_sync
= false;
127 static bool arg_no_wall
= false;
128 static bool arg_no_reload
= false;
129 static bool arg_value
= false;
130 static bool arg_show_types
= false;
131 static bool arg_ignore_inhibitors
= false;
132 static bool arg_dry
= false;
133 static bool arg_quiet
= false;
134 static bool arg_full
= false;
135 static bool arg_recursive
= false;
136 static int arg_force
= 0;
137 static bool arg_ask_password
= false;
138 static bool arg_runtime
= false;
139 static UnitFilePresetMode arg_preset_mode
= UNIT_FILE_PRESET_FULL
;
140 static char **arg_wall
= NULL
;
141 static const char *arg_kill_who
= NULL
;
142 static int arg_signal
= SIGTERM
;
143 static char *arg_root
= NULL
;
144 static usec_t arg_when
= 0;
166 ACTION_CANCEL_SHUTDOWN
,
168 } arg_action
= ACTION_SYSTEMCTL
;
169 static BusTransport arg_transport
= BUS_TRANSPORT_LOCAL
;
170 static const char *arg_host
= NULL
;
171 static unsigned arg_lines
= 10;
172 static OutputMode arg_output
= OUTPUT_SHORT
;
173 static bool arg_plain
= false;
174 static bool arg_firmware_setup
= false;
175 static bool arg_now
= false;
177 static int daemon_reload(int argc
, char *argv
[], void* userdata
);
178 static int trivial_method(int argc
, char *argv
[], void *userdata
);
179 static int halt_now(enum action a
);
180 static int get_state_one_unit(sd_bus
*bus
, const char *name
, UnitActiveState
*active_state
);
182 static bool original_stdout_is_tty
;
184 typedef enum BusFocus
{
185 BUS_FULL
, /* The full bus indicated via --system or --user */
186 BUS_MANAGER
, /* The manager itself, possibly directly, possibly via the bus */
190 static sd_bus
*busses
[_BUS_FOCUS_MAX
] = {};
192 static int acquire_bus(BusFocus focus
, sd_bus
**ret
) {
195 assert(focus
< _BUS_FOCUS_MAX
);
198 /* We only go directly to the manager, if we are using a local transport */
199 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
202 if (!busses
[focus
]) {
205 user
= arg_scope
!= UNIT_FILE_SYSTEM
;
207 if (focus
== BUS_MANAGER
)
208 r
= bus_connect_transport_systemd(arg_transport
, arg_host
, user
, &busses
[focus
]);
210 r
= bus_connect_transport(arg_transport
, arg_host
, user
, &busses
[focus
]);
212 return log_error_errno(r
, "Failed to connect to bus: %m");
214 (void) sd_bus_set_allow_interactive_authorization(busses
[focus
], arg_ask_password
);
217 *ret
= busses
[focus
];
221 static void release_busses(void) {
224 for (w
= 0; w
< _BUS_FOCUS_MAX
; w
++)
225 busses
[w
] = sd_bus_flush_close_unref(busses
[w
]);
228 static int map_string_no_copy(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
230 const char **p
= userdata
;
233 r
= sd_bus_message_read_basic(m
, SD_BUS_TYPE_STRING
, &s
);
243 static void ask_password_agent_open_if_enabled(void) {
245 /* Open the password agent as a child process if necessary */
247 if (!arg_ask_password
)
250 if (arg_scope
!= UNIT_FILE_SYSTEM
)
253 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
256 ask_password_agent_open();
259 static void polkit_agent_open_if_enabled(void) {
261 /* Open the polkit agent as a child process if necessary */
263 if (!arg_ask_password
)
266 if (arg_scope
!= UNIT_FILE_SYSTEM
)
269 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
275 static OutputFlags
get_output_flags(void) {
277 arg_all
* OUTPUT_SHOW_ALL
|
278 arg_full
* OUTPUT_FULL_WIDTH
|
279 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH
|
280 colors_enabled() * OUTPUT_COLOR
|
281 !arg_quiet
* OUTPUT_WARN_CUTOFF
;
284 static int translate_bus_error_to_exit_status(int r
, const sd_bus_error
*error
) {
287 if (!sd_bus_error_is_set(error
))
290 if (sd_bus_error_has_name(error
, SD_BUS_ERROR_ACCESS_DENIED
) ||
291 sd_bus_error_has_name(error
, BUS_ERROR_ONLY_BY_DEPENDENCY
) ||
292 sd_bus_error_has_name(error
, BUS_ERROR_NO_ISOLATION
) ||
293 sd_bus_error_has_name(error
, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE
))
294 return EXIT_NOPERMISSION
;
296 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
))
297 return EXIT_NOTINSTALLED
;
299 if (sd_bus_error_has_name(error
, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE
) ||
300 sd_bus_error_has_name(error
, SD_BUS_ERROR_NOT_SUPPORTED
))
301 return EXIT_NOTIMPLEMENTED
;
303 if (sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
))
304 return EXIT_NOTCONFIGURED
;
312 static bool install_client_side(void) {
314 /* Decides when to execute enable/disable/... operations
315 * client-side rather than server-side. */
317 if (running_in_chroot() > 0)
320 if (sd_booted() <= 0)
323 if (!isempty(arg_root
))
326 if (arg_scope
== UNIT_FILE_GLOBAL
)
329 /* Unsupported environment variable, mostly for debugging purposes */
330 if (getenv_bool("SYSTEMCTL_INSTALL_CLIENT_SIDE") > 0)
336 static int compare_unit_info(const void *a
, const void *b
) {
337 const UnitInfo
*u
= a
, *v
= b
;
341 /* First, order by machine */
342 if (!u
->machine
&& v
->machine
)
344 if (u
->machine
&& !v
->machine
)
346 if (u
->machine
&& v
->machine
) {
347 r
= strcasecmp(u
->machine
, v
->machine
);
352 /* Second, order by unit type */
353 d1
= strrchr(u
->id
, '.');
354 d2
= strrchr(v
->id
, '.');
356 r
= strcasecmp(d1
, d2
);
361 /* Third, order by name */
362 return strcasecmp(u
->id
, v
->id
);
365 static bool output_show_unit(const UnitInfo
*u
, char **patterns
) {
368 if (!strv_fnmatch_or_empty(patterns
, u
->id
, FNM_NOESCAPE
))
374 dot
= strrchr(u
->id
, '.');
378 if (!strv_find(arg_types
, dot
+1))
385 /* Note that '--all' is not purely a state filter, but also a
386 * filter that hides units that "follow" other units (which is
387 * used for device units that appear under different names). */
388 if (!isempty(u
->following
))
391 if (!strv_isempty(arg_states
))
394 /* By default show all units except the ones in inactive
395 * state and with no pending job */
399 if (streq(u
->active_state
, "inactive"))
405 static int output_units_list(const UnitInfo
*unit_infos
, unsigned c
) {
406 unsigned circle_len
= 0, id_len
, max_id_len
, load_len
, active_len
, sub_len
, job_len
, desc_len
;
408 unsigned n_shown
= 0;
411 max_id_len
= strlen("UNIT");
412 load_len
= strlen("LOAD");
413 active_len
= strlen("ACTIVE");
414 sub_len
= strlen("SUB");
415 job_len
= strlen("JOB");
418 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
419 max_id_len
= MAX(max_id_len
, strlen(u
->id
) + (u
->machine
? strlen(u
->machine
)+1 : 0));
420 load_len
= MAX(load_len
, strlen(u
->load_state
));
421 active_len
= MAX(active_len
, strlen(u
->active_state
));
422 sub_len
= MAX(sub_len
, strlen(u
->sub_state
));
424 if (u
->job_id
!= 0) {
425 job_len
= MAX(job_len
, strlen(u
->job_type
));
429 if (!arg_no_legend
&&
430 (streq(u
->active_state
, "failed") ||
431 STR_IN_SET(u
->load_state
, "error", "not-found", "masked")))
435 if (!arg_full
&& original_stdout_is_tty
) {
438 id_len
= MIN(max_id_len
, 25u);
439 basic_len
= circle_len
+ 5 + id_len
+ 5 + active_len
+ sub_len
;
442 basic_len
+= job_len
+ 1;
444 if (basic_len
< (unsigned) columns()) {
445 unsigned extra_len
, incr
;
446 extra_len
= columns() - basic_len
;
448 /* Either UNIT already got 25, or is fully satisfied.
449 * Grant up to 25 to DESC now. */
450 incr
= MIN(extra_len
, 25u);
454 /* split the remaining space between UNIT and DESC,
455 * but do not give UNIT more than it needs. */
457 incr
= MIN(extra_len
/ 2, max_id_len
- id_len
);
459 desc_len
+= extra_len
- incr
;
465 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
466 _cleanup_free_
char *e
= NULL
, *j
= NULL
;
467 const char *on_loaded
= "", *off_loaded
= "";
468 const char *on_active
= "", *off_active
= "";
469 const char *on_circle
= "", *off_circle
= "";
473 if (!n_shown
&& !arg_no_legend
) {
478 printf("%-*s %-*s %-*s %-*s ",
481 active_len
, "ACTIVE",
485 printf("%-*s ", job_len
, "JOB");
487 if (!arg_full
&& arg_no_pager
)
488 printf("%.*s\n", desc_len
, "DESCRIPTION");
490 printf("%s\n", "DESCRIPTION");
495 if (STR_IN_SET(u
->load_state
, "error", "not-found", "masked") && !arg_plain
) {
496 on_loaded
= ansi_highlight_red();
497 on_circle
= ansi_highlight_yellow();
498 off_loaded
= off_circle
= ansi_normal();
500 } else if (streq(u
->active_state
, "failed") && !arg_plain
) {
501 on_circle
= on_active
= ansi_highlight_red();
502 off_circle
= off_active
= ansi_normal();
507 j
= strjoin(u
->machine
, ":", u
->id
, NULL
);
516 e
= ellipsize(id
, id_len
, 33);
524 printf("%s%s%s ", on_circle
, circle
? special_glyph(BLACK_CIRCLE
) : " ", off_circle
);
526 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
527 on_active
, id_len
, id
, off_active
,
528 on_loaded
, load_len
, u
->load_state
, off_loaded
,
529 on_active
, active_len
, u
->active_state
,
530 sub_len
, u
->sub_state
, off_active
,
531 job_count
? job_len
+ 1 : 0, u
->job_id
? u
->job_type
: "");
534 printf("%.*s\n", desc_len
, u
->description
);
536 printf("%s\n", u
->description
);
539 if (!arg_no_legend
) {
540 const char *on
, *off
;
544 "LOAD = Reflects whether the unit definition was properly loaded.\n"
545 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
546 "SUB = The low-level unit activation state, values depend on unit type.");
547 puts(job_count
? "JOB = Pending job for the unit.\n" : "");
548 on
= ansi_highlight();
551 on
= ansi_highlight_red();
556 printf("%s%u loaded units listed.%s\n"
557 "To show all installed unit files use 'systemctl list-unit-files'.\n",
560 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
561 "To show all installed unit files use 'systemctl list-unit-files'.\n",
568 static int get_unit_list(
572 UnitInfo
**unit_infos
,
574 sd_bus_message
**_reply
) {
576 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
577 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
578 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
582 bool fallback
= false;
588 r
= sd_bus_message_new_method_call(
591 "org.freedesktop.systemd1",
592 "/org/freedesktop/systemd1",
593 "org.freedesktop.systemd1.Manager",
594 "ListUnitsByPatterns");
596 return bus_log_create_error(r
);
598 r
= sd_bus_message_append_strv(m
, arg_states
);
600 return bus_log_create_error(r
);
602 r
= sd_bus_message_append_strv(m
, patterns
);
604 return bus_log_create_error(r
);
606 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
607 if (r
< 0 && (sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_METHOD
) ||
608 sd_bus_error_has_name(&error
, SD_BUS_ERROR_ACCESS_DENIED
))) {
609 /* Fallback to legacy ListUnitsFiltered method */
611 log_debug_errno(r
, "Failed to list units: %s Falling back to ListUnitsFiltered method.", bus_error_message(&error
, r
));
612 m
= sd_bus_message_unref(m
);
613 sd_bus_error_free(&error
);
615 r
= sd_bus_message_new_method_call(
618 "org.freedesktop.systemd1",
619 "/org/freedesktop/systemd1",
620 "org.freedesktop.systemd1.Manager",
621 "ListUnitsFiltered");
623 return bus_log_create_error(r
);
625 r
= sd_bus_message_append_strv(m
, arg_states
);
627 return bus_log_create_error(r
);
629 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
632 return log_error_errno(r
, "Failed to list units: %s", bus_error_message(&error
, r
));
634 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssssouso)");
636 return bus_log_parse_error(r
);
638 while ((r
= bus_parse_unit_info(reply
, &u
)) > 0) {
641 if (!output_show_unit(&u
, fallback
? patterns
: NULL
))
644 if (!GREEDY_REALLOC(*unit_infos
, size
, c
+1))
647 (*unit_infos
)[c
++] = u
;
650 return bus_log_parse_error(r
);
652 r
= sd_bus_message_exit_container(reply
);
654 return bus_log_parse_error(r
);
662 static void message_set_freep(Set
**set
) {
665 while ((m
= set_steal_first(*set
)))
666 sd_bus_message_unref(m
);
671 static int get_unit_list_recursive(
674 UnitInfo
**_unit_infos
,
678 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
679 _cleanup_(message_set_freep
) Set
*replies
;
680 sd_bus_message
*reply
;
688 replies
= set_new(NULL
);
692 c
= get_unit_list(bus
, NULL
, patterns
, &unit_infos
, 0, &reply
);
696 r
= set_put(replies
, reply
);
698 sd_bus_message_unref(reply
);
703 _cleanup_strv_free_
char **machines
= NULL
;
706 r
= sd_get_machine_names(&machines
);
708 return log_error_errno(r
, "Failed to get machine names: %m");
710 STRV_FOREACH(i
, machines
) {
711 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*container
= NULL
;
714 r
= sd_bus_open_system_machine(&container
, *i
);
716 log_warning_errno(r
, "Failed to connect to container %s, ignoring: %m", *i
);
720 k
= get_unit_list(container
, *i
, patterns
, &unit_infos
, c
, &reply
);
726 r
= set_put(replies
, reply
);
728 sd_bus_message_unref(reply
);
733 *_machines
= machines
;
738 *_unit_infos
= unit_infos
;
747 static int list_units(int argc
, char *argv
[], void *userdata
) {
748 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
749 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
750 _cleanup_strv_free_
char **machines
= NULL
;
754 r
= acquire_bus(BUS_MANAGER
, &bus
);
758 pager_open(arg_no_pager
, false);
760 r
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
764 qsort_safe(unit_infos
, r
, sizeof(UnitInfo
), compare_unit_info
);
765 return output_units_list(unit_infos
, r
);
768 static int get_triggered_units(
773 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
780 r
= sd_bus_get_property_strv(
782 "org.freedesktop.systemd1",
784 "org.freedesktop.systemd1.Unit",
789 return log_error_errno(r
, "Failed to determine triggers: %s", bus_error_message(&error
, r
));
794 static int get_listening(
796 const char* unit_path
,
799 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
800 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
801 const char *type
, *path
;
804 r
= sd_bus_get_property(
806 "org.freedesktop.systemd1",
808 "org.freedesktop.systemd1.Socket",
814 return log_error_errno(r
, "Failed to get list of listening sockets: %s", bus_error_message(&error
, r
));
816 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
818 return bus_log_parse_error(r
);
820 while ((r
= sd_bus_message_read(reply
, "(ss)", &type
, &path
)) > 0) {
822 r
= strv_extend(listening
, type
);
826 r
= strv_extend(listening
, path
);
833 return bus_log_parse_error(r
);
835 r
= sd_bus_message_exit_container(reply
);
837 return bus_log_parse_error(r
);
849 /* Note: triggered is a list here, although it almost certainly
850 * will always be one unit. Nevertheless, dbus API allows for multiple
851 * values, so let's follow that. */
854 /* The strv above is shared. free is set only in the first one. */
858 static int socket_info_compare(const struct socket_info
*a
, const struct socket_info
*b
) {
864 if (!a
->machine
&& b
->machine
)
866 if (a
->machine
&& !b
->machine
)
868 if (a
->machine
&& b
->machine
) {
869 o
= strcasecmp(a
->machine
, b
->machine
);
874 o
= strcmp(a
->path
, b
->path
);
876 o
= strcmp(a
->type
, b
->type
);
881 static int output_sockets_list(struct socket_info
*socket_infos
, unsigned cs
) {
882 struct socket_info
*s
;
883 unsigned pathlen
= strlen("LISTEN"),
884 typelen
= strlen("TYPE") * arg_show_types
,
885 socklen
= strlen("UNIT"),
886 servlen
= strlen("ACTIVATES");
887 const char *on
, *off
;
889 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
893 socklen
= MAX(socklen
, strlen(s
->id
));
895 typelen
= MAX(typelen
, strlen(s
->type
));
896 pathlen
= MAX(pathlen
, strlen(s
->path
) + (s
->machine
? strlen(s
->machine
)+1 : 0));
898 STRV_FOREACH(a
, s
->triggered
)
899 tmp
+= strlen(*a
) + 2*(a
!= s
->triggered
);
900 servlen
= MAX(servlen
, tmp
);
905 printf("%-*s %-*.*s%-*s %s\n",
907 typelen
+ arg_show_types
, typelen
+ arg_show_types
, "TYPE ",
911 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
912 _cleanup_free_
char *j
= NULL
;
917 j
= strjoin(s
->machine
, ":", s
->path
, NULL
);
925 printf("%-*s %-*s %-*s",
926 pathlen
, path
, typelen
, s
->type
, socklen
, s
->id
);
929 pathlen
, path
, socklen
, s
->id
);
930 STRV_FOREACH(a
, s
->triggered
)
932 a
== s
->triggered
? "" : ",", *a
);
936 on
= ansi_highlight();
941 on
= ansi_highlight_red();
945 if (!arg_no_legend
) {
946 printf("%s%u sockets listed.%s\n", on
, cs
, off
);
948 printf("Pass --all to see loaded but inactive sockets, too.\n");
954 static int list_sockets(int argc
, char *argv
[], void *userdata
) {
955 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
956 _cleanup_strv_free_
char **machines
= NULL
;
957 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
958 _cleanup_free_
struct socket_info
*socket_infos
= NULL
;
960 struct socket_info
*s
;
966 r
= acquire_bus(BUS_MANAGER
, &bus
);
970 pager_open(arg_no_pager
, false);
972 n
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
976 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
977 _cleanup_strv_free_
char **listening
= NULL
, **triggered
= NULL
;
980 if (!endswith(u
->id
, ".socket"))
983 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
987 c
= get_listening(bus
, u
->unit_path
, &listening
);
993 if (!GREEDY_REALLOC(socket_infos
, size
, cs
+ c
)) {
998 for (i
= 0; i
< c
; i
++)
999 socket_infos
[cs
+ i
] = (struct socket_info
) {
1000 .machine
= u
->machine
,
1002 .type
= listening
[i
*2],
1003 .path
= listening
[i
*2 + 1],
1004 .triggered
= triggered
,
1005 .own_triggered
= i
==0,
1008 /* from this point on we will cleanup those socket_infos */
1011 listening
= triggered
= NULL
; /* avoid cleanup */
1014 qsort_safe(socket_infos
, cs
, sizeof(struct socket_info
),
1015 (__compar_fn_t
) socket_info_compare
);
1017 output_sockets_list(socket_infos
, cs
);
1020 assert(cs
== 0 || socket_infos
);
1021 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
1024 if (s
->own_triggered
)
1025 strv_free(s
->triggered
);
1031 static int get_next_elapse(
1034 dual_timestamp
*next
) {
1036 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1044 r
= sd_bus_get_property_trivial(
1046 "org.freedesktop.systemd1",
1048 "org.freedesktop.systemd1.Timer",
1049 "NextElapseUSecMonotonic",
1054 return log_error_errno(r
, "Failed to get next elapsation time: %s", bus_error_message(&error
, r
));
1056 r
= sd_bus_get_property_trivial(
1058 "org.freedesktop.systemd1",
1060 "org.freedesktop.systemd1.Timer",
1061 "NextElapseUSecRealtime",
1066 return log_error_errno(r
, "Failed to get next elapsation time: %s", bus_error_message(&error
, r
));
1072 static int get_last_trigger(
1077 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1084 r
= sd_bus_get_property_trivial(
1086 "org.freedesktop.systemd1",
1088 "org.freedesktop.systemd1.Timer",
1094 return log_error_errno(r
, "Failed to get last trigger time: %s", bus_error_message(&error
, r
));
1100 const char* machine
;
1103 usec_t last_trigger
;
1107 static int timer_info_compare(const struct timer_info
*a
, const struct timer_info
*b
) {
1113 if (!a
->machine
&& b
->machine
)
1115 if (a
->machine
&& !b
->machine
)
1117 if (a
->machine
&& b
->machine
) {
1118 o
= strcasecmp(a
->machine
, b
->machine
);
1123 if (a
->next_elapse
< b
->next_elapse
)
1125 if (a
->next_elapse
> b
->next_elapse
)
1128 return strcmp(a
->id
, b
->id
);
1131 static int output_timers_list(struct timer_info
*timer_infos
, unsigned n
) {
1132 struct timer_info
*t
;
1134 nextlen
= strlen("NEXT"),
1135 leftlen
= strlen("LEFT"),
1136 lastlen
= strlen("LAST"),
1137 passedlen
= strlen("PASSED"),
1138 unitlen
= strlen("UNIT"),
1139 activatelen
= strlen("ACTIVATES");
1141 const char *on
, *off
;
1143 assert(timer_infos
|| n
== 0);
1145 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1149 if (t
->next_elapse
> 0) {
1150 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1152 format_timestamp(tstamp
, sizeof(tstamp
), t
->next_elapse
);
1153 nextlen
= MAX(nextlen
, strlen(tstamp
) + 1);
1155 format_timestamp_relative(trel
, sizeof(trel
), t
->next_elapse
);
1156 leftlen
= MAX(leftlen
, strlen(trel
));
1159 if (t
->last_trigger
> 0) {
1160 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1162 format_timestamp(tstamp
, sizeof(tstamp
), t
->last_trigger
);
1163 lastlen
= MAX(lastlen
, strlen(tstamp
) + 1);
1165 format_timestamp_relative(trel
, sizeof(trel
), t
->last_trigger
);
1166 passedlen
= MAX(passedlen
, strlen(trel
));
1169 unitlen
= MAX(unitlen
, strlen(t
->id
) + (t
->machine
? strlen(t
->machine
)+1 : 0));
1171 STRV_FOREACH(a
, t
->triggered
)
1172 ul
+= strlen(*a
) + 2*(a
!= t
->triggered
);
1174 activatelen
= MAX(activatelen
, ul
);
1179 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1183 passedlen
, "PASSED",
1187 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1188 _cleanup_free_
char *j
= NULL
;
1190 char tstamp1
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel1
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1191 char tstamp2
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel2
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1194 format_timestamp(tstamp1
, sizeof(tstamp1
), t
->next_elapse
);
1195 format_timestamp_relative(trel1
, sizeof(trel1
), t
->next_elapse
);
1197 format_timestamp(tstamp2
, sizeof(tstamp2
), t
->last_trigger
);
1198 format_timestamp_relative(trel2
, sizeof(trel2
), t
->last_trigger
);
1201 j
= strjoin(t
->machine
, ":", t
->id
, NULL
);
1208 printf("%-*s %-*s %-*s %-*s %-*s",
1209 nextlen
, tstamp1
, leftlen
, trel1
, lastlen
, tstamp2
, passedlen
, trel2
, unitlen
, unit
);
1211 STRV_FOREACH(a
, t
->triggered
)
1213 a
== t
->triggered
? "" : ",", *a
);
1217 on
= ansi_highlight();
1218 off
= ansi_normal();
1222 on
= ansi_highlight_red();
1223 off
= ansi_normal();
1226 if (!arg_no_legend
) {
1227 printf("%s%u timers listed.%s\n", on
, n
, off
);
1229 printf("Pass --all to see loaded but inactive timers, too.\n");
1235 static usec_t
calc_next_elapse(dual_timestamp
*nw
, dual_timestamp
*next
) {
1241 if (next
->monotonic
!= USEC_INFINITY
&& next
->monotonic
> 0) {
1244 if (next
->monotonic
> nw
->monotonic
)
1245 converted
= nw
->realtime
+ (next
->monotonic
- nw
->monotonic
);
1247 converted
= nw
->realtime
- (nw
->monotonic
- next
->monotonic
);
1249 if (next
->realtime
!= USEC_INFINITY
&& next
->realtime
> 0)
1250 next_elapse
= MIN(converted
, next
->realtime
);
1252 next_elapse
= converted
;
1255 next_elapse
= next
->realtime
;
1260 static int list_timers(int argc
, char *argv
[], void *userdata
) {
1261 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
1262 _cleanup_strv_free_
char **machines
= NULL
;
1263 _cleanup_free_
struct timer_info
*timer_infos
= NULL
;
1264 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
1265 struct timer_info
*t
;
1273 r
= acquire_bus(BUS_MANAGER
, &bus
);
1277 pager_open(arg_no_pager
, false);
1279 n
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
1283 dual_timestamp_get(&nw
);
1285 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
1286 _cleanup_strv_free_
char **triggered
= NULL
;
1287 dual_timestamp next
= DUAL_TIMESTAMP_NULL
;
1290 if (!endswith(u
->id
, ".timer"))
1293 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
1297 r
= get_next_elapse(bus
, u
->unit_path
, &next
);
1301 get_last_trigger(bus
, u
->unit_path
, &last
);
1303 if (!GREEDY_REALLOC(timer_infos
, size
, c
+1)) {
1308 m
= calc_next_elapse(&nw
, &next
);
1310 timer_infos
[c
++] = (struct timer_info
) {
1311 .machine
= u
->machine
,
1314 .last_trigger
= last
,
1315 .triggered
= triggered
,
1318 triggered
= NULL
; /* avoid cleanup */
1321 qsort_safe(timer_infos
, c
, sizeof(struct timer_info
),
1322 (__compar_fn_t
) timer_info_compare
);
1324 output_timers_list(timer_infos
, c
);
1327 for (t
= timer_infos
; t
< timer_infos
+ c
; t
++)
1328 strv_free(t
->triggered
);
1333 static int compare_unit_file_list(const void *a
, const void *b
) {
1334 const char *d1
, *d2
;
1335 const UnitFileList
*u
= a
, *v
= b
;
1337 d1
= strrchr(u
->path
, '.');
1338 d2
= strrchr(v
->path
, '.');
1343 r
= strcasecmp(d1
, d2
);
1348 return strcasecmp(basename(u
->path
), basename(v
->path
));
1351 static bool output_show_unit_file(const UnitFileList
*u
, char **states
, char **patterns
) {
1354 if (!strv_fnmatch_or_empty(patterns
, basename(u
->path
), FNM_NOESCAPE
))
1357 if (!strv_isempty(arg_types
)) {
1360 dot
= strrchr(u
->path
, '.');
1364 if (!strv_find(arg_types
, dot
+1))
1368 if (!strv_isempty(states
) &&
1369 !strv_find(states
, unit_file_state_to_string(u
->state
)))
1375 static void output_unit_file_list(const UnitFileList
*units
, unsigned c
) {
1376 unsigned max_id_len
, id_cols
, state_cols
;
1377 const UnitFileList
*u
;
1379 max_id_len
= strlen("UNIT FILE");
1380 state_cols
= strlen("STATE");
1382 for (u
= units
; u
< units
+ c
; u
++) {
1383 max_id_len
= MAX(max_id_len
, strlen(basename(u
->path
)));
1384 state_cols
= MAX(state_cols
, strlen(unit_file_state_to_string(u
->state
)));
1388 unsigned basic_cols
;
1390 id_cols
= MIN(max_id_len
, 25u);
1391 basic_cols
= 1 + id_cols
+ state_cols
;
1392 if (basic_cols
< (unsigned) columns())
1393 id_cols
+= MIN(columns() - basic_cols
, max_id_len
- id_cols
);
1395 id_cols
= max_id_len
;
1397 if (!arg_no_legend
&& c
> 0)
1398 printf("%-*s %-*s\n",
1399 id_cols
, "UNIT FILE",
1400 state_cols
, "STATE");
1402 for (u
= units
; u
< units
+ c
; u
++) {
1403 _cleanup_free_
char *e
= NULL
;
1404 const char *on
, *off
;
1407 if (IN_SET(u
->state
,
1409 UNIT_FILE_MASKED_RUNTIME
,
1412 on
= ansi_highlight_red();
1413 off
= ansi_normal();
1414 } else if (u
->state
== UNIT_FILE_ENABLED
) {
1415 on
= ansi_highlight_green();
1416 off
= ansi_normal();
1420 id
= basename(u
->path
);
1422 e
= arg_full
? NULL
: ellipsize(id
, id_cols
, 33);
1424 printf("%-*s %s%-*s%s\n",
1425 id_cols
, e
? e
: id
,
1426 on
, state_cols
, unit_file_state_to_string(u
->state
), off
);
1430 printf("\n%u unit files listed.\n", c
);
1433 static int list_unit_files(int argc
, char *argv
[], void *userdata
) {
1434 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1435 _cleanup_free_ UnitFileList
*units
= NULL
;
1442 bool fallback
= false;
1444 if (install_client_side()) {
1450 h
= hashmap_new(&string_hash_ops
);
1454 r
= unit_file_get_list(arg_scope
, arg_root
, h
, arg_states
, strv_skip(argv
, 1));
1456 unit_file_list_free(h
);
1457 return log_error_errno(r
, "Failed to get unit file list: %m");
1460 n_units
= hashmap_size(h
);
1462 units
= new(UnitFileList
, n_units
?: 1); /* avoid malloc(0) */
1464 unit_file_list_free(h
);
1468 HASHMAP_FOREACH(u
, h
, i
) {
1469 if (!output_show_unit_file(u
, NULL
, NULL
))
1476 assert(c
<= n_units
);
1481 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
1482 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1485 r
= acquire_bus(BUS_MANAGER
, &bus
);
1489 r
= sd_bus_message_new_method_call(
1492 "org.freedesktop.systemd1",
1493 "/org/freedesktop/systemd1",
1494 "org.freedesktop.systemd1.Manager",
1495 "ListUnitFilesByPatterns");
1497 return bus_log_create_error(r
);
1499 r
= sd_bus_message_append_strv(m
, arg_states
);
1501 return bus_log_create_error(r
);
1503 r
= sd_bus_message_append_strv(m
, strv_skip(argv
, 1));
1505 return bus_log_create_error(r
);
1507 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
1508 if (r
< 0 && sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_METHOD
)) {
1509 /* Fallback to legacy ListUnitFiles method */
1511 log_debug_errno(r
, "Failed to list unit files: %s Falling back to ListUnitsFiles method.", bus_error_message(&error
, r
));
1512 m
= sd_bus_message_unref(m
);
1513 sd_bus_error_free(&error
);
1515 r
= sd_bus_message_new_method_call(
1518 "org.freedesktop.systemd1",
1519 "/org/freedesktop/systemd1",
1520 "org.freedesktop.systemd1.Manager",
1523 return bus_log_create_error(r
);
1525 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
1528 return log_error_errno(r
, "Failed to list unit files: %s", bus_error_message(&error
, r
));
1530 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
1532 return bus_log_parse_error(r
);
1534 while ((r
= sd_bus_message_read(reply
, "(ss)", &path
, &state
)) > 0) {
1536 if (!GREEDY_REALLOC(units
, size
, c
+ 1))
1539 units
[c
] = (struct UnitFileList
) {
1541 unit_file_state_from_string(state
)
1544 if (output_show_unit_file(&units
[c
],
1545 fallback
? arg_states
: NULL
,
1546 fallback
? strv_skip(argv
, 1) : NULL
))
1551 return bus_log_parse_error(r
);
1553 r
= sd_bus_message_exit_container(reply
);
1555 return bus_log_parse_error(r
);
1558 pager_open(arg_no_pager
, false);
1560 qsort_safe(units
, c
, sizeof(UnitFileList
), compare_unit_file_list
);
1561 output_unit_file_list(units
, c
);
1563 if (install_client_side())
1564 for (unit
= units
; unit
< units
+ c
; unit
++)
1570 static int list_dependencies_print(const char *name
, int level
, unsigned int branches
, bool last
) {
1571 _cleanup_free_
char *n
= NULL
;
1572 size_t max_len
= MAX(columns(),20u);
1578 for (i
= level
- 1; i
>= 0; i
--) {
1580 if (len
> max_len
- 3 && !arg_full
) {
1581 printf("%s...\n",max_len
% 2 ? "" : " ");
1584 printf("%s", special_glyph(branches
& (1 << i
) ? TREE_VERTICAL
: TREE_SPACE
));
1588 if (len
> max_len
- 3 && !arg_full
) {
1589 printf("%s...\n",max_len
% 2 ? "" : " ");
1593 printf("%s", special_glyph(last
? TREE_RIGHT
: TREE_BRANCH
));
1597 printf("%s\n", name
);
1601 n
= ellipsize(name
, max_len
-len
, 100);
1609 static int list_dependencies_get_dependencies(sd_bus
*bus
, const char *name
, char ***deps
) {
1611 static const char *dependencies
[_DEPENDENCY_MAX
] = {
1612 [DEPENDENCY_FORWARD
] = "Requires\0"
1617 [DEPENDENCY_REVERSE
] = "RequiredBy\0"
1622 [DEPENDENCY_AFTER
] = "After\0",
1623 [DEPENDENCY_BEFORE
] = "Before\0",
1626 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1627 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1628 _cleanup_strv_free_
char **ret
= NULL
;
1629 _cleanup_free_
char *path
= NULL
;
1635 assert_cc(ELEMENTSOF(dependencies
) == _DEPENDENCY_MAX
);
1637 path
= unit_dbus_path_from_name(name
);
1641 r
= sd_bus_call_method(
1643 "org.freedesktop.systemd1",
1645 "org.freedesktop.DBus.Properties",
1649 "s", "org.freedesktop.systemd1.Unit");
1651 return log_error_errno(r
, "Failed to get properties of %s: %s", name
, bus_error_message(&error
, r
));
1653 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
1655 return bus_log_parse_error(r
);
1657 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
1660 r
= sd_bus_message_read(reply
, "s", &prop
);
1662 return bus_log_parse_error(r
);
1664 if (!nulstr_contains(dependencies
[arg_dependency
], prop
)) {
1665 r
= sd_bus_message_skip(reply
, "v");
1667 return bus_log_parse_error(r
);
1670 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, "as");
1672 return bus_log_parse_error(r
);
1674 r
= bus_message_read_strv_extend(reply
, &ret
);
1676 return bus_log_parse_error(r
);
1678 r
= sd_bus_message_exit_container(reply
);
1680 return bus_log_parse_error(r
);
1683 r
= sd_bus_message_exit_container(reply
);
1685 return bus_log_parse_error(r
);
1689 return bus_log_parse_error(r
);
1691 r
= sd_bus_message_exit_container(reply
);
1693 return bus_log_parse_error(r
);
1701 static int list_dependencies_compare(const void *_a
, const void *_b
) {
1702 const char **a
= (const char**) _a
, **b
= (const char**) _b
;
1704 if (unit_name_to_type(*a
) == UNIT_TARGET
&& unit_name_to_type(*b
) != UNIT_TARGET
)
1706 if (unit_name_to_type(*a
) != UNIT_TARGET
&& unit_name_to_type(*b
) == UNIT_TARGET
)
1709 return strcasecmp(*a
, *b
);
1712 static int list_dependencies_one(
1717 unsigned int branches
) {
1719 _cleanup_strv_free_
char **deps
= NULL
;
1727 r
= strv_extend(units
, name
);
1731 r
= list_dependencies_get_dependencies(bus
, name
, &deps
);
1735 qsort_safe(deps
, strv_length(deps
), sizeof (char*), list_dependencies_compare
);
1737 STRV_FOREACH(c
, deps
) {
1738 if (strv_contains(*units
, *c
)) {
1740 r
= list_dependencies_print("...", level
+ 1, (branches
<< 1) | (c
[1] == NULL
? 0 : 1), 1);
1750 UnitActiveState active_state
= _UNIT_ACTIVE_STATE_INVALID
;
1753 (void) get_state_one_unit(bus
, *c
, &active_state
);
1755 switch (active_state
) {
1757 case UNIT_RELOADING
:
1758 case UNIT_ACTIVATING
:
1759 on
= ansi_highlight_green();
1763 case UNIT_DEACTIVATING
:
1768 on
= ansi_highlight_red();
1772 printf("%s%s%s ", on
, special_glyph(BLACK_CIRCLE
), ansi_normal());
1775 r
= list_dependencies_print(*c
, level
, branches
, c
[1] == NULL
);
1779 if (arg_all
|| unit_name_to_type(*c
) == UNIT_TARGET
) {
1780 r
= list_dependencies_one(bus
, *c
, level
+ 1, units
, (branches
<< 1) | (c
[1] == NULL
? 0 : 1));
1787 strv_remove(*units
, name
);
1792 static int list_dependencies(int argc
, char *argv
[], void *userdata
) {
1793 _cleanup_strv_free_
char **units
= NULL
;
1794 _cleanup_free_
char *unit
= NULL
;
1800 r
= unit_name_mangle(argv
[1], UNIT_NAME_NOGLOB
, &unit
);
1802 return log_error_errno(r
, "Failed to mangle unit name: %m");
1806 u
= SPECIAL_DEFAULT_TARGET
;
1808 r
= acquire_bus(BUS_MANAGER
, &bus
);
1812 pager_open(arg_no_pager
, false);
1816 return list_dependencies_one(bus
, u
, 0, &units
, 0);
1819 struct machine_info
{
1823 char *control_group
;
1824 uint32_t n_failed_units
;
1829 static const struct bus_properties_map machine_info_property_map
[] = {
1830 { "SystemState", "s", NULL
, offsetof(struct machine_info
, state
) },
1831 { "NJobs", "u", NULL
, offsetof(struct machine_info
, n_jobs
) },
1832 { "NFailedUnits", "u", NULL
, offsetof(struct machine_info
, n_failed_units
) },
1833 { "ControlGroup", "s", NULL
, offsetof(struct machine_info
, control_group
) },
1834 { "UserspaceTimestamp", "t", NULL
, offsetof(struct machine_info
, timestamp
) },
1838 static void machine_info_clear(struct machine_info
*info
) {
1843 free(info
->control_group
);
1847 static void free_machines_list(struct machine_info
*machine_infos
, int n
) {
1853 for (i
= 0; i
< n
; i
++)
1854 machine_info_clear(&machine_infos
[i
]);
1856 free(machine_infos
);
1859 static int compare_machine_info(const void *a
, const void *b
) {
1860 const struct machine_info
*u
= a
, *v
= b
;
1862 if (u
->is_host
!= v
->is_host
)
1863 return u
->is_host
> v
->is_host
? -1 : 1;
1865 return strcasecmp(u
->name
, v
->name
);
1868 static int get_machine_properties(sd_bus
*bus
, struct machine_info
*mi
) {
1869 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*container
= NULL
;
1875 r
= sd_bus_open_system_machine(&container
, mi
->name
);
1882 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, mi
);
1889 static bool output_show_machine(const char *name
, char **patterns
) {
1890 return strv_fnmatch_or_empty(patterns
, name
, FNM_NOESCAPE
);
1893 static int get_machine_list(
1895 struct machine_info
**_machine_infos
,
1898 struct machine_info
*machine_infos
= NULL
;
1899 _cleanup_strv_free_
char **m
= NULL
;
1900 _cleanup_free_
char *hn
= NULL
;
1905 hn
= gethostname_malloc();
1909 if (output_show_machine(hn
, patterns
)) {
1910 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1))
1913 machine_infos
[c
].is_host
= true;
1914 machine_infos
[c
].name
= hn
;
1917 get_machine_properties(bus
, &machine_infos
[c
]);
1921 r
= sd_get_machine_names(&m
);
1923 return log_error_errno(r
, "Failed to get machine list: %m");
1925 STRV_FOREACH(i
, m
) {
1926 _cleanup_free_
char *class = NULL
;
1928 if (!output_show_machine(*i
, patterns
))
1931 sd_machine_get_class(*i
, &class);
1932 if (!streq_ptr(class, "container"))
1935 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1)) {
1936 free_machines_list(machine_infos
, c
);
1940 machine_infos
[c
].is_host
= false;
1941 machine_infos
[c
].name
= strdup(*i
);
1942 if (!machine_infos
[c
].name
) {
1943 free_machines_list(machine_infos
, c
);
1947 get_machine_properties(NULL
, &machine_infos
[c
]);
1951 *_machine_infos
= machine_infos
;
1955 static void output_machines_list(struct machine_info
*machine_infos
, unsigned n
) {
1956 struct machine_info
*m
;
1959 namelen
= sizeof("NAME") - 1,
1960 statelen
= sizeof("STATE") - 1,
1961 failedlen
= sizeof("FAILED") - 1,
1962 jobslen
= sizeof("JOBS") - 1;
1964 assert(machine_infos
|| n
== 0);
1966 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
1967 namelen
= MAX(namelen
, strlen(m
->name
) + (m
->is_host
? sizeof(" (host)") - 1 : 0));
1968 statelen
= MAX(statelen
, m
->state
? strlen(m
->state
) : 0);
1969 failedlen
= MAX(failedlen
, DECIMAL_STR_WIDTH(m
->n_failed_units
));
1970 jobslen
= MAX(jobslen
, DECIMAL_STR_WIDTH(m
->n_jobs
));
1972 if (!arg_plain
&& !streq_ptr(m
->state
, "running"))
1976 if (!arg_no_legend
) {
1980 printf("%-*s %-*s %-*s %-*s\n",
1983 failedlen
, "FAILED",
1987 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
1988 const char *on_state
= "", *off_state
= "";
1989 const char *on_failed
= "", *off_failed
= "";
1990 bool circle
= false;
1992 if (streq_ptr(m
->state
, "degraded")) {
1993 on_state
= ansi_highlight_red();
1994 off_state
= ansi_normal();
1996 } else if (!streq_ptr(m
->state
, "running")) {
1997 on_state
= ansi_highlight_yellow();
1998 off_state
= ansi_normal();
2002 if (m
->n_failed_units
> 0) {
2003 on_failed
= ansi_highlight_red();
2004 off_failed
= ansi_normal();
2006 on_failed
= off_failed
= "";
2009 printf("%s%s%s ", on_state
, circle
? special_glyph(BLACK_CIRCLE
) : " ", off_state
);
2012 printf("%-*s (host) %s%-*s%s %s%*" PRIu32
"%s %*" PRIu32
"\n",
2013 (int) (namelen
- (sizeof(" (host)")-1)), strna(m
->name
),
2014 on_state
, statelen
, strna(m
->state
), off_state
,
2015 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
2016 jobslen
, m
->n_jobs
);
2018 printf("%-*s %s%-*s%s %s%*" PRIu32
"%s %*" PRIu32
"\n",
2019 namelen
, strna(m
->name
),
2020 on_state
, statelen
, strna(m
->state
), off_state
,
2021 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
2022 jobslen
, m
->n_jobs
);
2026 printf("\n%u machines listed.\n", n
);
2029 static int list_machines(int argc
, char *argv
[], void *userdata
) {
2030 struct machine_info
*machine_infos
= NULL
;
2034 if (geteuid() != 0) {
2035 log_error("Must be root.");
2039 r
= acquire_bus(BUS_MANAGER
, &bus
);
2043 r
= get_machine_list(bus
, &machine_infos
, strv_skip(argv
, 1));
2047 pager_open(arg_no_pager
, false);
2049 qsort_safe(machine_infos
, r
, sizeof(struct machine_info
), compare_machine_info
);
2050 output_machines_list(machine_infos
, r
);
2051 free_machines_list(machine_infos
, r
);
2056 static int get_default(int argc
, char *argv
[], void *userdata
) {
2057 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2058 _cleanup_free_
char *_path
= NULL
;
2062 if (install_client_side()) {
2063 r
= unit_file_get_default(arg_scope
, arg_root
, &_path
);
2065 return log_error_errno(r
, "Failed to get default target: %m");
2070 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2073 r
= acquire_bus(BUS_MANAGER
, &bus
);
2077 r
= sd_bus_call_method(
2079 "org.freedesktop.systemd1",
2080 "/org/freedesktop/systemd1",
2081 "org.freedesktop.systemd1.Manager",
2087 return log_error_errno(r
, "Failed to get default target: %s", bus_error_message(&error
, r
));
2089 r
= sd_bus_message_read(reply
, "s", &path
);
2091 return bus_log_parse_error(r
);
2095 printf("%s\n", path
);
2100 static int set_default(int argc
, char *argv
[], void *userdata
) {
2101 _cleanup_free_
char *unit
= NULL
;
2102 UnitFileChange
*changes
= NULL
;
2103 unsigned n_changes
= 0;
2109 r
= unit_name_mangle_with_suffix(argv
[1], UNIT_NAME_NOGLOB
, ".target", &unit
);
2111 return log_error_errno(r
, "Failed to mangle unit name: %m");
2113 if (install_client_side()) {
2114 r
= unit_file_set_default(arg_scope
, arg_root
, unit
, true, &changes
, &n_changes
);
2115 unit_file_dump_changes(r
, "set default", changes
, n_changes
, arg_quiet
);
2120 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2121 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2124 polkit_agent_open_if_enabled();
2126 r
= acquire_bus(BUS_MANAGER
, &bus
);
2130 r
= sd_bus_call_method(
2132 "org.freedesktop.systemd1",
2133 "/org/freedesktop/systemd1",
2134 "org.freedesktop.systemd1.Manager",
2140 return log_error_errno(r
, "Failed to set default target: %s", bus_error_message(&error
, r
));
2142 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
2146 /* Try to reload if enabled */
2148 r
= daemon_reload(argc
, argv
, userdata
);
2154 unit_file_changes_free(changes
, n_changes
);
2161 const char *name
, *type
, *state
;
2164 static void output_jobs_list(const struct job_info
* jobs
, unsigned n
, bool skipped
) {
2165 unsigned id_len
, unit_len
, type_len
, state_len
;
2166 const struct job_info
*j
;
2167 const char *on
, *off
;
2168 bool shorten
= false;
2170 assert(n
== 0 || jobs
);
2173 if (!arg_no_legend
) {
2174 on
= ansi_highlight_green();
2175 off
= ansi_normal();
2177 printf("%sNo jobs %s.%s\n", on
, skipped
? "listed" : "running", off
);
2182 pager_open(arg_no_pager
, false);
2184 id_len
= strlen("JOB");
2185 unit_len
= strlen("UNIT");
2186 type_len
= strlen("TYPE");
2187 state_len
= strlen("STATE");
2189 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2190 uint32_t id
= j
->id
;
2191 assert(j
->name
&& j
->type
&& j
->state
);
2193 id_len
= MAX(id_len
, DECIMAL_STR_WIDTH(id
));
2194 unit_len
= MAX(unit_len
, strlen(j
->name
));
2195 type_len
= MAX(type_len
, strlen(j
->type
));
2196 state_len
= MAX(state_len
, strlen(j
->state
));
2199 if (!arg_full
&& id_len
+ 1 + unit_len
+ type_len
+ 1 + state_len
> columns()) {
2200 unit_len
= MAX(33u, columns() - id_len
- type_len
- state_len
- 3);
2205 printf("%*s %-*s %-*s %-*s\n",
2209 state_len
, "STATE");
2211 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2212 _cleanup_free_
char *e
= NULL
;
2214 if (streq(j
->state
, "running")) {
2215 on
= ansi_highlight();
2216 off
= ansi_normal();
2220 e
= shorten
? ellipsize(j
->name
, unit_len
, 33) : NULL
;
2221 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2223 on
, unit_len
, e
? e
: j
->name
, off
,
2225 on
, state_len
, j
->state
, off
);
2228 if (!arg_no_legend
) {
2229 on
= ansi_highlight();
2230 off
= ansi_normal();
2232 printf("\n%s%u jobs listed%s.\n", on
, n
, off
);
2236 static bool output_show_job(struct job_info
*job
, char **patterns
) {
2237 return strv_fnmatch_or_empty(patterns
, job
->name
, FNM_NOESCAPE
);
2240 static int list_jobs(int argc
, char *argv
[], void *userdata
) {
2241 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2242 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2243 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2244 _cleanup_free_
struct job_info
*jobs
= NULL
;
2250 bool skipped
= false;
2252 r
= acquire_bus(BUS_MANAGER
, &bus
);
2256 r
= sd_bus_call_method(
2258 "org.freedesktop.systemd1",
2259 "/org/freedesktop/systemd1",
2260 "org.freedesktop.systemd1.Manager",
2266 return log_error_errno(r
, "Failed to list jobs: %s", bus_error_message(&error
, r
));
2268 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2270 return bus_log_parse_error(r
);
2272 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0) {
2273 struct job_info job
= { id
, name
, type
, state
};
2275 if (!output_show_job(&job
, strv_skip(argv
, 1))) {
2280 if (!GREEDY_REALLOC(jobs
, size
, c
+ 1))
2286 return bus_log_parse_error(r
);
2288 r
= sd_bus_message_exit_container(reply
);
2290 return bus_log_parse_error(r
);
2292 pager_open(arg_no_pager
, false);
2294 output_jobs_list(jobs
, c
, skipped
);
2298 static int cancel_job(int argc
, char *argv
[], void *userdata
) {
2304 return trivial_method(argc
, argv
, userdata
);
2306 r
= acquire_bus(BUS_MANAGER
, &bus
);
2310 polkit_agent_open_if_enabled();
2312 STRV_FOREACH(name
, strv_skip(argv
, 1)) {
2313 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2317 q
= safe_atou32(*name
, &id
);
2319 return log_error_errno(q
, "Failed to parse job id \"%s\": %m", *name
);
2321 q
= sd_bus_call_method(
2323 "org.freedesktop.systemd1",
2324 "/org/freedesktop/systemd1",
2325 "org.freedesktop.systemd1.Manager",
2331 log_error_errno(q
, "Failed to cancel job %"PRIu32
": %s", id
, bus_error_message(&error
, q
));
2340 static int need_daemon_reload(sd_bus
*bus
, const char *unit
) {
2341 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2345 /* We ignore all errors here, since this is used to show a
2348 /* We don't use unit_dbus_path_from_name() directly since we
2349 * don't want to load the unit if it isn't loaded. */
2351 r
= sd_bus_call_method(
2353 "org.freedesktop.systemd1",
2354 "/org/freedesktop/systemd1",
2355 "org.freedesktop.systemd1.Manager",
2363 r
= sd_bus_message_read(reply
, "o", &path
);
2367 r
= sd_bus_get_property_trivial(
2369 "org.freedesktop.systemd1",
2371 "org.freedesktop.systemd1.Unit",
2381 static void warn_unit_file_changed(const char *name
) {
2384 log_warning("%sWarning:%s %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
2385 ansi_highlight_red(),
2388 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user");
2391 static int unit_file_find_path(LookupPaths
*lp
, const char *unit_name
, char **unit_path
) {
2398 STRV_FOREACH(p
, lp
->search_path
) {
2399 _cleanup_free_
char *path
;
2401 path
= path_join(arg_root
, *p
, unit_name
);
2405 if (access(path
, F_OK
) == 0) {
2415 static int unit_find_paths(
2417 const char *unit_name
,
2419 char **fragment_path
,
2420 char ***dropin_paths
) {
2422 _cleanup_free_
char *path
= NULL
;
2423 _cleanup_strv_free_
char **dropins
= NULL
;
2427 * Finds where the unit is defined on disk. Returns 0 if the unit
2428 * is not found. Returns 1 if it is found, and sets
2429 * - the path to the unit in *path, if it exists on disk,
2430 * - and a strv of existing drop-ins in *dropins,
2431 * if the arg is not NULL and any dropins were found.
2435 assert(fragment_path
);
2438 if (!install_client_side() && !unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
2439 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2440 _cleanup_free_
char *unit
= NULL
;
2442 unit
= unit_dbus_path_from_name(unit_name
);
2446 r
= sd_bus_get_property_string(
2448 "org.freedesktop.systemd1",
2450 "org.freedesktop.systemd1.Unit",
2455 return log_error_errno(r
, "Failed to get FragmentPath: %s", bus_error_message(&error
, r
));
2458 r
= sd_bus_get_property_strv(
2460 "org.freedesktop.systemd1",
2462 "org.freedesktop.systemd1.Unit",
2467 return log_error_errno(r
, "Failed to get DropInPaths: %s", bus_error_message(&error
, r
));
2470 _cleanup_set_free_ Set
*names
;
2472 names
= set_new(NULL
);
2476 r
= set_put(names
, unit_name
);
2478 return log_error_errno(r
, "Failed to add unit name: %m");
2480 r
= unit_file_find_path(lp
, unit_name
, &path
);
2485 _cleanup_free_
char *template = NULL
;
2487 r
= unit_name_template(unit_name
, &template);
2488 if (r
< 0 && r
!= -EINVAL
)
2489 return log_error_errno(r
, "Failed to determine template name: %m");
2491 r
= unit_file_find_path(lp
, template, &path
);
2498 r
= unit_file_find_dropin_paths(lp
->search_path
, NULL
, names
, &dropins
);
2506 if (!isempty(path
)) {
2507 *fragment_path
= path
;
2512 if (dropin_paths
&& !strv_isempty(dropins
)) {
2513 *dropin_paths
= dropins
;
2518 if (r
== 0 && !arg_force
)
2519 log_error("No files found for %s.", unit_name
);
2524 static int get_state_one_unit(sd_bus
*bus
, const char *name
, UnitActiveState
*active_state
) {
2525 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2526 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2527 _cleanup_free_
char *buf
= NULL
;
2528 UnitActiveState state
;
2533 assert(active_state
);
2535 /* We don't use unit_dbus_path_from_name() directly since we don't want to load the unit unnecessarily, if it
2537 r
= sd_bus_call_method(
2539 "org.freedesktop.systemd1",
2540 "/org/freedesktop/systemd1",
2541 "org.freedesktop.systemd1.Manager",
2547 if (!sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_UNIT
))
2548 return log_error_errno(r
, "Failed to retrieve unit: %s", bus_error_message(&error
, r
));
2550 /* The unit is currently not loaded, hence say it's "inactive", since all units that aren't loaded are
2551 * considered inactive. */
2552 state
= UNIT_INACTIVE
;
2555 r
= sd_bus_message_read(reply
, "o", &path
);
2557 return bus_log_parse_error(r
);
2559 r
= sd_bus_get_property_string(
2561 "org.freedesktop.systemd1",
2563 "org.freedesktop.systemd1.Unit",
2568 return log_error_errno(r
, "Failed to retrieve unit state: %s", bus_error_message(&error
, r
));
2570 state
= unit_active_state_from_string(buf
);
2571 if (state
== _UNIT_ACTIVE_STATE_INVALID
) {
2572 log_error("Invalid unit state '%s' for: %s", buf
, name
);
2577 *active_state
= state
;
2581 static int check_triggering_units(
2585 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2586 _cleanup_free_
char *path
= NULL
, *n
= NULL
, *load_state
= NULL
;
2587 _cleanup_strv_free_
char **triggered_by
= NULL
;
2588 bool print_warning_label
= true;
2589 UnitActiveState active_state
;
2593 r
= unit_name_mangle(name
, UNIT_NAME_NOGLOB
, &n
);
2595 return log_error_errno(r
, "Failed to mangle unit name: %m");
2597 path
= unit_dbus_path_from_name(n
);
2601 r
= sd_bus_get_property_string(
2603 "org.freedesktop.systemd1",
2605 "org.freedesktop.systemd1.Unit",
2610 return log_error_errno(r
, "Failed to get load state of %s: %s", n
, bus_error_message(&error
, r
));
2612 if (streq(load_state
, "masked"))
2615 r
= sd_bus_get_property_strv(
2617 "org.freedesktop.systemd1",
2619 "org.freedesktop.systemd1.Unit",
2624 return log_error_errno(r
, "Failed to get triggered by array of %s: %s", n
, bus_error_message(&error
, r
));
2626 STRV_FOREACH(i
, triggered_by
) {
2627 r
= get_state_one_unit(bus
, *i
, &active_state
);
2631 if (!IN_SET(active_state
, UNIT_ACTIVE
, UNIT_RELOADING
))
2634 if (print_warning_label
) {
2635 log_warning("Warning: Stopping %s, but it can still be activated by:", n
);
2636 print_warning_label
= false;
2639 log_warning(" %s", *i
);
2645 static const struct {
2648 } unit_actions
[] = {
2649 { "start", "StartUnit" },
2650 { "stop", "StopUnit" },
2651 { "condstop", "StopUnit" },
2652 { "reload", "ReloadUnit" },
2653 { "restart", "RestartUnit" },
2654 { "try-restart", "TryRestartUnit" },
2655 { "condrestart", "TryRestartUnit" },
2656 { "reload-or-restart", "ReloadOrRestartUnit" },
2657 { "try-reload-or-restart", "ReloadOrTryRestartUnit" },
2658 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2659 { "condreload", "ReloadOrTryRestartUnit" },
2660 { "force-reload", "ReloadOrTryRestartUnit" }
2663 static const char *verb_to_method(const char *verb
) {
2666 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2667 if (streq_ptr(unit_actions
[i
].verb
, verb
))
2668 return unit_actions
[i
].method
;
2673 static const char *method_to_verb(const char *method
) {
2676 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2677 if (streq_ptr(unit_actions
[i
].method
, method
))
2678 return unit_actions
[i
].verb
;
2690 static void wait_context_free(WaitContext
*c
) {
2691 c
->match
= sd_bus_slot_unref(c
->match
);
2692 c
->event
= sd_event_unref(c
->event
);
2693 c
->unit_paths
= set_free(c
->unit_paths
);
2696 static int on_properties_changed(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
2697 WaitContext
*c
= userdata
;
2701 path
= sd_bus_message_get_path(m
);
2702 if (!set_contains(c
->unit_paths
, path
))
2705 /* Check if ActiveState changed to inactive/failed */
2706 /* (s interface, a{sv} changed_properties, as invalidated_properties) */
2707 r
= sd_bus_message_skip(m
, "s");
2709 return bus_log_parse_error(r
);
2710 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "{sv}");
2712 return bus_log_parse_error(r
);
2714 while ((r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
2718 r
= sd_bus_message_read(m
, "s", &s
);
2720 return bus_log_parse_error(r
);
2721 if (streq(s
, "ActiveState")) {
2722 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, "s");
2724 return bus_log_parse_error(r
);
2725 r
= sd_bus_message_read(m
, "s", &s
);
2727 return bus_log_parse_error(r
);
2728 is_failed
= streq(s
, "failed");
2729 if (streq(s
, "inactive") || is_failed
) {
2730 log_debug("%s became %s, dropping from --wait tracking", path
, s
);
2731 set_remove(c
->unit_paths
, path
);
2732 c
->any_failed
|= is_failed
;
2734 log_debug("ActiveState on %s changed to %s", path
, s
);
2735 break; /* no need to dissect the rest of the message */
2737 /* other property */
2738 r
= sd_bus_message_skip(m
, "v");
2740 return bus_log_parse_error(r
);
2742 r
= sd_bus_message_exit_container(m
);
2744 return bus_log_parse_error(r
);
2747 return bus_log_parse_error(r
);
2749 if (set_isempty(c
->unit_paths
))
2750 sd_event_exit(c
->event
, EXIT_SUCCESS
);
2755 static int start_unit_one(
2760 sd_bus_error
*error
,
2762 WaitContext
*wait_context
) {
2764 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2774 _cleanup_free_
char *unit_path
= NULL
;
2777 log_debug("Watching for property changes of %s", name
);
2778 r
= sd_bus_call_method(
2780 "org.freedesktop.systemd1",
2781 "/org/freedesktop/systemd1",
2782 "org.freedesktop.systemd1.Manager",
2788 return log_error_errno(r
, "Failed to RefUnit %s: %s", name
, bus_error_message(error
, r
));
2790 unit_path
= unit_dbus_path_from_name(name
);
2794 r
= set_put_strdup(wait_context
->unit_paths
, unit_path
);
2796 return log_error_errno(r
, "Failed to add unit path %s to set: %m", unit_path
);
2798 mt
= strjoina("type='signal',"
2799 "interface='org.freedesktop.DBus.Properties',"
2800 "path='", unit_path
, "',"
2801 "member='PropertiesChanged'");
2802 r
= sd_bus_add_match(bus
, &wait_context
->match
, mt
, on_properties_changed
, wait_context
);
2804 return log_error_errno(r
, "Failed to add match for PropertiesChanged signal: %m");
2807 log_debug("Calling manager for %s on %s, %s", method
, name
, mode
);
2809 r
= sd_bus_call_method(
2811 "org.freedesktop.systemd1",
2812 "/org/freedesktop/systemd1",
2813 "org.freedesktop.systemd1.Manager",
2821 /* There's always a fallback possible for legacy actions. */
2822 if (arg_action
!= ACTION_SYSTEMCTL
)
2825 verb
= method_to_verb(method
);
2827 log_error("Failed to %s %s: %s", verb
, name
, bus_error_message(error
, r
));
2829 if (!sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) &&
2830 !sd_bus_error_has_name(error
, BUS_ERROR_UNIT_MASKED
))
2831 log_error("See %s logs and 'systemctl%s status%s %s' for details.",
2832 arg_scope
== UNIT_FILE_SYSTEM
? "system" : "user",
2833 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user",
2834 name
[0] == '-' ? " --" : "",
2840 r
= sd_bus_message_read(reply
, "o", &path
);
2842 return bus_log_parse_error(r
);
2844 if (need_daemon_reload(bus
, name
) > 0)
2845 warn_unit_file_changed(name
);
2848 log_debug("Adding %s to the set", path
);
2849 r
= bus_wait_for_jobs_add(w
, path
);
2857 static int expand_names(sd_bus
*bus
, char **names
, const char* suffix
, char ***ret
) {
2858 _cleanup_strv_free_
char **mangled
= NULL
, **globs
= NULL
;
2865 STRV_FOREACH(name
, names
) {
2869 r
= unit_name_mangle_with_suffix(*name
, UNIT_NAME_GLOB
, suffix
, &t
);
2871 r
= unit_name_mangle(*name
, UNIT_NAME_GLOB
, &t
);
2873 return log_error_errno(r
, "Failed to mangle name: %m");
2875 if (string_is_glob(t
))
2876 r
= strv_consume(&globs
, t
);
2878 r
= strv_consume(&mangled
, t
);
2883 /* Query the manager only if any of the names are a glob, since
2884 * this is fairly expensive */
2885 if (!strv_isempty(globs
)) {
2886 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2887 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
2888 size_t allocated
, n
;
2890 r
= get_unit_list(bus
, NULL
, globs
, &unit_infos
, 0, &reply
);
2894 n
= strv_length(mangled
);
2897 for (i
= 0; i
< r
; i
++) {
2898 if (!GREEDY_REALLOC(mangled
, allocated
, n
+2))
2901 mangled
[n
] = strdup(unit_infos
[i
].id
);
2905 mangled
[++n
] = NULL
;
2910 mangled
= NULL
; /* do not free */
2915 static const struct {
2919 } action_table
[_ACTION_MAX
] = {
2920 [ACTION_HALT
] = { SPECIAL_HALT_TARGET
, "halt", "replace-irreversibly" },
2921 [ACTION_POWEROFF
] = { SPECIAL_POWEROFF_TARGET
, "poweroff", "replace-irreversibly" },
2922 [ACTION_REBOOT
] = { SPECIAL_REBOOT_TARGET
, "reboot", "replace-irreversibly" },
2923 [ACTION_KEXEC
] = { SPECIAL_KEXEC_TARGET
, "kexec", "replace-irreversibly" },
2924 [ACTION_RUNLEVEL2
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2925 [ACTION_RUNLEVEL3
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2926 [ACTION_RUNLEVEL4
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2927 [ACTION_RUNLEVEL5
] = { SPECIAL_GRAPHICAL_TARGET
, NULL
, "isolate" },
2928 [ACTION_RESCUE
] = { SPECIAL_RESCUE_TARGET
, "rescue", "isolate" },
2929 [ACTION_EMERGENCY
] = { SPECIAL_EMERGENCY_TARGET
, "emergency", "isolate" },
2930 [ACTION_DEFAULT
] = { SPECIAL_DEFAULT_TARGET
, "default", "isolate" },
2931 [ACTION_EXIT
] = { SPECIAL_EXIT_TARGET
, "exit", "replace-irreversibly" },
2932 [ACTION_SUSPEND
] = { SPECIAL_SUSPEND_TARGET
, "suspend", "replace-irreversibly" },
2933 [ACTION_HIBERNATE
] = { SPECIAL_HIBERNATE_TARGET
, "hibernate", "replace-irreversibly" },
2934 [ACTION_HYBRID_SLEEP
] = { SPECIAL_HYBRID_SLEEP_TARGET
, "hybrid-sleep", "replace-irreversibly" },
2937 static enum action
verb_to_action(const char *verb
) {
2940 for (i
= _ACTION_INVALID
; i
< _ACTION_MAX
; i
++)
2941 if (streq_ptr(action_table
[i
].verb
, verb
))
2944 return _ACTION_INVALID
;
2947 static int start_unit(int argc
, char *argv
[], void *userdata
) {
2948 _cleanup_(bus_wait_for_jobs_freep
) BusWaitForJobs
*w
= NULL
;
2949 const char *method
, *mode
, *one_name
, *suffix
= NULL
;
2950 _cleanup_strv_free_
char **names
= NULL
;
2952 _cleanup_(wait_context_free
) WaitContext wait_context
= {};
2956 if (arg_wait
&& !strstr(argv
[0], "start")) {
2957 log_error("--wait may only be used with a command that starts units.");
2961 /* we cannot do sender tracking on the private bus, so we need the full
2962 * one for RefUnit to implement --wait */
2963 r
= acquire_bus(arg_wait
? BUS_FULL
: BUS_MANAGER
, &bus
);
2967 ask_password_agent_open_if_enabled();
2968 polkit_agent_open_if_enabled();
2970 if (arg_action
== ACTION_SYSTEMCTL
) {
2973 method
= verb_to_method(argv
[0]);
2974 action
= verb_to_action(argv
[0]);
2976 if (streq(argv
[0], "isolate")) {
2980 mode
= action_table
[action
].mode
?: arg_job_mode
;
2982 one_name
= action_table
[action
].target
;
2984 assert(arg_action
< ELEMENTSOF(action_table
));
2985 assert(action_table
[arg_action
].target
);
2987 method
= "StartUnit";
2989 mode
= action_table
[arg_action
].mode
;
2990 one_name
= action_table
[arg_action
].target
;
2994 names
= strv_new(one_name
, NULL
);
2996 r
= expand_names(bus
, strv_skip(argv
, 1), suffix
, &names
);
2998 return log_error_errno(r
, "Failed to expand names: %m");
3001 if (!arg_no_block
) {
3002 r
= bus_wait_for_jobs_new(bus
, &w
);
3004 return log_error_errno(r
, "Could not watch jobs: %m");
3008 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3010 wait_context
.unit_paths
= set_new(&string_hash_ops
);
3011 if (!wait_context
.unit_paths
)
3014 r
= sd_bus_call_method(
3016 "org.freedesktop.systemd1",
3017 "/org/freedesktop/systemd1",
3018 "org.freedesktop.systemd1.Manager",
3023 return log_error_errno(r
, "Failed to enable subscription: %s", bus_error_message(&error
, r
));
3024 r
= sd_event_default(&wait_context
.event
);
3026 return log_error_errno(r
, "Failed to allocate event loop: %m");
3027 r
= sd_bus_attach_event(bus
, wait_context
.event
, 0);
3029 return log_error_errno(r
, "Failed to attach bus to event loop: %m");
3032 STRV_FOREACH(name
, names
) {
3033 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3036 q
= start_unit_one(bus
, method
, *name
, mode
, &error
, w
, arg_wait
? &wait_context
: NULL
);
3037 if (r
>= 0 && q
< 0)
3038 r
= translate_bus_error_to_exit_status(q
, &error
);
3041 if (!arg_no_block
) {
3042 int q
, arg_count
= 0;
3043 const char* extra_args
[4] = {};
3045 if (arg_scope
!= UNIT_FILE_SYSTEM
)
3046 extra_args
[arg_count
++] = "--user";
3048 assert(IN_SET(arg_transport
, BUS_TRANSPORT_LOCAL
, BUS_TRANSPORT_REMOTE
, BUS_TRANSPORT_MACHINE
));
3049 if (arg_transport
== BUS_TRANSPORT_REMOTE
) {
3050 extra_args
[arg_count
++] = "-H";
3051 extra_args
[arg_count
++] = arg_host
;
3052 } else if (arg_transport
== BUS_TRANSPORT_MACHINE
) {
3053 extra_args
[arg_count
++] = "-M";
3054 extra_args
[arg_count
++] = arg_host
;
3057 q
= bus_wait_for_jobs(w
, arg_quiet
, extra_args
);
3061 /* When stopping units, warn if they can still be triggered by
3062 * another active unit (socket, path, timer) */
3063 if (!arg_quiet
&& streq(method
, "StopUnit"))
3064 STRV_FOREACH(name
, names
)
3065 check_triggering_units(bus
, *name
);
3068 if (r
>= 0 && arg_wait
) {
3070 q
= sd_event_loop(wait_context
.event
);
3072 return log_error_errno(q
, "Failed to run event loop: %m");
3073 if (wait_context
.any_failed
)
3080 static int logind_set_wall_message(void) {
3082 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3084 _cleanup_free_
char *m
= NULL
;
3087 r
= acquire_bus(BUS_FULL
, &bus
);
3091 m
= strv_join(arg_wall
, " ");
3095 r
= sd_bus_call_method(
3097 "org.freedesktop.login1",
3098 "/org/freedesktop/login1",
3099 "org.freedesktop.login1.Manager",
3108 return log_warning_errno(r
, "Failed to set wall message, ignoring: %s", bus_error_message(&error
, r
));
3114 /* Ask systemd-logind, which might grant access to unprivileged users
3115 * through PolicyKit */
3116 static int logind_reboot(enum action a
) {
3118 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3119 const char *method
, *description
;
3123 r
= acquire_bus(BUS_FULL
, &bus
);
3131 description
= "reboot system";
3134 case ACTION_POWEROFF
:
3135 method
= "PowerOff";
3136 description
= "power off system";
3139 case ACTION_SUSPEND
:
3141 description
= "suspend system";
3144 case ACTION_HIBERNATE
:
3145 method
= "Hibernate";
3146 description
= "hibernate system";
3149 case ACTION_HYBRID_SLEEP
:
3150 method
= "HybridSleep";
3151 description
= "put system into hybrid sleep";
3158 polkit_agent_open_if_enabled();
3159 (void) logind_set_wall_message();
3161 r
= sd_bus_call_method(
3163 "org.freedesktop.login1",
3164 "/org/freedesktop/login1",
3165 "org.freedesktop.login1.Manager",
3169 "b", arg_ask_password
);
3171 return log_error_errno(r
, "Failed to %s via logind: %s", description
, bus_error_message(&error
, r
));
3179 static int logind_check_inhibitors(enum action a
) {
3181 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
3182 _cleanup_strv_free_
char **sessions
= NULL
;
3183 const char *what
, *who
, *why
, *mode
;
3190 if (arg_ignore_inhibitors
|| arg_force
> 0)
3202 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
3205 r
= acquire_bus(BUS_FULL
, &bus
);
3209 r
= sd_bus_call_method(
3211 "org.freedesktop.login1",
3212 "/org/freedesktop/login1",
3213 "org.freedesktop.login1.Manager",
3219 /* If logind is not around, then there are no inhibitors... */
3222 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssuu)");
3224 return bus_log_parse_error(r
);
3226 while ((r
= sd_bus_message_read(reply
, "(ssssuu)", &what
, &who
, &why
, &mode
, &uid
, &pid
)) > 0) {
3227 _cleanup_free_
char *comm
= NULL
, *user
= NULL
;
3228 _cleanup_strv_free_
char **sv
= NULL
;
3230 if (!streq(mode
, "block"))
3233 sv
= strv_split(what
, ":");
3237 if ((pid_t
) pid
< 0)
3238 return log_error_errno(ERANGE
, "Bad PID %"PRIu32
": %m", pid
);
3240 if (!strv_contains(sv
,
3245 ACTION_KEXEC
) ? "shutdown" : "sleep"))
3248 get_process_comm(pid
, &comm
);
3249 user
= uid_to_name(uid
);
3251 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT
" \"%s\", user %s), reason is \"%s\".",
3252 who
, (pid_t
) pid
, strna(comm
), strna(user
), why
);
3257 return bus_log_parse_error(r
);
3259 r
= sd_bus_message_exit_container(reply
);
3261 return bus_log_parse_error(r
);
3263 /* Check for current sessions */
3264 sd_get_sessions(&sessions
);
3265 STRV_FOREACH(s
, sessions
) {
3266 _cleanup_free_
char *type
= NULL
, *tty
= NULL
, *seat
= NULL
, *user
= NULL
, *service
= NULL
, *class = NULL
;
3268 if (sd_session_get_uid(*s
, &uid
) < 0 || uid
== getuid())
3271 if (sd_session_get_class(*s
, &class) < 0 || !streq(class, "user"))
3274 if (sd_session_get_type(*s
, &type
) < 0 || !STR_IN_SET(type
, "x11", "tty"))
3277 sd_session_get_tty(*s
, &tty
);
3278 sd_session_get_seat(*s
, &seat
);
3279 sd_session_get_service(*s
, &service
);
3280 user
= uid_to_name(uid
);
3282 log_warning("User %s is logged in on %s.", strna(user
), isempty(tty
) ? (isempty(seat
) ? strna(service
) : seat
) : tty
);
3289 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
3290 action_table
[a
].verb
);
3298 static int logind_prepare_firmware_setup(void) {
3300 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3304 r
= acquire_bus(BUS_FULL
, &bus
);
3308 r
= sd_bus_call_method(
3310 "org.freedesktop.login1",
3311 "/org/freedesktop/login1",
3312 "org.freedesktop.login1.Manager",
3313 "SetRebootToFirmwareSetup",
3318 return log_error_errno(r
, "Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error
, r
));
3322 log_error("Cannot remotely indicate to EFI to boot into setup mode.");
3327 static int prepare_firmware_setup(void) {
3330 if (!arg_firmware_setup
)
3333 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
3335 r
= efi_set_reboot_to_firmware(true);
3337 log_debug_errno(r
, "Cannot indicate to EFI to boot into setup mode, will retry via logind: %m");
3342 return logind_prepare_firmware_setup();
3345 static int set_exit_code(uint8_t code
) {
3346 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3350 r
= acquire_bus(BUS_MANAGER
, &bus
);
3354 r
= sd_bus_call_method(
3356 "org.freedesktop.systemd1",
3357 "/org/freedesktop/systemd1",
3358 "org.freedesktop.systemd1.Manager",
3364 return log_error_errno(r
, "Failed to set exit code: %s", bus_error_message(&error
, r
));
3369 static int start_special(int argc
, char *argv
[], void *userdata
) {
3375 a
= verb_to_action(argv
[0]);
3377 r
= logind_check_inhibitors(a
);
3381 if (arg_force
>= 2 && geteuid() != 0) {
3382 log_error("Must be root.");
3386 r
= prepare_firmware_setup();
3390 if (a
== ACTION_REBOOT
&& argc
> 1) {
3391 r
= update_reboot_parameter_and_warn(argv
[1]);
3395 } else if (a
== ACTION_EXIT
&& argc
> 1) {
3398 /* If the exit code is not given on the command line,
3399 * don't reset it to zero: just keep it as it might
3400 * have been set previously. */
3402 r
= safe_atou8(argv
[1], &code
);
3404 return log_error_errno(r
, "Invalid exit code.");
3406 r
= set_exit_code(code
);
3411 if (arg_force
>= 2 &&
3418 if (arg_force
>= 1 &&
3425 return trivial_method(argc
, argv
, userdata
);
3427 /* First try logind, to allow authentication with polkit */
3433 ACTION_HYBRID_SLEEP
)) {
3434 r
= logind_reboot(a
);
3437 if (IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
3438 /* requested operation is not supported or already in progress */
3441 /* On all other errors, try low-level operation */
3444 return start_unit(argc
, argv
, userdata
);
3447 static int start_system_special(int argc
, char *argv
[], void *userdata
) {
3448 /* Like start_special above, but raises an error when running in user mode */
3450 if (arg_scope
!= UNIT_FILE_SYSTEM
) {
3451 log_error("Bad action for %s mode.",
3452 arg_scope
== UNIT_FILE_GLOBAL
? "--global" : "--user");
3456 return start_special(argc
, argv
, userdata
);
3459 static int check_unit_generic(int code
, const UnitActiveState good_states
[], int nb_states
, char **args
) {
3460 _cleanup_strv_free_
char **names
= NULL
;
3461 UnitActiveState active_state
;
3467 r
= acquire_bus(BUS_MANAGER
, &bus
);
3471 r
= expand_names(bus
, args
, NULL
, &names
);
3473 return log_error_errno(r
, "Failed to expand names: %m");
3475 STRV_FOREACH(name
, names
) {
3476 r
= get_state_one_unit(bus
, *name
, &active_state
);
3481 puts(unit_active_state_to_string(active_state
));
3483 for (i
= 0; i
< nb_states
; ++i
)
3484 if (good_states
[i
] == active_state
)
3488 /* use the given return code for the case that we won't find
3489 * any unit which matches the list */
3490 return found
? 0 : code
;
3493 static int check_unit_active(int argc
, char *argv
[], void *userdata
) {
3494 const UnitActiveState states
[] = { UNIT_ACTIVE
, UNIT_RELOADING
};
3495 /* According to LSB: 3, "program is not running" */
3496 return check_unit_generic(EXIT_PROGRAM_NOT_RUNNING
, states
, ELEMENTSOF(states
), strv_skip(argv
, 1));
3499 static int check_unit_failed(int argc
, char *argv
[], void *userdata
) {
3500 const UnitActiveState states
[] = { UNIT_FAILED
};
3501 return check_unit_generic(EXIT_PROGRAM_DEAD_AND_PID_EXISTS
, states
, ELEMENTSOF(states
), strv_skip(argv
, 1));
3504 static int kill_unit(int argc
, char *argv
[], void *userdata
) {
3505 _cleanup_strv_free_
char **names
= NULL
;
3506 char *kill_who
= NULL
, **name
;
3510 r
= acquire_bus(BUS_MANAGER
, &bus
);
3514 polkit_agent_open_if_enabled();
3517 arg_kill_who
= "all";
3519 /* --fail was specified */
3520 if (streq(arg_job_mode
, "fail"))
3521 kill_who
= strjoina(arg_kill_who
, "-fail");
3523 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
3525 return log_error_errno(r
, "Failed to expand names: %m");
3527 STRV_FOREACH(name
, names
) {
3528 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3530 q
= sd_bus_call_method(
3532 "org.freedesktop.systemd1",
3533 "/org/freedesktop/systemd1",
3534 "org.freedesktop.systemd1.Manager",
3538 "ssi", *name
, kill_who
? kill_who
: arg_kill_who
, arg_signal
);
3540 log_error_errno(q
, "Failed to kill unit %s: %s", *name
, bus_error_message(&error
, q
));
3549 typedef struct ExecStatusInfo
{
3557 usec_t start_timestamp
;
3558 usec_t exit_timestamp
;
3563 LIST_FIELDS(struct ExecStatusInfo
, exec
);
3566 static void exec_status_info_free(ExecStatusInfo
*i
) {
3575 static int exec_status_info_deserialize(sd_bus_message
*m
, ExecStatusInfo
*i
) {
3576 uint64_t start_timestamp
, exit_timestamp
, start_timestamp_monotonic
, exit_timestamp_monotonic
;
3579 int32_t code
, status
;
3585 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_STRUCT
, "sasbttttuii");
3587 return bus_log_parse_error(r
);
3591 r
= sd_bus_message_read(m
, "s", &path
);
3593 return bus_log_parse_error(r
);
3595 i
->path
= strdup(path
);
3599 r
= sd_bus_message_read_strv(m
, &i
->argv
);
3601 return bus_log_parse_error(r
);
3603 r
= sd_bus_message_read(m
,
3606 &start_timestamp
, &start_timestamp_monotonic
,
3607 &exit_timestamp
, &exit_timestamp_monotonic
,
3611 return bus_log_parse_error(r
);
3614 i
->start_timestamp
= (usec_t
) start_timestamp
;
3615 i
->exit_timestamp
= (usec_t
) exit_timestamp
;
3616 i
->pid
= (pid_t
) pid
;
3620 r
= sd_bus_message_exit_container(m
);
3622 return bus_log_parse_error(r
);
3627 typedef struct UnitCondition
{
3634 LIST_FIELDS(struct UnitCondition
, conditions
);
3637 static void unit_condition_free(UnitCondition
*c
) {
3646 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitCondition
*, unit_condition_free
);
3648 typedef struct UnitStatusInfo
{
3650 const char *load_state
;
3651 const char *active_state
;
3652 const char *sub_state
;
3653 const char *unit_file_state
;
3654 const char *unit_file_preset
;
3656 const char *description
;
3657 const char *following
;
3659 char **documentation
;
3661 const char *fragment_path
;
3662 const char *source_path
;
3663 const char *control_group
;
3665 char **dropin_paths
;
3667 const char *load_error
;
3670 usec_t inactive_exit_timestamp
;
3671 usec_t inactive_exit_timestamp_monotonic
;
3672 usec_t active_enter_timestamp
;
3673 usec_t active_exit_timestamp
;
3674 usec_t inactive_enter_timestamp
;
3676 bool need_daemon_reload
;
3682 const char *status_text
;
3683 const char *pid_file
;
3687 usec_t start_timestamp
;
3688 usec_t exit_timestamp
;
3690 int exit_code
, exit_status
;
3692 usec_t condition_timestamp
;
3693 bool condition_result
;
3694 LIST_HEAD(UnitCondition
, conditions
);
3696 usec_t assert_timestamp
;
3698 bool failed_assert_trigger
;
3699 bool failed_assert_negate
;
3700 const char *failed_assert
;
3701 const char *failed_assert_parameter
;
3704 unsigned n_accepted
;
3705 unsigned n_connections
;
3708 /* Pairs of type, path */
3712 const char *sysfs_path
;
3714 /* Mount, Automount */
3721 uint64_t memory_current
;
3722 uint64_t memory_low
;
3723 uint64_t memory_high
;
3724 uint64_t memory_max
;
3725 uint64_t memory_swap_max
;
3726 uint64_t memory_limit
;
3727 uint64_t cpu_usage_nsec
;
3728 uint64_t tasks_current
;
3731 LIST_HEAD(ExecStatusInfo
, exec
);
3734 static void unit_status_info_free(UnitStatusInfo
*info
) {
3738 strv_free(info
->documentation
);
3739 strv_free(info
->dropin_paths
);
3740 strv_free(info
->listen
);
3742 while ((c
= info
->conditions
)) {
3743 LIST_REMOVE(conditions
, info
->conditions
, c
);
3744 unit_condition_free(c
);
3747 while ((p
= info
->exec
)) {
3748 LIST_REMOVE(exec
, info
->exec
, p
);
3749 exec_status_info_free(p
);
3753 static void print_status_info(
3759 const char *active_on
, *active_off
, *on
, *off
, *ss
;
3761 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], *s1
;
3762 char since2
[FORMAT_TIMESTAMP_MAX
], *s2
;
3769 /* This shows pretty information about a unit. See
3770 * print_property() for a low-level property printer */
3772 if (streq_ptr(i
->active_state
, "failed")) {
3773 active_on
= ansi_highlight_red();
3774 active_off
= ansi_normal();
3775 } else if (STRPTR_IN_SET(i
->active_state
, "active", "reloading")) {
3776 active_on
= ansi_highlight_green();
3777 active_off
= ansi_normal();
3779 active_on
= active_off
= "";
3781 printf("%s%s%s %s", active_on
, special_glyph(BLACK_CIRCLE
), active_off
, strna(i
->id
));
3783 if (i
->description
&& !streq_ptr(i
->id
, i
->description
))
3784 printf(" - %s", i
->description
);
3789 printf(" Follow: unit currently follows state of %s\n", i
->following
);
3791 if (streq_ptr(i
->load_state
, "error")) {
3792 on
= ansi_highlight_red();
3793 off
= ansi_normal();
3797 path
= i
->source_path
? i
->source_path
: i
->fragment_path
;
3799 if (i
->load_error
!= 0)
3800 printf(" Loaded: %s%s%s (Reason: %s)\n",
3801 on
, strna(i
->load_state
), off
, i
->load_error
);
3802 else if (path
&& !isempty(i
->unit_file_state
) && !isempty(i
->unit_file_preset
))
3803 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
3804 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
, i
->unit_file_preset
);
3805 else if (path
&& !isempty(i
->unit_file_state
))
3806 printf(" Loaded: %s%s%s (%s; %s)\n",
3807 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
);
3809 printf(" Loaded: %s%s%s (%s)\n",
3810 on
, strna(i
->load_state
), off
, path
);
3812 printf(" Loaded: %s%s%s\n",
3813 on
, strna(i
->load_state
), off
);
3816 printf("Transient: yes\n");
3818 if (!strv_isempty(i
->dropin_paths
)) {
3819 _cleanup_free_
char *dir
= NULL
;
3823 STRV_FOREACH(dropin
, i
->dropin_paths
) {
3824 if (! dir
|| last
) {
3825 printf(dir
? " " : " Drop-In: ");
3829 dir
= dirname_malloc(*dropin
);
3835 printf("%s\n %s", dir
,
3836 special_glyph(TREE_RIGHT
));
3839 last
= ! (*(dropin
+ 1) && startswith(*(dropin
+ 1), dir
));
3841 printf("%s%s", basename(*dropin
), last
? "\n" : ", ");
3845 ss
= streq_ptr(i
->active_state
, i
->sub_state
) ? NULL
: i
->sub_state
;
3847 printf(" Active: %s%s (%s)%s",
3848 active_on
, strna(i
->active_state
), ss
, active_off
);
3850 printf(" Active: %s%s%s",
3851 active_on
, strna(i
->active_state
), active_off
);
3853 if (!isempty(i
->result
) && !streq(i
->result
, "success"))
3854 printf(" (Result: %s)", i
->result
);
3856 timestamp
= STRPTR_IN_SET(i
->active_state
, "active", "reloading") ? i
->active_enter_timestamp
:
3857 STRPTR_IN_SET(i
->active_state
, "inactive", "failed") ? i
->inactive_enter_timestamp
:
3858 STRPTR_IN_SET(i
->active_state
, "activating") ? i
->inactive_exit_timestamp
:
3859 i
->active_exit_timestamp
;
3861 s1
= format_timestamp_relative(since1
, sizeof(since1
), timestamp
);
3862 s2
= format_timestamp(since2
, sizeof(since2
), timestamp
);
3865 printf(" since %s; %s\n", s2
, s1
);
3867 printf(" since %s\n", s2
);
3871 if (!i
->condition_result
&& i
->condition_timestamp
> 0) {
3875 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->condition_timestamp
);
3876 s2
= format_timestamp(since2
, sizeof(since2
), i
->condition_timestamp
);
3878 printf("Condition: start %scondition failed%s at %s%s%s\n",
3879 ansi_highlight_yellow(), ansi_normal(),
3880 s2
, s1
? "; " : "", strempty(s1
));
3882 LIST_FOREACH(conditions
, c
, i
->conditions
)
3883 if (c
->tristate
< 0)
3886 LIST_FOREACH(conditions
, c
, i
->conditions
)
3887 if (c
->tristate
< 0)
3888 printf(" %s %s=%s%s%s was not met\n",
3889 --n
? special_glyph(TREE_BRANCH
) : special_glyph(TREE_RIGHT
),
3891 c
->trigger
? "|" : "",
3892 c
->negate
? "!" : "",
3896 if (!i
->assert_result
&& i
->assert_timestamp
> 0) {
3897 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->assert_timestamp
);
3898 s2
= format_timestamp(since2
, sizeof(since2
), i
->assert_timestamp
);
3900 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
3901 ansi_highlight_red(), ansi_normal(),
3902 s2
, s1
? "; " : "", strempty(s1
));
3903 if (i
->failed_assert_trigger
)
3904 printf(" none of the trigger assertions were met\n");
3905 else if (i
->failed_assert
)
3906 printf(" %s=%s%s was not met\n",
3908 i
->failed_assert_negate
? "!" : "",
3909 i
->failed_assert_parameter
);
3913 printf(" Device: %s\n", i
->sysfs_path
);
3915 printf(" Where: %s\n", i
->where
);
3917 printf(" What: %s\n", i
->what
);
3919 STRV_FOREACH(t
, i
->documentation
)
3920 printf(" %*s %s\n", 9, t
== i
->documentation
? "Docs:" : "", *t
);
3922 STRV_FOREACH_PAIR(t
, t2
, i
->listen
)
3923 printf(" %*s %s (%s)\n", 9, t
== i
->listen
? "Listen:" : "", *t2
, *t
);
3926 printf(" Accepted: %u; Connected: %u\n", i
->n_accepted
, i
->n_connections
);
3928 LIST_FOREACH(exec
, p
, i
->exec
) {
3929 _cleanup_free_
char *argv
= NULL
;
3932 /* Only show exited processes here */
3936 argv
= strv_join(p
->argv
, " ");
3937 printf(" Process: "PID_FMT
" %s=%s ", p
->pid
, p
->name
, strna(argv
));
3939 good
= is_clean_exit_lsb(p
->code
, p
->status
, NULL
);
3941 on
= ansi_highlight_red();
3942 off
= ansi_normal();
3946 printf("%s(code=%s, ", on
, sigchld_code_to_string(p
->code
));
3948 if (p
->code
== CLD_EXITED
) {
3951 printf("status=%i", p
->status
);
3953 c
= exit_status_to_string(p
->status
, EXIT_STATUS_SYSTEMD
);
3958 printf("signal=%s", signal_to_string(p
->status
));
3960 printf(")%s\n", off
);
3962 if (i
->main_pid
== p
->pid
&&
3963 i
->start_timestamp
== p
->start_timestamp
&&
3964 i
->exit_timestamp
== p
->start_timestamp
)
3965 /* Let's not show this twice */
3968 if (p
->pid
== i
->control_pid
)
3972 if (i
->main_pid
> 0 || i
->control_pid
> 0) {
3973 if (i
->main_pid
> 0) {
3974 printf(" Main PID: "PID_FMT
, i
->main_pid
);
3977 _cleanup_free_
char *comm
= NULL
;
3978 (void) get_process_comm(i
->main_pid
, &comm
);
3980 printf(" (%s)", comm
);
3981 } else if (i
->exit_code
> 0) {
3982 printf(" (code=%s, ", sigchld_code_to_string(i
->exit_code
));
3984 if (i
->exit_code
== CLD_EXITED
) {
3987 printf("status=%i", i
->exit_status
);
3989 c
= exit_status_to_string(i
->exit_status
, EXIT_STATUS_SYSTEMD
);
3994 printf("signal=%s", signal_to_string(i
->exit_status
));
3999 if (i
->control_pid
> 0) {
4000 _cleanup_free_
char *c
= NULL
;
4002 if (i
->main_pid
> 0)
4003 fputs("; Control PID: ", stdout
);
4005 fputs("Cntrl PID: ", stdout
); /* if first in column, abbreviated so it fits alignment */
4007 printf(PID_FMT
, i
->control_pid
);
4009 (void) get_process_comm(i
->control_pid
, &c
);
4018 printf(" Status: \"%s\"\n", i
->status_text
);
4019 if (i
->status_errno
> 0)
4020 printf(" Error: %i (%s)\n", i
->status_errno
, strerror(i
->status_errno
));
4022 if (i
->tasks_current
!= (uint64_t) -1) {
4023 printf(" Tasks: %" PRIu64
, i
->tasks_current
);
4025 if (i
->tasks_max
!= (uint64_t) -1)
4026 printf(" (limit: %" PRIu64
")\n", i
->tasks_max
);
4031 if (i
->memory_current
!= (uint64_t) -1) {
4032 char buf
[FORMAT_BYTES_MAX
];
4034 printf(" Memory: %s", format_bytes(buf
, sizeof(buf
), i
->memory_current
));
4036 if (i
->memory_low
> 0 || i
->memory_high
!= CGROUP_LIMIT_MAX
||
4037 i
->memory_max
!= CGROUP_LIMIT_MAX
|| i
->memory_swap_max
!= CGROUP_LIMIT_MAX
||
4038 i
->memory_limit
!= CGROUP_LIMIT_MAX
) {
4039 const char *prefix
= "";
4042 if (i
->memory_low
> 0) {
4043 printf("%slow: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_low
));
4046 if (i
->memory_high
!= CGROUP_LIMIT_MAX
) {
4047 printf("%shigh: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_high
));
4050 if (i
->memory_max
!= CGROUP_LIMIT_MAX
) {
4051 printf("%smax: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_max
));
4054 if (i
->memory_swap_max
!= CGROUP_LIMIT_MAX
) {
4055 printf("%sswap max: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_swap_max
));
4058 if (i
->memory_limit
!= CGROUP_LIMIT_MAX
) {
4059 printf("%slimit: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_limit
));
4067 if (i
->cpu_usage_nsec
!= (uint64_t) -1) {
4068 char buf
[FORMAT_TIMESPAN_MAX
];
4069 printf(" CPU: %s\n", format_timespan(buf
, sizeof(buf
), i
->cpu_usage_nsec
/ NSEC_PER_USEC
, USEC_PER_MSEC
));
4072 if (i
->control_group
) {
4073 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
4074 static const char prefix
[] = " ";
4077 printf(" CGroup: %s\n", i
->control_group
);
4080 if (c
> sizeof(prefix
) - 1)
4081 c
-= sizeof(prefix
) - 1;
4085 r
= unit_show_processes(bus
, i
->id
, i
->control_group
, prefix
, c
, get_output_flags(), &error
);
4090 /* Fallback for older systemd versions where the GetUnitProcesses() call is not yet available */
4092 if (i
->main_pid
> 0)
4093 extra
[k
++] = i
->main_pid
;
4095 if (i
->control_pid
> 0)
4096 extra
[k
++] = i
->control_pid
;
4098 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, prefix
, c
, extra
, k
, get_output_flags());
4100 log_warning_errno(r
, "Failed to dump process list, ignoring: %s", bus_error_message(&error
, r
));
4103 if (i
->id
&& arg_transport
== BUS_TRANSPORT_LOCAL
)
4104 show_journal_by_unit(
4109 i
->inactive_exit_timestamp_monotonic
,
4112 get_output_flags() | OUTPUT_BEGIN_NEWLINE
,
4113 SD_JOURNAL_LOCAL_ONLY
,
4114 arg_scope
== UNIT_FILE_SYSTEM
,
4117 if (i
->need_daemon_reload
)
4118 warn_unit_file_changed(i
->id
);
4121 static void show_unit_help(UnitStatusInfo
*i
) {
4126 if (!i
->documentation
) {
4127 log_info("Documentation for %s not known.", i
->id
);
4131 STRV_FOREACH(p
, i
->documentation
)
4132 if (startswith(*p
, "man:"))
4133 show_man_page(*p
+ 4, false);
4135 log_info("Can't show: %s", *p
);
4138 static int status_property(const char *name
, sd_bus_message
*m
, UnitStatusInfo
*i
, const char *contents
) {
4145 switch (contents
[0]) {
4147 case SD_BUS_TYPE_STRING
: {
4150 r
= sd_bus_message_read(m
, "s", &s
);
4152 return bus_log_parse_error(r
);
4155 if (streq(name
, "Id"))
4157 else if (streq(name
, "LoadState"))
4159 else if (streq(name
, "ActiveState"))
4160 i
->active_state
= s
;
4161 else if (streq(name
, "SubState"))
4163 else if (streq(name
, "Description"))
4165 else if (streq(name
, "FragmentPath"))
4166 i
->fragment_path
= s
;
4167 else if (streq(name
, "SourcePath"))
4170 else if (streq(name
, "DefaultControlGroup")) {
4172 e
= startswith(s
, SYSTEMD_CGROUP_CONTROLLER
":");
4174 i
->control_group
= e
;
4177 else if (streq(name
, "ControlGroup"))
4178 i
->control_group
= s
;
4179 else if (streq(name
, "StatusText"))
4181 else if (streq(name
, "PIDFile"))
4183 else if (streq(name
, "SysFSPath"))
4185 else if (streq(name
, "Where"))
4187 else if (streq(name
, "What"))
4189 else if (streq(name
, "Following"))
4191 else if (streq(name
, "UnitFileState"))
4192 i
->unit_file_state
= s
;
4193 else if (streq(name
, "UnitFilePreset"))
4194 i
->unit_file_preset
= s
;
4195 else if (streq(name
, "Result"))
4202 case SD_BUS_TYPE_BOOLEAN
: {
4205 r
= sd_bus_message_read(m
, "b", &b
);
4207 return bus_log_parse_error(r
);
4209 if (streq(name
, "Accept"))
4211 else if (streq(name
, "NeedDaemonReload"))
4212 i
->need_daemon_reload
= b
;
4213 else if (streq(name
, "ConditionResult"))
4214 i
->condition_result
= b
;
4215 else if (streq(name
, "AssertResult"))
4216 i
->assert_result
= b
;
4217 else if (streq(name
, "Transient"))
4223 case SD_BUS_TYPE_UINT32
: {
4226 r
= sd_bus_message_read(m
, "u", &u
);
4228 return bus_log_parse_error(r
);
4230 if (streq(name
, "MainPID")) {
4232 i
->main_pid
= (pid_t
) u
;
4235 } else if (streq(name
, "ControlPID"))
4236 i
->control_pid
= (pid_t
) u
;
4237 else if (streq(name
, "ExecMainPID")) {
4239 i
->main_pid
= (pid_t
) u
;
4240 } else if (streq(name
, "NAccepted"))
4242 else if (streq(name
, "NConnections"))
4243 i
->n_connections
= u
;
4248 case SD_BUS_TYPE_INT32
: {
4251 r
= sd_bus_message_read(m
, "i", &j
);
4253 return bus_log_parse_error(r
);
4255 if (streq(name
, "ExecMainCode"))
4256 i
->exit_code
= (int) j
;
4257 else if (streq(name
, "ExecMainStatus"))
4258 i
->exit_status
= (int) j
;
4259 else if (streq(name
, "StatusErrno"))
4260 i
->status_errno
= (int) j
;
4265 case SD_BUS_TYPE_UINT64
: {
4268 r
= sd_bus_message_read(m
, "t", &u
);
4270 return bus_log_parse_error(r
);
4272 if (streq(name
, "ExecMainStartTimestamp"))
4273 i
->start_timestamp
= (usec_t
) u
;
4274 else if (streq(name
, "ExecMainExitTimestamp"))
4275 i
->exit_timestamp
= (usec_t
) u
;
4276 else if (streq(name
, "ActiveEnterTimestamp"))
4277 i
->active_enter_timestamp
= (usec_t
) u
;
4278 else if (streq(name
, "InactiveEnterTimestamp"))
4279 i
->inactive_enter_timestamp
= (usec_t
) u
;
4280 else if (streq(name
, "InactiveExitTimestamp"))
4281 i
->inactive_exit_timestamp
= (usec_t
) u
;
4282 else if (streq(name
, "InactiveExitTimestampMonotonic"))
4283 i
->inactive_exit_timestamp_monotonic
= (usec_t
) u
;
4284 else if (streq(name
, "ActiveExitTimestamp"))
4285 i
->active_exit_timestamp
= (usec_t
) u
;
4286 else if (streq(name
, "ConditionTimestamp"))
4287 i
->condition_timestamp
= (usec_t
) u
;
4288 else if (streq(name
, "AssertTimestamp"))
4289 i
->assert_timestamp
= (usec_t
) u
;
4290 else if (streq(name
, "MemoryCurrent"))
4291 i
->memory_current
= u
;
4292 else if (streq(name
, "MemoryLow"))
4294 else if (streq(name
, "MemoryHigh"))
4296 else if (streq(name
, "MemoryMax"))
4298 else if (streq(name
, "MemorySwapMax"))
4299 i
->memory_swap_max
= u
;
4300 else if (streq(name
, "MemoryLimit"))
4301 i
->memory_limit
= u
;
4302 else if (streq(name
, "TasksCurrent"))
4303 i
->tasks_current
= u
;
4304 else if (streq(name
, "TasksMax"))
4306 else if (streq(name
, "CPUUsageNSec"))
4307 i
->cpu_usage_nsec
= u
;
4312 case SD_BUS_TYPE_ARRAY
:
4314 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
4315 _cleanup_free_ ExecStatusInfo
*info
= NULL
;
4317 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4319 return bus_log_parse_error(r
);
4321 info
= new0(ExecStatusInfo
, 1);
4325 while ((r
= exec_status_info_deserialize(m
, info
)) > 0) {
4327 info
->name
= strdup(name
);
4331 LIST_PREPEND(exec
, i
->exec
, info
);
4333 info
= new0(ExecStatusInfo
, 1);
4339 return bus_log_parse_error(r
);
4341 r
= sd_bus_message_exit_container(m
);
4343 return bus_log_parse_error(r
);
4347 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
4348 const char *type
, *path
;
4350 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4352 return bus_log_parse_error(r
);
4354 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0) {
4356 r
= strv_extend(&i
->listen
, type
);
4360 r
= strv_extend(&i
->listen
, path
);
4365 return bus_log_parse_error(r
);
4367 r
= sd_bus_message_exit_container(m
);
4369 return bus_log_parse_error(r
);
4373 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "DropInPaths")) {
4375 r
= sd_bus_message_read_strv(m
, &i
->dropin_paths
);
4377 return bus_log_parse_error(r
);
4379 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Documentation")) {
4381 r
= sd_bus_message_read_strv(m
, &i
->documentation
);
4383 return bus_log_parse_error(r
);
4385 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Conditions")) {
4386 const char *cond
, *param
;
4387 int trigger
, negate
;
4390 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
4392 return bus_log_parse_error(r
);
4394 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
4395 _cleanup_(unit_condition_freep
) UnitCondition
*c
= NULL
;
4397 log_debug("%s trigger=%d negate=%d %s →%d", cond
, trigger
, negate
, param
, state
);
4399 c
= new0(UnitCondition
, 1);
4403 c
->name
= strdup(cond
);
4404 c
->param
= strdup(param
);
4405 if (!c
->name
|| !c
->param
)
4408 c
->trigger
= trigger
;
4410 c
->tristate
= state
;
4412 LIST_PREPEND(conditions
, i
->conditions
, c
);
4416 return bus_log_parse_error(r
);
4418 r
= sd_bus_message_exit_container(m
);
4420 return bus_log_parse_error(r
);
4422 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Asserts")) {
4423 const char *cond
, *param
;
4424 int trigger
, negate
;
4427 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
4429 return bus_log_parse_error(r
);
4431 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
4432 log_debug("%s %d %d %s %d", cond
, trigger
, negate
, param
, state
);
4433 if (state
< 0 && (!trigger
|| !i
->failed_assert
)) {
4434 i
->failed_assert
= cond
;
4435 i
->failed_assert_trigger
= trigger
;
4436 i
->failed_assert_negate
= negate
;
4437 i
->failed_assert_parameter
= param
;
4441 return bus_log_parse_error(r
);
4443 r
= sd_bus_message_exit_container(m
);
4445 return bus_log_parse_error(r
);
4452 case SD_BUS_TYPE_STRUCT_BEGIN
:
4454 if (streq(name
, "LoadError")) {
4455 const char *n
, *message
;
4457 r
= sd_bus_message_read(m
, "(ss)", &n
, &message
);
4459 return bus_log_parse_error(r
);
4461 if (!isempty(message
))
4462 i
->load_error
= message
;
4475 r
= sd_bus_message_skip(m
, contents
);
4477 return bus_log_parse_error(r
);
4482 #define print_prop(name, fmt, ...) \
4485 printf(fmt "\n", __VA_ARGS__); \
4487 printf("%s=" fmt "\n", name, __VA_ARGS__); \
4490 static int print_property(const char *name
, sd_bus_message
*m
, const char *contents
) {
4496 /* This is a low-level property printer, see
4497 * print_status_info() for the nicer output */
4499 if (arg_properties
&& !strv_find(arg_properties
, name
)) {
4500 /* skip what we didn't read */
4501 r
= sd_bus_message_skip(m
, contents
);
4505 switch (contents
[0]) {
4507 case SD_BUS_TYPE_STRUCT_BEGIN
:
4509 if (contents
[1] == SD_BUS_TYPE_UINT32
&& streq(name
, "Job")) {
4512 r
= sd_bus_message_read(m
, "(uo)", &u
, NULL
);
4514 return bus_log_parse_error(r
);
4517 print_prop(name
, "%"PRIu32
, u
);
4519 print_prop(name
, "%s", "");
4523 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Unit")) {
4526 r
= sd_bus_message_read(m
, "(so)", &s
, NULL
);
4528 return bus_log_parse_error(r
);
4530 if (arg_all
|| !isempty(s
))
4531 print_prop(name
, "%s", s
);
4535 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "LoadError")) {
4536 const char *a
= NULL
, *b
= NULL
;
4538 r
= sd_bus_message_read(m
, "(ss)", &a
, &b
);
4540 return bus_log_parse_error(r
);
4542 if (arg_all
|| !isempty(a
) || !isempty(b
))
4543 print_prop(name
, "%s \"%s\"", strempty(a
), strempty(b
));
4546 } else if (streq_ptr(name
, "SystemCallFilter")) {
4547 _cleanup_strv_free_
char **l
= NULL
;
4550 r
= sd_bus_message_enter_container(m
, 'r', "bas");
4552 return bus_log_parse_error(r
);
4554 r
= sd_bus_message_read(m
, "b", &whitelist
);
4556 return bus_log_parse_error(r
);
4558 r
= sd_bus_message_read_strv(m
, &l
);
4560 return bus_log_parse_error(r
);
4562 r
= sd_bus_message_exit_container(m
);
4564 return bus_log_parse_error(r
);
4566 if (arg_all
|| whitelist
|| !strv_isempty(l
)) {
4571 fputs(name
, stdout
);
4578 STRV_FOREACH(i
, l
) {
4586 fputc('\n', stdout
);
4594 case SD_BUS_TYPE_ARRAY
:
4596 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "EnvironmentFiles")) {
4600 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sb)");
4602 return bus_log_parse_error(r
);
4604 while ((r
= sd_bus_message_read(m
, "(sb)", &path
, &ignore
)) > 0)
4605 print_prop("EnvironmentFile", "%s (ignore_errors=%s)", path
, yes_no(ignore
));
4608 return bus_log_parse_error(r
);
4610 r
= sd_bus_message_exit_container(m
);
4612 return bus_log_parse_error(r
);
4616 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Paths")) {
4617 const char *type
, *path
;
4619 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4621 return bus_log_parse_error(r
);
4623 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4624 print_prop(type
, "%s", path
);
4626 return bus_log_parse_error(r
);
4628 r
= sd_bus_message_exit_container(m
);
4630 return bus_log_parse_error(r
);
4634 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
4635 const char *type
, *path
;
4637 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4639 return bus_log_parse_error(r
);
4641 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4645 printf("Listen%s=%s\n", type
, path
);
4647 return bus_log_parse_error(r
);
4649 r
= sd_bus_message_exit_container(m
);
4651 return bus_log_parse_error(r
);
4655 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Timers")) {
4657 uint64_t value
, next_elapse
;
4659 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(stt)");
4661 return bus_log_parse_error(r
);
4663 while ((r
= sd_bus_message_read(m
, "(stt)", &base
, &value
, &next_elapse
)) > 0) {
4664 char timespan1
[FORMAT_TIMESPAN_MAX
], timespan2
[FORMAT_TIMESPAN_MAX
];
4666 print_prop(base
, "{ value=%s ; next_elapse=%s }",
4667 format_timespan(timespan1
, sizeof(timespan1
), value
, 0),
4668 format_timespan(timespan2
, sizeof(timespan2
), next_elapse
, 0));
4671 return bus_log_parse_error(r
);
4673 r
= sd_bus_message_exit_container(m
);
4675 return bus_log_parse_error(r
);
4679 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
4680 ExecStatusInfo info
= {};
4682 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4684 return bus_log_parse_error(r
);
4686 while ((r
= exec_status_info_deserialize(m
, &info
)) > 0) {
4687 char timestamp1
[FORMAT_TIMESTAMP_MAX
], timestamp2
[FORMAT_TIMESTAMP_MAX
];
4688 _cleanup_free_
char *tt
;
4690 tt
= strv_join(info
.argv
, " ");
4693 "{ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT
" ; code=%s ; status=%i%s%s }",
4696 yes_no(info
.ignore
),
4697 strna(format_timestamp(timestamp1
, sizeof(timestamp1
), info
.start_timestamp
)),
4698 strna(format_timestamp(timestamp2
, sizeof(timestamp2
), info
.exit_timestamp
)),
4700 sigchld_code_to_string(info
.code
),
4702 info
.code
== CLD_EXITED
? "" : "/",
4703 strempty(info
.code
== CLD_EXITED
? NULL
: signal_to_string(info
.status
)));
4706 strv_free(info
.argv
);
4710 r
= sd_bus_message_exit_container(m
);
4712 return bus_log_parse_error(r
);
4716 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "DeviceAllow")) {
4717 const char *path
, *rwm
;
4719 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4721 return bus_log_parse_error(r
);
4723 while ((r
= sd_bus_message_read(m
, "(ss)", &path
, &rwm
)) > 0)
4724 print_prop(name
, "%s %s", strna(path
), strna(rwm
));
4726 return bus_log_parse_error(r
);
4728 r
= sd_bus_message_exit_container(m
);
4730 return bus_log_parse_error(r
);
4734 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&&
4735 STR_IN_SET(name
, "IODeviceWeight", "BlockIODeviceWeight")) {
4739 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4741 return bus_log_parse_error(r
);
4743 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &weight
)) > 0)
4744 print_prop(name
, "%s %"PRIu64
, strna(path
), weight
);
4746 return bus_log_parse_error(r
);
4748 r
= sd_bus_message_exit_container(m
);
4750 return bus_log_parse_error(r
);
4754 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&&
4755 (cgroup_io_limit_type_from_string(name
) >= 0 ||
4756 STR_IN_SET(name
, "BlockIOReadBandwidth", "BlockIOWriteBandwidth"))) {
4760 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4762 return bus_log_parse_error(r
);
4764 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &bandwidth
)) > 0)
4765 print_prop(name
, "%s %"PRIu64
, strna(path
), bandwidth
);
4767 return bus_log_parse_error(r
);
4769 r
= sd_bus_message_exit_container(m
);
4771 return bus_log_parse_error(r
);
4779 r
= bus_print_property(name
, m
, arg_value
, arg_all
);
4781 return bus_log_parse_error(r
);
4784 r
= sd_bus_message_skip(m
, contents
);
4786 return bus_log_parse_error(r
);
4789 printf("%s=[unprintable]\n", name
);
4795 static int show_one(
4800 bool show_properties
,
4804 static const struct bus_properties_map property_map
[] = {
4805 { "LoadState", "s", map_string_no_copy
, offsetof(UnitStatusInfo
, load_state
) },
4806 { "ActiveState", "s", map_string_no_copy
, offsetof(UnitStatusInfo
, active_state
) },
4810 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
4811 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
4812 _cleanup_set_free_ Set
*found_properties
= NULL
;
4813 _cleanup_(unit_status_info_free
) UnitStatusInfo info
= {
4814 .memory_current
= (uint64_t) -1,
4815 .memory_high
= CGROUP_LIMIT_MAX
,
4816 .memory_max
= CGROUP_LIMIT_MAX
,
4817 .memory_swap_max
= CGROUP_LIMIT_MAX
,
4818 .memory_limit
= (uint64_t) -1,
4819 .cpu_usage_nsec
= (uint64_t) -1,
4820 .tasks_current
= (uint64_t) -1,
4821 .tasks_max
= (uint64_t) -1,
4828 log_debug("Showing one %s", path
);
4830 r
= sd_bus_call_method(
4832 "org.freedesktop.systemd1",
4834 "org.freedesktop.DBus.Properties",
4840 return log_error_errno(r
, "Failed to get properties: %s", bus_error_message(&error
, r
));
4843 r
= bus_message_map_all_properties(reply
, property_map
, &info
);
4845 return log_error_errno(r
, "Failed to map properties: %s", bus_error_message(&error
, r
));
4847 if (streq_ptr(info
.load_state
, "not-found") && streq_ptr(info
.active_state
, "inactive")) {
4848 log_full(streq(verb
, "status") ? LOG_ERR
: LOG_DEBUG
,
4849 "Unit %s could not be found.", unit
);
4851 if (streq(verb
, "status"))
4852 return EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN
;
4854 if (!streq(verb
, "show"))
4858 r
= sd_bus_message_rewind(reply
, true);
4860 return log_error_errno(r
, "Failed to rewind: %s", bus_error_message(&error
, r
));
4863 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
4865 return bus_log_parse_error(r
);
4872 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
4873 const char *name
, *contents
;
4875 r
= sd_bus_message_read(reply
, "s", &name
);
4877 return bus_log_parse_error(r
);
4879 r
= sd_bus_message_peek_type(reply
, NULL
, &contents
);
4881 return bus_log_parse_error(r
);
4883 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, contents
);
4885 return bus_log_parse_error(r
);
4887 if (show_properties
) {
4888 r
= set_ensure_allocated(&found_properties
, &string_hash_ops
);
4892 r
= set_put(found_properties
, name
);
4893 if (r
< 0 && r
!= EEXIST
)
4896 r
= print_property(name
, reply
, contents
);
4898 r
= status_property(name
, reply
, &info
, contents
);
4902 r
= sd_bus_message_exit_container(reply
);
4904 return bus_log_parse_error(r
);
4906 r
= sd_bus_message_exit_container(reply
);
4908 return bus_log_parse_error(r
);
4911 return bus_log_parse_error(r
);
4913 r
= sd_bus_message_exit_container(reply
);
4915 return bus_log_parse_error(r
);
4918 if (show_properties
) {
4920 int not_found_level
= streq(verb
, "show") ? LOG_DEBUG
: LOG_WARNING
;
4922 STRV_FOREACH(pp
, arg_properties
)
4923 if (!set_contains(found_properties
, *pp
)) {
4924 log_full(not_found_level
, "Property %s does not exist.", *pp
);
4928 } else if (streq(verb
, "help"))
4929 show_unit_help(&info
);
4930 else if (streq(verb
, "status")) {
4931 print_status_info(bus
, &info
, ellipsized
);
4933 if (info
.active_state
&& !STR_IN_SET(info
.active_state
, "active", "reloading"))
4934 r
= EXIT_PROGRAM_NOT_RUNNING
;
4936 r
= EXIT_PROGRAM_RUNNING_OR_SERVICE_OK
;
4942 static int get_unit_dbus_path_by_pid(
4947 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
4948 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
4952 r
= sd_bus_call_method(
4954 "org.freedesktop.systemd1",
4955 "/org/freedesktop/systemd1",
4956 "org.freedesktop.systemd1.Manager",
4962 return log_error_errno(r
, "Failed to get unit for PID %"PRIu32
": %s", pid
, bus_error_message(&error
, r
));
4964 r
= sd_bus_message_read(reply
, "o", &u
);
4966 return bus_log_parse_error(r
);
4976 static int show_all(
4979 bool show_properties
,
4983 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
4984 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
4989 r
= get_unit_list(bus
, NULL
, NULL
, &unit_infos
, 0, &reply
);
4993 pager_open(arg_no_pager
, false);
4997 qsort_safe(unit_infos
, c
, sizeof(UnitInfo
), compare_unit_info
);
4999 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
5000 _cleanup_free_
char *p
= NULL
;
5002 p
= unit_dbus_path_from_name(u
->id
);
5006 r
= show_one(verb
, bus
, p
, u
->id
, show_properties
, new_line
, ellipsized
);
5009 else if (r
> 0 && ret
== 0)
5016 static int show_system_status(sd_bus
*bus
) {
5017 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], since2
[FORMAT_TIMESTAMP_MAX
];
5018 _cleanup_free_
char *hn
= NULL
;
5019 _cleanup_(machine_info_clear
) struct machine_info mi
= {};
5020 const char *on
, *off
;
5023 hn
= gethostname_malloc();
5027 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, &mi
);
5029 return log_error_errno(r
, "Failed to read server status: %m");
5031 if (streq_ptr(mi
.state
, "degraded")) {
5032 on
= ansi_highlight_red();
5033 off
= ansi_normal();
5034 } else if (!streq_ptr(mi
.state
, "running")) {
5035 on
= ansi_highlight_yellow();
5036 off
= ansi_normal();
5040 printf("%s%s%s %s\n", on
, special_glyph(BLACK_CIRCLE
), off
, arg_host
? arg_host
: hn
);
5042 printf(" State: %s%s%s\n",
5043 on
, strna(mi
.state
), off
);
5045 printf(" Jobs: %" PRIu32
" queued\n", mi
.n_jobs
);
5046 printf(" Failed: %" PRIu32
" units\n", mi
.n_failed_units
);
5048 printf(" Since: %s; %s\n",
5049 format_timestamp(since2
, sizeof(since2
), mi
.timestamp
),
5050 format_timestamp_relative(since1
, sizeof(since1
), mi
.timestamp
));
5052 printf(" CGroup: %s\n", mi
.control_group
?: "/");
5053 if (IN_SET(arg_transport
,
5054 BUS_TRANSPORT_LOCAL
,
5055 BUS_TRANSPORT_MACHINE
)) {
5056 static const char prefix
[] = " ";
5060 if (c
> sizeof(prefix
) - 1)
5061 c
-= sizeof(prefix
) - 1;
5065 show_cgroup(SYSTEMD_CGROUP_CONTROLLER
, strempty(mi
.control_group
), prefix
, c
, get_output_flags());
5071 static int show(int argc
, char *argv
[], void *userdata
) {
5072 bool show_properties
, show_status
, show_help
, new_line
= false;
5073 bool ellipsized
= false;
5079 show_properties
= streq(argv
[0], "show");
5080 show_status
= streq(argv
[0], "status");
5081 show_help
= streq(argv
[0], "help");
5083 if (show_help
&& argc
<= 1) {
5084 log_error("This command expects one or more unit names. Did you mean --help?");
5088 r
= acquire_bus(BUS_MANAGER
, &bus
);
5092 pager_open(arg_no_pager
, false);
5095 /* Increase max number of open files to 16K if we can, we
5096 * might needs this when browsing journal files, which might
5097 * be split up into many files. */
5098 setrlimit_closest(RLIMIT_NOFILE
, &RLIMIT_MAKE_CONST(16384));
5100 /* If no argument is specified inspect the manager itself */
5101 if (show_properties
&& argc
<= 1)
5102 return show_one(argv
[0], bus
, "/org/freedesktop/systemd1", NULL
, show_properties
, &new_line
, &ellipsized
);
5104 if (show_status
&& argc
<= 1) {
5106 show_system_status(bus
);
5110 ret
= show_all(argv
[0], bus
, false, &new_line
, &ellipsized
);
5112 _cleanup_free_
char **patterns
= NULL
;
5115 STRV_FOREACH(name
, strv_skip(argv
, 1)) {
5116 _cleanup_free_
char *path
= NULL
, *unit
= NULL
;
5119 if (safe_atou32(*name
, &id
) < 0) {
5120 if (strv_push(&patterns
, *name
) < 0)
5124 } else if (show_properties
) {
5125 /* Interpret as job id */
5126 if (asprintf(&path
, "/org/freedesktop/systemd1/job/%u", id
) < 0)
5130 /* Interpret as PID */
5131 r
= get_unit_dbus_path_by_pid(bus
, id
, &path
);
5137 r
= unit_name_from_dbus_path(path
, &unit
);
5142 r
= show_one(argv
[0], bus
, path
, unit
, show_properties
, &new_line
, &ellipsized
);
5145 else if (r
> 0 && ret
== 0)
5149 if (!strv_isempty(patterns
)) {
5150 _cleanup_strv_free_
char **names
= NULL
;
5152 r
= expand_names(bus
, patterns
, NULL
, &names
);
5154 return log_error_errno(r
, "Failed to expand names: %m");
5156 STRV_FOREACH(name
, names
) {
5157 _cleanup_free_
char *path
;
5159 path
= unit_dbus_path_from_name(*name
);
5163 r
= show_one(argv
[0], bus
, path
, *name
, show_properties
, &new_line
, &ellipsized
);
5166 if (r
> 0 && ret
== 0)
5172 if (ellipsized
&& !arg_quiet
)
5173 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
5178 static int cat_file(const char *filename
, bool newline
) {
5179 _cleanup_close_
int fd
;
5181 fd
= open(filename
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
5185 printf("%s%s# %s%s\n",
5186 newline
? "\n" : "",
5187 ansi_highlight_blue(),
5192 return copy_bytes(fd
, STDOUT_FILENO
, (uint64_t) -1, false);
5195 static int cat(int argc
, char *argv
[], void *userdata
) {
5196 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
5197 _cleanup_strv_free_
char **names
= NULL
;
5203 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
5204 log_error("Cannot remotely cat units.");
5208 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
5210 return log_error_errno(r
, "Failed to determine unit paths: %m");
5212 r
= acquire_bus(BUS_MANAGER
, &bus
);
5216 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
5218 return log_error_errno(r
, "Failed to expand names: %m");
5220 pager_open(arg_no_pager
, false);
5222 STRV_FOREACH(name
, names
) {
5223 _cleanup_free_
char *fragment_path
= NULL
;
5224 _cleanup_strv_free_
char **dropin_paths
= NULL
;
5227 r
= unit_find_paths(bus
, *name
, &lp
, &fragment_path
, &dropin_paths
);
5238 if (fragment_path
) {
5239 r
= cat_file(fragment_path
, false);
5241 return log_warning_errno(r
, "Failed to cat %s: %m", fragment_path
);
5244 STRV_FOREACH(path
, dropin_paths
) {
5245 r
= cat_file(*path
, path
== dropin_paths
);
5247 return log_warning_errno(r
, "Failed to cat %s: %m", *path
);
5254 static int set_property(int argc
, char *argv
[], void *userdata
) {
5255 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5256 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5257 _cleanup_free_
char *n
= NULL
;
5261 r
= acquire_bus(BUS_MANAGER
, &bus
);
5265 polkit_agent_open_if_enabled();
5267 r
= sd_bus_message_new_method_call(
5270 "org.freedesktop.systemd1",
5271 "/org/freedesktop/systemd1",
5272 "org.freedesktop.systemd1.Manager",
5273 "SetUnitProperties");
5275 return bus_log_create_error(r
);
5277 r
= unit_name_mangle(argv
[1], UNIT_NAME_NOGLOB
, &n
);
5279 return log_error_errno(r
, "Failed to mangle unit name: %m");
5281 r
= sd_bus_message_append(m
, "sb", n
, arg_runtime
);
5283 return bus_log_create_error(r
);
5285 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, "(sv)");
5287 return bus_log_create_error(r
);
5289 r
= bus_append_unit_property_assignment_many(m
, strv_skip(argv
, 2));
5293 r
= sd_bus_message_close_container(m
);
5295 return bus_log_create_error(r
);
5297 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5299 return log_error_errno(r
, "Failed to set unit properties on %s: %s", n
, bus_error_message(&error
, r
));
5304 static int daemon_reload(int argc
, char *argv
[], void *userdata
) {
5305 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5306 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5311 r
= acquire_bus(BUS_MANAGER
, &bus
);
5315 polkit_agent_open_if_enabled();
5317 switch (arg_action
) {
5324 method
= "Reexecute";
5327 case ACTION_SYSTEMCTL
:
5328 method
= streq(argv
[0], "daemon-reexec") ? "Reexecute" :
5329 /* "daemon-reload" */ "Reload";
5333 assert_not_reached("Unexpected action");
5336 r
= sd_bus_message_new_method_call(
5339 "org.freedesktop.systemd1",
5340 "/org/freedesktop/systemd1",
5341 "org.freedesktop.systemd1.Manager",
5344 return bus_log_create_error(r
);
5346 /* Note we use an extra-long timeout here. This is because a reload or reexec means generators are rerun which
5347 * are timed out after DEFAULT_TIMEOUT_USEC. Let's use twice that time here, so that the generators can have
5348 * their timeout, and for everything else there's the same time budget in place. */
5350 r
= sd_bus_call(bus
, m
, DEFAULT_TIMEOUT_USEC
* 2, &error
, NULL
);
5352 /* On reexecution, we expect a disconnect, not a reply */
5353 if (IN_SET(r
, -ETIMEDOUT
, -ECONNRESET
) && streq(method
, "Reexecute"))
5356 if (r
< 0 && arg_action
== ACTION_SYSTEMCTL
)
5357 return log_error_errno(r
, "Failed to reload daemon: %s", bus_error_message(&error
, r
));
5359 /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
5360 * old ways of doing things, hence don't log any error in that case here. */
5362 return r
< 0 ? r
: 0;
5365 static int trivial_method(int argc
, char *argv
[], void *userdata
) {
5366 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5371 r
= acquire_bus(BUS_MANAGER
, &bus
);
5375 polkit_agent_open_if_enabled();
5378 streq(argv
[0], "clear-jobs") ||
5379 streq(argv
[0], "cancel") ? "ClearJobs" :
5380 streq(argv
[0], "reset-failed") ? "ResetFailed" :
5381 streq(argv
[0], "halt") ? "Halt" :
5382 streq(argv
[0], "reboot") ? "Reboot" :
5383 streq(argv
[0], "kexec") ? "KExec" :
5384 streq(argv
[0], "exit") ? "Exit" :
5385 /* poweroff */ "PowerOff";
5387 r
= sd_bus_call_method(
5389 "org.freedesktop.systemd1",
5390 "/org/freedesktop/systemd1",
5391 "org.freedesktop.systemd1.Manager",
5396 if (r
< 0 && arg_action
== ACTION_SYSTEMCTL
)
5397 return log_error_errno(r
, "Failed to execute operation: %s", bus_error_message(&error
, r
));
5399 /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
5400 * old ways of doing things, hence don't log any error in that case here. */
5402 return r
< 0 ? r
: 0;
5405 static int reset_failed(int argc
, char *argv
[], void *userdata
) {
5406 _cleanup_strv_free_
char **names
= NULL
;
5412 return trivial_method(argc
, argv
, userdata
);
5414 r
= acquire_bus(BUS_MANAGER
, &bus
);
5418 polkit_agent_open_if_enabled();
5420 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
5422 return log_error_errno(r
, "Failed to expand names: %m");
5424 STRV_FOREACH(name
, names
) {
5425 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5427 q
= sd_bus_call_method(
5429 "org.freedesktop.systemd1",
5430 "/org/freedesktop/systemd1",
5431 "org.freedesktop.systemd1.Manager",
5437 log_error_errno(q
, "Failed to reset failed state of unit %s: %s", *name
, bus_error_message(&error
, q
));
5446 static int show_environment(int argc
, char *argv
[], void *userdata
) {
5447 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5448 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5453 r
= acquire_bus(BUS_MANAGER
, &bus
);
5457 pager_open(arg_no_pager
, false);
5459 r
= sd_bus_get_property(
5461 "org.freedesktop.systemd1",
5462 "/org/freedesktop/systemd1",
5463 "org.freedesktop.systemd1.Manager",
5469 return log_error_errno(r
, "Failed to get environment: %s", bus_error_message(&error
, r
));
5471 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
5473 return bus_log_parse_error(r
);
5475 while ((r
= sd_bus_message_read_basic(reply
, SD_BUS_TYPE_STRING
, &text
)) > 0)
5478 return bus_log_parse_error(r
);
5480 r
= sd_bus_message_exit_container(reply
);
5482 return bus_log_parse_error(r
);
5487 static int switch_root(int argc
, char *argv
[], void *userdata
) {
5488 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5489 _cleanup_free_
char *cmdline_init
= NULL
;
5490 const char *root
, *init
;
5494 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
5495 log_error("Cannot switch root remotely.");
5499 if (argc
< 2 || argc
> 3) {
5500 log_error("Wrong number of arguments.");
5509 r
= parse_env_file("/proc/cmdline", WHITESPACE
,
5510 "init", &cmdline_init
,
5513 log_debug_errno(r
, "Failed to parse /proc/cmdline: %m");
5515 init
= cmdline_init
;
5518 init
= empty_to_null(init
);
5520 const char *root_systemd_path
= NULL
, *root_init_path
= NULL
;
5522 root_systemd_path
= strjoina(root
, "/" SYSTEMD_BINARY_PATH
);
5523 root_init_path
= strjoina(root
, "/", init
);
5525 /* If the passed init is actually the same as the
5526 * systemd binary, then let's suppress it. */
5527 if (files_same(root_init_path
, root_systemd_path
) > 0)
5531 r
= acquire_bus(BUS_MANAGER
, &bus
);
5535 log_debug("Switching root - root: %s; init: %s", root
, strna(init
));
5537 r
= sd_bus_call_method(
5539 "org.freedesktop.systemd1",
5540 "/org/freedesktop/systemd1",
5541 "org.freedesktop.systemd1.Manager",
5547 return log_error_errno(r
, "Failed to switch root: %s", bus_error_message(&error
, r
));
5552 static int set_environment(int argc
, char *argv
[], void *userdata
) {
5553 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5554 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5562 r
= acquire_bus(BUS_MANAGER
, &bus
);
5566 polkit_agent_open_if_enabled();
5568 method
= streq(argv
[0], "set-environment")
5570 : "UnsetEnvironment";
5572 r
= sd_bus_message_new_method_call(
5575 "org.freedesktop.systemd1",
5576 "/org/freedesktop/systemd1",
5577 "org.freedesktop.systemd1.Manager",
5580 return bus_log_create_error(r
);
5582 r
= sd_bus_message_append_strv(m
, strv_skip(argv
, 1));
5584 return bus_log_create_error(r
);
5586 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5588 return log_error_errno(r
, "Failed to set environment: %s", bus_error_message(&error
, r
));
5593 static int import_environment(int argc
, char *argv
[], void *userdata
) {
5594 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5595 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5599 r
= acquire_bus(BUS_MANAGER
, &bus
);
5603 polkit_agent_open_if_enabled();
5605 r
= sd_bus_message_new_method_call(
5608 "org.freedesktop.systemd1",
5609 "/org/freedesktop/systemd1",
5610 "org.freedesktop.systemd1.Manager",
5613 return bus_log_create_error(r
);
5616 r
= sd_bus_message_append_strv(m
, environ
);
5620 r
= sd_bus_message_open_container(m
, 'a', "s");
5622 return bus_log_create_error(r
);
5624 STRV_FOREACH(a
, strv_skip(argv
, 1)) {
5626 if (!env_name_is_valid(*a
)) {
5627 log_error("Not a valid environment variable name: %s", *a
);
5631 STRV_FOREACH(b
, environ
) {
5634 eq
= startswith(*b
, *a
);
5635 if (eq
&& *eq
== '=') {
5637 r
= sd_bus_message_append(m
, "s", *b
);
5639 return bus_log_create_error(r
);
5646 r
= sd_bus_message_close_container(m
);
5649 return bus_log_create_error(r
);
5651 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5653 return log_error_errno(r
, "Failed to import environment: %s", bus_error_message(&error
, r
));
5658 static int enable_sysv_units(const char *verb
, char **args
) {
5661 #if defined(HAVE_SYSV_COMPAT)
5662 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
5665 /* Processes all SysV units, and reshuffles the array so that afterwards only the native units remain */
5667 if (arg_scope
!= UNIT_FILE_SYSTEM
)
5670 if (getenv_bool("SYSTEMCTL_SKIP_SYSV") > 0)
5673 if (!STR_IN_SET(verb
,
5679 r
= lookup_paths_init(&paths
, arg_scope
, LOOKUP_PATHS_EXCLUDE_GENERATED
, arg_root
);
5686 const char *argv
[] = {
5687 ROOTLIBEXECDIR
"/systemd-sysv-install",
5694 _cleanup_free_
char *p
= NULL
, *q
= NULL
, *l
= NULL
;
5695 bool found_native
= false, found_sysv
;
5704 if (!endswith(name
, ".service"))
5707 if (path_is_absolute(name
))
5710 j
= unit_file_exists(arg_scope
, &paths
, name
);
5711 if (j
< 0 && !IN_SET(j
, -ELOOP
, -ERFKILL
, -EADDRNOTAVAIL
))
5712 return log_error_errno(j
, "Failed to lookup unit file state: %m");
5713 found_native
= j
!= 0;
5715 /* If we have both a native unit and a SysV script, enable/disable them both (below); for is-enabled,
5716 * prefer the native unit */
5717 if (found_native
&& streq(verb
, "is-enabled"))
5720 p
= path_join(arg_root
, SYSTEM_SYSVINIT_PATH
, name
);
5724 p
[strlen(p
) - strlen(".service")] = 0;
5725 found_sysv
= access(p
, F_OK
) >= 0;
5731 log_info("Synchronizing state of %s with SysV service script with %s.", name
, argv
[0]);
5733 log_info("%s is not a native service, redirecting to systemd-sysv-install.", name
);
5736 if (!isempty(arg_root
))
5737 argv
[c
++] = q
= strappend("--root=", arg_root
);
5740 argv
[c
++] = basename(p
);
5743 l
= strv_join((char**)argv
, " ");
5747 log_info("Executing: %s", l
);
5751 return log_error_errno(errno
, "Failed to fork: %m");
5752 else if (pid
== 0) {
5755 (void) reset_all_signal_handlers();
5756 (void) reset_signal_mask();
5758 execv(argv
[0], (char**) argv
);
5759 log_error_errno(errno
, "Failed to execute %s: %m", argv
[0]);
5760 _exit(EXIT_FAILURE
);
5763 j
= wait_for_terminate(pid
, &status
);
5765 return log_error_errno(j
, "Failed to wait for child: %m");
5767 if (status
.si_code
== CLD_EXITED
) {
5768 if (streq(verb
, "is-enabled")) {
5769 if (status
.si_status
== 0) {
5778 } else if (status
.si_status
!= 0)
5779 return -EBADE
; /* We don't warn here, under the assumption the script already showed an explanation */
5781 log_error("Unexpected waitid() result.");
5788 /* Remove this entry, so that we don't try enabling it as native unit */
5791 assert(args
[f
] == name
);
5792 strv_remove(args
, name
);
5799 static int mangle_names(char **original_names
, char ***mangled_names
) {
5800 char **i
, **l
, **name
;
5803 l
= i
= new(char*, strv_length(original_names
) + 1);
5807 STRV_FOREACH(name
, original_names
) {
5809 /* When enabling units qualified path names are OK,
5810 * too, hence allow them explicitly. */
5812 if (is_path(*name
)) {
5819 r
= unit_name_mangle(*name
, UNIT_NAME_NOGLOB
, i
);
5822 return log_error_errno(r
, "Failed to mangle unit name: %m");
5835 static int normalize_names(char **names
, bool warn_if_path
) {
5837 bool was_path
= false;
5839 STRV_FOREACH(u
, names
) {
5845 r
= free_and_strdup(u
, basename(*u
));
5847 return log_error_errno(r
, "Failed to normalize unit file path: %m");
5852 if (warn_if_path
&& was_path
)
5853 log_warning("Warning: Can't execute disable on the unit file path. Proceeding with the unit name.");
5858 static int unit_exists(const char *unit
) {
5859 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5860 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5861 _cleanup_free_
char *path
= NULL
;
5862 static const struct bus_properties_map property_map
[] = {
5863 { "LoadState", "s", map_string_no_copy
, offsetof(UnitStatusInfo
, load_state
) },
5864 { "ActiveState", "s", map_string_no_copy
, offsetof(UnitStatusInfo
, active_state
)},
5867 UnitStatusInfo info
= {};
5871 path
= unit_dbus_path_from_name(unit
);
5875 r
= acquire_bus(BUS_MANAGER
, &bus
);
5879 r
= sd_bus_call_method(
5881 "org.freedesktop.systemd1",
5883 "org.freedesktop.DBus.Properties",
5889 return log_error_errno(r
, "Failed to get properties: %s", bus_error_message(&error
, r
));
5891 r
= bus_message_map_all_properties(reply
, property_map
, &info
);
5893 return log_error_errno(r
, "Failed to map properties: %s", bus_error_message(&error
, r
));
5895 return !streq_ptr(info
.load_state
, "not-found") || !streq_ptr(info
.active_state
, "inactive");
5898 static int enable_unit(int argc
, char *argv
[], void *userdata
) {
5899 _cleanup_strv_free_
char **names
= NULL
;
5900 const char *verb
= argv
[0];
5901 UnitFileChange
*changes
= NULL
;
5902 unsigned n_changes
= 0;
5903 int carries_install_info
= -1;
5904 bool ignore_carries_install_info
= arg_quiet
;
5910 r
= mangle_names(strv_skip(argv
, 1), &names
);
5914 r
= enable_sysv_units(verb
, names
);
5918 /* If the operation was fully executed by the SysV compat, let's finish early */
5919 if (strv_isempty(names
)) {
5920 if (arg_no_reload
|| install_client_side())
5922 return daemon_reload(argc
, argv
, userdata
);
5925 if (streq(verb
, "disable")) {
5926 r
= normalize_names(names
, true);
5931 if (install_client_side()) {
5932 if (streq(verb
, "enable")) {
5933 r
= unit_file_enable(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5934 carries_install_info
= r
;
5935 } else if (streq(verb
, "disable"))
5936 r
= unit_file_disable(arg_scope
, arg_runtime
, arg_root
, names
, &changes
, &n_changes
);
5937 else if (streq(verb
, "reenable")) {
5938 r
= unit_file_reenable(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5939 carries_install_info
= r
;
5940 } else if (streq(verb
, "link"))
5941 r
= unit_file_link(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5942 else if (streq(verb
, "preset")) {
5943 r
= unit_file_preset(arg_scope
, arg_runtime
, arg_root
, names
, arg_preset_mode
, arg_force
, &changes
, &n_changes
);
5944 } else if (streq(verb
, "mask"))
5945 r
= unit_file_mask(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5946 else if (streq(verb
, "unmask"))
5947 r
= unit_file_unmask(arg_scope
, arg_runtime
, arg_root
, names
, &changes
, &n_changes
);
5948 else if (streq(verb
, "revert"))
5949 r
= unit_file_revert(arg_scope
, arg_root
, names
, &changes
, &n_changes
);
5951 assert_not_reached("Unknown verb");
5953 unit_file_dump_changes(r
, verb
, changes
, n_changes
, arg_quiet
);
5958 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
, *m
= NULL
;
5959 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5960 bool expect_carries_install_info
= false;
5961 bool send_runtime
= true, send_force
= true, send_preset_mode
= false;
5965 if (STR_IN_SET(verb
, "mask", "unmask")) {
5966 r
= unit_exists(*names
);
5970 log_notice("Unit %s does not exist, proceeding anyway.", *names
);
5973 r
= acquire_bus(BUS_MANAGER
, &bus
);
5977 polkit_agent_open_if_enabled();
5979 if (streq(verb
, "enable")) {
5980 method
= "EnableUnitFiles";
5981 expect_carries_install_info
= true;
5982 } else if (streq(verb
, "disable")) {
5983 method
= "DisableUnitFiles";
5985 } else if (streq(verb
, "reenable")) {
5986 method
= "ReenableUnitFiles";
5987 expect_carries_install_info
= true;
5988 } else if (streq(verb
, "link"))
5989 method
= "LinkUnitFiles";
5990 else if (streq(verb
, "preset")) {
5992 if (arg_preset_mode
!= UNIT_FILE_PRESET_FULL
) {
5993 method
= "PresetUnitFilesWithMode";
5994 send_preset_mode
= true;
5996 method
= "PresetUnitFiles";
5998 expect_carries_install_info
= true;
5999 ignore_carries_install_info
= true;
6000 } else if (streq(verb
, "mask"))
6001 method
= "MaskUnitFiles";
6002 else if (streq(verb
, "unmask")) {
6003 method
= "UnmaskUnitFiles";
6005 } else if (streq(verb
, "revert")) {
6006 method
= "RevertUnitFiles";
6007 send_runtime
= send_force
= false;
6009 assert_not_reached("Unknown verb");
6011 r
= sd_bus_message_new_method_call(
6014 "org.freedesktop.systemd1",
6015 "/org/freedesktop/systemd1",
6016 "org.freedesktop.systemd1.Manager",
6019 return bus_log_create_error(r
);
6021 r
= sd_bus_message_append_strv(m
, names
);
6023 return bus_log_create_error(r
);
6025 if (send_preset_mode
) {
6026 r
= sd_bus_message_append(m
, "s", unit_file_preset_mode_to_string(arg_preset_mode
));
6028 return bus_log_create_error(r
);
6032 r
= sd_bus_message_append(m
, "b", arg_runtime
);
6034 return bus_log_create_error(r
);
6038 r
= sd_bus_message_append(m
, "b", arg_force
);
6040 return bus_log_create_error(r
);
6043 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
6045 return log_error_errno(r
, "Failed to %s unit: %s", verb
, bus_error_message(&error
, r
));
6047 if (expect_carries_install_info
) {
6048 r
= sd_bus_message_read(reply
, "b", &carries_install_info
);
6050 return bus_log_parse_error(r
);
6053 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
6057 /* Try to reload if enabled */
6059 r
= daemon_reload(argc
, argv
, userdata
);
6064 if (carries_install_info
== 0 && !ignore_carries_install_info
)
6065 log_warning("The unit files have no installation config (WantedBy, RequiredBy, Also, Alias\n"
6066 "settings in the [Install] section, and DefaultInstance for template units).\n"
6067 "This means they are not meant to be enabled using systemctl.\n"
6068 "Possible reasons for having this kind of units are:\n"
6069 "1) A unit may be statically enabled by being symlinked from another unit's\n"
6070 " .wants/ or .requires/ directory.\n"
6071 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
6072 " a requirement dependency on it.\n"
6073 "3) A unit may be started when needed via activation (socket, path, timer,\n"
6074 " D-Bus, udev, scripted systemctl call, ...).\n"
6075 "4) In case of template units, the unit is meant to be enabled with some\n"
6076 " instance name specified.");
6078 if (arg_now
&& n_changes
> 0 && STR_IN_SET(argv
[0], "enable", "disable", "mask")) {
6079 char *new_args
[n_changes
+ 2];
6083 r
= acquire_bus(BUS_MANAGER
, &bus
);
6087 new_args
[0] = (char*) (streq(argv
[0], "enable") ? "start" : "stop");
6088 for (i
= 0; i
< n_changes
; i
++)
6089 new_args
[i
+ 1] = basename(changes
[i
].path
);
6090 new_args
[i
+ 1] = NULL
;
6092 r
= start_unit(strv_length(new_args
), new_args
, userdata
);
6096 unit_file_changes_free(changes
, n_changes
);
6101 static int add_dependency(int argc
, char *argv
[], void *userdata
) {
6102 _cleanup_strv_free_
char **names
= NULL
;
6103 _cleanup_free_
char *target
= NULL
;
6104 const char *verb
= argv
[0];
6105 UnitFileChange
*changes
= NULL
;
6106 unsigned n_changes
= 0;
6113 r
= unit_name_mangle_with_suffix(argv
[1], UNIT_NAME_NOGLOB
, ".target", &target
);
6115 return log_error_errno(r
, "Failed to mangle unit name: %m");
6117 r
= mangle_names(strv_skip(argv
, 2), &names
);
6121 if (streq(verb
, "add-wants"))
6123 else if (streq(verb
, "add-requires"))
6124 dep
= UNIT_REQUIRES
;
6126 assert_not_reached("Unknown verb");
6128 if (install_client_side()) {
6129 r
= unit_file_add_dependency(arg_scope
, arg_runtime
, arg_root
, names
, target
, dep
, arg_force
, &changes
, &n_changes
);
6130 unit_file_dump_changes(r
, "add dependency on", changes
, n_changes
, arg_quiet
);
6135 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
, *m
= NULL
;
6136 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6139 r
= acquire_bus(BUS_MANAGER
, &bus
);
6143 polkit_agent_open_if_enabled();
6145 r
= sd_bus_message_new_method_call(
6148 "org.freedesktop.systemd1",
6149 "/org/freedesktop/systemd1",
6150 "org.freedesktop.systemd1.Manager",
6151 "AddDependencyUnitFiles");
6153 return bus_log_create_error(r
);
6155 r
= sd_bus_message_append_strv(m
, names
);
6157 return bus_log_create_error(r
);
6159 r
= sd_bus_message_append(m
, "ssbb", target
, unit_dependency_to_string(dep
), arg_runtime
, arg_force
);
6161 return bus_log_create_error(r
);
6163 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
6165 return log_error_errno(r
, "Failed to add dependency: %s", bus_error_message(&error
, r
));
6167 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
6171 if (arg_no_reload
) {
6176 r
= daemon_reload(argc
, argv
, userdata
);
6180 unit_file_changes_free(changes
, n_changes
);
6185 static int preset_all(int argc
, char *argv
[], void *userdata
) {
6186 UnitFileChange
*changes
= NULL
;
6187 unsigned n_changes
= 0;
6190 if (install_client_side()) {
6191 r
= unit_file_preset_all(arg_scope
, arg_runtime
, arg_root
, arg_preset_mode
, arg_force
, &changes
, &n_changes
);
6192 unit_file_dump_changes(r
, "preset", changes
, n_changes
, arg_quiet
);
6197 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6198 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6201 r
= acquire_bus(BUS_MANAGER
, &bus
);
6205 polkit_agent_open_if_enabled();
6207 r
= sd_bus_call_method(
6209 "org.freedesktop.systemd1",
6210 "/org/freedesktop/systemd1",
6211 "org.freedesktop.systemd1.Manager",
6212 "PresetAllUnitFiles",
6216 unit_file_preset_mode_to_string(arg_preset_mode
),
6220 return log_error_errno(r
, "Failed to preset all units: %s", bus_error_message(&error
, r
));
6222 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
6226 if (arg_no_reload
) {
6231 r
= daemon_reload(argc
, argv
, userdata
);
6235 unit_file_changes_free(changes
, n_changes
);
6240 static int unit_is_enabled(int argc
, char *argv
[], void *userdata
) {
6242 _cleanup_strv_free_
char **names
= NULL
;
6247 r
= mangle_names(strv_skip(argv
, 1), &names
);
6251 r
= enable_sysv_units(argv
[0], names
);
6257 if (install_client_side()) {
6259 STRV_FOREACH(name
, names
) {
6260 UnitFileState state
;
6262 r
= unit_file_get_state(arg_scope
, arg_root
, *name
, &state
);
6264 return log_error_errno(state
, "Failed to get unit file state for %s: %m", *name
);
6268 UNIT_FILE_ENABLED_RUNTIME
,
6271 UNIT_FILE_GENERATED
))
6275 puts(unit_file_state_to_string(state
));
6280 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6283 r
= acquire_bus(BUS_MANAGER
, &bus
);
6287 STRV_FOREACH(name
, names
) {
6288 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6291 r
= sd_bus_call_method(
6293 "org.freedesktop.systemd1",
6294 "/org/freedesktop/systemd1",
6295 "org.freedesktop.systemd1.Manager",
6301 return log_error_errno(r
, "Failed to get unit file state for %s: %s", *name
, bus_error_message(&error
, r
));
6303 r
= sd_bus_message_read(reply
, "s", &s
);
6305 return bus_log_parse_error(r
);
6307 if (STR_IN_SET(s
, "enabled", "enabled-runtime", "static", "indirect", "generated"))
6315 return enabled
? EXIT_SUCCESS
: EXIT_FAILURE
;
6318 static int is_system_running(int argc
, char *argv
[], void *userdata
) {
6319 _cleanup_free_
char *state
= NULL
;
6323 if (running_in_chroot() > 0 || (arg_transport
== BUS_TRANSPORT_LOCAL
&& !sd_booted())) {
6326 return EXIT_FAILURE
;
6329 r
= acquire_bus(BUS_MANAGER
, &bus
);
6333 r
= sd_bus_get_property_string(
6335 "org.freedesktop.systemd1",
6336 "/org/freedesktop/systemd1",
6337 "org.freedesktop.systemd1.Manager",
6350 return streq(state
, "running") ? EXIT_SUCCESS
: EXIT_FAILURE
;
6353 static int create_edit_temp_file(const char *new_path
, const char *original_path
, char **ret_tmp_fn
) {
6354 _cleanup_free_
char *t
= NULL
;
6358 assert(original_path
);
6361 r
= tempfn_random(new_path
, NULL
, &t
);
6363 return log_error_errno(r
, "Failed to determine temporary filename for \"%s\": %m", new_path
);
6365 r
= mkdir_parents(new_path
, 0755);
6367 return log_error_errno(r
, "Failed to create directories for \"%s\": %m", new_path
);
6369 r
= copy_file(original_path
, t
, 0, 0644, 0);
6374 return log_error_errno(r
, "Failed to create temporary file \"%s\": %m", t
);
6377 return log_error_errno(r
, "Failed to create temporary file for \"%s\": %m", new_path
);
6385 static int get_file_to_edit(
6386 const LookupPaths
*paths
,
6390 _cleanup_free_
char *path
= NULL
, *run
= NULL
;
6395 path
= strjoin(paths
->persistent_config
, "/", name
, NULL
);
6400 run
= strjoin(paths
->runtime_config
, "/", name
, NULL
);
6406 if (access(path
, F_OK
) >= 0) {
6407 log_error("Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.", run
, path
);
6421 static int unit_file_create_new(
6422 const LookupPaths
*paths
,
6423 const char *unit_name
,
6425 char **ret_new_path
,
6426 char **ret_tmp_path
) {
6428 char *tmp_new_path
, *tmp_tmp_path
, *ending
;
6432 assert(ret_new_path
);
6433 assert(ret_tmp_path
);
6435 ending
= strjoina(unit_name
, suffix
);
6436 r
= get_file_to_edit(paths
, ending
, &tmp_new_path
);
6440 r
= create_edit_temp_file(tmp_new_path
, tmp_new_path
, &tmp_tmp_path
);
6446 *ret_new_path
= tmp_new_path
;
6447 *ret_tmp_path
= tmp_tmp_path
;
6452 static int unit_file_create_copy(
6453 const LookupPaths
*paths
,
6454 const char *unit_name
,
6455 const char *fragment_path
,
6456 char **ret_new_path
,
6457 char **ret_tmp_path
) {
6459 char *tmp_new_path
, *tmp_tmp_path
;
6462 assert(fragment_path
);
6464 assert(ret_new_path
);
6465 assert(ret_tmp_path
);
6467 r
= get_file_to_edit(paths
, unit_name
, &tmp_new_path
);
6471 if (!path_equal(fragment_path
, tmp_new_path
) && access(tmp_new_path
, F_OK
) == 0) {
6474 r
= ask_char(&response
, "yn", "\"%s\" already exists. Overwrite with \"%s\"? [(y)es, (n)o] ", tmp_new_path
, fragment_path
);
6479 if (response
!= 'y') {
6480 log_warning("%s ignored", unit_name
);
6482 return -EKEYREJECTED
;
6486 r
= create_edit_temp_file(tmp_new_path
, fragment_path
, &tmp_tmp_path
);
6492 *ret_new_path
= tmp_new_path
;
6493 *ret_tmp_path
= tmp_tmp_path
;
6498 static int run_editor(char **paths
) {
6506 return log_error_errno(errno
, "Failed to fork: %m");
6510 char *editor
, **editor_args
= NULL
;
6511 char **tmp_path
, **original_path
, *p
;
6512 unsigned n_editor_args
= 0, i
= 1;
6515 (void) reset_all_signal_handlers();
6516 (void) reset_signal_mask();
6518 argc
= strv_length(paths
)/2 + 1;
6520 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
6521 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
6522 * we try to execute well known editors
6524 editor
= getenv("SYSTEMD_EDITOR");
6526 editor
= getenv("EDITOR");
6528 editor
= getenv("VISUAL");
6530 if (!isempty(editor
)) {
6531 editor_args
= strv_split(editor
, WHITESPACE
);
6534 _exit(EXIT_FAILURE
);
6536 n_editor_args
= strv_length(editor_args
);
6537 argc
+= n_editor_args
- 1;
6539 args
= newa(const char*, argc
+ 1);
6541 if (n_editor_args
> 0) {
6542 args
[0] = editor_args
[0];
6543 for (; i
< n_editor_args
; i
++)
6544 args
[i
] = editor_args
[i
];
6547 STRV_FOREACH_PAIR(original_path
, tmp_path
, paths
) {
6548 args
[i
] = *tmp_path
;
6553 if (n_editor_args
> 0)
6554 execvp(args
[0], (char* const*) args
);
6556 FOREACH_STRING(p
, "editor", "nano", "vim", "vi") {
6558 execvp(p
, (char* const*) args
);
6559 /* We do not fail if the editor doesn't exist
6560 * because we want to try each one of them before
6563 if (errno
!= ENOENT
) {
6564 log_error_errno(errno
, "Failed to execute %s: %m", editor
);
6565 _exit(EXIT_FAILURE
);
6569 log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR, $EDITOR or $VISUAL.");
6570 _exit(EXIT_FAILURE
);
6573 r
= wait_for_terminate_and_warn("editor", pid
, true);
6575 return log_error_errno(r
, "Failed to wait for child: %m");
6580 static int find_paths_to_edit(sd_bus
*bus
, char **names
, char ***paths
) {
6581 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
6588 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
6592 STRV_FOREACH(name
, names
) {
6593 _cleanup_free_
char *path
= NULL
, *new_path
= NULL
, *tmp_path
= NULL
;
6595 r
= unit_find_paths(bus
, *name
, &lp
, &path
, NULL
);
6598 else if (!arg_force
) {
6600 log_error("Run 'systemctl edit --force %s' to create a new unit.", *name
);
6603 // FIXME: support units with path==NULL (no FragmentPath)
6604 log_error("No fragment exists for %s.", *name
);
6611 r
= unit_file_create_copy(&lp
, *name
, path
, &new_path
, &tmp_path
);
6613 r
= unit_file_create_new(&lp
, *name
, ".d/override.conf", &new_path
, &tmp_path
);
6615 r
= unit_file_create_new(&lp
, *name
, NULL
, &new_path
, &tmp_path
);
6619 r
= strv_push_pair(paths
, new_path
, tmp_path
);
6622 new_path
= tmp_path
= NULL
;
6628 static int edit(int argc
, char *argv
[], void *userdata
) {
6629 _cleanup_strv_free_
char **names
= NULL
;
6630 _cleanup_strv_free_
char **paths
= NULL
;
6631 char **original
, **tmp
;
6636 log_error("Cannot edit units if not on a tty.");
6640 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
6641 log_error("Cannot edit units remotely.");
6645 r
= acquire_bus(BUS_MANAGER
, &bus
);
6649 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
6651 return log_error_errno(r
, "Failed to expand names: %m");
6653 r
= find_paths_to_edit(bus
, names
, &paths
);
6657 if (strv_isempty(paths
))
6660 r
= run_editor(paths
);
6664 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
6665 /* If the temporary file is empty we ignore it. It's
6666 * useful if the user wants to cancel its modification
6668 if (null_or_empty_path(*tmp
)) {
6669 log_warning("Editing \"%s\" canceled: temporary file is empty.", *original
);
6673 r
= rename(*tmp
, *original
);
6675 r
= log_error_errno(errno
, "Failed to rename \"%s\" to \"%s\": %m", *tmp
, *original
);
6682 if (!arg_no_reload
&& !install_client_side())
6683 r
= daemon_reload(argc
, argv
, userdata
);
6686 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
6687 (void) unlink(*tmp
);
6689 /* Removing empty dropin dirs */
6691 _cleanup_free_
char *dir
;
6693 dir
= dirname_malloc(*original
);
6697 /* no need to check if the dir is empty, rmdir
6698 * does nothing if it is not the case.
6707 static void systemctl_help(void) {
6709 pager_open(arg_no_pager
, false);
6711 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
6712 "Query or send control commands to the systemd manager.\n\n"
6713 " -h --help Show this help\n"
6714 " --version Show package version\n"
6715 " --system Connect to system manager\n"
6716 " --user Connect to user service manager\n"
6717 " -H --host=[USER@]HOST\n"
6718 " Operate on remote host\n"
6719 " -M --machine=CONTAINER\n"
6720 " Operate on local container\n"
6721 " -t --type=TYPE List units of a particular type\n"
6722 " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n"
6723 " -p --property=NAME Show only properties by this name\n"
6724 " -a --all Show all loaded units/properties, including dead/empty\n"
6725 " ones. To list all units installed on the system, use\n"
6726 " the 'list-unit-files' command instead.\n"
6727 " -l --full Don't ellipsize unit names on output\n"
6728 " -r --recursive Show unit list of host and local containers\n"
6729 " --reverse Show reverse dependencies with 'list-dependencies'\n"
6730 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
6731 " queueing a new job\n"
6732 " --show-types When showing sockets, explicitly show their type\n"
6733 " --value When showing properties, only print the value\n"
6734 " -i --ignore-inhibitors\n"
6735 " When shutting down or sleeping, ignore inhibitors\n"
6736 " --kill-who=WHO Who to send signal to\n"
6737 " -s --signal=SIGNAL Which signal to send\n"
6738 " --now Start or stop unit in addition to enabling or disabling it\n"
6739 " -q --quiet Suppress output\n"
6740 " --wait For (re)start, wait until service stopped again\n"
6741 " --no-block Do not wait until operation finished\n"
6742 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6743 " --no-reload Don't reload daemon after en-/dis-abling unit files\n"
6744 " --no-legend Do not print a legend (column headers and hints)\n"
6745 " --no-pager Do not pipe output into a pager\n"
6746 " --no-ask-password\n"
6747 " Do not ask for system passwords\n"
6748 " --global Enable/disable unit files globally\n"
6749 " --runtime Enable unit files only temporarily until next reboot\n"
6750 " -f --force When enabling unit files, override existing symlinks\n"
6751 " When shutting down, execute action immediately\n"
6752 " --preset-mode= Apply only enable, only disable, or all presets\n"
6753 " --root=PATH Enable unit files in the specified root directory\n"
6754 " -n --lines=INTEGER Number of journal entries to show\n"
6755 " -o --output=STRING Change journal output mode (short, short-precise,\n"
6756 " short-iso, short-full, short-monotonic, short-unix,\n"
6757 " verbose, export, json, json-pretty, json-sse, cat)\n"
6758 " --firmware-setup Tell the firmware to show the setup menu on next boot\n"
6759 " --plain Print unit dependencies as a list instead of a tree\n\n"
6761 " list-units [PATTERN...] List loaded units\n"
6762 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
6763 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
6764 " start NAME... Start (activate) one or more units\n"
6765 " stop NAME... Stop (deactivate) one or more units\n"
6766 " reload NAME... Reload one or more units\n"
6767 " restart NAME... Start or restart one or more units\n"
6768 " try-restart NAME... Restart one or more units if active\n"
6769 " reload-or-restart NAME... Reload one or more units if possible,\n"
6770 " otherwise start or restart\n"
6771 " try-reload-or-restart NAME... If active, reload one or more units,\n"
6772 " if supported, otherwise restart\n"
6773 " isolate NAME Start one unit and stop all others\n"
6774 " kill NAME... Send signal to processes of a unit\n"
6775 " is-active PATTERN... Check whether units are active\n"
6776 " is-failed PATTERN... Check whether units are failed\n"
6777 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
6778 " show [PATTERN...|JOB...] Show properties of one or more\n"
6779 " units/jobs or the manager\n"
6780 " cat PATTERN... Show files and drop-ins of one or more units\n"
6781 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
6782 " help PATTERN...|PID... Show manual for one or more units\n"
6783 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
6785 " list-dependencies [NAME] Recursively show units which are required\n"
6786 " or wanted by this unit or by which this\n"
6787 " unit is required or wanted\n\n"
6788 "Unit File Commands:\n"
6789 " list-unit-files [PATTERN...] List installed unit files\n"
6790 " enable [NAME...|PATH...] Enable one or more unit files\n"
6791 " disable NAME... Disable one or more unit files\n"
6792 " reenable NAME... Reenable one or more unit files\n"
6793 " preset NAME... Enable/disable one or more unit files\n"
6794 " based on preset configuration\n"
6795 " preset-all Enable/disable all unit files based on\n"
6796 " preset configuration\n"
6797 " is-enabled NAME... Check whether unit files are enabled\n"
6798 " mask NAME... Mask one or more units\n"
6799 " unmask NAME... Unmask one or more units\n"
6800 " link PATH... Link one or more units files into\n"
6801 " the search path\n"
6802 " revert NAME... Revert one or more unit files to vendor\n"
6804 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
6805 " on specified one or more units\n"
6806 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
6807 " on specified one or more units\n"
6808 " edit NAME... Edit one or more unit files\n"
6809 " get-default Get the name of the default target\n"
6810 " set-default NAME Set the default target\n\n"
6811 "Machine Commands:\n"
6812 " list-machines [PATTERN...] List local containers and host\n\n"
6814 " list-jobs [PATTERN...] List jobs\n"
6815 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
6816 "Environment Commands:\n"
6817 " show-environment Dump environment\n"
6818 " set-environment NAME=VALUE... Set one or more environment variables\n"
6819 " unset-environment NAME... Unset one or more environment variables\n"
6820 " import-environment [NAME...] Import all or some environment variables\n\n"
6821 "Manager Lifecycle Commands:\n"
6822 " daemon-reload Reload systemd manager configuration\n"
6823 " daemon-reexec Reexecute systemd manager\n\n"
6824 "System Commands:\n"
6825 " is-system-running Check whether system is fully running\n"
6826 " default Enter system default mode\n"
6827 " rescue Enter system rescue mode\n"
6828 " emergency Enter system emergency mode\n"
6829 " halt Shut down and halt the system\n"
6830 " poweroff Shut down and power-off the system\n"
6831 " reboot [ARG] Shut down and reboot the system\n"
6832 " kexec Shut down and reboot the system with kexec\n"
6833 " exit [EXIT_CODE] Request user instance or container exit\n"
6834 " switch-root ROOT [INIT] Change to a different root file system\n"
6835 " suspend Suspend the system\n"
6836 " hibernate Hibernate the system\n"
6837 " hybrid-sleep Hibernate and suspend the system\n",
6838 program_invocation_short_name
);
6841 static void halt_help(void) {
6842 printf("%s [OPTIONS...]%s\n\n"
6843 "%s the system.\n\n"
6844 " --help Show this help\n"
6845 " --halt Halt the machine\n"
6846 " -p --poweroff Switch off the machine\n"
6847 " --reboot Reboot the machine\n"
6848 " -f --force Force immediate halt/power-off/reboot\n"
6849 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
6850 " -d --no-wtmp Don't write wtmp record\n"
6851 " --no-wall Don't send wall message before halt/power-off/reboot\n",
6852 program_invocation_short_name
,
6853 arg_action
== ACTION_REBOOT
? " [ARG]" : "",
6854 arg_action
== ACTION_REBOOT
? "Reboot" :
6855 arg_action
== ACTION_POWEROFF
? "Power off" :
6859 static void shutdown_help(void) {
6860 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
6861 "Shut down the system.\n\n"
6862 " --help Show this help\n"
6863 " -H --halt Halt the machine\n"
6864 " -P --poweroff Power-off the machine\n"
6865 " -r --reboot Reboot the machine\n"
6866 " -h Equivalent to --poweroff, overridden by --halt\n"
6867 " -k Don't halt/power-off/reboot, just send warnings\n"
6868 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6869 " -c Cancel a pending shutdown\n",
6870 program_invocation_short_name
);
6873 static void telinit_help(void) {
6874 printf("%s [OPTIONS...] {COMMAND}\n\n"
6875 "Send control commands to the init daemon.\n\n"
6876 " --help Show this help\n"
6877 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
6879 " 0 Power-off the machine\n"
6880 " 6 Reboot the machine\n"
6881 " 2, 3, 4, 5 Start runlevelX.target unit\n"
6882 " 1, s, S Enter rescue mode\n"
6883 " q, Q Reload init daemon configuration\n"
6884 " u, U Reexecute init daemon\n",
6885 program_invocation_short_name
);
6888 static void runlevel_help(void) {
6889 printf("%s [OPTIONS...]\n\n"
6890 "Prints the previous and current runlevel of the init system.\n\n"
6891 " --help Show this help\n",
6892 program_invocation_short_name
);
6895 static void help_types(void) {
6899 puts("Available unit types:");
6900 for (i
= 0; i
< _UNIT_TYPE_MAX
; i
++)
6901 puts(unit_type_to_string(i
));
6904 static void help_states(void) {
6908 puts("Available unit load states:");
6909 for (i
= 0; i
< _UNIT_LOAD_STATE_MAX
; i
++)
6910 puts(unit_load_state_to_string(i
));
6913 puts("\nAvailable unit active states:");
6914 for (i
= 0; i
< _UNIT_ACTIVE_STATE_MAX
; i
++)
6915 puts(unit_active_state_to_string(i
));
6918 puts("\nAvailable automount unit substates:");
6919 for (i
= 0; i
< _AUTOMOUNT_STATE_MAX
; i
++)
6920 puts(automount_state_to_string(i
));
6923 puts("\nAvailable busname unit substates:");
6924 for (i
= 0; i
< _BUSNAME_STATE_MAX
; i
++)
6925 puts(busname_state_to_string(i
));
6928 puts("\nAvailable device unit substates:");
6929 for (i
= 0; i
< _DEVICE_STATE_MAX
; i
++)
6930 puts(device_state_to_string(i
));
6933 puts("\nAvailable mount unit substates:");
6934 for (i
= 0; i
< _MOUNT_STATE_MAX
; i
++)
6935 puts(mount_state_to_string(i
));
6938 puts("\nAvailable path unit substates:");
6939 for (i
= 0; i
< _PATH_STATE_MAX
; i
++)
6940 puts(path_state_to_string(i
));
6943 puts("\nAvailable scope unit substates:");
6944 for (i
= 0; i
< _SCOPE_STATE_MAX
; i
++)
6945 puts(scope_state_to_string(i
));
6948 puts("\nAvailable service unit substates:");
6949 for (i
= 0; i
< _SERVICE_STATE_MAX
; i
++)
6950 puts(service_state_to_string(i
));
6953 puts("\nAvailable slice unit substates:");
6954 for (i
= 0; i
< _SLICE_STATE_MAX
; i
++)
6955 puts(slice_state_to_string(i
));
6958 puts("\nAvailable socket unit substates:");
6959 for (i
= 0; i
< _SOCKET_STATE_MAX
; i
++)
6960 puts(socket_state_to_string(i
));
6963 puts("\nAvailable swap unit substates:");
6964 for (i
= 0; i
< _SWAP_STATE_MAX
; i
++)
6965 puts(swap_state_to_string(i
));
6968 puts("\nAvailable target unit substates:");
6969 for (i
= 0; i
< _TARGET_STATE_MAX
; i
++)
6970 puts(target_state_to_string(i
));
6973 puts("\nAvailable timer unit substates:");
6974 for (i
= 0; i
< _TIMER_STATE_MAX
; i
++)
6975 puts(timer_state_to_string(i
));
6978 static int systemctl_parse_argv(int argc
, char *argv
[]) {
6987 ARG_IGNORE_DEPENDENCIES
,
7000 ARG_NO_ASK_PASSWORD
,
7014 static const struct option options
[] = {
7015 { "help", no_argument
, NULL
, 'h' },
7016 { "version", no_argument
, NULL
, ARG_VERSION
},
7017 { "type", required_argument
, NULL
, 't' },
7018 { "property", required_argument
, NULL
, 'p' },
7019 { "all", no_argument
, NULL
, 'a' },
7020 { "reverse", no_argument
, NULL
, ARG_REVERSE
},
7021 { "after", no_argument
, NULL
, ARG_AFTER
},
7022 { "before", no_argument
, NULL
, ARG_BEFORE
},
7023 { "show-types", no_argument
, NULL
, ARG_SHOW_TYPES
},
7024 { "failed", no_argument
, NULL
, ARG_FAILED
}, /* compatibility only */
7025 { "full", no_argument
, NULL
, 'l' },
7026 { "job-mode", required_argument
, NULL
, ARG_JOB_MODE
},
7027 { "fail", no_argument
, NULL
, ARG_FAIL
}, /* compatibility only */
7028 { "irreversible", no_argument
, NULL
, ARG_IRREVERSIBLE
}, /* compatibility only */
7029 { "ignore-dependencies", no_argument
, NULL
, ARG_IGNORE_DEPENDENCIES
}, /* compatibility only */
7030 { "ignore-inhibitors", no_argument
, NULL
, 'i' },
7031 { "value", no_argument
, NULL
, ARG_VALUE
},
7032 { "user", no_argument
, NULL
, ARG_USER
},
7033 { "system", no_argument
, NULL
, ARG_SYSTEM
},
7034 { "global", no_argument
, NULL
, ARG_GLOBAL
},
7035 { "wait", no_argument
, NULL
, ARG_WAIT
},
7036 { "no-block", no_argument
, NULL
, ARG_NO_BLOCK
},
7037 { "no-legend", no_argument
, NULL
, ARG_NO_LEGEND
},
7038 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
7039 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7040 { "quiet", no_argument
, NULL
, 'q' },
7041 { "root", required_argument
, NULL
, ARG_ROOT
},
7042 { "force", no_argument
, NULL
, ARG_FORCE
},
7043 { "no-reload", no_argument
, NULL
, ARG_NO_RELOAD
},
7044 { "kill-who", required_argument
, NULL
, ARG_KILL_WHO
},
7045 { "signal", required_argument
, NULL
, 's' },
7046 { "no-ask-password", no_argument
, NULL
, ARG_NO_ASK_PASSWORD
},
7047 { "host", required_argument
, NULL
, 'H' },
7048 { "machine", required_argument
, NULL
, 'M' },
7049 { "runtime", no_argument
, NULL
, ARG_RUNTIME
},
7050 { "lines", required_argument
, NULL
, 'n' },
7051 { "output", required_argument
, NULL
, 'o' },
7052 { "plain", no_argument
, NULL
, ARG_PLAIN
},
7053 { "state", required_argument
, NULL
, ARG_STATE
},
7054 { "recursive", no_argument
, NULL
, 'r' },
7055 { "preset-mode", required_argument
, NULL
, ARG_PRESET_MODE
},
7056 { "firmware-setup", no_argument
, NULL
, ARG_FIRMWARE_SETUP
},
7057 { "now", no_argument
, NULL
, ARG_NOW
},
7058 { "message", required_argument
, NULL
, ARG_MESSAGE
},
7068 /* we default to allowing interactive authorization only in systemctl (not in the legacy commands) */
7069 arg_ask_password
= true;
7071 while ((c
= getopt_long(argc
, argv
, "ht:p:alqfs:H:M:n:o:ir", options
, NULL
)) >= 0)
7083 if (isempty(optarg
)) {
7084 log_error("--type requires arguments.");
7090 _cleanup_free_
char *type
= NULL
;
7092 r
= extract_first_word(&p
, &type
, ",", 0);
7094 return log_error_errno(r
, "Failed to parse type: %s", optarg
);
7099 if (streq(type
, "help")) {
7104 if (unit_type_from_string(type
) >= 0) {
7105 if (strv_push(&arg_types
, type
) < 0)
7111 /* It's much nicer to use --state= for
7112 * load states, but let's support this
7113 * in --types= too for compatibility
7114 * with old versions */
7115 if (unit_load_state_from_string(type
) >= 0) {
7116 if (strv_push(&arg_states
, type
) < 0)
7122 log_error("Unknown unit type or load state '%s'.", type
);
7123 log_info("Use -t help to see a list of allowed values.");
7131 /* Make sure that if the empty property list
7132 was specified, we won't show any properties. */
7133 if (isempty(optarg
) && !arg_properties
) {
7134 arg_properties
= new0(char*, 1);
7135 if (!arg_properties
)
7140 _cleanup_free_
char *prop
= NULL
;
7142 r
= extract_first_word(&p
, &prop
, ",", 0);
7144 return log_error_errno(r
, "Failed to parse property: %s", optarg
);
7149 if (strv_push(&arg_properties
, prop
) < 0)
7156 /* If the user asked for a particular
7157 * property, show it to him, even if it is
7169 arg_dependency
= DEPENDENCY_REVERSE
;
7173 arg_dependency
= DEPENDENCY_AFTER
;
7177 arg_dependency
= DEPENDENCY_BEFORE
;
7180 case ARG_SHOW_TYPES
:
7181 arg_show_types
= true;
7189 arg_job_mode
= optarg
;
7193 arg_job_mode
= "fail";
7196 case ARG_IRREVERSIBLE
:
7197 arg_job_mode
= "replace-irreversibly";
7200 case ARG_IGNORE_DEPENDENCIES
:
7201 arg_job_mode
= "ignore-dependencies";
7205 arg_scope
= UNIT_FILE_USER
;
7209 arg_scope
= UNIT_FILE_SYSTEM
;
7213 arg_scope
= UNIT_FILE_GLOBAL
;
7221 arg_no_block
= true;
7225 arg_no_legend
= true;
7229 arg_no_pager
= true;
7237 r
= parse_path_argument_and_warn(optarg
, false, &arg_root
);
7247 if (strv_extend(&arg_states
, "failed") < 0)
7265 arg_no_reload
= true;
7269 arg_kill_who
= optarg
;
7273 arg_signal
= signal_from_string_try_harder(optarg
);
7274 if (arg_signal
< 0) {
7275 log_error("Failed to parse signal string %s.", optarg
);
7280 case ARG_NO_ASK_PASSWORD
:
7281 arg_ask_password
= false;
7285 arg_transport
= BUS_TRANSPORT_REMOTE
;
7290 arg_transport
= BUS_TRANSPORT_MACHINE
;
7299 if (safe_atou(optarg
, &arg_lines
) < 0) {
7300 log_error("Failed to parse lines '%s'", optarg
);
7306 arg_output
= output_mode_from_string(optarg
);
7307 if (arg_output
< 0) {
7308 log_error("Unknown output '%s'.", optarg
);
7314 arg_ignore_inhibitors
= true;
7321 case ARG_FIRMWARE_SETUP
:
7322 arg_firmware_setup
= true;
7326 if (isempty(optarg
)) {
7327 log_error("--signal requires arguments.");
7333 _cleanup_free_
char *s
= NULL
;
7335 r
= extract_first_word(&p
, &s
, ",", 0);
7337 return log_error_errno(r
, "Failed to parse signal: %s", optarg
);
7342 if (streq(s
, "help")) {
7347 if (strv_push(&arg_states
, s
) < 0)
7356 if (geteuid() != 0) {
7357 log_error("--recursive requires root privileges.");
7361 arg_recursive
= true;
7364 case ARG_PRESET_MODE
:
7366 arg_preset_mode
= unit_file_preset_mode_from_string(optarg
);
7367 if (arg_preset_mode
< 0) {
7368 log_error("Failed to parse preset mode: %s.", optarg
);
7379 if (strv_extend(&arg_wall
, optarg
) < 0)
7387 assert_not_reached("Unhandled option");
7390 if (arg_transport
!= BUS_TRANSPORT_LOCAL
&& arg_scope
!= UNIT_FILE_SYSTEM
) {
7391 log_error("Cannot access user instance remotely.");
7395 if (arg_wait
&& arg_no_block
) {
7396 log_error("--wait may not be combined with --no-block.");
7403 static int halt_parse_argv(int argc
, char *argv
[]) {
7412 static const struct option options
[] = {
7413 { "help", no_argument
, NULL
, ARG_HELP
},
7414 { "halt", no_argument
, NULL
, ARG_HALT
},
7415 { "poweroff", no_argument
, NULL
, 'p' },
7416 { "reboot", no_argument
, NULL
, ARG_REBOOT
},
7417 { "force", no_argument
, NULL
, 'f' },
7418 { "wtmp-only", no_argument
, NULL
, 'w' },
7419 { "no-wtmp", no_argument
, NULL
, 'd' },
7420 { "no-sync", no_argument
, NULL
, 'n' },
7421 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7430 if (utmp_get_runlevel(&runlevel
, NULL
) >= 0)
7431 if (runlevel
== '0' || runlevel
== '6')
7434 while ((c
= getopt_long(argc
, argv
, "pfwdnih", options
, NULL
)) >= 0)
7442 arg_action
= ACTION_HALT
;
7446 if (arg_action
!= ACTION_REBOOT
)
7447 arg_action
= ACTION_POWEROFF
;
7451 arg_action
= ACTION_REBOOT
;
7476 /* Compatibility nops */
7483 assert_not_reached("Unhandled option");
7486 if (arg_action
== ACTION_REBOOT
&& (argc
== optind
|| argc
== optind
+ 1)) {
7487 r
= update_reboot_parameter_and_warn(argc
== optind
+ 1 ? argv
[optind
] : NULL
);
7490 } else if (optind
< argc
) {
7491 log_error("Too many arguments.");
7498 static int parse_shutdown_time_spec(const char *t
, usec_t
*_u
) {
7502 if (streq(t
, "now"))
7504 else if (!strchr(t
, ':')) {
7507 if (safe_atou64(t
, &u
) < 0)
7510 *_u
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
* u
;
7519 hour
= strtol(t
, &e
, 10);
7520 if (errno
> 0 || *e
!= ':' || hour
< 0 || hour
> 23)
7523 minute
= strtol(e
+1, &e
, 10);
7524 if (errno
> 0 || *e
!= 0 || minute
< 0 || minute
> 59)
7527 n
= now(CLOCK_REALTIME
);
7528 s
= (time_t) (n
/ USEC_PER_SEC
);
7530 assert_se(localtime_r(&s
, &tm
));
7532 tm
.tm_hour
= (int) hour
;
7533 tm
.tm_min
= (int) minute
;
7536 assert_se(s
= mktime(&tm
));
7538 *_u
= (usec_t
) s
* USEC_PER_SEC
;
7541 *_u
+= USEC_PER_DAY
;
7547 static int shutdown_parse_argv(int argc
, char *argv
[]) {
7554 static const struct option options
[] = {
7555 { "help", no_argument
, NULL
, ARG_HELP
},
7556 { "halt", no_argument
, NULL
, 'H' },
7557 { "poweroff", no_argument
, NULL
, 'P' },
7558 { "reboot", no_argument
, NULL
, 'r' },
7559 { "kexec", no_argument
, NULL
, 'K' }, /* not documented extension */
7560 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7570 while ((c
= getopt_long(argc
, argv
, "HPrhkKtafFc", options
, NULL
)) >= 0)
7578 arg_action
= ACTION_HALT
;
7582 arg_action
= ACTION_POWEROFF
;
7587 arg_action
= ACTION_KEXEC
;
7589 arg_action
= ACTION_REBOOT
;
7593 arg_action
= ACTION_KEXEC
;
7597 if (arg_action
!= ACTION_HALT
)
7598 arg_action
= ACTION_POWEROFF
;
7613 /* Compatibility nops */
7617 arg_action
= ACTION_CANCEL_SHUTDOWN
;
7624 assert_not_reached("Unhandled option");
7627 if (argc
> optind
&& arg_action
!= ACTION_CANCEL_SHUTDOWN
) {
7628 r
= parse_shutdown_time_spec(argv
[optind
], &arg_when
);
7630 log_error("Failed to parse time specification: %s", argv
[optind
]);
7634 arg_when
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
;
7636 if (argc
> optind
&& arg_action
== ACTION_CANCEL_SHUTDOWN
)
7637 /* No time argument for shutdown cancel */
7638 wall
= argv
+ optind
;
7639 else if (argc
> optind
+ 1)
7640 /* We skip the time argument */
7641 wall
= argv
+ optind
+ 1;
7644 arg_wall
= strv_copy(wall
);
7654 static int telinit_parse_argv(int argc
, char *argv
[]) {
7661 static const struct option options
[] = {
7662 { "help", no_argument
, NULL
, ARG_HELP
},
7663 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7667 static const struct {
7671 { '0', ACTION_POWEROFF
},
7672 { '6', ACTION_REBOOT
},
7673 { '1', ACTION_RESCUE
},
7674 { '2', ACTION_RUNLEVEL2
},
7675 { '3', ACTION_RUNLEVEL3
},
7676 { '4', ACTION_RUNLEVEL4
},
7677 { '5', ACTION_RUNLEVEL5
},
7678 { 's', ACTION_RESCUE
},
7679 { 'S', ACTION_RESCUE
},
7680 { 'q', ACTION_RELOAD
},
7681 { 'Q', ACTION_RELOAD
},
7682 { 'u', ACTION_REEXEC
},
7683 { 'U', ACTION_REEXEC
}
7692 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
7707 assert_not_reached("Unhandled option");
7710 if (optind
>= argc
) {
7711 log_error("%s: required argument missing.", program_invocation_short_name
);
7715 if (optind
+ 1 < argc
) {
7716 log_error("Too many arguments.");
7720 if (strlen(argv
[optind
]) != 1) {
7721 log_error("Expected single character argument.");
7725 for (i
= 0; i
< ELEMENTSOF(table
); i
++)
7726 if (table
[i
].from
== argv
[optind
][0])
7729 if (i
>= ELEMENTSOF(table
)) {
7730 log_error("Unknown command '%s'.", argv
[optind
]);
7734 arg_action
= table
[i
].to
;
7741 static int runlevel_parse_argv(int argc
, char *argv
[]) {
7747 static const struct option options
[] = {
7748 { "help", no_argument
, NULL
, ARG_HELP
},
7757 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
7768 assert_not_reached("Unhandled option");
7771 if (optind
< argc
) {
7772 log_error("Too many arguments.");
7779 static int parse_argv(int argc
, char *argv
[]) {
7783 if (program_invocation_short_name
) {
7785 if (strstr(program_invocation_short_name
, "halt")) {
7786 arg_action
= ACTION_HALT
;
7787 return halt_parse_argv(argc
, argv
);
7788 } else if (strstr(program_invocation_short_name
, "poweroff")) {
7789 arg_action
= ACTION_POWEROFF
;
7790 return halt_parse_argv(argc
, argv
);
7791 } else if (strstr(program_invocation_short_name
, "reboot")) {
7793 arg_action
= ACTION_KEXEC
;
7795 arg_action
= ACTION_REBOOT
;
7796 return halt_parse_argv(argc
, argv
);
7797 } else if (strstr(program_invocation_short_name
, "shutdown")) {
7798 arg_action
= ACTION_POWEROFF
;
7799 return shutdown_parse_argv(argc
, argv
);
7800 } else if (strstr(program_invocation_short_name
, "init")) {
7802 if (sd_booted() > 0) {
7803 arg_action
= _ACTION_INVALID
;
7804 return telinit_parse_argv(argc
, argv
);
7806 /* Hmm, so some other init system is
7807 * running, we need to forward this
7808 * request to it. For now we simply
7809 * guess that it is Upstart. */
7811 execv(TELINIT
, argv
);
7813 log_error("Couldn't find an alternative telinit implementation to spawn.");
7817 } else if (strstr(program_invocation_short_name
, "runlevel")) {
7818 arg_action
= ACTION_RUNLEVEL
;
7819 return runlevel_parse_argv(argc
, argv
);
7823 arg_action
= ACTION_SYSTEMCTL
;
7824 return systemctl_parse_argv(argc
, argv
);
7827 #ifdef HAVE_SYSV_COMPAT
7828 _pure_
static int action_to_runlevel(void) {
7830 static const char table
[_ACTION_MAX
] = {
7831 [ACTION_HALT
] = '0',
7832 [ACTION_POWEROFF
] = '0',
7833 [ACTION_REBOOT
] = '6',
7834 [ACTION_RUNLEVEL2
] = '2',
7835 [ACTION_RUNLEVEL3
] = '3',
7836 [ACTION_RUNLEVEL4
] = '4',
7837 [ACTION_RUNLEVEL5
] = '5',
7838 [ACTION_RESCUE
] = '1'
7841 assert(arg_action
< _ACTION_MAX
);
7843 return table
[arg_action
];
7847 static int talk_initctl(void) {
7848 #ifdef HAVE_SYSV_COMPAT
7849 struct init_request request
= {
7850 .magic
= INIT_MAGIC
,
7852 .cmd
= INIT_CMD_RUNLVL
7855 _cleanup_close_
int fd
= -1;
7859 rl
= action_to_runlevel();
7863 request
.runlevel
= rl
;
7865 fd
= open(INIT_FIFO
, O_WRONLY
|O_NDELAY
|O_CLOEXEC
|O_NOCTTY
);
7867 if (errno
== ENOENT
)
7870 return log_error_errno(errno
, "Failed to open "INIT_FIFO
": %m");
7873 r
= loop_write(fd
, &request
, sizeof(request
), false);
7875 return log_error_errno(r
, "Failed to write to "INIT_FIFO
": %m");
7883 static int systemctl_main(int argc
, char *argv
[]) {
7885 static const Verb verbs
[] = {
7886 { "list-units", VERB_ANY
, VERB_ANY
, VERB_DEFAULT
|VERB_NOCHROOT
, list_units
},
7887 { "list-unit-files", VERB_ANY
, VERB_ANY
, 0, list_unit_files
},
7888 { "list-sockets", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_sockets
},
7889 { "list-timers", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_timers
},
7890 { "list-jobs", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_jobs
},
7891 { "list-machines", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_machines
},
7892 { "clear-jobs", VERB_ANY
, 1, VERB_NOCHROOT
, trivial_method
},
7893 { "cancel", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, cancel_job
},
7894 { "start", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
7895 { "stop", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
7896 { "condstop", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with ALTLinux */
7897 { "reload", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
7898 { "restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
7899 { "try-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
7900 { "reload-or-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
7901 { "reload-or-try-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatbility with old systemctl <= 228 */
7902 { "try-reload-or-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
7903 { "force-reload", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with SysV */
7904 { "condreload", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with ALTLinux */
7905 { "condrestart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with RH */
7906 { "isolate", 2, 2, VERB_NOCHROOT
, start_unit
},
7907 { "kill", 2, VERB_ANY
, VERB_NOCHROOT
, kill_unit
},
7908 { "is-active", 2, VERB_ANY
, VERB_NOCHROOT
, check_unit_active
},
7909 { "check", 2, VERB_ANY
, VERB_NOCHROOT
, check_unit_active
},
7910 { "is-failed", 2, VERB_ANY
, VERB_NOCHROOT
, check_unit_failed
},
7911 { "show", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, show
},
7912 { "cat", 2, VERB_ANY
, VERB_NOCHROOT
, cat
},
7913 { "status", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, show
},
7914 { "help", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, show
},
7915 { "daemon-reload", VERB_ANY
, 1, VERB_NOCHROOT
, daemon_reload
},
7916 { "daemon-reexec", VERB_ANY
, 1, VERB_NOCHROOT
, daemon_reload
},
7917 { "show-environment", VERB_ANY
, 1, VERB_NOCHROOT
, show_environment
},
7918 { "set-environment", 2, VERB_ANY
, VERB_NOCHROOT
, set_environment
},
7919 { "unset-environment", 2, VERB_ANY
, VERB_NOCHROOT
, set_environment
},
7920 { "import-environment", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, import_environment
},
7921 { "halt", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
7922 { "poweroff", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
7923 { "reboot", VERB_ANY
, 2, VERB_NOCHROOT
, start_system_special
},
7924 { "kexec", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
7925 { "suspend", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
7926 { "hibernate", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
7927 { "hybrid-sleep", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
7928 { "default", VERB_ANY
, 1, VERB_NOCHROOT
, start_special
},
7929 { "rescue", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
7930 { "emergency", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
7931 { "exit", VERB_ANY
, 2, VERB_NOCHROOT
, start_special
},
7932 { "reset-failed", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, reset_failed
},
7933 { "enable", 2, VERB_ANY
, 0, enable_unit
},
7934 { "disable", 2, VERB_ANY
, 0, enable_unit
},
7935 { "is-enabled", 2, VERB_ANY
, 0, unit_is_enabled
},
7936 { "reenable", 2, VERB_ANY
, 0, enable_unit
},
7937 { "preset", 2, VERB_ANY
, 0, enable_unit
},
7938 { "preset-all", VERB_ANY
, 1, 0, preset_all
},
7939 { "mask", 2, VERB_ANY
, 0, enable_unit
},
7940 { "unmask", 2, VERB_ANY
, 0, enable_unit
},
7941 { "link", 2, VERB_ANY
, 0, enable_unit
},
7942 { "revert", 2, VERB_ANY
, 0, enable_unit
},
7943 { "switch-root", 2, VERB_ANY
, VERB_NOCHROOT
, switch_root
},
7944 { "list-dependencies", VERB_ANY
, 2, VERB_NOCHROOT
, list_dependencies
},
7945 { "set-default", 2, 2, 0, set_default
},
7946 { "get-default", VERB_ANY
, 1, 0, get_default
},
7947 { "set-property", 3, VERB_ANY
, VERB_NOCHROOT
, set_property
},
7948 { "is-system-running", VERB_ANY
, 1, 0, is_system_running
},
7949 { "add-wants", 3, VERB_ANY
, 0, add_dependency
},
7950 { "add-requires", 3, VERB_ANY
, 0, add_dependency
},
7951 { "edit", 2, VERB_ANY
, VERB_NOCHROOT
, edit
},
7955 return dispatch_verb(argc
, argv
, verbs
, NULL
);
7958 static int reload_with_fallback(void) {
7960 /* First, try systemd via D-Bus. */
7961 if (daemon_reload(0, NULL
, NULL
) >= 0)
7964 /* Nothing else worked, so let's try signals */
7965 assert(IN_SET(arg_action
, ACTION_RELOAD
, ACTION_REEXEC
));
7967 if (kill(1, arg_action
== ACTION_RELOAD
? SIGHUP
: SIGTERM
) < 0)
7968 return log_error_errno(errno
, "kill() failed: %m");
7973 static int start_with_fallback(void) {
7975 /* First, try systemd via D-Bus. */
7976 if (start_unit(0, NULL
, NULL
) >= 0)
7979 /* Nothing else worked, so let's try /dev/initctl */
7980 if (talk_initctl() > 0)
7983 log_error("Failed to talk to init daemon.");
7987 static int halt_now(enum action a
) {
7990 /* The kernel will automaticall flush ATA disks and suchlike
7991 * on reboot(), but the file systems need to be synce'd
7992 * explicitly in advance. */
7996 /* Make sure C-A-D is handled by the kernel from this point
7998 (void) reboot(RB_ENABLE_CAD
);
8003 log_info("Halting.");
8004 (void) reboot(RB_HALT_SYSTEM
);
8007 case ACTION_POWEROFF
:
8008 log_info("Powering off.");
8009 (void) reboot(RB_POWER_OFF
);
8013 case ACTION_REBOOT
: {
8014 _cleanup_free_
char *param
= NULL
;
8016 r
= read_one_line_file("/run/systemd/reboot-param", ¶m
);
8018 log_warning_errno(r
, "Failed to read reboot parameter file: %m");
8020 if (!isempty(param
)) {
8021 log_info("Rebooting with argument '%s'.", param
);
8022 (void) syscall(SYS_reboot
, LINUX_REBOOT_MAGIC1
, LINUX_REBOOT_MAGIC2
, LINUX_REBOOT_CMD_RESTART2
, param
);
8023 log_warning_errno(errno
, "Failed to reboot with parameter, retrying without: %m");
8026 log_info("Rebooting.");
8027 (void) reboot(RB_AUTOBOOT
);
8032 assert_not_reached("Unknown action.");
8036 static int logind_schedule_shutdown(void) {
8039 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
8040 char date
[FORMAT_TIMESTAMP_MAX
];
8045 r
= acquire_bus(BUS_FULL
, &bus
);
8049 switch (arg_action
) {
8053 case ACTION_POWEROFF
:
8054 action
= "poweroff";
8069 action
= strjoina("dry-", action
);
8071 (void) logind_set_wall_message();
8073 r
= sd_bus_call_method(
8075 "org.freedesktop.login1",
8076 "/org/freedesktop/login1",
8077 "org.freedesktop.login1.Manager",
8085 return log_warning_errno(r
, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s", bus_error_message(&error
, r
));
8087 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.", format_timestamp(date
, sizeof(date
), arg_when
));
8090 log_error("Cannot schedule shutdown without logind support, proceeding with immediate shutdown.");
8095 static int halt_main(void) {
8098 r
= logind_check_inhibitors(arg_action
);
8103 return logind_schedule_shutdown();
8105 if (geteuid() != 0) {
8106 if (arg_dry
|| arg_force
> 0) {
8107 log_error("Must be root.");
8111 /* Try logind if we are a normal user and no special
8112 * mode applies. Maybe PolicyKit allows us to shutdown
8114 if (IN_SET(arg_action
, ACTION_POWEROFF
, ACTION_REBOOT
)) {
8115 r
= logind_reboot(arg_action
);
8118 if (IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
8119 /* requested operation is not
8120 * supported on the local system or
8121 * already in progress */
8123 /* on all other errors, try low-level operation */
8127 if (!arg_dry
&& !arg_force
)
8128 return start_with_fallback();
8130 assert(geteuid() == 0);
8133 if (sd_booted() > 0)
8134 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
8136 r
= utmp_put_shutdown();
8138 log_warning_errno(r
, "Failed to write utmp record: %m");
8145 r
= halt_now(arg_action
);
8146 return log_error_errno(r
, "Failed to reboot: %m");
8149 static int runlevel_main(void) {
8150 int r
, runlevel
, previous
;
8152 r
= utmp_get_runlevel(&runlevel
, &previous
);
8159 previous
<= 0 ? 'N' : previous
,
8160 runlevel
<= 0 ? 'N' : runlevel
);
8165 static int logind_cancel_shutdown(void) {
8167 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
8171 r
= acquire_bus(BUS_FULL
, &bus
);
8175 (void) logind_set_wall_message();
8177 r
= sd_bus_call_method(
8179 "org.freedesktop.login1",
8180 "/org/freedesktop/login1",
8181 "org.freedesktop.login1.Manager",
8182 "CancelScheduledShutdown",
8186 return log_warning_errno(r
, "Failed to talk to logind, shutdown hasn't been cancelled: %s", bus_error_message(&error
, r
));
8190 log_error("Not compiled with logind support, cannot cancel scheduled shutdowns.");
8195 int main(int argc
, char*argv
[]) {
8198 setlocale(LC_ALL
, "");
8199 log_parse_environment();
8203 /* Explicitly not on_tty() to avoid setting cached value.
8204 * This becomes relevant for piping output which might be
8206 original_stdout_is_tty
= isatty(STDOUT_FILENO
);
8208 r
= parse_argv(argc
, argv
);
8212 if (arg_action
!= ACTION_SYSTEMCTL
&& running_in_chroot() > 0) {
8213 log_info("Running in chroot, ignoring request.");
8218 /* systemctl_main() will print an error message for the bus
8219 * connection, but only if it needs to */
8221 switch (arg_action
) {
8223 case ACTION_SYSTEMCTL
:
8224 r
= systemctl_main(argc
, argv
);
8228 case ACTION_POWEROFF
:
8234 case ACTION_RUNLEVEL2
:
8235 case ACTION_RUNLEVEL3
:
8236 case ACTION_RUNLEVEL4
:
8237 case ACTION_RUNLEVEL5
:
8239 case ACTION_EMERGENCY
:
8240 case ACTION_DEFAULT
:
8241 r
= start_with_fallback();
8246 r
= reload_with_fallback();
8249 case ACTION_CANCEL_SHUTDOWN
:
8250 r
= logind_cancel_shutdown();
8253 case ACTION_RUNLEVEL
:
8254 r
= runlevel_main();
8257 case _ACTION_INVALID
:
8259 assert_not_reached("Unknown action");
8266 ask_password_agent_close();
8267 polkit_agent_close();
8269 strv_free(arg_types
);
8270 strv_free(arg_states
);
8271 strv_free(arg_properties
);
8273 strv_free(arg_wall
);
8276 /* Note that we return r here, not EXIT_SUCCESS, so that we can implement the LSB-like return codes */
8277 return r
< 0 ? EXIT_FAILURE
: r
;