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"
51 #include "exit-status.h"
54 #include "format-util.h"
56 #include "glob-util.h"
57 #include "hostname-util.h"
62 #include "locale-util.h"
64 #include "logs-show.h"
68 #include "parse-util.h"
69 #include "path-lookup.h"
70 #include "path-util.h"
71 #include "process-util.h"
72 #include "rlimit-util.h"
75 #include "signal-util.h"
76 #include "socket-util.h"
77 #include "spawn-ask-password-agent.h"
78 #include "spawn-polkit-agent.h"
80 #include "stat-util.h"
82 #include "terminal-util.h"
83 #include "unit-name.h"
84 #include "user-util.h"
86 #include "utmp-wtmp.h"
90 /* The init script exit status codes
91 0 program is running or service is OK
92 1 program is dead and /var/run pid file exists
93 2 program is dead and /var/lock lock file exists
94 3 program is not running
95 4 program or service status is unknown
96 5-99 reserved for future LSB use
97 100-149 reserved for distribution use
98 150-199 reserved for application use
102 EXIT_PROGRAM_RUNNING_OR_SERVICE_OK
= 0,
103 EXIT_PROGRAM_DEAD_AND_PID_EXISTS
= 1,
104 EXIT_PROGRAM_DEAD_AND_LOCK_FILE_EXISTS
= 2,
105 EXIT_PROGRAM_NOT_RUNNING
= 3,
106 EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN
= 4,
109 static char **arg_types
= NULL
;
110 static char **arg_states
= NULL
;
111 static char **arg_properties
= NULL
;
112 static bool arg_all
= false;
113 static enum dependency
{
119 } arg_dependency
= DEPENDENCY_FORWARD
;
120 static const char *arg_job_mode
= "replace";
121 static UnitFileScope arg_scope
= UNIT_FILE_SYSTEM
;
122 static bool arg_wait
= false;
123 static bool arg_no_block
= false;
124 static bool arg_no_legend
= false;
125 static bool arg_no_pager
= false;
126 static bool arg_no_wtmp
= false;
127 static bool arg_no_sync
= false;
128 static bool arg_no_wall
= false;
129 static bool arg_no_reload
= false;
130 static bool arg_value
= false;
131 static bool arg_show_types
= false;
132 static bool arg_ignore_inhibitors
= false;
133 static bool arg_dry
= false;
134 static bool arg_quiet
= false;
135 static bool arg_full
= false;
136 static bool arg_recursive
= false;
137 static int arg_force
= 0;
138 static bool arg_ask_password
= false;
139 static bool arg_runtime
= false;
140 static UnitFilePresetMode arg_preset_mode
= UNIT_FILE_PRESET_FULL
;
141 static char **arg_wall
= NULL
;
142 static const char *arg_kill_who
= NULL
;
143 static int arg_signal
= SIGTERM
;
144 static char *arg_root
= NULL
;
145 static usec_t arg_when
= 0;
146 static char *argv_cmdline
= NULL
;
167 ACTION_CANCEL_SHUTDOWN
,
170 } arg_action
= ACTION_SYSTEMCTL
;
171 static BusTransport arg_transport
= BUS_TRANSPORT_LOCAL
;
172 static const char *arg_host
= NULL
;
173 static unsigned arg_lines
= 10;
174 static OutputMode arg_output
= OUTPUT_SHORT
;
175 static bool arg_plain
= false;
176 static bool arg_firmware_setup
= false;
177 static bool arg_now
= false;
178 static bool arg_jobs_before
= false;
179 static bool arg_jobs_after
= false;
181 static int daemon_reload(int argc
, char *argv
[], void* userdata
);
182 static int trivial_method(int argc
, char *argv
[], void *userdata
);
183 static int halt_now(enum action a
);
184 static int get_state_one_unit(sd_bus
*bus
, const char *name
, UnitActiveState
*active_state
);
186 static bool original_stdout_is_tty
;
188 typedef enum BusFocus
{
189 BUS_FULL
, /* The full bus indicated via --system or --user */
190 BUS_MANAGER
, /* The manager itself, possibly directly, possibly via the bus */
194 static sd_bus
*busses
[_BUS_FOCUS_MAX
] = {};
196 static UnitFileFlags
args_to_flags(void) {
197 return (arg_runtime
? UNIT_FILE_RUNTIME
: 0) |
198 (arg_force
? UNIT_FILE_FORCE
: 0);
201 static int acquire_bus(BusFocus focus
, sd_bus
**ret
) {
204 assert(focus
< _BUS_FOCUS_MAX
);
207 /* We only go directly to the manager, if we are using a local transport */
208 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
211 if (getenv_bool("SYSTEMCTL_FORCE_BUS") > 0)
214 if (!busses
[focus
]) {
217 user
= arg_scope
!= UNIT_FILE_SYSTEM
;
219 if (focus
== BUS_MANAGER
)
220 r
= bus_connect_transport_systemd(arg_transport
, arg_host
, user
, &busses
[focus
]);
222 r
= bus_connect_transport(arg_transport
, arg_host
, user
, &busses
[focus
]);
224 return log_error_errno(r
, "Failed to connect to bus: %m");
226 (void) sd_bus_set_allow_interactive_authorization(busses
[focus
], arg_ask_password
);
229 *ret
= busses
[focus
];
233 static void release_busses(void) {
236 for (w
= 0; w
< _BUS_FOCUS_MAX
; w
++)
237 busses
[w
] = sd_bus_flush_close_unref(busses
[w
]);
240 static int map_string_no_copy(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
242 const char **p
= userdata
;
245 r
= sd_bus_message_read_basic(m
, SD_BUS_TYPE_STRING
, &s
);
255 static void ask_password_agent_open_if_enabled(void) {
257 /* Open the password agent as a child process if necessary */
259 if (!arg_ask_password
)
262 if (arg_scope
!= UNIT_FILE_SYSTEM
)
265 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
268 ask_password_agent_open();
271 static void polkit_agent_open_if_enabled(void) {
273 /* Open the polkit agent as a child process if necessary */
275 if (!arg_ask_password
)
278 if (arg_scope
!= UNIT_FILE_SYSTEM
)
281 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
287 static OutputFlags
get_output_flags(void) {
289 arg_all
* OUTPUT_SHOW_ALL
|
290 arg_full
* OUTPUT_FULL_WIDTH
|
291 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH
|
292 colors_enabled() * OUTPUT_COLOR
|
293 !arg_quiet
* OUTPUT_WARN_CUTOFF
;
296 static int translate_bus_error_to_exit_status(int r
, const sd_bus_error
*error
) {
299 if (!sd_bus_error_is_set(error
))
302 if (sd_bus_error_has_name(error
, SD_BUS_ERROR_ACCESS_DENIED
) ||
303 sd_bus_error_has_name(error
, BUS_ERROR_ONLY_BY_DEPENDENCY
) ||
304 sd_bus_error_has_name(error
, BUS_ERROR_NO_ISOLATION
) ||
305 sd_bus_error_has_name(error
, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE
))
306 return EXIT_NOPERMISSION
;
308 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
))
309 return EXIT_NOTINSTALLED
;
311 if (sd_bus_error_has_name(error
, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE
) ||
312 sd_bus_error_has_name(error
, SD_BUS_ERROR_NOT_SUPPORTED
))
313 return EXIT_NOTIMPLEMENTED
;
315 if (sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
))
316 return EXIT_NOTCONFIGURED
;
324 static bool install_client_side(void) {
326 /* Decides when to execute enable/disable/... operations
327 * client-side rather than server-side. */
329 if (running_in_chroot() > 0)
332 if (sd_booted() <= 0)
335 if (!isempty(arg_root
))
338 if (arg_scope
== UNIT_FILE_GLOBAL
)
341 /* Unsupported environment variable, mostly for debugging purposes */
342 if (getenv_bool("SYSTEMCTL_INSTALL_CLIENT_SIDE") > 0)
348 static int compare_unit_info(const void *a
, const void *b
) {
349 const UnitInfo
*u
= a
, *v
= b
;
353 /* First, order by machine */
354 if (!u
->machine
&& v
->machine
)
356 if (u
->machine
&& !v
->machine
)
358 if (u
->machine
&& v
->machine
) {
359 r
= strcasecmp(u
->machine
, v
->machine
);
364 /* Second, order by unit type */
365 d1
= strrchr(u
->id
, '.');
366 d2
= strrchr(v
->id
, '.');
368 r
= strcasecmp(d1
, d2
);
373 /* Third, order by name */
374 return strcasecmp(u
->id
, v
->id
);
377 static const char* unit_type_suffix(const char *name
) {
380 dot
= strrchr(name
, '.');
387 static bool output_show_unit(const UnitInfo
*u
, char **patterns
) {
390 if (!strv_fnmatch_or_empty(patterns
, u
->id
, FNM_NOESCAPE
))
393 if (arg_types
&& !strv_find(arg_types
, unit_type_suffix(u
->id
)))
399 /* Note that '--all' is not purely a state filter, but also a
400 * filter that hides units that "follow" other units (which is
401 * used for device units that appear under different names). */
402 if (!isempty(u
->following
))
405 if (!strv_isempty(arg_states
))
408 /* By default show all units except the ones in inactive
409 * state and with no pending job */
413 if (streq(u
->active_state
, "inactive"))
419 static int output_units_list(const UnitInfo
*unit_infos
, unsigned c
) {
420 unsigned circle_len
= 0, id_len
, max_id_len
, load_len
, active_len
, sub_len
, job_len
, desc_len
, max_desc_len
;
422 unsigned n_shown
= 0;
425 max_id_len
= strlen("UNIT");
426 load_len
= strlen("LOAD");
427 active_len
= strlen("ACTIVE");
428 sub_len
= strlen("SUB");
429 job_len
= strlen("JOB");
430 max_desc_len
= strlen("DESCRIPTION");
432 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
433 max_id_len
= MAX(max_id_len
, strlen(u
->id
) + (u
->machine
? strlen(u
->machine
)+1 : 0));
434 load_len
= MAX(load_len
, strlen(u
->load_state
));
435 active_len
= MAX(active_len
, strlen(u
->active_state
));
436 sub_len
= MAX(sub_len
, strlen(u
->sub_state
));
437 max_desc_len
= MAX(max_desc_len
, strlen(u
->description
));
439 if (u
->job_id
!= 0) {
440 job_len
= MAX(job_len
, strlen(u
->job_type
));
444 if (!arg_no_legend
&&
445 (streq(u
->active_state
, "failed") ||
446 STR_IN_SET(u
->load_state
, "error", "not-found", "masked")))
450 if (!arg_full
&& original_stdout_is_tty
) {
453 id_len
= MIN(max_id_len
, 25u); /* as much as it needs, but at most 25 for now */
454 basic_len
= circle_len
+ 1 + id_len
+ 1 + load_len
+ 1 + active_len
+ 1 + sub_len
+ 1;
457 basic_len
+= job_len
+ 1;
459 if (basic_len
< (unsigned) columns()) {
460 unsigned extra_len
, incr
;
461 extra_len
= columns() - basic_len
;
463 /* Either UNIT already got 25, or is fully satisfied.
464 * Grant up to 25 to DESC now. */
465 incr
= MIN(extra_len
, 25u);
469 /* Of the remainder give as much as the ID needs to the ID, and give the rest to the
470 * description but not more than it needs. */
472 incr
= MIN(max_id_len
- id_len
, extra_len
);
474 desc_len
+= MIN(extra_len
- incr
, max_desc_len
- desc_len
);
480 desc_len
= max_desc_len
;
483 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
484 _cleanup_free_
char *e
= NULL
, *j
= NULL
;
485 const char *on_underline
= "", *off_underline
= "";
486 const char *on_loaded
= "", *off_loaded
= "";
487 const char *on_active
= "", *off_active
= "";
488 const char *on_circle
= "", *off_circle
= "";
490 bool circle
= false, underline
= false;
492 if (!n_shown
&& !arg_no_legend
) {
497 printf("%s%-*s %-*s %-*s %-*s ",
501 active_len
, "ACTIVE",
505 printf("%-*s ", job_len
, "JOB");
509 !arg_full
&& arg_no_pager
? (int) desc_len
: -1,
516 if (u
+ 1 < unit_infos
+ c
&&
517 !streq(unit_type_suffix(u
->id
), unit_type_suffix((u
+ 1)->id
))) {
518 on_underline
= ansi_underline();
519 off_underline
= ansi_normal();
523 if (STR_IN_SET(u
->load_state
, "error", "not-found", "masked") && !arg_plain
) {
524 on_circle
= ansi_highlight_yellow();
525 off_circle
= ansi_normal();
527 on_loaded
= underline
? ansi_highlight_red_underline() : ansi_highlight_red();
528 off_loaded
= underline
? on_underline
: ansi_normal();
529 } else if (streq(u
->active_state
, "failed") && !arg_plain
) {
530 on_circle
= ansi_highlight_red();
531 off_circle
= ansi_normal();
533 on_active
= underline
? ansi_highlight_red_underline() : ansi_highlight_red();
534 off_active
= underline
? on_underline
: ansi_normal();
538 j
= strjoin(u
->machine
, ":", u
->id
);
547 e
= ellipsize(id
, id_len
, 33);
555 printf("%s%s%s ", on_circle
, circle
? special_glyph(BLACK_CIRCLE
) : " ", off_circle
);
557 printf("%s%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
559 on_active
, id_len
, id
, off_active
,
560 on_loaded
, load_len
, u
->load_state
, off_loaded
,
561 on_active
, active_len
, u
->active_state
,
562 sub_len
, u
->sub_state
, off_active
,
563 job_count
? job_len
+ 1 : 0, u
->job_id
? u
->job_type
: "");
567 !arg_full
&& arg_no_pager
? (int) desc_len
: -1,
572 if (!arg_no_legend
) {
573 const char *on
, *off
;
577 "LOAD = Reflects whether the unit definition was properly loaded.\n"
578 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
579 "SUB = The low-level unit activation state, values depend on unit type.");
580 puts(job_count
? "JOB = Pending job for the unit.\n" : "");
581 on
= ansi_highlight();
584 on
= ansi_highlight_red();
589 printf("%s%u loaded units listed.%s\n"
590 "To show all installed unit files use 'systemctl list-unit-files'.\n",
593 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
594 "To show all installed unit files use 'systemctl list-unit-files'.\n",
601 static int get_unit_list(
605 UnitInfo
**unit_infos
,
607 sd_bus_message
**_reply
) {
609 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
610 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
611 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
615 bool fallback
= false;
621 r
= sd_bus_message_new_method_call(
624 "org.freedesktop.systemd1",
625 "/org/freedesktop/systemd1",
626 "org.freedesktop.systemd1.Manager",
627 "ListUnitsByPatterns");
629 return bus_log_create_error(r
);
631 r
= sd_bus_message_append_strv(m
, arg_states
);
633 return bus_log_create_error(r
);
635 r
= sd_bus_message_append_strv(m
, patterns
);
637 return bus_log_create_error(r
);
639 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
640 if (r
< 0 && (sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_METHOD
) ||
641 sd_bus_error_has_name(&error
, SD_BUS_ERROR_ACCESS_DENIED
))) {
642 /* Fallback to legacy ListUnitsFiltered method */
644 log_debug_errno(r
, "Failed to list units: %s Falling back to ListUnitsFiltered method.", bus_error_message(&error
, r
));
645 m
= sd_bus_message_unref(m
);
646 sd_bus_error_free(&error
);
648 r
= sd_bus_message_new_method_call(
651 "org.freedesktop.systemd1",
652 "/org/freedesktop/systemd1",
653 "org.freedesktop.systemd1.Manager",
654 "ListUnitsFiltered");
656 return bus_log_create_error(r
);
658 r
= sd_bus_message_append_strv(m
, arg_states
);
660 return bus_log_create_error(r
);
662 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
665 return log_error_errno(r
, "Failed to list units: %s", bus_error_message(&error
, r
));
667 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssssouso)");
669 return bus_log_parse_error(r
);
671 while ((r
= bus_parse_unit_info(reply
, &u
)) > 0) {
674 if (!output_show_unit(&u
, fallback
? patterns
: NULL
))
677 if (!GREEDY_REALLOC(*unit_infos
, size
, c
+1))
680 (*unit_infos
)[c
++] = u
;
683 return bus_log_parse_error(r
);
685 r
= sd_bus_message_exit_container(reply
);
687 return bus_log_parse_error(r
);
695 static void message_set_freep(Set
**set
) {
698 while ((m
= set_steal_first(*set
)))
699 sd_bus_message_unref(m
);
704 static int get_unit_list_recursive(
707 UnitInfo
**_unit_infos
,
711 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
712 _cleanup_(message_set_freep
) Set
*replies
;
713 sd_bus_message
*reply
;
721 replies
= set_new(NULL
);
725 c
= get_unit_list(bus
, NULL
, patterns
, &unit_infos
, 0, &reply
);
729 r
= set_put(replies
, reply
);
731 sd_bus_message_unref(reply
);
736 _cleanup_strv_free_
char **machines
= NULL
;
739 r
= sd_get_machine_names(&machines
);
741 return log_error_errno(r
, "Failed to get machine names: %m");
743 STRV_FOREACH(i
, machines
) {
744 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*container
= NULL
;
747 r
= sd_bus_open_system_machine(&container
, *i
);
749 log_warning_errno(r
, "Failed to connect to container %s, ignoring: %m", *i
);
753 k
= get_unit_list(container
, *i
, patterns
, &unit_infos
, c
, &reply
);
759 r
= set_put(replies
, reply
);
761 sd_bus_message_unref(reply
);
766 *_machines
= machines
;
771 *_unit_infos
= unit_infos
;
780 static int list_units(int argc
, char *argv
[], void *userdata
) {
781 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
782 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
783 _cleanup_strv_free_
char **machines
= NULL
;
787 r
= acquire_bus(BUS_MANAGER
, &bus
);
791 pager_open(arg_no_pager
, false);
793 r
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
797 qsort_safe(unit_infos
, r
, sizeof(UnitInfo
), compare_unit_info
);
798 return output_units_list(unit_infos
, r
);
801 static int get_triggered_units(
806 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
813 r
= sd_bus_get_property_strv(
815 "org.freedesktop.systemd1",
817 "org.freedesktop.systemd1.Unit",
822 return log_error_errno(r
, "Failed to determine triggers: %s", bus_error_message(&error
, r
));
827 static int get_listening(
829 const char* unit_path
,
832 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
833 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
834 const char *type
, *path
;
837 r
= sd_bus_get_property(
839 "org.freedesktop.systemd1",
841 "org.freedesktop.systemd1.Socket",
847 return log_error_errno(r
, "Failed to get list of listening sockets: %s", bus_error_message(&error
, r
));
849 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
851 return bus_log_parse_error(r
);
853 while ((r
= sd_bus_message_read(reply
, "(ss)", &type
, &path
)) > 0) {
855 r
= strv_extend(listening
, type
);
859 r
= strv_extend(listening
, path
);
866 return bus_log_parse_error(r
);
868 r
= sd_bus_message_exit_container(reply
);
870 return bus_log_parse_error(r
);
882 /* Note: triggered is a list here, although it almost certainly
883 * will always be one unit. Nevertheless, dbus API allows for multiple
884 * values, so let's follow that. */
887 /* The strv above is shared. free is set only in the first one. */
891 static int socket_info_compare(const struct socket_info
*a
, const struct socket_info
*b
) {
897 if (!a
->machine
&& b
->machine
)
899 if (a
->machine
&& !b
->machine
)
901 if (a
->machine
&& b
->machine
) {
902 o
= strcasecmp(a
->machine
, b
->machine
);
907 o
= strcmp(a
->path
, b
->path
);
909 o
= strcmp(a
->type
, b
->type
);
914 static int output_sockets_list(struct socket_info
*socket_infos
, unsigned cs
) {
915 struct socket_info
*s
;
916 unsigned pathlen
= strlen("LISTEN"),
917 typelen
= strlen("TYPE") * arg_show_types
,
918 socklen
= strlen("UNIT"),
919 servlen
= strlen("ACTIVATES");
920 const char *on
, *off
;
922 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
926 socklen
= MAX(socklen
, strlen(s
->id
));
928 typelen
= MAX(typelen
, strlen(s
->type
));
929 pathlen
= MAX(pathlen
, strlen(s
->path
) + (s
->machine
? strlen(s
->machine
)+1 : 0));
931 STRV_FOREACH(a
, s
->triggered
)
932 tmp
+= strlen(*a
) + 2*(a
!= s
->triggered
);
933 servlen
= MAX(servlen
, tmp
);
938 printf("%-*s %-*.*s%-*s %s\n",
940 typelen
+ arg_show_types
, typelen
+ arg_show_types
, "TYPE ",
944 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
945 _cleanup_free_
char *j
= NULL
;
950 j
= strjoin(s
->machine
, ":", s
->path
);
958 printf("%-*s %-*s %-*s",
959 pathlen
, path
, typelen
, s
->type
, socklen
, s
->id
);
962 pathlen
, path
, socklen
, s
->id
);
963 STRV_FOREACH(a
, s
->triggered
)
965 a
== s
->triggered
? "" : ",", *a
);
969 on
= ansi_highlight();
974 on
= ansi_highlight_red();
978 if (!arg_no_legend
) {
979 printf("%s%u sockets listed.%s\n", on
, cs
, off
);
981 printf("Pass --all to see loaded but inactive sockets, too.\n");
987 static int list_sockets(int argc
, char *argv
[], void *userdata
) {
988 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
989 _cleanup_strv_free_
char **machines
= NULL
;
990 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
991 _cleanup_free_
struct socket_info
*socket_infos
= NULL
;
993 struct socket_info
*s
;
999 r
= acquire_bus(BUS_MANAGER
, &bus
);
1003 pager_open(arg_no_pager
, false);
1005 n
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
1009 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
1010 _cleanup_strv_free_
char **listening
= NULL
, **triggered
= NULL
;
1013 if (!endswith(u
->id
, ".socket"))
1016 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
1020 c
= get_listening(bus
, u
->unit_path
, &listening
);
1026 if (!GREEDY_REALLOC(socket_infos
, size
, cs
+ c
)) {
1031 for (i
= 0; i
< c
; i
++)
1032 socket_infos
[cs
+ i
] = (struct socket_info
) {
1033 .machine
= u
->machine
,
1035 .type
= listening
[i
*2],
1036 .path
= listening
[i
*2 + 1],
1037 .triggered
= triggered
,
1038 .own_triggered
= i
==0,
1041 /* from this point on we will cleanup those socket_infos */
1044 listening
= triggered
= NULL
; /* avoid cleanup */
1047 qsort_safe(socket_infos
, cs
, sizeof(struct socket_info
),
1048 (__compar_fn_t
) socket_info_compare
);
1050 output_sockets_list(socket_infos
, cs
);
1053 assert(cs
== 0 || socket_infos
);
1054 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
1057 if (s
->own_triggered
)
1058 strv_free(s
->triggered
);
1064 static int get_next_elapse(
1067 dual_timestamp
*next
) {
1069 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1077 r
= sd_bus_get_property_trivial(
1079 "org.freedesktop.systemd1",
1081 "org.freedesktop.systemd1.Timer",
1082 "NextElapseUSecMonotonic",
1087 return log_error_errno(r
, "Failed to get next elapsation time: %s", bus_error_message(&error
, r
));
1089 r
= sd_bus_get_property_trivial(
1091 "org.freedesktop.systemd1",
1093 "org.freedesktop.systemd1.Timer",
1094 "NextElapseUSecRealtime",
1099 return log_error_errno(r
, "Failed to get next elapsation time: %s", bus_error_message(&error
, r
));
1105 static int get_last_trigger(
1110 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1117 r
= sd_bus_get_property_trivial(
1119 "org.freedesktop.systemd1",
1121 "org.freedesktop.systemd1.Timer",
1127 return log_error_errno(r
, "Failed to get last trigger time: %s", bus_error_message(&error
, r
));
1133 const char* machine
;
1136 usec_t last_trigger
;
1140 static int timer_info_compare(const struct timer_info
*a
, const struct timer_info
*b
) {
1146 if (!a
->machine
&& b
->machine
)
1148 if (a
->machine
&& !b
->machine
)
1150 if (a
->machine
&& b
->machine
) {
1151 o
= strcasecmp(a
->machine
, b
->machine
);
1156 if (a
->next_elapse
< b
->next_elapse
)
1158 if (a
->next_elapse
> b
->next_elapse
)
1161 return strcmp(a
->id
, b
->id
);
1164 static int output_timers_list(struct timer_info
*timer_infos
, unsigned n
) {
1165 struct timer_info
*t
;
1167 nextlen
= strlen("NEXT"),
1168 leftlen
= strlen("LEFT"),
1169 lastlen
= strlen("LAST"),
1170 passedlen
= strlen("PASSED"),
1171 unitlen
= strlen("UNIT"),
1172 activatelen
= strlen("ACTIVATES");
1174 const char *on
, *off
;
1176 assert(timer_infos
|| n
== 0);
1178 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1182 if (t
->next_elapse
> 0) {
1183 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1185 format_timestamp(tstamp
, sizeof(tstamp
), t
->next_elapse
);
1186 nextlen
= MAX(nextlen
, strlen(tstamp
) + 1);
1188 format_timestamp_relative(trel
, sizeof(trel
), t
->next_elapse
);
1189 leftlen
= MAX(leftlen
, strlen(trel
));
1192 if (t
->last_trigger
> 0) {
1193 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1195 format_timestamp(tstamp
, sizeof(tstamp
), t
->last_trigger
);
1196 lastlen
= MAX(lastlen
, strlen(tstamp
) + 1);
1198 format_timestamp_relative(trel
, sizeof(trel
), t
->last_trigger
);
1199 passedlen
= MAX(passedlen
, strlen(trel
));
1202 unitlen
= MAX(unitlen
, strlen(t
->id
) + (t
->machine
? strlen(t
->machine
)+1 : 0));
1204 STRV_FOREACH(a
, t
->triggered
)
1205 ul
+= strlen(*a
) + 2*(a
!= t
->triggered
);
1207 activatelen
= MAX(activatelen
, ul
);
1212 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1216 passedlen
, "PASSED",
1220 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1221 _cleanup_free_
char *j
= NULL
;
1223 char tstamp1
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel1
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1224 char tstamp2
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel2
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1227 format_timestamp(tstamp1
, sizeof(tstamp1
), t
->next_elapse
);
1228 format_timestamp_relative(trel1
, sizeof(trel1
), t
->next_elapse
);
1230 format_timestamp(tstamp2
, sizeof(tstamp2
), t
->last_trigger
);
1231 format_timestamp_relative(trel2
, sizeof(trel2
), t
->last_trigger
);
1234 j
= strjoin(t
->machine
, ":", t
->id
);
1241 printf("%-*s %-*s %-*s %-*s %-*s",
1242 nextlen
, tstamp1
, leftlen
, trel1
, lastlen
, tstamp2
, passedlen
, trel2
, unitlen
, unit
);
1244 STRV_FOREACH(a
, t
->triggered
)
1246 a
== t
->triggered
? "" : ",", *a
);
1250 on
= ansi_highlight();
1251 off
= ansi_normal();
1255 on
= ansi_highlight_red();
1256 off
= ansi_normal();
1259 if (!arg_no_legend
) {
1260 printf("%s%u timers listed.%s\n", on
, n
, off
);
1262 printf("Pass --all to see loaded but inactive timers, too.\n");
1268 static usec_t
calc_next_elapse(dual_timestamp
*nw
, dual_timestamp
*next
) {
1274 if (next
->monotonic
!= USEC_INFINITY
&& next
->monotonic
> 0) {
1277 if (next
->monotonic
> nw
->monotonic
)
1278 converted
= nw
->realtime
+ (next
->monotonic
- nw
->monotonic
);
1280 converted
= nw
->realtime
- (nw
->monotonic
- next
->monotonic
);
1282 if (next
->realtime
!= USEC_INFINITY
&& next
->realtime
> 0)
1283 next_elapse
= MIN(converted
, next
->realtime
);
1285 next_elapse
= converted
;
1288 next_elapse
= next
->realtime
;
1293 static int list_timers(int argc
, char *argv
[], void *userdata
) {
1294 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
1295 _cleanup_strv_free_
char **machines
= NULL
;
1296 _cleanup_free_
struct timer_info
*timer_infos
= NULL
;
1297 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
1298 struct timer_info
*t
;
1306 r
= acquire_bus(BUS_MANAGER
, &bus
);
1310 pager_open(arg_no_pager
, false);
1312 n
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
1316 dual_timestamp_get(&nw
);
1318 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
1319 _cleanup_strv_free_
char **triggered
= NULL
;
1320 dual_timestamp next
= DUAL_TIMESTAMP_NULL
;
1323 if (!endswith(u
->id
, ".timer"))
1326 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
1330 r
= get_next_elapse(bus
, u
->unit_path
, &next
);
1334 get_last_trigger(bus
, u
->unit_path
, &last
);
1336 if (!GREEDY_REALLOC(timer_infos
, size
, c
+1)) {
1341 m
= calc_next_elapse(&nw
, &next
);
1343 timer_infos
[c
++] = (struct timer_info
) {
1344 .machine
= u
->machine
,
1347 .last_trigger
= last
,
1348 .triggered
= triggered
,
1351 triggered
= NULL
; /* avoid cleanup */
1354 qsort_safe(timer_infos
, c
, sizeof(struct timer_info
),
1355 (__compar_fn_t
) timer_info_compare
);
1357 output_timers_list(timer_infos
, c
);
1360 for (t
= timer_infos
; t
< timer_infos
+ c
; t
++)
1361 strv_free(t
->triggered
);
1366 static int compare_unit_file_list(const void *a
, const void *b
) {
1367 const char *d1
, *d2
;
1368 const UnitFileList
*u
= a
, *v
= b
;
1370 d1
= strrchr(u
->path
, '.');
1371 d2
= strrchr(v
->path
, '.');
1376 r
= strcasecmp(d1
, d2
);
1381 return strcasecmp(basename(u
->path
), basename(v
->path
));
1384 static bool output_show_unit_file(const UnitFileList
*u
, char **states
, char **patterns
) {
1387 if (!strv_fnmatch_or_empty(patterns
, basename(u
->path
), FNM_NOESCAPE
))
1390 if (!strv_isempty(arg_types
)) {
1393 dot
= strrchr(u
->path
, '.');
1397 if (!strv_find(arg_types
, dot
+1))
1401 if (!strv_isempty(states
) &&
1402 !strv_find(states
, unit_file_state_to_string(u
->state
)))
1408 static void output_unit_file_list(const UnitFileList
*units
, unsigned c
) {
1409 unsigned max_id_len
, id_cols
, state_cols
;
1410 const UnitFileList
*u
;
1412 max_id_len
= strlen("UNIT FILE");
1413 state_cols
= strlen("STATE");
1415 for (u
= units
; u
< units
+ c
; u
++) {
1416 max_id_len
= MAX(max_id_len
, strlen(basename(u
->path
)));
1417 state_cols
= MAX(state_cols
, strlen(unit_file_state_to_string(u
->state
)));
1421 unsigned basic_cols
;
1423 id_cols
= MIN(max_id_len
, 25u);
1424 basic_cols
= 1 + id_cols
+ state_cols
;
1425 if (basic_cols
< (unsigned) columns())
1426 id_cols
+= MIN(columns() - basic_cols
, max_id_len
- id_cols
);
1428 id_cols
= max_id_len
;
1430 if (!arg_no_legend
&& c
> 0)
1431 printf("%s%-*s %-*s%s\n",
1433 id_cols
, "UNIT FILE",
1434 state_cols
, "STATE",
1437 for (u
= units
; u
< units
+ c
; u
++) {
1438 _cleanup_free_
char *e
= NULL
;
1439 const char *on
, *off
, *on_underline
= "", *off_underline
= "";
1441 bool underline
= false;
1443 if (u
+ 1 < units
+ c
&&
1444 !streq(unit_type_suffix(u
->path
), unit_type_suffix((u
+ 1)->path
))) {
1445 on_underline
= ansi_underline();
1446 off_underline
= ansi_normal();
1450 if (IN_SET(u
->state
,
1452 UNIT_FILE_MASKED_RUNTIME
,
1455 on
= underline
? ansi_highlight_red_underline() : ansi_highlight_red();
1456 else if (u
->state
== UNIT_FILE_ENABLED
)
1457 on
= underline
? ansi_highlight_green_underline() : ansi_highlight_green();
1460 off
= off_underline
;
1462 id
= basename(u
->path
);
1464 e
= arg_full
? NULL
: ellipsize(id
, id_cols
, 33);
1466 printf("%s%-*s %s%-*s%s%s\n",
1468 id_cols
, e
? e
: id
,
1469 on
, state_cols
, unit_file_state_to_string(u
->state
), off
,
1474 printf("\n%u unit files listed.\n", c
);
1477 static int list_unit_files(int argc
, char *argv
[], void *userdata
) {
1478 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1479 _cleanup_free_ UnitFileList
*units
= NULL
;
1486 bool fallback
= false;
1488 if (install_client_side()) {
1494 h
= hashmap_new(&string_hash_ops
);
1498 r
= unit_file_get_list(arg_scope
, arg_root
, h
, arg_states
, strv_skip(argv
, 1));
1500 unit_file_list_free(h
);
1501 return log_error_errno(r
, "Failed to get unit file list: %m");
1504 n_units
= hashmap_size(h
);
1506 units
= new(UnitFileList
, n_units
?: 1); /* avoid malloc(0) */
1508 unit_file_list_free(h
);
1512 HASHMAP_FOREACH(u
, h
, i
) {
1513 if (!output_show_unit_file(u
, NULL
, NULL
))
1520 assert(c
<= n_units
);
1525 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
1526 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1529 r
= acquire_bus(BUS_MANAGER
, &bus
);
1533 r
= sd_bus_message_new_method_call(
1536 "org.freedesktop.systemd1",
1537 "/org/freedesktop/systemd1",
1538 "org.freedesktop.systemd1.Manager",
1539 "ListUnitFilesByPatterns");
1541 return bus_log_create_error(r
);
1543 r
= sd_bus_message_append_strv(m
, arg_states
);
1545 return bus_log_create_error(r
);
1547 r
= sd_bus_message_append_strv(m
, strv_skip(argv
, 1));
1549 return bus_log_create_error(r
);
1551 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
1552 if (r
< 0 && sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_METHOD
)) {
1553 /* Fallback to legacy ListUnitFiles method */
1555 log_debug_errno(r
, "Failed to list unit files: %s Falling back to ListUnitsFiles method.", bus_error_message(&error
, r
));
1556 m
= sd_bus_message_unref(m
);
1557 sd_bus_error_free(&error
);
1559 r
= sd_bus_message_new_method_call(
1562 "org.freedesktop.systemd1",
1563 "/org/freedesktop/systemd1",
1564 "org.freedesktop.systemd1.Manager",
1567 return bus_log_create_error(r
);
1569 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
1572 return log_error_errno(r
, "Failed to list unit files: %s", bus_error_message(&error
, r
));
1574 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
1576 return bus_log_parse_error(r
);
1578 while ((r
= sd_bus_message_read(reply
, "(ss)", &path
, &state
)) > 0) {
1580 if (!GREEDY_REALLOC(units
, size
, c
+ 1))
1583 units
[c
] = (struct UnitFileList
) {
1585 unit_file_state_from_string(state
)
1588 if (output_show_unit_file(&units
[c
],
1589 fallback
? arg_states
: NULL
,
1590 fallback
? strv_skip(argv
, 1) : NULL
))
1595 return bus_log_parse_error(r
);
1597 r
= sd_bus_message_exit_container(reply
);
1599 return bus_log_parse_error(r
);
1602 pager_open(arg_no_pager
, false);
1604 qsort_safe(units
, c
, sizeof(UnitFileList
), compare_unit_file_list
);
1605 output_unit_file_list(units
, c
);
1607 if (install_client_side())
1608 for (unit
= units
; unit
< units
+ c
; unit
++)
1614 static int list_dependencies_print(const char *name
, int level
, unsigned int branches
, bool last
) {
1615 _cleanup_free_
char *n
= NULL
;
1616 size_t max_len
= MAX(columns(),20u);
1622 for (i
= level
- 1; i
>= 0; i
--) {
1624 if (len
> max_len
- 3 && !arg_full
) {
1625 printf("%s...\n",max_len
% 2 ? "" : " ");
1628 printf("%s", special_glyph(branches
& (1 << i
) ? TREE_VERTICAL
: TREE_SPACE
));
1632 if (len
> max_len
- 3 && !arg_full
) {
1633 printf("%s...\n",max_len
% 2 ? "" : " ");
1637 printf("%s", special_glyph(last
? TREE_RIGHT
: TREE_BRANCH
));
1641 printf("%s\n", name
);
1645 n
= ellipsize(name
, max_len
-len
, 100);
1653 static int list_dependencies_get_dependencies(sd_bus
*bus
, const char *name
, char ***deps
) {
1655 static const char *dependencies
[_DEPENDENCY_MAX
] = {
1656 [DEPENDENCY_FORWARD
] = "Requires\0"
1661 [DEPENDENCY_REVERSE
] = "RequiredBy\0"
1666 [DEPENDENCY_AFTER
] = "After\0",
1667 [DEPENDENCY_BEFORE
] = "Before\0",
1670 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1671 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1672 _cleanup_strv_free_
char **ret
= NULL
;
1673 _cleanup_free_
char *path
= NULL
;
1679 assert_cc(ELEMENTSOF(dependencies
) == _DEPENDENCY_MAX
);
1681 path
= unit_dbus_path_from_name(name
);
1685 r
= sd_bus_call_method(
1687 "org.freedesktop.systemd1",
1689 "org.freedesktop.DBus.Properties",
1693 "s", "org.freedesktop.systemd1.Unit");
1695 return log_error_errno(r
, "Failed to get properties of %s: %s", name
, bus_error_message(&error
, r
));
1697 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
1699 return bus_log_parse_error(r
);
1701 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
1704 r
= sd_bus_message_read(reply
, "s", &prop
);
1706 return bus_log_parse_error(r
);
1708 if (!nulstr_contains(dependencies
[arg_dependency
], prop
)) {
1709 r
= sd_bus_message_skip(reply
, "v");
1711 return bus_log_parse_error(r
);
1714 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, "as");
1716 return bus_log_parse_error(r
);
1718 r
= bus_message_read_strv_extend(reply
, &ret
);
1720 return bus_log_parse_error(r
);
1722 r
= sd_bus_message_exit_container(reply
);
1724 return bus_log_parse_error(r
);
1727 r
= sd_bus_message_exit_container(reply
);
1729 return bus_log_parse_error(r
);
1733 return bus_log_parse_error(r
);
1735 r
= sd_bus_message_exit_container(reply
);
1737 return bus_log_parse_error(r
);
1739 *deps
= strv_uniq(ret
);
1745 static int list_dependencies_compare(const void *_a
, const void *_b
) {
1746 const char **a
= (const char**) _a
, **b
= (const char**) _b
;
1748 if (unit_name_to_type(*a
) == UNIT_TARGET
&& unit_name_to_type(*b
) != UNIT_TARGET
)
1750 if (unit_name_to_type(*a
) != UNIT_TARGET
&& unit_name_to_type(*b
) == UNIT_TARGET
)
1753 return strcasecmp(*a
, *b
);
1756 static int list_dependencies_one(
1761 unsigned int branches
) {
1763 _cleanup_strv_free_
char **deps
= NULL
;
1771 r
= strv_extend(units
, name
);
1775 r
= list_dependencies_get_dependencies(bus
, name
, &deps
);
1779 qsort_safe(deps
, strv_length(deps
), sizeof (char*), list_dependencies_compare
);
1781 STRV_FOREACH(c
, deps
) {
1782 if (strv_contains(*units
, *c
)) {
1785 r
= list_dependencies_print("...", level
+ 1, (branches
<< 1) | (c
[1] == NULL
? 0 : 1), 1);
1795 UnitActiveState active_state
= _UNIT_ACTIVE_STATE_INVALID
;
1798 (void) get_state_one_unit(bus
, *c
, &active_state
);
1800 switch (active_state
) {
1802 case UNIT_RELOADING
:
1803 case UNIT_ACTIVATING
:
1804 on
= ansi_highlight_green();
1808 case UNIT_DEACTIVATING
:
1813 on
= ansi_highlight_red();
1817 printf("%s%s%s ", on
, special_glyph(BLACK_CIRCLE
), ansi_normal());
1820 r
= list_dependencies_print(*c
, level
, branches
, c
[1] == NULL
);
1824 if (arg_all
|| unit_name_to_type(*c
) == UNIT_TARGET
) {
1825 r
= list_dependencies_one(bus
, *c
, level
+ 1, units
, (branches
<< 1) | (c
[1] == NULL
? 0 : 1));
1832 strv_remove(*units
, name
);
1837 static int list_dependencies(int argc
, char *argv
[], void *userdata
) {
1838 _cleanup_strv_free_
char **units
= NULL
;
1839 _cleanup_free_
char *unit
= NULL
;
1845 r
= unit_name_mangle(argv
[1], UNIT_NAME_NOGLOB
, &unit
);
1847 return log_error_errno(r
, "Failed to mangle unit name: %m");
1851 u
= SPECIAL_DEFAULT_TARGET
;
1853 r
= acquire_bus(BUS_MANAGER
, &bus
);
1857 pager_open(arg_no_pager
, false);
1861 return list_dependencies_one(bus
, u
, 0, &units
, 0);
1864 struct machine_info
{
1868 char *control_group
;
1869 uint32_t n_failed_units
;
1874 static const struct bus_properties_map machine_info_property_map
[] = {
1875 { "SystemState", "s", NULL
, offsetof(struct machine_info
, state
) },
1876 { "NJobs", "u", NULL
, offsetof(struct machine_info
, n_jobs
) },
1877 { "NFailedUnits", "u", NULL
, offsetof(struct machine_info
, n_failed_units
) },
1878 { "ControlGroup", "s", NULL
, offsetof(struct machine_info
, control_group
) },
1879 { "UserspaceTimestamp", "t", NULL
, offsetof(struct machine_info
, timestamp
) },
1883 static void machine_info_clear(struct machine_info
*info
) {
1888 free(info
->control_group
);
1892 static void free_machines_list(struct machine_info
*machine_infos
, int n
) {
1898 for (i
= 0; i
< n
; i
++)
1899 machine_info_clear(&machine_infos
[i
]);
1901 free(machine_infos
);
1904 static int compare_machine_info(const void *a
, const void *b
) {
1905 const struct machine_info
*u
= a
, *v
= b
;
1907 if (u
->is_host
!= v
->is_host
)
1908 return u
->is_host
> v
->is_host
? -1 : 1;
1910 return strcasecmp(u
->name
, v
->name
);
1913 static int get_machine_properties(sd_bus
*bus
, struct machine_info
*mi
) {
1914 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*container
= NULL
;
1920 r
= sd_bus_open_system_machine(&container
, mi
->name
);
1927 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, NULL
, mi
);
1934 static bool output_show_machine(const char *name
, char **patterns
) {
1935 return strv_fnmatch_or_empty(patterns
, name
, FNM_NOESCAPE
);
1938 static int get_machine_list(
1940 struct machine_info
**_machine_infos
,
1943 struct machine_info
*machine_infos
= NULL
;
1944 _cleanup_strv_free_
char **m
= NULL
;
1945 _cleanup_free_
char *hn
= NULL
;
1950 hn
= gethostname_malloc();
1954 if (output_show_machine(hn
, patterns
)) {
1955 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1))
1958 machine_infos
[c
].is_host
= true;
1959 machine_infos
[c
].name
= hn
;
1962 (void) get_machine_properties(bus
, &machine_infos
[c
]);
1966 r
= sd_get_machine_names(&m
);
1968 return log_error_errno(r
, "Failed to get machine list: %m");
1970 STRV_FOREACH(i
, m
) {
1971 _cleanup_free_
char *class = NULL
;
1973 if (!output_show_machine(*i
, patterns
))
1976 sd_machine_get_class(*i
, &class);
1977 if (!streq_ptr(class, "container"))
1980 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1)) {
1981 free_machines_list(machine_infos
, c
);
1985 machine_infos
[c
].is_host
= false;
1986 machine_infos
[c
].name
= strdup(*i
);
1987 if (!machine_infos
[c
].name
) {
1988 free_machines_list(machine_infos
, c
);
1992 (void) get_machine_properties(NULL
, &machine_infos
[c
]);
1996 *_machine_infos
= machine_infos
;
2000 static void output_machines_list(struct machine_info
*machine_infos
, unsigned n
) {
2001 struct machine_info
*m
;
2004 namelen
= sizeof("NAME") - 1,
2005 statelen
= sizeof("STATE") - 1,
2006 failedlen
= sizeof("FAILED") - 1,
2007 jobslen
= sizeof("JOBS") - 1;
2009 assert(machine_infos
|| n
== 0);
2011 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
2012 namelen
= MAX(namelen
, strlen(m
->name
) + (m
->is_host
? sizeof(" (host)") - 1 : 0));
2013 statelen
= MAX(statelen
, strlen_ptr(m
->state
));
2014 failedlen
= MAX(failedlen
, DECIMAL_STR_WIDTH(m
->n_failed_units
));
2015 jobslen
= MAX(jobslen
, DECIMAL_STR_WIDTH(m
->n_jobs
));
2017 if (!arg_plain
&& !streq_ptr(m
->state
, "running"))
2021 if (!arg_no_legend
) {
2025 printf("%-*s %-*s %-*s %-*s\n",
2028 failedlen
, "FAILED",
2032 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
2033 const char *on_state
= "", *off_state
= "";
2034 const char *on_failed
= "", *off_failed
= "";
2035 bool circle
= false;
2037 if (streq_ptr(m
->state
, "degraded")) {
2038 on_state
= ansi_highlight_red();
2039 off_state
= ansi_normal();
2041 } else if (!streq_ptr(m
->state
, "running")) {
2042 on_state
= ansi_highlight_yellow();
2043 off_state
= ansi_normal();
2047 if (m
->n_failed_units
> 0) {
2048 on_failed
= ansi_highlight_red();
2049 off_failed
= ansi_normal();
2051 on_failed
= off_failed
= "";
2054 printf("%s%s%s ", on_state
, circle
? special_glyph(BLACK_CIRCLE
) : " ", off_state
);
2057 printf("%-*s (host) %s%-*s%s %s%*" PRIu32
"%s %*" PRIu32
"\n",
2058 (int) (namelen
- (sizeof(" (host)")-1)), strna(m
->name
),
2059 on_state
, statelen
, strna(m
->state
), off_state
,
2060 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
2061 jobslen
, m
->n_jobs
);
2063 printf("%-*s %s%-*s%s %s%*" PRIu32
"%s %*" PRIu32
"\n",
2064 namelen
, strna(m
->name
),
2065 on_state
, statelen
, strna(m
->state
), off_state
,
2066 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
2067 jobslen
, m
->n_jobs
);
2071 printf("\n%u machines listed.\n", n
);
2074 static int list_machines(int argc
, char *argv
[], void *userdata
) {
2075 struct machine_info
*machine_infos
= NULL
;
2079 if (geteuid() != 0) {
2080 log_error("Must be root.");
2084 r
= acquire_bus(BUS_MANAGER
, &bus
);
2088 r
= get_machine_list(bus
, &machine_infos
, strv_skip(argv
, 1));
2092 pager_open(arg_no_pager
, false);
2094 qsort_safe(machine_infos
, r
, sizeof(struct machine_info
), compare_machine_info
);
2095 output_machines_list(machine_infos
, r
);
2096 free_machines_list(machine_infos
, r
);
2101 static int get_default(int argc
, char *argv
[], void *userdata
) {
2102 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2103 _cleanup_free_
char *_path
= NULL
;
2107 if (install_client_side()) {
2108 r
= unit_file_get_default(arg_scope
, arg_root
, &_path
);
2110 return log_error_errno(r
, "Failed to get default target: %m");
2115 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2118 r
= acquire_bus(BUS_MANAGER
, &bus
);
2122 r
= sd_bus_call_method(
2124 "org.freedesktop.systemd1",
2125 "/org/freedesktop/systemd1",
2126 "org.freedesktop.systemd1.Manager",
2132 return log_error_errno(r
, "Failed to get default target: %s", bus_error_message(&error
, r
));
2134 r
= sd_bus_message_read(reply
, "s", &path
);
2136 return bus_log_parse_error(r
);
2140 printf("%s\n", path
);
2145 static int set_default(int argc
, char *argv
[], void *userdata
) {
2146 _cleanup_free_
char *unit
= NULL
;
2147 UnitFileChange
*changes
= NULL
;
2148 unsigned n_changes
= 0;
2154 r
= unit_name_mangle_with_suffix(argv
[1], UNIT_NAME_NOGLOB
, ".target", &unit
);
2156 return log_error_errno(r
, "Failed to mangle unit name: %m");
2158 if (install_client_side()) {
2159 r
= unit_file_set_default(arg_scope
, UNIT_FILE_FORCE
, arg_root
, unit
, &changes
, &n_changes
);
2160 unit_file_dump_changes(r
, "set default", changes
, n_changes
, arg_quiet
);
2165 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2166 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2169 polkit_agent_open_if_enabled();
2171 r
= acquire_bus(BUS_MANAGER
, &bus
);
2175 r
= sd_bus_call_method(
2177 "org.freedesktop.systemd1",
2178 "/org/freedesktop/systemd1",
2179 "org.freedesktop.systemd1.Manager",
2185 return log_error_errno(r
, "Failed to set default target: %s", bus_error_message(&error
, r
));
2187 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
2191 /* Try to reload if enabled */
2193 r
= daemon_reload(argc
, argv
, userdata
);
2199 unit_file_changes_free(changes
, n_changes
);
2204 static int output_waiting_jobs(sd_bus
*bus
, uint32_t id
, const char *method
, const char *prefix
) {
2205 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2206 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2207 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2213 r
= sd_bus_call_method(
2215 "org.freedesktop.systemd1",
2216 "/org/freedesktop/systemd1",
2217 "org.freedesktop.systemd1.Manager",
2223 return log_debug_errno(r
, "Failed to get waiting jobs for job %" PRIu32
, id
);
2225 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2227 return bus_log_parse_error(r
);
2229 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &other_id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0)
2230 printf("%s %u (%s/%s)\n", prefix
, other_id
, name
, type
);
2232 return bus_log_parse_error(r
);
2234 r
= sd_bus_message_exit_container(reply
);
2236 return bus_log_parse_error(r
);
2243 const char *name
, *type
, *state
;
2246 static void output_jobs_list(sd_bus
*bus
, const struct job_info
* jobs
, unsigned n
, bool skipped
) {
2247 unsigned id_len
, unit_len
, type_len
, state_len
;
2248 const struct job_info
*j
;
2249 const char *on
, *off
;
2250 bool shorten
= false;
2252 assert(n
== 0 || jobs
);
2255 if (!arg_no_legend
) {
2256 on
= ansi_highlight_green();
2257 off
= ansi_normal();
2259 printf("%sNo jobs %s.%s\n", on
, skipped
? "listed" : "running", off
);
2264 pager_open(arg_no_pager
, false);
2266 id_len
= strlen("JOB");
2267 unit_len
= strlen("UNIT");
2268 type_len
= strlen("TYPE");
2269 state_len
= strlen("STATE");
2271 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2272 uint32_t id
= j
->id
;
2273 assert(j
->name
&& j
->type
&& j
->state
);
2275 id_len
= MAX(id_len
, DECIMAL_STR_WIDTH(id
));
2276 unit_len
= MAX(unit_len
, strlen(j
->name
));
2277 type_len
= MAX(type_len
, strlen(j
->type
));
2278 state_len
= MAX(state_len
, strlen(j
->state
));
2281 if (!arg_full
&& id_len
+ 1 + unit_len
+ type_len
+ 1 + state_len
> columns()) {
2282 unit_len
= MAX(33u, columns() - id_len
- type_len
- state_len
- 3);
2287 printf("%*s %-*s %-*s %-*s\n",
2291 state_len
, "STATE");
2293 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2294 _cleanup_free_
char *e
= NULL
;
2296 if (streq(j
->state
, "running")) {
2297 on
= ansi_highlight();
2298 off
= ansi_normal();
2302 e
= shorten
? ellipsize(j
->name
, unit_len
, 33) : NULL
;
2303 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2305 on
, unit_len
, e
? e
: j
->name
, off
,
2307 on
, state_len
, j
->state
, off
);
2310 output_waiting_jobs(bus
, j
->id
, "GetJobAfter", "\twaiting for job");
2311 if (arg_jobs_before
)
2312 output_waiting_jobs(bus
, j
->id
, "GetJobBefore", "\tblocking job");
2315 if (!arg_no_legend
) {
2316 on
= ansi_highlight();
2317 off
= ansi_normal();
2319 printf("\n%s%u jobs listed%s.\n", on
, n
, off
);
2323 static bool output_show_job(struct job_info
*job
, char **patterns
) {
2324 return strv_fnmatch_or_empty(patterns
, job
->name
, FNM_NOESCAPE
);
2327 static int list_jobs(int argc
, char *argv
[], void *userdata
) {
2328 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2329 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2330 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2331 _cleanup_free_
struct job_info
*jobs
= NULL
;
2337 bool skipped
= false;
2339 r
= acquire_bus(BUS_MANAGER
, &bus
);
2343 r
= sd_bus_call_method(
2345 "org.freedesktop.systemd1",
2346 "/org/freedesktop/systemd1",
2347 "org.freedesktop.systemd1.Manager",
2353 return log_error_errno(r
, "Failed to list jobs: %s", bus_error_message(&error
, r
));
2355 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2357 return bus_log_parse_error(r
);
2359 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0) {
2360 struct job_info job
= { id
, name
, type
, state
};
2362 if (!output_show_job(&job
, strv_skip(argv
, 1))) {
2367 if (!GREEDY_REALLOC(jobs
, size
, c
+ 1))
2373 return bus_log_parse_error(r
);
2375 r
= sd_bus_message_exit_container(reply
);
2377 return bus_log_parse_error(r
);
2379 pager_open(arg_no_pager
, false);
2381 output_jobs_list(bus
, jobs
, c
, skipped
);
2385 static int cancel_job(int argc
, char *argv
[], void *userdata
) {
2391 return trivial_method(argc
, argv
, userdata
);
2393 r
= acquire_bus(BUS_MANAGER
, &bus
);
2397 polkit_agent_open_if_enabled();
2399 STRV_FOREACH(name
, strv_skip(argv
, 1)) {
2400 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2404 q
= safe_atou32(*name
, &id
);
2406 return log_error_errno(q
, "Failed to parse job id \"%s\": %m", *name
);
2408 q
= sd_bus_call_method(
2410 "org.freedesktop.systemd1",
2411 "/org/freedesktop/systemd1",
2412 "org.freedesktop.systemd1.Manager",
2418 log_error_errno(q
, "Failed to cancel job %"PRIu32
": %s", id
, bus_error_message(&error
, q
));
2427 static int need_daemon_reload(sd_bus
*bus
, const char *unit
) {
2428 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2432 /* We ignore all errors here, since this is used to show a
2435 /* We don't use unit_dbus_path_from_name() directly since we
2436 * don't want to load the unit if it isn't loaded. */
2438 r
= sd_bus_call_method(
2440 "org.freedesktop.systemd1",
2441 "/org/freedesktop/systemd1",
2442 "org.freedesktop.systemd1.Manager",
2450 r
= sd_bus_message_read(reply
, "o", &path
);
2454 r
= sd_bus_get_property_trivial(
2456 "org.freedesktop.systemd1",
2458 "org.freedesktop.systemd1.Unit",
2468 static void warn_unit_file_changed(const char *name
) {
2471 log_warning("%sWarning:%s %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
2472 ansi_highlight_red(),
2475 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user");
2478 static int unit_file_find_path(LookupPaths
*lp
, const char *unit_name
, char **unit_path
) {
2485 STRV_FOREACH(p
, lp
->search_path
) {
2486 _cleanup_free_
char *path
= NULL
, *lpath
= NULL
;
2489 path
= path_join(NULL
, *p
, unit_name
);
2493 r
= chase_symlinks(path
, arg_root
, 0, &lpath
);
2499 return log_error_errno(r
, "Failed to access path '%s': %m", path
);
2509 static int unit_find_paths(
2511 const char *unit_name
,
2513 char **fragment_path
,
2514 char ***dropin_paths
) {
2516 _cleanup_free_
char *path
= NULL
;
2517 _cleanup_strv_free_
char **dropins
= NULL
;
2521 * Finds where the unit is defined on disk. Returns 0 if the unit
2522 * is not found. Returns 1 if it is found, and sets
2523 * - the path to the unit in *path, if it exists on disk,
2524 * - and a strv of existing drop-ins in *dropins,
2525 * if the arg is not NULL and any dropins were found.
2529 assert(fragment_path
);
2532 if (!install_client_side() && !unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
2533 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2534 _cleanup_free_
char *unit
= NULL
;
2536 unit
= unit_dbus_path_from_name(unit_name
);
2540 r
= sd_bus_get_property_string(
2542 "org.freedesktop.systemd1",
2544 "org.freedesktop.systemd1.Unit",
2549 return log_error_errno(r
, "Failed to get FragmentPath: %s", bus_error_message(&error
, r
));
2552 r
= sd_bus_get_property_strv(
2554 "org.freedesktop.systemd1",
2556 "org.freedesktop.systemd1.Unit",
2561 return log_error_errno(r
, "Failed to get DropInPaths: %s", bus_error_message(&error
, r
));
2564 _cleanup_set_free_ Set
*names
;
2565 _cleanup_free_
char *template = NULL
;
2567 names
= set_new(NULL
);
2571 r
= unit_file_find_path(lp
, unit_name
, &path
);
2576 r
= unit_name_template(unit_name
, &template);
2577 if (r
< 0 && r
!= -EINVAL
)
2578 return log_error_errno(r
, "Failed to determine template name: %m");
2580 r
= unit_file_find_path(lp
, template, &path
);
2587 /* We found the unit file. If we followed symlinks, this name might be
2588 * different then the unit_name with started with. Look for dropins matching
2589 * that "final" name. */
2590 r
= set_put(names
, basename(path
));
2592 /* No unit file, let's look for dropins matching the original name.
2593 * systemd has fairly complicated rules (based on unit type and provenience),
2594 * which units are allowed not to have the main unit file. We err on the
2595 * side of including too many files, and always try to load dropins. */
2596 r
= set_put(names
, unit_name
);
2598 /* The cases where we allow a unit to exist without the main file are
2599 * never valid for templates. Don't try to load dropins in this case. */
2603 return log_error_errno(r
, "Failed to add unit name: %m");
2606 r
= unit_file_find_dropin_conf_paths(arg_root
, lp
->search_path
,
2607 NULL
, names
, &dropins
);
2615 if (!isempty(path
)) {
2616 *fragment_path
= path
;
2621 if (dropin_paths
&& !strv_isempty(dropins
)) {
2622 *dropin_paths
= dropins
;
2627 if (r
== 0 && !arg_force
)
2628 log_error("No files found for %s.", unit_name
);
2633 static int get_state_one_unit(sd_bus
*bus
, const char *name
, UnitActiveState
*active_state
) {
2634 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2635 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2636 _cleanup_free_
char *buf
= NULL
;
2637 UnitActiveState state
;
2642 assert(active_state
);
2644 /* We don't use unit_dbus_path_from_name() directly since we don't want to load the unit unnecessarily, if it
2646 r
= sd_bus_call_method(
2648 "org.freedesktop.systemd1",
2649 "/org/freedesktop/systemd1",
2650 "org.freedesktop.systemd1.Manager",
2656 if (!sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_UNIT
))
2657 return log_error_errno(r
, "Failed to retrieve unit: %s", bus_error_message(&error
, r
));
2659 /* The unit is currently not loaded, hence say it's "inactive", since all units that aren't loaded are
2660 * considered inactive. */
2661 state
= UNIT_INACTIVE
;
2664 r
= sd_bus_message_read(reply
, "o", &path
);
2666 return bus_log_parse_error(r
);
2668 r
= sd_bus_get_property_string(
2670 "org.freedesktop.systemd1",
2672 "org.freedesktop.systemd1.Unit",
2677 return log_error_errno(r
, "Failed to retrieve unit state: %s", bus_error_message(&error
, r
));
2679 state
= unit_active_state_from_string(buf
);
2680 if (state
== _UNIT_ACTIVE_STATE_INVALID
) {
2681 log_error("Invalid unit state '%s' for: %s", buf
, name
);
2686 *active_state
= state
;
2690 static int check_triggering_units(
2694 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2695 _cleanup_free_
char *path
= NULL
, *n
= NULL
, *load_state
= NULL
;
2696 _cleanup_strv_free_
char **triggered_by
= NULL
;
2697 bool print_warning_label
= true;
2698 UnitActiveState active_state
;
2702 r
= unit_name_mangle(name
, UNIT_NAME_NOGLOB
, &n
);
2704 return log_error_errno(r
, "Failed to mangle unit name: %m");
2706 path
= unit_dbus_path_from_name(n
);
2710 r
= sd_bus_get_property_string(
2712 "org.freedesktop.systemd1",
2714 "org.freedesktop.systemd1.Unit",
2719 return log_error_errno(r
, "Failed to get load state of %s: %s", n
, bus_error_message(&error
, r
));
2721 if (streq(load_state
, "masked"))
2724 r
= sd_bus_get_property_strv(
2726 "org.freedesktop.systemd1",
2728 "org.freedesktop.systemd1.Unit",
2733 return log_error_errno(r
, "Failed to get triggered by array of %s: %s", n
, bus_error_message(&error
, r
));
2735 STRV_FOREACH(i
, triggered_by
) {
2736 r
= get_state_one_unit(bus
, *i
, &active_state
);
2740 if (!IN_SET(active_state
, UNIT_ACTIVE
, UNIT_RELOADING
))
2743 if (print_warning_label
) {
2744 log_warning("Warning: Stopping %s, but it can still be activated by:", n
);
2745 print_warning_label
= false;
2748 log_warning(" %s", *i
);
2754 static const struct {
2757 } unit_actions
[] = {
2758 { "start", "StartUnit" },
2759 { "stop", "StopUnit" },
2760 { "condstop", "StopUnit" },
2761 { "reload", "ReloadUnit" },
2762 { "restart", "RestartUnit" },
2763 { "try-restart", "TryRestartUnit" },
2764 { "condrestart", "TryRestartUnit" },
2765 { "reload-or-restart", "ReloadOrRestartUnit" },
2766 { "try-reload-or-restart", "ReloadOrTryRestartUnit" },
2767 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2768 { "condreload", "ReloadOrTryRestartUnit" },
2769 { "force-reload", "ReloadOrTryRestartUnit" }
2772 static const char *verb_to_method(const char *verb
) {
2775 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2776 if (streq_ptr(unit_actions
[i
].verb
, verb
))
2777 return unit_actions
[i
].method
;
2782 static const char *method_to_verb(const char *method
) {
2785 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2786 if (streq_ptr(unit_actions
[i
].method
, method
))
2787 return unit_actions
[i
].verb
;
2799 static void wait_context_free(WaitContext
*c
) {
2800 c
->match
= sd_bus_slot_unref(c
->match
);
2801 c
->event
= sd_event_unref(c
->event
);
2802 c
->unit_paths
= set_free_free(c
->unit_paths
);
2805 static int on_properties_changed(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
2806 WaitContext
*c
= userdata
;
2810 path
= sd_bus_message_get_path(m
);
2811 if (!set_contains(c
->unit_paths
, path
))
2814 /* Check if ActiveState changed to inactive/failed */
2815 /* (s interface, a{sv} changed_properties, as invalidated_properties) */
2816 r
= sd_bus_message_skip(m
, "s");
2818 return bus_log_parse_error(r
);
2820 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "{sv}");
2822 return bus_log_parse_error(r
);
2824 while ((r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
2827 r
= sd_bus_message_read(m
, "s", &s
);
2829 return bus_log_parse_error(r
);
2831 if (streq(s
, "ActiveState")) {
2834 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, "s");
2836 return bus_log_parse_error(r
);
2838 r
= sd_bus_message_read(m
, "s", &s
);
2840 return bus_log_parse_error(r
);
2842 is_failed
= streq(s
, "failed");
2843 if (streq(s
, "inactive") || is_failed
) {
2844 log_debug("%s became %s, dropping from --wait tracking", path
, s
);
2845 free(set_remove(c
->unit_paths
, path
));
2846 c
->any_failed
= c
->any_failed
|| is_failed
;
2848 log_debug("ActiveState on %s changed to %s", path
, s
);
2850 break; /* no need to dissect the rest of the message */
2852 /* other property */
2853 r
= sd_bus_message_skip(m
, "v");
2855 return bus_log_parse_error(r
);
2857 r
= sd_bus_message_exit_container(m
);
2859 return bus_log_parse_error(r
);
2862 return bus_log_parse_error(r
);
2864 if (set_isempty(c
->unit_paths
))
2865 sd_event_exit(c
->event
, EXIT_SUCCESS
);
2870 static int start_unit_one(
2875 sd_bus_error
*error
,
2877 WaitContext
*wait_context
) {
2879 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2889 _cleanup_free_
char *unit_path
= NULL
;
2892 log_debug("Watching for property changes of %s", name
);
2893 r
= sd_bus_call_method(
2895 "org.freedesktop.systemd1",
2896 "/org/freedesktop/systemd1",
2897 "org.freedesktop.systemd1.Manager",
2903 return log_error_errno(r
, "Failed to RefUnit %s: %s", name
, bus_error_message(error
, r
));
2905 unit_path
= unit_dbus_path_from_name(name
);
2909 r
= set_put_strdup(wait_context
->unit_paths
, unit_path
);
2911 return log_error_errno(r
, "Failed to add unit path %s to set: %m", unit_path
);
2913 mt
= strjoina("type='signal',"
2914 "interface='org.freedesktop.DBus.Properties',"
2915 "path='", unit_path
, "',"
2916 "member='PropertiesChanged'");
2917 r
= sd_bus_add_match(bus
, &wait_context
->match
, mt
, on_properties_changed
, wait_context
);
2919 return log_error_errno(r
, "Failed to add match for PropertiesChanged signal: %m");
2922 log_debug("Calling manager for %s on %s, %s", method
, name
, mode
);
2924 r
= sd_bus_call_method(
2926 "org.freedesktop.systemd1",
2927 "/org/freedesktop/systemd1",
2928 "org.freedesktop.systemd1.Manager",
2936 /* There's always a fallback possible for legacy actions. */
2937 if (arg_action
!= ACTION_SYSTEMCTL
)
2940 verb
= method_to_verb(method
);
2942 log_error("Failed to %s %s: %s", verb
, name
, bus_error_message(error
, r
));
2944 if (!sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) &&
2945 !sd_bus_error_has_name(error
, BUS_ERROR_UNIT_MASKED
))
2946 log_error("See %s logs and 'systemctl%s status%s %s' for details.",
2947 arg_scope
== UNIT_FILE_SYSTEM
? "system" : "user",
2948 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user",
2949 name
[0] == '-' ? " --" : "",
2955 r
= sd_bus_message_read(reply
, "o", &path
);
2957 return bus_log_parse_error(r
);
2959 if (need_daemon_reload(bus
, name
) > 0)
2960 warn_unit_file_changed(name
);
2963 log_debug("Adding %s to the set", path
);
2964 r
= bus_wait_for_jobs_add(w
, path
);
2972 static int expand_names(sd_bus
*bus
, char **names
, const char* suffix
, char ***ret
) {
2973 _cleanup_strv_free_
char **mangled
= NULL
, **globs
= NULL
;
2980 STRV_FOREACH(name
, names
) {
2984 r
= unit_name_mangle_with_suffix(*name
, UNIT_NAME_GLOB
, suffix
, &t
);
2986 r
= unit_name_mangle(*name
, UNIT_NAME_GLOB
, &t
);
2988 return log_error_errno(r
, "Failed to mangle name: %m");
2990 if (string_is_glob(t
))
2991 r
= strv_consume(&globs
, t
);
2993 r
= strv_consume(&mangled
, t
);
2998 /* Query the manager only if any of the names are a glob, since
2999 * this is fairly expensive */
3000 if (!strv_isempty(globs
)) {
3001 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
3002 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
3003 size_t allocated
, n
;
3005 r
= get_unit_list(bus
, NULL
, globs
, &unit_infos
, 0, &reply
);
3009 n
= strv_length(mangled
);
3012 for (i
= 0; i
< r
; i
++) {
3013 if (!GREEDY_REALLOC(mangled
, allocated
, n
+2))
3016 mangled
[n
] = strdup(unit_infos
[i
].id
);
3020 mangled
[++n
] = NULL
;
3025 mangled
= NULL
; /* do not free */
3030 static const struct {
3034 } action_table
[_ACTION_MAX
] = {
3035 [ACTION_HALT
] = { SPECIAL_HALT_TARGET
, "halt", "replace-irreversibly" },
3036 [ACTION_POWEROFF
] = { SPECIAL_POWEROFF_TARGET
, "poweroff", "replace-irreversibly" },
3037 [ACTION_REBOOT
] = { SPECIAL_REBOOT_TARGET
, "reboot", "replace-irreversibly" },
3038 [ACTION_KEXEC
] = { SPECIAL_KEXEC_TARGET
, "kexec", "replace-irreversibly" },
3039 [ACTION_RUNLEVEL2
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
3040 [ACTION_RUNLEVEL3
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
3041 [ACTION_RUNLEVEL4
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
3042 [ACTION_RUNLEVEL5
] = { SPECIAL_GRAPHICAL_TARGET
, NULL
, "isolate" },
3043 [ACTION_RESCUE
] = { SPECIAL_RESCUE_TARGET
, "rescue", "isolate" },
3044 [ACTION_EMERGENCY
] = { SPECIAL_EMERGENCY_TARGET
, "emergency", "isolate" },
3045 [ACTION_DEFAULT
] = { SPECIAL_DEFAULT_TARGET
, "default", "isolate" },
3046 [ACTION_EXIT
] = { SPECIAL_EXIT_TARGET
, "exit", "replace-irreversibly" },
3047 [ACTION_SUSPEND
] = { SPECIAL_SUSPEND_TARGET
, "suspend", "replace-irreversibly" },
3048 [ACTION_HIBERNATE
] = { SPECIAL_HIBERNATE_TARGET
, "hibernate", "replace-irreversibly" },
3049 [ACTION_HYBRID_SLEEP
] = { SPECIAL_HYBRID_SLEEP_TARGET
, "hybrid-sleep", "replace-irreversibly" },
3052 static enum action
verb_to_action(const char *verb
) {
3055 for (i
= 0; i
< _ACTION_MAX
; i
++)
3056 if (streq_ptr(action_table
[i
].verb
, verb
))
3059 return _ACTION_INVALID
;
3062 static int start_unit(int argc
, char *argv
[], void *userdata
) {
3063 _cleanup_(bus_wait_for_jobs_freep
) BusWaitForJobs
*w
= NULL
;
3064 const char *method
, *mode
, *one_name
, *suffix
= NULL
;
3065 _cleanup_strv_free_
char **names
= NULL
;
3067 _cleanup_(wait_context_free
) WaitContext wait_context
= {};
3071 if (arg_wait
&& !STR_IN_SET(argv
[0], "start", "restart")) {
3072 log_error("--wait may only be used with the 'start' or 'restart' commands.");
3076 /* we cannot do sender tracking on the private bus, so we need the full
3077 * one for RefUnit to implement --wait */
3078 r
= acquire_bus(arg_wait
? BUS_FULL
: BUS_MANAGER
, &bus
);
3082 ask_password_agent_open_if_enabled();
3083 polkit_agent_open_if_enabled();
3085 if (arg_action
== ACTION_SYSTEMCTL
) {
3088 action
= verb_to_action(argv
[0]);
3090 if (action
!= _ACTION_INVALID
) {
3091 method
= "StartUnit";
3092 mode
= action_table
[action
].mode
;
3093 one_name
= action_table
[action
].target
;
3095 if (streq(argv
[0], "isolate")) {
3096 method
= "StartUnit";
3101 method
= verb_to_method(argv
[0]);
3102 mode
= arg_job_mode
;
3107 assert(arg_action
>= 0 && arg_action
< _ACTION_MAX
);
3108 assert(action_table
[arg_action
].target
);
3109 assert(action_table
[arg_action
].mode
);
3111 method
= "StartUnit";
3112 mode
= action_table
[arg_action
].mode
;
3113 one_name
= action_table
[arg_action
].target
;
3117 names
= strv_new(one_name
, NULL
);
3119 r
= expand_names(bus
, strv_skip(argv
, 1), suffix
, &names
);
3121 return log_error_errno(r
, "Failed to expand names: %m");
3124 if (!arg_no_block
) {
3125 r
= bus_wait_for_jobs_new(bus
, &w
);
3127 return log_error_errno(r
, "Could not watch jobs: %m");
3131 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3133 wait_context
.unit_paths
= set_new(&string_hash_ops
);
3134 if (!wait_context
.unit_paths
)
3137 r
= sd_bus_call_method(
3139 "org.freedesktop.systemd1",
3140 "/org/freedesktop/systemd1",
3141 "org.freedesktop.systemd1.Manager",
3146 return log_error_errno(r
, "Failed to enable subscription: %s", bus_error_message(&error
, r
));
3147 r
= sd_event_default(&wait_context
.event
);
3149 return log_error_errno(r
, "Failed to allocate event loop: %m");
3150 r
= sd_bus_attach_event(bus
, wait_context
.event
, 0);
3152 return log_error_errno(r
, "Failed to attach bus to event loop: %m");
3155 STRV_FOREACH(name
, names
) {
3156 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3159 q
= start_unit_one(bus
, method
, *name
, mode
, &error
, w
, arg_wait
? &wait_context
: NULL
);
3160 if (r
>= 0 && q
< 0)
3161 r
= translate_bus_error_to_exit_status(q
, &error
);
3164 if (!arg_no_block
) {
3165 int q
, arg_count
= 0;
3166 const char* extra_args
[4] = {};
3168 if (arg_scope
!= UNIT_FILE_SYSTEM
)
3169 extra_args
[arg_count
++] = "--user";
3171 assert(IN_SET(arg_transport
, BUS_TRANSPORT_LOCAL
, BUS_TRANSPORT_REMOTE
, BUS_TRANSPORT_MACHINE
));
3172 if (arg_transport
== BUS_TRANSPORT_REMOTE
) {
3173 extra_args
[arg_count
++] = "-H";
3174 extra_args
[arg_count
++] = arg_host
;
3175 } else if (arg_transport
== BUS_TRANSPORT_MACHINE
) {
3176 extra_args
[arg_count
++] = "-M";
3177 extra_args
[arg_count
++] = arg_host
;
3180 q
= bus_wait_for_jobs(w
, arg_quiet
, extra_args
);
3184 /* When stopping units, warn if they can still be triggered by
3185 * another active unit (socket, path, timer) */
3186 if (!arg_quiet
&& streq(method
, "StopUnit"))
3187 STRV_FOREACH(name
, names
)
3188 check_triggering_units(bus
, *name
);
3191 if (r
>= 0 && arg_wait
) {
3193 q
= sd_event_loop(wait_context
.event
);
3195 return log_error_errno(q
, "Failed to run event loop: %m");
3196 if (wait_context
.any_failed
)
3203 #ifdef ENABLE_LOGIND
3204 static int logind_set_wall_message(void) {
3205 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3207 _cleanup_free_
char *m
= NULL
;
3210 r
= acquire_bus(BUS_FULL
, &bus
);
3214 m
= strv_join(arg_wall
, " ");
3218 r
= sd_bus_call_method(
3220 "org.freedesktop.login1",
3221 "/org/freedesktop/login1",
3222 "org.freedesktop.login1.Manager",
3231 return log_warning_errno(r
, "Failed to set wall message, ignoring: %s", bus_error_message(&error
, r
));
3236 /* Ask systemd-logind, which might grant access to unprivileged users
3237 * through PolicyKit */
3238 static int logind_reboot(enum action a
) {
3239 #ifdef ENABLE_LOGIND
3240 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3241 const char *method
, *description
;
3245 r
= acquire_bus(BUS_FULL
, &bus
);
3253 description
= "reboot system";
3256 case ACTION_POWEROFF
:
3257 method
= "PowerOff";
3258 description
= "power off system";
3261 case ACTION_SUSPEND
:
3263 description
= "suspend system";
3266 case ACTION_HIBERNATE
:
3267 method
= "Hibernate";
3268 description
= "hibernate system";
3271 case ACTION_HYBRID_SLEEP
:
3272 method
= "HybridSleep";
3273 description
= "put system into hybrid sleep";
3280 polkit_agent_open_if_enabled();
3281 (void) logind_set_wall_message();
3283 r
= sd_bus_call_method(
3285 "org.freedesktop.login1",
3286 "/org/freedesktop/login1",
3287 "org.freedesktop.login1.Manager",
3291 "b", arg_ask_password
);
3293 return log_error_errno(r
, "Failed to %s via logind: %s", description
, bus_error_message(&error
, r
));
3301 static int logind_check_inhibitors(enum action a
) {
3302 #ifdef ENABLE_LOGIND
3303 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
3304 _cleanup_strv_free_
char **sessions
= NULL
;
3305 const char *what
, *who
, *why
, *mode
;
3312 if (arg_ignore_inhibitors
|| arg_force
> 0)
3324 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
3327 r
= acquire_bus(BUS_FULL
, &bus
);
3331 r
= sd_bus_call_method(
3333 "org.freedesktop.login1",
3334 "/org/freedesktop/login1",
3335 "org.freedesktop.login1.Manager",
3341 /* If logind is not around, then there are no inhibitors... */
3344 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssuu)");
3346 return bus_log_parse_error(r
);
3348 while ((r
= sd_bus_message_read(reply
, "(ssssuu)", &what
, &who
, &why
, &mode
, &uid
, &pid
)) > 0) {
3349 _cleanup_free_
char *comm
= NULL
, *user
= NULL
;
3350 _cleanup_strv_free_
char **sv
= NULL
;
3352 if (!streq(mode
, "block"))
3355 sv
= strv_split(what
, ":");
3359 if (!pid_is_valid((pid_t
) pid
)) {
3360 log_error("Invalid PID %" PRIu32
".", pid
);
3364 if (!strv_contains(sv
,
3369 ACTION_KEXEC
) ? "shutdown" : "sleep"))
3372 get_process_comm(pid
, &comm
);
3373 user
= uid_to_name(uid
);
3375 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT
" \"%s\", user %s), reason is \"%s\".",
3376 who
, (pid_t
) pid
, strna(comm
), strna(user
), why
);
3381 return bus_log_parse_error(r
);
3383 r
= sd_bus_message_exit_container(reply
);
3385 return bus_log_parse_error(r
);
3387 /* Check for current sessions */
3388 sd_get_sessions(&sessions
);
3389 STRV_FOREACH(s
, sessions
) {
3390 _cleanup_free_
char *type
= NULL
, *tty
= NULL
, *seat
= NULL
, *user
= NULL
, *service
= NULL
, *class = NULL
;
3392 if (sd_session_get_uid(*s
, &uid
) < 0 || uid
== getuid())
3395 if (sd_session_get_class(*s
, &class) < 0 || !streq(class, "user"))
3398 if (sd_session_get_type(*s
, &type
) < 0 || !STR_IN_SET(type
, "x11", "tty"))
3401 sd_session_get_tty(*s
, &tty
);
3402 sd_session_get_seat(*s
, &seat
);
3403 sd_session_get_service(*s
, &service
);
3404 user
= uid_to_name(uid
);
3406 log_warning("User %s is logged in on %s.", strna(user
), isempty(tty
) ? (isempty(seat
) ? strna(service
) : seat
) : tty
);
3413 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
3414 action_table
[a
].verb
);
3422 static int logind_prepare_firmware_setup(void) {
3423 #ifdef ENABLE_LOGIND
3424 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3428 r
= acquire_bus(BUS_FULL
, &bus
);
3432 r
= sd_bus_call_method(
3434 "org.freedesktop.login1",
3435 "/org/freedesktop/login1",
3436 "org.freedesktop.login1.Manager",
3437 "SetRebootToFirmwareSetup",
3442 return log_error_errno(r
, "Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error
, r
));
3446 log_error("Cannot remotely indicate to EFI to boot into setup mode.");
3451 static int prepare_firmware_setup(void) {
3454 if (!arg_firmware_setup
)
3457 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
3459 r
= efi_set_reboot_to_firmware(true);
3461 log_debug_errno(r
, "Cannot indicate to EFI to boot into setup mode, will retry via logind: %m");
3466 return logind_prepare_firmware_setup();
3469 static int set_exit_code(uint8_t code
) {
3470 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3474 r
= acquire_bus(BUS_MANAGER
, &bus
);
3478 r
= sd_bus_call_method(
3480 "org.freedesktop.systemd1",
3481 "/org/freedesktop/systemd1",
3482 "org.freedesktop.systemd1.Manager",
3488 return log_error_errno(r
, "Failed to set exit code: %s", bus_error_message(&error
, r
));
3493 static int start_special(int argc
, char *argv
[], void *userdata
) {
3496 bool termination_action
; /* an action that terminates the manager,
3497 * can be performed also by signal. */
3501 a
= verb_to_action(argv
[0]);
3503 r
= logind_check_inhibitors(a
);
3507 if (arg_force
>= 2 && geteuid() != 0) {
3508 log_error("Must be root.");
3512 r
= prepare_firmware_setup();
3516 if (a
== ACTION_REBOOT
&& argc
> 1) {
3517 r
= update_reboot_parameter_and_warn(argv
[1]);
3521 } else if (a
== ACTION_EXIT
&& argc
> 1) {
3524 /* If the exit code is not given on the command line,
3525 * don't reset it to zero: just keep it as it might
3526 * have been set previously. */
3528 r
= safe_atou8(argv
[1], &code
);
3530 return log_error_errno(r
, "Invalid exit code.");
3532 r
= set_exit_code(code
);
3537 termination_action
= IN_SET(a
,
3541 if (termination_action
&& arg_force
>= 2)
3544 if (arg_force
>= 1 &&
3545 (termination_action
|| IN_SET(a
, ACTION_KEXEC
, ACTION_EXIT
)))
3546 r
= trivial_method(argc
, argv
, userdata
);
3548 /* First try logind, to allow authentication with polkit */
3554 ACTION_HYBRID_SLEEP
)) {
3556 r
= logind_reboot(a
);
3559 if (IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
3560 /* requested operation is not supported or already in progress */
3563 /* On all other errors, try low-level operation */
3566 r
= start_unit(argc
, argv
, userdata
);
3569 if (termination_action
&& arg_force
< 2 &&
3570 IN_SET(r
, -ENOENT
, -ETIMEDOUT
))
3571 log_notice("It is possible to perform action directly, see discussion of --force --force in man:systemctl(1).");
3576 static int start_system_special(int argc
, char *argv
[], void *userdata
) {
3577 /* Like start_special above, but raises an error when running in user mode */
3579 if (arg_scope
!= UNIT_FILE_SYSTEM
) {
3580 log_error("Bad action for %s mode.",
3581 arg_scope
== UNIT_FILE_GLOBAL
? "--global" : "--user");
3585 return start_special(argc
, argv
, userdata
);
3588 static int check_unit_generic(int code
, const UnitActiveState good_states
[], int nb_states
, char **args
) {
3589 _cleanup_strv_free_
char **names
= NULL
;
3590 UnitActiveState active_state
;
3596 r
= acquire_bus(BUS_MANAGER
, &bus
);
3600 r
= expand_names(bus
, args
, NULL
, &names
);
3602 return log_error_errno(r
, "Failed to expand names: %m");
3604 STRV_FOREACH(name
, names
) {
3605 r
= get_state_one_unit(bus
, *name
, &active_state
);
3610 puts(unit_active_state_to_string(active_state
));
3612 for (i
= 0; i
< nb_states
; ++i
)
3613 if (good_states
[i
] == active_state
)
3617 /* use the given return code for the case that we won't find
3618 * any unit which matches the list */
3619 return found
? 0 : code
;
3622 static int check_unit_active(int argc
, char *argv
[], void *userdata
) {
3623 const UnitActiveState states
[] = { UNIT_ACTIVE
, UNIT_RELOADING
};
3624 /* According to LSB: 3, "program is not running" */
3625 return check_unit_generic(EXIT_PROGRAM_NOT_RUNNING
, states
, ELEMENTSOF(states
), strv_skip(argv
, 1));
3628 static int check_unit_failed(int argc
, char *argv
[], void *userdata
) {
3629 const UnitActiveState states
[] = { UNIT_FAILED
};
3630 return check_unit_generic(EXIT_PROGRAM_DEAD_AND_PID_EXISTS
, states
, ELEMENTSOF(states
), strv_skip(argv
, 1));
3633 static int kill_unit(int argc
, char *argv
[], void *userdata
) {
3634 _cleanup_strv_free_
char **names
= NULL
;
3635 char *kill_who
= NULL
, **name
;
3639 r
= acquire_bus(BUS_MANAGER
, &bus
);
3643 polkit_agent_open_if_enabled();
3646 arg_kill_who
= "all";
3648 /* --fail was specified */
3649 if (streq(arg_job_mode
, "fail"))
3650 kill_who
= strjoina(arg_kill_who
, "-fail");
3652 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
3654 return log_error_errno(r
, "Failed to expand names: %m");
3656 STRV_FOREACH(name
, names
) {
3657 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3659 q
= sd_bus_call_method(
3661 "org.freedesktop.systemd1",
3662 "/org/freedesktop/systemd1",
3663 "org.freedesktop.systemd1.Manager",
3667 "ssi", *name
, kill_who
? kill_who
: arg_kill_who
, arg_signal
);
3669 log_error_errno(q
, "Failed to kill unit %s: %s", *name
, bus_error_message(&error
, q
));
3678 typedef struct ExecStatusInfo
{
3686 usec_t start_timestamp
;
3687 usec_t exit_timestamp
;
3692 LIST_FIELDS(struct ExecStatusInfo
, exec
);
3695 static void exec_status_info_free(ExecStatusInfo
*i
) {
3704 static int exec_status_info_deserialize(sd_bus_message
*m
, ExecStatusInfo
*i
) {
3705 uint64_t start_timestamp
, exit_timestamp
, start_timestamp_monotonic
, exit_timestamp_monotonic
;
3708 int32_t code
, status
;
3714 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_STRUCT
, "sasbttttuii");
3716 return bus_log_parse_error(r
);
3720 r
= sd_bus_message_read(m
, "s", &path
);
3722 return bus_log_parse_error(r
);
3724 i
->path
= strdup(path
);
3728 r
= sd_bus_message_read_strv(m
, &i
->argv
);
3730 return bus_log_parse_error(r
);
3732 r
= sd_bus_message_read(m
,
3735 &start_timestamp
, &start_timestamp_monotonic
,
3736 &exit_timestamp
, &exit_timestamp_monotonic
,
3740 return bus_log_parse_error(r
);
3743 i
->start_timestamp
= (usec_t
) start_timestamp
;
3744 i
->exit_timestamp
= (usec_t
) exit_timestamp
;
3745 i
->pid
= (pid_t
) pid
;
3749 r
= sd_bus_message_exit_container(m
);
3751 return bus_log_parse_error(r
);
3756 typedef struct UnitCondition
{
3763 LIST_FIELDS(struct UnitCondition
, conditions
);
3766 static void unit_condition_free(UnitCondition
*c
) {
3775 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitCondition
*, unit_condition_free
);
3777 typedef struct UnitStatusInfo
{
3779 const char *load_state
;
3780 const char *active_state
;
3781 const char *sub_state
;
3782 const char *unit_file_state
;
3783 const char *unit_file_preset
;
3785 const char *description
;
3786 const char *following
;
3788 char **documentation
;
3790 const char *fragment_path
;
3791 const char *source_path
;
3792 const char *control_group
;
3794 char **dropin_paths
;
3796 const char *load_error
;
3799 usec_t inactive_exit_timestamp
;
3800 usec_t inactive_exit_timestamp_monotonic
;
3801 usec_t active_enter_timestamp
;
3802 usec_t active_exit_timestamp
;
3803 usec_t inactive_enter_timestamp
;
3805 bool need_daemon_reload
;
3811 const char *status_text
;
3812 const char *pid_file
;
3816 usec_t start_timestamp
;
3817 usec_t exit_timestamp
;
3819 int exit_code
, exit_status
;
3821 usec_t condition_timestamp
;
3822 bool condition_result
;
3823 LIST_HEAD(UnitCondition
, conditions
);
3825 usec_t assert_timestamp
;
3827 bool failed_assert_trigger
;
3828 bool failed_assert_negate
;
3829 const char *failed_assert
;
3830 const char *failed_assert_parameter
;
3831 usec_t next_elapse_real
;
3832 usec_t next_elapse_monotonic
;
3835 unsigned n_accepted
;
3836 unsigned n_connections
;
3839 /* Pairs of type, path */
3843 const char *sysfs_path
;
3845 /* Mount, Automount */
3852 uint64_t memory_current
;
3853 uint64_t memory_low
;
3854 uint64_t memory_high
;
3855 uint64_t memory_max
;
3856 uint64_t memory_swap_max
;
3857 uint64_t memory_limit
;
3858 uint64_t cpu_usage_nsec
;
3859 uint64_t tasks_current
;
3862 LIST_HEAD(ExecStatusInfo
, exec
);
3865 static void unit_status_info_free(UnitStatusInfo
*info
) {
3869 strv_free(info
->documentation
);
3870 strv_free(info
->dropin_paths
);
3871 strv_free(info
->listen
);
3873 while ((c
= info
->conditions
)) {
3874 LIST_REMOVE(conditions
, info
->conditions
, c
);
3875 unit_condition_free(c
);
3878 while ((p
= info
->exec
)) {
3879 LIST_REMOVE(exec
, info
->exec
, p
);
3880 exec_status_info_free(p
);
3884 static void print_status_info(
3890 const char *active_on
, *active_off
, *on
, *off
, *ss
;
3892 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], *s1
;
3893 char since2
[FORMAT_TIMESTAMP_MAX
], *s2
;
3900 /* This shows pretty information about a unit. See
3901 * print_property() for a low-level property printer */
3903 if (streq_ptr(i
->active_state
, "failed")) {
3904 active_on
= ansi_highlight_red();
3905 active_off
= ansi_normal();
3906 } else if (STRPTR_IN_SET(i
->active_state
, "active", "reloading")) {
3907 active_on
= ansi_highlight_green();
3908 active_off
= ansi_normal();
3910 active_on
= active_off
= "";
3912 printf("%s%s%s %s", active_on
, special_glyph(BLACK_CIRCLE
), active_off
, strna(i
->id
));
3914 if (i
->description
&& !streq_ptr(i
->id
, i
->description
))
3915 printf(" - %s", i
->description
);
3920 printf(" Follow: unit currently follows state of %s\n", i
->following
);
3922 if (streq_ptr(i
->load_state
, "error")) {
3923 on
= ansi_highlight_red();
3924 off
= ansi_normal();
3928 path
= i
->source_path
? i
->source_path
: i
->fragment_path
;
3930 if (i
->load_error
!= 0)
3931 printf(" Loaded: %s%s%s (Reason: %s)\n",
3932 on
, strna(i
->load_state
), off
, i
->load_error
);
3933 else if (path
&& !isempty(i
->unit_file_state
) && !isempty(i
->unit_file_preset
))
3934 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
3935 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
, i
->unit_file_preset
);
3936 else if (path
&& !isempty(i
->unit_file_state
))
3937 printf(" Loaded: %s%s%s (%s; %s)\n",
3938 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
);
3940 printf(" Loaded: %s%s%s (%s)\n",
3941 on
, strna(i
->load_state
), off
, path
);
3943 printf(" Loaded: %s%s%s\n",
3944 on
, strna(i
->load_state
), off
);
3947 printf("Transient: yes\n");
3949 if (!strv_isempty(i
->dropin_paths
)) {
3950 _cleanup_free_
char *dir
= NULL
;
3954 STRV_FOREACH(dropin
, i
->dropin_paths
) {
3955 if (! dir
|| last
) {
3956 printf(dir
? " " : " Drop-In: ");
3960 dir
= dirname_malloc(*dropin
);
3966 printf("%s\n %s", dir
,
3967 special_glyph(TREE_RIGHT
));
3970 last
= ! (*(dropin
+ 1) && startswith(*(dropin
+ 1), dir
));
3972 printf("%s%s", basename(*dropin
), last
? "\n" : ", ");
3976 ss
= streq_ptr(i
->active_state
, i
->sub_state
) ? NULL
: i
->sub_state
;
3978 printf(" Active: %s%s (%s)%s",
3979 active_on
, strna(i
->active_state
), ss
, active_off
);
3981 printf(" Active: %s%s%s",
3982 active_on
, strna(i
->active_state
), active_off
);
3984 if (!isempty(i
->result
) && !streq(i
->result
, "success"))
3985 printf(" (Result: %s)", i
->result
);
3987 timestamp
= STRPTR_IN_SET(i
->active_state
, "active", "reloading") ? i
->active_enter_timestamp
:
3988 STRPTR_IN_SET(i
->active_state
, "inactive", "failed") ? i
->inactive_enter_timestamp
:
3989 STRPTR_IN_SET(i
->active_state
, "activating") ? i
->inactive_exit_timestamp
:
3990 i
->active_exit_timestamp
;
3992 s1
= format_timestamp_relative(since1
, sizeof(since1
), timestamp
);
3993 s2
= format_timestamp(since2
, sizeof(since2
), timestamp
);
3996 printf(" since %s; %s\n", s2
, s1
);
3998 printf(" since %s\n", s2
);
4002 if (endswith(i
->id
, ".timer")) {
4003 char tstamp1
[FORMAT_TIMESTAMP_RELATIVE_MAX
],
4004 tstamp2
[FORMAT_TIMESTAMP_MAX
];
4005 char *next_rel_time
, *next_time
;
4006 dual_timestamp nw
, next
= {i
->next_elapse_real
,
4007 i
->next_elapse_monotonic
};
4010 printf(" Trigger: ");
4012 dual_timestamp_get(&nw
);
4013 next_elapse
= calc_next_elapse(&nw
, &next
);
4014 next_rel_time
= format_timestamp_relative(tstamp1
,
4017 next_time
= format_timestamp(tstamp2
,
4021 if (next_time
&& next_rel_time
)
4022 printf("%s; %s\n", next_time
, next_rel_time
);
4027 if (!i
->condition_result
&& i
->condition_timestamp
> 0) {
4031 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->condition_timestamp
);
4032 s2
= format_timestamp(since2
, sizeof(since2
), i
->condition_timestamp
);
4034 printf("Condition: start %scondition failed%s at %s%s%s\n",
4035 ansi_highlight_yellow(), ansi_normal(),
4036 s2
, s1
? "; " : "", strempty(s1
));
4038 LIST_FOREACH(conditions
, c
, i
->conditions
)
4039 if (c
->tristate
< 0)
4042 LIST_FOREACH(conditions
, c
, i
->conditions
)
4043 if (c
->tristate
< 0)
4044 printf(" %s %s=%s%s%s was not met\n",
4045 --n
? special_glyph(TREE_BRANCH
) : special_glyph(TREE_RIGHT
),
4047 c
->trigger
? "|" : "",
4048 c
->negate
? "!" : "",
4052 if (!i
->assert_result
&& i
->assert_timestamp
> 0) {
4053 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->assert_timestamp
);
4054 s2
= format_timestamp(since2
, sizeof(since2
), i
->assert_timestamp
);
4056 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
4057 ansi_highlight_red(), ansi_normal(),
4058 s2
, s1
? "; " : "", strempty(s1
));
4059 if (i
->failed_assert_trigger
)
4060 printf(" none of the trigger assertions were met\n");
4061 else if (i
->failed_assert
)
4062 printf(" %s=%s%s was not met\n",
4064 i
->failed_assert_negate
? "!" : "",
4065 i
->failed_assert_parameter
);
4069 printf(" Device: %s\n", i
->sysfs_path
);
4071 printf(" Where: %s\n", i
->where
);
4073 printf(" What: %s\n", i
->what
);
4075 STRV_FOREACH(t
, i
->documentation
)
4076 printf(" %*s %s\n", 9, t
== i
->documentation
? "Docs:" : "", *t
);
4078 STRV_FOREACH_PAIR(t
, t2
, i
->listen
)
4079 printf(" %*s %s (%s)\n", 9, t
== i
->listen
? "Listen:" : "", *t2
, *t
);
4082 printf(" Accepted: %u; Connected: %u\n", i
->n_accepted
, i
->n_connections
);
4084 LIST_FOREACH(exec
, p
, i
->exec
) {
4085 _cleanup_free_
char *argv
= NULL
;
4088 /* Only show exited processes here */
4092 argv
= strv_join(p
->argv
, " ");
4093 printf(" Process: "PID_FMT
" %s=%s ", p
->pid
, p
->name
, strna(argv
));
4095 good
= is_clean_exit(p
->code
, p
->status
, EXIT_CLEAN_DAEMON
, NULL
);
4097 on
= ansi_highlight_red();
4098 off
= ansi_normal();
4102 printf("%s(code=%s, ", on
, sigchld_code_to_string(p
->code
));
4104 if (p
->code
== CLD_EXITED
) {
4107 printf("status=%i", p
->status
);
4109 c
= exit_status_to_string(p
->status
, EXIT_STATUS_SYSTEMD
);
4114 printf("signal=%s", signal_to_string(p
->status
));
4116 printf(")%s\n", off
);
4118 if (i
->main_pid
== p
->pid
&&
4119 i
->start_timestamp
== p
->start_timestamp
&&
4120 i
->exit_timestamp
== p
->start_timestamp
)
4121 /* Let's not show this twice */
4124 if (p
->pid
== i
->control_pid
)
4128 if (i
->main_pid
> 0 || i
->control_pid
> 0) {
4129 if (i
->main_pid
> 0) {
4130 printf(" Main PID: "PID_FMT
, i
->main_pid
);
4133 _cleanup_free_
char *comm
= NULL
;
4134 (void) get_process_comm(i
->main_pid
, &comm
);
4136 printf(" (%s)", comm
);
4137 } else if (i
->exit_code
> 0) {
4138 printf(" (code=%s, ", sigchld_code_to_string(i
->exit_code
));
4140 if (i
->exit_code
== CLD_EXITED
) {
4143 printf("status=%i", i
->exit_status
);
4145 c
= exit_status_to_string(i
->exit_status
, EXIT_STATUS_SYSTEMD
);
4150 printf("signal=%s", signal_to_string(i
->exit_status
));
4155 if (i
->control_pid
> 0) {
4156 _cleanup_free_
char *c
= NULL
;
4158 if (i
->main_pid
> 0)
4159 fputs("; Control PID: ", stdout
);
4161 fputs("Cntrl PID: ", stdout
); /* if first in column, abbreviated so it fits alignment */
4163 printf(PID_FMT
, i
->control_pid
);
4165 (void) get_process_comm(i
->control_pid
, &c
);
4174 printf(" Status: \"%s\"\n", i
->status_text
);
4175 if (i
->status_errno
> 0)
4176 printf(" Error: %i (%s)\n", i
->status_errno
, strerror(i
->status_errno
));
4178 if (i
->tasks_current
!= (uint64_t) -1) {
4179 printf(" Tasks: %" PRIu64
, i
->tasks_current
);
4181 if (i
->tasks_max
!= (uint64_t) -1)
4182 printf(" (limit: %" PRIu64
")\n", i
->tasks_max
);
4187 if (i
->memory_current
!= (uint64_t) -1) {
4188 char buf
[FORMAT_BYTES_MAX
];
4190 printf(" Memory: %s", format_bytes(buf
, sizeof(buf
), i
->memory_current
));
4192 if (i
->memory_low
> 0 || i
->memory_high
!= CGROUP_LIMIT_MAX
||
4193 i
->memory_max
!= CGROUP_LIMIT_MAX
|| i
->memory_swap_max
!= CGROUP_LIMIT_MAX
||
4194 i
->memory_limit
!= CGROUP_LIMIT_MAX
) {
4195 const char *prefix
= "";
4198 if (i
->memory_low
> 0) {
4199 printf("%slow: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_low
));
4202 if (i
->memory_high
!= CGROUP_LIMIT_MAX
) {
4203 printf("%shigh: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_high
));
4206 if (i
->memory_max
!= CGROUP_LIMIT_MAX
) {
4207 printf("%smax: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_max
));
4210 if (i
->memory_swap_max
!= CGROUP_LIMIT_MAX
) {
4211 printf("%sswap max: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_swap_max
));
4214 if (i
->memory_limit
!= CGROUP_LIMIT_MAX
) {
4215 printf("%slimit: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_limit
));
4223 if (i
->cpu_usage_nsec
!= (uint64_t) -1) {
4224 char buf
[FORMAT_TIMESPAN_MAX
];
4225 printf(" CPU: %s\n", format_timespan(buf
, sizeof(buf
), i
->cpu_usage_nsec
/ NSEC_PER_USEC
, USEC_PER_MSEC
));
4228 if (i
->control_group
) {
4229 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
4230 static const char prefix
[] = " ";
4233 printf(" CGroup: %s\n", i
->control_group
);
4236 if (c
> sizeof(prefix
) - 1)
4237 c
-= sizeof(prefix
) - 1;
4241 r
= unit_show_processes(bus
, i
->id
, i
->control_group
, prefix
, c
, get_output_flags(), &error
);
4246 /* Fallback for older systemd versions where the GetUnitProcesses() call is not yet available */
4248 if (i
->main_pid
> 0)
4249 extra
[k
++] = i
->main_pid
;
4251 if (i
->control_pid
> 0)
4252 extra
[k
++] = i
->control_pid
;
4254 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, prefix
, c
, extra
, k
, get_output_flags());
4256 log_warning_errno(r
, "Failed to dump process list, ignoring: %s", bus_error_message(&error
, r
));
4259 if (i
->id
&& arg_transport
== BUS_TRANSPORT_LOCAL
)
4260 show_journal_by_unit(
4265 i
->inactive_exit_timestamp_monotonic
,
4268 get_output_flags() | OUTPUT_BEGIN_NEWLINE
,
4269 SD_JOURNAL_LOCAL_ONLY
,
4270 arg_scope
== UNIT_FILE_SYSTEM
,
4273 if (i
->need_daemon_reload
)
4274 warn_unit_file_changed(i
->id
);
4277 static void show_unit_help(UnitStatusInfo
*i
) {
4282 if (!i
->documentation
) {
4283 log_info("Documentation for %s not known.", i
->id
);
4287 STRV_FOREACH(p
, i
->documentation
)
4288 if (startswith(*p
, "man:"))
4289 show_man_page(*p
+ 4, false);
4291 log_info("Can't show: %s", *p
);
4294 static int status_property(const char *name
, sd_bus_message
*m
, UnitStatusInfo
*i
, const char *contents
) {
4301 switch (contents
[0]) {
4303 case SD_BUS_TYPE_STRING
: {
4306 r
= sd_bus_message_read(m
, "s", &s
);
4308 return bus_log_parse_error(r
);
4311 if (streq(name
, "Id"))
4313 else if (streq(name
, "LoadState"))
4315 else if (streq(name
, "ActiveState"))
4316 i
->active_state
= s
;
4317 else if (streq(name
, "SubState"))
4319 else if (streq(name
, "Description"))
4321 else if (streq(name
, "FragmentPath"))
4322 i
->fragment_path
= s
;
4323 else if (streq(name
, "SourcePath"))
4326 else if (streq(name
, "DefaultControlGroup")) {
4328 e
= startswith(s
, SYSTEMD_CGROUP_CONTROLLER
":");
4330 i
->control_group
= e
;
4333 else if (streq(name
, "ControlGroup"))
4334 i
->control_group
= s
;
4335 else if (streq(name
, "StatusText"))
4337 else if (streq(name
, "PIDFile"))
4339 else if (streq(name
, "SysFSPath"))
4341 else if (streq(name
, "Where"))
4343 else if (streq(name
, "What"))
4345 else if (streq(name
, "Following"))
4347 else if (streq(name
, "UnitFileState"))
4348 i
->unit_file_state
= s
;
4349 else if (streq(name
, "UnitFilePreset"))
4350 i
->unit_file_preset
= s
;
4351 else if (streq(name
, "Result"))
4358 case SD_BUS_TYPE_BOOLEAN
: {
4361 r
= sd_bus_message_read(m
, "b", &b
);
4363 return bus_log_parse_error(r
);
4365 if (streq(name
, "Accept"))
4367 else if (streq(name
, "NeedDaemonReload"))
4368 i
->need_daemon_reload
= b
;
4369 else if (streq(name
, "ConditionResult"))
4370 i
->condition_result
= b
;
4371 else if (streq(name
, "AssertResult"))
4372 i
->assert_result
= b
;
4373 else if (streq(name
, "Transient"))
4379 case SD_BUS_TYPE_UINT32
: {
4382 r
= sd_bus_message_read(m
, "u", &u
);
4384 return bus_log_parse_error(r
);
4386 if (streq(name
, "MainPID")) {
4388 i
->main_pid
= (pid_t
) u
;
4391 } else if (streq(name
, "ControlPID"))
4392 i
->control_pid
= (pid_t
) u
;
4393 else if (streq(name
, "ExecMainPID")) {
4395 i
->main_pid
= (pid_t
) u
;
4396 } else if (streq(name
, "NAccepted"))
4398 else if (streq(name
, "NConnections"))
4399 i
->n_connections
= u
;
4404 case SD_BUS_TYPE_INT32
: {
4407 r
= sd_bus_message_read(m
, "i", &j
);
4409 return bus_log_parse_error(r
);
4411 if (streq(name
, "ExecMainCode"))
4412 i
->exit_code
= (int) j
;
4413 else if (streq(name
, "ExecMainStatus"))
4414 i
->exit_status
= (int) j
;
4415 else if (streq(name
, "StatusErrno"))
4416 i
->status_errno
= (int) j
;
4421 case SD_BUS_TYPE_UINT64
: {
4424 r
= sd_bus_message_read(m
, "t", &u
);
4426 return bus_log_parse_error(r
);
4428 if (streq(name
, "ExecMainStartTimestamp"))
4429 i
->start_timestamp
= (usec_t
) u
;
4430 else if (streq(name
, "ExecMainExitTimestamp"))
4431 i
->exit_timestamp
= (usec_t
) u
;
4432 else if (streq(name
, "ActiveEnterTimestamp"))
4433 i
->active_enter_timestamp
= (usec_t
) u
;
4434 else if (streq(name
, "InactiveEnterTimestamp"))
4435 i
->inactive_enter_timestamp
= (usec_t
) u
;
4436 else if (streq(name
, "InactiveExitTimestamp"))
4437 i
->inactive_exit_timestamp
= (usec_t
) u
;
4438 else if (streq(name
, "InactiveExitTimestampMonotonic"))
4439 i
->inactive_exit_timestamp_monotonic
= (usec_t
) u
;
4440 else if (streq(name
, "ActiveExitTimestamp"))
4441 i
->active_exit_timestamp
= (usec_t
) u
;
4442 else if (streq(name
, "ConditionTimestamp"))
4443 i
->condition_timestamp
= (usec_t
) u
;
4444 else if (streq(name
, "AssertTimestamp"))
4445 i
->assert_timestamp
= (usec_t
) u
;
4446 else if (streq(name
, "MemoryCurrent"))
4447 i
->memory_current
= u
;
4448 else if (streq(name
, "MemoryLow"))
4450 else if (streq(name
, "MemoryHigh"))
4452 else if (streq(name
, "MemoryMax"))
4454 else if (streq(name
, "MemorySwapMax"))
4455 i
->memory_swap_max
= u
;
4456 else if (streq(name
, "MemoryLimit"))
4457 i
->memory_limit
= u
;
4458 else if (streq(name
, "TasksCurrent"))
4459 i
->tasks_current
= u
;
4460 else if (streq(name
, "TasksMax"))
4462 else if (streq(name
, "CPUUsageNSec"))
4463 i
->cpu_usage_nsec
= u
;
4464 else if (streq(name
, "NextElapseUSecMonotonic"))
4465 i
->next_elapse_monotonic
= u
;
4466 else if (streq(name
, "NextElapseUSecRealtime"))
4467 i
->next_elapse_real
= u
;
4472 case SD_BUS_TYPE_ARRAY
:
4474 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
4475 _cleanup_free_ ExecStatusInfo
*info
= NULL
;
4477 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4479 return bus_log_parse_error(r
);
4481 info
= new0(ExecStatusInfo
, 1);
4485 while ((r
= exec_status_info_deserialize(m
, info
)) > 0) {
4487 info
->name
= strdup(name
);
4491 LIST_PREPEND(exec
, i
->exec
, info
);
4493 info
= new0(ExecStatusInfo
, 1);
4499 return bus_log_parse_error(r
);
4501 r
= sd_bus_message_exit_container(m
);
4503 return bus_log_parse_error(r
);
4507 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
4508 const char *type
, *path
;
4510 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4512 return bus_log_parse_error(r
);
4514 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0) {
4516 r
= strv_extend(&i
->listen
, type
);
4520 r
= strv_extend(&i
->listen
, path
);
4525 return bus_log_parse_error(r
);
4527 r
= sd_bus_message_exit_container(m
);
4529 return bus_log_parse_error(r
);
4533 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "DropInPaths")) {
4535 r
= sd_bus_message_read_strv(m
, &i
->dropin_paths
);
4537 return bus_log_parse_error(r
);
4539 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Documentation")) {
4541 r
= sd_bus_message_read_strv(m
, &i
->documentation
);
4543 return bus_log_parse_error(r
);
4545 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Conditions")) {
4546 const char *cond
, *param
;
4547 int trigger
, negate
;
4550 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
4552 return bus_log_parse_error(r
);
4554 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
4555 _cleanup_(unit_condition_freep
) UnitCondition
*c
= NULL
;
4557 log_debug("%s trigger=%d negate=%d %s →%d", cond
, trigger
, negate
, param
, state
);
4559 c
= new0(UnitCondition
, 1);
4563 c
->name
= strdup(cond
);
4564 c
->param
= strdup(param
);
4565 if (!c
->name
|| !c
->param
)
4568 c
->trigger
= trigger
;
4570 c
->tristate
= state
;
4572 LIST_PREPEND(conditions
, i
->conditions
, c
);
4576 return bus_log_parse_error(r
);
4578 r
= sd_bus_message_exit_container(m
);
4580 return bus_log_parse_error(r
);
4582 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Asserts")) {
4583 const char *cond
, *param
;
4584 int trigger
, negate
;
4587 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
4589 return bus_log_parse_error(r
);
4591 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
4592 log_debug("%s %d %d %s %d", cond
, trigger
, negate
, param
, state
);
4593 if (state
< 0 && (!trigger
|| !i
->failed_assert
)) {
4594 i
->failed_assert
= cond
;
4595 i
->failed_assert_trigger
= trigger
;
4596 i
->failed_assert_negate
= negate
;
4597 i
->failed_assert_parameter
= param
;
4601 return bus_log_parse_error(r
);
4603 r
= sd_bus_message_exit_container(m
);
4605 return bus_log_parse_error(r
);
4612 case SD_BUS_TYPE_STRUCT_BEGIN
:
4614 if (streq(name
, "LoadError")) {
4615 const char *n
, *message
;
4617 r
= sd_bus_message_read(m
, "(ss)", &n
, &message
);
4619 return bus_log_parse_error(r
);
4621 if (!isempty(message
))
4622 i
->load_error
= message
;
4635 r
= sd_bus_message_skip(m
, contents
);
4637 return bus_log_parse_error(r
);
4642 #define print_prop(name, fmt, ...) \
4645 printf(fmt "\n", __VA_ARGS__); \
4647 printf("%s=" fmt "\n", name, __VA_ARGS__); \
4650 static int print_property(const char *name
, sd_bus_message
*m
, const char *contents
) {
4656 /* This is a low-level property printer, see
4657 * print_status_info() for the nicer output */
4659 if (arg_properties
&& !strv_find(arg_properties
, name
)) {
4660 /* skip what we didn't read */
4661 r
= sd_bus_message_skip(m
, contents
);
4665 switch (contents
[0]) {
4667 case SD_BUS_TYPE_STRUCT_BEGIN
:
4669 if (contents
[1] == SD_BUS_TYPE_UINT32
&& streq(name
, "Job")) {
4672 r
= sd_bus_message_read(m
, "(uo)", &u
, NULL
);
4674 return bus_log_parse_error(r
);
4677 print_prop(name
, "%"PRIu32
, u
);
4679 print_prop(name
, "%s", "");
4683 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Unit")) {
4686 r
= sd_bus_message_read(m
, "(so)", &s
, NULL
);
4688 return bus_log_parse_error(r
);
4690 if (arg_all
|| !isempty(s
))
4691 print_prop(name
, "%s", s
);
4695 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "LoadError")) {
4696 const char *a
= NULL
, *b
= NULL
;
4698 r
= sd_bus_message_read(m
, "(ss)", &a
, &b
);
4700 return bus_log_parse_error(r
);
4702 if (arg_all
|| !isempty(a
) || !isempty(b
))
4703 print_prop(name
, "%s \"%s\"", strempty(a
), strempty(b
));
4706 } else if (streq_ptr(name
, "SystemCallFilter")) {
4707 _cleanup_strv_free_
char **l
= NULL
;
4710 r
= sd_bus_message_enter_container(m
, 'r', "bas");
4712 return bus_log_parse_error(r
);
4714 r
= sd_bus_message_read(m
, "b", &whitelist
);
4716 return bus_log_parse_error(r
);
4718 r
= sd_bus_message_read_strv(m
, &l
);
4720 return bus_log_parse_error(r
);
4722 r
= sd_bus_message_exit_container(m
);
4724 return bus_log_parse_error(r
);
4726 if (arg_all
|| whitelist
|| !strv_isempty(l
)) {
4731 fputs(name
, stdout
);
4738 STRV_FOREACH(i
, l
) {
4746 fputc('\n', stdout
);
4754 case SD_BUS_TYPE_ARRAY
:
4756 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "EnvironmentFiles")) {
4760 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sb)");
4762 return bus_log_parse_error(r
);
4764 while ((r
= sd_bus_message_read(m
, "(sb)", &path
, &ignore
)) > 0)
4765 print_prop("EnvironmentFile", "%s (ignore_errors=%s)", path
, yes_no(ignore
));
4768 return bus_log_parse_error(r
);
4770 r
= sd_bus_message_exit_container(m
);
4772 return bus_log_parse_error(r
);
4776 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Paths")) {
4777 const char *type
, *path
;
4779 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4781 return bus_log_parse_error(r
);
4783 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4784 print_prop(type
, "%s", path
);
4786 return bus_log_parse_error(r
);
4788 r
= sd_bus_message_exit_container(m
);
4790 return bus_log_parse_error(r
);
4794 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
4795 const char *type
, *path
;
4797 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4799 return bus_log_parse_error(r
);
4801 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4805 printf("Listen%s=%s\n", type
, path
);
4807 return bus_log_parse_error(r
);
4809 r
= sd_bus_message_exit_container(m
);
4811 return bus_log_parse_error(r
);
4815 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Timers")) {
4817 uint64_t value
, next_elapse
;
4819 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(stt)");
4821 return bus_log_parse_error(r
);
4823 while ((r
= sd_bus_message_read(m
, "(stt)", &base
, &value
, &next_elapse
)) > 0) {
4824 char timespan1
[FORMAT_TIMESPAN_MAX
], timespan2
[FORMAT_TIMESPAN_MAX
];
4826 print_prop(base
, "{ value=%s ; next_elapse=%s }",
4827 format_timespan(timespan1
, sizeof(timespan1
), value
, 0),
4828 format_timespan(timespan2
, sizeof(timespan2
), next_elapse
, 0));
4831 return bus_log_parse_error(r
);
4833 r
= sd_bus_message_exit_container(m
);
4835 return bus_log_parse_error(r
);
4839 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
4840 ExecStatusInfo info
= {};
4842 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4844 return bus_log_parse_error(r
);
4846 while ((r
= exec_status_info_deserialize(m
, &info
)) > 0) {
4847 char timestamp1
[FORMAT_TIMESTAMP_MAX
], timestamp2
[FORMAT_TIMESTAMP_MAX
];
4848 _cleanup_free_
char *tt
;
4850 tt
= strv_join(info
.argv
, " ");
4853 "{ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT
" ; code=%s ; status=%i%s%s }",
4856 yes_no(info
.ignore
),
4857 strna(format_timestamp(timestamp1
, sizeof(timestamp1
), info
.start_timestamp
)),
4858 strna(format_timestamp(timestamp2
, sizeof(timestamp2
), info
.exit_timestamp
)),
4860 sigchld_code_to_string(info
.code
),
4862 info
.code
== CLD_EXITED
? "" : "/",
4863 strempty(info
.code
== CLD_EXITED
? NULL
: signal_to_string(info
.status
)));
4866 strv_free(info
.argv
);
4870 r
= sd_bus_message_exit_container(m
);
4872 return bus_log_parse_error(r
);
4876 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "DeviceAllow")) {
4877 const char *path
, *rwm
;
4879 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4881 return bus_log_parse_error(r
);
4883 while ((r
= sd_bus_message_read(m
, "(ss)", &path
, &rwm
)) > 0)
4884 print_prop(name
, "%s %s", strna(path
), strna(rwm
));
4886 return bus_log_parse_error(r
);
4888 r
= sd_bus_message_exit_container(m
);
4890 return bus_log_parse_error(r
);
4894 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&&
4895 STR_IN_SET(name
, "IODeviceWeight", "BlockIODeviceWeight")) {
4899 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4901 return bus_log_parse_error(r
);
4903 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &weight
)) > 0)
4904 print_prop(name
, "%s %"PRIu64
, strna(path
), weight
);
4906 return bus_log_parse_error(r
);
4908 r
= sd_bus_message_exit_container(m
);
4910 return bus_log_parse_error(r
);
4914 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&&
4915 (cgroup_io_limit_type_from_string(name
) >= 0 ||
4916 STR_IN_SET(name
, "BlockIOReadBandwidth", "BlockIOWriteBandwidth"))) {
4920 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4922 return bus_log_parse_error(r
);
4924 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &bandwidth
)) > 0)
4925 print_prop(name
, "%s %"PRIu64
, strna(path
), bandwidth
);
4927 return bus_log_parse_error(r
);
4929 r
= sd_bus_message_exit_container(m
);
4931 return bus_log_parse_error(r
);
4939 r
= bus_print_property(name
, m
, arg_value
, arg_all
);
4941 return bus_log_parse_error(r
);
4944 r
= sd_bus_message_skip(m
, contents
);
4946 return bus_log_parse_error(r
);
4949 printf("%s=[unprintable]\n", name
);
4955 static int show_one(
4960 bool show_properties
,
4964 static const struct bus_properties_map property_map
[] = {
4965 { "LoadState", "s", map_string_no_copy
, offsetof(UnitStatusInfo
, load_state
) },
4966 { "ActiveState", "s", map_string_no_copy
, offsetof(UnitStatusInfo
, active_state
) },
4970 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
4971 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
4972 _cleanup_set_free_ Set
*found_properties
= NULL
;
4973 _cleanup_(unit_status_info_free
) UnitStatusInfo info
= {
4974 .memory_current
= (uint64_t) -1,
4975 .memory_high
= CGROUP_LIMIT_MAX
,
4976 .memory_max
= CGROUP_LIMIT_MAX
,
4977 .memory_swap_max
= CGROUP_LIMIT_MAX
,
4978 .memory_limit
= (uint64_t) -1,
4979 .cpu_usage_nsec
= (uint64_t) -1,
4980 .tasks_current
= (uint64_t) -1,
4981 .tasks_max
= (uint64_t) -1,
4988 log_debug("Showing one %s", path
);
4990 r
= sd_bus_call_method(
4992 "org.freedesktop.systemd1",
4994 "org.freedesktop.DBus.Properties",
5000 return log_error_errno(r
, "Failed to get properties: %s", bus_error_message(&error
, r
));
5003 r
= bus_message_map_all_properties(reply
, property_map
, &error
, &info
);
5005 return log_error_errno(r
, "Failed to map properties: %s", bus_error_message(&error
, r
));
5007 if (streq_ptr(info
.load_state
, "not-found") && streq_ptr(info
.active_state
, "inactive")) {
5008 log_full(streq(verb
, "status") ? LOG_ERR
: LOG_DEBUG
,
5009 "Unit %s could not be found.", unit
);
5011 if (streq(verb
, "status"))
5012 return EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN
;
5014 if (!streq(verb
, "show"))
5018 r
= sd_bus_message_rewind(reply
, true);
5020 return log_error_errno(r
, "Failed to rewind: %s", bus_error_message(&error
, r
));
5023 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
5025 return bus_log_parse_error(r
);
5032 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
5033 const char *name
, *contents
;
5035 r
= sd_bus_message_read(reply
, "s", &name
);
5037 return bus_log_parse_error(r
);
5039 r
= sd_bus_message_peek_type(reply
, NULL
, &contents
);
5041 return bus_log_parse_error(r
);
5043 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, contents
);
5045 return bus_log_parse_error(r
);
5047 if (show_properties
) {
5048 r
= set_ensure_allocated(&found_properties
, &string_hash_ops
);
5052 r
= set_put(found_properties
, name
);
5053 if (r
< 0 && r
!= EEXIST
)
5056 r
= print_property(name
, reply
, contents
);
5058 r
= status_property(name
, reply
, &info
, contents
);
5062 r
= sd_bus_message_exit_container(reply
);
5064 return bus_log_parse_error(r
);
5066 r
= sd_bus_message_exit_container(reply
);
5068 return bus_log_parse_error(r
);
5071 return bus_log_parse_error(r
);
5073 r
= sd_bus_message_exit_container(reply
);
5075 return bus_log_parse_error(r
);
5078 if (show_properties
) {
5081 STRV_FOREACH(pp
, arg_properties
)
5082 if (!set_contains(found_properties
, *pp
))
5083 log_debug("Property %s does not exist.", *pp
);
5085 } else if (streq(verb
, "help"))
5086 show_unit_help(&info
);
5087 else if (streq(verb
, "status")) {
5088 print_status_info(bus
, &info
, ellipsized
);
5090 if (info
.active_state
&& !STR_IN_SET(info
.active_state
, "active", "reloading"))
5091 r
= EXIT_PROGRAM_NOT_RUNNING
;
5093 r
= EXIT_PROGRAM_RUNNING_OR_SERVICE_OK
;
5099 static int get_unit_dbus_path_by_pid(
5104 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5105 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5109 r
= sd_bus_call_method(
5111 "org.freedesktop.systemd1",
5112 "/org/freedesktop/systemd1",
5113 "org.freedesktop.systemd1.Manager",
5119 return log_error_errno(r
, "Failed to get unit for PID %"PRIu32
": %s", pid
, bus_error_message(&error
, r
));
5121 r
= sd_bus_message_read(reply
, "o", &u
);
5123 return bus_log_parse_error(r
);
5133 static int show_all(
5136 bool show_properties
,
5140 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5141 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
5146 r
= get_unit_list(bus
, NULL
, NULL
, &unit_infos
, 0, &reply
);
5150 pager_open(arg_no_pager
, false);
5154 qsort_safe(unit_infos
, c
, sizeof(UnitInfo
), compare_unit_info
);
5156 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
5157 _cleanup_free_
char *p
= NULL
;
5159 p
= unit_dbus_path_from_name(u
->id
);
5163 r
= show_one(verb
, bus
, p
, u
->id
, show_properties
, new_line
, ellipsized
);
5166 else if (r
> 0 && ret
== 0)
5173 static int show_system_status(sd_bus
*bus
) {
5174 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], since2
[FORMAT_TIMESTAMP_MAX
];
5175 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5176 _cleanup_(machine_info_clear
) struct machine_info mi
= {};
5177 _cleanup_free_
char *hn
= NULL
;
5178 const char *on
, *off
;
5181 hn
= gethostname_malloc();
5185 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, &error
, &mi
);
5187 return log_error_errno(r
, "Failed to read server status: %s", bus_error_message(&error
, r
));
5189 if (streq_ptr(mi
.state
, "degraded")) {
5190 on
= ansi_highlight_red();
5191 off
= ansi_normal();
5192 } else if (!streq_ptr(mi
.state
, "running")) {
5193 on
= ansi_highlight_yellow();
5194 off
= ansi_normal();
5198 printf("%s%s%s %s\n", on
, special_glyph(BLACK_CIRCLE
), off
, arg_host
? arg_host
: hn
);
5200 printf(" State: %s%s%s\n",
5201 on
, strna(mi
.state
), off
);
5203 printf(" Jobs: %" PRIu32
" queued\n", mi
.n_jobs
);
5204 printf(" Failed: %" PRIu32
" units\n", mi
.n_failed_units
);
5206 printf(" Since: %s; %s\n",
5207 format_timestamp(since2
, sizeof(since2
), mi
.timestamp
),
5208 format_timestamp_relative(since1
, sizeof(since1
), mi
.timestamp
));
5210 printf(" CGroup: %s\n", mi
.control_group
?: "/");
5211 if (IN_SET(arg_transport
,
5212 BUS_TRANSPORT_LOCAL
,
5213 BUS_TRANSPORT_MACHINE
)) {
5214 static const char prefix
[] = " ";
5218 if (c
> sizeof(prefix
) - 1)
5219 c
-= sizeof(prefix
) - 1;
5223 show_cgroup(SYSTEMD_CGROUP_CONTROLLER
, strempty(mi
.control_group
), prefix
, c
, get_output_flags());
5229 static int show(int argc
, char *argv
[], void *userdata
) {
5230 bool show_properties
, show_status
, show_help
, new_line
= false;
5231 bool ellipsized
= false;
5237 show_properties
= streq(argv
[0], "show");
5238 show_status
= streq(argv
[0], "status");
5239 show_help
= streq(argv
[0], "help");
5241 if (show_help
&& argc
<= 1) {
5242 log_error("This command expects one or more unit names. Did you mean --help?");
5246 r
= acquire_bus(BUS_MANAGER
, &bus
);
5250 pager_open(arg_no_pager
, false);
5253 /* Increase max number of open files to 16K if we can, we
5254 * might needs this when browsing journal files, which might
5255 * be split up into many files. */
5256 setrlimit_closest(RLIMIT_NOFILE
, &RLIMIT_MAKE_CONST(16384));
5258 /* If no argument is specified inspect the manager itself */
5259 if (show_properties
&& argc
<= 1)
5260 return show_one(argv
[0], bus
, "/org/freedesktop/systemd1", NULL
, show_properties
, &new_line
, &ellipsized
);
5262 if (show_status
&& argc
<= 1) {
5264 show_system_status(bus
);
5268 ret
= show_all(argv
[0], bus
, false, &new_line
, &ellipsized
);
5270 _cleanup_free_
char **patterns
= NULL
;
5273 STRV_FOREACH(name
, strv_skip(argv
, 1)) {
5274 _cleanup_free_
char *path
= NULL
, *unit
= NULL
;
5277 if (safe_atou32(*name
, &id
) < 0) {
5278 if (strv_push(&patterns
, *name
) < 0)
5282 } else if (show_properties
) {
5283 /* Interpret as job id */
5284 if (asprintf(&path
, "/org/freedesktop/systemd1/job/%u", id
) < 0)
5288 /* Interpret as PID */
5289 r
= get_unit_dbus_path_by_pid(bus
, id
, &path
);
5295 r
= unit_name_from_dbus_path(path
, &unit
);
5300 r
= show_one(argv
[0], bus
, path
, unit
, show_properties
, &new_line
, &ellipsized
);
5303 else if (r
> 0 && ret
== 0)
5307 if (!strv_isempty(patterns
)) {
5308 _cleanup_strv_free_
char **names
= NULL
;
5310 r
= expand_names(bus
, patterns
, NULL
, &names
);
5312 return log_error_errno(r
, "Failed to expand names: %m");
5314 STRV_FOREACH(name
, names
) {
5315 _cleanup_free_
char *path
;
5317 path
= unit_dbus_path_from_name(*name
);
5321 r
= show_one(argv
[0], bus
, path
, *name
, show_properties
, &new_line
, &ellipsized
);
5324 if (r
> 0 && ret
== 0)
5330 if (ellipsized
&& !arg_quiet
)
5331 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
5336 static int cat_file(const char *filename
, bool newline
) {
5337 _cleanup_close_
int fd
;
5339 fd
= open(filename
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
5343 printf("%s%s# %s%s\n",
5344 newline
? "\n" : "",
5345 ansi_highlight_blue(),
5350 return copy_bytes(fd
, STDOUT_FILENO
, (uint64_t) -1, 0);
5353 static int cat(int argc
, char *argv
[], void *userdata
) {
5354 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
5355 _cleanup_strv_free_
char **names
= NULL
;
5361 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
5362 log_error("Cannot remotely cat units.");
5366 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
5368 return log_error_errno(r
, "Failed to determine unit paths: %m");
5370 r
= acquire_bus(BUS_MANAGER
, &bus
);
5374 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
5376 return log_error_errno(r
, "Failed to expand names: %m");
5378 pager_open(arg_no_pager
, false);
5380 STRV_FOREACH(name
, names
) {
5381 _cleanup_free_
char *fragment_path
= NULL
;
5382 _cleanup_strv_free_
char **dropin_paths
= NULL
;
5385 r
= unit_find_paths(bus
, *name
, &lp
, &fragment_path
, &dropin_paths
);
5396 if (need_daemon_reload(bus
, *name
) > 0) /* ignore errors (<0), this is informational output */
5398 "%s# Warning: %s changed on disk, the version systemd has loaded is outdated.\n"
5399 "%s# This output shows the current version of the unit's original fragment and drop-in files.\n"
5400 "%s# If fragments or drop-ins were added or removed, they are not properly reflected in this output.\n"
5401 "%s# Run 'systemctl%s daemon-reload' to reload units.%s\n",
5402 ansi_highlight_red(),
5404 ansi_highlight_red(),
5405 ansi_highlight_red(),
5406 ansi_highlight_red(),
5407 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user",
5410 if (fragment_path
) {
5411 r
= cat_file(fragment_path
, false);
5413 return log_warning_errno(r
, "Failed to cat %s: %m", fragment_path
);
5416 STRV_FOREACH(path
, dropin_paths
) {
5417 r
= cat_file(*path
, path
== dropin_paths
);
5419 return log_warning_errno(r
, "Failed to cat %s: %m", *path
);
5426 static int set_property(int argc
, char *argv
[], void *userdata
) {
5427 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5428 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5429 _cleanup_free_
char *n
= NULL
;
5433 r
= acquire_bus(BUS_MANAGER
, &bus
);
5437 polkit_agent_open_if_enabled();
5439 r
= sd_bus_message_new_method_call(
5442 "org.freedesktop.systemd1",
5443 "/org/freedesktop/systemd1",
5444 "org.freedesktop.systemd1.Manager",
5445 "SetUnitProperties");
5447 return bus_log_create_error(r
);
5449 r
= unit_name_mangle(argv
[1], UNIT_NAME_NOGLOB
, &n
);
5451 return log_error_errno(r
, "Failed to mangle unit name: %m");
5453 r
= sd_bus_message_append(m
, "sb", n
, arg_runtime
);
5455 return bus_log_create_error(r
);
5457 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, "(sv)");
5459 return bus_log_create_error(r
);
5461 r
= bus_append_unit_property_assignment_many(m
, strv_skip(argv
, 2));
5465 r
= sd_bus_message_close_container(m
);
5467 return bus_log_create_error(r
);
5469 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5471 return log_error_errno(r
, "Failed to set unit properties on %s: %s", n
, bus_error_message(&error
, r
));
5476 static int daemon_reload(int argc
, char *argv
[], void *userdata
) {
5477 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5478 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5483 r
= acquire_bus(BUS_MANAGER
, &bus
);
5487 polkit_agent_open_if_enabled();
5489 switch (arg_action
) {
5496 method
= "Reexecute";
5499 case ACTION_SYSTEMCTL
:
5500 method
= streq(argv
[0], "daemon-reexec") ? "Reexecute" :
5501 /* "daemon-reload" */ "Reload";
5505 assert_not_reached("Unexpected action");
5508 r
= sd_bus_message_new_method_call(
5511 "org.freedesktop.systemd1",
5512 "/org/freedesktop/systemd1",
5513 "org.freedesktop.systemd1.Manager",
5516 return bus_log_create_error(r
);
5518 /* Note we use an extra-long timeout here. This is because a reload or reexec means generators are rerun which
5519 * are timed out after DEFAULT_TIMEOUT_USEC. Let's use twice that time here, so that the generators can have
5520 * their timeout, and for everything else there's the same time budget in place. */
5522 r
= sd_bus_call(bus
, m
, DEFAULT_TIMEOUT_USEC
* 2, &error
, NULL
);
5524 /* On reexecution, we expect a disconnect, not a reply */
5525 if (IN_SET(r
, -ETIMEDOUT
, -ECONNRESET
) && streq(method
, "Reexecute"))
5528 if (r
< 0 && arg_action
== ACTION_SYSTEMCTL
)
5529 return log_error_errno(r
, "Failed to reload daemon: %s", bus_error_message(&error
, r
));
5531 /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
5532 * old ways of doing things, hence don't log any error in that case here. */
5534 return r
< 0 ? r
: 0;
5537 static int trivial_method(int argc
, char *argv
[], void *userdata
) {
5538 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5543 r
= acquire_bus(BUS_MANAGER
, &bus
);
5547 polkit_agent_open_if_enabled();
5550 streq(argv
[0], "clear-jobs") ||
5551 streq(argv
[0], "cancel") ? "ClearJobs" :
5552 streq(argv
[0], "reset-failed") ? "ResetFailed" :
5553 streq(argv
[0], "halt") ? "Halt" :
5554 streq(argv
[0], "reboot") ? "Reboot" :
5555 streq(argv
[0], "kexec") ? "KExec" :
5556 streq(argv
[0], "exit") ? "Exit" :
5557 /* poweroff */ "PowerOff";
5559 r
= sd_bus_call_method(
5561 "org.freedesktop.systemd1",
5562 "/org/freedesktop/systemd1",
5563 "org.freedesktop.systemd1.Manager",
5568 if (r
< 0 && arg_action
== ACTION_SYSTEMCTL
)
5569 return log_error_errno(r
, "Failed to execute operation: %s", bus_error_message(&error
, r
));
5571 /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
5572 * old ways of doing things, hence don't log any error in that case here. */
5574 return r
< 0 ? r
: 0;
5577 static int reset_failed(int argc
, char *argv
[], void *userdata
) {
5578 _cleanup_strv_free_
char **names
= NULL
;
5584 return trivial_method(argc
, argv
, userdata
);
5586 r
= acquire_bus(BUS_MANAGER
, &bus
);
5590 polkit_agent_open_if_enabled();
5592 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
5594 return log_error_errno(r
, "Failed to expand names: %m");
5596 STRV_FOREACH(name
, names
) {
5597 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5599 q
= sd_bus_call_method(
5601 "org.freedesktop.systemd1",
5602 "/org/freedesktop/systemd1",
5603 "org.freedesktop.systemd1.Manager",
5609 log_error_errno(q
, "Failed to reset failed state of unit %s: %s", *name
, bus_error_message(&error
, q
));
5618 static int print_variable(const char *s
) {
5620 _cleanup_free_
char *esc
= NULL
;
5622 sep
= strchr(s
, '=');
5624 log_error("Invalid environment block");
5628 esc
= shell_maybe_quote(sep
+ 1, ESCAPE_POSIX
);
5632 printf("%.*s=%s\n", (int)(sep
-s
), s
, esc
);
5636 static int show_environment(int argc
, char *argv
[], void *userdata
) {
5637 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5638 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5643 r
= acquire_bus(BUS_MANAGER
, &bus
);
5647 pager_open(arg_no_pager
, false);
5649 r
= sd_bus_get_property(
5651 "org.freedesktop.systemd1",
5652 "/org/freedesktop/systemd1",
5653 "org.freedesktop.systemd1.Manager",
5659 return log_error_errno(r
, "Failed to get environment: %s", bus_error_message(&error
, r
));
5661 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
5663 return bus_log_parse_error(r
);
5665 while ((r
= sd_bus_message_read_basic(reply
, SD_BUS_TYPE_STRING
, &text
)) > 0) {
5666 r
= print_variable(text
);
5671 return bus_log_parse_error(r
);
5673 r
= sd_bus_message_exit_container(reply
);
5675 return bus_log_parse_error(r
);
5680 static int switch_root(int argc
, char *argv
[], void *userdata
) {
5681 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5682 _cleanup_free_
char *cmdline_init
= NULL
;
5683 const char *root
, *init
;
5687 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
5688 log_error("Cannot switch root remotely.");
5692 if (argc
< 2 || argc
> 3) {
5693 log_error("Wrong number of arguments.");
5702 r
= parse_env_file("/proc/cmdline", WHITESPACE
,
5703 "init", &cmdline_init
,
5706 log_debug_errno(r
, "Failed to parse /proc/cmdline: %m");
5708 init
= cmdline_init
;
5711 init
= empty_to_null(init
);
5713 const char *root_systemd_path
= NULL
, *root_init_path
= NULL
;
5715 root_systemd_path
= strjoina(root
, "/" SYSTEMD_BINARY_PATH
);
5716 root_init_path
= strjoina(root
, "/", init
);
5718 /* If the passed init is actually the same as the
5719 * systemd binary, then let's suppress it. */
5720 if (files_same(root_init_path
, root_systemd_path
, 0) > 0)
5724 /* Instruct PID1 to exclude us from its killing spree applied during
5725 * the transition. Otherwise we would exit with a failure status even
5726 * though the switch to the new root has succeed. */
5727 argv_cmdline
[0] = '@';
5729 r
= acquire_bus(BUS_MANAGER
, &bus
);
5733 /* If we are slow to exit after the root switch, the new systemd instance
5734 * will send us a signal to terminate. Just ignore it and exit normally.
5735 * This way the unit does not end up as failed.
5737 r
= ignore_signals(SIGTERM
, -1);
5739 log_warning_errno(r
, "Failed to change disposition of SIGTERM to ignore: %m");
5741 log_debug("Switching root - root: %s; init: %s", root
, strna(init
));
5743 r
= sd_bus_call_method(
5745 "org.freedesktop.systemd1",
5746 "/org/freedesktop/systemd1",
5747 "org.freedesktop.systemd1.Manager",
5753 (void) default_signals(SIGTERM
, -1);
5755 return log_error_errno(r
, "Failed to switch root: %s", bus_error_message(&error
, r
));
5761 static int set_environment(int argc
, char *argv
[], void *userdata
) {
5762 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5763 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5771 r
= acquire_bus(BUS_MANAGER
, &bus
);
5775 polkit_agent_open_if_enabled();
5777 method
= streq(argv
[0], "set-environment")
5779 : "UnsetEnvironment";
5781 r
= sd_bus_message_new_method_call(
5784 "org.freedesktop.systemd1",
5785 "/org/freedesktop/systemd1",
5786 "org.freedesktop.systemd1.Manager",
5789 return bus_log_create_error(r
);
5791 r
= sd_bus_message_append_strv(m
, strv_skip(argv
, 1));
5793 return bus_log_create_error(r
);
5795 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5797 return log_error_errno(r
, "Failed to set environment: %s", bus_error_message(&error
, r
));
5802 static int import_environment(int argc
, char *argv
[], void *userdata
) {
5803 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5804 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5808 r
= acquire_bus(BUS_MANAGER
, &bus
);
5812 polkit_agent_open_if_enabled();
5814 r
= sd_bus_message_new_method_call(
5817 "org.freedesktop.systemd1",
5818 "/org/freedesktop/systemd1",
5819 "org.freedesktop.systemd1.Manager",
5822 return bus_log_create_error(r
);
5825 r
= sd_bus_message_append_strv(m
, environ
);
5829 r
= sd_bus_message_open_container(m
, 'a', "s");
5831 return bus_log_create_error(r
);
5833 STRV_FOREACH(a
, strv_skip(argv
, 1)) {
5835 if (!env_name_is_valid(*a
)) {
5836 log_error("Not a valid environment variable name: %s", *a
);
5840 STRV_FOREACH(b
, environ
) {
5843 eq
= startswith(*b
, *a
);
5844 if (eq
&& *eq
== '=') {
5846 r
= sd_bus_message_append(m
, "s", *b
);
5848 return bus_log_create_error(r
);
5855 r
= sd_bus_message_close_container(m
);
5858 return bus_log_create_error(r
);
5860 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5862 return log_error_errno(r
, "Failed to import environment: %s", bus_error_message(&error
, r
));
5867 static int enable_sysv_units(const char *verb
, char **args
) {
5870 #if defined(HAVE_SYSV_COMPAT)
5871 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
5874 /* Processes all SysV units, and reshuffles the array so that afterwards only the native units remain */
5876 if (arg_scope
!= UNIT_FILE_SYSTEM
)
5879 if (getenv_bool("SYSTEMCTL_SKIP_SYSV") > 0)
5882 if (!STR_IN_SET(verb
,
5888 r
= lookup_paths_init(&paths
, arg_scope
, LOOKUP_PATHS_EXCLUDE_GENERATED
, arg_root
);
5895 const char *argv
[] = {
5896 ROOTLIBEXECDIR
"/systemd-sysv-install",
5903 _cleanup_free_
char *p
= NULL
, *q
= NULL
, *l
= NULL
;
5904 bool found_native
= false, found_sysv
;
5913 if (!endswith(name
, ".service"))
5916 if (path_is_absolute(name
))
5919 j
= unit_file_exists(arg_scope
, &paths
, name
);
5920 if (j
< 0 && !IN_SET(j
, -ELOOP
, -ERFKILL
, -EADDRNOTAVAIL
))
5921 return log_error_errno(j
, "Failed to lookup unit file state: %m");
5922 found_native
= j
!= 0;
5924 /* If we have both a native unit and a SysV script, enable/disable them both (below); for is-enabled,
5925 * prefer the native unit */
5926 if (found_native
&& streq(verb
, "is-enabled"))
5929 p
= path_join(arg_root
, SYSTEM_SYSVINIT_PATH
, name
);
5933 p
[strlen(p
) - strlen(".service")] = 0;
5934 found_sysv
= access(p
, F_OK
) >= 0;
5940 log_info("Synchronizing state of %s with SysV service script with %s.", name
, argv
[0]);
5942 log_info("%s is not a native service, redirecting to systemd-sysv-install.", name
);
5945 if (!isempty(arg_root
))
5946 argv
[c
++] = q
= strappend("--root=", arg_root
);
5949 argv
[c
++] = basename(p
);
5952 l
= strv_join((char**)argv
, " ");
5957 log_info("Executing: %s", l
);
5961 return log_error_errno(errno
, "Failed to fork: %m");
5962 else if (pid
== 0) {
5965 (void) reset_all_signal_handlers();
5966 (void) reset_signal_mask();
5968 execv(argv
[0], (char**) argv
);
5969 log_error_errno(errno
, "Failed to execute %s: %m", argv
[0]);
5970 _exit(EXIT_FAILURE
);
5973 j
= wait_for_terminate(pid
, &status
);
5975 return log_error_errno(j
, "Failed to wait for child: %m");
5977 if (status
.si_code
== CLD_EXITED
) {
5978 if (streq(verb
, "is-enabled")) {
5979 if (status
.si_status
== 0) {
5988 } else if (status
.si_status
!= 0)
5989 return -EBADE
; /* We don't warn here, under the assumption the script already showed an explanation */
5991 log_error("Unexpected waitid() result.");
5998 /* Remove this entry, so that we don't try enabling it as native unit */
6001 assert(args
[f
] == name
);
6002 strv_remove(args
, name
);
6009 static int mangle_names(char **original_names
, char ***mangled_names
) {
6010 char **i
, **l
, **name
;
6013 l
= i
= new(char*, strv_length(original_names
) + 1);
6017 STRV_FOREACH(name
, original_names
) {
6019 /* When enabling units qualified path names are OK,
6020 * too, hence allow them explicitly. */
6022 if (is_path(*name
)) {
6029 r
= unit_name_mangle(*name
, UNIT_NAME_NOGLOB
, i
);
6033 return log_error_errno(r
, "Failed to mangle unit name: %m");
6046 static int normalize_filenames(char **names
) {
6050 STRV_FOREACH(u
, names
)
6051 if (!path_is_absolute(*u
)) {
6052 char* normalized_path
;
6054 if (!isempty(arg_root
)) {
6055 log_error("Non-absolute paths are not allowed when --root is used: %s", *u
);
6059 if (!strchr(*u
,'/')) {
6060 log_error("Link argument does contain at least one directory separator: %s", *u
);
6064 r
= path_make_absolute_cwd(*u
, &normalized_path
);
6068 free_and_replace(*u
, normalized_path
);
6074 static int normalize_names(char **names
, bool warn_if_path
) {
6076 bool was_path
= false;
6078 STRV_FOREACH(u
, names
) {
6084 r
= free_and_strdup(u
, basename(*u
));
6086 return log_error_errno(r
, "Failed to normalize unit file path: %m");
6091 if (warn_if_path
&& was_path
)
6092 log_warning("Warning: Can't execute disable on the unit file path. Proceeding with the unit name.");
6097 static int unit_exists(const char *unit
) {
6098 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6099 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6100 _cleanup_free_
char *path
= NULL
;
6101 static const struct bus_properties_map property_map
[] = {
6102 { "LoadState", "s", map_string_no_copy
, offsetof(UnitStatusInfo
, load_state
) },
6103 { "ActiveState", "s", map_string_no_copy
, offsetof(UnitStatusInfo
, active_state
)},
6106 UnitStatusInfo info
= {};
6110 path
= unit_dbus_path_from_name(unit
);
6114 r
= acquire_bus(BUS_MANAGER
, &bus
);
6118 r
= sd_bus_call_method(
6120 "org.freedesktop.systemd1",
6122 "org.freedesktop.DBus.Properties",
6128 return log_error_errno(r
, "Failed to get properties: %s", bus_error_message(&error
, r
));
6130 r
= bus_message_map_all_properties(reply
, property_map
, &error
, &info
);
6132 return log_error_errno(r
, "Failed to map properties: %s", bus_error_message(&error
, r
));
6134 return !streq_ptr(info
.load_state
, "not-found") || !streq_ptr(info
.active_state
, "inactive");
6137 static int enable_unit(int argc
, char *argv
[], void *userdata
) {
6138 _cleanup_strv_free_
char **names
= NULL
;
6139 const char *verb
= argv
[0];
6140 UnitFileChange
*changes
= NULL
;
6141 unsigned n_changes
= 0;
6142 int carries_install_info
= -1;
6143 bool ignore_carries_install_info
= arg_quiet
;
6149 r
= mangle_names(strv_skip(argv
, 1), &names
);
6153 r
= enable_sysv_units(verb
, names
);
6157 /* If the operation was fully executed by the SysV compat, let's finish early */
6158 if (strv_isempty(names
)) {
6159 if (arg_no_reload
|| install_client_side())
6161 return daemon_reload(argc
, argv
, userdata
);
6164 if (streq(verb
, "disable")) {
6165 r
= normalize_names(names
, true);
6170 if (streq(verb
, "link")) {
6171 r
= normalize_filenames(names
);
6176 if (install_client_side()) {
6177 UnitFileFlags flags
;
6179 flags
= args_to_flags();
6180 if (streq(verb
, "enable")) {
6181 r
= unit_file_enable(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6182 carries_install_info
= r
;
6183 } else if (streq(verb
, "disable"))
6184 r
= unit_file_disable(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6185 else if (streq(verb
, "reenable")) {
6186 r
= unit_file_reenable(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6187 carries_install_info
= r
;
6188 } else if (streq(verb
, "link"))
6189 r
= unit_file_link(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6190 else if (streq(verb
, "preset")) {
6191 r
= unit_file_preset(arg_scope
, flags
, arg_root
, names
, arg_preset_mode
, &changes
, &n_changes
);
6192 } else if (streq(verb
, "mask"))
6193 r
= unit_file_mask(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6194 else if (streq(verb
, "unmask"))
6195 r
= unit_file_unmask(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6196 else if (streq(verb
, "revert"))
6197 r
= unit_file_revert(arg_scope
, arg_root
, names
, &changes
, &n_changes
);
6199 assert_not_reached("Unknown verb");
6201 unit_file_dump_changes(r
, verb
, changes
, n_changes
, arg_quiet
);
6206 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
, *m
= NULL
;
6207 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6208 bool expect_carries_install_info
= false;
6209 bool send_runtime
= true, send_force
= true, send_preset_mode
= false;
6213 if (STR_IN_SET(verb
, "mask", "unmask")) {
6214 r
= unit_exists(*names
);
6218 log_notice("Unit %s does not exist, proceeding anyway.", *names
);
6221 r
= acquire_bus(BUS_MANAGER
, &bus
);
6225 polkit_agent_open_if_enabled();
6227 if (streq(verb
, "enable")) {
6228 method
= "EnableUnitFiles";
6229 expect_carries_install_info
= true;
6230 } else if (streq(verb
, "disable")) {
6231 method
= "DisableUnitFiles";
6233 } else if (streq(verb
, "reenable")) {
6234 method
= "ReenableUnitFiles";
6235 expect_carries_install_info
= true;
6236 } else if (streq(verb
, "link"))
6237 method
= "LinkUnitFiles";
6238 else if (streq(verb
, "preset")) {
6240 if (arg_preset_mode
!= UNIT_FILE_PRESET_FULL
) {
6241 method
= "PresetUnitFilesWithMode";
6242 send_preset_mode
= true;
6244 method
= "PresetUnitFiles";
6246 expect_carries_install_info
= true;
6247 ignore_carries_install_info
= true;
6248 } else if (streq(verb
, "mask"))
6249 method
= "MaskUnitFiles";
6250 else if (streq(verb
, "unmask")) {
6251 method
= "UnmaskUnitFiles";
6253 } else if (streq(verb
, "revert")) {
6254 method
= "RevertUnitFiles";
6255 send_runtime
= send_force
= false;
6257 assert_not_reached("Unknown verb");
6259 r
= sd_bus_message_new_method_call(
6262 "org.freedesktop.systemd1",
6263 "/org/freedesktop/systemd1",
6264 "org.freedesktop.systemd1.Manager",
6267 return bus_log_create_error(r
);
6269 r
= sd_bus_message_append_strv(m
, names
);
6271 return bus_log_create_error(r
);
6273 if (send_preset_mode
) {
6274 r
= sd_bus_message_append(m
, "s", unit_file_preset_mode_to_string(arg_preset_mode
));
6276 return bus_log_create_error(r
);
6280 r
= sd_bus_message_append(m
, "b", arg_runtime
);
6282 return bus_log_create_error(r
);
6286 r
= sd_bus_message_append(m
, "b", arg_force
);
6288 return bus_log_create_error(r
);
6291 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
6293 return log_error_errno(r
, "Failed to %s unit: %s", verb
, bus_error_message(&error
, r
));
6295 if (expect_carries_install_info
) {
6296 r
= sd_bus_message_read(reply
, "b", &carries_install_info
);
6298 return bus_log_parse_error(r
);
6301 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
6305 /* Try to reload if enabled */
6307 r
= daemon_reload(argc
, argv
, userdata
);
6312 if (carries_install_info
== 0 && !ignore_carries_install_info
)
6313 log_warning("The unit files have no installation config (WantedBy, RequiredBy, Also, Alias\n"
6314 "settings in the [Install] section, and DefaultInstance for template units).\n"
6315 "This means they are not meant to be enabled using systemctl.\n"
6316 "Possible reasons for having this kind of units are:\n"
6317 "1) A unit may be statically enabled by being symlinked from another unit's\n"
6318 " .wants/ or .requires/ directory.\n"
6319 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
6320 " a requirement dependency on it.\n"
6321 "3) A unit may be started when needed via activation (socket, path, timer,\n"
6322 " D-Bus, udev, scripted systemctl call, ...).\n"
6323 "4) In case of template units, the unit is meant to be enabled with some\n"
6324 " instance name specified.");
6326 if (arg_now
&& STR_IN_SET(argv
[0], "enable", "disable", "mask")) {
6330 r
= acquire_bus(BUS_MANAGER
, &bus
);
6334 len
= strv_length(names
);
6336 char *new_args
[len
+ 2];
6338 new_args
[0] = (char*) (streq(argv
[0], "enable") ? "start" : "stop");
6339 for (i
= 0; i
< len
; i
++)
6340 new_args
[i
+ 1] = basename(names
[i
]);
6341 new_args
[i
+ 1] = NULL
;
6343 r
= start_unit(len
+ 1, new_args
, userdata
);
6348 unit_file_changes_free(changes
, n_changes
);
6353 static int add_dependency(int argc
, char *argv
[], void *userdata
) {
6354 _cleanup_strv_free_
char **names
= NULL
;
6355 _cleanup_free_
char *target
= NULL
;
6356 const char *verb
= argv
[0];
6357 UnitFileChange
*changes
= NULL
;
6358 unsigned n_changes
= 0;
6365 r
= unit_name_mangle_with_suffix(argv
[1], UNIT_NAME_NOGLOB
, ".target", &target
);
6367 return log_error_errno(r
, "Failed to mangle unit name: %m");
6369 r
= mangle_names(strv_skip(argv
, 2), &names
);
6373 if (streq(verb
, "add-wants"))
6375 else if (streq(verb
, "add-requires"))
6376 dep
= UNIT_REQUIRES
;
6378 assert_not_reached("Unknown verb");
6380 if (install_client_side()) {
6381 r
= unit_file_add_dependency(arg_scope
, args_to_flags(), arg_root
, names
, target
, dep
, &changes
, &n_changes
);
6382 unit_file_dump_changes(r
, "add dependency on", changes
, n_changes
, arg_quiet
);
6387 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
, *m
= NULL
;
6388 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6391 r
= acquire_bus(BUS_MANAGER
, &bus
);
6395 polkit_agent_open_if_enabled();
6397 r
= sd_bus_message_new_method_call(
6400 "org.freedesktop.systemd1",
6401 "/org/freedesktop/systemd1",
6402 "org.freedesktop.systemd1.Manager",
6403 "AddDependencyUnitFiles");
6405 return bus_log_create_error(r
);
6407 r
= sd_bus_message_append_strv(m
, names
);
6409 return bus_log_create_error(r
);
6411 r
= sd_bus_message_append(m
, "ssbb", target
, unit_dependency_to_string(dep
), arg_runtime
, arg_force
);
6413 return bus_log_create_error(r
);
6415 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
6417 return log_error_errno(r
, "Failed to add dependency: %s", bus_error_message(&error
, r
));
6419 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
6423 if (arg_no_reload
) {
6428 r
= daemon_reload(argc
, argv
, userdata
);
6432 unit_file_changes_free(changes
, n_changes
);
6437 static int preset_all(int argc
, char *argv
[], void *userdata
) {
6438 UnitFileChange
*changes
= NULL
;
6439 unsigned n_changes
= 0;
6442 if (install_client_side()) {
6443 r
= unit_file_preset_all(arg_scope
, args_to_flags(), arg_root
, arg_preset_mode
, &changes
, &n_changes
);
6444 unit_file_dump_changes(r
, "preset", changes
, n_changes
, arg_quiet
);
6449 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6450 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6453 r
= acquire_bus(BUS_MANAGER
, &bus
);
6457 polkit_agent_open_if_enabled();
6459 r
= sd_bus_call_method(
6461 "org.freedesktop.systemd1",
6462 "/org/freedesktop/systemd1",
6463 "org.freedesktop.systemd1.Manager",
6464 "PresetAllUnitFiles",
6468 unit_file_preset_mode_to_string(arg_preset_mode
),
6472 return log_error_errno(r
, "Failed to preset all units: %s", bus_error_message(&error
, r
));
6474 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
6478 if (arg_no_reload
) {
6483 r
= daemon_reload(argc
, argv
, userdata
);
6487 unit_file_changes_free(changes
, n_changes
);
6492 static int show_installation_targets_client_side(const char *name
) {
6493 UnitFileChange
*changes
= NULL
;
6494 unsigned n_changes
= 0, i
;
6495 UnitFileFlags flags
;
6499 p
= STRV_MAKE(name
);
6500 flags
= UNIT_FILE_DRY_RUN
|
6501 (arg_runtime
? UNIT_FILE_RUNTIME
: 0);
6503 r
= unit_file_disable(UNIT_FILE_SYSTEM
, flags
, NULL
, p
, &changes
, &n_changes
);
6505 return log_error_errno(r
, "Failed to get file links for %s: %m", name
);
6507 for (i
= 0; i
< n_changes
; i
++)
6508 if (changes
[i
].type
== UNIT_FILE_UNLINK
)
6509 printf(" %s\n", changes
[i
].path
);
6514 static int show_installation_targets(sd_bus
*bus
, const char *name
) {
6515 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6516 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6520 r
= sd_bus_call_method(
6522 "org.freedesktop.systemd1",
6523 "/org/freedesktop/systemd1",
6524 "org.freedesktop.systemd1.Manager",
6528 "sb", name
, arg_runtime
);
6530 return log_error_errno(r
, "Failed to get unit file links for %s: %s", name
, bus_error_message(&error
, r
));
6532 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
6534 return bus_log_parse_error(r
);
6536 while ((r
= sd_bus_message_read(reply
, "s", &link
)) > 0)
6537 printf(" %s\n", link
);
6540 return bus_log_parse_error(r
);
6542 r
= sd_bus_message_exit_container(reply
);
6544 return bus_log_parse_error(r
);
6549 static int unit_is_enabled(int argc
, char *argv
[], void *userdata
) {
6551 _cleanup_strv_free_
char **names
= NULL
;
6556 r
= mangle_names(strv_skip(argv
, 1), &names
);
6560 r
= enable_sysv_units(argv
[0], names
);
6566 if (install_client_side()) {
6567 STRV_FOREACH(name
, names
) {
6568 UnitFileState state
;
6570 r
= unit_file_get_state(arg_scope
, arg_root
, *name
, &state
);
6572 return log_error_errno(r
, "Failed to get unit file state for %s: %m", *name
);
6576 UNIT_FILE_ENABLED_RUNTIME
,
6579 UNIT_FILE_GENERATED
))
6583 puts(unit_file_state_to_string(state
));
6585 r
= show_installation_targets_client_side(*name
);
6594 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6597 r
= acquire_bus(BUS_MANAGER
, &bus
);
6601 STRV_FOREACH(name
, names
) {
6602 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6605 r
= sd_bus_call_method(
6607 "org.freedesktop.systemd1",
6608 "/org/freedesktop/systemd1",
6609 "org.freedesktop.systemd1.Manager",
6615 return log_error_errno(r
, "Failed to get unit file state for %s: %s", *name
, bus_error_message(&error
, r
));
6617 r
= sd_bus_message_read(reply
, "s", &s
);
6619 return bus_log_parse_error(r
);
6621 if (STR_IN_SET(s
, "enabled", "enabled-runtime", "static", "indirect", "generated"))
6627 r
= show_installation_targets(bus
, *name
);
6635 return enabled
? EXIT_SUCCESS
: EXIT_FAILURE
;
6638 static int is_system_running(int argc
, char *argv
[], void *userdata
) {
6639 _cleanup_free_
char *state
= NULL
;
6643 if (running_in_chroot() > 0 || (arg_transport
== BUS_TRANSPORT_LOCAL
&& !sd_booted())) {
6646 return EXIT_FAILURE
;
6649 r
= acquire_bus(BUS_MANAGER
, &bus
);
6653 r
= sd_bus_get_property_string(
6655 "org.freedesktop.systemd1",
6656 "/org/freedesktop/systemd1",
6657 "org.freedesktop.systemd1.Manager",
6670 return streq(state
, "running") ? EXIT_SUCCESS
: EXIT_FAILURE
;
6673 static int create_edit_temp_file(const char *new_path
, const char *original_path
, char **ret_tmp_fn
) {
6674 _cleanup_free_
char *t
= NULL
;
6678 assert(original_path
);
6681 r
= tempfn_random(new_path
, NULL
, &t
);
6683 return log_error_errno(r
, "Failed to determine temporary filename for \"%s\": %m", new_path
);
6685 r
= mkdir_parents(new_path
, 0755);
6687 return log_error_errno(r
, "Failed to create directories for \"%s\": %m", new_path
);
6689 r
= copy_file(original_path
, t
, 0, 0644, 0, COPY_REFLINK
);
6694 return log_error_errno(r
, "Failed to create temporary file \"%s\": %m", t
);
6697 return log_error_errno(r
, "Failed to create temporary file for \"%s\": %m", new_path
);
6705 static int get_file_to_edit(
6706 const LookupPaths
*paths
,
6710 _cleanup_free_
char *path
= NULL
, *run
= NULL
;
6715 path
= strjoin(paths
->persistent_config
, "/", name
);
6720 run
= strjoin(paths
->runtime_config
, "/", name
);
6726 if (access(path
, F_OK
) >= 0) {
6727 log_error("Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.", run
, path
);
6741 static int unit_file_create_new(
6742 const LookupPaths
*paths
,
6743 const char *unit_name
,
6745 char **ret_new_path
,
6746 char **ret_tmp_path
) {
6748 char *tmp_new_path
, *tmp_tmp_path
, *ending
;
6752 assert(ret_new_path
);
6753 assert(ret_tmp_path
);
6755 ending
= strjoina(unit_name
, suffix
);
6756 r
= get_file_to_edit(paths
, ending
, &tmp_new_path
);
6760 r
= create_edit_temp_file(tmp_new_path
, tmp_new_path
, &tmp_tmp_path
);
6766 *ret_new_path
= tmp_new_path
;
6767 *ret_tmp_path
= tmp_tmp_path
;
6772 static int unit_file_create_copy(
6773 const LookupPaths
*paths
,
6774 const char *unit_name
,
6775 const char *fragment_path
,
6776 char **ret_new_path
,
6777 char **ret_tmp_path
) {
6779 char *tmp_new_path
, *tmp_tmp_path
;
6782 assert(fragment_path
);
6784 assert(ret_new_path
);
6785 assert(ret_tmp_path
);
6787 r
= get_file_to_edit(paths
, unit_name
, &tmp_new_path
);
6791 if (!path_equal(fragment_path
, tmp_new_path
) && access(tmp_new_path
, F_OK
) == 0) {
6794 r
= ask_char(&response
, "yn", "\"%s\" already exists. Overwrite with \"%s\"? [(y)es, (n)o] ", tmp_new_path
, fragment_path
);
6799 if (response
!= 'y') {
6800 log_warning("%s ignored", unit_name
);
6802 return -EKEYREJECTED
;
6806 r
= create_edit_temp_file(tmp_new_path
, fragment_path
, &tmp_tmp_path
);
6812 *ret_new_path
= tmp_new_path
;
6813 *ret_tmp_path
= tmp_tmp_path
;
6818 static int run_editor(char **paths
) {
6826 return log_error_errno(errno
, "Failed to fork: %m");
6830 char *editor
, **editor_args
= NULL
;
6831 char **tmp_path
, **original_path
, *p
;
6832 unsigned n_editor_args
= 0, i
= 1;
6835 (void) reset_all_signal_handlers();
6836 (void) reset_signal_mask();
6838 argc
= strv_length(paths
)/2 + 1;
6840 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
6841 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
6842 * we try to execute well known editors
6844 editor
= getenv("SYSTEMD_EDITOR");
6846 editor
= getenv("EDITOR");
6848 editor
= getenv("VISUAL");
6850 if (!isempty(editor
)) {
6851 editor_args
= strv_split(editor
, WHITESPACE
);
6854 _exit(EXIT_FAILURE
);
6856 n_editor_args
= strv_length(editor_args
);
6857 argc
+= n_editor_args
- 1;
6859 args
= newa(const char*, argc
+ 1);
6861 if (n_editor_args
> 0) {
6862 args
[0] = editor_args
[0];
6863 for (; i
< n_editor_args
; i
++)
6864 args
[i
] = editor_args
[i
];
6867 STRV_FOREACH_PAIR(original_path
, tmp_path
, paths
) {
6868 args
[i
] = *tmp_path
;
6873 if (n_editor_args
> 0)
6874 execvp(args
[0], (char* const*) args
);
6876 FOREACH_STRING(p
, "editor", "nano", "vim", "vi") {
6878 execvp(p
, (char* const*) args
);
6879 /* We do not fail if the editor doesn't exist
6880 * because we want to try each one of them before
6883 if (errno
!= ENOENT
) {
6884 log_error_errno(errno
, "Failed to execute %s: %m", editor
);
6885 _exit(EXIT_FAILURE
);
6889 log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR, $EDITOR or $VISUAL.");
6890 _exit(EXIT_FAILURE
);
6893 r
= wait_for_terminate_and_warn("editor", pid
, true);
6895 return log_error_errno(r
, "Failed to wait for child: %m");
6900 static int find_paths_to_edit(sd_bus
*bus
, char **names
, char ***paths
) {
6901 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
6908 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
6912 STRV_FOREACH(name
, names
) {
6913 _cleanup_free_
char *path
= NULL
, *new_path
= NULL
, *tmp_path
= NULL
, *tmp_name
= NULL
;
6914 const char *unit_name
;
6916 r
= unit_find_paths(bus
, *name
, &lp
, &path
, NULL
);
6924 log_error("Run 'systemctl edit%s --force %s' to create a new unit.",
6925 arg_scope
== UNIT_FILE_GLOBAL
? " --global" :
6926 arg_scope
== UNIT_FILE_USER
? " --user" : "",
6931 /* Create a new unit from scratch */
6933 r
= unit_file_create_new(&lp
, unit_name
,
6934 arg_full
? NULL
: ".d/override.conf",
6935 &new_path
, &tmp_path
);
6939 unit_name
= basename(path
);
6940 /* We follow unit aliases, but we need to propagate the instance */
6941 if (unit_name_is_valid(*name
, UNIT_NAME_INSTANCE
) &&
6942 unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
6943 _cleanup_free_
char *instance
= NULL
;
6945 r
= unit_name_to_instance(*name
, &instance
);
6949 r
= unit_name_replace_instance(unit_name
, instance
, &tmp_name
);
6953 unit_name
= tmp_name
;
6957 r
= unit_file_create_copy(&lp
, unit_name
, path
, &new_path
, &tmp_path
);
6959 r
= unit_file_create_new(&lp
, unit_name
, ".d/override.conf", &new_path
, &tmp_path
);
6964 r
= strv_push_pair(paths
, new_path
, tmp_path
);
6967 new_path
= tmp_path
= NULL
;
6973 static int edit(int argc
, char *argv
[], void *userdata
) {
6974 _cleanup_strv_free_
char **names
= NULL
;
6975 _cleanup_strv_free_
char **paths
= NULL
;
6976 char **original
, **tmp
;
6981 log_error("Cannot edit units if not on a tty.");
6985 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
6986 log_error("Cannot edit units remotely.");
6990 r
= acquire_bus(BUS_MANAGER
, &bus
);
6994 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
6996 return log_error_errno(r
, "Failed to expand names: %m");
6998 r
= find_paths_to_edit(bus
, names
, &paths
);
7002 if (strv_isempty(paths
))
7005 r
= run_editor(paths
);
7009 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
7010 /* If the temporary file is empty we ignore it. It's
7011 * useful if the user wants to cancel its modification
7013 if (null_or_empty_path(*tmp
)) {
7014 log_warning("Editing \"%s\" canceled: temporary file is empty.", *original
);
7018 r
= rename(*tmp
, *original
);
7020 r
= log_error_errno(errno
, "Failed to rename \"%s\" to \"%s\": %m", *tmp
, *original
);
7027 if (!arg_no_reload
&& !install_client_side())
7028 r
= daemon_reload(argc
, argv
, userdata
);
7031 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
7032 (void) unlink(*tmp
);
7034 /* Removing empty dropin dirs */
7036 _cleanup_free_
char *dir
;
7038 dir
= dirname_malloc(*original
);
7042 /* no need to check if the dir is empty, rmdir
7043 * does nothing if it is not the case.
7052 static void systemctl_help(void) {
7054 pager_open(arg_no_pager
, false);
7056 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
7057 "Query or send control commands to the systemd manager.\n\n"
7058 " -h --help Show this help\n"
7059 " --version Show package version\n"
7060 " --system Connect to system manager\n"
7061 " --user Connect to user service manager\n"
7062 " -H --host=[USER@]HOST\n"
7063 " Operate on remote host\n"
7064 " -M --machine=CONTAINER\n"
7065 " Operate on local container\n"
7066 " -t --type=TYPE List units of a particular type\n"
7067 " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n"
7068 " -p --property=NAME Show only properties by this name\n"
7069 " -a --all Show all properties/all units currently in memory,\n"
7070 " including dead/empty ones. To list all units installed on\n"
7071 " the system, use the 'list-unit-files' command instead.\n"
7072 " --failed Same as --state=failed\n"
7073 " -l --full Don't ellipsize unit names on output\n"
7074 " -r --recursive Show unit list of host and local containers\n"
7075 " --reverse Show reverse dependencies with 'list-dependencies'\n"
7076 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
7077 " queueing a new job\n"
7078 " --show-types When showing sockets, explicitly show their type\n"
7079 " --value When showing properties, only print the value\n"
7080 " -i --ignore-inhibitors\n"
7081 " When shutting down or sleeping, ignore inhibitors\n"
7082 " --kill-who=WHO Who to send signal to\n"
7083 " -s --signal=SIGNAL Which signal to send\n"
7084 " --now Start or stop unit in addition to enabling or disabling it\n"
7085 " -q --quiet Suppress output\n"
7086 " --wait For (re)start, wait until service stopped again\n"
7087 " --no-block Do not wait until operation finished\n"
7088 " --no-wall Don't send wall message before halt/power-off/reboot\n"
7089 " --no-reload Don't reload daemon after en-/dis-abling unit files\n"
7090 " --no-legend Do not print a legend (column headers and hints)\n"
7091 " --no-pager Do not pipe output into a pager\n"
7092 " --no-ask-password\n"
7093 " Do not ask for system passwords\n"
7094 " --global Enable/disable unit files globally\n"
7095 " --runtime Enable unit files only temporarily until next reboot\n"
7096 " -f --force When enabling unit files, override existing symlinks\n"
7097 " When shutting down, execute action immediately\n"
7098 " --preset-mode= Apply only enable, only disable, or all presets\n"
7099 " --root=PATH Enable unit files in the specified root directory\n"
7100 " -n --lines=INTEGER Number of journal entries to show\n"
7101 " -o --output=STRING Change journal output mode (short, short-precise,\n"
7102 " short-iso, short-iso-precise, short-full,\n"
7103 " short-monotonic, short-unix,\n"
7104 " verbose, export, json, json-pretty, json-sse, cat)\n"
7105 " --firmware-setup Tell the firmware to show the setup menu on next boot\n"
7106 " --plain Print unit dependencies as a list instead of a tree\n\n"
7108 " list-units [PATTERN...] List units currently in memory\n"
7109 " list-sockets [PATTERN...] List socket units currently in memory, ordered\n"
7111 " list-timers [PATTERN...] List timer units currently in memory, ordered\n"
7113 " start NAME... Start (activate) one or more units\n"
7114 " stop NAME... Stop (deactivate) one or more units\n"
7115 " reload NAME... Reload one or more units\n"
7116 " restart NAME... Start or restart one or more units\n"
7117 " try-restart NAME... Restart one or more units if active\n"
7118 " reload-or-restart NAME... Reload one or more units if possible,\n"
7119 " otherwise start or restart\n"
7120 " try-reload-or-restart NAME... If active, reload one or more units,\n"
7121 " if supported, otherwise restart\n"
7122 " isolate NAME Start one unit and stop all others\n"
7123 " kill NAME... Send signal to processes of a unit\n"
7124 " is-active PATTERN... Check whether units are active\n"
7125 " is-failed PATTERN... Check whether units are failed\n"
7126 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
7127 " show [PATTERN...|JOB...] Show properties of one or more\n"
7128 " units/jobs or the manager\n"
7129 " cat PATTERN... Show files and drop-ins of one or more units\n"
7130 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
7131 " help PATTERN...|PID... Show manual for one or more units\n"
7132 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
7134 " list-dependencies [NAME] Recursively show units which are required\n"
7135 " or wanted by this unit or by which this\n"
7136 " unit is required or wanted\n\n"
7137 "Unit File Commands:\n"
7138 " list-unit-files [PATTERN...] List installed unit files\n"
7139 " enable [NAME...|PATH...] Enable one or more unit files\n"
7140 " disable NAME... Disable one or more unit files\n"
7141 " reenable NAME... Reenable one or more unit files\n"
7142 " preset NAME... Enable/disable one or more unit files\n"
7143 " based on preset configuration\n"
7144 " preset-all Enable/disable all unit files based on\n"
7145 " preset configuration\n"
7146 " is-enabled NAME... Check whether unit files are enabled\n"
7147 " mask NAME... Mask one or more units\n"
7148 " unmask NAME... Unmask one or more units\n"
7149 " link PATH... Link one or more units files into\n"
7150 " the search path\n"
7151 " revert NAME... Revert one or more unit files to vendor\n"
7153 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
7154 " on specified one or more units\n"
7155 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
7156 " on specified one or more units\n"
7157 " edit NAME... Edit one or more unit files\n"
7158 " get-default Get the name of the default target\n"
7159 " set-default NAME Set the default target\n\n"
7160 "Machine Commands:\n"
7161 " list-machines [PATTERN...] List local containers and host\n\n"
7163 " list-jobs [PATTERN...] List jobs\n"
7164 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
7165 "Environment Commands:\n"
7166 " show-environment Dump environment\n"
7167 " set-environment NAME=VALUE... Set one or more environment variables\n"
7168 " unset-environment NAME... Unset one or more environment variables\n"
7169 " import-environment [NAME...] Import all or some environment variables\n\n"
7170 "Manager Lifecycle Commands:\n"
7171 " daemon-reload Reload systemd manager configuration\n"
7172 " daemon-reexec Reexecute systemd manager\n\n"
7173 "System Commands:\n"
7174 " is-system-running Check whether system is fully running\n"
7175 " default Enter system default mode\n"
7176 " rescue Enter system rescue mode\n"
7177 " emergency Enter system emergency mode\n"
7178 " halt Shut down and halt the system\n"
7179 " poweroff Shut down and power-off the system\n"
7180 " reboot [ARG] Shut down and reboot the system\n"
7181 " kexec Shut down and reboot the system with kexec\n"
7182 " exit [EXIT_CODE] Request user instance or container exit\n"
7183 " switch-root ROOT [INIT] Change to a different root file system\n"
7184 " suspend Suspend the system\n"
7185 " hibernate Hibernate the system\n"
7186 " hybrid-sleep Hibernate and suspend the system\n",
7187 program_invocation_short_name
);
7190 static void halt_help(void) {
7191 printf("%s [OPTIONS...]%s\n\n"
7192 "%s the system.\n\n"
7193 " --help Show this help\n"
7194 " --halt Halt the machine\n"
7195 " -p --poweroff Switch off the machine\n"
7196 " --reboot Reboot the machine\n"
7197 " -f --force Force immediate halt/power-off/reboot\n"
7198 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
7199 " -d --no-wtmp Don't write wtmp record\n"
7200 " --no-wall Don't send wall message before halt/power-off/reboot\n",
7201 program_invocation_short_name
,
7202 arg_action
== ACTION_REBOOT
? " [ARG]" : "",
7203 arg_action
== ACTION_REBOOT
? "Reboot" :
7204 arg_action
== ACTION_POWEROFF
? "Power off" :
7208 static void shutdown_help(void) {
7209 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
7210 "Shut down the system.\n\n"
7211 " --help Show this help\n"
7212 " -H --halt Halt the machine\n"
7213 " -P --poweroff Power-off the machine\n"
7214 " -r --reboot Reboot the machine\n"
7215 " -h Equivalent to --poweroff, overridden by --halt\n"
7216 " -k Don't halt/power-off/reboot, just send warnings\n"
7217 " --no-wall Don't send wall message before halt/power-off/reboot\n"
7218 " -c Cancel a pending shutdown\n",
7219 program_invocation_short_name
);
7222 static void telinit_help(void) {
7223 printf("%s [OPTIONS...] {COMMAND}\n\n"
7224 "Send control commands to the init daemon.\n\n"
7225 " --help Show this help\n"
7226 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
7228 " 0 Power-off the machine\n"
7229 " 6 Reboot the machine\n"
7230 " 2, 3, 4, 5 Start runlevelX.target unit\n"
7231 " 1, s, S Enter rescue mode\n"
7232 " q, Q Reload init daemon configuration\n"
7233 " u, U Reexecute init daemon\n",
7234 program_invocation_short_name
);
7237 static void runlevel_help(void) {
7238 printf("%s [OPTIONS...]\n\n"
7239 "Prints the previous and current runlevel of the init system.\n\n"
7240 " --help Show this help\n",
7241 program_invocation_short_name
);
7244 static void help_types(void) {
7248 puts("Available unit types:");
7249 for (i
= 0; i
< _UNIT_TYPE_MAX
; i
++)
7250 puts(unit_type_to_string(i
));
7253 static void help_states(void) {
7257 puts("Available unit load states:");
7258 for (i
= 0; i
< _UNIT_LOAD_STATE_MAX
; i
++)
7259 puts(unit_load_state_to_string(i
));
7262 puts("\nAvailable unit active states:");
7263 for (i
= 0; i
< _UNIT_ACTIVE_STATE_MAX
; i
++)
7264 puts(unit_active_state_to_string(i
));
7267 puts("\nAvailable automount unit substates:");
7268 for (i
= 0; i
< _AUTOMOUNT_STATE_MAX
; i
++)
7269 puts(automount_state_to_string(i
));
7272 puts("\nAvailable device unit substates:");
7273 for (i
= 0; i
< _DEVICE_STATE_MAX
; i
++)
7274 puts(device_state_to_string(i
));
7277 puts("\nAvailable mount unit substates:");
7278 for (i
= 0; i
< _MOUNT_STATE_MAX
; i
++)
7279 puts(mount_state_to_string(i
));
7282 puts("\nAvailable path unit substates:");
7283 for (i
= 0; i
< _PATH_STATE_MAX
; i
++)
7284 puts(path_state_to_string(i
));
7287 puts("\nAvailable scope unit substates:");
7288 for (i
= 0; i
< _SCOPE_STATE_MAX
; i
++)
7289 puts(scope_state_to_string(i
));
7292 puts("\nAvailable service unit substates:");
7293 for (i
= 0; i
< _SERVICE_STATE_MAX
; i
++)
7294 puts(service_state_to_string(i
));
7297 puts("\nAvailable slice unit substates:");
7298 for (i
= 0; i
< _SLICE_STATE_MAX
; i
++)
7299 puts(slice_state_to_string(i
));
7302 puts("\nAvailable socket unit substates:");
7303 for (i
= 0; i
< _SOCKET_STATE_MAX
; i
++)
7304 puts(socket_state_to_string(i
));
7307 puts("\nAvailable swap unit substates:");
7308 for (i
= 0; i
< _SWAP_STATE_MAX
; i
++)
7309 puts(swap_state_to_string(i
));
7312 puts("\nAvailable target unit substates:");
7313 for (i
= 0; i
< _TARGET_STATE_MAX
; i
++)
7314 puts(target_state_to_string(i
));
7317 puts("\nAvailable timer unit substates:");
7318 for (i
= 0; i
< _TIMER_STATE_MAX
; i
++)
7319 puts(timer_state_to_string(i
));
7322 static int systemctl_parse_argv(int argc
, char *argv
[]) {
7331 ARG_IGNORE_DEPENDENCIES
,
7344 ARG_NO_ASK_PASSWORD
,
7358 static const struct option options
[] = {
7359 { "help", no_argument
, NULL
, 'h' },
7360 { "version", no_argument
, NULL
, ARG_VERSION
},
7361 { "type", required_argument
, NULL
, 't' },
7362 { "property", required_argument
, NULL
, 'p' },
7363 { "all", no_argument
, NULL
, 'a' },
7364 { "reverse", no_argument
, NULL
, ARG_REVERSE
},
7365 { "after", no_argument
, NULL
, ARG_AFTER
},
7366 { "before", no_argument
, NULL
, ARG_BEFORE
},
7367 { "show-types", no_argument
, NULL
, ARG_SHOW_TYPES
},
7368 { "failed", no_argument
, NULL
, ARG_FAILED
}, /* compatibility only */
7369 { "full", no_argument
, NULL
, 'l' },
7370 { "job-mode", required_argument
, NULL
, ARG_JOB_MODE
},
7371 { "fail", no_argument
, NULL
, ARG_FAIL
}, /* compatibility only */
7372 { "irreversible", no_argument
, NULL
, ARG_IRREVERSIBLE
}, /* compatibility only */
7373 { "ignore-dependencies", no_argument
, NULL
, ARG_IGNORE_DEPENDENCIES
}, /* compatibility only */
7374 { "ignore-inhibitors", no_argument
, NULL
, 'i' },
7375 { "value", no_argument
, NULL
, ARG_VALUE
},
7376 { "user", no_argument
, NULL
, ARG_USER
},
7377 { "system", no_argument
, NULL
, ARG_SYSTEM
},
7378 { "global", no_argument
, NULL
, ARG_GLOBAL
},
7379 { "wait", no_argument
, NULL
, ARG_WAIT
},
7380 { "no-block", no_argument
, NULL
, ARG_NO_BLOCK
},
7381 { "no-legend", no_argument
, NULL
, ARG_NO_LEGEND
},
7382 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
7383 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7384 { "quiet", no_argument
, NULL
, 'q' },
7385 { "root", required_argument
, NULL
, ARG_ROOT
},
7386 { "force", no_argument
, NULL
, ARG_FORCE
},
7387 { "no-reload", no_argument
, NULL
, ARG_NO_RELOAD
},
7388 { "kill-who", required_argument
, NULL
, ARG_KILL_WHO
},
7389 { "signal", required_argument
, NULL
, 's' },
7390 { "no-ask-password", no_argument
, NULL
, ARG_NO_ASK_PASSWORD
},
7391 { "host", required_argument
, NULL
, 'H' },
7392 { "machine", required_argument
, NULL
, 'M' },
7393 { "runtime", no_argument
, NULL
, ARG_RUNTIME
},
7394 { "lines", required_argument
, NULL
, 'n' },
7395 { "output", required_argument
, NULL
, 'o' },
7396 { "plain", no_argument
, NULL
, ARG_PLAIN
},
7397 { "state", required_argument
, NULL
, ARG_STATE
},
7398 { "recursive", no_argument
, NULL
, 'r' },
7399 { "preset-mode", required_argument
, NULL
, ARG_PRESET_MODE
},
7400 { "firmware-setup", no_argument
, NULL
, ARG_FIRMWARE_SETUP
},
7401 { "now", no_argument
, NULL
, ARG_NOW
},
7402 { "message", required_argument
, NULL
, ARG_MESSAGE
},
7412 /* we default to allowing interactive authorization only in systemctl (not in the legacy commands) */
7413 arg_ask_password
= true;
7415 while ((c
= getopt_long(argc
, argv
, "ht:p:alqfs:H:M:n:o:ir", options
, NULL
)) >= 0)
7427 if (isempty(optarg
)) {
7428 log_error("--type= requires arguments.");
7432 for (p
= optarg
;;) {
7433 _cleanup_free_
char *type
= NULL
;
7435 r
= extract_first_word(&p
, &type
, ",", 0);
7437 return log_error_errno(r
, "Failed to parse type: %s", optarg
);
7441 if (streq(type
, "help")) {
7446 if (unit_type_from_string(type
) >= 0) {
7447 if (strv_push(&arg_types
, type
) < 0)
7453 /* It's much nicer to use --state= for
7454 * load states, but let's support this
7455 * in --types= too for compatibility
7456 * with old versions */
7457 if (unit_load_state_from_string(type
) >= 0) {
7458 if (strv_push(&arg_states
, type
) < 0)
7464 log_error("Unknown unit type or load state '%s'.", type
);
7465 log_info("Use -t help to see a list of allowed values.");
7473 /* Make sure that if the empty property list
7474 was specified, we won't show any properties. */
7475 if (isempty(optarg
) && !arg_properties
) {
7476 arg_properties
= new0(char*, 1);
7477 if (!arg_properties
)
7480 for (p
= optarg
;;) {
7481 _cleanup_free_
char *prop
= NULL
;
7483 r
= extract_first_word(&p
, &prop
, ",", 0);
7485 return log_error_errno(r
, "Failed to parse property: %s", optarg
);
7489 if (strv_push(&arg_properties
, prop
) < 0)
7495 /* If the user asked for a particular
7496 * property, show it to him, even if it is
7508 arg_dependency
= DEPENDENCY_REVERSE
;
7512 arg_dependency
= DEPENDENCY_AFTER
;
7513 arg_jobs_after
= true;
7517 arg_dependency
= DEPENDENCY_BEFORE
;
7518 arg_jobs_before
= true;
7521 case ARG_SHOW_TYPES
:
7522 arg_show_types
= true;
7530 arg_job_mode
= optarg
;
7534 arg_job_mode
= "fail";
7537 case ARG_IRREVERSIBLE
:
7538 arg_job_mode
= "replace-irreversibly";
7541 case ARG_IGNORE_DEPENDENCIES
:
7542 arg_job_mode
= "ignore-dependencies";
7546 arg_scope
= UNIT_FILE_USER
;
7550 arg_scope
= UNIT_FILE_SYSTEM
;
7554 arg_scope
= UNIT_FILE_GLOBAL
;
7562 arg_no_block
= true;
7566 arg_no_legend
= true;
7570 arg_no_pager
= true;
7578 r
= parse_path_argument_and_warn(optarg
, false, &arg_root
);
7588 if (strv_extend(&arg_states
, "failed") < 0)
7606 arg_no_reload
= true;
7610 arg_kill_who
= optarg
;
7614 arg_signal
= signal_from_string_try_harder(optarg
);
7615 if (arg_signal
< 0) {
7616 log_error("Failed to parse signal string %s.", optarg
);
7621 case ARG_NO_ASK_PASSWORD
:
7622 arg_ask_password
= false;
7626 arg_transport
= BUS_TRANSPORT_REMOTE
;
7631 arg_transport
= BUS_TRANSPORT_MACHINE
;
7640 if (safe_atou(optarg
, &arg_lines
) < 0) {
7641 log_error("Failed to parse lines '%s'", optarg
);
7647 arg_output
= output_mode_from_string(optarg
);
7648 if (arg_output
< 0) {
7649 log_error("Unknown output '%s'.", optarg
);
7655 arg_ignore_inhibitors
= true;
7662 case ARG_FIRMWARE_SETUP
:
7663 arg_firmware_setup
= true;
7667 if (isempty(optarg
)) {
7668 log_error("--state= requires arguments.");
7672 for (p
= optarg
;;) {
7673 _cleanup_free_
char *s
= NULL
;
7675 r
= extract_first_word(&p
, &s
, ",", 0);
7677 return log_error_errno(r
, "Failed to parse state: %s", optarg
);
7681 if (streq(s
, "help")) {
7686 if (strv_push(&arg_states
, s
) < 0)
7695 if (geteuid() != 0) {
7696 log_error("--recursive requires root privileges.");
7700 arg_recursive
= true;
7703 case ARG_PRESET_MODE
:
7705 arg_preset_mode
= unit_file_preset_mode_from_string(optarg
);
7706 if (arg_preset_mode
< 0) {
7707 log_error("Failed to parse preset mode: %s.", optarg
);
7718 if (strv_extend(&arg_wall
, optarg
) < 0)
7726 assert_not_reached("Unhandled option");
7729 if (arg_transport
!= BUS_TRANSPORT_LOCAL
&& arg_scope
!= UNIT_FILE_SYSTEM
) {
7730 log_error("Cannot access user instance remotely.");
7734 if (arg_wait
&& arg_no_block
) {
7735 log_error("--wait may not be combined with --no-block.");
7742 static int halt_parse_argv(int argc
, char *argv
[]) {
7751 static const struct option options
[] = {
7752 { "help", no_argument
, NULL
, ARG_HELP
},
7753 { "halt", no_argument
, NULL
, ARG_HALT
},
7754 { "poweroff", no_argument
, NULL
, 'p' },
7755 { "reboot", no_argument
, NULL
, ARG_REBOOT
},
7756 { "force", no_argument
, NULL
, 'f' },
7757 { "wtmp-only", no_argument
, NULL
, 'w' },
7758 { "no-wtmp", no_argument
, NULL
, 'd' },
7759 { "no-sync", no_argument
, NULL
, 'n' },
7760 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7769 if (utmp_get_runlevel(&runlevel
, NULL
) >= 0)
7770 if (runlevel
== '0' || runlevel
== '6')
7773 while ((c
= getopt_long(argc
, argv
, "pfwdnih", options
, NULL
)) >= 0)
7781 arg_action
= ACTION_HALT
;
7785 if (arg_action
!= ACTION_REBOOT
)
7786 arg_action
= ACTION_POWEROFF
;
7790 arg_action
= ACTION_REBOOT
;
7815 /* Compatibility nops */
7822 assert_not_reached("Unhandled option");
7825 if (arg_action
== ACTION_REBOOT
&& (argc
== optind
|| argc
== optind
+ 1)) {
7826 r
= update_reboot_parameter_and_warn(argc
== optind
+ 1 ? argv
[optind
] : NULL
);
7829 } else if (optind
< argc
) {
7830 log_error("Too many arguments.");
7837 static int parse_shutdown_time_spec(const char *t
, usec_t
*_u
) {
7841 if (streq(t
, "now"))
7843 else if (!strchr(t
, ':')) {
7846 if (safe_atou64(t
, &u
) < 0)
7849 *_u
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
* u
;
7858 hour
= strtol(t
, &e
, 10);
7859 if (errno
> 0 || *e
!= ':' || hour
< 0 || hour
> 23)
7862 minute
= strtol(e
+1, &e
, 10);
7863 if (errno
> 0 || *e
!= 0 || minute
< 0 || minute
> 59)
7866 n
= now(CLOCK_REALTIME
);
7867 s
= (time_t) (n
/ USEC_PER_SEC
);
7869 assert_se(localtime_r(&s
, &tm
));
7871 tm
.tm_hour
= (int) hour
;
7872 tm
.tm_min
= (int) minute
;
7875 assert_se(s
= mktime(&tm
));
7877 *_u
= (usec_t
) s
* USEC_PER_SEC
;
7880 *_u
+= USEC_PER_DAY
;
7886 static int shutdown_parse_argv(int argc
, char *argv
[]) {
7893 static const struct option options
[] = {
7894 { "help", no_argument
, NULL
, ARG_HELP
},
7895 { "halt", no_argument
, NULL
, 'H' },
7896 { "poweroff", no_argument
, NULL
, 'P' },
7897 { "reboot", no_argument
, NULL
, 'r' },
7898 { "kexec", no_argument
, NULL
, 'K' }, /* not documented extension */
7899 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7909 while ((c
= getopt_long(argc
, argv
, "HPrhkKtafFc", options
, NULL
)) >= 0)
7917 arg_action
= ACTION_HALT
;
7921 arg_action
= ACTION_POWEROFF
;
7926 arg_action
= ACTION_KEXEC
;
7928 arg_action
= ACTION_REBOOT
;
7932 arg_action
= ACTION_KEXEC
;
7936 if (arg_action
!= ACTION_HALT
)
7937 arg_action
= ACTION_POWEROFF
;
7952 /* Compatibility nops */
7956 arg_action
= ACTION_CANCEL_SHUTDOWN
;
7963 assert_not_reached("Unhandled option");
7966 if (argc
> optind
&& arg_action
!= ACTION_CANCEL_SHUTDOWN
) {
7967 r
= parse_shutdown_time_spec(argv
[optind
], &arg_when
);
7969 log_error("Failed to parse time specification: %s", argv
[optind
]);
7973 arg_when
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
;
7975 if (argc
> optind
&& arg_action
== ACTION_CANCEL_SHUTDOWN
)
7976 /* No time argument for shutdown cancel */
7977 wall
= argv
+ optind
;
7978 else if (argc
> optind
+ 1)
7979 /* We skip the time argument */
7980 wall
= argv
+ optind
+ 1;
7983 arg_wall
= strv_copy(wall
);
7993 static int telinit_parse_argv(int argc
, char *argv
[]) {
8000 static const struct option options
[] = {
8001 { "help", no_argument
, NULL
, ARG_HELP
},
8002 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
8006 static const struct {
8010 { '0', ACTION_POWEROFF
},
8011 { '6', ACTION_REBOOT
},
8012 { '1', ACTION_RESCUE
},
8013 { '2', ACTION_RUNLEVEL2
},
8014 { '3', ACTION_RUNLEVEL3
},
8015 { '4', ACTION_RUNLEVEL4
},
8016 { '5', ACTION_RUNLEVEL5
},
8017 { 's', ACTION_RESCUE
},
8018 { 'S', ACTION_RESCUE
},
8019 { 'q', ACTION_RELOAD
},
8020 { 'Q', ACTION_RELOAD
},
8021 { 'u', ACTION_REEXEC
},
8022 { 'U', ACTION_REEXEC
}
8031 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
8046 assert_not_reached("Unhandled option");
8049 if (optind
>= argc
) {
8050 log_error("%s: required argument missing.", program_invocation_short_name
);
8054 if (optind
+ 1 < argc
) {
8055 log_error("Too many arguments.");
8059 if (strlen(argv
[optind
]) != 1) {
8060 log_error("Expected single character argument.");
8064 for (i
= 0; i
< ELEMENTSOF(table
); i
++)
8065 if (table
[i
].from
== argv
[optind
][0])
8068 if (i
>= ELEMENTSOF(table
)) {
8069 log_error("Unknown command '%s'.", argv
[optind
]);
8073 arg_action
= table
[i
].to
;
8080 static int runlevel_parse_argv(int argc
, char *argv
[]) {
8086 static const struct option options
[] = {
8087 { "help", no_argument
, NULL
, ARG_HELP
},
8096 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
8107 assert_not_reached("Unhandled option");
8110 if (optind
< argc
) {
8111 log_error("Too many arguments.");
8118 static int parse_argv(int argc
, char *argv
[]) {
8122 if (program_invocation_short_name
) {
8124 if (strstr(program_invocation_short_name
, "halt")) {
8125 arg_action
= ACTION_HALT
;
8126 return halt_parse_argv(argc
, argv
);
8127 } else if (strstr(program_invocation_short_name
, "poweroff")) {
8128 arg_action
= ACTION_POWEROFF
;
8129 return halt_parse_argv(argc
, argv
);
8130 } else if (strstr(program_invocation_short_name
, "reboot")) {
8132 arg_action
= ACTION_KEXEC
;
8134 arg_action
= ACTION_REBOOT
;
8135 return halt_parse_argv(argc
, argv
);
8136 } else if (strstr(program_invocation_short_name
, "shutdown")) {
8137 arg_action
= ACTION_POWEROFF
;
8138 return shutdown_parse_argv(argc
, argv
);
8139 } else if (strstr(program_invocation_short_name
, "init")) {
8141 if (sd_booted() > 0) {
8142 arg_action
= _ACTION_INVALID
;
8143 return telinit_parse_argv(argc
, argv
);
8145 /* Hmm, so some other init system is
8146 * running, we need to forward this
8147 * request to it. For now we simply
8148 * guess that it is Upstart. */
8150 execv(TELINIT
, argv
);
8152 log_error("Couldn't find an alternative telinit implementation to spawn.");
8156 } else if (strstr(program_invocation_short_name
, "runlevel")) {
8157 arg_action
= ACTION_RUNLEVEL
;
8158 return runlevel_parse_argv(argc
, argv
);
8162 arg_action
= ACTION_SYSTEMCTL
;
8163 return systemctl_parse_argv(argc
, argv
);
8166 #ifdef HAVE_SYSV_COMPAT
8167 _pure_
static int action_to_runlevel(void) {
8169 static const char table
[_ACTION_MAX
] = {
8170 [ACTION_HALT
] = '0',
8171 [ACTION_POWEROFF
] = '0',
8172 [ACTION_REBOOT
] = '6',
8173 [ACTION_RUNLEVEL2
] = '2',
8174 [ACTION_RUNLEVEL3
] = '3',
8175 [ACTION_RUNLEVEL4
] = '4',
8176 [ACTION_RUNLEVEL5
] = '5',
8177 [ACTION_RESCUE
] = '1'
8180 assert(arg_action
>= 0 && arg_action
< _ACTION_MAX
);
8182 return table
[arg_action
];
8186 static int talk_initctl(void) {
8187 #ifdef HAVE_SYSV_COMPAT
8188 struct init_request request
= {
8189 .magic
= INIT_MAGIC
,
8191 .cmd
= INIT_CMD_RUNLVL
8194 _cleanup_close_
int fd
= -1;
8198 rl
= action_to_runlevel();
8202 request
.runlevel
= rl
;
8204 fd
= open(INIT_FIFO
, O_WRONLY
|O_NDELAY
|O_CLOEXEC
|O_NOCTTY
);
8206 if (errno
== ENOENT
)
8209 return log_error_errno(errno
, "Failed to open "INIT_FIFO
": %m");
8212 r
= loop_write(fd
, &request
, sizeof(request
), false);
8214 return log_error_errno(r
, "Failed to write to "INIT_FIFO
": %m");
8222 static int systemctl_main(int argc
, char *argv
[]) {
8224 static const Verb verbs
[] = {
8225 { "list-units", VERB_ANY
, VERB_ANY
, VERB_DEFAULT
|VERB_NOCHROOT
, list_units
},
8226 { "list-unit-files", VERB_ANY
, VERB_ANY
, 0, list_unit_files
},
8227 { "list-sockets", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_sockets
},
8228 { "list-timers", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_timers
},
8229 { "list-jobs", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_jobs
},
8230 { "list-machines", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_machines
},
8231 { "clear-jobs", VERB_ANY
, 1, VERB_NOCHROOT
, trivial_method
},
8232 { "cancel", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, cancel_job
},
8233 { "start", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8234 { "stop", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8235 { "condstop", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with ALTLinux */
8236 { "reload", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8237 { "restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8238 { "try-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8239 { "reload-or-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8240 { "reload-or-try-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatbility with old systemctl <= 228 */
8241 { "try-reload-or-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8242 { "force-reload", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with SysV */
8243 { "condreload", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with ALTLinux */
8244 { "condrestart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with RH */
8245 { "isolate", 2, 2, VERB_NOCHROOT
, start_unit
},
8246 { "kill", 2, VERB_ANY
, VERB_NOCHROOT
, kill_unit
},
8247 { "is-active", 2, VERB_ANY
, VERB_NOCHROOT
, check_unit_active
},
8248 { "check", 2, VERB_ANY
, VERB_NOCHROOT
, check_unit_active
},
8249 { "is-failed", 2, VERB_ANY
, VERB_NOCHROOT
, check_unit_failed
},
8250 { "show", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, show
},
8251 { "cat", 2, VERB_ANY
, VERB_NOCHROOT
, cat
},
8252 { "status", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, show
},
8253 { "help", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, show
},
8254 { "daemon-reload", VERB_ANY
, 1, VERB_NOCHROOT
, daemon_reload
},
8255 { "daemon-reexec", VERB_ANY
, 1, VERB_NOCHROOT
, daemon_reload
},
8256 { "show-environment", VERB_ANY
, 1, VERB_NOCHROOT
, show_environment
},
8257 { "set-environment", 2, VERB_ANY
, VERB_NOCHROOT
, set_environment
},
8258 { "unset-environment", 2, VERB_ANY
, VERB_NOCHROOT
, set_environment
},
8259 { "import-environment", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, import_environment
},
8260 { "halt", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8261 { "poweroff", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8262 { "reboot", VERB_ANY
, 2, VERB_NOCHROOT
, start_system_special
},
8263 { "kexec", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8264 { "suspend", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8265 { "hibernate", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8266 { "hybrid-sleep", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8267 { "default", VERB_ANY
, 1, VERB_NOCHROOT
, start_special
},
8268 { "rescue", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8269 { "emergency", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8270 { "exit", VERB_ANY
, 2, VERB_NOCHROOT
, start_special
},
8271 { "reset-failed", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, reset_failed
},
8272 { "enable", 2, VERB_ANY
, 0, enable_unit
},
8273 { "disable", 2, VERB_ANY
, 0, enable_unit
},
8274 { "is-enabled", 2, VERB_ANY
, 0, unit_is_enabled
},
8275 { "reenable", 2, VERB_ANY
, 0, enable_unit
},
8276 { "preset", 2, VERB_ANY
, 0, enable_unit
},
8277 { "preset-all", VERB_ANY
, 1, 0, preset_all
},
8278 { "mask", 2, VERB_ANY
, 0, enable_unit
},
8279 { "unmask", 2, VERB_ANY
, 0, enable_unit
},
8280 { "link", 2, VERB_ANY
, 0, enable_unit
},
8281 { "revert", 2, VERB_ANY
, 0, enable_unit
},
8282 { "switch-root", 2, VERB_ANY
, VERB_NOCHROOT
, switch_root
},
8283 { "list-dependencies", VERB_ANY
, 2, VERB_NOCHROOT
, list_dependencies
},
8284 { "set-default", 2, 2, 0, set_default
},
8285 { "get-default", VERB_ANY
, 1, 0, get_default
},
8286 { "set-property", 3, VERB_ANY
, VERB_NOCHROOT
, set_property
},
8287 { "is-system-running", VERB_ANY
, 1, 0, is_system_running
},
8288 { "add-wants", 3, VERB_ANY
, 0, add_dependency
},
8289 { "add-requires", 3, VERB_ANY
, 0, add_dependency
},
8290 { "edit", 2, VERB_ANY
, VERB_NOCHROOT
, edit
},
8294 return dispatch_verb(argc
, argv
, verbs
, NULL
);
8297 static int reload_with_fallback(void) {
8299 /* First, try systemd via D-Bus. */
8300 if (daemon_reload(0, NULL
, NULL
) >= 0)
8303 /* Nothing else worked, so let's try signals */
8304 assert(IN_SET(arg_action
, ACTION_RELOAD
, ACTION_REEXEC
));
8306 if (kill(1, arg_action
== ACTION_RELOAD
? SIGHUP
: SIGTERM
) < 0)
8307 return log_error_errno(errno
, "kill() failed: %m");
8312 static int start_with_fallback(void) {
8314 /* First, try systemd via D-Bus. */
8315 if (start_unit(0, NULL
, NULL
) >= 0)
8318 /* Nothing else worked, so let's try /dev/initctl */
8319 if (talk_initctl() > 0)
8322 log_error("Failed to talk to init daemon.");
8326 static int halt_now(enum action a
) {
8329 /* The kernel will automaticall flush ATA disks and suchlike
8330 * on reboot(), but the file systems need to be synce'd
8331 * explicitly in advance. */
8335 /* Make sure C-A-D is handled by the kernel from this point
8337 (void) reboot(RB_ENABLE_CAD
);
8343 log_info("Halting.");
8344 (void) reboot(RB_HALT_SYSTEM
);
8347 case ACTION_POWEROFF
:
8349 log_info("Powering off.");
8350 (void) reboot(RB_POWER_OFF
);
8354 case ACTION_REBOOT
: {
8355 _cleanup_free_
char *param
= NULL
;
8357 r
= read_one_line_file("/run/systemd/reboot-param", ¶m
);
8358 if (r
< 0 && r
!= -ENOENT
)
8359 log_warning_errno(r
, "Failed to read reboot parameter file: %m");
8361 if (!isempty(param
)) {
8363 log_info("Rebooting with argument '%s'.", param
);
8364 (void) syscall(SYS_reboot
, LINUX_REBOOT_MAGIC1
, LINUX_REBOOT_MAGIC2
, LINUX_REBOOT_CMD_RESTART2
, param
);
8365 log_warning_errno(errno
, "Failed to reboot with parameter, retrying without: %m");
8369 log_info("Rebooting.");
8370 (void) reboot(RB_AUTOBOOT
);
8375 assert_not_reached("Unknown action.");
8379 static int logind_schedule_shutdown(void) {
8381 #ifdef ENABLE_LOGIND
8382 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
8383 char date
[FORMAT_TIMESTAMP_MAX
];
8388 r
= acquire_bus(BUS_FULL
, &bus
);
8392 switch (arg_action
) {
8396 case ACTION_POWEROFF
:
8397 action
= "poweroff";
8412 action
= strjoina("dry-", action
);
8414 (void) logind_set_wall_message();
8416 r
= sd_bus_call_method(
8418 "org.freedesktop.login1",
8419 "/org/freedesktop/login1",
8420 "org.freedesktop.login1.Manager",
8428 return log_warning_errno(r
, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s", bus_error_message(&error
, r
));
8431 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.", format_timestamp(date
, sizeof(date
), arg_when
));
8434 log_error("Cannot schedule shutdown without logind support, proceeding with immediate shutdown.");
8439 static int halt_main(void) {
8442 r
= logind_check_inhibitors(arg_action
);
8447 return logind_schedule_shutdown();
8449 if (geteuid() != 0) {
8450 if (arg_dry
|| arg_force
> 0) {
8451 log_error("Must be root.");
8455 /* Try logind if we are a normal user and no special
8456 * mode applies. Maybe PolicyKit allows us to shutdown
8458 if (IN_SET(arg_action
, ACTION_POWEROFF
, ACTION_REBOOT
)) {
8459 r
= logind_reboot(arg_action
);
8462 if (IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
8463 /* requested operation is not
8464 * supported on the local system or
8465 * already in progress */
8467 /* on all other errors, try low-level operation */
8471 if (!arg_dry
&& !arg_force
)
8472 return start_with_fallback();
8474 assert(geteuid() == 0);
8477 if (sd_booted() > 0)
8478 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
8480 r
= utmp_put_shutdown();
8482 log_warning_errno(r
, "Failed to write utmp record: %m");
8489 r
= halt_now(arg_action
);
8490 return log_error_errno(r
, "Failed to reboot: %m");
8493 static int runlevel_main(void) {
8494 int r
, runlevel
, previous
;
8496 r
= utmp_get_runlevel(&runlevel
, &previous
);
8503 previous
<= 0 ? 'N' : previous
,
8504 runlevel
<= 0 ? 'N' : runlevel
);
8509 static int logind_cancel_shutdown(void) {
8510 #ifdef ENABLE_LOGIND
8511 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
8515 r
= acquire_bus(BUS_FULL
, &bus
);
8519 (void) logind_set_wall_message();
8521 r
= sd_bus_call_method(
8523 "org.freedesktop.login1",
8524 "/org/freedesktop/login1",
8525 "org.freedesktop.login1.Manager",
8526 "CancelScheduledShutdown",
8530 return log_warning_errno(r
, "Failed to talk to logind, shutdown hasn't been cancelled: %s", bus_error_message(&error
, r
));
8534 log_error("Not compiled with logind support, cannot cancel scheduled shutdowns.");
8539 int main(int argc
, char*argv
[]) {
8542 argv_cmdline
= argv
[0];
8544 setlocale(LC_ALL
, "");
8545 log_parse_environment();
8549 /* Explicitly not on_tty() to avoid setting cached value.
8550 * This becomes relevant for piping output which might be
8552 original_stdout_is_tty
= isatty(STDOUT_FILENO
);
8554 r
= parse_argv(argc
, argv
);
8558 if (arg_action
!= ACTION_SYSTEMCTL
&& running_in_chroot() > 0) {
8561 log_info("Running in chroot, ignoring request.");
8566 /* systemctl_main() will print an error message for the bus
8567 * connection, but only if it needs to */
8569 switch (arg_action
) {
8571 case ACTION_SYSTEMCTL
:
8572 r
= systemctl_main(argc
, argv
);
8575 /* Legacy command aliases set arg_action. They provide some fallbacks,
8576 * e.g. to tell sysvinit to reboot after you have installed systemd
8580 case ACTION_POWEROFF
:
8586 case ACTION_RUNLEVEL2
:
8587 case ACTION_RUNLEVEL3
:
8588 case ACTION_RUNLEVEL4
:
8589 case ACTION_RUNLEVEL5
:
8591 r
= start_with_fallback();
8596 r
= reload_with_fallback();
8599 case ACTION_CANCEL_SHUTDOWN
:
8600 r
= logind_cancel_shutdown();
8603 case ACTION_RUNLEVEL
:
8604 r
= runlevel_main();
8608 case ACTION_SUSPEND
:
8609 case ACTION_HIBERNATE
:
8610 case ACTION_HYBRID_SLEEP
:
8611 case ACTION_EMERGENCY
:
8612 case ACTION_DEFAULT
:
8613 /* systemctl verbs with no equivalent in the legacy commands.
8614 * These cannot appear in arg_action. Fall through. */
8616 case _ACTION_INVALID
:
8618 assert_not_reached("Unknown action");
8625 ask_password_agent_close();
8626 polkit_agent_close();
8628 strv_free(arg_types
);
8629 strv_free(arg_states
);
8630 strv_free(arg_properties
);
8632 strv_free(arg_wall
);
8635 /* Note that we return r here, not EXIT_SUCCESS, so that we can implement the LSB-like return codes */
8636 return r
< 0 ? EXIT_FAILURE
: r
;