1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2010 Lennart Poettering
6 Copyright 2013 Marc-Antoine Perennou
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
30 #include <sys/prctl.h>
31 #include <sys/reboot.h>
32 #include <sys/socket.h>
36 #include "sd-daemon.h"
39 #include "alloc-util.h"
41 #include "bus-common-errors.h"
42 #include "bus-error.h"
43 #include "bus-message.h"
44 #include "bus-unit-util.h"
46 #include "cgroup-show.h"
47 #include "cgroup-util.h"
53 #include "exit-status.h"
56 #include "format-util.h"
58 #include "glob-util.h"
59 #include "hexdecoct.h"
60 #include "hostname-util.h"
65 #include "locale-util.h"
67 #include "logs-show.h"
71 #include "parse-util.h"
72 #include "path-lookup.h"
73 #include "path-util.h"
74 #include "process-util.h"
75 #include "reboot-util.h"
76 #include "rlimit-util.h"
79 #include "signal-util.h"
80 #include "socket-util.h"
81 #include "spawn-ask-password-agent.h"
82 #include "spawn-polkit-agent.h"
84 #include "stat-util.h"
85 #include "string-table.h"
87 #include "terminal-util.h"
89 #include "unit-name.h"
90 #include "user-util.h"
92 #include "utmp-wtmp.h"
96 /* The init script exit status codes
97 0 program is running or service is OK
98 1 program is dead and /var/run pid file exists
99 2 program is dead and /var/lock lock file exists
100 3 program is not running
101 4 program or service status is unknown
102 5-99 reserved for future LSB use
103 100-149 reserved for distribution use
104 150-199 reserved for application use
108 EXIT_PROGRAM_RUNNING_OR_SERVICE_OK
= 0,
109 EXIT_PROGRAM_DEAD_AND_PID_EXISTS
= 1,
110 EXIT_PROGRAM_DEAD_AND_LOCK_FILE_EXISTS
= 2,
111 EXIT_PROGRAM_NOT_RUNNING
= 3,
112 EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN
= 4,
115 static char **arg_types
= NULL
;
116 static char **arg_states
= NULL
;
117 static char **arg_properties
= NULL
;
118 static bool arg_all
= false;
119 static enum dependency
{
125 } arg_dependency
= DEPENDENCY_FORWARD
;
126 static const char *arg_job_mode
= "replace";
127 static UnitFileScope arg_scope
= UNIT_FILE_SYSTEM
;
128 static bool arg_wait
= false;
129 static bool arg_no_block
= false;
130 static bool arg_no_legend
= false;
131 static bool arg_no_pager
= false;
132 static bool arg_no_wtmp
= false;
133 static bool arg_no_sync
= false;
134 static bool arg_no_wall
= false;
135 static bool arg_no_reload
= false;
136 static bool arg_value
= false;
137 static bool arg_show_types
= false;
138 static bool arg_ignore_inhibitors
= false;
139 static bool arg_dry_run
= false;
140 static bool arg_quiet
= false;
141 static bool arg_full
= false;
142 static bool arg_recursive
= false;
143 static int arg_force
= 0;
144 static bool arg_ask_password
= false;
145 static bool arg_runtime
= false;
146 static UnitFilePresetMode arg_preset_mode
= UNIT_FILE_PRESET_FULL
;
147 static char **arg_wall
= NULL
;
148 static const char *arg_kill_who
= NULL
;
149 static int arg_signal
= SIGTERM
;
150 static char *arg_root
= NULL
;
151 static usec_t arg_when
= 0;
152 static char *arg_esp_path
= NULL
;
153 static char *argv_cmdline
= NULL
;
164 ACTION_SUSPEND_THEN_HIBERNATE
,
175 ACTION_CANCEL_SHUTDOWN
,
178 } arg_action
= ACTION_SYSTEMCTL
;
179 static BusTransport arg_transport
= BUS_TRANSPORT_LOCAL
;
180 static const char *arg_host
= NULL
;
181 static unsigned arg_lines
= 10;
182 static OutputMode arg_output
= OUTPUT_SHORT
;
183 static bool arg_plain
= false;
184 static bool arg_firmware_setup
= false;
185 static bool arg_now
= false;
186 static bool arg_jobs_before
= false;
187 static bool arg_jobs_after
= false;
189 static int daemon_reload(int argc
, char *argv
[], void* userdata
);
190 static int trivial_method(int argc
, char *argv
[], void *userdata
);
191 static int halt_now(enum action a
);
192 static int get_state_one_unit(sd_bus
*bus
, const char *name
, UnitActiveState
*active_state
);
194 static bool original_stdout_is_tty
;
196 typedef enum BusFocus
{
197 BUS_FULL
, /* The full bus indicated via --system or --user */
198 BUS_MANAGER
, /* The manager itself, possibly directly, possibly via the bus */
202 static sd_bus
*busses
[_BUS_FOCUS_MAX
] = {};
204 static UnitFileFlags
args_to_flags(void) {
205 return (arg_runtime
? UNIT_FILE_RUNTIME
: 0) |
206 (arg_force
? UNIT_FILE_FORCE
: 0);
209 static int acquire_bus(BusFocus focus
, sd_bus
**ret
) {
212 assert(focus
< _BUS_FOCUS_MAX
);
215 /* We only go directly to the manager, if we are using a local transport */
216 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
219 if (getenv_bool("SYSTEMCTL_FORCE_BUS") > 0)
222 if (!busses
[focus
]) {
225 user
= arg_scope
!= UNIT_FILE_SYSTEM
;
227 if (!user
&& sd_booted() <= 0) {
228 /* Print a friendly message when the local system is actually not running systemd as PID 1. */
229 log_error("System has not been booted with systemd as init system (PID 1). Can't operate.");
233 if (focus
== BUS_MANAGER
)
234 r
= bus_connect_transport_systemd(arg_transport
, arg_host
, user
, &busses
[focus
]);
236 r
= bus_connect_transport(arg_transport
, arg_host
, user
, &busses
[focus
]);
238 return log_error_errno(r
, "Failed to connect to bus: %m");
240 (void) sd_bus_set_allow_interactive_authorization(busses
[focus
], arg_ask_password
);
243 *ret
= busses
[focus
];
247 static void release_busses(void) {
250 for (w
= 0; w
< _BUS_FOCUS_MAX
; w
++)
251 busses
[w
] = sd_bus_flush_close_unref(busses
[w
]);
254 static void ask_password_agent_open_if_enabled(void) {
256 /* Open the password agent as a child process if necessary */
261 if (!arg_ask_password
)
264 if (arg_scope
!= UNIT_FILE_SYSTEM
)
267 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
270 ask_password_agent_open();
273 static void polkit_agent_open_maybe(void) {
274 /* Open the polkit agent as a child process if necessary */
276 if (arg_scope
!= UNIT_FILE_SYSTEM
)
279 polkit_agent_open_if_enabled(arg_transport
, arg_ask_password
);
282 static OutputFlags
get_output_flags(void) {
284 arg_all
* OUTPUT_SHOW_ALL
|
285 (arg_full
|| !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH
|
286 colors_enabled() * OUTPUT_COLOR
|
287 !arg_quiet
* OUTPUT_WARN_CUTOFF
;
290 static int translate_bus_error_to_exit_status(int r
, const sd_bus_error
*error
) {
293 if (!sd_bus_error_is_set(error
))
296 if (sd_bus_error_has_name(error
, SD_BUS_ERROR_ACCESS_DENIED
) ||
297 sd_bus_error_has_name(error
, BUS_ERROR_ONLY_BY_DEPENDENCY
) ||
298 sd_bus_error_has_name(error
, BUS_ERROR_NO_ISOLATION
) ||
299 sd_bus_error_has_name(error
, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE
))
300 return EXIT_NOPERMISSION
;
302 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
))
303 return EXIT_NOTINSTALLED
;
305 if (sd_bus_error_has_name(error
, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE
) ||
306 sd_bus_error_has_name(error
, SD_BUS_ERROR_NOT_SUPPORTED
))
307 return EXIT_NOTIMPLEMENTED
;
309 if (sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
))
310 return EXIT_NOTCONFIGURED
;
318 static bool install_client_side(void) {
320 /* Decides when to execute enable/disable/... operations
321 * client-side rather than server-side. */
323 if (running_in_chroot_or_offline())
326 if (sd_booted() <= 0)
329 if (!isempty(arg_root
))
332 if (arg_scope
== UNIT_FILE_GLOBAL
)
335 /* Unsupported environment variable, mostly for debugging purposes */
336 if (getenv_bool("SYSTEMCTL_INSTALL_CLIENT_SIDE") > 0)
342 static int compare_unit_info(const void *a
, const void *b
) {
343 const UnitInfo
*u
= a
, *v
= b
;
347 /* First, order by machine */
348 if (!u
->machine
&& v
->machine
)
350 if (u
->machine
&& !v
->machine
)
352 if (u
->machine
&& v
->machine
) {
353 r
= strcasecmp(u
->machine
, v
->machine
);
358 /* Second, order by unit type */
359 d1
= strrchr(u
->id
, '.');
360 d2
= strrchr(v
->id
, '.');
362 r
= strcasecmp(d1
, d2
);
367 /* Third, order by name */
368 return strcasecmp(u
->id
, v
->id
);
371 static const char* unit_type_suffix(const char *name
) {
374 dot
= strrchr(name
, '.');
381 static bool output_show_unit(const UnitInfo
*u
, char **patterns
) {
384 if (!strv_fnmatch_or_empty(patterns
, u
->id
, FNM_NOESCAPE
))
387 if (arg_types
&& !strv_find(arg_types
, unit_type_suffix(u
->id
)))
393 /* Note that '--all' is not purely a state filter, but also a
394 * filter that hides units that "follow" other units (which is
395 * used for device units that appear under different names). */
396 if (!isempty(u
->following
))
399 if (!strv_isempty(arg_states
))
402 /* By default show all units except the ones in inactive
403 * state and with no pending job */
407 if (streq(u
->active_state
, "inactive"))
413 static int output_units_list(const UnitInfo
*unit_infos
, unsigned c
) {
414 unsigned circle_len
= 0, id_len
, max_id_len
, load_len
, active_len
, sub_len
, job_len
, desc_len
, max_desc_len
;
416 unsigned n_shown
= 0;
419 max_id_len
= STRLEN("UNIT");
420 load_len
= STRLEN("LOAD");
421 active_len
= STRLEN("ACTIVE");
422 sub_len
= STRLEN("SUB");
423 job_len
= STRLEN("JOB");
424 max_desc_len
= STRLEN("DESCRIPTION");
426 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
427 max_id_len
= MAX(max_id_len
, strlen(u
->id
) + (u
->machine
? strlen(u
->machine
)+1 : 0));
428 load_len
= MAX(load_len
, strlen(u
->load_state
));
429 active_len
= MAX(active_len
, strlen(u
->active_state
));
430 sub_len
= MAX(sub_len
, strlen(u
->sub_state
));
431 max_desc_len
= MAX(max_desc_len
, strlen(u
->description
));
433 if (u
->job_id
!= 0) {
434 job_len
= MAX(job_len
, strlen(u
->job_type
));
438 if (!arg_no_legend
&&
439 (streq(u
->active_state
, "failed") ||
440 STR_IN_SET(u
->load_state
, "error", "not-found", "masked")))
444 if (!arg_full
&& original_stdout_is_tty
) {
447 id_len
= MIN(max_id_len
, 25u); /* as much as it needs, but at most 25 for now */
448 basic_len
= circle_len
+ 1 + id_len
+ 1 + load_len
+ 1 + active_len
+ 1 + sub_len
+ 1;
451 basic_len
+= job_len
+ 1;
453 if (basic_len
< (unsigned) columns()) {
454 unsigned extra_len
, incr
;
455 extra_len
= columns() - basic_len
;
457 /* Either UNIT already got 25, or is fully satisfied.
458 * Grant up to 25 to DESC now. */
459 incr
= MIN(extra_len
, 25u);
463 /* Of the remainder give as much as the ID needs to the ID, and give the rest to the
464 * description but not more than it needs. */
466 incr
= MIN(max_id_len
- id_len
, extra_len
);
468 desc_len
+= MIN(extra_len
- incr
, max_desc_len
- desc_len
);
474 desc_len
= max_desc_len
;
477 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
478 _cleanup_free_
char *e
= NULL
, *j
= NULL
;
479 const char *on_underline
= "", *off_underline
= "";
480 const char *on_loaded
= "", *off_loaded
= "";
481 const char *on_active
= "", *off_active
= "";
482 const char *on_circle
= "", *off_circle
= "";
484 bool circle
= false, underline
= false;
486 if (!n_shown
&& !arg_no_legend
) {
491 printf("%s%-*s %-*s %-*s %-*s ",
495 active_len
, "ACTIVE",
499 printf("%-*s ", job_len
, "JOB");
503 !arg_full
&& arg_no_pager
? (int) desc_len
: -1,
510 if (u
+ 1 < unit_infos
+ c
&&
511 !streq(unit_type_suffix(u
->id
), unit_type_suffix((u
+ 1)->id
))) {
512 on_underline
= ansi_underline();
513 off_underline
= ansi_normal();
517 if (STR_IN_SET(u
->load_state
, "error", "not-found", "masked") && !arg_plain
) {
518 on_circle
= ansi_highlight_yellow();
519 off_circle
= ansi_normal();
521 on_loaded
= underline
? ansi_highlight_red_underline() : ansi_highlight_red();
522 off_loaded
= underline
? on_underline
: ansi_normal();
523 } else if (streq(u
->active_state
, "failed") && !arg_plain
) {
524 on_circle
= ansi_highlight_red();
525 off_circle
= ansi_normal();
527 on_active
= underline
? ansi_highlight_red_underline() : ansi_highlight_red();
528 off_active
= underline
? on_underline
: ansi_normal();
532 j
= strjoin(u
->machine
, ":", u
->id
);
541 e
= ellipsize(id
, id_len
, 33);
549 printf("%s%s%s ", on_circle
, circle
? special_glyph(BLACK_CIRCLE
) : " ", off_circle
);
551 printf("%s%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
553 on_active
, id_len
, id
, off_active
,
554 on_loaded
, load_len
, u
->load_state
, off_loaded
,
555 on_active
, active_len
, u
->active_state
,
556 sub_len
, u
->sub_state
, off_active
,
557 job_count
? job_len
+ 1 : 0, u
->job_id
? u
->job_type
: "");
561 !arg_full
&& arg_no_pager
? (int) desc_len
: -1,
566 if (!arg_no_legend
) {
567 const char *on
, *off
;
571 "LOAD = Reflects whether the unit definition was properly loaded.\n"
572 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
573 "SUB = The low-level unit activation state, values depend on unit type.");
574 puts(job_count
? "JOB = Pending job for the unit.\n" : "");
575 on
= ansi_highlight();
578 on
= ansi_highlight_red();
583 printf("%s%u loaded units listed.%s\n"
584 "To show all installed unit files use 'systemctl list-unit-files'.\n",
587 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
588 "To show all installed unit files use 'systemctl list-unit-files'.\n",
595 static int get_unit_list(
599 UnitInfo
**unit_infos
,
601 sd_bus_message
**_reply
) {
603 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
604 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
605 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
609 bool fallback
= false;
615 r
= sd_bus_message_new_method_call(
618 "org.freedesktop.systemd1",
619 "/org/freedesktop/systemd1",
620 "org.freedesktop.systemd1.Manager",
621 "ListUnitsByPatterns");
623 return bus_log_create_error(r
);
625 r
= sd_bus_message_append_strv(m
, arg_states
);
627 return bus_log_create_error(r
);
629 r
= sd_bus_message_append_strv(m
, patterns
);
631 return bus_log_create_error(r
);
633 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
634 if (r
< 0 && (sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_METHOD
) ||
635 sd_bus_error_has_name(&error
, SD_BUS_ERROR_ACCESS_DENIED
))) {
636 /* Fallback to legacy ListUnitsFiltered method */
638 log_debug_errno(r
, "Failed to list units: %s Falling back to ListUnitsFiltered method.", bus_error_message(&error
, r
));
639 m
= sd_bus_message_unref(m
);
640 sd_bus_error_free(&error
);
642 r
= sd_bus_message_new_method_call(
645 "org.freedesktop.systemd1",
646 "/org/freedesktop/systemd1",
647 "org.freedesktop.systemd1.Manager",
648 "ListUnitsFiltered");
650 return bus_log_create_error(r
);
652 r
= sd_bus_message_append_strv(m
, arg_states
);
654 return bus_log_create_error(r
);
656 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
659 return log_error_errno(r
, "Failed to list units: %s", bus_error_message(&error
, r
));
661 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssssouso)");
663 return bus_log_parse_error(r
);
665 while ((r
= bus_parse_unit_info(reply
, &u
)) > 0) {
668 if (!output_show_unit(&u
, fallback
? patterns
: NULL
))
671 if (!GREEDY_REALLOC(*unit_infos
, size
, c
+1))
674 (*unit_infos
)[c
++] = u
;
677 return bus_log_parse_error(r
);
679 r
= sd_bus_message_exit_container(reply
);
681 return bus_log_parse_error(r
);
683 *_reply
= TAKE_PTR(reply
);
688 static void message_set_freep(Set
**set
) {
689 set_free_with_destructor(*set
, sd_bus_message_unref
);
692 static int get_unit_list_recursive(
695 UnitInfo
**_unit_infos
,
699 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
700 _cleanup_(message_set_freep
) Set
*replies
;
701 sd_bus_message
*reply
;
709 replies
= set_new(NULL
);
713 c
= get_unit_list(bus
, NULL
, patterns
, &unit_infos
, 0, &reply
);
717 r
= set_put(replies
, reply
);
719 sd_bus_message_unref(reply
);
724 _cleanup_strv_free_
char **machines
= NULL
;
727 r
= sd_get_machine_names(&machines
);
729 return log_error_errno(r
, "Failed to get machine names: %m");
731 STRV_FOREACH(i
, machines
) {
732 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*container
= NULL
;
735 r
= sd_bus_open_system_machine(&container
, *i
);
737 log_warning_errno(r
, "Failed to connect to container %s, ignoring: %m", *i
);
741 k
= get_unit_list(container
, *i
, patterns
, &unit_infos
, c
, &reply
);
747 r
= set_put(replies
, reply
);
749 sd_bus_message_unref(reply
);
754 *_machines
= TAKE_PTR(machines
);
758 *_unit_infos
= TAKE_PTR(unit_infos
);
760 *_replies
= TAKE_PTR(replies
);
765 static int list_units(int argc
, char *argv
[], void *userdata
) {
766 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
767 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
768 _cleanup_strv_free_
char **machines
= NULL
;
772 r
= acquire_bus(BUS_MANAGER
, &bus
);
776 (void) pager_open(arg_no_pager
, false);
778 r
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
782 qsort_safe(unit_infos
, r
, sizeof(UnitInfo
), compare_unit_info
);
783 return output_units_list(unit_infos
, r
);
786 static int get_triggered_units(
791 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
798 r
= sd_bus_get_property_strv(
800 "org.freedesktop.systemd1",
802 "org.freedesktop.systemd1.Unit",
807 return log_error_errno(r
, "Failed to determine triggers: %s", bus_error_message(&error
, r
));
812 static int get_listening(
814 const char* unit_path
,
817 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
818 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
819 const char *type
, *path
;
822 r
= sd_bus_get_property(
824 "org.freedesktop.systemd1",
826 "org.freedesktop.systemd1.Socket",
832 return log_error_errno(r
, "Failed to get list of listening sockets: %s", bus_error_message(&error
, r
));
834 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
836 return bus_log_parse_error(r
);
838 while ((r
= sd_bus_message_read(reply
, "(ss)", &type
, &path
)) > 0) {
840 r
= strv_extend(listening
, type
);
844 r
= strv_extend(listening
, path
);
851 return bus_log_parse_error(r
);
853 r
= sd_bus_message_exit_container(reply
);
855 return bus_log_parse_error(r
);
867 /* Note: triggered is a list here, although it almost certainly
868 * will always be one unit. Nevertheless, dbus API allows for multiple
869 * values, so let's follow that. */
872 /* The strv above is shared. free is set only in the first one. */
876 static int socket_info_compare(const struct socket_info
*a
, const struct socket_info
*b
) {
882 if (!a
->machine
&& b
->machine
)
884 if (a
->machine
&& !b
->machine
)
886 if (a
->machine
&& b
->machine
) {
887 o
= strcasecmp(a
->machine
, b
->machine
);
892 o
= strcmp(a
->path
, b
->path
);
894 o
= strcmp(a
->type
, b
->type
);
899 static int output_sockets_list(struct socket_info
*socket_infos
, unsigned cs
) {
900 struct socket_info
*s
;
901 unsigned pathlen
= STRLEN("LISTEN"),
902 typelen
= STRLEN("TYPE") * arg_show_types
,
903 socklen
= STRLEN("UNIT"),
904 servlen
= STRLEN("ACTIVATES");
905 const char *on
, *off
;
907 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
911 socklen
= MAX(socklen
, strlen(s
->id
));
913 typelen
= MAX(typelen
, strlen(s
->type
));
914 pathlen
= MAX(pathlen
, strlen(s
->path
) + (s
->machine
? strlen(s
->machine
)+1 : 0));
916 STRV_FOREACH(a
, s
->triggered
)
917 tmp
+= strlen(*a
) + 2*(a
!= s
->triggered
);
918 servlen
= MAX(servlen
, tmp
);
923 printf("%-*s %-*.*s%-*s %s\n",
925 typelen
+ arg_show_types
, typelen
+ arg_show_types
, "TYPE ",
929 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
930 _cleanup_free_
char *j
= NULL
;
935 j
= strjoin(s
->machine
, ":", s
->path
);
943 printf("%-*s %-*s %-*s",
944 pathlen
, path
, typelen
, s
->type
, socklen
, s
->id
);
947 pathlen
, path
, socklen
, s
->id
);
948 STRV_FOREACH(a
, s
->triggered
)
950 a
== s
->triggered
? "" : ",", *a
);
954 on
= ansi_highlight();
959 on
= ansi_highlight_red();
963 if (!arg_no_legend
) {
964 printf("%s%u sockets listed.%s\n", on
, cs
, off
);
966 printf("Pass --all to see loaded but inactive sockets, too.\n");
972 static int list_sockets(int argc
, char *argv
[], void *userdata
) {
973 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
974 _cleanup_strv_free_
char **machines
= NULL
;
975 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
976 _cleanup_free_
struct socket_info
*socket_infos
= NULL
;
978 struct socket_info
*s
;
984 r
= acquire_bus(BUS_MANAGER
, &bus
);
988 (void) pager_open(arg_no_pager
, false);
990 n
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
994 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
995 _cleanup_strv_free_
char **listening
= NULL
, **triggered
= NULL
;
998 if (!endswith(u
->id
, ".socket"))
1001 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
1005 c
= get_listening(bus
, u
->unit_path
, &listening
);
1011 if (!GREEDY_REALLOC(socket_infos
, size
, cs
+ c
)) {
1016 for (i
= 0; i
< c
; i
++)
1017 socket_infos
[cs
+ i
] = (struct socket_info
) {
1018 .machine
= u
->machine
,
1020 .type
= listening
[i
*2],
1021 .path
= listening
[i
*2 + 1],
1022 .triggered
= triggered
,
1023 .own_triggered
= i
==0,
1026 /* from this point on we will cleanup those socket_infos */
1029 listening
= triggered
= NULL
; /* avoid cleanup */
1032 qsort_safe(socket_infos
, cs
, sizeof(struct socket_info
),
1033 (__compar_fn_t
) socket_info_compare
);
1035 output_sockets_list(socket_infos
, cs
);
1038 assert(cs
== 0 || socket_infos
);
1039 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
1042 if (s
->own_triggered
)
1043 strv_free(s
->triggered
);
1049 static int get_next_elapse(
1052 dual_timestamp
*next
) {
1054 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1062 r
= sd_bus_get_property_trivial(
1064 "org.freedesktop.systemd1",
1066 "org.freedesktop.systemd1.Timer",
1067 "NextElapseUSecMonotonic",
1072 return log_error_errno(r
, "Failed to get next elapse time: %s", bus_error_message(&error
, r
));
1074 r
= sd_bus_get_property_trivial(
1076 "org.freedesktop.systemd1",
1078 "org.freedesktop.systemd1.Timer",
1079 "NextElapseUSecRealtime",
1084 return log_error_errno(r
, "Failed to get next elapse time: %s", bus_error_message(&error
, r
));
1090 static int get_last_trigger(
1095 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1102 r
= sd_bus_get_property_trivial(
1104 "org.freedesktop.systemd1",
1106 "org.freedesktop.systemd1.Timer",
1112 return log_error_errno(r
, "Failed to get last trigger time: %s", bus_error_message(&error
, r
));
1118 const char* machine
;
1121 usec_t last_trigger
;
1125 static int timer_info_compare(const struct timer_info
*a
, const struct timer_info
*b
) {
1131 if (!a
->machine
&& b
->machine
)
1133 if (a
->machine
&& !b
->machine
)
1135 if (a
->machine
&& b
->machine
) {
1136 o
= strcasecmp(a
->machine
, b
->machine
);
1141 if (a
->next_elapse
< b
->next_elapse
)
1143 if (a
->next_elapse
> b
->next_elapse
)
1146 return strcmp(a
->id
, b
->id
);
1149 static int output_timers_list(struct timer_info
*timer_infos
, unsigned n
) {
1150 struct timer_info
*t
;
1152 nextlen
= STRLEN("NEXT"),
1153 leftlen
= STRLEN("LEFT"),
1154 lastlen
= STRLEN("LAST"),
1155 passedlen
= STRLEN("PASSED"),
1156 unitlen
= STRLEN("UNIT"),
1157 activatelen
= STRLEN("ACTIVATES");
1159 const char *on
, *off
;
1161 assert(timer_infos
|| n
== 0);
1163 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1167 if (t
->next_elapse
> 0) {
1168 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1170 format_timestamp(tstamp
, sizeof(tstamp
), t
->next_elapse
);
1171 nextlen
= MAX(nextlen
, strlen(tstamp
) + 1);
1173 format_timestamp_relative(trel
, sizeof(trel
), t
->next_elapse
);
1174 leftlen
= MAX(leftlen
, strlen(trel
));
1177 if (t
->last_trigger
> 0) {
1178 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1180 format_timestamp(tstamp
, sizeof(tstamp
), t
->last_trigger
);
1181 lastlen
= MAX(lastlen
, strlen(tstamp
) + 1);
1183 format_timestamp_relative(trel
, sizeof(trel
), t
->last_trigger
);
1184 passedlen
= MAX(passedlen
, strlen(trel
));
1187 unitlen
= MAX(unitlen
, strlen(t
->id
) + (t
->machine
? strlen(t
->machine
)+1 : 0));
1189 STRV_FOREACH(a
, t
->triggered
)
1190 ul
+= strlen(*a
) + 2*(a
!= t
->triggered
);
1192 activatelen
= MAX(activatelen
, ul
);
1197 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1201 passedlen
, "PASSED",
1205 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1206 _cleanup_free_
char *j
= NULL
;
1208 char tstamp1
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel1
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1209 char tstamp2
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel2
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1212 format_timestamp(tstamp1
, sizeof(tstamp1
), t
->next_elapse
);
1213 format_timestamp_relative(trel1
, sizeof(trel1
), t
->next_elapse
);
1215 format_timestamp(tstamp2
, sizeof(tstamp2
), t
->last_trigger
);
1216 format_timestamp_relative(trel2
, sizeof(trel2
), t
->last_trigger
);
1219 j
= strjoin(t
->machine
, ":", t
->id
);
1226 printf("%-*s %-*s %-*s %-*s %-*s",
1227 nextlen
, tstamp1
, leftlen
, trel1
, lastlen
, tstamp2
, passedlen
, trel2
, unitlen
, unit
);
1229 STRV_FOREACH(a
, t
->triggered
)
1231 a
== t
->triggered
? "" : ",", *a
);
1235 on
= ansi_highlight();
1236 off
= ansi_normal();
1240 on
= ansi_highlight_red();
1241 off
= ansi_normal();
1244 if (!arg_no_legend
) {
1245 printf("%s%u timers listed.%s\n", on
, n
, off
);
1247 printf("Pass --all to see loaded but inactive timers, too.\n");
1253 static usec_t
calc_next_elapse(dual_timestamp
*nw
, dual_timestamp
*next
) {
1259 if (next
->monotonic
!= USEC_INFINITY
&& next
->monotonic
> 0) {
1262 if (next
->monotonic
> nw
->monotonic
)
1263 converted
= nw
->realtime
+ (next
->monotonic
- nw
->monotonic
);
1265 converted
= nw
->realtime
- (nw
->monotonic
- next
->monotonic
);
1267 if (next
->realtime
!= USEC_INFINITY
&& next
->realtime
> 0)
1268 next_elapse
= MIN(converted
, next
->realtime
);
1270 next_elapse
= converted
;
1273 next_elapse
= next
->realtime
;
1278 static int list_timers(int argc
, char *argv
[], void *userdata
) {
1279 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
1280 _cleanup_strv_free_
char **machines
= NULL
;
1281 _cleanup_free_
struct timer_info
*timer_infos
= NULL
;
1282 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
1283 struct timer_info
*t
;
1291 r
= acquire_bus(BUS_MANAGER
, &bus
);
1295 (void) pager_open(arg_no_pager
, false);
1297 n
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
1301 dual_timestamp_get(&nw
);
1303 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
1304 _cleanup_strv_free_
char **triggered
= NULL
;
1305 dual_timestamp next
= DUAL_TIMESTAMP_NULL
;
1308 if (!endswith(u
->id
, ".timer"))
1311 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
1315 r
= get_next_elapse(bus
, u
->unit_path
, &next
);
1319 get_last_trigger(bus
, u
->unit_path
, &last
);
1321 if (!GREEDY_REALLOC(timer_infos
, size
, c
+1)) {
1326 m
= calc_next_elapse(&nw
, &next
);
1328 timer_infos
[c
++] = (struct timer_info
) {
1329 .machine
= u
->machine
,
1332 .last_trigger
= last
,
1333 .triggered
= TAKE_PTR(triggered
),
1337 qsort_safe(timer_infos
, c
, sizeof(struct timer_info
),
1338 (__compar_fn_t
) timer_info_compare
);
1340 output_timers_list(timer_infos
, c
);
1343 for (t
= timer_infos
; t
< timer_infos
+ c
; t
++)
1344 strv_free(t
->triggered
);
1349 static int compare_unit_file_list(const void *a
, const void *b
) {
1350 const char *d1
, *d2
;
1351 const UnitFileList
*u
= a
, *v
= b
;
1353 d1
= strrchr(u
->path
, '.');
1354 d2
= strrchr(v
->path
, '.');
1359 r
= strcasecmp(d1
, d2
);
1364 return strcasecmp(basename(u
->path
), basename(v
->path
));
1367 static bool output_show_unit_file(const UnitFileList
*u
, char **states
, char **patterns
) {
1370 if (!strv_fnmatch_or_empty(patterns
, basename(u
->path
), FNM_NOESCAPE
))
1373 if (!strv_isempty(arg_types
)) {
1376 dot
= strrchr(u
->path
, '.');
1380 if (!strv_find(arg_types
, dot
+1))
1384 if (!strv_isempty(states
) &&
1385 !strv_find(states
, unit_file_state_to_string(u
->state
)))
1391 static void output_unit_file_list(const UnitFileList
*units
, unsigned c
) {
1392 unsigned max_id_len
, id_cols
, state_cols
;
1393 const UnitFileList
*u
;
1395 max_id_len
= STRLEN("UNIT FILE");
1396 state_cols
= STRLEN("STATE");
1398 for (u
= units
; u
< units
+ c
; u
++) {
1399 max_id_len
= MAX(max_id_len
, strlen(basename(u
->path
)));
1400 state_cols
= MAX(state_cols
, strlen(unit_file_state_to_string(u
->state
)));
1404 unsigned basic_cols
;
1406 id_cols
= MIN(max_id_len
, 25u);
1407 basic_cols
= 1 + id_cols
+ state_cols
;
1408 if (basic_cols
< (unsigned) columns())
1409 id_cols
+= MIN(columns() - basic_cols
, max_id_len
- id_cols
);
1411 id_cols
= max_id_len
;
1413 if (!arg_no_legend
&& c
> 0)
1414 printf("%s%-*s %-*s%s\n",
1416 id_cols
, "UNIT FILE",
1417 state_cols
, "STATE",
1420 for (u
= units
; u
< units
+ c
; u
++) {
1421 const char *on_underline
= NULL
, *on_color
= NULL
, *off
= NULL
, *id
;
1422 _cleanup_free_
char *e
= NULL
;
1425 underline
= u
+ 1 < units
+ c
&&
1426 !streq(unit_type_suffix(u
->path
), unit_type_suffix((u
+ 1)->path
));
1429 on_underline
= ansi_underline();
1431 if (IN_SET(u
->state
,
1433 UNIT_FILE_MASKED_RUNTIME
,
1436 on_color
= underline
? ansi_highlight_red_underline() : ansi_highlight_red();
1437 else if (u
->state
== UNIT_FILE_ENABLED
)
1438 on_color
= underline
? ansi_highlight_green_underline() : ansi_highlight_green();
1440 if (on_underline
|| on_color
)
1441 off
= ansi_normal();
1443 id
= basename(u
->path
);
1445 e
= arg_full
? NULL
: ellipsize(id
, id_cols
, 33);
1447 printf("%s%-*s %s%-*s%s\n",
1448 strempty(on_underline
),
1449 id_cols
, e
? e
: id
,
1450 strempty(on_color
), state_cols
, unit_file_state_to_string(u
->state
), strempty(off
));
1454 printf("\n%u unit files listed.\n", c
);
1457 static int list_unit_files(int argc
, char *argv
[], void *userdata
) {
1458 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1459 _cleanup_free_ UnitFileList
*units
= NULL
;
1466 bool fallback
= false;
1468 if (install_client_side()) {
1474 h
= hashmap_new(&string_hash_ops
);
1478 r
= unit_file_get_list(arg_scope
, arg_root
, h
, arg_states
, strv_skip(argv
, 1));
1480 unit_file_list_free(h
);
1481 return log_error_errno(r
, "Failed to get unit file list: %m");
1484 n_units
= hashmap_size(h
);
1486 units
= new(UnitFileList
, n_units
?: 1); /* avoid malloc(0) */
1488 unit_file_list_free(h
);
1492 HASHMAP_FOREACH(u
, h
, i
) {
1493 if (!output_show_unit_file(u
, NULL
, NULL
))
1500 assert(c
<= n_units
);
1505 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
1506 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1509 r
= acquire_bus(BUS_MANAGER
, &bus
);
1513 r
= sd_bus_message_new_method_call(
1516 "org.freedesktop.systemd1",
1517 "/org/freedesktop/systemd1",
1518 "org.freedesktop.systemd1.Manager",
1519 "ListUnitFilesByPatterns");
1521 return bus_log_create_error(r
);
1523 r
= sd_bus_message_append_strv(m
, arg_states
);
1525 return bus_log_create_error(r
);
1527 r
= sd_bus_message_append_strv(m
, strv_skip(argv
, 1));
1529 return bus_log_create_error(r
);
1531 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
1532 if (r
< 0 && sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_METHOD
)) {
1533 /* Fallback to legacy ListUnitFiles method */
1535 log_debug_errno(r
, "Failed to list unit files: %s Falling back to ListUnitsFiles method.", bus_error_message(&error
, r
));
1536 m
= sd_bus_message_unref(m
);
1537 sd_bus_error_free(&error
);
1539 r
= sd_bus_message_new_method_call(
1542 "org.freedesktop.systemd1",
1543 "/org/freedesktop/systemd1",
1544 "org.freedesktop.systemd1.Manager",
1547 return bus_log_create_error(r
);
1549 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
1552 return log_error_errno(r
, "Failed to list unit files: %s", bus_error_message(&error
, r
));
1554 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
1556 return bus_log_parse_error(r
);
1558 while ((r
= sd_bus_message_read(reply
, "(ss)", &path
, &state
)) > 0) {
1560 if (!GREEDY_REALLOC(units
, size
, c
+ 1))
1563 units
[c
] = (struct UnitFileList
) {
1565 unit_file_state_from_string(state
)
1568 if (output_show_unit_file(&units
[c
],
1569 fallback
? arg_states
: NULL
,
1570 fallback
? strv_skip(argv
, 1) : NULL
))
1575 return bus_log_parse_error(r
);
1577 r
= sd_bus_message_exit_container(reply
);
1579 return bus_log_parse_error(r
);
1582 (void) pager_open(arg_no_pager
, false);
1584 qsort_safe(units
, c
, sizeof(UnitFileList
), compare_unit_file_list
);
1585 output_unit_file_list(units
, c
);
1587 if (install_client_side())
1588 for (unit
= units
; unit
< units
+ c
; unit
++)
1594 static int list_dependencies_print(const char *name
, int level
, unsigned int branches
, bool last
) {
1595 _cleanup_free_
char *n
= NULL
;
1596 size_t max_len
= MAX(columns(),20u);
1602 for (i
= level
- 1; i
>= 0; i
--) {
1604 if (len
> max_len
- 3 && !arg_full
) {
1605 printf("%s...\n",max_len
% 2 ? "" : " ");
1608 printf("%s", special_glyph(branches
& (1 << i
) ? TREE_VERTICAL
: TREE_SPACE
));
1612 if (len
> max_len
- 3 && !arg_full
) {
1613 printf("%s...\n",max_len
% 2 ? "" : " ");
1617 printf("%s", special_glyph(last
? TREE_RIGHT
: TREE_BRANCH
));
1621 printf("%s\n", name
);
1625 n
= ellipsize(name
, max_len
-len
, 100);
1633 static int list_dependencies_get_dependencies(sd_bus
*bus
, const char *name
, char ***deps
) {
1635 struct DependencyStatusInfo
{
1639 static const struct bus_properties_map map
[_DEPENDENCY_MAX
][6] = {
1640 [DEPENDENCY_FORWARD
] = {
1641 { "Requires", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[0]) },
1642 { "Requisite", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[1]) },
1643 { "Wants", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[2]) },
1644 { "ConsistsOf", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[3]) },
1645 { "BindsTo", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[4]) },
1648 [DEPENDENCY_REVERSE
] = {
1649 { "RequiredBy", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[0]) },
1650 { "RequisiteOf", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[1]) },
1651 { "WantedBy", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[2]) },
1652 { "PartOf", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[3]) },
1653 { "BoundBy", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[4]) },
1656 [DEPENDENCY_AFTER
] = {
1657 { "After", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[0]) },
1660 [DEPENDENCY_BEFORE
] = {
1661 { "Before", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[0]) },
1666 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1667 _cleanup_strv_free_
char **ret
= NULL
;
1668 _cleanup_free_
char *path
= NULL
;
1675 path
= unit_dbus_path_from_name(name
);
1679 r
= bus_map_all_properties(bus
,
1680 "org.freedesktop.systemd1",
1682 map
[arg_dependency
],
1688 return log_error_errno(r
, "Failed to get properties of %s: %s", name
, bus_error_message(&error
, r
));
1690 if (IN_SET(arg_dependency
, DEPENDENCY_AFTER
, DEPENDENCY_BEFORE
)) {
1691 *deps
= info
.dep
[0];
1695 for (i
= 0; i
< 5; i
++) {
1696 r
= strv_extend_strv(&ret
, info
.dep
[i
], true);
1699 info
.dep
[i
] = strv_free(info
.dep
[i
]);
1702 *deps
= TAKE_PTR(ret
);
1707 static int list_dependencies_compare(const void *_a
, const void *_b
) {
1708 const char **a
= (const char**) _a
, **b
= (const char**) _b
;
1710 if (unit_name_to_type(*a
) == UNIT_TARGET
&& unit_name_to_type(*b
) != UNIT_TARGET
)
1712 if (unit_name_to_type(*a
) != UNIT_TARGET
&& unit_name_to_type(*b
) == UNIT_TARGET
)
1715 return strcasecmp(*a
, *b
);
1718 static int list_dependencies_one(
1723 unsigned int branches
) {
1725 _cleanup_strv_free_
char **deps
= NULL
;
1733 r
= strv_extend(units
, name
);
1737 r
= list_dependencies_get_dependencies(bus
, name
, &deps
);
1741 qsort_safe(deps
, strv_length(deps
), sizeof (char*), list_dependencies_compare
);
1743 STRV_FOREACH(c
, deps
) {
1744 if (strv_contains(*units
, *c
)) {
1747 r
= list_dependencies_print("...", level
+ 1, (branches
<< 1) | (c
[1] == NULL
? 0 : 1), 1);
1757 UnitActiveState active_state
= _UNIT_ACTIVE_STATE_INVALID
;
1760 (void) get_state_one_unit(bus
, *c
, &active_state
);
1762 switch (active_state
) {
1764 case UNIT_RELOADING
:
1765 case UNIT_ACTIVATING
:
1766 on
= ansi_highlight_green();
1770 case UNIT_DEACTIVATING
:
1775 on
= ansi_highlight_red();
1779 printf("%s%s%s ", on
, special_glyph(BLACK_CIRCLE
), ansi_normal());
1782 r
= list_dependencies_print(*c
, level
, branches
, c
[1] == NULL
);
1786 if (arg_all
|| unit_name_to_type(*c
) == UNIT_TARGET
) {
1787 r
= list_dependencies_one(bus
, *c
, level
+ 1, units
, (branches
<< 1) | (c
[1] == NULL
? 0 : 1));
1794 strv_remove(*units
, name
);
1799 static int list_dependencies(int argc
, char *argv
[], void *userdata
) {
1800 _cleanup_strv_free_
char **units
= NULL
;
1801 _cleanup_free_
char *unit
= NULL
;
1807 r
= unit_name_mangle(argv
[1], arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
, &unit
);
1809 return log_error_errno(r
, "Failed to mangle unit name: %m");
1813 u
= SPECIAL_DEFAULT_TARGET
;
1815 r
= acquire_bus(BUS_MANAGER
, &bus
);
1819 (void) pager_open(arg_no_pager
, false);
1823 return list_dependencies_one(bus
, u
, 0, &units
, 0);
1826 struct machine_info
{
1830 char *control_group
;
1831 uint32_t n_failed_units
;
1836 static const struct bus_properties_map machine_info_property_map
[] = {
1837 { "SystemState", "s", NULL
, offsetof(struct machine_info
, state
) },
1838 { "NJobs", "u", NULL
, offsetof(struct machine_info
, n_jobs
) },
1839 { "NFailedUnits", "u", NULL
, offsetof(struct machine_info
, n_failed_units
) },
1840 { "ControlGroup", "s", NULL
, offsetof(struct machine_info
, control_group
) },
1841 { "UserspaceTimestamp", "t", NULL
, offsetof(struct machine_info
, timestamp
) },
1845 static void machine_info_clear(struct machine_info
*info
) {
1850 free(info
->control_group
);
1854 static void free_machines_list(struct machine_info
*machine_infos
, int n
) {
1860 for (i
= 0; i
< n
; i
++)
1861 machine_info_clear(&machine_infos
[i
]);
1863 free(machine_infos
);
1866 static int compare_machine_info(const void *a
, const void *b
) {
1867 const struct machine_info
*u
= a
, *v
= b
;
1869 if (u
->is_host
!= v
->is_host
)
1870 return u
->is_host
> v
->is_host
? -1 : 1;
1872 return strcasecmp(u
->name
, v
->name
);
1875 static int get_machine_properties(sd_bus
*bus
, struct machine_info
*mi
) {
1876 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*container
= NULL
;
1882 r
= sd_bus_open_system_machine(&container
, mi
->name
);
1889 r
= bus_map_all_properties(
1891 "org.freedesktop.systemd1",
1892 "/org/freedesktop/systemd1",
1893 machine_info_property_map
,
1904 static bool output_show_machine(const char *name
, char **patterns
) {
1905 return strv_fnmatch_or_empty(patterns
, name
, FNM_NOESCAPE
);
1908 static int get_machine_list(
1910 struct machine_info
**_machine_infos
,
1913 struct machine_info
*machine_infos
= NULL
;
1914 _cleanup_strv_free_
char **m
= NULL
;
1915 _cleanup_free_
char *hn
= NULL
;
1920 hn
= gethostname_malloc();
1924 if (output_show_machine(hn
, patterns
)) {
1925 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1))
1928 machine_infos
[c
].is_host
= true;
1929 machine_infos
[c
].name
= TAKE_PTR(hn
);
1931 (void) get_machine_properties(bus
, &machine_infos
[c
]);
1935 r
= sd_get_machine_names(&m
);
1937 return log_error_errno(r
, "Failed to get machine list: %m");
1939 STRV_FOREACH(i
, m
) {
1940 _cleanup_free_
char *class = NULL
;
1942 if (!output_show_machine(*i
, patterns
))
1945 sd_machine_get_class(*i
, &class);
1946 if (!streq_ptr(class, "container"))
1949 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1)) {
1950 free_machines_list(machine_infos
, c
);
1954 machine_infos
[c
].is_host
= false;
1955 machine_infos
[c
].name
= strdup(*i
);
1956 if (!machine_infos
[c
].name
) {
1957 free_machines_list(machine_infos
, c
);
1961 (void) get_machine_properties(NULL
, &machine_infos
[c
]);
1965 *_machine_infos
= machine_infos
;
1969 static void output_machines_list(struct machine_info
*machine_infos
, unsigned n
) {
1970 struct machine_info
*m
;
1973 namelen
= STRLEN("NAME"),
1974 statelen
= STRLEN("STATE"),
1975 failedlen
= STRLEN("FAILED"),
1976 jobslen
= STRLEN("JOBS");
1978 assert(machine_infos
|| n
== 0);
1980 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
1981 namelen
= MAX(namelen
,
1982 strlen(m
->name
) + (m
->is_host
? STRLEN(" (host)") : 0));
1983 statelen
= MAX(statelen
, strlen_ptr(m
->state
));
1984 failedlen
= MAX(failedlen
, DECIMAL_STR_WIDTH(m
->n_failed_units
));
1985 jobslen
= MAX(jobslen
, DECIMAL_STR_WIDTH(m
->n_jobs
));
1987 if (!arg_plain
&& !streq_ptr(m
->state
, "running"))
1991 if (!arg_no_legend
) {
1995 printf("%-*s %-*s %-*s %-*s\n",
1998 failedlen
, "FAILED",
2002 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
2003 const char *on_state
= "", *off_state
= "";
2004 const char *on_failed
= "", *off_failed
= "";
2005 bool circle
= false;
2007 if (streq_ptr(m
->state
, "degraded")) {
2008 on_state
= ansi_highlight_red();
2009 off_state
= ansi_normal();
2011 } else if (!streq_ptr(m
->state
, "running")) {
2012 on_state
= ansi_highlight_yellow();
2013 off_state
= ansi_normal();
2017 if (m
->n_failed_units
> 0) {
2018 on_failed
= ansi_highlight_red();
2019 off_failed
= ansi_normal();
2021 on_failed
= off_failed
= "";
2024 printf("%s%s%s ", on_state
, circle
? special_glyph(BLACK_CIRCLE
) : " ", off_state
);
2027 printf("%-*s (host) %s%-*s%s %s%*" PRIu32
"%s %*" PRIu32
"\n",
2028 (int) (namelen
- (STRLEN(" (host)"))),
2030 on_state
, statelen
, strna(m
->state
), off_state
,
2031 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
2032 jobslen
, m
->n_jobs
);
2034 printf("%-*s %s%-*s%s %s%*" PRIu32
"%s %*" PRIu32
"\n",
2035 namelen
, strna(m
->name
),
2036 on_state
, statelen
, strna(m
->state
), off_state
,
2037 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
2038 jobslen
, m
->n_jobs
);
2042 printf("\n%u machines listed.\n", n
);
2045 static int list_machines(int argc
, char *argv
[], void *userdata
) {
2046 struct machine_info
*machine_infos
= NULL
;
2050 r
= acquire_bus(BUS_MANAGER
, &bus
);
2054 r
= get_machine_list(bus
, &machine_infos
, strv_skip(argv
, 1));
2058 (void) pager_open(arg_no_pager
, false);
2060 qsort_safe(machine_infos
, r
, sizeof(struct machine_info
), compare_machine_info
);
2061 output_machines_list(machine_infos
, r
);
2062 free_machines_list(machine_infos
, r
);
2067 static int get_default(int argc
, char *argv
[], void *userdata
) {
2068 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2069 _cleanup_free_
char *_path
= NULL
;
2073 if (install_client_side()) {
2074 r
= unit_file_get_default(arg_scope
, arg_root
, &_path
);
2076 return log_error_errno(r
, "Failed to get default target: %m");
2081 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2084 r
= acquire_bus(BUS_MANAGER
, &bus
);
2088 r
= sd_bus_call_method(
2090 "org.freedesktop.systemd1",
2091 "/org/freedesktop/systemd1",
2092 "org.freedesktop.systemd1.Manager",
2098 return log_error_errno(r
, "Failed to get default target: %s", bus_error_message(&error
, r
));
2100 r
= sd_bus_message_read(reply
, "s", &path
);
2102 return bus_log_parse_error(r
);
2106 printf("%s\n", path
);
2111 static int set_default(int argc
, char *argv
[], void *userdata
) {
2112 _cleanup_free_
char *unit
= NULL
;
2113 UnitFileChange
*changes
= NULL
;
2114 unsigned n_changes
= 0;
2120 r
= unit_name_mangle_with_suffix(argv
[1], arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
, ".target", &unit
);
2122 return log_error_errno(r
, "Failed to mangle unit name: %m");
2124 if (install_client_side()) {
2125 r
= unit_file_set_default(arg_scope
, UNIT_FILE_FORCE
, arg_root
, unit
, &changes
, &n_changes
);
2126 unit_file_dump_changes(r
, "set default", changes
, n_changes
, arg_quiet
);
2131 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2132 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2135 polkit_agent_open_maybe();
2137 r
= acquire_bus(BUS_MANAGER
, &bus
);
2141 r
= sd_bus_call_method(
2143 "org.freedesktop.systemd1",
2144 "/org/freedesktop/systemd1",
2145 "org.freedesktop.systemd1.Manager",
2151 return log_error_errno(r
, "Failed to set default target: %s", bus_error_message(&error
, r
));
2153 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
2157 /* Try to reload if enabled */
2159 r
= daemon_reload(argc
, argv
, userdata
);
2165 unit_file_changes_free(changes
, n_changes
);
2170 static int output_waiting_jobs(sd_bus
*bus
, uint32_t id
, const char *method
, const char *prefix
) {
2171 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2172 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2173 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2179 r
= sd_bus_call_method(
2181 "org.freedesktop.systemd1",
2182 "/org/freedesktop/systemd1",
2183 "org.freedesktop.systemd1.Manager",
2189 return log_debug_errno(r
, "Failed to get waiting jobs for job %" PRIu32
, id
);
2191 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2193 return bus_log_parse_error(r
);
2195 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &other_id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0)
2196 printf("%s %u (%s/%s)\n", prefix
, other_id
, name
, type
);
2198 return bus_log_parse_error(r
);
2200 r
= sd_bus_message_exit_container(reply
);
2202 return bus_log_parse_error(r
);
2209 const char *name
, *type
, *state
;
2212 static void output_jobs_list(sd_bus
*bus
, const struct job_info
* jobs
, unsigned n
, bool skipped
) {
2213 unsigned id_len
, unit_len
, type_len
, state_len
;
2214 const struct job_info
*j
;
2215 const char *on
, *off
;
2216 bool shorten
= false;
2218 assert(n
== 0 || jobs
);
2221 if (!arg_no_legend
) {
2222 on
= ansi_highlight_green();
2223 off
= ansi_normal();
2225 printf("%sNo jobs %s.%s\n", on
, skipped
? "listed" : "running", off
);
2230 (void) pager_open(arg_no_pager
, false);
2232 id_len
= STRLEN("JOB");
2233 unit_len
= STRLEN("UNIT");
2234 type_len
= STRLEN("TYPE");
2235 state_len
= STRLEN("STATE");
2237 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2238 uint32_t id
= j
->id
;
2239 assert(j
->name
&& j
->type
&& j
->state
);
2241 id_len
= MAX(id_len
, DECIMAL_STR_WIDTH(id
));
2242 unit_len
= MAX(unit_len
, strlen(j
->name
));
2243 type_len
= MAX(type_len
, strlen(j
->type
));
2244 state_len
= MAX(state_len
, strlen(j
->state
));
2247 if (!arg_full
&& id_len
+ 1 + unit_len
+ type_len
+ 1 + state_len
> columns()) {
2248 unit_len
= MAX(33u, columns() - id_len
- type_len
- state_len
- 3);
2253 printf("%*s %-*s %-*s %-*s\n",
2257 state_len
, "STATE");
2259 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2260 _cleanup_free_
char *e
= NULL
;
2262 if (streq(j
->state
, "running")) {
2263 on
= ansi_highlight();
2264 off
= ansi_normal();
2268 e
= shorten
? ellipsize(j
->name
, unit_len
, 33) : NULL
;
2269 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2271 on
, unit_len
, e
? e
: j
->name
, off
,
2273 on
, state_len
, j
->state
, off
);
2276 output_waiting_jobs(bus
, j
->id
, "GetJobAfter", "\twaiting for job");
2277 if (arg_jobs_before
)
2278 output_waiting_jobs(bus
, j
->id
, "GetJobBefore", "\tblocking job");
2281 if (!arg_no_legend
) {
2282 on
= ansi_highlight();
2283 off
= ansi_normal();
2285 printf("\n%s%u jobs listed%s.\n", on
, n
, off
);
2289 static bool output_show_job(struct job_info
*job
, char **patterns
) {
2290 return strv_fnmatch_or_empty(patterns
, job
->name
, FNM_NOESCAPE
);
2293 static int list_jobs(int argc
, char *argv
[], void *userdata
) {
2294 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2295 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2296 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2297 _cleanup_free_
struct job_info
*jobs
= NULL
;
2303 bool skipped
= false;
2305 r
= acquire_bus(BUS_MANAGER
, &bus
);
2309 r
= sd_bus_call_method(
2311 "org.freedesktop.systemd1",
2312 "/org/freedesktop/systemd1",
2313 "org.freedesktop.systemd1.Manager",
2319 return log_error_errno(r
, "Failed to list jobs: %s", bus_error_message(&error
, r
));
2321 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2323 return bus_log_parse_error(r
);
2325 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0) {
2326 struct job_info job
= { id
, name
, type
, state
};
2328 if (!output_show_job(&job
, strv_skip(argv
, 1))) {
2333 if (!GREEDY_REALLOC(jobs
, size
, c
+ 1))
2339 return bus_log_parse_error(r
);
2341 r
= sd_bus_message_exit_container(reply
);
2343 return bus_log_parse_error(r
);
2345 (void) pager_open(arg_no_pager
, false);
2347 output_jobs_list(bus
, jobs
, c
, skipped
);
2351 static int cancel_job(int argc
, char *argv
[], void *userdata
) {
2357 return trivial_method(argc
, argv
, userdata
);
2359 r
= acquire_bus(BUS_MANAGER
, &bus
);
2363 polkit_agent_open_maybe();
2365 STRV_FOREACH(name
, strv_skip(argv
, 1)) {
2366 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2370 q
= safe_atou32(*name
, &id
);
2372 return log_error_errno(q
, "Failed to parse job id \"%s\": %m", *name
);
2374 q
= sd_bus_call_method(
2376 "org.freedesktop.systemd1",
2377 "/org/freedesktop/systemd1",
2378 "org.freedesktop.systemd1.Manager",
2384 log_error_errno(q
, "Failed to cancel job %"PRIu32
": %s", id
, bus_error_message(&error
, q
));
2393 static int need_daemon_reload(sd_bus
*bus
, const char *unit
) {
2394 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2398 /* We ignore all errors here, since this is used to show a
2401 /* We don't use unit_dbus_path_from_name() directly since we
2402 * don't want to load the unit if it isn't loaded. */
2404 r
= sd_bus_call_method(
2406 "org.freedesktop.systemd1",
2407 "/org/freedesktop/systemd1",
2408 "org.freedesktop.systemd1.Manager",
2416 r
= sd_bus_message_read(reply
, "o", &path
);
2420 r
= sd_bus_get_property_trivial(
2422 "org.freedesktop.systemd1",
2424 "org.freedesktop.systemd1.Unit",
2434 static void warn_unit_file_changed(const char *name
) {
2437 log_warning("%sWarning:%s The unit file, source configuration file or drop-ins of %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
2438 ansi_highlight_red(),
2441 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user");
2444 static int unit_file_find_path(LookupPaths
*lp
, const char *unit_name
, char **unit_path
) {
2450 STRV_FOREACH(p
, lp
->search_path
) {
2451 _cleanup_free_
char *path
= NULL
, *lpath
= NULL
;
2454 path
= path_join(NULL
, *p
, unit_name
);
2458 r
= chase_symlinks(path
, arg_root
, 0, &lpath
);
2464 return log_error_errno(r
, "Failed to access path '%s': %m", path
);
2467 *unit_path
= TAKE_PTR(lpath
);
2475 static int unit_find_template_path(
2476 const char *unit_name
,
2478 char **fragment_path
,
2481 _cleanup_free_
char *_template
= NULL
;
2484 /* Returns 1 if a fragment was found, 0 if not found, negative on error. */
2486 r
= unit_file_find_path(lp
, unit_name
, fragment_path
);
2488 return r
; /* error or found a real unit */
2490 r
= unit_name_template(unit_name
, &_template
);
2492 return 0; /* not a template, does not exist */
2494 return log_error_errno(r
, "Failed to determine template name: %m");
2496 r
= unit_file_find_path(lp
, _template
, fragment_path
);
2501 *template = TAKE_PTR(_template
);
2506 static int unit_find_paths(
2508 const char *unit_name
,
2510 char **fragment_path
,
2511 char ***dropin_paths
) {
2513 _cleanup_free_
char *path
= NULL
;
2514 _cleanup_strv_free_
char **dropins
= NULL
;
2518 * Finds where the unit is defined on disk. Returns 0 if the unit
2519 * is not found. Returns 1 if it is found, and sets
2520 * - the path to the unit in *path, if it exists on disk,
2521 * - and a strv of existing drop-ins in *dropins,
2522 * if the arg is not NULL and any dropins were found.
2526 assert(fragment_path
);
2529 if (!install_client_side() && !unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
2530 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2531 _cleanup_free_
char *unit
= NULL
;
2533 unit
= unit_dbus_path_from_name(unit_name
);
2537 r
= sd_bus_get_property_string(
2539 "org.freedesktop.systemd1",
2541 "org.freedesktop.systemd1.Unit",
2546 return log_error_errno(r
, "Failed to get FragmentPath: %s", bus_error_message(&error
, r
));
2549 r
= sd_bus_get_property_strv(
2551 "org.freedesktop.systemd1",
2553 "org.freedesktop.systemd1.Unit",
2558 return log_error_errno(r
, "Failed to get DropInPaths: %s", bus_error_message(&error
, r
));
2561 _cleanup_set_free_ Set
*names
= NULL
;
2562 _cleanup_free_
char *template = NULL
;
2564 names
= set_new(NULL
);
2568 r
= unit_find_template_path(unit_name
, lp
, &path
, &template);
2573 /* We found the unit file. If we followed symlinks, this name might be
2574 * different then the unit_name with started with. Look for dropins matching
2575 * that "final" name. */
2576 r
= set_put(names
, basename(path
));
2578 /* No unit file, let's look for dropins matching the original name.
2579 * systemd has fairly complicated rules (based on unit type and provenience),
2580 * which units are allowed not to have the main unit file. We err on the
2581 * side of including too many files, and always try to load dropins. */
2582 r
= set_put(names
, unit_name
);
2584 /* The cases where we allow a unit to exist without the main file are
2585 * never valid for templates. Don't try to load dropins in this case. */
2589 return log_error_errno(r
, "Failed to add unit name: %m");
2592 r
= unit_file_find_dropin_conf_paths(arg_root
, lp
->search_path
,
2593 NULL
, names
, &dropins
);
2601 if (!isempty(path
)) {
2602 *fragment_path
= TAKE_PTR(path
);
2606 if (dropin_paths
&& !strv_isempty(dropins
)) {
2607 *dropin_paths
= TAKE_PTR(dropins
);
2611 if (r
== 0 && !arg_force
)
2612 log_error("No files found for %s.", unit_name
);
2617 static int get_state_one_unit(sd_bus
*bus
, const char *name
, UnitActiveState
*active_state
) {
2618 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2619 _cleanup_free_
char *buf
= NULL
, *path
= NULL
;
2620 UnitActiveState state
;
2624 assert(active_state
);
2626 path
= unit_dbus_path_from_name(name
);
2630 r
= sd_bus_get_property_string(
2632 "org.freedesktop.systemd1",
2634 "org.freedesktop.systemd1.Unit",
2639 return log_error_errno(r
, "Failed to retrieve unit state: %s", bus_error_message(&error
, r
));
2641 state
= unit_active_state_from_string(buf
);
2642 if (state
== _UNIT_ACTIVE_STATE_INVALID
) {
2643 log_error("Invalid unit state '%s' for: %s", buf
, name
);
2647 *active_state
= state
;
2651 static int unit_is_masked(sd_bus
*bus
, const char *name
) {
2652 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2653 _cleanup_free_
char *path
= NULL
, *load_state
= NULL
;
2656 path
= unit_dbus_path_from_name(name
);
2660 r
= sd_bus_get_property_string(
2662 "org.freedesktop.systemd1",
2664 "org.freedesktop.systemd1.Unit",
2669 return log_error_errno(r
, "Failed to get load state of %s: %s", name
, bus_error_message(&error
, r
));
2671 return streq(load_state
, "masked");
2674 static int check_triggering_units(sd_bus
*bus
, const char *name
) {
2675 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2676 _cleanup_free_
char *n
= NULL
, *path
= NULL
;
2677 _cleanup_strv_free_
char **triggered_by
= NULL
;
2678 bool print_warning_label
= true;
2679 UnitActiveState active_state
;
2683 r
= unit_name_mangle(name
, 0, &n
);
2685 return log_error_errno(r
, "Failed to mangle unit name: %m");
2687 r
= unit_is_masked(bus
, n
);
2689 return r
< 0 ? r
: 0;
2691 path
= unit_dbus_path_from_name(n
);
2695 r
= sd_bus_get_property_strv(
2697 "org.freedesktop.systemd1",
2699 "org.freedesktop.systemd1.Unit",
2704 return log_error_errno(r
, "Failed to get triggered by array of %s: %s", n
, bus_error_message(&error
, r
));
2706 STRV_FOREACH(i
, triggered_by
) {
2707 r
= get_state_one_unit(bus
, *i
, &active_state
);
2711 if (!IN_SET(active_state
, UNIT_ACTIVE
, UNIT_RELOADING
))
2714 if (print_warning_label
) {
2715 log_warning("Warning: Stopping %s, but it can still be activated by:", n
);
2716 print_warning_label
= false;
2719 log_warning(" %s", *i
);
2725 static const struct {
2728 } unit_actions
[] = {
2729 { "start", "StartUnit" },
2730 { "stop", "StopUnit" },
2731 { "condstop", "StopUnit" },
2732 { "reload", "ReloadUnit" },
2733 { "restart", "RestartUnit" },
2734 { "try-restart", "TryRestartUnit" },
2735 { "condrestart", "TryRestartUnit" },
2736 { "reload-or-restart", "ReloadOrRestartUnit" },
2737 { "try-reload-or-restart", "ReloadOrTryRestartUnit" },
2738 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2739 { "condreload", "ReloadOrTryRestartUnit" },
2740 { "force-reload", "ReloadOrTryRestartUnit" }
2743 static const char *verb_to_method(const char *verb
) {
2746 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2747 if (streq_ptr(unit_actions
[i
].verb
, verb
))
2748 return unit_actions
[i
].method
;
2753 static const char *method_to_verb(const char *method
) {
2756 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2757 if (streq_ptr(unit_actions
[i
].method
, method
))
2758 return unit_actions
[i
].verb
;
2770 static void wait_context_free(WaitContext
*c
) {
2771 c
->match
= sd_bus_slot_unref(c
->match
);
2772 c
->event
= sd_event_unref(c
->event
);
2773 c
->unit_paths
= set_free_free(c
->unit_paths
);
2776 static int on_properties_changed(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
2777 WaitContext
*c
= userdata
;
2781 path
= sd_bus_message_get_path(m
);
2782 if (!set_contains(c
->unit_paths
, path
))
2785 /* Check if ActiveState changed to inactive/failed */
2786 /* (s interface, a{sv} changed_properties, as invalidated_properties) */
2787 r
= sd_bus_message_skip(m
, "s");
2789 return bus_log_parse_error(r
);
2791 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "{sv}");
2793 return bus_log_parse_error(r
);
2795 while ((r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
2798 r
= sd_bus_message_read(m
, "s", &s
);
2800 return bus_log_parse_error(r
);
2802 if (streq(s
, "ActiveState")) {
2805 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, "s");
2807 return bus_log_parse_error(r
);
2809 r
= sd_bus_message_read(m
, "s", &s
);
2811 return bus_log_parse_error(r
);
2813 is_failed
= streq(s
, "failed");
2814 if (streq(s
, "inactive") || is_failed
) {
2815 log_debug("%s became %s, dropping from --wait tracking", path
, s
);
2816 free(set_remove(c
->unit_paths
, path
));
2817 c
->any_failed
= c
->any_failed
|| is_failed
;
2819 log_debug("ActiveState on %s changed to %s", path
, s
);
2821 break; /* no need to dissect the rest of the message */
2823 /* other property */
2824 r
= sd_bus_message_skip(m
, "v");
2826 return bus_log_parse_error(r
);
2828 r
= sd_bus_message_exit_container(m
);
2830 return bus_log_parse_error(r
);
2833 return bus_log_parse_error(r
);
2835 if (set_isempty(c
->unit_paths
))
2836 sd_event_exit(c
->event
, EXIT_SUCCESS
);
2841 static int start_unit_one(
2846 sd_bus_error
*error
,
2848 WaitContext
*wait_context
) {
2850 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2860 _cleanup_free_
char *unit_path
= NULL
;
2862 log_debug("Watching for property changes of %s", name
);
2863 r
= sd_bus_call_method(
2865 "org.freedesktop.systemd1",
2866 "/org/freedesktop/systemd1",
2867 "org.freedesktop.systemd1.Manager",
2873 return log_error_errno(r
, "Failed to RefUnit %s: %s", name
, bus_error_message(error
, r
));
2875 unit_path
= unit_dbus_path_from_name(name
);
2879 r
= set_put_strdup(wait_context
->unit_paths
, unit_path
);
2881 return log_error_errno(r
, "Failed to add unit path %s to set: %m", unit_path
);
2883 r
= sd_bus_match_signal_async(bus
,
2884 &wait_context
->match
,
2887 "org.freedesktop.DBus.Properties",
2888 "PropertiesChanged",
2889 on_properties_changed
, NULL
, wait_context
);
2891 return log_error_errno(r
, "Failed to request match for PropertiesChanged signal: %m");
2894 log_debug("%s dbus call org.freedesktop.systemd1.Manager %s(%s, %s)",
2895 arg_dry_run
? "Would execute" : "Executing",
2896 method
, name
, mode
);
2900 r
= sd_bus_call_method(
2902 "org.freedesktop.systemd1",
2903 "/org/freedesktop/systemd1",
2904 "org.freedesktop.systemd1.Manager",
2912 /* There's always a fallback possible for legacy actions. */
2913 if (arg_action
!= ACTION_SYSTEMCTL
)
2916 verb
= method_to_verb(method
);
2918 log_error("Failed to %s %s: %s", verb
, name
, bus_error_message(error
, r
));
2920 if (!sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) &&
2921 !sd_bus_error_has_name(error
, BUS_ERROR_UNIT_MASKED
) &&
2922 !sd_bus_error_has_name(error
, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE
))
2923 log_error("See %s logs and 'systemctl%s status%s %s' for details.",
2924 arg_scope
== UNIT_FILE_SYSTEM
? "system" : "user",
2925 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user",
2926 name
[0] == '-' ? " --" : "",
2932 r
= sd_bus_message_read(reply
, "o", &path
);
2934 return bus_log_parse_error(r
);
2936 if (need_daemon_reload(bus
, name
) > 0)
2937 warn_unit_file_changed(name
);
2940 log_debug("Adding %s to the set", path
);
2941 r
= bus_wait_for_jobs_add(w
, path
);
2949 static int expand_names(sd_bus
*bus
, char **names
, const char* suffix
, char ***ret
) {
2950 _cleanup_strv_free_
char **mangled
= NULL
, **globs
= NULL
;
2957 STRV_FOREACH(name
, names
) {
2959 UnitNameMangle options
= UNIT_NAME_MANGLE_GLOB
| (arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
);
2962 r
= unit_name_mangle_with_suffix(*name
, options
, suffix
, &t
);
2964 r
= unit_name_mangle(*name
, options
, &t
);
2966 return log_error_errno(r
, "Failed to mangle name: %m");
2968 if (string_is_glob(t
))
2969 r
= strv_consume(&globs
, t
);
2971 r
= strv_consume(&mangled
, t
);
2976 /* Query the manager only if any of the names are a glob, since
2977 * this is fairly expensive */
2978 if (!strv_isempty(globs
)) {
2979 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2980 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
2981 size_t allocated
, n
;
2983 r
= get_unit_list(bus
, NULL
, globs
, &unit_infos
, 0, &reply
);
2987 n
= strv_length(mangled
);
2990 for (i
= 0; i
< r
; i
++) {
2991 if (!GREEDY_REALLOC(mangled
, allocated
, n
+2))
2994 mangled
[n
] = strdup(unit_infos
[i
].id
);
2998 mangled
[++n
] = NULL
;
3002 *ret
= TAKE_PTR(mangled
);
3007 static const struct {
3011 } action_table
[_ACTION_MAX
] = {
3012 [ACTION_HALT
] = { SPECIAL_HALT_TARGET
, "halt", "replace-irreversibly" },
3013 [ACTION_POWEROFF
] = { SPECIAL_POWEROFF_TARGET
, "poweroff", "replace-irreversibly" },
3014 [ACTION_REBOOT
] = { SPECIAL_REBOOT_TARGET
, "reboot", "replace-irreversibly" },
3015 [ACTION_KEXEC
] = { SPECIAL_KEXEC_TARGET
, "kexec", "replace-irreversibly" },
3016 [ACTION_RUNLEVEL2
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
3017 [ACTION_RUNLEVEL3
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
3018 [ACTION_RUNLEVEL4
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
3019 [ACTION_RUNLEVEL5
] = { SPECIAL_GRAPHICAL_TARGET
, NULL
, "isolate" },
3020 [ACTION_RESCUE
] = { SPECIAL_RESCUE_TARGET
, "rescue", "isolate" },
3021 [ACTION_EMERGENCY
] = { SPECIAL_EMERGENCY_TARGET
, "emergency", "isolate" },
3022 [ACTION_DEFAULT
] = { SPECIAL_DEFAULT_TARGET
, "default", "isolate" },
3023 [ACTION_EXIT
] = { SPECIAL_EXIT_TARGET
, "exit", "replace-irreversibly" },
3024 [ACTION_SUSPEND
] = { SPECIAL_SUSPEND_TARGET
, "suspend", "replace-irreversibly" },
3025 [ACTION_HIBERNATE
] = { SPECIAL_HIBERNATE_TARGET
, "hibernate", "replace-irreversibly" },
3026 [ACTION_HYBRID_SLEEP
] = { SPECIAL_HYBRID_SLEEP_TARGET
, "hybrid-sleep", "replace-irreversibly" },
3027 [ACTION_SUSPEND_THEN_HIBERNATE
] = { SPECIAL_SUSPEND_THEN_HIBERNATE_TARGET
, "suspend-then-hibernate", "replace-irreversibly" },
3030 static enum action
verb_to_action(const char *verb
) {
3033 for (i
= 0; i
< _ACTION_MAX
; i
++)
3034 if (streq_ptr(action_table
[i
].verb
, verb
))
3037 return _ACTION_INVALID
;
3040 static int start_unit(int argc
, char *argv
[], void *userdata
) {
3041 _cleanup_(bus_wait_for_jobs_freep
) BusWaitForJobs
*w
= NULL
;
3042 const char *method
, *mode
, *one_name
, *suffix
= NULL
;
3043 _cleanup_strv_free_
char **names
= NULL
;
3045 _cleanup_(wait_context_free
) WaitContext wait_context
= {};
3049 if (arg_wait
&& !STR_IN_SET(argv
[0], "start", "restart")) {
3050 log_error("--wait may only be used with the 'start' or 'restart' commands.");
3054 /* we cannot do sender tracking on the private bus, so we need the full
3055 * one for RefUnit to implement --wait */
3056 r
= acquire_bus(arg_wait
? BUS_FULL
: BUS_MANAGER
, &bus
);
3060 ask_password_agent_open_if_enabled();
3061 polkit_agent_open_maybe();
3063 if (arg_action
== ACTION_SYSTEMCTL
) {
3066 action
= verb_to_action(argv
[0]);
3068 if (action
!= _ACTION_INVALID
) {
3069 method
= "StartUnit";
3070 mode
= action_table
[action
].mode
;
3071 one_name
= action_table
[action
].target
;
3073 if (streq(argv
[0], "isolate")) {
3074 method
= "StartUnit";
3079 method
= verb_to_method(argv
[0]);
3080 mode
= arg_job_mode
;
3085 assert(arg_action
>= 0 && arg_action
< _ACTION_MAX
);
3086 assert(action_table
[arg_action
].target
);
3087 assert(action_table
[arg_action
].mode
);
3089 method
= "StartUnit";
3090 mode
= action_table
[arg_action
].mode
;
3091 one_name
= action_table
[arg_action
].target
;
3095 names
= strv_new(one_name
, NULL
);
3097 r
= expand_names(bus
, strv_skip(argv
, 1), suffix
, &names
);
3099 return log_error_errno(r
, "Failed to expand names: %m");
3102 if (!arg_no_block
) {
3103 r
= bus_wait_for_jobs_new(bus
, &w
);
3105 return log_error_errno(r
, "Could not watch jobs: %m");
3109 wait_context
.unit_paths
= set_new(&string_hash_ops
);
3110 if (!wait_context
.unit_paths
)
3113 r
= sd_bus_call_method_async(
3116 "org.freedesktop.systemd1",
3117 "/org/freedesktop/systemd1",
3118 "org.freedesktop.systemd1.Manager",
3123 return log_error_errno(r
, "Failed to enable subscription: %m");
3124 r
= sd_event_default(&wait_context
.event
);
3126 return log_error_errno(r
, "Failed to allocate event loop: %m");
3127 r
= sd_bus_attach_event(bus
, wait_context
.event
, 0);
3129 return log_error_errno(r
, "Failed to attach bus to event loop: %m");
3132 STRV_FOREACH(name
, names
) {
3133 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3136 q
= start_unit_one(bus
, method
, *name
, mode
, &error
, w
, arg_wait
? &wait_context
: NULL
);
3137 if (r
>= 0 && q
< 0)
3138 r
= translate_bus_error_to_exit_status(q
, &error
);
3141 if (!arg_no_block
) {
3142 int q
, arg_count
= 0;
3143 const char* extra_args
[4] = {};
3145 if (arg_scope
!= UNIT_FILE_SYSTEM
)
3146 extra_args
[arg_count
++] = "--user";
3148 assert(IN_SET(arg_transport
, BUS_TRANSPORT_LOCAL
, BUS_TRANSPORT_REMOTE
, BUS_TRANSPORT_MACHINE
));
3149 if (arg_transport
== BUS_TRANSPORT_REMOTE
) {
3150 extra_args
[arg_count
++] = "-H";
3151 extra_args
[arg_count
++] = arg_host
;
3152 } else if (arg_transport
== BUS_TRANSPORT_MACHINE
) {
3153 extra_args
[arg_count
++] = "-M";
3154 extra_args
[arg_count
++] = arg_host
;
3157 q
= bus_wait_for_jobs(w
, arg_quiet
, extra_args
);
3161 /* When stopping units, warn if they can still be triggered by
3162 * another active unit (socket, path, timer) */
3163 if (!arg_quiet
&& streq(method
, "StopUnit"))
3164 STRV_FOREACH(name
, names
)
3165 check_triggering_units(bus
, *name
);
3168 if (r
>= 0 && arg_wait
) {
3170 q
= sd_event_loop(wait_context
.event
);
3172 return log_error_errno(q
, "Failed to run event loop: %m");
3173 if (wait_context
.any_failed
)
3181 static int logind_set_wall_message(void) {
3182 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3184 _cleanup_free_
char *m
= NULL
;
3187 r
= acquire_bus(BUS_FULL
, &bus
);
3191 m
= strv_join(arg_wall
, " ");
3195 log_debug("%s wall message \"%s\".", arg_dry_run
? "Would set" : "Setting", m
);
3199 r
= sd_bus_call_method(
3201 "org.freedesktop.login1",
3202 "/org/freedesktop/login1",
3203 "org.freedesktop.login1.Manager",
3212 return log_warning_errno(r
, "Failed to set wall message, ignoring: %s", bus_error_message(&error
, r
));
3217 /* Ask systemd-logind, which might grant access to unprivileged users
3218 * through PolicyKit */
3219 static int logind_reboot(enum action a
) {
3221 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3222 const char *method
, *description
;
3226 r
= acquire_bus(BUS_FULL
, &bus
);
3232 case ACTION_POWEROFF
:
3233 method
= "PowerOff";
3234 description
= "power off system";
3239 description
= "reboot system";
3244 description
= "halt system";
3247 case ACTION_SUSPEND
:
3249 description
= "suspend system";
3252 case ACTION_HIBERNATE
:
3253 method
= "Hibernate";
3254 description
= "hibernate system";
3257 case ACTION_HYBRID_SLEEP
:
3258 method
= "HybridSleep";
3259 description
= "put system into hybrid sleep";
3262 case ACTION_SUSPEND_THEN_HIBERNATE
:
3263 method
= "SuspendThenHibernate";
3264 description
= "put system into suspend followed by hibernate";
3271 polkit_agent_open_maybe();
3272 (void) logind_set_wall_message();
3274 log_debug("%s org.freedesktop.login1.Manager %s dbus call.", arg_dry_run
? "Would execute" : "Executing", method
);
3278 r
= sd_bus_call_method(
3280 "org.freedesktop.login1",
3281 "/org/freedesktop/login1",
3282 "org.freedesktop.login1.Manager",
3286 "b", arg_ask_password
);
3288 return log_error_errno(r
, "Failed to %s via logind: %s", description
, bus_error_message(&error
, r
));
3296 static int logind_check_inhibitors(enum action a
) {
3298 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
3299 _cleanup_strv_free_
char **sessions
= NULL
;
3300 const char *what
, *who
, *why
, *mode
;
3307 if (arg_ignore_inhibitors
|| arg_force
> 0)
3319 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
3322 r
= acquire_bus(BUS_FULL
, &bus
);
3326 r
= sd_bus_call_method(
3328 "org.freedesktop.login1",
3329 "/org/freedesktop/login1",
3330 "org.freedesktop.login1.Manager",
3336 /* If logind is not around, then there are no inhibitors... */
3339 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssuu)");
3341 return bus_log_parse_error(r
);
3343 while ((r
= sd_bus_message_read(reply
, "(ssssuu)", &what
, &who
, &why
, &mode
, &uid
, &pid
)) > 0) {
3344 _cleanup_free_
char *comm
= NULL
, *user
= NULL
;
3345 _cleanup_strv_free_
char **sv
= NULL
;
3347 if (!streq(mode
, "block"))
3350 sv
= strv_split(what
, ":");
3354 if (!pid_is_valid((pid_t
) pid
)) {
3355 log_error("Invalid PID "PID_FMT
".", (pid_t
) pid
);
3359 if (!strv_contains(sv
,
3364 ACTION_KEXEC
) ? "shutdown" : "sleep"))
3367 get_process_comm(pid
, &comm
);
3368 user
= uid_to_name(uid
);
3370 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT
" \"%s\", user %s), reason is \"%s\".",
3371 who
, (pid_t
) pid
, strna(comm
), strna(user
), why
);
3376 return bus_log_parse_error(r
);
3378 r
= sd_bus_message_exit_container(reply
);
3380 return bus_log_parse_error(r
);
3382 /* Check for current sessions */
3383 sd_get_sessions(&sessions
);
3384 STRV_FOREACH(s
, sessions
) {
3385 _cleanup_free_
char *type
= NULL
, *tty
= NULL
, *seat
= NULL
, *user
= NULL
, *service
= NULL
, *class = NULL
;
3387 if (sd_session_get_uid(*s
, &uid
) < 0 || uid
== getuid())
3390 if (sd_session_get_class(*s
, &class) < 0 || !streq(class, "user"))
3393 if (sd_session_get_type(*s
, &type
) < 0 || !STR_IN_SET(type
, "x11", "wayland", "tty", "mir"))
3396 sd_session_get_tty(*s
, &tty
);
3397 sd_session_get_seat(*s
, &seat
);
3398 sd_session_get_service(*s
, &service
);
3399 user
= uid_to_name(uid
);
3401 log_warning("User %s is logged in on %s.", strna(user
), isempty(tty
) ? (isempty(seat
) ? strna(service
) : seat
) : tty
);
3408 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
3409 action_table
[a
].verb
);
3417 static int logind_prepare_firmware_setup(void) {
3419 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3423 r
= acquire_bus(BUS_FULL
, &bus
);
3427 r
= sd_bus_call_method(
3429 "org.freedesktop.login1",
3430 "/org/freedesktop/login1",
3431 "org.freedesktop.login1.Manager",
3432 "SetRebootToFirmwareSetup",
3437 return log_error_errno(r
, "Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error
, r
));
3441 log_error("Cannot remotely indicate to EFI to boot into setup mode.");
3446 static int prepare_firmware_setup(void) {
3449 if (!arg_firmware_setup
)
3452 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
3454 r
= efi_set_reboot_to_firmware(true);
3456 log_debug_errno(r
, "Cannot indicate to EFI to boot into setup mode, will retry via logind: %m");
3461 return logind_prepare_firmware_setup();
3464 static int load_kexec_kernel(void) {
3465 _cleanup_(boot_config_free
) BootConfig config
= {};
3466 _cleanup_free_
char *where
= NULL
, *kernel
= NULL
, *initrd
= NULL
, *options
= NULL
;
3471 if (kexec_loaded()) {
3472 log_debug("Kexec kernel already loaded.");
3476 if (access(KEXEC
, X_OK
) < 0)
3477 return log_error_errno(errno
, KEXEC
" is not available: %m");
3479 r
= find_esp_and_warn(arg_esp_path
, false, &where
, NULL
, NULL
, NULL
, NULL
);
3480 if (r
== -ENOKEY
) /* find_esp_and_warn() doesn't warn about this case */
3481 return log_error_errno(r
, "Cannot find the ESP partition mount point.");
3482 if (r
< 0) /* But it logs about all these cases, hence don't log here again */
3485 r
= boot_entries_load_config(where
, &config
);
3487 return log_error_errno(r
, "Failed to load bootspec config from \"%s/loader\": %m", where
);
3489 if (config
.default_entry
< 0) {
3490 log_error("No entry suitable as default, refusing to guess.");
3493 e
= &config
.entries
[config
.default_entry
];
3495 if (strv_length(e
->initrd
) > 1) {
3496 log_error("Boot entry specifies multiple initrds, which is not supported currently.");
3500 kernel
= path_join(NULL
, where
, e
->kernel
);
3501 if (!strv_isempty(e
->initrd
))
3502 initrd
= path_join(NULL
, where
, *e
->initrd
);
3503 options
= strv_join(e
->options
, " ");
3507 log_full(arg_quiet
? LOG_DEBUG
: LOG_INFO
,
3508 "%s "KEXEC
" --load \"%s\" --append \"%s\"%s%s%s",
3509 arg_dry_run
? "Would run" : "Running",
3512 initrd
? " --initrd \"" : NULL
, strempty(initrd
), initrd
? "\"" : "");
3516 r
= safe_fork("(kexec)", FORK_RESET_SIGNALS
|FORK_DEATHSIG
|FORK_LOG
, &pid
);
3520 const char* const args
[] = {
3523 "--append", options
,
3524 initrd
? "--initrd" : NULL
, initrd
,
3528 execv(args
[0], (char * const *) args
);
3529 _exit(EXIT_FAILURE
);
3532 r
= wait_for_terminate_and_check("kexec", pid
, WAIT_LOG
);
3536 /* Command failed */
3541 static int set_exit_code(uint8_t code
) {
3542 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3546 r
= acquire_bus(BUS_MANAGER
, &bus
);
3550 r
= sd_bus_call_method(
3552 "org.freedesktop.systemd1",
3553 "/org/freedesktop/systemd1",
3554 "org.freedesktop.systemd1.Manager",
3560 return log_error_errno(r
, "Failed to set exit code: %s", bus_error_message(&error
, r
));
3565 static int start_special(int argc
, char *argv
[], void *userdata
) {
3568 bool termination_action
; /* an action that terminates the manager,
3569 * can be performed also by signal. */
3573 a
= verb_to_action(argv
[0]);
3575 r
= logind_check_inhibitors(a
);
3579 if (arg_force
>= 2) {
3585 r
= prepare_firmware_setup();
3589 if (a
== ACTION_REBOOT
&& argc
> 1) {
3590 r
= update_reboot_parameter_and_warn(argv
[1]);
3594 } else if (a
== ACTION_KEXEC
) {
3595 r
= load_kexec_kernel();
3596 if (r
< 0 && arg_force
>= 1)
3597 log_notice("Failed to load kexec kernel, continuing without.");
3601 } else if (a
== ACTION_EXIT
&& argc
> 1) {
3604 /* If the exit code is not given on the command line,
3605 * don't reset it to zero: just keep it as it might
3606 * have been set previously. */
3608 r
= safe_atou8(argv
[1], &code
);
3610 return log_error_errno(r
, "Invalid exit code.");
3612 r
= set_exit_code(code
);
3617 termination_action
= IN_SET(a
,
3621 if (termination_action
&& arg_force
>= 2)
3624 if (arg_force
>= 1 &&
3625 (termination_action
|| IN_SET(a
, ACTION_KEXEC
, ACTION_EXIT
)))
3626 r
= trivial_method(argc
, argv
, userdata
);
3628 /* First try logind, to allow authentication with polkit */
3635 ACTION_HYBRID_SLEEP
,
3636 ACTION_SUSPEND_THEN_HIBERNATE
)) {
3638 r
= logind_reboot(a
);
3641 if (IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
3642 /* requested operation is not supported or already in progress */
3645 /* On all other errors, try low-level operation. In order to minimize the difference between
3646 * operation with and without logind, we explicitly enable non-blocking mode for this, as
3647 * logind's shutdown operations are always non-blocking. */
3649 arg_no_block
= true;
3651 } else if (IN_SET(a
, ACTION_EXIT
, ACTION_KEXEC
))
3652 /* Since exit/kexec are so close in behaviour to power-off/reboot, let's also make them
3653 * asynchronous, in order to not confuse the user needlessly with unexpected behaviour. */
3654 arg_no_block
= true;
3656 r
= start_unit(argc
, argv
, userdata
);
3659 if (termination_action
&& arg_force
< 2 &&
3660 IN_SET(r
, -ENOENT
, -ETIMEDOUT
))
3661 log_notice("It is possible to perform action directly, see discussion of --force --force in man:systemctl(1).");
3666 static int start_system_special(int argc
, char *argv
[], void *userdata
) {
3667 /* Like start_special above, but raises an error when running in user mode */
3669 if (arg_scope
!= UNIT_FILE_SYSTEM
) {
3670 log_error("Bad action for %s mode.",
3671 arg_scope
== UNIT_FILE_GLOBAL
? "--global" : "--user");
3675 return start_special(argc
, argv
, userdata
);
3678 static int check_unit_generic(int code
, const UnitActiveState good_states
[], int nb_states
, char **args
) {
3679 _cleanup_strv_free_
char **names
= NULL
;
3680 UnitActiveState active_state
;
3686 r
= acquire_bus(BUS_MANAGER
, &bus
);
3690 r
= expand_names(bus
, args
, NULL
, &names
);
3692 return log_error_errno(r
, "Failed to expand names: %m");
3694 STRV_FOREACH(name
, names
) {
3695 r
= get_state_one_unit(bus
, *name
, &active_state
);
3700 puts(unit_active_state_to_string(active_state
));
3702 for (i
= 0; i
< nb_states
; ++i
)
3703 if (good_states
[i
] == active_state
)
3707 /* use the given return code for the case that we won't find
3708 * any unit which matches the list */
3709 return found
? 0 : code
;
3712 static int check_unit_active(int argc
, char *argv
[], void *userdata
) {
3713 const UnitActiveState states
[] = { UNIT_ACTIVE
, UNIT_RELOADING
};
3714 /* According to LSB: 3, "program is not running" */
3715 return check_unit_generic(EXIT_PROGRAM_NOT_RUNNING
, states
, ELEMENTSOF(states
), strv_skip(argv
, 1));
3718 static int check_unit_failed(int argc
, char *argv
[], void *userdata
) {
3719 const UnitActiveState states
[] = { UNIT_FAILED
};
3720 return check_unit_generic(EXIT_PROGRAM_DEAD_AND_PID_EXISTS
, states
, ELEMENTSOF(states
), strv_skip(argv
, 1));
3723 static int kill_unit(int argc
, char *argv
[], void *userdata
) {
3724 _cleanup_strv_free_
char **names
= NULL
;
3725 char *kill_who
= NULL
, **name
;
3729 r
= acquire_bus(BUS_MANAGER
, &bus
);
3733 polkit_agent_open_maybe();
3736 arg_kill_who
= "all";
3738 /* --fail was specified */
3739 if (streq(arg_job_mode
, "fail"))
3740 kill_who
= strjoina(arg_kill_who
, "-fail");
3742 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
3744 return log_error_errno(r
, "Failed to expand names: %m");
3746 STRV_FOREACH(name
, names
) {
3747 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3749 q
= sd_bus_call_method(
3751 "org.freedesktop.systemd1",
3752 "/org/freedesktop/systemd1",
3753 "org.freedesktop.systemd1.Manager",
3757 "ssi", *name
, kill_who
? kill_who
: arg_kill_who
, arg_signal
);
3759 log_error_errno(q
, "Failed to kill unit %s: %s", *name
, bus_error_message(&error
, q
));
3768 typedef struct ExecStatusInfo
{
3776 usec_t start_timestamp
;
3777 usec_t exit_timestamp
;
3782 LIST_FIELDS(struct ExecStatusInfo
, exec
);
3785 static void exec_status_info_free(ExecStatusInfo
*i
) {
3794 static int exec_status_info_deserialize(sd_bus_message
*m
, ExecStatusInfo
*i
) {
3795 uint64_t start_timestamp
, exit_timestamp
, start_timestamp_monotonic
, exit_timestamp_monotonic
;
3798 int32_t code
, status
;
3804 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_STRUCT
, "sasbttttuii");
3806 return bus_log_parse_error(r
);
3810 r
= sd_bus_message_read(m
, "s", &path
);
3812 return bus_log_parse_error(r
);
3814 i
->path
= strdup(path
);
3818 r
= sd_bus_message_read_strv(m
, &i
->argv
);
3820 return bus_log_parse_error(r
);
3822 r
= sd_bus_message_read(m
,
3825 &start_timestamp
, &start_timestamp_monotonic
,
3826 &exit_timestamp
, &exit_timestamp_monotonic
,
3830 return bus_log_parse_error(r
);
3833 i
->start_timestamp
= (usec_t
) start_timestamp
;
3834 i
->exit_timestamp
= (usec_t
) exit_timestamp
;
3835 i
->pid
= (pid_t
) pid
;
3839 r
= sd_bus_message_exit_container(m
);
3841 return bus_log_parse_error(r
);
3846 typedef struct UnitCondition
{
3853 LIST_FIELDS(struct UnitCondition
, conditions
);
3856 static void unit_condition_free(UnitCondition
*c
) {
3865 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitCondition
*, unit_condition_free
);
3867 typedef struct UnitStatusInfo
{
3869 const char *load_state
;
3870 const char *active_state
;
3871 const char *sub_state
;
3872 const char *unit_file_state
;
3873 const char *unit_file_preset
;
3875 const char *description
;
3876 const char *following
;
3878 char **documentation
;
3880 const char *fragment_path
;
3881 const char *source_path
;
3882 const char *control_group
;
3884 char **dropin_paths
;
3886 const char *load_error
;
3889 usec_t inactive_exit_timestamp
;
3890 usec_t inactive_exit_timestamp_monotonic
;
3891 usec_t active_enter_timestamp
;
3892 usec_t active_exit_timestamp
;
3893 usec_t inactive_enter_timestamp
;
3895 bool need_daemon_reload
;
3901 const char *status_text
;
3902 const char *pid_file
;
3906 usec_t start_timestamp
;
3907 usec_t exit_timestamp
;
3909 int exit_code
, exit_status
;
3911 usec_t condition_timestamp
;
3912 bool condition_result
;
3913 LIST_HEAD(UnitCondition
, conditions
);
3915 usec_t assert_timestamp
;
3917 bool failed_assert_trigger
;
3918 bool failed_assert_negate
;
3919 const char *failed_assert
;
3920 const char *failed_assert_parameter
;
3921 usec_t next_elapse_real
;
3922 usec_t next_elapse_monotonic
;
3925 unsigned n_accepted
;
3926 unsigned n_connections
;
3929 /* Pairs of type, path */
3933 const char *sysfs_path
;
3935 /* Mount, Automount */
3942 uint64_t memory_current
;
3943 uint64_t memory_low
;
3944 uint64_t memory_high
;
3945 uint64_t memory_max
;
3946 uint64_t memory_swap_max
;
3947 uint64_t memory_limit
;
3948 uint64_t cpu_usage_nsec
;
3949 uint64_t tasks_current
;
3952 uint64_t ip_ingress_bytes
;
3953 uint64_t ip_egress_bytes
;
3955 LIST_HEAD(ExecStatusInfo
, exec
);
3958 static void unit_status_info_free(UnitStatusInfo
*info
) {
3962 strv_free(info
->documentation
);
3963 strv_free(info
->dropin_paths
);
3964 strv_free(info
->listen
);
3966 while ((c
= info
->conditions
)) {
3967 LIST_REMOVE(conditions
, info
->conditions
, c
);
3968 unit_condition_free(c
);
3971 while ((p
= info
->exec
)) {
3972 LIST_REMOVE(exec
, info
->exec
, p
);
3973 exec_status_info_free(p
);
3977 static void print_status_info(
3983 const char *active_on
, *active_off
, *on
, *off
, *ss
;
3985 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], *s1
;
3986 char since2
[FORMAT_TIMESTAMP_MAX
], *s2
;
3993 /* This shows pretty information about a unit. See
3994 * print_property() for a low-level property printer */
3996 if (streq_ptr(i
->active_state
, "failed")) {
3997 active_on
= ansi_highlight_red();
3998 active_off
= ansi_normal();
3999 } else if (STRPTR_IN_SET(i
->active_state
, "active", "reloading")) {
4000 active_on
= ansi_highlight_green();
4001 active_off
= ansi_normal();
4003 active_on
= active_off
= "";
4005 printf("%s%s%s %s", active_on
, special_glyph(BLACK_CIRCLE
), active_off
, strna(i
->id
));
4007 if (i
->description
&& !streq_ptr(i
->id
, i
->description
))
4008 printf(" - %s", i
->description
);
4013 printf(" Follow: unit currently follows state of %s\n", i
->following
);
4015 if (streq_ptr(i
->load_state
, "error")) {
4016 on
= ansi_highlight_red();
4017 off
= ansi_normal();
4021 path
= i
->source_path
? i
->source_path
: i
->fragment_path
;
4023 if (i
->load_error
!= 0)
4024 printf(" Loaded: %s%s%s (Reason: %s)\n",
4025 on
, strna(i
->load_state
), off
, i
->load_error
);
4026 else if (path
&& !isempty(i
->unit_file_state
) && !isempty(i
->unit_file_preset
) &&
4027 !STR_IN_SET(i
->unit_file_state
, "generated", "transient"))
4028 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
4029 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
, i
->unit_file_preset
);
4030 else if (path
&& !isempty(i
->unit_file_state
))
4031 printf(" Loaded: %s%s%s (%s; %s)\n",
4032 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
);
4034 printf(" Loaded: %s%s%s (%s)\n",
4035 on
, strna(i
->load_state
), off
, path
);
4037 printf(" Loaded: %s%s%s\n",
4038 on
, strna(i
->load_state
), off
);
4041 printf("Transient: yes\n");
4043 if (!strv_isempty(i
->dropin_paths
)) {
4044 _cleanup_free_
char *dir
= NULL
;
4048 STRV_FOREACH(dropin
, i
->dropin_paths
) {
4049 if (! dir
|| last
) {
4050 printf(dir
? " " : " Drop-In: ");
4054 dir
= dirname_malloc(*dropin
);
4060 printf("%s\n %s", dir
,
4061 special_glyph(TREE_RIGHT
));
4064 last
= ! (*(dropin
+ 1) && startswith(*(dropin
+ 1), dir
));
4066 printf("%s%s", basename(*dropin
), last
? "\n" : ", ");
4070 ss
= streq_ptr(i
->active_state
, i
->sub_state
) ? NULL
: i
->sub_state
;
4072 printf(" Active: %s%s (%s)%s",
4073 active_on
, strna(i
->active_state
), ss
, active_off
);
4075 printf(" Active: %s%s%s",
4076 active_on
, strna(i
->active_state
), active_off
);
4078 if (!isempty(i
->result
) && !streq(i
->result
, "success"))
4079 printf(" (Result: %s)", i
->result
);
4081 timestamp
= STRPTR_IN_SET(i
->active_state
, "active", "reloading") ? i
->active_enter_timestamp
:
4082 STRPTR_IN_SET(i
->active_state
, "inactive", "failed") ? i
->inactive_enter_timestamp
:
4083 STRPTR_IN_SET(i
->active_state
, "activating") ? i
->inactive_exit_timestamp
:
4084 i
->active_exit_timestamp
;
4086 s1
= format_timestamp_relative(since1
, sizeof(since1
), timestamp
);
4087 s2
= format_timestamp(since2
, sizeof(since2
), timestamp
);
4090 printf(" since %s; %s\n", s2
, s1
);
4092 printf(" since %s\n", s2
);
4096 if (endswith(i
->id
, ".timer")) {
4097 char tstamp1
[FORMAT_TIMESTAMP_RELATIVE_MAX
],
4098 tstamp2
[FORMAT_TIMESTAMP_MAX
];
4099 char *next_rel_time
, *next_time
;
4100 dual_timestamp nw
, next
= {i
->next_elapse_real
,
4101 i
->next_elapse_monotonic
};
4104 printf(" Trigger: ");
4106 dual_timestamp_get(&nw
);
4107 next_elapse
= calc_next_elapse(&nw
, &next
);
4108 next_rel_time
= format_timestamp_relative(tstamp1
,
4111 next_time
= format_timestamp(tstamp2
,
4115 if (next_time
&& next_rel_time
)
4116 printf("%s; %s\n", next_time
, next_rel_time
);
4121 if (!i
->condition_result
&& i
->condition_timestamp
> 0) {
4125 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->condition_timestamp
);
4126 s2
= format_timestamp(since2
, sizeof(since2
), i
->condition_timestamp
);
4128 printf("Condition: start %scondition failed%s at %s%s%s\n",
4129 ansi_highlight_yellow(), ansi_normal(),
4130 s2
, s1
? "; " : "", strempty(s1
));
4132 LIST_FOREACH(conditions
, c
, i
->conditions
)
4133 if (c
->tristate
< 0)
4136 LIST_FOREACH(conditions
, c
, i
->conditions
)
4137 if (c
->tristate
< 0)
4138 printf(" %s %s=%s%s%s was not met\n",
4139 --n
? special_glyph(TREE_BRANCH
) : special_glyph(TREE_RIGHT
),
4141 c
->trigger
? "|" : "",
4142 c
->negate
? "!" : "",
4146 if (!i
->assert_result
&& i
->assert_timestamp
> 0) {
4147 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->assert_timestamp
);
4148 s2
= format_timestamp(since2
, sizeof(since2
), i
->assert_timestamp
);
4150 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
4151 ansi_highlight_red(), ansi_normal(),
4152 s2
, s1
? "; " : "", strempty(s1
));
4153 if (i
->failed_assert_trigger
)
4154 printf(" none of the trigger assertions were met\n");
4155 else if (i
->failed_assert
)
4156 printf(" %s=%s%s was not met\n",
4158 i
->failed_assert_negate
? "!" : "",
4159 i
->failed_assert_parameter
);
4163 printf(" Device: %s\n", i
->sysfs_path
);
4165 printf(" Where: %s\n", i
->where
);
4167 printf(" What: %s\n", i
->what
);
4169 STRV_FOREACH(t
, i
->documentation
)
4170 printf(" %*s %s\n", 9, t
== i
->documentation
? "Docs:" : "", *t
);
4172 STRV_FOREACH_PAIR(t
, t2
, i
->listen
)
4173 printf(" %*s %s (%s)\n", 9, t
== i
->listen
? "Listen:" : "", *t2
, *t
);
4176 printf(" Accepted: %u; Connected: %u\n", i
->n_accepted
, i
->n_connections
);
4178 LIST_FOREACH(exec
, p
, i
->exec
) {
4179 _cleanup_free_
char *argv
= NULL
;
4182 /* Only show exited processes here */
4186 argv
= strv_join(p
->argv
, " ");
4187 printf(" Process: "PID_FMT
" %s=%s ", p
->pid
, p
->name
, strna(argv
));
4189 good
= is_clean_exit(p
->code
, p
->status
, EXIT_CLEAN_DAEMON
, NULL
);
4191 on
= ansi_highlight_red();
4192 off
= ansi_normal();
4196 printf("%s(code=%s, ", on
, sigchld_code_to_string(p
->code
));
4198 if (p
->code
== CLD_EXITED
) {
4201 printf("status=%i", p
->status
);
4203 c
= exit_status_to_string(p
->status
, EXIT_STATUS_SYSTEMD
);
4208 printf("signal=%s", signal_to_string(p
->status
));
4210 printf(")%s\n", off
);
4212 if (i
->main_pid
== p
->pid
&&
4213 i
->start_timestamp
== p
->start_timestamp
&&
4214 i
->exit_timestamp
== p
->start_timestamp
)
4215 /* Let's not show this twice */
4218 if (p
->pid
== i
->control_pid
)
4222 if (i
->main_pid
> 0 || i
->control_pid
> 0) {
4223 if (i
->main_pid
> 0) {
4224 printf(" Main PID: "PID_FMT
, i
->main_pid
);
4228 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
4229 _cleanup_free_
char *comm
= NULL
;
4231 (void) get_process_comm(i
->main_pid
, &comm
);
4233 printf(" (%s)", comm
);
4236 } else if (i
->exit_code
> 0) {
4237 printf(" (code=%s, ", sigchld_code_to_string(i
->exit_code
));
4239 if (i
->exit_code
== CLD_EXITED
) {
4242 printf("status=%i", i
->exit_status
);
4244 c
= exit_status_to_string(i
->exit_status
, EXIT_STATUS_SYSTEMD
);
4249 printf("signal=%s", signal_to_string(i
->exit_status
));
4254 if (i
->control_pid
> 0) {
4255 _cleanup_free_
char *c
= NULL
;
4257 if (i
->main_pid
> 0)
4258 fputs("; Control PID: ", stdout
);
4260 fputs("Cntrl PID: ", stdout
); /* if first in column, abbreviated so it fits alignment */
4262 printf(PID_FMT
, i
->control_pid
);
4264 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
4265 (void) get_process_comm(i
->control_pid
, &c
);
4275 printf(" Status: \"%s\"\n", i
->status_text
);
4276 if (i
->status_errno
> 0)
4277 printf(" Error: %i (%s)\n", i
->status_errno
, strerror(i
->status_errno
));
4279 if (i
->ip_ingress_bytes
!= (uint64_t) -1 && i
->ip_egress_bytes
!= (uint64_t) -1) {
4280 char buf_in
[FORMAT_BYTES_MAX
], buf_out
[FORMAT_BYTES_MAX
];
4282 printf(" IP: %s in, %s out\n",
4283 format_bytes(buf_in
, sizeof(buf_in
), i
->ip_ingress_bytes
),
4284 format_bytes(buf_out
, sizeof(buf_out
), i
->ip_egress_bytes
));
4287 if (i
->tasks_current
!= (uint64_t) -1) {
4288 printf(" Tasks: %" PRIu64
, i
->tasks_current
);
4290 if (i
->tasks_max
!= (uint64_t) -1)
4291 printf(" (limit: %" PRIu64
")\n", i
->tasks_max
);
4296 if (i
->memory_current
!= (uint64_t) -1) {
4297 char buf
[FORMAT_BYTES_MAX
];
4299 printf(" Memory: %s", format_bytes(buf
, sizeof(buf
), i
->memory_current
));
4301 if (i
->memory_low
> 0 || i
->memory_high
!= CGROUP_LIMIT_MAX
||
4302 i
->memory_max
!= CGROUP_LIMIT_MAX
|| i
->memory_swap_max
!= CGROUP_LIMIT_MAX
||
4303 i
->memory_limit
!= CGROUP_LIMIT_MAX
) {
4304 const char *prefix
= "";
4307 if (i
->memory_low
> 0) {
4308 printf("%slow: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_low
));
4311 if (i
->memory_high
!= CGROUP_LIMIT_MAX
) {
4312 printf("%shigh: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_high
));
4315 if (i
->memory_max
!= CGROUP_LIMIT_MAX
) {
4316 printf("%smax: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_max
));
4319 if (i
->memory_swap_max
!= CGROUP_LIMIT_MAX
) {
4320 printf("%sswap max: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_swap_max
));
4323 if (i
->memory_limit
!= CGROUP_LIMIT_MAX
) {
4324 printf("%slimit: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_limit
));
4332 if (i
->cpu_usage_nsec
!= (uint64_t) -1) {
4333 char buf
[FORMAT_TIMESPAN_MAX
];
4334 printf(" CPU: %s\n", format_timespan(buf
, sizeof(buf
), i
->cpu_usage_nsec
/ NSEC_PER_USEC
, USEC_PER_MSEC
));
4337 if (i
->control_group
) {
4338 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
4339 static const char prefix
[] = " ";
4342 printf(" CGroup: %s\n", i
->control_group
);
4345 if (c
> sizeof(prefix
) - 1)
4346 c
-= sizeof(prefix
) - 1;
4350 r
= unit_show_processes(bus
, i
->id
, i
->control_group
, prefix
, c
, get_output_flags(), &error
);
4355 /* Fallback for older systemd versions where the GetUnitProcesses() call is not yet available */
4357 if (i
->main_pid
> 0)
4358 extra
[k
++] = i
->main_pid
;
4360 if (i
->control_pid
> 0)
4361 extra
[k
++] = i
->control_pid
;
4363 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, prefix
, c
, extra
, k
, get_output_flags());
4365 log_warning_errno(r
, "Failed to dump process list, ignoring: %s", bus_error_message(&error
, r
));
4368 if (i
->id
&& arg_transport
== BUS_TRANSPORT_LOCAL
)
4369 show_journal_by_unit(
4374 i
->inactive_exit_timestamp_monotonic
,
4377 get_output_flags() | OUTPUT_BEGIN_NEWLINE
,
4378 SD_JOURNAL_LOCAL_ONLY
,
4379 arg_scope
== UNIT_FILE_SYSTEM
,
4382 if (i
->need_daemon_reload
)
4383 warn_unit_file_changed(i
->id
);
4386 static void show_unit_help(UnitStatusInfo
*i
) {
4391 if (!i
->documentation
) {
4392 log_info("Documentation for %s not known.", i
->id
);
4396 STRV_FOREACH(p
, i
->documentation
)
4397 if (startswith(*p
, "man:"))
4398 show_man_page(*p
+ 4, false);
4400 log_info("Can't show: %s", *p
);
4403 static int map_main_pid(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
4404 UnitStatusInfo
*i
= userdata
;
4408 r
= sd_bus_message_read(m
, "u", &u
);
4412 i
->main_pid
= (pid_t
) u
;
4418 static int map_load_error(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
4419 const char *n
, *message
;
4420 const char **p
= userdata
;
4423 r
= sd_bus_message_read(m
, "(ss)", &n
, &message
);
4427 if (!isempty(message
))
4433 static int map_listen(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
4434 const char *type
, *path
;
4435 char ***p
= userdata
;
4438 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4442 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0) {
4444 r
= strv_extend(p
, type
);
4448 r
= strv_extend(p
, path
);
4455 r
= sd_bus_message_exit_container(m
);
4462 static int map_conditions(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
4463 UnitStatusInfo
*i
= userdata
;
4464 const char *cond
, *param
;
4465 int trigger
, negate
;
4469 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
4473 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
4474 _cleanup_(unit_condition_freep
) UnitCondition
*c
= NULL
;
4476 c
= new0(UnitCondition
, 1);
4480 c
->name
= strdup(cond
);
4481 c
->param
= strdup(param
);
4482 if (!c
->name
|| !c
->param
)
4485 c
->trigger
= trigger
;
4487 c
->tristate
= state
;
4489 LIST_PREPEND(conditions
, i
->conditions
, c
);
4495 r
= sd_bus_message_exit_container(m
);
4502 static int map_asserts(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
4503 UnitStatusInfo
*i
= userdata
;
4504 const char *cond
, *param
;
4505 int trigger
, negate
;
4509 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
4513 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
4514 if (state
< 0 && (!trigger
|| !i
->failed_assert
)) {
4515 i
->failed_assert
= cond
;
4516 i
->failed_assert_trigger
= trigger
;
4517 i
->failed_assert_negate
= negate
;
4518 i
->failed_assert_parameter
= param
;
4524 r
= sd_bus_message_exit_container(m
);
4531 static int map_exec(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
4532 _cleanup_free_ ExecStatusInfo
*info
= NULL
;
4533 UnitStatusInfo
*i
= userdata
;
4536 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4540 info
= new0(ExecStatusInfo
, 1);
4544 while ((r
= exec_status_info_deserialize(m
, info
)) > 0) {
4546 info
->name
= strdup(member
);
4550 LIST_PREPEND(exec
, i
->exec
, info
);
4552 info
= new0(ExecStatusInfo
, 1);
4559 r
= sd_bus_message_exit_container(m
);
4566 #define print_prop(name, fmt, ...) \
4569 printf(fmt "\n", __VA_ARGS__); \
4571 printf("%s=" fmt "\n", name, __VA_ARGS__); \
4574 static int print_property(const char *name
, sd_bus_message
*m
, bool value
, bool all
) {
4576 const char *contents
;
4582 /* This is a low-level property printer, see
4583 * print_status_info() for the nicer output */
4585 r
= sd_bus_message_peek_type(m
, &bus_type
, &contents
);
4591 case SD_BUS_TYPE_STRUCT
:
4593 if (contents
[0] == SD_BUS_TYPE_UINT32
&& streq(name
, "Job")) {
4596 r
= sd_bus_message_read(m
, "(uo)", &u
, NULL
);
4598 return bus_log_parse_error(r
);
4601 print_prop(name
, "%"PRIu32
, u
);
4603 print_prop(name
, "%s", "");
4607 } else if (contents
[0] == SD_BUS_TYPE_STRING
&& streq(name
, "Unit")) {
4610 r
= sd_bus_message_read(m
, "(so)", &s
, NULL
);
4612 return bus_log_parse_error(r
);
4614 if (all
|| !isempty(s
))
4615 print_prop(name
, "%s", s
);
4619 } else if (contents
[0] == SD_BUS_TYPE_STRING
&& streq(name
, "LoadError")) {
4620 const char *a
= NULL
, *b
= NULL
;
4622 r
= sd_bus_message_read(m
, "(ss)", &a
, &b
);
4624 return bus_log_parse_error(r
);
4626 if (all
|| !isempty(a
) || !isempty(b
))
4627 print_prop(name
, "%s \"%s\"", strempty(a
), strempty(b
));
4630 } else if (streq_ptr(name
, "SystemCallFilter")) {
4631 _cleanup_strv_free_
char **l
= NULL
;
4634 r
= sd_bus_message_enter_container(m
, 'r', "bas");
4636 return bus_log_parse_error(r
);
4638 r
= sd_bus_message_read(m
, "b", &whitelist
);
4640 return bus_log_parse_error(r
);
4642 r
= sd_bus_message_read_strv(m
, &l
);
4644 return bus_log_parse_error(r
);
4646 r
= sd_bus_message_exit_container(m
);
4648 return bus_log_parse_error(r
);
4650 if (all
|| whitelist
|| !strv_isempty(l
)) {
4655 fputs(name
, stdout
);
4662 STRV_FOREACH(i
, l
) {
4670 fputc('\n', stdout
);
4678 case SD_BUS_TYPE_ARRAY
:
4680 if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "EnvironmentFiles")) {
4684 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sb)");
4686 return bus_log_parse_error(r
);
4688 while ((r
= sd_bus_message_read(m
, "(sb)", &path
, &ignore
)) > 0)
4689 print_prop(name
, "%s (ignore_errors=%s)", path
, yes_no(ignore
));
4692 return bus_log_parse_error(r
);
4694 r
= sd_bus_message_exit_container(m
);
4696 return bus_log_parse_error(r
);
4700 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Paths")) {
4701 const char *type
, *path
;
4703 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4705 return bus_log_parse_error(r
);
4707 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4708 print_prop(name
, "%s (%s)", path
, type
);
4710 return bus_log_parse_error(r
);
4712 r
= sd_bus_message_exit_container(m
);
4714 return bus_log_parse_error(r
);
4718 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
4719 const char *type
, *path
;
4721 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4723 return bus_log_parse_error(r
);
4725 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4726 print_prop(name
, "%s (%s)", path
, type
);
4728 return bus_log_parse_error(r
);
4730 r
= sd_bus_message_exit_container(m
);
4732 return bus_log_parse_error(r
);
4736 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "TimersMonotonic")) {
4738 uint64_t v
, next_elapse
;
4740 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(stt)");
4742 return bus_log_parse_error(r
);
4744 while ((r
= sd_bus_message_read(m
, "(stt)", &base
, &v
, &next_elapse
)) > 0) {
4745 char timespan1
[FORMAT_TIMESPAN_MAX
], timespan2
[FORMAT_TIMESPAN_MAX
];
4747 print_prop(name
, "{ %s=%s ; next_elapse=%s }", base
,
4748 format_timespan(timespan1
, sizeof(timespan1
), v
, 0),
4749 format_timespan(timespan2
, sizeof(timespan2
), next_elapse
, 0));
4752 return bus_log_parse_error(r
);
4754 r
= sd_bus_message_exit_container(m
);
4756 return bus_log_parse_error(r
);
4760 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "TimersCalendar")) {
4761 const char *base
, *spec
;
4762 uint64_t next_elapse
;
4764 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sst)");
4766 return bus_log_parse_error(r
);
4768 while ((r
= sd_bus_message_read(m
, "(sst)", &base
, &spec
, &next_elapse
)) > 0) {
4769 char timestamp
[FORMAT_TIMESTAMP_MAX
];
4771 print_prop(name
, "{ %s=%s ; next_elapse=%s }", base
, spec
,
4772 format_timestamp(timestamp
, sizeof(timestamp
), next_elapse
));
4775 return bus_log_parse_error(r
);
4777 r
= sd_bus_message_exit_container(m
);
4779 return bus_log_parse_error(r
);
4783 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
4784 ExecStatusInfo info
= {};
4786 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4788 return bus_log_parse_error(r
);
4790 while ((r
= exec_status_info_deserialize(m
, &info
)) > 0) {
4791 char timestamp1
[FORMAT_TIMESTAMP_MAX
], timestamp2
[FORMAT_TIMESTAMP_MAX
];
4792 _cleanup_free_
char *tt
;
4794 tt
= strv_join(info
.argv
, " ");
4797 "{ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT
" ; code=%s ; status=%i%s%s }",
4800 yes_no(info
.ignore
),
4801 strna(format_timestamp(timestamp1
, sizeof(timestamp1
), info
.start_timestamp
)),
4802 strna(format_timestamp(timestamp2
, sizeof(timestamp2
), info
.exit_timestamp
)),
4804 sigchld_code_to_string(info
.code
),
4806 info
.code
== CLD_EXITED
? "" : "/",
4807 strempty(info
.code
== CLD_EXITED
? NULL
: signal_to_string(info
.status
)));
4810 strv_free(info
.argv
);
4814 r
= sd_bus_message_exit_container(m
);
4816 return bus_log_parse_error(r
);
4820 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "DeviceAllow")) {
4821 const char *path
, *rwm
;
4823 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4825 return bus_log_parse_error(r
);
4827 while ((r
= sd_bus_message_read(m
, "(ss)", &path
, &rwm
)) > 0)
4828 print_prop(name
, "%s %s", strna(path
), strna(rwm
));
4830 return bus_log_parse_error(r
);
4832 r
= sd_bus_message_exit_container(m
);
4834 return bus_log_parse_error(r
);
4838 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&&
4839 STR_IN_SET(name
, "IODeviceWeight", "BlockIODeviceWeight")) {
4843 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4845 return bus_log_parse_error(r
);
4847 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &weight
)) > 0)
4848 print_prop(name
, "%s %"PRIu64
, strna(path
), weight
);
4850 return bus_log_parse_error(r
);
4852 r
= sd_bus_message_exit_container(m
);
4854 return bus_log_parse_error(r
);
4858 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&&
4859 (cgroup_io_limit_type_from_string(name
) >= 0 ||
4860 STR_IN_SET(name
, "BlockIOReadBandwidth", "BlockIOWriteBandwidth"))) {
4864 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4866 return bus_log_parse_error(r
);
4868 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &bandwidth
)) > 0)
4869 print_prop(name
, "%s %"PRIu64
, strna(path
), bandwidth
);
4871 return bus_log_parse_error(r
);
4873 r
= sd_bus_message_exit_container(m
);
4875 return bus_log_parse_error(r
);
4879 } else if (contents
[0] == SD_BUS_TYPE_BYTE
&& streq(name
, "StandardInputData")) {
4880 _cleanup_free_
char *h
= NULL
;
4885 r
= sd_bus_message_read_array(m
, 'y', &p
, &sz
);
4887 return bus_log_parse_error(r
);
4889 n
= base64mem(p
, sz
, &h
);
4893 print_prop(name
, "%s", h
);
4904 typedef enum SystemctlShowMode
{
4905 SYSTEMCTL_SHOW_PROPERTIES
,
4906 SYSTEMCTL_SHOW_STATUS
,
4907 SYSTEMCTL_SHOW_HELP
,
4908 _SYSTEMCTL_SHOW_MODE_MAX
,
4909 _SYSTEMCTL_SHOW_MODE_INVALID
= -1,
4910 } SystemctlShowMode
;
4912 static const char* const systemctl_show_mode_table
[] = {
4913 [SYSTEMCTL_SHOW_PROPERTIES
] = "show",
4914 [SYSTEMCTL_SHOW_STATUS
] = "status",
4915 [SYSTEMCTL_SHOW_HELP
] = "help",
4918 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(systemctl_show_mode
, SystemctlShowMode
);
4920 static int show_one(
4924 SystemctlShowMode show_mode
,
4928 static const struct bus_properties_map property_map
[] = {
4929 { "LoadState", "s", NULL
, offsetof(UnitStatusInfo
, load_state
) },
4930 { "ActiveState", "s", NULL
, offsetof(UnitStatusInfo
, active_state
) },
4931 { "Documentation", "as", NULL
, offsetof(UnitStatusInfo
, documentation
) },
4934 { "Id", "s", NULL
, offsetof(UnitStatusInfo
, id
) },
4935 { "LoadState", "s", NULL
, offsetof(UnitStatusInfo
, load_state
) },
4936 { "ActiveState", "s", NULL
, offsetof(UnitStatusInfo
, active_state
) },
4937 { "SubState", "s", NULL
, offsetof(UnitStatusInfo
, sub_state
) },
4938 { "UnitFileState", "s", NULL
, offsetof(UnitStatusInfo
, unit_file_state
) },
4939 { "UnitFilePreset", "s", NULL
, offsetof(UnitStatusInfo
, unit_file_preset
) },
4940 { "Description", "s", NULL
, offsetof(UnitStatusInfo
, description
) },
4941 { "Following", "s", NULL
, offsetof(UnitStatusInfo
, following
) },
4942 { "Documentation", "as", NULL
, offsetof(UnitStatusInfo
, documentation
) },
4943 { "FragmentPath", "s", NULL
, offsetof(UnitStatusInfo
, fragment_path
) },
4944 { "SourcePath", "s", NULL
, offsetof(UnitStatusInfo
, source_path
) },
4945 { "ControlGroup", "s", NULL
, offsetof(UnitStatusInfo
, control_group
) },
4946 { "DropInPaths", "as", NULL
, offsetof(UnitStatusInfo
, dropin_paths
) },
4947 { "LoadError", "(ss)", map_load_error
, offsetof(UnitStatusInfo
, load_error
) },
4948 { "Result", "s", NULL
, offsetof(UnitStatusInfo
, result
) },
4949 { "InactiveExitTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, inactive_exit_timestamp
) },
4950 { "InactiveExitTimestampMonotonic", "t", NULL
, offsetof(UnitStatusInfo
, inactive_exit_timestamp_monotonic
) },
4951 { "ActiveEnterTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, active_enter_timestamp
) },
4952 { "ActiveExitTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, active_exit_timestamp
) },
4953 { "InactiveEnterTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, inactive_enter_timestamp
) },
4954 { "NeedDaemonReload", "b", NULL
, offsetof(UnitStatusInfo
, need_daemon_reload
) },
4955 { "Transient", "b", NULL
, offsetof(UnitStatusInfo
, transient
) },
4956 { "ExecMainPID", "u", NULL
, offsetof(UnitStatusInfo
, main_pid
) },
4957 { "MainPID", "u", map_main_pid
, 0 },
4958 { "ControlPID", "u", NULL
, offsetof(UnitStatusInfo
, control_pid
) },
4959 { "StatusText", "s", NULL
, offsetof(UnitStatusInfo
, status_text
) },
4960 { "PIDFile", "s", NULL
, offsetof(UnitStatusInfo
, pid_file
) },
4961 { "StatusErrno", "i", NULL
, offsetof(UnitStatusInfo
, status_errno
) },
4962 { "ExecMainStartTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, start_timestamp
) },
4963 { "ExecMainExitTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, exit_timestamp
) },
4964 { "ExecMainCode", "i", NULL
, offsetof(UnitStatusInfo
, exit_code
) },
4965 { "ExecMainStatus", "i", NULL
, offsetof(UnitStatusInfo
, exit_status
) },
4966 { "ConditionTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, condition_timestamp
) },
4967 { "ConditionResult", "b", NULL
, offsetof(UnitStatusInfo
, condition_result
) },
4968 { "Conditions", "a(sbbsi)", map_conditions
, 0 },
4969 { "AssertTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, assert_timestamp
) },
4970 { "AssertResult", "b", NULL
, offsetof(UnitStatusInfo
, assert_result
) },
4971 { "Asserts", "a(sbbsi)", map_asserts
, 0 },
4972 { "NextElapseUSecRealtime", "t", NULL
, offsetof(UnitStatusInfo
, next_elapse_real
) },
4973 { "NextElapseUSecMonotonic", "t", NULL
, offsetof(UnitStatusInfo
, next_elapse_monotonic
) },
4974 { "NAccepted", "u", NULL
, offsetof(UnitStatusInfo
, n_accepted
) },
4975 { "NConnections", "u", NULL
, offsetof(UnitStatusInfo
, n_connections
) },
4976 { "Accept", "b", NULL
, offsetof(UnitStatusInfo
, accept
) },
4977 { "Listen", "a(ss)", map_listen
, offsetof(UnitStatusInfo
, listen
) },
4978 { "SysFSPath", "s", NULL
, offsetof(UnitStatusInfo
, sysfs_path
) },
4979 { "Where", "s", NULL
, offsetof(UnitStatusInfo
, where
) },
4980 { "What", "s", NULL
, offsetof(UnitStatusInfo
, what
) },
4981 { "MemoryCurrent", "t", NULL
, offsetof(UnitStatusInfo
, memory_current
) },
4982 { "MemoryLow", "t", NULL
, offsetof(UnitStatusInfo
, memory_low
) },
4983 { "MemoryHigh", "t", NULL
, offsetof(UnitStatusInfo
, memory_high
) },
4984 { "MemoryMax", "t", NULL
, offsetof(UnitStatusInfo
, memory_max
) },
4985 { "MemorySwapMax", "t", NULL
, offsetof(UnitStatusInfo
, memory_swap_max
) },
4986 { "MemoryLimit", "t", NULL
, offsetof(UnitStatusInfo
, memory_limit
) },
4987 { "CPUUsageNSec", "t", NULL
, offsetof(UnitStatusInfo
, cpu_usage_nsec
) },
4988 { "TasksCurrent", "t", NULL
, offsetof(UnitStatusInfo
, tasks_current
) },
4989 { "TasksMax", "t", NULL
, offsetof(UnitStatusInfo
, tasks_max
) },
4990 { "IPIngressBytes", "t", NULL
, offsetof(UnitStatusInfo
, ip_ingress_bytes
) },
4991 { "IPEgressBytes", "t", NULL
, offsetof(UnitStatusInfo
, ip_egress_bytes
) },
4992 { "ExecStartPre", "a(sasbttttuii)", map_exec
, 0 },
4993 { "ExecStart", "a(sasbttttuii)", map_exec
, 0 },
4994 { "ExecStartPost", "a(sasbttttuii)", map_exec
, 0 },
4995 { "ExecReload", "a(sasbttttuii)", map_exec
, 0 },
4996 { "ExecStopPre", "a(sasbttttuii)", map_exec
, 0 },
4997 { "ExecStop", "a(sasbttttuii)", map_exec
, 0 },
4998 { "ExecStopPost", "a(sasbttttuii)", map_exec
, 0 },
5002 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5003 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5004 _cleanup_set_free_ Set
*found_properties
= NULL
;
5005 _cleanup_(unit_status_info_free
) UnitStatusInfo info
= {
5006 .memory_current
= (uint64_t) -1,
5007 .memory_high
= CGROUP_LIMIT_MAX
,
5008 .memory_max
= CGROUP_LIMIT_MAX
,
5009 .memory_swap_max
= CGROUP_LIMIT_MAX
,
5010 .memory_limit
= (uint64_t) -1,
5011 .cpu_usage_nsec
= (uint64_t) -1,
5012 .tasks_current
= (uint64_t) -1,
5013 .tasks_max
= (uint64_t) -1,
5014 .ip_ingress_bytes
= (uint64_t) -1,
5015 .ip_egress_bytes
= (uint64_t) -1,
5023 log_debug("Showing one %s", path
);
5025 r
= bus_map_all_properties(
5027 "org.freedesktop.systemd1",
5029 show_mode
== SYSTEMCTL_SHOW_STATUS
? status_map
: property_map
,
5030 BUS_MAP_BOOLEAN_AS_BOOL
,
5035 return log_error_errno(r
, "Failed to get properties: %s", bus_error_message(&error
, r
));
5037 if (unit
&& streq_ptr(info
.load_state
, "not-found") && streq_ptr(info
.active_state
, "inactive")) {
5038 log_full(show_mode
== SYSTEMCTL_SHOW_STATUS
? LOG_ERR
: LOG_DEBUG
,
5039 "Unit %s could not be found.", unit
);
5041 if (show_mode
== SYSTEMCTL_SHOW_STATUS
)
5042 return EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN
;
5043 else if (show_mode
== SYSTEMCTL_SHOW_HELP
)
5052 if (show_mode
== SYSTEMCTL_SHOW_STATUS
) {
5053 print_status_info(bus
, &info
, ellipsized
);
5055 if (info
.active_state
&& !STR_IN_SET(info
.active_state
, "active", "reloading"))
5056 return EXIT_PROGRAM_NOT_RUNNING
;
5058 return EXIT_PROGRAM_RUNNING_OR_SERVICE_OK
;
5060 } else if (show_mode
== SYSTEMCTL_SHOW_HELP
) {
5061 show_unit_help(&info
);
5065 r
= sd_bus_message_rewind(reply
, true);
5067 return log_error_errno(r
, "Failed to rewind: %s", bus_error_message(&error
, r
));
5069 r
= bus_message_print_all_properties(reply
, print_property
, arg_properties
, arg_value
, arg_all
, &found_properties
);
5071 return bus_log_parse_error(r
);
5073 STRV_FOREACH(pp
, arg_properties
)
5074 if (!set_contains(found_properties
, *pp
))
5075 log_debug("Property %s does not exist.", *pp
);
5080 static int get_unit_dbus_path_by_pid(
5085 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5086 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5090 r
= sd_bus_call_method(
5092 "org.freedesktop.systemd1",
5093 "/org/freedesktop/systemd1",
5094 "org.freedesktop.systemd1.Manager",
5100 return log_error_errno(r
, "Failed to get unit for PID %"PRIu32
": %s", pid
, bus_error_message(&error
, r
));
5102 r
= sd_bus_message_read(reply
, "o", &u
);
5104 return bus_log_parse_error(r
);
5114 static int show_all(
5119 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5120 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
5125 r
= get_unit_list(bus
, NULL
, NULL
, &unit_infos
, 0, &reply
);
5129 (void) pager_open(arg_no_pager
, false);
5133 qsort_safe(unit_infos
, c
, sizeof(UnitInfo
), compare_unit_info
);
5135 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
5136 _cleanup_free_
char *p
= NULL
;
5138 p
= unit_dbus_path_from_name(u
->id
);
5142 r
= show_one(bus
, p
, u
->id
, SYSTEMCTL_SHOW_STATUS
, new_line
, ellipsized
);
5145 else if (r
> 0 && ret
== 0)
5152 static int show_system_status(sd_bus
*bus
) {
5153 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], since2
[FORMAT_TIMESTAMP_MAX
];
5154 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5155 _cleanup_(machine_info_clear
) struct machine_info mi
= {};
5156 _cleanup_free_
char *hn
= NULL
;
5157 const char *on
, *off
;
5160 hn
= gethostname_malloc();
5164 r
= bus_map_all_properties(
5166 "org.freedesktop.systemd1",
5167 "/org/freedesktop/systemd1",
5168 machine_info_property_map
,
5174 return log_error_errno(r
, "Failed to read server status: %s", bus_error_message(&error
, r
));
5176 if (streq_ptr(mi
.state
, "degraded")) {
5177 on
= ansi_highlight_red();
5178 off
= ansi_normal();
5179 } else if (streq_ptr(mi
.state
, "running")) {
5180 on
= ansi_highlight_green();
5181 off
= ansi_normal();
5183 on
= ansi_highlight_yellow();
5184 off
= ansi_normal();
5187 printf("%s%s%s %s\n", on
, special_glyph(BLACK_CIRCLE
), off
, arg_host
? arg_host
: hn
);
5189 printf(" State: %s%s%s\n",
5190 on
, strna(mi
.state
), off
);
5192 printf(" Jobs: %" PRIu32
" queued\n", mi
.n_jobs
);
5193 printf(" Failed: %" PRIu32
" units\n", mi
.n_failed_units
);
5195 printf(" Since: %s; %s\n",
5196 format_timestamp(since2
, sizeof(since2
), mi
.timestamp
),
5197 format_timestamp_relative(since1
, sizeof(since1
), mi
.timestamp
));
5199 printf(" CGroup: %s\n", mi
.control_group
?: "/");
5200 if (IN_SET(arg_transport
,
5201 BUS_TRANSPORT_LOCAL
,
5202 BUS_TRANSPORT_MACHINE
)) {
5203 static const char prefix
[] = " ";
5207 if (c
> sizeof(prefix
) - 1)
5208 c
-= sizeof(prefix
) - 1;
5212 show_cgroup(SYSTEMD_CGROUP_CONTROLLER
, strempty(mi
.control_group
), prefix
, c
, get_output_flags());
5218 static int show(int argc
, char *argv
[], void *userdata
) {
5219 bool new_line
= false, ellipsized
= false;
5220 SystemctlShowMode show_mode
;
5226 show_mode
= systemctl_show_mode_from_string(argv
[0]);
5227 if (show_mode
< 0) {
5228 log_error("Invalid argument.");
5232 if (show_mode
== SYSTEMCTL_SHOW_HELP
&& argc
<= 1) {
5233 log_error("This command expects one or more unit names. Did you mean --help?");
5237 r
= acquire_bus(BUS_MANAGER
, &bus
);
5241 (void) pager_open(arg_no_pager
, false);
5243 if (show_mode
== SYSTEMCTL_SHOW_STATUS
)
5244 /* Increase max number of open files to 16K if we can, we
5245 * might needs this when browsing journal files, which might
5246 * be split up into many files. */
5247 setrlimit_closest(RLIMIT_NOFILE
, &RLIMIT_MAKE_CONST(16384));
5249 /* If no argument is specified inspect the manager itself */
5250 if (show_mode
== SYSTEMCTL_SHOW_PROPERTIES
&& argc
<= 1)
5251 return show_one(bus
, "/org/freedesktop/systemd1", NULL
, show_mode
, &new_line
, &ellipsized
);
5253 if (show_mode
== SYSTEMCTL_SHOW_STATUS
&& argc
<= 1) {
5255 show_system_status(bus
);
5259 ret
= show_all(bus
, &new_line
, &ellipsized
);
5261 _cleanup_free_
char **patterns
= NULL
;
5264 STRV_FOREACH(name
, strv_skip(argv
, 1)) {
5265 _cleanup_free_
char *path
= NULL
, *unit
= NULL
;
5268 if (safe_atou32(*name
, &id
) < 0) {
5269 if (strv_push(&patterns
, *name
) < 0)
5273 } else if (show_mode
== SYSTEMCTL_SHOW_PROPERTIES
) {
5274 /* Interpret as job id */
5275 if (asprintf(&path
, "/org/freedesktop/systemd1/job/%u", id
) < 0)
5279 /* Interpret as PID */
5280 r
= get_unit_dbus_path_by_pid(bus
, id
, &path
);
5286 r
= unit_name_from_dbus_path(path
, &unit
);
5291 r
= show_one(bus
, path
, unit
, show_mode
, &new_line
, &ellipsized
);
5294 else if (r
> 0 && ret
== 0)
5298 if (!strv_isempty(patterns
)) {
5299 _cleanup_strv_free_
char **names
= NULL
;
5301 r
= expand_names(bus
, patterns
, NULL
, &names
);
5303 return log_error_errno(r
, "Failed to expand names: %m");
5305 STRV_FOREACH(name
, names
) {
5306 _cleanup_free_
char *path
;
5308 path
= unit_dbus_path_from_name(*name
);
5312 r
= show_one(bus
, path
, *name
, show_mode
, &new_line
, &ellipsized
);
5315 if (r
> 0 && ret
== 0)
5321 if (ellipsized
&& !arg_quiet
)
5322 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
5327 static int cat_file(const char *filename
, bool newline
) {
5328 _cleanup_close_
int fd
;
5330 fd
= open(filename
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
5334 printf("%s%s# %s%s\n",
5335 newline
? "\n" : "",
5336 ansi_highlight_blue(),
5341 return copy_bytes(fd
, STDOUT_FILENO
, (uint64_t) -1, 0);
5344 static int cat(int argc
, char *argv
[], void *userdata
) {
5345 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
5346 _cleanup_strv_free_
char **names
= NULL
;
5352 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
5353 log_error("Cannot remotely cat units.");
5357 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
5359 return log_error_errno(r
, "Failed to determine unit paths: %m");
5361 r
= acquire_bus(BUS_MANAGER
, &bus
);
5365 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
5367 return log_error_errno(r
, "Failed to expand names: %m");
5369 (void) pager_open(arg_no_pager
, false);
5371 STRV_FOREACH(name
, names
) {
5372 _cleanup_free_
char *fragment_path
= NULL
;
5373 _cleanup_strv_free_
char **dropin_paths
= NULL
;
5376 r
= unit_find_paths(bus
, *name
, &lp
, &fragment_path
, &dropin_paths
);
5387 if (need_daemon_reload(bus
, *name
) > 0) /* ignore errors (<0), this is informational output */
5389 "%s# Warning: %s changed on disk, the version systemd has loaded is outdated.\n"
5390 "%s# This output shows the current version of the unit's original fragment and drop-in files.\n"
5391 "%s# If fragments or drop-ins were added or removed, they are not properly reflected in this output.\n"
5392 "%s# Run 'systemctl%s daemon-reload' to reload units.%s\n",
5393 ansi_highlight_red(),
5395 ansi_highlight_red(),
5396 ansi_highlight_red(),
5397 ansi_highlight_red(),
5398 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user",
5401 if (fragment_path
) {
5402 r
= cat_file(fragment_path
, false);
5404 return log_warning_errno(r
, "Failed to cat %s: %m", fragment_path
);
5407 STRV_FOREACH(path
, dropin_paths
) {
5408 r
= cat_file(*path
, path
== dropin_paths
);
5410 return log_warning_errno(r
, "Failed to cat %s: %m", *path
);
5417 static int set_property(int argc
, char *argv
[], void *userdata
) {
5418 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5419 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5420 _cleanup_free_
char *n
= NULL
;
5425 r
= acquire_bus(BUS_MANAGER
, &bus
);
5429 polkit_agent_open_maybe();
5431 r
= sd_bus_message_new_method_call(
5434 "org.freedesktop.systemd1",
5435 "/org/freedesktop/systemd1",
5436 "org.freedesktop.systemd1.Manager",
5437 "SetUnitProperties");
5439 return bus_log_create_error(r
);
5441 r
= unit_name_mangle(argv
[1], arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
, &n
);
5443 return log_error_errno(r
, "Failed to mangle unit name: %m");
5445 t
= unit_name_to_type(n
);
5447 log_error("Invalid unit type: %s", n
);
5451 r
= sd_bus_message_append(m
, "sb", n
, arg_runtime
);
5453 return bus_log_create_error(r
);
5455 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, "(sv)");
5457 return bus_log_create_error(r
);
5459 r
= bus_append_unit_property_assignment_many(m
, t
, strv_skip(argv
, 2));
5463 r
= sd_bus_message_close_container(m
);
5465 return bus_log_create_error(r
);
5467 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5469 return log_error_errno(r
, "Failed to set unit properties on %s: %s", n
, bus_error_message(&error
, r
));
5474 static int daemon_reload(int argc
, char *argv
[], void *userdata
) {
5475 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5476 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5481 r
= acquire_bus(BUS_MANAGER
, &bus
);
5485 polkit_agent_open_maybe();
5487 switch (arg_action
) {
5494 method
= "Reexecute";
5497 case ACTION_SYSTEMCTL
:
5498 method
= streq(argv
[0], "daemon-reexec") ? "Reexecute" :
5499 /* "daemon-reload" */ "Reload";
5503 assert_not_reached("Unexpected action");
5506 r
= sd_bus_message_new_method_call(
5509 "org.freedesktop.systemd1",
5510 "/org/freedesktop/systemd1",
5511 "org.freedesktop.systemd1.Manager",
5514 return bus_log_create_error(r
);
5516 /* Note we use an extra-long timeout here. This is because a reload or reexec means generators are rerun which
5517 * are timed out after DEFAULT_TIMEOUT_USEC. Let's use twice that time here, so that the generators can have
5518 * their timeout, and for everything else there's the same time budget in place. */
5520 r
= sd_bus_call(bus
, m
, DEFAULT_TIMEOUT_USEC
* 2, &error
, NULL
);
5522 /* On reexecution, we expect a disconnect, not a reply */
5523 if (IN_SET(r
, -ETIMEDOUT
, -ECONNRESET
) && streq(method
, "Reexecute"))
5526 if (r
< 0 && arg_action
== ACTION_SYSTEMCTL
)
5527 return log_error_errno(r
, "Failed to reload daemon: %s", bus_error_message(&error
, r
));
5529 /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
5530 * old ways of doing things, hence don't log any error in that case here. */
5532 return r
< 0 ? r
: 0;
5535 static int trivial_method(int argc
, char *argv
[], void *userdata
) {
5536 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5544 r
= acquire_bus(BUS_MANAGER
, &bus
);
5548 polkit_agent_open_maybe();
5551 streq(argv
[0], "clear-jobs") ||
5552 streq(argv
[0], "cancel") ? "ClearJobs" :
5553 streq(argv
[0], "reset-failed") ? "ResetFailed" :
5554 streq(argv
[0], "halt") ? "Halt" :
5555 streq(argv
[0], "reboot") ? "Reboot" :
5556 streq(argv
[0], "kexec") ? "KExec" :
5557 streq(argv
[0], "exit") ? "Exit" :
5558 /* poweroff */ "PowerOff";
5560 r
= sd_bus_call_method(
5562 "org.freedesktop.systemd1",
5563 "/org/freedesktop/systemd1",
5564 "org.freedesktop.systemd1.Manager",
5569 if (r
< 0 && arg_action
== ACTION_SYSTEMCTL
)
5570 return log_error_errno(r
, "Failed to execute operation: %s", bus_error_message(&error
, r
));
5572 /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
5573 * old ways of doing things, hence don't log any error in that case here. */
5575 return r
< 0 ? r
: 0;
5578 static int reset_failed(int argc
, char *argv
[], void *userdata
) {
5579 _cleanup_strv_free_
char **names
= NULL
;
5585 return trivial_method(argc
, argv
, userdata
);
5587 r
= acquire_bus(BUS_MANAGER
, &bus
);
5591 polkit_agent_open_maybe();
5593 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
5595 return log_error_errno(r
, "Failed to expand names: %m");
5597 STRV_FOREACH(name
, names
) {
5598 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5600 q
= sd_bus_call_method(
5602 "org.freedesktop.systemd1",
5603 "/org/freedesktop/systemd1",
5604 "org.freedesktop.systemd1.Manager",
5610 log_error_errno(q
, "Failed to reset failed state of unit %s: %s", *name
, bus_error_message(&error
, q
));
5619 static int print_variable(const char *s
) {
5621 _cleanup_free_
char *esc
= NULL
;
5623 sep
= strchr(s
, '=');
5625 log_error("Invalid environment block");
5629 esc
= shell_maybe_quote(sep
+ 1, ESCAPE_POSIX
);
5633 printf("%.*s=%s\n", (int)(sep
-s
), s
, esc
);
5637 static int show_environment(int argc
, char *argv
[], void *userdata
) {
5638 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5639 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5644 r
= acquire_bus(BUS_MANAGER
, &bus
);
5648 (void) pager_open(arg_no_pager
, false);
5650 r
= sd_bus_get_property(
5652 "org.freedesktop.systemd1",
5653 "/org/freedesktop/systemd1",
5654 "org.freedesktop.systemd1.Manager",
5660 return log_error_errno(r
, "Failed to get environment: %s", bus_error_message(&error
, r
));
5662 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
5664 return bus_log_parse_error(r
);
5666 while ((r
= sd_bus_message_read_basic(reply
, SD_BUS_TYPE_STRING
, &text
)) > 0) {
5667 r
= print_variable(text
);
5672 return bus_log_parse_error(r
);
5674 r
= sd_bus_message_exit_container(reply
);
5676 return bus_log_parse_error(r
);
5681 static int switch_root(int argc
, char *argv
[], void *userdata
) {
5682 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5683 _cleanup_free_
char *cmdline_init
= NULL
;
5684 const char *root
, *init
;
5688 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
5689 log_error("Cannot switch root remotely.");
5693 if (argc
< 2 || argc
> 3) {
5694 log_error("Wrong number of arguments.");
5703 r
= parse_env_file("/proc/cmdline", WHITESPACE
,
5704 "init", &cmdline_init
,
5707 log_debug_errno(r
, "Failed to parse /proc/cmdline: %m");
5709 init
= cmdline_init
;
5712 init
= empty_to_null(init
);
5714 const char *root_systemd_path
= NULL
, *root_init_path
= NULL
;
5716 root_systemd_path
= strjoina(root
, "/" SYSTEMD_BINARY_PATH
);
5717 root_init_path
= strjoina(root
, "/", init
);
5719 /* If the passed init is actually the same as the
5720 * systemd binary, then let's suppress it. */
5721 if (files_same(root_init_path
, root_systemd_path
, 0) > 0)
5725 /* Instruct PID1 to exclude us from its killing spree applied during
5726 * the transition. Otherwise we would exit with a failure status even
5727 * though the switch to the new root has succeed. */
5728 argv_cmdline
[0] = '@';
5730 r
= acquire_bus(BUS_MANAGER
, &bus
);
5734 /* If we are slow to exit after the root switch, the new systemd instance
5735 * will send us a signal to terminate. Just ignore it and exit normally.
5736 * This way the unit does not end up as failed.
5738 r
= ignore_signals(SIGTERM
, -1);
5740 log_warning_errno(r
, "Failed to change disposition of SIGTERM to ignore: %m");
5742 log_debug("Switching root - root: %s; init: %s", root
, strna(init
));
5744 r
= sd_bus_call_method(
5746 "org.freedesktop.systemd1",
5747 "/org/freedesktop/systemd1",
5748 "org.freedesktop.systemd1.Manager",
5754 (void) default_signals(SIGTERM
, -1);
5756 return log_error_errno(r
, "Failed to switch root: %s", bus_error_message(&error
, r
));
5762 static int set_environment(int argc
, char *argv
[], void *userdata
) {
5763 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5764 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5772 r
= acquire_bus(BUS_MANAGER
, &bus
);
5776 polkit_agent_open_maybe();
5778 method
= streq(argv
[0], "set-environment")
5780 : "UnsetEnvironment";
5782 r
= sd_bus_message_new_method_call(
5785 "org.freedesktop.systemd1",
5786 "/org/freedesktop/systemd1",
5787 "org.freedesktop.systemd1.Manager",
5790 return bus_log_create_error(r
);
5792 r
= sd_bus_message_append_strv(m
, strv_skip(argv
, 1));
5794 return bus_log_create_error(r
);
5796 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5798 return log_error_errno(r
, "Failed to set environment: %s", bus_error_message(&error
, r
));
5803 static int import_environment(int argc
, char *argv
[], void *userdata
) {
5804 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5805 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5809 r
= acquire_bus(BUS_MANAGER
, &bus
);
5813 polkit_agent_open_maybe();
5815 r
= sd_bus_message_new_method_call(
5818 "org.freedesktop.systemd1",
5819 "/org/freedesktop/systemd1",
5820 "org.freedesktop.systemd1.Manager",
5823 return bus_log_create_error(r
);
5826 r
= sd_bus_message_append_strv(m
, environ
);
5830 r
= sd_bus_message_open_container(m
, 'a', "s");
5832 return bus_log_create_error(r
);
5834 STRV_FOREACH(a
, strv_skip(argv
, 1)) {
5836 if (!env_name_is_valid(*a
)) {
5837 log_error("Not a valid environment variable name: %s", *a
);
5841 STRV_FOREACH(b
, environ
) {
5844 eq
= startswith(*b
, *a
);
5845 if (eq
&& *eq
== '=') {
5847 r
= sd_bus_message_append(m
, "s", *b
);
5849 return bus_log_create_error(r
);
5856 r
= sd_bus_message_close_container(m
);
5859 return bus_log_create_error(r
);
5861 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5863 return log_error_errno(r
, "Failed to import environment: %s", bus_error_message(&error
, r
));
5868 static int enable_sysv_units(const char *verb
, char **args
) {
5871 #if HAVE_SYSV_COMPAT
5872 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
5875 /* Processes all SysV units, and reshuffles the array so that afterwards only the native units remain */
5877 if (arg_scope
!= UNIT_FILE_SYSTEM
)
5880 if (getenv_bool("SYSTEMCTL_SKIP_SYSV") > 0)
5883 if (!STR_IN_SET(verb
,
5889 r
= lookup_paths_init(&paths
, arg_scope
, LOOKUP_PATHS_EXCLUDE_GENERATED
, arg_root
);
5896 const char *argv
[] = {
5897 ROOTLIBEXECDIR
"/systemd-sysv-install",
5904 _cleanup_free_
char *p
= NULL
, *q
= NULL
, *l
= NULL
;
5905 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
);
5959 j
= safe_fork("(sysv-install)", FORK_RESET_SIGNALS
|FORK_DEATHSIG
|FORK_LOG
, &pid
);
5964 execv(argv
[0], (char**) argv
);
5965 log_error_errno(errno
, "Failed to execute %s: %m", argv
[0]);
5966 _exit(EXIT_FAILURE
);
5969 j
= wait_for_terminate_and_check("sysv-install", pid
, WAIT_LOG_ABNORMAL
);
5972 if (streq(verb
, "is-enabled")) {
5973 if (j
== EXIT_SUCCESS
) {
5982 } else if (j
!= EXIT_SUCCESS
)
5983 return -EBADE
; /* We don't warn here, under the assumption the script already showed an explanation */
5988 /* Remove this entry, so that we don't try enabling it as native unit */
5991 assert(args
[f
] == name
);
5992 strv_remove(args
, name
);
5999 static int mangle_names(char **original_names
, char ***mangled_names
) {
6000 char **i
, **l
, **name
;
6003 l
= i
= new(char*, strv_length(original_names
) + 1);
6007 STRV_FOREACH(name
, original_names
) {
6009 /* When enabling units qualified path names are OK,
6010 * too, hence allow them explicitly. */
6012 if (is_path(*name
)) {
6019 r
= unit_name_mangle(*name
, arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
, i
);
6023 return log_error_errno(r
, "Failed to mangle unit name: %m");
6036 static int normalize_filenames(char **names
) {
6040 STRV_FOREACH(u
, names
)
6041 if (!path_is_absolute(*u
)) {
6042 char* normalized_path
;
6044 if (!isempty(arg_root
)) {
6045 log_error("Non-absolute paths are not allowed when --root is used: %s", *u
);
6049 if (!strchr(*u
,'/')) {
6050 log_error("Link argument does contain at least one directory separator: %s", *u
);
6054 r
= path_make_absolute_cwd(*u
, &normalized_path
);
6058 free_and_replace(*u
, normalized_path
);
6064 static int normalize_names(char **names
, bool warn_if_path
) {
6066 bool was_path
= false;
6068 STRV_FOREACH(u
, names
) {
6074 r
= free_and_strdup(u
, basename(*u
));
6076 return log_error_errno(r
, "Failed to normalize unit file path: %m");
6081 if (warn_if_path
&& was_path
)
6082 log_warning("Warning: Can't execute disable on the unit file path. Proceeding with the unit name.");
6087 static int unit_exists(LookupPaths
*lp
, const char *unit
) {
6088 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6089 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
6090 _cleanup_free_
char *path
= NULL
;
6091 static const struct bus_properties_map property_map
[] = {
6092 { "LoadState", "s", NULL
, offsetof(UnitStatusInfo
, load_state
) },
6093 { "ActiveState", "s", NULL
, offsetof(UnitStatusInfo
, active_state
)},
6096 UnitStatusInfo info
= {};
6100 if (unit_name_is_valid(unit
, UNIT_NAME_TEMPLATE
))
6101 return unit_find_template_path(unit
, lp
, NULL
, NULL
);
6103 path
= unit_dbus_path_from_name(unit
);
6107 r
= acquire_bus(BUS_MANAGER
, &bus
);
6111 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", path
, property_map
, 0, &error
, &m
, &info
);
6113 return log_error_errno(r
, "Failed to get properties: %s", bus_error_message(&error
, r
));
6115 return !streq_ptr(info
.load_state
, "not-found") || !streq_ptr(info
.active_state
, "inactive");
6118 static int enable_unit(int argc
, char *argv
[], void *userdata
) {
6119 _cleanup_strv_free_
char **names
= NULL
;
6120 const char *verb
= argv
[0];
6121 UnitFileChange
*changes
= NULL
;
6122 unsigned n_changes
= 0;
6123 int carries_install_info
= -1;
6124 bool ignore_carries_install_info
= arg_quiet
;
6130 r
= mangle_names(strv_skip(argv
, 1), &names
);
6134 r
= enable_sysv_units(verb
, names
);
6138 /* If the operation was fully executed by the SysV compat, let's finish early */
6139 if (strv_isempty(names
)) {
6140 if (arg_no_reload
|| install_client_side())
6142 return daemon_reload(argc
, argv
, userdata
);
6145 if (streq(verb
, "disable")) {
6146 r
= normalize_names(names
, true);
6151 if (streq(verb
, "link")) {
6152 r
= normalize_filenames(names
);
6157 if (install_client_side()) {
6158 UnitFileFlags flags
;
6160 flags
= args_to_flags();
6161 if (streq(verb
, "enable")) {
6162 r
= unit_file_enable(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6163 carries_install_info
= r
;
6164 } else if (streq(verb
, "disable"))
6165 r
= unit_file_disable(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6166 else if (streq(verb
, "reenable")) {
6167 r
= unit_file_reenable(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6168 carries_install_info
= r
;
6169 } else if (streq(verb
, "link"))
6170 r
= unit_file_link(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6171 else if (streq(verb
, "preset")) {
6172 r
= unit_file_preset(arg_scope
, flags
, arg_root
, names
, arg_preset_mode
, &changes
, &n_changes
);
6173 } else if (streq(verb
, "mask"))
6174 r
= unit_file_mask(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6175 else if (streq(verb
, "unmask"))
6176 r
= unit_file_unmask(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6177 else if (streq(verb
, "revert"))
6178 r
= unit_file_revert(arg_scope
, arg_root
, names
, &changes
, &n_changes
);
6180 assert_not_reached("Unknown verb");
6182 unit_file_dump_changes(r
, verb
, changes
, n_changes
, arg_quiet
);
6187 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
, *m
= NULL
;
6188 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6189 bool expect_carries_install_info
= false;
6190 bool send_runtime
= true, send_force
= true, send_preset_mode
= false;
6194 if (STR_IN_SET(verb
, "mask", "unmask")) {
6196 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
6198 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
6202 STRV_FOREACH(name
, names
) {
6203 r
= unit_exists(&lp
, *name
);
6207 log_notice("Unit %s does not exist, proceeding anyway.", *names
);
6211 r
= acquire_bus(BUS_MANAGER
, &bus
);
6215 polkit_agent_open_maybe();
6217 if (streq(verb
, "enable")) {
6218 method
= "EnableUnitFiles";
6219 expect_carries_install_info
= true;
6220 } else if (streq(verb
, "disable")) {
6221 method
= "DisableUnitFiles";
6223 } else if (streq(verb
, "reenable")) {
6224 method
= "ReenableUnitFiles";
6225 expect_carries_install_info
= true;
6226 } else if (streq(verb
, "link"))
6227 method
= "LinkUnitFiles";
6228 else if (streq(verb
, "preset")) {
6230 if (arg_preset_mode
!= UNIT_FILE_PRESET_FULL
) {
6231 method
= "PresetUnitFilesWithMode";
6232 send_preset_mode
= true;
6234 method
= "PresetUnitFiles";
6236 expect_carries_install_info
= true;
6237 ignore_carries_install_info
= true;
6238 } else if (streq(verb
, "mask"))
6239 method
= "MaskUnitFiles";
6240 else if (streq(verb
, "unmask")) {
6241 method
= "UnmaskUnitFiles";
6243 } else if (streq(verb
, "revert")) {
6244 method
= "RevertUnitFiles";
6245 send_runtime
= send_force
= false;
6247 assert_not_reached("Unknown verb");
6249 r
= sd_bus_message_new_method_call(
6252 "org.freedesktop.systemd1",
6253 "/org/freedesktop/systemd1",
6254 "org.freedesktop.systemd1.Manager",
6257 return bus_log_create_error(r
);
6259 r
= sd_bus_message_append_strv(m
, names
);
6261 return bus_log_create_error(r
);
6263 if (send_preset_mode
) {
6264 r
= sd_bus_message_append(m
, "s", unit_file_preset_mode_to_string(arg_preset_mode
));
6266 return bus_log_create_error(r
);
6270 r
= sd_bus_message_append(m
, "b", arg_runtime
);
6272 return bus_log_create_error(r
);
6276 r
= sd_bus_message_append(m
, "b", arg_force
);
6278 return bus_log_create_error(r
);
6281 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
6283 return log_error_errno(r
, "Failed to %s unit: %s", verb
, bus_error_message(&error
, r
));
6285 if (expect_carries_install_info
) {
6286 r
= sd_bus_message_read(reply
, "b", &carries_install_info
);
6288 return bus_log_parse_error(r
);
6291 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
6295 /* Try to reload if enabled */
6297 r
= daemon_reload(argc
, argv
, userdata
);
6302 if (carries_install_info
== 0 && !ignore_carries_install_info
)
6303 log_warning("The unit files have no installation config (WantedBy, RequiredBy, Also, Alias\n"
6304 "settings in the [Install] section, and DefaultInstance for template units).\n"
6305 "This means they are not meant to be enabled using systemctl.\n"
6306 "Possible reasons for having this kind of units are:\n"
6307 "1) A unit may be statically enabled by being symlinked from another unit's\n"
6308 " .wants/ or .requires/ directory.\n"
6309 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
6310 " a requirement dependency on it.\n"
6311 "3) A unit may be started when needed via activation (socket, path, timer,\n"
6312 " D-Bus, udev, scripted systemctl call, ...).\n"
6313 "4) In case of template units, the unit is meant to be enabled with some\n"
6314 " instance name specified.");
6316 if (arg_now
&& STR_IN_SET(argv
[0], "enable", "disable", "mask")) {
6320 r
= acquire_bus(BUS_MANAGER
, &bus
);
6324 len
= strv_length(names
);
6326 char *new_args
[len
+ 2];
6328 new_args
[0] = (char*) (streq(argv
[0], "enable") ? "start" : "stop");
6329 for (i
= 0; i
< len
; i
++)
6330 new_args
[i
+ 1] = basename(names
[i
]);
6331 new_args
[i
+ 1] = NULL
;
6333 r
= start_unit(len
+ 1, new_args
, userdata
);
6338 unit_file_changes_free(changes
, n_changes
);
6343 static int add_dependency(int argc
, char *argv
[], void *userdata
) {
6344 _cleanup_strv_free_
char **names
= NULL
;
6345 _cleanup_free_
char *target
= NULL
;
6346 const char *verb
= argv
[0];
6347 UnitFileChange
*changes
= NULL
;
6348 unsigned n_changes
= 0;
6355 r
= unit_name_mangle_with_suffix(argv
[1], arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
, ".target", &target
);
6357 return log_error_errno(r
, "Failed to mangle unit name: %m");
6359 r
= mangle_names(strv_skip(argv
, 2), &names
);
6363 if (streq(verb
, "add-wants"))
6365 else if (streq(verb
, "add-requires"))
6366 dep
= UNIT_REQUIRES
;
6368 assert_not_reached("Unknown verb");
6370 if (install_client_side()) {
6371 r
= unit_file_add_dependency(arg_scope
, args_to_flags(), arg_root
, names
, target
, dep
, &changes
, &n_changes
);
6372 unit_file_dump_changes(r
, "add dependency on", changes
, n_changes
, arg_quiet
);
6377 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
, *m
= NULL
;
6378 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6381 r
= acquire_bus(BUS_MANAGER
, &bus
);
6385 polkit_agent_open_maybe();
6387 r
= sd_bus_message_new_method_call(
6390 "org.freedesktop.systemd1",
6391 "/org/freedesktop/systemd1",
6392 "org.freedesktop.systemd1.Manager",
6393 "AddDependencyUnitFiles");
6395 return bus_log_create_error(r
);
6397 r
= sd_bus_message_append_strv(m
, names
);
6399 return bus_log_create_error(r
);
6401 r
= sd_bus_message_append(m
, "ssbb", target
, unit_dependency_to_string(dep
), arg_runtime
, arg_force
);
6403 return bus_log_create_error(r
);
6405 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
6407 return log_error_errno(r
, "Failed to add dependency: %s", bus_error_message(&error
, r
));
6409 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
6413 if (arg_no_reload
) {
6418 r
= daemon_reload(argc
, argv
, userdata
);
6422 unit_file_changes_free(changes
, n_changes
);
6427 static int preset_all(int argc
, char *argv
[], void *userdata
) {
6428 UnitFileChange
*changes
= NULL
;
6429 unsigned n_changes
= 0;
6432 if (install_client_side()) {
6433 r
= unit_file_preset_all(arg_scope
, args_to_flags(), arg_root
, arg_preset_mode
, &changes
, &n_changes
);
6434 unit_file_dump_changes(r
, "preset", changes
, n_changes
, arg_quiet
);
6439 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6440 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6443 r
= acquire_bus(BUS_MANAGER
, &bus
);
6447 polkit_agent_open_maybe();
6449 r
= sd_bus_call_method(
6451 "org.freedesktop.systemd1",
6452 "/org/freedesktop/systemd1",
6453 "org.freedesktop.systemd1.Manager",
6454 "PresetAllUnitFiles",
6458 unit_file_preset_mode_to_string(arg_preset_mode
),
6462 return log_error_errno(r
, "Failed to preset all units: %s", bus_error_message(&error
, r
));
6464 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
6468 if (arg_no_reload
) {
6473 r
= daemon_reload(argc
, argv
, userdata
);
6477 unit_file_changes_free(changes
, n_changes
);
6482 static int show_installation_targets_client_side(const char *name
) {
6483 UnitFileChange
*changes
= NULL
;
6484 unsigned n_changes
= 0, i
;
6485 UnitFileFlags flags
;
6489 p
= STRV_MAKE(name
);
6490 flags
= UNIT_FILE_DRY_RUN
|
6491 (arg_runtime
? UNIT_FILE_RUNTIME
: 0);
6493 r
= unit_file_disable(UNIT_FILE_SYSTEM
, flags
, NULL
, p
, &changes
, &n_changes
);
6495 return log_error_errno(r
, "Failed to get file links for %s: %m", name
);
6497 for (i
= 0; i
< n_changes
; i
++)
6498 if (changes
[i
].type
== UNIT_FILE_UNLINK
)
6499 printf(" %s\n", changes
[i
].path
);
6504 static int show_installation_targets(sd_bus
*bus
, const char *name
) {
6505 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6506 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6510 r
= sd_bus_call_method(
6512 "org.freedesktop.systemd1",
6513 "/org/freedesktop/systemd1",
6514 "org.freedesktop.systemd1.Manager",
6518 "sb", name
, arg_runtime
);
6520 return log_error_errno(r
, "Failed to get unit file links for %s: %s", name
, bus_error_message(&error
, r
));
6522 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
6524 return bus_log_parse_error(r
);
6526 while ((r
= sd_bus_message_read(reply
, "s", &link
)) > 0)
6527 printf(" %s\n", link
);
6530 return bus_log_parse_error(r
);
6532 r
= sd_bus_message_exit_container(reply
);
6534 return bus_log_parse_error(r
);
6539 static int unit_is_enabled(int argc
, char *argv
[], void *userdata
) {
6541 _cleanup_strv_free_
char **names
= NULL
;
6546 r
= mangle_names(strv_skip(argv
, 1), &names
);
6550 r
= enable_sysv_units(argv
[0], names
);
6556 if (install_client_side()) {
6557 STRV_FOREACH(name
, names
) {
6558 UnitFileState state
;
6560 r
= unit_file_get_state(arg_scope
, arg_root
, *name
, &state
);
6562 return log_error_errno(r
, "Failed to get unit file state for %s: %m", *name
);
6566 UNIT_FILE_ENABLED_RUNTIME
,
6569 UNIT_FILE_GENERATED
))
6573 puts(unit_file_state_to_string(state
));
6575 r
= show_installation_targets_client_side(*name
);
6584 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6587 r
= acquire_bus(BUS_MANAGER
, &bus
);
6591 STRV_FOREACH(name
, names
) {
6592 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6595 r
= sd_bus_call_method(
6597 "org.freedesktop.systemd1",
6598 "/org/freedesktop/systemd1",
6599 "org.freedesktop.systemd1.Manager",
6605 return log_error_errno(r
, "Failed to get unit file state for %s: %s", *name
, bus_error_message(&error
, r
));
6607 r
= sd_bus_message_read(reply
, "s", &s
);
6609 return bus_log_parse_error(r
);
6611 if (STR_IN_SET(s
, "enabled", "enabled-runtime", "static", "indirect", "generated"))
6617 r
= show_installation_targets(bus
, *name
);
6625 return enabled
? EXIT_SUCCESS
: EXIT_FAILURE
;
6628 static int is_system_running(int argc
, char *argv
[], void *userdata
) {
6629 _cleanup_free_
char *state
= NULL
;
6633 if (running_in_chroot() > 0 || (arg_transport
== BUS_TRANSPORT_LOCAL
&& !sd_booted())) {
6636 return EXIT_FAILURE
;
6639 r
= acquire_bus(BUS_MANAGER
, &bus
);
6643 r
= sd_bus_get_property_string(
6645 "org.freedesktop.systemd1",
6646 "/org/freedesktop/systemd1",
6647 "org.freedesktop.systemd1.Manager",
6660 return streq(state
, "running") ? EXIT_SUCCESS
: EXIT_FAILURE
;
6663 static int create_edit_temp_file(const char *new_path
, const char *original_path
, char **ret_tmp_fn
) {
6664 _cleanup_free_
char *t
= NULL
;
6668 assert(original_path
);
6671 r
= tempfn_random(new_path
, NULL
, &t
);
6673 return log_error_errno(r
, "Failed to determine temporary filename for \"%s\": %m", new_path
);
6675 r
= mkdir_parents(new_path
, 0755);
6677 return log_error_errno(r
, "Failed to create directories for \"%s\": %m", new_path
);
6679 r
= copy_file(original_path
, t
, 0, 0644, 0, COPY_REFLINK
);
6684 return log_error_errno(r
, "Failed to create temporary file \"%s\": %m", t
);
6687 return log_error_errno(r
, "Failed to create temporary file for \"%s\": %m", new_path
);
6689 *ret_tmp_fn
= TAKE_PTR(t
);
6694 static int get_file_to_edit(
6695 const LookupPaths
*paths
,
6699 _cleanup_free_
char *path
= NULL
, *run
= NULL
;
6704 path
= strjoin(paths
->persistent_config
, "/", name
);
6709 run
= strjoin(paths
->runtime_config
, "/", name
);
6715 if (access(path
, F_OK
) >= 0) {
6716 log_error("Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.", run
, path
);
6720 *ret_path
= TAKE_PTR(run
);
6722 *ret_path
= TAKE_PTR(path
);
6727 static int unit_file_create_new(
6728 const LookupPaths
*paths
,
6729 const char *unit_name
,
6731 char **ret_new_path
,
6732 char **ret_tmp_path
) {
6734 char *tmp_new_path
, *tmp_tmp_path
, *ending
;
6738 assert(ret_new_path
);
6739 assert(ret_tmp_path
);
6741 ending
= strjoina(unit_name
, suffix
);
6742 r
= get_file_to_edit(paths
, ending
, &tmp_new_path
);
6746 r
= create_edit_temp_file(tmp_new_path
, tmp_new_path
, &tmp_tmp_path
);
6752 *ret_new_path
= tmp_new_path
;
6753 *ret_tmp_path
= tmp_tmp_path
;
6758 static int unit_file_create_copy(
6759 const LookupPaths
*paths
,
6760 const char *unit_name
,
6761 const char *fragment_path
,
6762 char **ret_new_path
,
6763 char **ret_tmp_path
) {
6765 char *tmp_new_path
, *tmp_tmp_path
;
6768 assert(fragment_path
);
6770 assert(ret_new_path
);
6771 assert(ret_tmp_path
);
6773 r
= get_file_to_edit(paths
, unit_name
, &tmp_new_path
);
6777 if (!path_equal(fragment_path
, tmp_new_path
) && access(tmp_new_path
, F_OK
) == 0) {
6780 r
= ask_char(&response
, "yn", "\"%s\" already exists. Overwrite with \"%s\"? [(y)es, (n)o] ", tmp_new_path
, fragment_path
);
6785 if (response
!= 'y') {
6786 log_warning("%s ignored", unit_name
);
6788 return -EKEYREJECTED
;
6792 r
= create_edit_temp_file(tmp_new_path
, fragment_path
, &tmp_tmp_path
);
6798 *ret_new_path
= tmp_new_path
;
6799 *ret_tmp_path
= tmp_tmp_path
;
6804 static int run_editor(char **paths
) {
6809 r
= safe_fork("(editor)", FORK_RESET_SIGNALS
|FORK_DEATHSIG
|FORK_LOG
|FORK_WAIT
, NULL
);
6814 char *editor
, **editor_args
= NULL
;
6815 char **tmp_path
, **original_path
, *p
;
6816 unsigned n_editor_args
= 0, i
= 1;
6819 argc
= strv_length(paths
)/2 + 1;
6821 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
6822 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
6823 * we try to execute well known editors
6825 editor
= getenv("SYSTEMD_EDITOR");
6827 editor
= getenv("EDITOR");
6829 editor
= getenv("VISUAL");
6831 if (!isempty(editor
)) {
6832 editor_args
= strv_split(editor
, WHITESPACE
);
6835 _exit(EXIT_FAILURE
);
6837 n_editor_args
= strv_length(editor_args
);
6838 argc
+= n_editor_args
- 1;
6840 args
= newa(const char*, argc
+ 1);
6842 if (n_editor_args
> 0) {
6843 args
[0] = editor_args
[0];
6844 for (; i
< n_editor_args
; i
++)
6845 args
[i
] = editor_args
[i
];
6848 STRV_FOREACH_PAIR(original_path
, tmp_path
, paths
) {
6849 args
[i
] = *tmp_path
;
6854 if (n_editor_args
> 0)
6855 execvp(args
[0], (char* const*) args
);
6857 FOREACH_STRING(p
, "editor", "nano", "vim", "vi") {
6859 execvp(p
, (char* const*) args
);
6860 /* We do not fail if the editor doesn't exist
6861 * because we want to try each one of them before
6864 if (errno
!= ENOENT
) {
6865 log_error_errno(errno
, "Failed to execute %s: %m", editor
);
6866 _exit(EXIT_FAILURE
);
6870 log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR, $EDITOR or $VISUAL.");
6871 _exit(EXIT_FAILURE
);
6877 static int find_paths_to_edit(sd_bus
*bus
, char **names
, char ***paths
) {
6878 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
6885 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
6889 STRV_FOREACH(name
, names
) {
6890 _cleanup_free_
char *path
= NULL
, *new_path
= NULL
, *tmp_path
= NULL
, *tmp_name
= NULL
;
6891 const char *unit_name
;
6893 r
= unit_find_paths(bus
, *name
, &lp
, &path
, NULL
);
6901 log_error("Run 'systemctl edit%s --force %s' to create a new unit.",
6902 arg_scope
== UNIT_FILE_GLOBAL
? " --global" :
6903 arg_scope
== UNIT_FILE_USER
? " --user" : "",
6908 /* Create a new unit from scratch */
6910 r
= unit_file_create_new(&lp
, unit_name
,
6911 arg_full
? NULL
: ".d/override.conf",
6912 &new_path
, &tmp_path
);
6916 unit_name
= basename(path
);
6917 /* We follow unit aliases, but we need to propagate the instance */
6918 if (unit_name_is_valid(*name
, UNIT_NAME_INSTANCE
) &&
6919 unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
6920 _cleanup_free_
char *instance
= NULL
;
6922 r
= unit_name_to_instance(*name
, &instance
);
6926 r
= unit_name_replace_instance(unit_name
, instance
, &tmp_name
);
6930 unit_name
= tmp_name
;
6934 r
= unit_file_create_copy(&lp
, unit_name
, path
, &new_path
, &tmp_path
);
6936 r
= unit_file_create_new(&lp
, unit_name
, ".d/override.conf", &new_path
, &tmp_path
);
6941 r
= strv_push_pair(paths
, new_path
, tmp_path
);
6944 new_path
= tmp_path
= NULL
;
6950 static int edit(int argc
, char *argv
[], void *userdata
) {
6951 _cleanup_strv_free_
char **names
= NULL
;
6952 _cleanup_strv_free_
char **paths
= NULL
;
6953 char **original
, **tmp
;
6958 log_error("Cannot edit units if not on a tty.");
6962 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
6963 log_error("Cannot edit units remotely.");
6967 r
= acquire_bus(BUS_MANAGER
, &bus
);
6971 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
6973 return log_error_errno(r
, "Failed to expand names: %m");
6975 STRV_FOREACH(tmp
, names
) {
6976 r
= unit_is_masked(bus
, *tmp
);
6981 log_error("Cannot edit %s: unit is masked.", *tmp
);
6986 r
= find_paths_to_edit(bus
, names
, &paths
);
6990 if (strv_isempty(paths
))
6993 r
= run_editor(paths
);
6997 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
6998 /* If the temporary file is empty we ignore it.
6999 * This allows the user to cancel the modification.
7001 if (null_or_empty_path(*tmp
)) {
7002 log_warning("Editing \"%s\" canceled: temporary file is empty.", *original
);
7006 r
= rename(*tmp
, *original
);
7008 r
= log_error_errno(errno
, "Failed to rename \"%s\" to \"%s\": %m", *tmp
, *original
);
7015 if (!arg_no_reload
&& !install_client_side())
7016 r
= daemon_reload(argc
, argv
, userdata
);
7019 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
7020 (void) unlink(*tmp
);
7022 /* Removing empty dropin dirs */
7024 _cleanup_free_
char *dir
;
7026 dir
= dirname_malloc(*original
);
7030 /* no need to check if the dir is empty, rmdir
7031 * does nothing if it is not the case.
7040 static void systemctl_help(void) {
7042 (void) pager_open(arg_no_pager
, false);
7044 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
7045 "Query or send control commands to the systemd manager.\n\n"
7046 " -h --help Show this help\n"
7047 " --version Show package version\n"
7048 " --system Connect to system manager\n"
7049 " --user Connect to user service manager\n"
7050 " -H --host=[USER@]HOST\n"
7051 " Operate on remote host\n"
7052 " -M --machine=CONTAINER\n"
7053 " Operate on local container\n"
7054 " -t --type=TYPE List units of a particular type\n"
7055 " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n"
7056 " -p --property=NAME Show only properties by this name\n"
7057 " -a --all Show all properties/all units currently in memory,\n"
7058 " including dead/empty ones. To list all units installed on\n"
7059 " the system, use the 'list-unit-files' command instead.\n"
7060 " --failed Same as --state=failed\n"
7061 " -l --full Don't ellipsize unit names on output\n"
7062 " -r --recursive Show unit list of host and local containers\n"
7063 " --reverse Show reverse dependencies with 'list-dependencies'\n"
7064 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
7065 " queueing a new job\n"
7066 " --show-types When showing sockets, explicitly show their type\n"
7067 " --value When showing properties, only print the value\n"
7068 " -i --ignore-inhibitors\n"
7069 " When shutting down or sleeping, ignore inhibitors\n"
7070 " --kill-who=WHO Who to send signal to\n"
7071 " -s --signal=SIGNAL Which signal to send\n"
7072 " --now Start or stop unit in addition to enabling or disabling it\n"
7073 " --dry-run Only print what would be done\n"
7074 " -q --quiet Suppress output\n"
7075 " --wait For (re)start, wait until service stopped again\n"
7076 " --no-block Do not wait until operation finished\n"
7077 " --no-wall Don't send wall message before halt/power-off/reboot\n"
7078 " --no-reload Don't reload daemon after en-/dis-abling unit files\n"
7079 " --no-legend Do not print a legend (column headers and hints)\n"
7080 " --no-pager Do not pipe output into a pager\n"
7081 " --no-ask-password\n"
7082 " Do not ask for system passwords\n"
7083 " --global Enable/disable/mask unit files globally\n"
7084 " --runtime Enable/disable/mask unit files temporarily until next\n"
7086 " -f --force When enabling unit files, override existing symlinks\n"
7087 " When shutting down, execute action immediately\n"
7088 " --preset-mode= Apply only enable, only disable, or all presets\n"
7089 " --root=PATH Enable/disable/mask unit files in the specified root\n"
7091 " -n --lines=INTEGER Number of journal entries to show\n"
7092 " -o --output=STRING Change journal output mode (short, short-precise,\n"
7093 " short-iso, short-iso-precise, short-full,\n"
7094 " short-monotonic, short-unix,\n"
7095 " verbose, export, json, json-pretty, json-sse, cat)\n"
7096 " --firmware-setup Tell the firmware to show the setup menu on next boot\n"
7097 " --plain Print unit dependencies as a list instead of a tree\n\n"
7099 " list-units [PATTERN...] List units currently in memory\n"
7100 " list-sockets [PATTERN...] List socket units currently in memory,\n"
7101 " ordered by address\n"
7102 " list-timers [PATTERN...] List timer units currently in memory,\n"
7103 " ordered by next elapse\n"
7104 " start UNIT... Start (activate) one or more units\n"
7105 " stop UNIT... Stop (deactivate) one or more units\n"
7106 " reload UNIT... Reload one or more units\n"
7107 " restart UNIT... Start or restart one or more units\n"
7108 " try-restart UNIT... Restart one or more units if active\n"
7109 " reload-or-restart UNIT... Reload one or more units if possible,\n"
7110 " otherwise start or restart\n"
7111 " try-reload-or-restart UNIT... If active, reload one or more units,\n"
7112 " if supported, otherwise restart\n"
7113 " isolate UNIT Start one unit and stop all others\n"
7114 " kill UNIT... Send signal to processes of a unit\n"
7115 " is-active PATTERN... Check whether units are active\n"
7116 " is-failed PATTERN... Check whether units are failed\n"
7117 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
7118 " show [PATTERN...|JOB...] Show properties of one or more\n"
7119 " units/jobs or the manager\n"
7120 " cat PATTERN... Show files and drop-ins of specified units\n"
7121 " set-property UNIT PROPERTY=VALUE... Sets one or more properties of a unit\n"
7122 " help PATTERN...|PID... Show manual for one or more units\n"
7123 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
7125 " list-dependencies [UNIT] Recursively show units which are required\n"
7126 " or wanted by this unit or by which this\n"
7127 " unit is required or wanted\n\n"
7128 "Unit File Commands:\n"
7129 " list-unit-files [PATTERN...] List installed unit files\n"
7130 " enable [UNIT...|PATH...] Enable one or more unit files\n"
7131 " disable UNIT... Disable one or more unit files\n"
7132 " reenable UNIT... Reenable one or more unit files\n"
7133 " preset UNIT... Enable/disable one or more unit files\n"
7134 " based on preset configuration\n"
7135 " preset-all Enable/disable all unit files based on\n"
7136 " preset configuration\n"
7137 " is-enabled UNIT... Check whether unit files are enabled\n"
7138 " mask UNIT... Mask one or more units\n"
7139 " unmask UNIT... Unmask one or more units\n"
7140 " link PATH... Link one or more units files into\n"
7141 " the search path\n"
7142 " revert UNIT... Revert one or more unit files to vendor\n"
7144 " add-wants TARGET UNIT... Add 'Wants' dependency for the target\n"
7145 " on specified one or more units\n"
7146 " add-requires TARGET UNIT... Add 'Requires' dependency for the target\n"
7147 " on specified one or more units\n"
7148 " edit UNIT... Edit one or more unit files\n"
7149 " get-default Get the name of the default target\n"
7150 " set-default TARGET Set the default target\n\n"
7151 "Machine Commands:\n"
7152 " list-machines [PATTERN...] List local containers and host\n\n"
7154 " list-jobs [PATTERN...] List jobs\n"
7155 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
7156 "Environment Commands:\n"
7157 " show-environment Dump environment\n"
7158 " set-environment VARIABLE=VALUE... Set one or more environment variables\n"
7159 " unset-environment VARIABLE... Unset one or more environment variables\n"
7160 " import-environment [VARIABLE...] Import all or some environment variables\n\n"
7161 "Manager Lifecycle Commands:\n"
7162 " daemon-reload Reload systemd manager configuration\n"
7163 " daemon-reexec Reexecute systemd manager\n\n"
7164 "System Commands:\n"
7165 " is-system-running Check whether system is fully running\n"
7166 " default Enter system default mode\n"
7167 " rescue Enter system rescue mode\n"
7168 " emergency Enter system emergency mode\n"
7169 " halt Shut down and halt the system\n"
7170 " poweroff Shut down and power-off the system\n"
7171 " reboot [ARG] Shut down and reboot the system\n"
7172 " kexec Shut down and reboot the system with kexec\n"
7173 " exit [EXIT_CODE] Request user instance or container exit\n"
7174 " switch-root ROOT [INIT] Change to a different root file system\n"
7175 " suspend Suspend the system\n"
7176 " hibernate Hibernate the system\n"
7177 " hybrid-sleep Hibernate and suspend the system\n"
7178 " suspend-then-hibernate Suspend the system, wake after a period of\n"
7179 " time and put it into hibernate\n",
7180 program_invocation_short_name
);
7183 static void halt_help(void) {
7184 printf("%s [OPTIONS...]%s\n\n"
7185 "%s the system.\n\n"
7186 " --help Show this help\n"
7187 " --halt Halt the machine\n"
7188 " -p --poweroff Switch off the machine\n"
7189 " --reboot Reboot the machine\n"
7190 " -f --force Force immediate halt/power-off/reboot\n"
7191 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
7192 " -d --no-wtmp Don't write wtmp record\n"
7193 " --no-wall Don't send wall message before halt/power-off/reboot\n",
7194 program_invocation_short_name
,
7195 arg_action
== ACTION_REBOOT
? " [ARG]" : "",
7196 arg_action
== ACTION_REBOOT
? "Reboot" :
7197 arg_action
== ACTION_POWEROFF
? "Power off" :
7201 static void shutdown_help(void) {
7202 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
7203 "Shut down the system.\n\n"
7204 " --help Show this help\n"
7205 " -H --halt Halt the machine\n"
7206 " -P --poweroff Power-off the machine\n"
7207 " -r --reboot Reboot the machine\n"
7208 " -h Equivalent to --poweroff, overridden by --halt\n"
7209 " -k Don't halt/power-off/reboot, just send warnings\n"
7210 " --no-wall Don't send wall message before halt/power-off/reboot\n"
7211 " -c Cancel a pending shutdown\n",
7212 program_invocation_short_name
);
7215 static void telinit_help(void) {
7216 printf("%s [OPTIONS...] {COMMAND}\n\n"
7217 "Send control commands to the init daemon.\n\n"
7218 " --help Show this help\n"
7219 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
7221 " 0 Power-off the machine\n"
7222 " 6 Reboot the machine\n"
7223 " 2, 3, 4, 5 Start runlevelX.target unit\n"
7224 " 1, s, S Enter rescue mode\n"
7225 " q, Q Reload init daemon configuration\n"
7226 " u, U Reexecute init daemon\n",
7227 program_invocation_short_name
);
7230 static void runlevel_help(void) {
7231 printf("%s [OPTIONS...]\n\n"
7232 "Prints the previous and current runlevel of the init system.\n\n"
7233 " --help Show this help\n",
7234 program_invocation_short_name
);
7237 static void help_types(void) {
7241 puts("Available unit types:");
7242 for (i
= 0; i
< _UNIT_TYPE_MAX
; i
++)
7243 puts(unit_type_to_string(i
));
7246 static void help_states(void) {
7250 puts("Available unit load states:");
7251 for (i
= 0; i
< _UNIT_LOAD_STATE_MAX
; i
++)
7252 puts(unit_load_state_to_string(i
));
7255 puts("\nAvailable unit active states:");
7256 for (i
= 0; i
< _UNIT_ACTIVE_STATE_MAX
; i
++)
7257 puts(unit_active_state_to_string(i
));
7260 puts("\nAvailable automount unit substates:");
7261 for (i
= 0; i
< _AUTOMOUNT_STATE_MAX
; i
++)
7262 puts(automount_state_to_string(i
));
7265 puts("\nAvailable device unit substates:");
7266 for (i
= 0; i
< _DEVICE_STATE_MAX
; i
++)
7267 puts(device_state_to_string(i
));
7270 puts("\nAvailable mount unit substates:");
7271 for (i
= 0; i
< _MOUNT_STATE_MAX
; i
++)
7272 puts(mount_state_to_string(i
));
7275 puts("\nAvailable path unit substates:");
7276 for (i
= 0; i
< _PATH_STATE_MAX
; i
++)
7277 puts(path_state_to_string(i
));
7280 puts("\nAvailable scope unit substates:");
7281 for (i
= 0; i
< _SCOPE_STATE_MAX
; i
++)
7282 puts(scope_state_to_string(i
));
7285 puts("\nAvailable service unit substates:");
7286 for (i
= 0; i
< _SERVICE_STATE_MAX
; i
++)
7287 puts(service_state_to_string(i
));
7290 puts("\nAvailable slice unit substates:");
7291 for (i
= 0; i
< _SLICE_STATE_MAX
; i
++)
7292 puts(slice_state_to_string(i
));
7295 puts("\nAvailable socket unit substates:");
7296 for (i
= 0; i
< _SOCKET_STATE_MAX
; i
++)
7297 puts(socket_state_to_string(i
));
7300 puts("\nAvailable swap unit substates:");
7301 for (i
= 0; i
< _SWAP_STATE_MAX
; i
++)
7302 puts(swap_state_to_string(i
));
7305 puts("\nAvailable target unit substates:");
7306 for (i
= 0; i
< _TARGET_STATE_MAX
; i
++)
7307 puts(target_state_to_string(i
));
7310 puts("\nAvailable timer unit substates:");
7311 for (i
= 0; i
< _TIMER_STATE_MAX
; i
++)
7312 puts(timer_state_to_string(i
));
7315 static int systemctl_parse_argv(int argc
, char *argv
[]) {
7325 ARG_IGNORE_DEPENDENCIES
,
7338 ARG_NO_ASK_PASSWORD
,
7351 static const struct option options
[] = {
7352 { "help", no_argument
, NULL
, 'h' },
7353 { "version", no_argument
, NULL
, ARG_VERSION
},
7354 { "type", required_argument
, NULL
, 't' },
7355 { "property", required_argument
, NULL
, 'p' },
7356 { "all", no_argument
, NULL
, 'a' },
7357 { "reverse", no_argument
, NULL
, ARG_REVERSE
},
7358 { "after", no_argument
, NULL
, ARG_AFTER
},
7359 { "before", no_argument
, NULL
, ARG_BEFORE
},
7360 { "show-types", no_argument
, NULL
, ARG_SHOW_TYPES
},
7361 { "failed", no_argument
, NULL
, ARG_FAILED
}, /* compatibility only */
7362 { "full", no_argument
, NULL
, 'l' },
7363 { "job-mode", required_argument
, NULL
, ARG_JOB_MODE
},
7364 { "fail", no_argument
, NULL
, ARG_FAIL
}, /* compatibility only */
7365 { "irreversible", no_argument
, NULL
, ARG_IRREVERSIBLE
}, /* compatibility only */
7366 { "ignore-dependencies", no_argument
, NULL
, ARG_IGNORE_DEPENDENCIES
}, /* compatibility only */
7367 { "ignore-inhibitors", no_argument
, NULL
, 'i' },
7368 { "value", no_argument
, NULL
, ARG_VALUE
},
7369 { "user", no_argument
, NULL
, ARG_USER
},
7370 { "system", no_argument
, NULL
, ARG_SYSTEM
},
7371 { "global", no_argument
, NULL
, ARG_GLOBAL
},
7372 { "wait", no_argument
, NULL
, ARG_WAIT
},
7373 { "no-block", no_argument
, NULL
, ARG_NO_BLOCK
},
7374 { "no-legend", no_argument
, NULL
, ARG_NO_LEGEND
},
7375 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
7376 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7377 { "dry-run", no_argument
, NULL
, ARG_DRY_RUN
},
7378 { "quiet", no_argument
, NULL
, 'q' },
7379 { "root", required_argument
, NULL
, ARG_ROOT
},
7380 { "force", no_argument
, NULL
, 'f' },
7381 { "no-reload", no_argument
, NULL
, ARG_NO_RELOAD
},
7382 { "kill-who", required_argument
, NULL
, ARG_KILL_WHO
},
7383 { "signal", required_argument
, NULL
, 's' },
7384 { "no-ask-password", no_argument
, NULL
, ARG_NO_ASK_PASSWORD
},
7385 { "host", required_argument
, NULL
, 'H' },
7386 { "machine", required_argument
, NULL
, 'M' },
7387 { "runtime", no_argument
, NULL
, ARG_RUNTIME
},
7388 { "lines", required_argument
, NULL
, 'n' },
7389 { "output", required_argument
, NULL
, 'o' },
7390 { "plain", no_argument
, NULL
, ARG_PLAIN
},
7391 { "state", required_argument
, NULL
, ARG_STATE
},
7392 { "recursive", no_argument
, NULL
, 'r' },
7393 { "preset-mode", required_argument
, NULL
, ARG_PRESET_MODE
},
7394 { "firmware-setup", no_argument
, NULL
, ARG_FIRMWARE_SETUP
},
7395 { "now", no_argument
, NULL
, ARG_NOW
},
7396 { "message", required_argument
, NULL
, ARG_MESSAGE
},
7406 /* we default to allowing interactive authorization only in systemctl (not in the legacy commands) */
7407 arg_ask_password
= true;
7409 while ((c
= getopt_long(argc
, argv
, "ht:p:alqfs:H:M:n:o:ir", options
, NULL
)) >= 0)
7421 if (isempty(optarg
)) {
7422 log_error("--type= requires arguments.");
7426 for (p
= optarg
;;) {
7427 _cleanup_free_
char *type
= NULL
;
7429 r
= extract_first_word(&p
, &type
, ",", 0);
7431 return log_error_errno(r
, "Failed to parse type: %s", optarg
);
7435 if (streq(type
, "help")) {
7440 if (unit_type_from_string(type
) >= 0) {
7441 if (strv_push(&arg_types
, type
) < 0)
7447 /* It's much nicer to use --state= for
7448 * load states, but let's support this
7449 * in --types= too for compatibility
7450 * with old versions */
7451 if (unit_load_state_from_string(type
) >= 0) {
7452 if (strv_push(&arg_states
, type
) < 0)
7458 log_error("Unknown unit type or load state '%s'.", type
);
7459 log_info("Use -t help to see a list of allowed values.");
7467 /* Make sure that if the empty property list
7468 was specified, we won't show any properties. */
7469 if (isempty(optarg
) && !arg_properties
) {
7470 arg_properties
= new0(char*, 1);
7471 if (!arg_properties
)
7474 for (p
= optarg
;;) {
7475 _cleanup_free_
char *prop
= NULL
;
7477 r
= extract_first_word(&p
, &prop
, ",", 0);
7479 return log_error_errno(r
, "Failed to parse property: %s", optarg
);
7483 if (strv_push(&arg_properties
, prop
) < 0)
7489 /* If the user asked for a particular
7490 * property, show it to him, even if it is
7502 arg_dependency
= DEPENDENCY_REVERSE
;
7506 arg_dependency
= DEPENDENCY_AFTER
;
7507 arg_jobs_after
= true;
7511 arg_dependency
= DEPENDENCY_BEFORE
;
7512 arg_jobs_before
= true;
7515 case ARG_SHOW_TYPES
:
7516 arg_show_types
= true;
7524 arg_job_mode
= optarg
;
7528 arg_job_mode
= "fail";
7531 case ARG_IRREVERSIBLE
:
7532 arg_job_mode
= "replace-irreversibly";
7535 case ARG_IGNORE_DEPENDENCIES
:
7536 arg_job_mode
= "ignore-dependencies";
7540 arg_scope
= UNIT_FILE_USER
;
7544 arg_scope
= UNIT_FILE_SYSTEM
;
7548 arg_scope
= UNIT_FILE_GLOBAL
;
7556 arg_no_block
= true;
7560 arg_no_legend
= true;
7564 arg_no_pager
= true;
7572 r
= parse_path_argument_and_warn(optarg
, false, &arg_root
);
7582 if (strv_extend(&arg_states
, "failed") < 0)
7600 arg_no_reload
= true;
7604 arg_kill_who
= optarg
;
7608 arg_signal
= signal_from_string_try_harder(optarg
);
7609 if (arg_signal
< 0) {
7610 log_error("Failed to parse signal string %s.", optarg
);
7615 case ARG_NO_ASK_PASSWORD
:
7616 arg_ask_password
= false;
7620 arg_transport
= BUS_TRANSPORT_REMOTE
;
7625 arg_transport
= BUS_TRANSPORT_MACHINE
;
7634 if (safe_atou(optarg
, &arg_lines
) < 0) {
7635 log_error("Failed to parse lines '%s'", optarg
);
7641 arg_output
= output_mode_from_string(optarg
);
7642 if (arg_output
< 0) {
7643 log_error("Unknown output '%s'.", optarg
);
7649 arg_ignore_inhibitors
= true;
7656 case ARG_FIRMWARE_SETUP
:
7657 arg_firmware_setup
= true;
7661 if (isempty(optarg
)) {
7662 log_error("--state= requires arguments.");
7666 for (p
= optarg
;;) {
7667 _cleanup_free_
char *s
= NULL
;
7669 r
= extract_first_word(&p
, &s
, ",", 0);
7671 return log_error_errno(r
, "Failed to parse state: %s", optarg
);
7675 if (streq(s
, "help")) {
7680 if (strv_push(&arg_states
, s
) < 0)
7689 if (geteuid() != 0) {
7690 log_error("--recursive requires root privileges.");
7694 arg_recursive
= true;
7697 case ARG_PRESET_MODE
:
7699 arg_preset_mode
= unit_file_preset_mode_from_string(optarg
);
7700 if (arg_preset_mode
< 0) {
7701 log_error("Failed to parse preset mode: %s.", optarg
);
7712 if (strv_extend(&arg_wall
, optarg
) < 0)
7720 assert_not_reached("Unhandled option");
7723 if (arg_transport
!= BUS_TRANSPORT_LOCAL
&& arg_scope
!= UNIT_FILE_SYSTEM
) {
7724 log_error("Cannot access user instance remotely.");
7728 if (arg_wait
&& arg_no_block
) {
7729 log_error("--wait may not be combined with --no-block.");
7736 static int halt_parse_argv(int argc
, char *argv
[]) {
7745 static const struct option options
[] = {
7746 { "help", no_argument
, NULL
, ARG_HELP
},
7747 { "halt", no_argument
, NULL
, ARG_HALT
},
7748 { "poweroff", no_argument
, NULL
, 'p' },
7749 { "reboot", no_argument
, NULL
, ARG_REBOOT
},
7750 { "force", no_argument
, NULL
, 'f' },
7751 { "wtmp-only", no_argument
, NULL
, 'w' },
7752 { "no-wtmp", no_argument
, NULL
, 'd' },
7753 { "no-sync", no_argument
, NULL
, 'n' },
7754 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7763 if (utmp_get_runlevel(&runlevel
, NULL
) >= 0)
7764 if (IN_SET(runlevel
, '0', '6'))
7767 while ((c
= getopt_long(argc
, argv
, "pfwdnih", options
, NULL
)) >= 0)
7775 arg_action
= ACTION_HALT
;
7779 if (arg_action
!= ACTION_REBOOT
)
7780 arg_action
= ACTION_POWEROFF
;
7784 arg_action
= ACTION_REBOOT
;
7809 /* Compatibility nops */
7816 assert_not_reached("Unhandled option");
7819 if (arg_action
== ACTION_REBOOT
&& (argc
== optind
|| argc
== optind
+ 1)) {
7820 r
= update_reboot_parameter_and_warn(argc
== optind
+ 1 ? argv
[optind
] : NULL
);
7823 } else if (optind
< argc
) {
7824 log_error("Too many arguments.");
7831 static int parse_shutdown_time_spec(const char *t
, usec_t
*_u
) {
7835 if (streq(t
, "now"))
7837 else if (!strchr(t
, ':')) {
7840 if (safe_atou64(t
, &u
) < 0)
7843 *_u
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
* u
;
7852 hour
= strtol(t
, &e
, 10);
7853 if (errno
> 0 || *e
!= ':' || hour
< 0 || hour
> 23)
7856 minute
= strtol(e
+1, &e
, 10);
7857 if (errno
> 0 || *e
!= 0 || minute
< 0 || minute
> 59)
7860 n
= now(CLOCK_REALTIME
);
7861 s
= (time_t) (n
/ USEC_PER_SEC
);
7863 assert_se(localtime_r(&s
, &tm
));
7865 tm
.tm_hour
= (int) hour
;
7866 tm
.tm_min
= (int) minute
;
7869 assert_se(s
= mktime(&tm
));
7871 *_u
= (usec_t
) s
* USEC_PER_SEC
;
7874 *_u
+= USEC_PER_DAY
;
7880 static int shutdown_parse_argv(int argc
, char *argv
[]) {
7887 static const struct option options
[] = {
7888 { "help", no_argument
, NULL
, ARG_HELP
},
7889 { "halt", no_argument
, NULL
, 'H' },
7890 { "poweroff", no_argument
, NULL
, 'P' },
7891 { "reboot", no_argument
, NULL
, 'r' },
7892 { "kexec", no_argument
, NULL
, 'K' }, /* not documented extension */
7893 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7903 while ((c
= getopt_long(argc
, argv
, "HPrhkKat:fFc", options
, NULL
)) >= 0)
7911 arg_action
= ACTION_HALT
;
7915 arg_action
= ACTION_POWEROFF
;
7920 arg_action
= ACTION_KEXEC
;
7922 arg_action
= ACTION_REBOOT
;
7926 arg_action
= ACTION_KEXEC
;
7930 if (arg_action
!= ACTION_HALT
)
7931 arg_action
= ACTION_POWEROFF
;
7943 case 't': /* Note that we also ignore any passed argument to -t, not just the -t itself */
7946 /* Compatibility nops */
7950 arg_action
= ACTION_CANCEL_SHUTDOWN
;
7957 assert_not_reached("Unhandled option");
7960 if (argc
> optind
&& arg_action
!= ACTION_CANCEL_SHUTDOWN
) {
7961 r
= parse_shutdown_time_spec(argv
[optind
], &arg_when
);
7963 log_error("Failed to parse time specification: %s", argv
[optind
]);
7967 arg_when
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
;
7969 if (argc
> optind
&& arg_action
== ACTION_CANCEL_SHUTDOWN
)
7970 /* No time argument for shutdown cancel */
7971 wall
= argv
+ optind
;
7972 else if (argc
> optind
+ 1)
7973 /* We skip the time argument */
7974 wall
= argv
+ optind
+ 1;
7977 arg_wall
= strv_copy(wall
);
7987 static int telinit_parse_argv(int argc
, char *argv
[]) {
7994 static const struct option options
[] = {
7995 { "help", no_argument
, NULL
, ARG_HELP
},
7996 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
8000 static const struct {
8004 { '0', ACTION_POWEROFF
},
8005 { '6', ACTION_REBOOT
},
8006 { '1', ACTION_RESCUE
},
8007 { '2', ACTION_RUNLEVEL2
},
8008 { '3', ACTION_RUNLEVEL3
},
8009 { '4', ACTION_RUNLEVEL4
},
8010 { '5', ACTION_RUNLEVEL5
},
8011 { 's', ACTION_RESCUE
},
8012 { 'S', ACTION_RESCUE
},
8013 { 'q', ACTION_RELOAD
},
8014 { 'Q', ACTION_RELOAD
},
8015 { 'u', ACTION_REEXEC
},
8016 { 'U', ACTION_REEXEC
}
8025 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
8040 assert_not_reached("Unhandled option");
8043 if (optind
>= argc
) {
8044 log_error("%s: required argument missing.", program_invocation_short_name
);
8048 if (optind
+ 1 < argc
) {
8049 log_error("Too many arguments.");
8053 if (strlen(argv
[optind
]) != 1) {
8054 log_error("Expected single character argument.");
8058 for (i
= 0; i
< ELEMENTSOF(table
); i
++)
8059 if (table
[i
].from
== argv
[optind
][0])
8062 if (i
>= ELEMENTSOF(table
)) {
8063 log_error("Unknown command '%s'.", argv
[optind
]);
8067 arg_action
= table
[i
].to
;
8074 static int runlevel_parse_argv(int argc
, char *argv
[]) {
8080 static const struct option options
[] = {
8081 { "help", no_argument
, NULL
, ARG_HELP
},
8090 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
8101 assert_not_reached("Unhandled option");
8104 if (optind
< argc
) {
8105 log_error("Too many arguments.");
8112 static int parse_argv(int argc
, char *argv
[]) {
8116 if (program_invocation_short_name
) {
8118 if (strstr(program_invocation_short_name
, "halt")) {
8119 arg_action
= ACTION_HALT
;
8120 return halt_parse_argv(argc
, argv
);
8122 } else if (strstr(program_invocation_short_name
, "poweroff")) {
8123 arg_action
= ACTION_POWEROFF
;
8124 return halt_parse_argv(argc
, argv
);
8126 } else if (strstr(program_invocation_short_name
, "reboot")) {
8128 arg_action
= ACTION_KEXEC
;
8130 arg_action
= ACTION_REBOOT
;
8131 return halt_parse_argv(argc
, argv
);
8133 } else if (strstr(program_invocation_short_name
, "shutdown")) {
8134 arg_action
= ACTION_POWEROFF
;
8135 return shutdown_parse_argv(argc
, argv
);
8137 } else if (strstr(program_invocation_short_name
, "init")) {
8139 /* Matches invocations as "init" as well as "telinit", which are synonymous when run as PID !=
8142 * On SysV "telinit" was the official command to communicate with PID 1, but "init" would
8143 * redirect itself to "telinit" if called with PID != 1. We follow the same logic here still,
8144 * though we add one level of indirection, as we implement "telinit" in "systemctl". Hence, for
8145 * us if you invoke "init" you get "systemd", but it will execve() "systemctl" immediately with
8146 * argv[] unmodified if PID is != 1. If you invoke "telinit" you directly get "systemctl". In
8147 * both cases we shall do the same thing, which is why we do strstr(p_i_s_n, "init") here, as a
8148 * quick way to match both.
8150 * Also see redirect_telinit() in src/core/main.c. */
8152 if (sd_booted() > 0) {
8153 arg_action
= _ACTION_INVALID
;
8154 return telinit_parse_argv(argc
, argv
);
8156 /* Hmm, so some other init system is running, we need to forward this request to
8157 * it. For now we simply guess that it is Upstart. */
8159 execv(TELINIT
, argv
);
8161 log_error("Couldn't find an alternative telinit implementation to spawn.");
8165 } else if (strstr(program_invocation_short_name
, "runlevel")) {
8166 arg_action
= ACTION_RUNLEVEL
;
8167 return runlevel_parse_argv(argc
, argv
);
8171 arg_action
= ACTION_SYSTEMCTL
;
8172 return systemctl_parse_argv(argc
, argv
);
8175 #if HAVE_SYSV_COMPAT
8176 _pure_
static int action_to_runlevel(void) {
8178 static const char table
[_ACTION_MAX
] = {
8179 [ACTION_HALT
] = '0',
8180 [ACTION_POWEROFF
] = '0',
8181 [ACTION_REBOOT
] = '6',
8182 [ACTION_RUNLEVEL2
] = '2',
8183 [ACTION_RUNLEVEL3
] = '3',
8184 [ACTION_RUNLEVEL4
] = '4',
8185 [ACTION_RUNLEVEL5
] = '5',
8186 [ACTION_RESCUE
] = '1'
8189 assert(arg_action
>= 0 && arg_action
< _ACTION_MAX
);
8191 return table
[arg_action
];
8195 static int talk_initctl(void) {
8196 #if HAVE_SYSV_COMPAT
8197 struct init_request request
= {
8198 .magic
= INIT_MAGIC
,
8200 .cmd
= INIT_CMD_RUNLVL
8203 _cleanup_close_
int fd
= -1;
8208 rl
= action_to_runlevel();
8212 request
.runlevel
= rl
;
8214 FOREACH_STRING(p
, "/run/initctl", "/dev/initctl") {
8215 fd
= open(p
, O_WRONLY
|O_NONBLOCK
|O_CLOEXEC
|O_NOCTTY
);
8216 if (fd
>= 0 || errno
!= ENOENT
)
8220 if (errno
== ENOENT
)
8223 return log_error_errno(errno
, "Failed to open initctl fifo: %m");
8226 r
= loop_write(fd
, &request
, sizeof(request
), false);
8228 return log_error_errno(r
, "Failed to write to %s: %m", p
);
8236 static int systemctl_main(int argc
, char *argv
[]) {
8238 static const Verb verbs
[] = {
8239 { "list-units", VERB_ANY
, VERB_ANY
, VERB_DEFAULT
|VERB_ONLINE_ONLY
, list_units
},
8240 { "list-unit-files", VERB_ANY
, VERB_ANY
, 0, list_unit_files
},
8241 { "list-sockets", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, list_sockets
},
8242 { "list-timers", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, list_timers
},
8243 { "list-jobs", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, list_jobs
},
8244 { "list-machines", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
|VERB_MUST_BE_ROOT
, list_machines
},
8245 { "clear-jobs", VERB_ANY
, 1, VERB_ONLINE_ONLY
, trivial_method
},
8246 { "cancel", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, cancel_job
},
8247 { "start", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8248 { "stop", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8249 { "condstop", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
}, /* For compatibility with ALTLinux */
8250 { "reload", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8251 { "restart", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8252 { "try-restart", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8253 { "reload-or-restart", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8254 { "reload-or-try-restart", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
}, /* For compatbility with old systemctl <= 228 */
8255 { "try-reload-or-restart", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8256 { "force-reload", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
}, /* For compatibility with SysV */
8257 { "condreload", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
}, /* For compatibility with ALTLinux */
8258 { "condrestart", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
}, /* For compatibility with RH */
8259 { "isolate", 2, 2, VERB_ONLINE_ONLY
, start_unit
},
8260 { "kill", 2, VERB_ANY
, VERB_ONLINE_ONLY
, kill_unit
},
8261 { "is-active", 2, VERB_ANY
, VERB_ONLINE_ONLY
, check_unit_active
},
8262 { "check", 2, VERB_ANY
, VERB_ONLINE_ONLY
, check_unit_active
}, /* deprecated alias of is-active */
8263 { "is-failed", 2, VERB_ANY
, VERB_ONLINE_ONLY
, check_unit_failed
},
8264 { "show", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, show
},
8265 { "cat", 2, VERB_ANY
, VERB_ONLINE_ONLY
, cat
},
8266 { "status", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, show
},
8267 { "help", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, show
},
8268 { "daemon-reload", VERB_ANY
, 1, VERB_ONLINE_ONLY
, daemon_reload
},
8269 { "daemon-reexec", VERB_ANY
, 1, VERB_ONLINE_ONLY
, daemon_reload
},
8270 { "show-environment", VERB_ANY
, 1, VERB_ONLINE_ONLY
, show_environment
},
8271 { "set-environment", 2, VERB_ANY
, VERB_ONLINE_ONLY
, set_environment
},
8272 { "unset-environment", 2, VERB_ANY
, VERB_ONLINE_ONLY
, set_environment
},
8273 { "import-environment", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, import_environment
},
8274 { "halt", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8275 { "poweroff", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8276 { "reboot", VERB_ANY
, 2, VERB_ONLINE_ONLY
, start_system_special
},
8277 { "kexec", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8278 { "suspend", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8279 { "hibernate", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8280 { "hybrid-sleep", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8281 { "suspend-then-hibernate",VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8282 { "default", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_special
},
8283 { "rescue", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8284 { "emergency", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8285 { "exit", VERB_ANY
, 2, VERB_ONLINE_ONLY
, start_special
},
8286 { "reset-failed", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, reset_failed
},
8287 { "enable", 2, VERB_ANY
, 0, enable_unit
},
8288 { "disable", 2, VERB_ANY
, 0, enable_unit
},
8289 { "is-enabled", 2, VERB_ANY
, 0, unit_is_enabled
},
8290 { "reenable", 2, VERB_ANY
, 0, enable_unit
},
8291 { "preset", 2, VERB_ANY
, 0, enable_unit
},
8292 { "preset-all", VERB_ANY
, 1, 0, preset_all
},
8293 { "mask", 2, VERB_ANY
, 0, enable_unit
},
8294 { "unmask", 2, VERB_ANY
, 0, enable_unit
},
8295 { "link", 2, VERB_ANY
, 0, enable_unit
},
8296 { "revert", 2, VERB_ANY
, 0, enable_unit
},
8297 { "switch-root", 2, VERB_ANY
, VERB_ONLINE_ONLY
, switch_root
},
8298 { "list-dependencies", VERB_ANY
, 2, VERB_ONLINE_ONLY
, list_dependencies
},
8299 { "set-default", 2, 2, 0, set_default
},
8300 { "get-default", VERB_ANY
, 1, 0, get_default
},
8301 { "set-property", 3, VERB_ANY
, VERB_ONLINE_ONLY
, set_property
},
8302 { "is-system-running", VERB_ANY
, 1, 0, is_system_running
},
8303 { "add-wants", 3, VERB_ANY
, 0, add_dependency
},
8304 { "add-requires", 3, VERB_ANY
, 0, add_dependency
},
8305 { "edit", 2, VERB_ANY
, VERB_ONLINE_ONLY
, edit
},
8309 return dispatch_verb(argc
, argv
, verbs
, NULL
);
8312 static int reload_with_fallback(void) {
8314 /* First, try systemd via D-Bus. */
8315 if (daemon_reload(0, NULL
, NULL
) >= 0)
8318 /* Nothing else worked, so let's try signals */
8319 assert(IN_SET(arg_action
, ACTION_RELOAD
, ACTION_REEXEC
));
8321 if (kill(1, arg_action
== ACTION_RELOAD
? SIGHUP
: SIGTERM
) < 0)
8322 return log_error_errno(errno
, "kill() failed: %m");
8327 static int start_with_fallback(void) {
8329 /* First, try systemd via D-Bus. */
8330 if (start_unit(0, NULL
, NULL
) >= 0)
8333 /* Nothing else worked, so let's try /dev/initctl */
8334 if (talk_initctl() > 0)
8337 log_error("Failed to talk to init daemon.");
8341 static int halt_now(enum action a
) {
8343 /* The kernel will automatically flush ATA disks and suchlike on reboot(), but the file systems need to be
8344 * synce'd explicitly in advance. */
8345 if (!arg_no_sync
&& !arg_dry_run
)
8348 /* Make sure C-A-D is handled by the kernel from this point on... */
8350 (void) reboot(RB_ENABLE_CAD
);
8356 log_info("Halting.");
8359 (void) reboot(RB_HALT_SYSTEM
);
8362 case ACTION_POWEROFF
:
8364 log_info("Powering off.");
8367 (void) reboot(RB_POWER_OFF
);
8372 return reboot_with_parameter(REBOOT_FALLBACK
|
8373 (arg_quiet
? 0 : REBOOT_LOG
) |
8374 (arg_dry_run
? REBOOT_DRY_RUN
: 0));
8377 assert_not_reached("Unknown action.");
8381 static int logind_schedule_shutdown(void) {
8384 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
8385 char date
[FORMAT_TIMESTAMP_MAX
];
8390 r
= acquire_bus(BUS_FULL
, &bus
);
8394 switch (arg_action
) {
8398 case ACTION_POWEROFF
:
8399 action
= "poweroff";
8414 action
= strjoina("dry-", action
);
8416 (void) logind_set_wall_message();
8418 r
= sd_bus_call_method(
8420 "org.freedesktop.login1",
8421 "/org/freedesktop/login1",
8422 "org.freedesktop.login1.Manager",
8430 return log_warning_errno(r
, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s", bus_error_message(&error
, r
));
8433 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.", format_timestamp(date
, sizeof(date
), arg_when
));
8436 log_error("Cannot schedule shutdown without logind support, proceeding with immediate shutdown.");
8441 static int halt_main(void) {
8444 r
= logind_check_inhibitors(arg_action
);
8449 return logind_schedule_shutdown();
8451 if (geteuid() != 0) {
8452 if (arg_dry_run
|| arg_force
> 0) {
8453 (void) must_be_root();
8457 /* Try logind if we are a normal user and no special
8458 * mode applies. Maybe PolicyKit allows us to shutdown
8460 if (IN_SET(arg_action
, ACTION_POWEROFF
, ACTION_REBOOT
, ACTION_HALT
)) {
8461 r
= logind_reboot(arg_action
);
8464 if (IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
8465 /* requested operation is not
8466 * supported on the local system or
8467 * already in progress */
8469 /* on all other errors, try low-level operation */
8473 if (!arg_dry_run
&& !arg_force
)
8474 return start_with_fallback();
8476 assert(geteuid() == 0);
8479 if (sd_booted() > 0)
8480 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
8482 r
= utmp_put_shutdown();
8484 log_warning_errno(r
, "Failed to write utmp record: %m");
8491 r
= halt_now(arg_action
);
8492 return log_error_errno(r
, "Failed to reboot: %m");
8495 static int runlevel_main(void) {
8496 int r
, runlevel
, previous
;
8498 r
= utmp_get_runlevel(&runlevel
, &previous
);
8505 previous
<= 0 ? 'N' : previous
,
8506 runlevel
<= 0 ? 'N' : runlevel
);
8511 static int logind_cancel_shutdown(void) {
8513 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
8517 r
= acquire_bus(BUS_FULL
, &bus
);
8521 (void) logind_set_wall_message();
8523 r
= sd_bus_call_method(
8525 "org.freedesktop.login1",
8526 "/org/freedesktop/login1",
8527 "org.freedesktop.login1.Manager",
8528 "CancelScheduledShutdown",
8532 return log_warning_errno(r
, "Failed to talk to logind, shutdown hasn't been cancelled: %s", bus_error_message(&error
, r
));
8536 log_error("Not compiled with logind support, cannot cancel scheduled shutdowns.");
8541 int main(int argc
, char*argv
[]) {
8544 argv_cmdline
= argv
[0];
8546 setlocale(LC_ALL
, "");
8547 log_parse_environment();
8551 /* Explicitly not on_tty() to avoid setting cached value.
8552 * This becomes relevant for piping output which might be
8554 original_stdout_is_tty
= isatty(STDOUT_FILENO
);
8556 r
= parse_argv(argc
, argv
);
8560 if (arg_action
!= ACTION_SYSTEMCTL
&& running_in_chroot() > 0) {
8563 log_info("Running in chroot, ignoring request.");
8568 /* systemctl_main() will print an error message for the bus
8569 * connection, but only if it needs to */
8571 switch (arg_action
) {
8573 case ACTION_SYSTEMCTL
:
8574 r
= systemctl_main(argc
, argv
);
8577 /* Legacy command aliases set arg_action. They provide some fallbacks,
8578 * e.g. to tell sysvinit to reboot after you have installed systemd
8582 case ACTION_POWEROFF
:
8588 case ACTION_RUNLEVEL2
:
8589 case ACTION_RUNLEVEL3
:
8590 case ACTION_RUNLEVEL4
:
8591 case ACTION_RUNLEVEL5
:
8593 r
= start_with_fallback();
8598 r
= reload_with_fallback();
8601 case ACTION_CANCEL_SHUTDOWN
:
8602 r
= logind_cancel_shutdown();
8605 case ACTION_RUNLEVEL
:
8606 r
= runlevel_main();
8610 case ACTION_SUSPEND
:
8611 case ACTION_HIBERNATE
:
8612 case ACTION_HYBRID_SLEEP
:
8613 case ACTION_SUSPEND_THEN_HIBERNATE
:
8614 case ACTION_EMERGENCY
:
8615 case ACTION_DEFAULT
:
8616 /* systemctl verbs with no equivalent in the legacy commands.
8617 * These cannot appear in arg_action. Fall through. */
8619 case _ACTION_INVALID
:
8621 assert_not_reached("Unknown action");
8628 ask_password_agent_close();
8629 polkit_agent_close();
8631 strv_free(arg_types
);
8632 strv_free(arg_states
);
8633 strv_free(arg_properties
);
8635 strv_free(arg_wall
);
8639 /* Note that we return r here, not EXIT_SUCCESS, so that we can implement the LSB-like return codes */
8640 return r
< 0 ? EXIT_FAILURE
: r
;