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/>.
25 #include <linux/reboot.h>
31 #include <sys/prctl.h>
32 #include <sys/reboot.h>
33 #include <sys/socket.h>
37 #include "sd-daemon.h"
40 #include "alloc-util.h"
42 #include "bus-common-errors.h"
43 #include "bus-error.h"
44 #include "bus-message.h"
45 #include "bus-unit-util.h"
47 #include "cgroup-show.h"
48 #include "cgroup-util.h"
54 #include "exit-status.h"
57 #include "format-util.h"
59 #include "glob-util.h"
60 #include "hostname-util.h"
61 #include "hexdecoct.h"
66 #include "locale-util.h"
68 #include "logs-show.h"
72 #include "parse-util.h"
73 #include "path-lookup.h"
74 #include "path-util.h"
75 #include "process-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"
86 #include "terminal-util.h"
88 #include "unit-name.h"
89 #include "user-util.h"
91 #include "utmp-wtmp.h"
95 /* The init script exit status codes
96 0 program is running or service is OK
97 1 program is dead and /var/run pid file exists
98 2 program is dead and /var/lock lock file exists
99 3 program is not running
100 4 program or service status is unknown
101 5-99 reserved for future LSB use
102 100-149 reserved for distribution use
103 150-199 reserved for application use
107 EXIT_PROGRAM_RUNNING_OR_SERVICE_OK
= 0,
108 EXIT_PROGRAM_DEAD_AND_PID_EXISTS
= 1,
109 EXIT_PROGRAM_DEAD_AND_LOCK_FILE_EXISTS
= 2,
110 EXIT_PROGRAM_NOT_RUNNING
= 3,
111 EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN
= 4,
114 static char **arg_types
= NULL
;
115 static char **arg_states
= NULL
;
116 static char **arg_properties
= NULL
;
117 static bool arg_all
= false;
118 static enum dependency
{
124 } arg_dependency
= DEPENDENCY_FORWARD
;
125 static const char *arg_job_mode
= "replace";
126 static UnitFileScope arg_scope
= UNIT_FILE_SYSTEM
;
127 static bool arg_wait
= false;
128 static bool arg_no_block
= false;
129 static bool arg_no_legend
= false;
130 static bool arg_no_pager
= false;
131 static bool arg_no_wtmp
= false;
132 static bool arg_no_sync
= false;
133 static bool arg_no_wall
= false;
134 static bool arg_no_reload
= false;
135 static bool arg_value
= false;
136 static bool arg_show_types
= false;
137 static bool arg_ignore_inhibitors
= false;
138 static bool arg_dry_run
= false;
139 static bool arg_quiet
= false;
140 static bool arg_full
= false;
141 static bool arg_recursive
= false;
142 static int arg_force
= 0;
143 static bool arg_ask_password
= false;
144 static bool arg_runtime
= false;
145 static UnitFilePresetMode arg_preset_mode
= UNIT_FILE_PRESET_FULL
;
146 static char **arg_wall
= NULL
;
147 static const char *arg_kill_who
= NULL
;
148 static int arg_signal
= SIGTERM
;
149 static char *arg_root
= NULL
;
150 static usec_t arg_when
= 0;
151 static char *arg_esp_path
= NULL
;
152 static char *argv_cmdline
= NULL
;
173 ACTION_CANCEL_SHUTDOWN
,
176 } arg_action
= ACTION_SYSTEMCTL
;
177 static BusTransport arg_transport
= BUS_TRANSPORT_LOCAL
;
178 static const char *arg_host
= NULL
;
179 static unsigned arg_lines
= 10;
180 static OutputMode arg_output
= OUTPUT_SHORT
;
181 static bool arg_plain
= false;
182 static bool arg_firmware_setup
= false;
183 static bool arg_now
= false;
184 static bool arg_jobs_before
= false;
185 static bool arg_jobs_after
= false;
187 static int daemon_reload(int argc
, char *argv
[], void* userdata
);
188 static int trivial_method(int argc
, char *argv
[], void *userdata
);
189 static int halt_now(enum action a
);
190 static int get_state_one_unit(sd_bus
*bus
, const char *name
, UnitActiveState
*active_state
);
192 static bool original_stdout_is_tty
;
194 typedef enum BusFocus
{
195 BUS_FULL
, /* The full bus indicated via --system or --user */
196 BUS_MANAGER
, /* The manager itself, possibly directly, possibly via the bus */
200 static sd_bus
*busses
[_BUS_FOCUS_MAX
] = {};
202 static UnitFileFlags
args_to_flags(void) {
203 return (arg_runtime
? UNIT_FILE_RUNTIME
: 0) |
204 (arg_force
? UNIT_FILE_FORCE
: 0);
207 static int acquire_bus(BusFocus focus
, sd_bus
**ret
) {
210 assert(focus
< _BUS_FOCUS_MAX
);
213 /* We only go directly to the manager, if we are using a local transport */
214 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
217 if (getenv_bool("SYSTEMCTL_FORCE_BUS") > 0)
220 if (!busses
[focus
]) {
223 user
= arg_scope
!= UNIT_FILE_SYSTEM
;
225 if (!user
&& sd_booted() <= 0) {
226 /* Print a friendly message when the local system is actually not running systemd as PID 1. */
227 log_error("System has not been booted with systemd as init system (PID 1). Can't operate.");
231 if (focus
== BUS_MANAGER
)
232 r
= bus_connect_transport_systemd(arg_transport
, arg_host
, user
, &busses
[focus
]);
234 r
= bus_connect_transport(arg_transport
, arg_host
, user
, &busses
[focus
]);
236 return log_error_errno(r
, "Failed to connect to bus: %m");
238 (void) sd_bus_set_allow_interactive_authorization(busses
[focus
], arg_ask_password
);
241 *ret
= busses
[focus
];
245 static void release_busses(void) {
248 for (w
= 0; w
< _BUS_FOCUS_MAX
; w
++)
249 busses
[w
] = sd_bus_flush_close_unref(busses
[w
]);
252 static int map_string_no_copy(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
254 const char **p
= userdata
;
257 r
= sd_bus_message_read_basic(m
, SD_BUS_TYPE_STRING
, &s
);
267 static void ask_password_agent_open_if_enabled(void) {
269 /* Open the password agent as a child process if necessary */
274 if (!arg_ask_password
)
277 if (arg_scope
!= UNIT_FILE_SYSTEM
)
280 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
283 ask_password_agent_open();
286 static void polkit_agent_open_maybe(void) {
287 /* Open the polkit agent as a child process if necessary */
289 if (arg_scope
!= UNIT_FILE_SYSTEM
)
292 polkit_agent_open_if_enabled(arg_transport
, arg_ask_password
);
295 static OutputFlags
get_output_flags(void) {
297 arg_all
* OUTPUT_SHOW_ALL
|
298 (arg_full
|| !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH
|
299 colors_enabled() * OUTPUT_COLOR
|
300 !arg_quiet
* OUTPUT_WARN_CUTOFF
;
303 static int translate_bus_error_to_exit_status(int r
, const sd_bus_error
*error
) {
306 if (!sd_bus_error_is_set(error
))
309 if (sd_bus_error_has_name(error
, SD_BUS_ERROR_ACCESS_DENIED
) ||
310 sd_bus_error_has_name(error
, BUS_ERROR_ONLY_BY_DEPENDENCY
) ||
311 sd_bus_error_has_name(error
, BUS_ERROR_NO_ISOLATION
) ||
312 sd_bus_error_has_name(error
, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE
))
313 return EXIT_NOPERMISSION
;
315 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
))
316 return EXIT_NOTINSTALLED
;
318 if (sd_bus_error_has_name(error
, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE
) ||
319 sd_bus_error_has_name(error
, SD_BUS_ERROR_NOT_SUPPORTED
))
320 return EXIT_NOTIMPLEMENTED
;
322 if (sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
))
323 return EXIT_NOTCONFIGURED
;
331 static bool install_client_side(void) {
333 /* Decides when to execute enable/disable/... operations
334 * client-side rather than server-side. */
336 if (running_in_chroot_or_offline())
339 if (sd_booted() <= 0)
342 if (!isempty(arg_root
))
345 if (arg_scope
== UNIT_FILE_GLOBAL
)
348 /* Unsupported environment variable, mostly for debugging purposes */
349 if (getenv_bool("SYSTEMCTL_INSTALL_CLIENT_SIDE") > 0)
355 static int compare_unit_info(const void *a
, const void *b
) {
356 const UnitInfo
*u
= a
, *v
= b
;
360 /* First, order by machine */
361 if (!u
->machine
&& v
->machine
)
363 if (u
->machine
&& !v
->machine
)
365 if (u
->machine
&& v
->machine
) {
366 r
= strcasecmp(u
->machine
, v
->machine
);
371 /* Second, order by unit type */
372 d1
= strrchr(u
->id
, '.');
373 d2
= strrchr(v
->id
, '.');
375 r
= strcasecmp(d1
, d2
);
380 /* Third, order by name */
381 return strcasecmp(u
->id
, v
->id
);
384 static const char* unit_type_suffix(const char *name
) {
387 dot
= strrchr(name
, '.');
394 static bool output_show_unit(const UnitInfo
*u
, char **patterns
) {
397 if (!strv_fnmatch_or_empty(patterns
, u
->id
, FNM_NOESCAPE
))
400 if (arg_types
&& !strv_find(arg_types
, unit_type_suffix(u
->id
)))
406 /* Note that '--all' is not purely a state filter, but also a
407 * filter that hides units that "follow" other units (which is
408 * used for device units that appear under different names). */
409 if (!isempty(u
->following
))
412 if (!strv_isempty(arg_states
))
415 /* By default show all units except the ones in inactive
416 * state and with no pending job */
420 if (streq(u
->active_state
, "inactive"))
426 static int output_units_list(const UnitInfo
*unit_infos
, unsigned c
) {
427 unsigned circle_len
= 0, id_len
, max_id_len
, load_len
, active_len
, sub_len
, job_len
, desc_len
, max_desc_len
;
429 unsigned n_shown
= 0;
432 max_id_len
= STRLEN("UNIT");
433 load_len
= STRLEN("LOAD");
434 active_len
= STRLEN("ACTIVE");
435 sub_len
= STRLEN("SUB");
436 job_len
= STRLEN("JOB");
437 max_desc_len
= STRLEN("DESCRIPTION");
439 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
440 max_id_len
= MAX(max_id_len
, strlen(u
->id
) + (u
->machine
? strlen(u
->machine
)+1 : 0));
441 load_len
= MAX(load_len
, strlen(u
->load_state
));
442 active_len
= MAX(active_len
, strlen(u
->active_state
));
443 sub_len
= MAX(sub_len
, strlen(u
->sub_state
));
444 max_desc_len
= MAX(max_desc_len
, strlen(u
->description
));
446 if (u
->job_id
!= 0) {
447 job_len
= MAX(job_len
, strlen(u
->job_type
));
451 if (!arg_no_legend
&&
452 (streq(u
->active_state
, "failed") ||
453 STR_IN_SET(u
->load_state
, "error", "not-found", "masked")))
457 if (!arg_full
&& original_stdout_is_tty
) {
460 id_len
= MIN(max_id_len
, 25u); /* as much as it needs, but at most 25 for now */
461 basic_len
= circle_len
+ 1 + id_len
+ 1 + load_len
+ 1 + active_len
+ 1 + sub_len
+ 1;
464 basic_len
+= job_len
+ 1;
466 if (basic_len
< (unsigned) columns()) {
467 unsigned extra_len
, incr
;
468 extra_len
= columns() - basic_len
;
470 /* Either UNIT already got 25, or is fully satisfied.
471 * Grant up to 25 to DESC now. */
472 incr
= MIN(extra_len
, 25u);
476 /* Of the remainder give as much as the ID needs to the ID, and give the rest to the
477 * description but not more than it needs. */
479 incr
= MIN(max_id_len
- id_len
, extra_len
);
481 desc_len
+= MIN(extra_len
- incr
, max_desc_len
- desc_len
);
487 desc_len
= max_desc_len
;
490 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
491 _cleanup_free_
char *e
= NULL
, *j
= NULL
;
492 const char *on_underline
= "", *off_underline
= "";
493 const char *on_loaded
= "", *off_loaded
= "";
494 const char *on_active
= "", *off_active
= "";
495 const char *on_circle
= "", *off_circle
= "";
497 bool circle
= false, underline
= false;
499 if (!n_shown
&& !arg_no_legend
) {
504 printf("%s%-*s %-*s %-*s %-*s ",
508 active_len
, "ACTIVE",
512 printf("%-*s ", job_len
, "JOB");
516 !arg_full
&& arg_no_pager
? (int) desc_len
: -1,
523 if (u
+ 1 < unit_infos
+ c
&&
524 !streq(unit_type_suffix(u
->id
), unit_type_suffix((u
+ 1)->id
))) {
525 on_underline
= ansi_underline();
526 off_underline
= ansi_normal();
530 if (STR_IN_SET(u
->load_state
, "error", "not-found", "masked") && !arg_plain
) {
531 on_circle
= ansi_highlight_yellow();
532 off_circle
= ansi_normal();
534 on_loaded
= underline
? ansi_highlight_red_underline() : ansi_highlight_red();
535 off_loaded
= underline
? on_underline
: ansi_normal();
536 } else if (streq(u
->active_state
, "failed") && !arg_plain
) {
537 on_circle
= ansi_highlight_red();
538 off_circle
= ansi_normal();
540 on_active
= underline
? ansi_highlight_red_underline() : ansi_highlight_red();
541 off_active
= underline
? on_underline
: ansi_normal();
545 j
= strjoin(u
->machine
, ":", u
->id
);
554 e
= ellipsize(id
, id_len
, 33);
562 printf("%s%s%s ", on_circle
, circle
? special_glyph(BLACK_CIRCLE
) : " ", off_circle
);
564 printf("%s%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
566 on_active
, id_len
, id
, off_active
,
567 on_loaded
, load_len
, u
->load_state
, off_loaded
,
568 on_active
, active_len
, u
->active_state
,
569 sub_len
, u
->sub_state
, off_active
,
570 job_count
? job_len
+ 1 : 0, u
->job_id
? u
->job_type
: "");
574 !arg_full
&& arg_no_pager
? (int) desc_len
: -1,
579 if (!arg_no_legend
) {
580 const char *on
, *off
;
584 "LOAD = Reflects whether the unit definition was properly loaded.\n"
585 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
586 "SUB = The low-level unit activation state, values depend on unit type.");
587 puts(job_count
? "JOB = Pending job for the unit.\n" : "");
588 on
= ansi_highlight();
591 on
= ansi_highlight_red();
596 printf("%s%u loaded units listed.%s\n"
597 "To show all installed unit files use 'systemctl list-unit-files'.\n",
600 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
601 "To show all installed unit files use 'systemctl list-unit-files'.\n",
608 static int get_unit_list(
612 UnitInfo
**unit_infos
,
614 sd_bus_message
**_reply
) {
616 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
617 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
618 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
622 bool fallback
= false;
628 r
= sd_bus_message_new_method_call(
631 "org.freedesktop.systemd1",
632 "/org/freedesktop/systemd1",
633 "org.freedesktop.systemd1.Manager",
634 "ListUnitsByPatterns");
636 return bus_log_create_error(r
);
638 r
= sd_bus_message_append_strv(m
, arg_states
);
640 return bus_log_create_error(r
);
642 r
= sd_bus_message_append_strv(m
, patterns
);
644 return bus_log_create_error(r
);
646 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
647 if (r
< 0 && (sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_METHOD
) ||
648 sd_bus_error_has_name(&error
, SD_BUS_ERROR_ACCESS_DENIED
))) {
649 /* Fallback to legacy ListUnitsFiltered method */
651 log_debug_errno(r
, "Failed to list units: %s Falling back to ListUnitsFiltered method.", bus_error_message(&error
, r
));
652 m
= sd_bus_message_unref(m
);
653 sd_bus_error_free(&error
);
655 r
= sd_bus_message_new_method_call(
658 "org.freedesktop.systemd1",
659 "/org/freedesktop/systemd1",
660 "org.freedesktop.systemd1.Manager",
661 "ListUnitsFiltered");
663 return bus_log_create_error(r
);
665 r
= sd_bus_message_append_strv(m
, arg_states
);
667 return bus_log_create_error(r
);
669 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
672 return log_error_errno(r
, "Failed to list units: %s", bus_error_message(&error
, r
));
674 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssssouso)");
676 return bus_log_parse_error(r
);
678 while ((r
= bus_parse_unit_info(reply
, &u
)) > 0) {
681 if (!output_show_unit(&u
, fallback
? patterns
: NULL
))
684 if (!GREEDY_REALLOC(*unit_infos
, size
, c
+1))
687 (*unit_infos
)[c
++] = u
;
690 return bus_log_parse_error(r
);
692 r
= sd_bus_message_exit_container(reply
);
694 return bus_log_parse_error(r
);
702 static void message_set_freep(Set
**set
) {
703 set_free_with_destructor(*set
, sd_bus_message_unref
);
706 static int get_unit_list_recursive(
709 UnitInfo
**_unit_infos
,
713 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
714 _cleanup_(message_set_freep
) Set
*replies
;
715 sd_bus_message
*reply
;
723 replies
= set_new(NULL
);
727 c
= get_unit_list(bus
, NULL
, patterns
, &unit_infos
, 0, &reply
);
731 r
= set_put(replies
, reply
);
733 sd_bus_message_unref(reply
);
738 _cleanup_strv_free_
char **machines
= NULL
;
741 r
= sd_get_machine_names(&machines
);
743 return log_error_errno(r
, "Failed to get machine names: %m");
745 STRV_FOREACH(i
, machines
) {
746 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*container
= NULL
;
749 r
= sd_bus_open_system_machine(&container
, *i
);
751 log_warning_errno(r
, "Failed to connect to container %s, ignoring: %m", *i
);
755 k
= get_unit_list(container
, *i
, patterns
, &unit_infos
, c
, &reply
);
761 r
= set_put(replies
, reply
);
763 sd_bus_message_unref(reply
);
768 *_machines
= machines
;
773 *_unit_infos
= unit_infos
;
782 static int list_units(int argc
, char *argv
[], void *userdata
) {
783 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
784 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
785 _cleanup_strv_free_
char **machines
= NULL
;
789 r
= acquire_bus(BUS_MANAGER
, &bus
);
793 pager_open(arg_no_pager
, false);
795 r
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
799 qsort_safe(unit_infos
, r
, sizeof(UnitInfo
), compare_unit_info
);
800 return output_units_list(unit_infos
, r
);
803 static int get_triggered_units(
808 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
815 r
= sd_bus_get_property_strv(
817 "org.freedesktop.systemd1",
819 "org.freedesktop.systemd1.Unit",
824 return log_error_errno(r
, "Failed to determine triggers: %s", bus_error_message(&error
, r
));
829 static int get_listening(
831 const char* unit_path
,
834 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
835 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
836 const char *type
, *path
;
839 r
= sd_bus_get_property(
841 "org.freedesktop.systemd1",
843 "org.freedesktop.systemd1.Socket",
849 return log_error_errno(r
, "Failed to get list of listening sockets: %s", bus_error_message(&error
, r
));
851 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
853 return bus_log_parse_error(r
);
855 while ((r
= sd_bus_message_read(reply
, "(ss)", &type
, &path
)) > 0) {
857 r
= strv_extend(listening
, type
);
861 r
= strv_extend(listening
, path
);
868 return bus_log_parse_error(r
);
870 r
= sd_bus_message_exit_container(reply
);
872 return bus_log_parse_error(r
);
884 /* Note: triggered is a list here, although it almost certainly
885 * will always be one unit. Nevertheless, dbus API allows for multiple
886 * values, so let's follow that. */
889 /* The strv above is shared. free is set only in the first one. */
893 static int socket_info_compare(const struct socket_info
*a
, const struct socket_info
*b
) {
899 if (!a
->machine
&& b
->machine
)
901 if (a
->machine
&& !b
->machine
)
903 if (a
->machine
&& b
->machine
) {
904 o
= strcasecmp(a
->machine
, b
->machine
);
909 o
= strcmp(a
->path
, b
->path
);
911 o
= strcmp(a
->type
, b
->type
);
916 static int output_sockets_list(struct socket_info
*socket_infos
, unsigned cs
) {
917 struct socket_info
*s
;
918 unsigned pathlen
= STRLEN("LISTEN"),
919 typelen
= STRLEN("TYPE") * arg_show_types
,
920 socklen
= STRLEN("UNIT"),
921 servlen
= STRLEN("ACTIVATES");
922 const char *on
, *off
;
924 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
928 socklen
= MAX(socklen
, strlen(s
->id
));
930 typelen
= MAX(typelen
, strlen(s
->type
));
931 pathlen
= MAX(pathlen
, strlen(s
->path
) + (s
->machine
? strlen(s
->machine
)+1 : 0));
933 STRV_FOREACH(a
, s
->triggered
)
934 tmp
+= strlen(*a
) + 2*(a
!= s
->triggered
);
935 servlen
= MAX(servlen
, tmp
);
940 printf("%-*s %-*.*s%-*s %s\n",
942 typelen
+ arg_show_types
, typelen
+ arg_show_types
, "TYPE ",
946 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
947 _cleanup_free_
char *j
= NULL
;
952 j
= strjoin(s
->machine
, ":", s
->path
);
960 printf("%-*s %-*s %-*s",
961 pathlen
, path
, typelen
, s
->type
, socklen
, s
->id
);
964 pathlen
, path
, socklen
, s
->id
);
965 STRV_FOREACH(a
, s
->triggered
)
967 a
== s
->triggered
? "" : ",", *a
);
971 on
= ansi_highlight();
976 on
= ansi_highlight_red();
980 if (!arg_no_legend
) {
981 printf("%s%u sockets listed.%s\n", on
, cs
, off
);
983 printf("Pass --all to see loaded but inactive sockets, too.\n");
989 static int list_sockets(int argc
, char *argv
[], void *userdata
) {
990 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
991 _cleanup_strv_free_
char **machines
= NULL
;
992 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
993 _cleanup_free_
struct socket_info
*socket_infos
= NULL
;
995 struct socket_info
*s
;
1001 r
= acquire_bus(BUS_MANAGER
, &bus
);
1005 pager_open(arg_no_pager
, false);
1007 n
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
1011 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
1012 _cleanup_strv_free_
char **listening
= NULL
, **triggered
= NULL
;
1015 if (!endswith(u
->id
, ".socket"))
1018 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
1022 c
= get_listening(bus
, u
->unit_path
, &listening
);
1028 if (!GREEDY_REALLOC(socket_infos
, size
, cs
+ c
)) {
1033 for (i
= 0; i
< c
; i
++)
1034 socket_infos
[cs
+ i
] = (struct socket_info
) {
1035 .machine
= u
->machine
,
1037 .type
= listening
[i
*2],
1038 .path
= listening
[i
*2 + 1],
1039 .triggered
= triggered
,
1040 .own_triggered
= i
==0,
1043 /* from this point on we will cleanup those socket_infos */
1046 listening
= triggered
= NULL
; /* avoid cleanup */
1049 qsort_safe(socket_infos
, cs
, sizeof(struct socket_info
),
1050 (__compar_fn_t
) socket_info_compare
);
1052 output_sockets_list(socket_infos
, cs
);
1055 assert(cs
== 0 || socket_infos
);
1056 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
1059 if (s
->own_triggered
)
1060 strv_free(s
->triggered
);
1066 static int get_next_elapse(
1069 dual_timestamp
*next
) {
1071 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1079 r
= sd_bus_get_property_trivial(
1081 "org.freedesktop.systemd1",
1083 "org.freedesktop.systemd1.Timer",
1084 "NextElapseUSecMonotonic",
1089 return log_error_errno(r
, "Failed to get next elapse time: %s", bus_error_message(&error
, r
));
1091 r
= sd_bus_get_property_trivial(
1093 "org.freedesktop.systemd1",
1095 "org.freedesktop.systemd1.Timer",
1096 "NextElapseUSecRealtime",
1101 return log_error_errno(r
, "Failed to get next elapse time: %s", bus_error_message(&error
, r
));
1107 static int get_last_trigger(
1112 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1119 r
= sd_bus_get_property_trivial(
1121 "org.freedesktop.systemd1",
1123 "org.freedesktop.systemd1.Timer",
1129 return log_error_errno(r
, "Failed to get last trigger time: %s", bus_error_message(&error
, r
));
1135 const char* machine
;
1138 usec_t last_trigger
;
1142 static int timer_info_compare(const struct timer_info
*a
, const struct timer_info
*b
) {
1148 if (!a
->machine
&& b
->machine
)
1150 if (a
->machine
&& !b
->machine
)
1152 if (a
->machine
&& b
->machine
) {
1153 o
= strcasecmp(a
->machine
, b
->machine
);
1158 if (a
->next_elapse
< b
->next_elapse
)
1160 if (a
->next_elapse
> b
->next_elapse
)
1163 return strcmp(a
->id
, b
->id
);
1166 static int output_timers_list(struct timer_info
*timer_infos
, unsigned n
) {
1167 struct timer_info
*t
;
1169 nextlen
= STRLEN("NEXT"),
1170 leftlen
= STRLEN("LEFT"),
1171 lastlen
= STRLEN("LAST"),
1172 passedlen
= STRLEN("PASSED"),
1173 unitlen
= STRLEN("UNIT"),
1174 activatelen
= STRLEN("ACTIVATES");
1176 const char *on
, *off
;
1178 assert(timer_infos
|| n
== 0);
1180 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1184 if (t
->next_elapse
> 0) {
1185 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1187 format_timestamp(tstamp
, sizeof(tstamp
), t
->next_elapse
);
1188 nextlen
= MAX(nextlen
, strlen(tstamp
) + 1);
1190 format_timestamp_relative(trel
, sizeof(trel
), t
->next_elapse
);
1191 leftlen
= MAX(leftlen
, strlen(trel
));
1194 if (t
->last_trigger
> 0) {
1195 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1197 format_timestamp(tstamp
, sizeof(tstamp
), t
->last_trigger
);
1198 lastlen
= MAX(lastlen
, strlen(tstamp
) + 1);
1200 format_timestamp_relative(trel
, sizeof(trel
), t
->last_trigger
);
1201 passedlen
= MAX(passedlen
, strlen(trel
));
1204 unitlen
= MAX(unitlen
, strlen(t
->id
) + (t
->machine
? strlen(t
->machine
)+1 : 0));
1206 STRV_FOREACH(a
, t
->triggered
)
1207 ul
+= strlen(*a
) + 2*(a
!= t
->triggered
);
1209 activatelen
= MAX(activatelen
, ul
);
1214 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1218 passedlen
, "PASSED",
1222 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1223 _cleanup_free_
char *j
= NULL
;
1225 char tstamp1
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel1
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1226 char tstamp2
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel2
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1229 format_timestamp(tstamp1
, sizeof(tstamp1
), t
->next_elapse
);
1230 format_timestamp_relative(trel1
, sizeof(trel1
), t
->next_elapse
);
1232 format_timestamp(tstamp2
, sizeof(tstamp2
), t
->last_trigger
);
1233 format_timestamp_relative(trel2
, sizeof(trel2
), t
->last_trigger
);
1236 j
= strjoin(t
->machine
, ":", t
->id
);
1243 printf("%-*s %-*s %-*s %-*s %-*s",
1244 nextlen
, tstamp1
, leftlen
, trel1
, lastlen
, tstamp2
, passedlen
, trel2
, unitlen
, unit
);
1246 STRV_FOREACH(a
, t
->triggered
)
1248 a
== t
->triggered
? "" : ",", *a
);
1252 on
= ansi_highlight();
1253 off
= ansi_normal();
1257 on
= ansi_highlight_red();
1258 off
= ansi_normal();
1261 if (!arg_no_legend
) {
1262 printf("%s%u timers listed.%s\n", on
, n
, off
);
1264 printf("Pass --all to see loaded but inactive timers, too.\n");
1270 static usec_t
calc_next_elapse(dual_timestamp
*nw
, dual_timestamp
*next
) {
1276 if (next
->monotonic
!= USEC_INFINITY
&& next
->monotonic
> 0) {
1279 if (next
->monotonic
> nw
->monotonic
)
1280 converted
= nw
->realtime
+ (next
->monotonic
- nw
->monotonic
);
1282 converted
= nw
->realtime
- (nw
->monotonic
- next
->monotonic
);
1284 if (next
->realtime
!= USEC_INFINITY
&& next
->realtime
> 0)
1285 next_elapse
= MIN(converted
, next
->realtime
);
1287 next_elapse
= converted
;
1290 next_elapse
= next
->realtime
;
1295 static int list_timers(int argc
, char *argv
[], void *userdata
) {
1296 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
1297 _cleanup_strv_free_
char **machines
= NULL
;
1298 _cleanup_free_
struct timer_info
*timer_infos
= NULL
;
1299 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
1300 struct timer_info
*t
;
1308 r
= acquire_bus(BUS_MANAGER
, &bus
);
1312 pager_open(arg_no_pager
, false);
1314 n
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
1318 dual_timestamp_get(&nw
);
1320 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
1321 _cleanup_strv_free_
char **triggered
= NULL
;
1322 dual_timestamp next
= DUAL_TIMESTAMP_NULL
;
1325 if (!endswith(u
->id
, ".timer"))
1328 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
1332 r
= get_next_elapse(bus
, u
->unit_path
, &next
);
1336 get_last_trigger(bus
, u
->unit_path
, &last
);
1338 if (!GREEDY_REALLOC(timer_infos
, size
, c
+1)) {
1343 m
= calc_next_elapse(&nw
, &next
);
1345 timer_infos
[c
++] = (struct timer_info
) {
1346 .machine
= u
->machine
,
1349 .last_trigger
= last
,
1350 .triggered
= triggered
,
1353 triggered
= NULL
; /* avoid cleanup */
1356 qsort_safe(timer_infos
, c
, sizeof(struct timer_info
),
1357 (__compar_fn_t
) timer_info_compare
);
1359 output_timers_list(timer_infos
, c
);
1362 for (t
= timer_infos
; t
< timer_infos
+ c
; t
++)
1363 strv_free(t
->triggered
);
1368 static int compare_unit_file_list(const void *a
, const void *b
) {
1369 const char *d1
, *d2
;
1370 const UnitFileList
*u
= a
, *v
= b
;
1372 d1
= strrchr(u
->path
, '.');
1373 d2
= strrchr(v
->path
, '.');
1378 r
= strcasecmp(d1
, d2
);
1383 return strcasecmp(basename(u
->path
), basename(v
->path
));
1386 static bool output_show_unit_file(const UnitFileList
*u
, char **states
, char **patterns
) {
1389 if (!strv_fnmatch_or_empty(patterns
, basename(u
->path
), FNM_NOESCAPE
))
1392 if (!strv_isempty(arg_types
)) {
1395 dot
= strrchr(u
->path
, '.');
1399 if (!strv_find(arg_types
, dot
+1))
1403 if (!strv_isempty(states
) &&
1404 !strv_find(states
, unit_file_state_to_string(u
->state
)))
1410 static void output_unit_file_list(const UnitFileList
*units
, unsigned c
) {
1411 unsigned max_id_len
, id_cols
, state_cols
;
1412 const UnitFileList
*u
;
1414 max_id_len
= STRLEN("UNIT FILE");
1415 state_cols
= STRLEN("STATE");
1417 for (u
= units
; u
< units
+ c
; u
++) {
1418 max_id_len
= MAX(max_id_len
, strlen(basename(u
->path
)));
1419 state_cols
= MAX(state_cols
, strlen(unit_file_state_to_string(u
->state
)));
1423 unsigned basic_cols
;
1425 id_cols
= MIN(max_id_len
, 25u);
1426 basic_cols
= 1 + id_cols
+ state_cols
;
1427 if (basic_cols
< (unsigned) columns())
1428 id_cols
+= MIN(columns() - basic_cols
, max_id_len
- id_cols
);
1430 id_cols
= max_id_len
;
1432 if (!arg_no_legend
&& c
> 0)
1433 printf("%s%-*s %-*s%s\n",
1435 id_cols
, "UNIT FILE",
1436 state_cols
, "STATE",
1439 for (u
= units
; u
< units
+ c
; u
++) {
1440 const char *on_underline
= NULL
, *on_color
= NULL
, *off
= NULL
, *id
;
1441 _cleanup_free_
char *e
= NULL
;
1444 underline
= u
+ 1 < units
+ c
&&
1445 !streq(unit_type_suffix(u
->path
), unit_type_suffix((u
+ 1)->path
));
1448 on_underline
= ansi_underline();
1450 if (IN_SET(u
->state
,
1452 UNIT_FILE_MASKED_RUNTIME
,
1455 on_color
= underline
? ansi_highlight_red_underline() : ansi_highlight_red();
1456 else if (u
->state
== UNIT_FILE_ENABLED
)
1457 on_color
= underline
? ansi_highlight_green_underline() : ansi_highlight_green();
1459 if (on_underline
|| on_color
)
1460 off
= ansi_normal();
1462 id
= basename(u
->path
);
1464 e
= arg_full
? NULL
: ellipsize(id
, id_cols
, 33);
1466 printf("%s%-*s %s%-*s%s\n",
1467 strempty(on_underline
),
1468 id_cols
, e
? e
: id
,
1469 strempty(on_color
), state_cols
, unit_file_state_to_string(u
->state
), strempty(off
));
1473 printf("\n%u unit files listed.\n", c
);
1476 static int list_unit_files(int argc
, char *argv
[], void *userdata
) {
1477 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1478 _cleanup_free_ UnitFileList
*units
= NULL
;
1485 bool fallback
= false;
1487 if (install_client_side()) {
1493 h
= hashmap_new(&string_hash_ops
);
1497 r
= unit_file_get_list(arg_scope
, arg_root
, h
, arg_states
, strv_skip(argv
, 1));
1499 unit_file_list_free(h
);
1500 return log_error_errno(r
, "Failed to get unit file list: %m");
1503 n_units
= hashmap_size(h
);
1505 units
= new(UnitFileList
, n_units
?: 1); /* avoid malloc(0) */
1507 unit_file_list_free(h
);
1511 HASHMAP_FOREACH(u
, h
, i
) {
1512 if (!output_show_unit_file(u
, NULL
, NULL
))
1519 assert(c
<= n_units
);
1524 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
1525 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1528 r
= acquire_bus(BUS_MANAGER
, &bus
);
1532 r
= sd_bus_message_new_method_call(
1535 "org.freedesktop.systemd1",
1536 "/org/freedesktop/systemd1",
1537 "org.freedesktop.systemd1.Manager",
1538 "ListUnitFilesByPatterns");
1540 return bus_log_create_error(r
);
1542 r
= sd_bus_message_append_strv(m
, arg_states
);
1544 return bus_log_create_error(r
);
1546 r
= sd_bus_message_append_strv(m
, strv_skip(argv
, 1));
1548 return bus_log_create_error(r
);
1550 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
1551 if (r
< 0 && sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_METHOD
)) {
1552 /* Fallback to legacy ListUnitFiles method */
1554 log_debug_errno(r
, "Failed to list unit files: %s Falling back to ListUnitsFiles method.", bus_error_message(&error
, r
));
1555 m
= sd_bus_message_unref(m
);
1556 sd_bus_error_free(&error
);
1558 r
= sd_bus_message_new_method_call(
1561 "org.freedesktop.systemd1",
1562 "/org/freedesktop/systemd1",
1563 "org.freedesktop.systemd1.Manager",
1566 return bus_log_create_error(r
);
1568 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
1571 return log_error_errno(r
, "Failed to list unit files: %s", bus_error_message(&error
, r
));
1573 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
1575 return bus_log_parse_error(r
);
1577 while ((r
= sd_bus_message_read(reply
, "(ss)", &path
, &state
)) > 0) {
1579 if (!GREEDY_REALLOC(units
, size
, c
+ 1))
1582 units
[c
] = (struct UnitFileList
) {
1584 unit_file_state_from_string(state
)
1587 if (output_show_unit_file(&units
[c
],
1588 fallback
? arg_states
: NULL
,
1589 fallback
? strv_skip(argv
, 1) : NULL
))
1594 return bus_log_parse_error(r
);
1596 r
= sd_bus_message_exit_container(reply
);
1598 return bus_log_parse_error(r
);
1601 pager_open(arg_no_pager
, false);
1603 qsort_safe(units
, c
, sizeof(UnitFileList
), compare_unit_file_list
);
1604 output_unit_file_list(units
, c
);
1606 if (install_client_side())
1607 for (unit
= units
; unit
< units
+ c
; unit
++)
1613 static int list_dependencies_print(const char *name
, int level
, unsigned int branches
, bool last
) {
1614 _cleanup_free_
char *n
= NULL
;
1615 size_t max_len
= MAX(columns(),20u);
1621 for (i
= level
- 1; i
>= 0; i
--) {
1623 if (len
> max_len
- 3 && !arg_full
) {
1624 printf("%s...\n",max_len
% 2 ? "" : " ");
1627 printf("%s", special_glyph(branches
& (1 << i
) ? TREE_VERTICAL
: TREE_SPACE
));
1631 if (len
> max_len
- 3 && !arg_full
) {
1632 printf("%s...\n",max_len
% 2 ? "" : " ");
1636 printf("%s", special_glyph(last
? TREE_RIGHT
: TREE_BRANCH
));
1640 printf("%s\n", name
);
1644 n
= ellipsize(name
, max_len
-len
, 100);
1652 static int list_dependencies_get_dependencies(sd_bus
*bus
, const char *name
, char ***deps
) {
1654 static const char *dependencies
[_DEPENDENCY_MAX
] = {
1655 [DEPENDENCY_FORWARD
] = "Requires\0"
1660 [DEPENDENCY_REVERSE
] = "RequiredBy\0"
1665 [DEPENDENCY_AFTER
] = "After\0",
1666 [DEPENDENCY_BEFORE
] = "Before\0",
1669 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1670 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1671 _cleanup_strv_free_
char **ret
= NULL
;
1672 _cleanup_free_
char *path
= NULL
;
1678 assert_cc(ELEMENTSOF(dependencies
) == _DEPENDENCY_MAX
);
1680 path
= unit_dbus_path_from_name(name
);
1684 r
= sd_bus_call_method(
1686 "org.freedesktop.systemd1",
1688 "org.freedesktop.DBus.Properties",
1692 "s", "org.freedesktop.systemd1.Unit");
1694 return log_error_errno(r
, "Failed to get properties of %s: %s", name
, bus_error_message(&error
, r
));
1696 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
1698 return bus_log_parse_error(r
);
1700 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
1703 r
= sd_bus_message_read(reply
, "s", &prop
);
1705 return bus_log_parse_error(r
);
1707 if (!nulstr_contains(dependencies
[arg_dependency
], prop
)) {
1708 r
= sd_bus_message_skip(reply
, "v");
1710 return bus_log_parse_error(r
);
1713 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, "as");
1715 return bus_log_parse_error(r
);
1717 r
= bus_message_read_strv_extend(reply
, &ret
);
1719 return bus_log_parse_error(r
);
1721 r
= sd_bus_message_exit_container(reply
);
1723 return bus_log_parse_error(r
);
1726 r
= sd_bus_message_exit_container(reply
);
1728 return bus_log_parse_error(r
);
1732 return bus_log_parse_error(r
);
1734 r
= sd_bus_message_exit_container(reply
);
1736 return bus_log_parse_error(r
);
1738 *deps
= strv_uniq(ret
);
1744 static int list_dependencies_compare(const void *_a
, const void *_b
) {
1745 const char **a
= (const char**) _a
, **b
= (const char**) _b
;
1747 if (unit_name_to_type(*a
) == UNIT_TARGET
&& unit_name_to_type(*b
) != UNIT_TARGET
)
1749 if (unit_name_to_type(*a
) != UNIT_TARGET
&& unit_name_to_type(*b
) == UNIT_TARGET
)
1752 return strcasecmp(*a
, *b
);
1755 static int list_dependencies_one(
1760 unsigned int branches
) {
1762 _cleanup_strv_free_
char **deps
= NULL
;
1770 r
= strv_extend(units
, name
);
1774 r
= list_dependencies_get_dependencies(bus
, name
, &deps
);
1778 qsort_safe(deps
, strv_length(deps
), sizeof (char*), list_dependencies_compare
);
1780 STRV_FOREACH(c
, deps
) {
1781 if (strv_contains(*units
, *c
)) {
1784 r
= list_dependencies_print("...", level
+ 1, (branches
<< 1) | (c
[1] == NULL
? 0 : 1), 1);
1794 UnitActiveState active_state
= _UNIT_ACTIVE_STATE_INVALID
;
1797 (void) get_state_one_unit(bus
, *c
, &active_state
);
1799 switch (active_state
) {
1801 case UNIT_RELOADING
:
1802 case UNIT_ACTIVATING
:
1803 on
= ansi_highlight_green();
1807 case UNIT_DEACTIVATING
:
1812 on
= ansi_highlight_red();
1816 printf("%s%s%s ", on
, special_glyph(BLACK_CIRCLE
), ansi_normal());
1819 r
= list_dependencies_print(*c
, level
, branches
, c
[1] == NULL
);
1823 if (arg_all
|| unit_name_to_type(*c
) == UNIT_TARGET
) {
1824 r
= list_dependencies_one(bus
, *c
, level
+ 1, units
, (branches
<< 1) | (c
[1] == NULL
? 0 : 1));
1831 strv_remove(*units
, name
);
1836 static int list_dependencies(int argc
, char *argv
[], void *userdata
) {
1837 _cleanup_strv_free_
char **units
= NULL
;
1838 _cleanup_free_
char *unit
= NULL
;
1844 r
= unit_name_mangle(argv
[1], UNIT_NAME_NOGLOB
, &unit
);
1846 return log_error_errno(r
, "Failed to mangle unit name: %m");
1850 u
= SPECIAL_DEFAULT_TARGET
;
1852 r
= acquire_bus(BUS_MANAGER
, &bus
);
1856 pager_open(arg_no_pager
, false);
1860 return list_dependencies_one(bus
, u
, 0, &units
, 0);
1863 struct machine_info
{
1867 char *control_group
;
1868 uint32_t n_failed_units
;
1873 static const struct bus_properties_map machine_info_property_map
[] = {
1874 { "SystemState", "s", NULL
, offsetof(struct machine_info
, state
) },
1875 { "NJobs", "u", NULL
, offsetof(struct machine_info
, n_jobs
) },
1876 { "NFailedUnits", "u", NULL
, offsetof(struct machine_info
, n_failed_units
) },
1877 { "ControlGroup", "s", NULL
, offsetof(struct machine_info
, control_group
) },
1878 { "UserspaceTimestamp", "t", NULL
, offsetof(struct machine_info
, timestamp
) },
1882 static void machine_info_clear(struct machine_info
*info
) {
1887 free(info
->control_group
);
1891 static void free_machines_list(struct machine_info
*machine_infos
, int n
) {
1897 for (i
= 0; i
< n
; i
++)
1898 machine_info_clear(&machine_infos
[i
]);
1900 free(machine_infos
);
1903 static int compare_machine_info(const void *a
, const void *b
) {
1904 const struct machine_info
*u
= a
, *v
= b
;
1906 if (u
->is_host
!= v
->is_host
)
1907 return u
->is_host
> v
->is_host
? -1 : 1;
1909 return strcasecmp(u
->name
, v
->name
);
1912 static int get_machine_properties(sd_bus
*bus
, struct machine_info
*mi
) {
1913 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*container
= NULL
;
1919 r
= sd_bus_open_system_machine(&container
, mi
->name
);
1926 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, NULL
, mi
);
1933 static bool output_show_machine(const char *name
, char **patterns
) {
1934 return strv_fnmatch_or_empty(patterns
, name
, FNM_NOESCAPE
);
1937 static int get_machine_list(
1939 struct machine_info
**_machine_infos
,
1942 struct machine_info
*machine_infos
= NULL
;
1943 _cleanup_strv_free_
char **m
= NULL
;
1944 _cleanup_free_
char *hn
= NULL
;
1949 hn
= gethostname_malloc();
1953 if (output_show_machine(hn
, patterns
)) {
1954 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1))
1957 machine_infos
[c
].is_host
= true;
1958 machine_infos
[c
].name
= hn
;
1961 (void) get_machine_properties(bus
, &machine_infos
[c
]);
1965 r
= sd_get_machine_names(&m
);
1967 return log_error_errno(r
, "Failed to get machine list: %m");
1969 STRV_FOREACH(i
, m
) {
1970 _cleanup_free_
char *class = NULL
;
1972 if (!output_show_machine(*i
, patterns
))
1975 sd_machine_get_class(*i
, &class);
1976 if (!streq_ptr(class, "container"))
1979 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1)) {
1980 free_machines_list(machine_infos
, c
);
1984 machine_infos
[c
].is_host
= false;
1985 machine_infos
[c
].name
= strdup(*i
);
1986 if (!machine_infos
[c
].name
) {
1987 free_machines_list(machine_infos
, c
);
1991 (void) get_machine_properties(NULL
, &machine_infos
[c
]);
1995 *_machine_infos
= machine_infos
;
1999 static void output_machines_list(struct machine_info
*machine_infos
, unsigned n
) {
2000 struct machine_info
*m
;
2003 namelen
= STRLEN("NAME"),
2004 statelen
= STRLEN("STATE"),
2005 failedlen
= STRLEN("FAILED"),
2006 jobslen
= STRLEN("JOBS");
2008 assert(machine_infos
|| n
== 0);
2010 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
2011 namelen
= MAX(namelen
,
2012 strlen(m
->name
) + (m
->is_host
? STRLEN(" (host)") : 0));
2013 statelen
= MAX(statelen
, strlen_ptr(m
->state
));
2014 failedlen
= MAX(failedlen
, DECIMAL_STR_WIDTH(m
->n_failed_units
));
2015 jobslen
= MAX(jobslen
, DECIMAL_STR_WIDTH(m
->n_jobs
));
2017 if (!arg_plain
&& !streq_ptr(m
->state
, "running"))
2021 if (!arg_no_legend
) {
2025 printf("%-*s %-*s %-*s %-*s\n",
2028 failedlen
, "FAILED",
2032 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
2033 const char *on_state
= "", *off_state
= "";
2034 const char *on_failed
= "", *off_failed
= "";
2035 bool circle
= false;
2037 if (streq_ptr(m
->state
, "degraded")) {
2038 on_state
= ansi_highlight_red();
2039 off_state
= ansi_normal();
2041 } else if (!streq_ptr(m
->state
, "running")) {
2042 on_state
= ansi_highlight_yellow();
2043 off_state
= ansi_normal();
2047 if (m
->n_failed_units
> 0) {
2048 on_failed
= ansi_highlight_red();
2049 off_failed
= ansi_normal();
2051 on_failed
= off_failed
= "";
2054 printf("%s%s%s ", on_state
, circle
? special_glyph(BLACK_CIRCLE
) : " ", off_state
);
2057 printf("%-*s (host) %s%-*s%s %s%*" PRIu32
"%s %*" PRIu32
"\n",
2058 (int) (namelen
- (STRLEN(" (host)"))),
2060 on_state
, statelen
, strna(m
->state
), off_state
,
2061 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
2062 jobslen
, m
->n_jobs
);
2064 printf("%-*s %s%-*s%s %s%*" PRIu32
"%s %*" PRIu32
"\n",
2065 namelen
, strna(m
->name
),
2066 on_state
, statelen
, strna(m
->state
), off_state
,
2067 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
2068 jobslen
, m
->n_jobs
);
2072 printf("\n%u machines listed.\n", n
);
2075 static int list_machines(int argc
, char *argv
[], void *userdata
) {
2076 struct machine_info
*machine_infos
= NULL
;
2080 r
= acquire_bus(BUS_MANAGER
, &bus
);
2084 r
= get_machine_list(bus
, &machine_infos
, strv_skip(argv
, 1));
2088 pager_open(arg_no_pager
, false);
2090 qsort_safe(machine_infos
, r
, sizeof(struct machine_info
), compare_machine_info
);
2091 output_machines_list(machine_infos
, r
);
2092 free_machines_list(machine_infos
, r
);
2097 static int get_default(int argc
, char *argv
[], void *userdata
) {
2098 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2099 _cleanup_free_
char *_path
= NULL
;
2103 if (install_client_side()) {
2104 r
= unit_file_get_default(arg_scope
, arg_root
, &_path
);
2106 return log_error_errno(r
, "Failed to get default target: %m");
2111 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2114 r
= acquire_bus(BUS_MANAGER
, &bus
);
2118 r
= sd_bus_call_method(
2120 "org.freedesktop.systemd1",
2121 "/org/freedesktop/systemd1",
2122 "org.freedesktop.systemd1.Manager",
2128 return log_error_errno(r
, "Failed to get default target: %s", bus_error_message(&error
, r
));
2130 r
= sd_bus_message_read(reply
, "s", &path
);
2132 return bus_log_parse_error(r
);
2136 printf("%s\n", path
);
2141 static int set_default(int argc
, char *argv
[], void *userdata
) {
2142 _cleanup_free_
char *unit
= NULL
;
2143 UnitFileChange
*changes
= NULL
;
2144 unsigned n_changes
= 0;
2150 r
= unit_name_mangle_with_suffix(argv
[1], UNIT_NAME_NOGLOB
, ".target", &unit
);
2152 return log_error_errno(r
, "Failed to mangle unit name: %m");
2154 if (install_client_side()) {
2155 r
= unit_file_set_default(arg_scope
, UNIT_FILE_FORCE
, arg_root
, unit
, &changes
, &n_changes
);
2156 unit_file_dump_changes(r
, "set default", changes
, n_changes
, arg_quiet
);
2161 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2162 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2165 polkit_agent_open_maybe();
2167 r
= acquire_bus(BUS_MANAGER
, &bus
);
2171 r
= sd_bus_call_method(
2173 "org.freedesktop.systemd1",
2174 "/org/freedesktop/systemd1",
2175 "org.freedesktop.systemd1.Manager",
2181 return log_error_errno(r
, "Failed to set default target: %s", bus_error_message(&error
, r
));
2183 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
2187 /* Try to reload if enabled */
2189 r
= daemon_reload(argc
, argv
, userdata
);
2195 unit_file_changes_free(changes
, n_changes
);
2200 static int output_waiting_jobs(sd_bus
*bus
, uint32_t id
, const char *method
, const char *prefix
) {
2201 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2202 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2203 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2209 r
= sd_bus_call_method(
2211 "org.freedesktop.systemd1",
2212 "/org/freedesktop/systemd1",
2213 "org.freedesktop.systemd1.Manager",
2219 return log_debug_errno(r
, "Failed to get waiting jobs for job %" PRIu32
, id
);
2221 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2223 return bus_log_parse_error(r
);
2225 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &other_id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0)
2226 printf("%s %u (%s/%s)\n", prefix
, other_id
, name
, type
);
2228 return bus_log_parse_error(r
);
2230 r
= sd_bus_message_exit_container(reply
);
2232 return bus_log_parse_error(r
);
2239 const char *name
, *type
, *state
;
2242 static void output_jobs_list(sd_bus
*bus
, const struct job_info
* jobs
, unsigned n
, bool skipped
) {
2243 unsigned id_len
, unit_len
, type_len
, state_len
;
2244 const struct job_info
*j
;
2245 const char *on
, *off
;
2246 bool shorten
= false;
2248 assert(n
== 0 || jobs
);
2251 if (!arg_no_legend
) {
2252 on
= ansi_highlight_green();
2253 off
= ansi_normal();
2255 printf("%sNo jobs %s.%s\n", on
, skipped
? "listed" : "running", off
);
2260 pager_open(arg_no_pager
, false);
2262 id_len
= STRLEN("JOB");
2263 unit_len
= STRLEN("UNIT");
2264 type_len
= STRLEN("TYPE");
2265 state_len
= STRLEN("STATE");
2267 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2268 uint32_t id
= j
->id
;
2269 assert(j
->name
&& j
->type
&& j
->state
);
2271 id_len
= MAX(id_len
, DECIMAL_STR_WIDTH(id
));
2272 unit_len
= MAX(unit_len
, strlen(j
->name
));
2273 type_len
= MAX(type_len
, strlen(j
->type
));
2274 state_len
= MAX(state_len
, strlen(j
->state
));
2277 if (!arg_full
&& id_len
+ 1 + unit_len
+ type_len
+ 1 + state_len
> columns()) {
2278 unit_len
= MAX(33u, columns() - id_len
- type_len
- state_len
- 3);
2283 printf("%*s %-*s %-*s %-*s\n",
2287 state_len
, "STATE");
2289 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2290 _cleanup_free_
char *e
= NULL
;
2292 if (streq(j
->state
, "running")) {
2293 on
= ansi_highlight();
2294 off
= ansi_normal();
2298 e
= shorten
? ellipsize(j
->name
, unit_len
, 33) : NULL
;
2299 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2301 on
, unit_len
, e
? e
: j
->name
, off
,
2303 on
, state_len
, j
->state
, off
);
2306 output_waiting_jobs(bus
, j
->id
, "GetJobAfter", "\twaiting for job");
2307 if (arg_jobs_before
)
2308 output_waiting_jobs(bus
, j
->id
, "GetJobBefore", "\tblocking job");
2311 if (!arg_no_legend
) {
2312 on
= ansi_highlight();
2313 off
= ansi_normal();
2315 printf("\n%s%u jobs listed%s.\n", on
, n
, off
);
2319 static bool output_show_job(struct job_info
*job
, char **patterns
) {
2320 return strv_fnmatch_or_empty(patterns
, job
->name
, FNM_NOESCAPE
);
2323 static int list_jobs(int argc
, char *argv
[], void *userdata
) {
2324 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2325 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2326 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2327 _cleanup_free_
struct job_info
*jobs
= NULL
;
2333 bool skipped
= false;
2335 r
= acquire_bus(BUS_MANAGER
, &bus
);
2339 r
= sd_bus_call_method(
2341 "org.freedesktop.systemd1",
2342 "/org/freedesktop/systemd1",
2343 "org.freedesktop.systemd1.Manager",
2349 return log_error_errno(r
, "Failed to list jobs: %s", bus_error_message(&error
, r
));
2351 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2353 return bus_log_parse_error(r
);
2355 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0) {
2356 struct job_info job
= { id
, name
, type
, state
};
2358 if (!output_show_job(&job
, strv_skip(argv
, 1))) {
2363 if (!GREEDY_REALLOC(jobs
, size
, c
+ 1))
2369 return bus_log_parse_error(r
);
2371 r
= sd_bus_message_exit_container(reply
);
2373 return bus_log_parse_error(r
);
2375 pager_open(arg_no_pager
, false);
2377 output_jobs_list(bus
, jobs
, c
, skipped
);
2381 static int cancel_job(int argc
, char *argv
[], void *userdata
) {
2387 return trivial_method(argc
, argv
, userdata
);
2389 r
= acquire_bus(BUS_MANAGER
, &bus
);
2393 polkit_agent_open_maybe();
2395 STRV_FOREACH(name
, strv_skip(argv
, 1)) {
2396 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2400 q
= safe_atou32(*name
, &id
);
2402 return log_error_errno(q
, "Failed to parse job id \"%s\": %m", *name
);
2404 q
= sd_bus_call_method(
2406 "org.freedesktop.systemd1",
2407 "/org/freedesktop/systemd1",
2408 "org.freedesktop.systemd1.Manager",
2414 log_error_errno(q
, "Failed to cancel job %"PRIu32
": %s", id
, bus_error_message(&error
, q
));
2423 static int need_daemon_reload(sd_bus
*bus
, const char *unit
) {
2424 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2428 /* We ignore all errors here, since this is used to show a
2431 /* We don't use unit_dbus_path_from_name() directly since we
2432 * don't want to load the unit if it isn't loaded. */
2434 r
= sd_bus_call_method(
2436 "org.freedesktop.systemd1",
2437 "/org/freedesktop/systemd1",
2438 "org.freedesktop.systemd1.Manager",
2446 r
= sd_bus_message_read(reply
, "o", &path
);
2450 r
= sd_bus_get_property_trivial(
2452 "org.freedesktop.systemd1",
2454 "org.freedesktop.systemd1.Unit",
2464 static void warn_unit_file_changed(const char *name
) {
2467 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.",
2468 ansi_highlight_red(),
2471 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user");
2474 static int unit_file_find_path(LookupPaths
*lp
, const char *unit_name
, char **unit_path
) {
2480 STRV_FOREACH(p
, lp
->search_path
) {
2481 _cleanup_free_
char *path
= NULL
, *lpath
= NULL
;
2484 path
= path_join(NULL
, *p
, unit_name
);
2488 r
= chase_symlinks(path
, arg_root
, 0, &lpath
);
2494 return log_error_errno(r
, "Failed to access path '%s': %m", path
);
2506 static int unit_find_template_path(
2507 const char *unit_name
,
2509 char **fragment_path
,
2512 _cleanup_free_
char *_template
= NULL
;
2515 /* Returns 1 if a fragment was found, 0 if not found, negative on error. */
2517 r
= unit_file_find_path(lp
, unit_name
, fragment_path
);
2519 return r
; /* error or found a real unit */
2521 r
= unit_name_template(unit_name
, &_template
);
2523 return 0; /* not a template, does not exist */
2525 return log_error_errno(r
, "Failed to determine template name: %m");
2527 r
= unit_file_find_path(lp
, _template
, fragment_path
);
2532 *template = _template
;
2538 static int unit_find_paths(
2540 const char *unit_name
,
2542 char **fragment_path
,
2543 char ***dropin_paths
) {
2545 _cleanup_free_
char *path
= NULL
;
2546 _cleanup_strv_free_
char **dropins
= NULL
;
2550 * Finds where the unit is defined on disk. Returns 0 if the unit
2551 * is not found. Returns 1 if it is found, and sets
2552 * - the path to the unit in *path, if it exists on disk,
2553 * - and a strv of existing drop-ins in *dropins,
2554 * if the arg is not NULL and any dropins were found.
2558 assert(fragment_path
);
2561 if (!install_client_side() && !unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
2562 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2563 _cleanup_free_
char *unit
= NULL
;
2565 unit
= unit_dbus_path_from_name(unit_name
);
2569 r
= sd_bus_get_property_string(
2571 "org.freedesktop.systemd1",
2573 "org.freedesktop.systemd1.Unit",
2578 return log_error_errno(r
, "Failed to get FragmentPath: %s", bus_error_message(&error
, r
));
2581 r
= sd_bus_get_property_strv(
2583 "org.freedesktop.systemd1",
2585 "org.freedesktop.systemd1.Unit",
2590 return log_error_errno(r
, "Failed to get DropInPaths: %s", bus_error_message(&error
, r
));
2593 _cleanup_set_free_ Set
*names
= NULL
;
2594 _cleanup_free_
char *template = NULL
;
2596 names
= set_new(NULL
);
2600 r
= unit_find_template_path(unit_name
, lp
, &path
, &template);
2605 /* We found the unit file. If we followed symlinks, this name might be
2606 * different then the unit_name with started with. Look for dropins matching
2607 * that "final" name. */
2608 r
= set_put(names
, basename(path
));
2610 /* No unit file, let's look for dropins matching the original name.
2611 * systemd has fairly complicated rules (based on unit type and provenience),
2612 * which units are allowed not to have the main unit file. We err on the
2613 * side of including too many files, and always try to load dropins. */
2614 r
= set_put(names
, unit_name
);
2616 /* The cases where we allow a unit to exist without the main file are
2617 * never valid for templates. Don't try to load dropins in this case. */
2621 return log_error_errno(r
, "Failed to add unit name: %m");
2624 r
= unit_file_find_dropin_conf_paths(arg_root
, lp
->search_path
,
2625 NULL
, names
, &dropins
);
2633 if (!isempty(path
)) {
2634 *fragment_path
= path
;
2639 if (dropin_paths
&& !strv_isempty(dropins
)) {
2640 *dropin_paths
= dropins
;
2645 if (r
== 0 && !arg_force
)
2646 log_error("No files found for %s.", unit_name
);
2651 static int get_state_one_unit(sd_bus
*bus
, const char *name
, UnitActiveState
*active_state
) {
2652 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2653 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2654 _cleanup_free_
char *buf
= NULL
;
2655 UnitActiveState state
;
2660 assert(active_state
);
2662 /* We don't use unit_dbus_path_from_name() directly since we don't want to load the unit unnecessarily, if it
2664 r
= sd_bus_call_method(
2666 "org.freedesktop.systemd1",
2667 "/org/freedesktop/systemd1",
2668 "org.freedesktop.systemd1.Manager",
2674 if (!sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_UNIT
))
2675 return log_error_errno(r
, "Failed to retrieve unit: %s", bus_error_message(&error
, r
));
2677 /* The unit is currently not loaded, hence say it's "inactive", since all units that aren't loaded are
2678 * considered inactive. */
2679 state
= UNIT_INACTIVE
;
2682 r
= sd_bus_message_read(reply
, "o", &path
);
2684 return bus_log_parse_error(r
);
2686 r
= sd_bus_get_property_string(
2688 "org.freedesktop.systemd1",
2690 "org.freedesktop.systemd1.Unit",
2695 return log_error_errno(r
, "Failed to retrieve unit state: %s", bus_error_message(&error
, r
));
2697 state
= unit_active_state_from_string(buf
);
2698 if (state
== _UNIT_ACTIVE_STATE_INVALID
) {
2699 log_error("Invalid unit state '%s' for: %s", buf
, name
);
2704 *active_state
= state
;
2708 static int check_triggering_units(
2712 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2713 _cleanup_free_
char *path
= NULL
, *n
= NULL
, *load_state
= NULL
;
2714 _cleanup_strv_free_
char **triggered_by
= NULL
;
2715 bool print_warning_label
= true;
2716 UnitActiveState active_state
;
2720 r
= unit_name_mangle(name
, UNIT_NAME_NOGLOB
, &n
);
2722 return log_error_errno(r
, "Failed to mangle unit name: %m");
2724 path
= unit_dbus_path_from_name(n
);
2728 r
= sd_bus_get_property_string(
2730 "org.freedesktop.systemd1",
2732 "org.freedesktop.systemd1.Unit",
2737 return log_error_errno(r
, "Failed to get load state of %s: %s", n
, bus_error_message(&error
, r
));
2739 if (streq(load_state
, "masked"))
2742 r
= sd_bus_get_property_strv(
2744 "org.freedesktop.systemd1",
2746 "org.freedesktop.systemd1.Unit",
2751 return log_error_errno(r
, "Failed to get triggered by array of %s: %s", n
, bus_error_message(&error
, r
));
2753 STRV_FOREACH(i
, triggered_by
) {
2754 r
= get_state_one_unit(bus
, *i
, &active_state
);
2758 if (!IN_SET(active_state
, UNIT_ACTIVE
, UNIT_RELOADING
))
2761 if (print_warning_label
) {
2762 log_warning("Warning: Stopping %s, but it can still be activated by:", n
);
2763 print_warning_label
= false;
2766 log_warning(" %s", *i
);
2772 static const struct {
2775 } unit_actions
[] = {
2776 { "start", "StartUnit" },
2777 { "stop", "StopUnit" },
2778 { "condstop", "StopUnit" },
2779 { "reload", "ReloadUnit" },
2780 { "restart", "RestartUnit" },
2781 { "try-restart", "TryRestartUnit" },
2782 { "condrestart", "TryRestartUnit" },
2783 { "reload-or-restart", "ReloadOrRestartUnit" },
2784 { "try-reload-or-restart", "ReloadOrTryRestartUnit" },
2785 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2786 { "condreload", "ReloadOrTryRestartUnit" },
2787 { "force-reload", "ReloadOrTryRestartUnit" }
2790 static const char *verb_to_method(const char *verb
) {
2793 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2794 if (streq_ptr(unit_actions
[i
].verb
, verb
))
2795 return unit_actions
[i
].method
;
2800 static const char *method_to_verb(const char *method
) {
2803 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2804 if (streq_ptr(unit_actions
[i
].method
, method
))
2805 return unit_actions
[i
].verb
;
2817 static void wait_context_free(WaitContext
*c
) {
2818 c
->match
= sd_bus_slot_unref(c
->match
);
2819 c
->event
= sd_event_unref(c
->event
);
2820 c
->unit_paths
= set_free_free(c
->unit_paths
);
2823 static int on_properties_changed(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
2824 WaitContext
*c
= userdata
;
2828 path
= sd_bus_message_get_path(m
);
2829 if (!set_contains(c
->unit_paths
, path
))
2832 /* Check if ActiveState changed to inactive/failed */
2833 /* (s interface, a{sv} changed_properties, as invalidated_properties) */
2834 r
= sd_bus_message_skip(m
, "s");
2836 return bus_log_parse_error(r
);
2838 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "{sv}");
2840 return bus_log_parse_error(r
);
2842 while ((r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
2845 r
= sd_bus_message_read(m
, "s", &s
);
2847 return bus_log_parse_error(r
);
2849 if (streq(s
, "ActiveState")) {
2852 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, "s");
2854 return bus_log_parse_error(r
);
2856 r
= sd_bus_message_read(m
, "s", &s
);
2858 return bus_log_parse_error(r
);
2860 is_failed
= streq(s
, "failed");
2861 if (streq(s
, "inactive") || is_failed
) {
2862 log_debug("%s became %s, dropping from --wait tracking", path
, s
);
2863 free(set_remove(c
->unit_paths
, path
));
2864 c
->any_failed
= c
->any_failed
|| is_failed
;
2866 log_debug("ActiveState on %s changed to %s", path
, s
);
2868 break; /* no need to dissect the rest of the message */
2870 /* other property */
2871 r
= sd_bus_message_skip(m
, "v");
2873 return bus_log_parse_error(r
);
2875 r
= sd_bus_message_exit_container(m
);
2877 return bus_log_parse_error(r
);
2880 return bus_log_parse_error(r
);
2882 if (set_isempty(c
->unit_paths
))
2883 sd_event_exit(c
->event
, EXIT_SUCCESS
);
2888 static int start_unit_one(
2893 sd_bus_error
*error
,
2895 WaitContext
*wait_context
) {
2897 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2907 _cleanup_free_
char *unit_path
= NULL
;
2910 log_debug("Watching for property changes of %s", name
);
2911 r
= sd_bus_call_method(
2913 "org.freedesktop.systemd1",
2914 "/org/freedesktop/systemd1",
2915 "org.freedesktop.systemd1.Manager",
2921 return log_error_errno(r
, "Failed to RefUnit %s: %s", name
, bus_error_message(error
, r
));
2923 unit_path
= unit_dbus_path_from_name(name
);
2927 r
= set_put_strdup(wait_context
->unit_paths
, unit_path
);
2929 return log_error_errno(r
, "Failed to add unit path %s to set: %m", unit_path
);
2931 mt
= strjoina("type='signal',"
2932 "interface='org.freedesktop.DBus.Properties',"
2933 "path='", unit_path
, "',"
2934 "member='PropertiesChanged'");
2935 r
= sd_bus_add_match(bus
, &wait_context
->match
, mt
, on_properties_changed
, wait_context
);
2937 return log_error_errno(r
, "Failed to add match for PropertiesChanged signal: %m");
2940 log_debug("%s manager for %s on %s, %s",
2941 arg_dry_run
? "Would call" : "Calling",
2942 method
, name
, mode
);
2946 r
= sd_bus_call_method(
2948 "org.freedesktop.systemd1",
2949 "/org/freedesktop/systemd1",
2950 "org.freedesktop.systemd1.Manager",
2958 /* There's always a fallback possible for legacy actions. */
2959 if (arg_action
!= ACTION_SYSTEMCTL
)
2962 verb
= method_to_verb(method
);
2964 log_error("Failed to %s %s: %s", verb
, name
, bus_error_message(error
, r
));
2966 if (!sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) &&
2967 !sd_bus_error_has_name(error
, BUS_ERROR_UNIT_MASKED
))
2968 log_error("See %s logs and 'systemctl%s status%s %s' for details.",
2969 arg_scope
== UNIT_FILE_SYSTEM
? "system" : "user",
2970 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user",
2971 name
[0] == '-' ? " --" : "",
2977 r
= sd_bus_message_read(reply
, "o", &path
);
2979 return bus_log_parse_error(r
);
2981 if (need_daemon_reload(bus
, name
) > 0)
2982 warn_unit_file_changed(name
);
2985 log_debug("Adding %s to the set", path
);
2986 r
= bus_wait_for_jobs_add(w
, path
);
2994 static int expand_names(sd_bus
*bus
, char **names
, const char* suffix
, char ***ret
) {
2995 _cleanup_strv_free_
char **mangled
= NULL
, **globs
= NULL
;
3002 STRV_FOREACH(name
, names
) {
3006 r
= unit_name_mangle_with_suffix(*name
, UNIT_NAME_GLOB
, suffix
, &t
);
3008 r
= unit_name_mangle(*name
, UNIT_NAME_GLOB
, &t
);
3010 return log_error_errno(r
, "Failed to mangle name: %m");
3012 if (string_is_glob(t
))
3013 r
= strv_consume(&globs
, t
);
3015 r
= strv_consume(&mangled
, t
);
3020 /* Query the manager only if any of the names are a glob, since
3021 * this is fairly expensive */
3022 if (!strv_isempty(globs
)) {
3023 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
3024 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
3025 size_t allocated
, n
;
3027 r
= get_unit_list(bus
, NULL
, globs
, &unit_infos
, 0, &reply
);
3031 n
= strv_length(mangled
);
3034 for (i
= 0; i
< r
; i
++) {
3035 if (!GREEDY_REALLOC(mangled
, allocated
, n
+2))
3038 mangled
[n
] = strdup(unit_infos
[i
].id
);
3042 mangled
[++n
] = NULL
;
3047 mangled
= NULL
; /* do not free */
3052 static const struct {
3056 } action_table
[_ACTION_MAX
] = {
3057 [ACTION_HALT
] = { SPECIAL_HALT_TARGET
, "halt", "replace-irreversibly" },
3058 [ACTION_POWEROFF
] = { SPECIAL_POWEROFF_TARGET
, "poweroff", "replace-irreversibly" },
3059 [ACTION_REBOOT
] = { SPECIAL_REBOOT_TARGET
, "reboot", "replace-irreversibly" },
3060 [ACTION_KEXEC
] = { SPECIAL_KEXEC_TARGET
, "kexec", "replace-irreversibly" },
3061 [ACTION_RUNLEVEL2
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
3062 [ACTION_RUNLEVEL3
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
3063 [ACTION_RUNLEVEL4
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
3064 [ACTION_RUNLEVEL5
] = { SPECIAL_GRAPHICAL_TARGET
, NULL
, "isolate" },
3065 [ACTION_RESCUE
] = { SPECIAL_RESCUE_TARGET
, "rescue", "isolate" },
3066 [ACTION_EMERGENCY
] = { SPECIAL_EMERGENCY_TARGET
, "emergency", "isolate" },
3067 [ACTION_DEFAULT
] = { SPECIAL_DEFAULT_TARGET
, "default", "isolate" },
3068 [ACTION_EXIT
] = { SPECIAL_EXIT_TARGET
, "exit", "replace-irreversibly" },
3069 [ACTION_SUSPEND
] = { SPECIAL_SUSPEND_TARGET
, "suspend", "replace-irreversibly" },
3070 [ACTION_HIBERNATE
] = { SPECIAL_HIBERNATE_TARGET
, "hibernate", "replace-irreversibly" },
3071 [ACTION_HYBRID_SLEEP
] = { SPECIAL_HYBRID_SLEEP_TARGET
, "hybrid-sleep", "replace-irreversibly" },
3074 static enum action
verb_to_action(const char *verb
) {
3077 for (i
= 0; i
< _ACTION_MAX
; i
++)
3078 if (streq_ptr(action_table
[i
].verb
, verb
))
3081 return _ACTION_INVALID
;
3084 static int start_unit(int argc
, char *argv
[], void *userdata
) {
3085 _cleanup_(bus_wait_for_jobs_freep
) BusWaitForJobs
*w
= NULL
;
3086 const char *method
, *mode
, *one_name
, *suffix
= NULL
;
3087 _cleanup_strv_free_
char **names
= NULL
;
3089 _cleanup_(wait_context_free
) WaitContext wait_context
= {};
3093 if (arg_wait
&& !STR_IN_SET(argv
[0], "start", "restart")) {
3094 log_error("--wait may only be used with the 'start' or 'restart' commands.");
3098 /* we cannot do sender tracking on the private bus, so we need the full
3099 * one for RefUnit to implement --wait */
3100 r
= acquire_bus(arg_wait
? BUS_FULL
: BUS_MANAGER
, &bus
);
3104 ask_password_agent_open_if_enabled();
3105 polkit_agent_open_maybe();
3107 if (arg_action
== ACTION_SYSTEMCTL
) {
3110 action
= verb_to_action(argv
[0]);
3112 if (action
!= _ACTION_INVALID
) {
3113 method
= "StartUnit";
3114 mode
= action_table
[action
].mode
;
3115 one_name
= action_table
[action
].target
;
3117 if (streq(argv
[0], "isolate")) {
3118 method
= "StartUnit";
3123 method
= verb_to_method(argv
[0]);
3124 mode
= arg_job_mode
;
3129 assert(arg_action
>= 0 && arg_action
< _ACTION_MAX
);
3130 assert(action_table
[arg_action
].target
);
3131 assert(action_table
[arg_action
].mode
);
3133 method
= "StartUnit";
3134 mode
= action_table
[arg_action
].mode
;
3135 one_name
= action_table
[arg_action
].target
;
3139 names
= strv_new(one_name
, NULL
);
3141 r
= expand_names(bus
, strv_skip(argv
, 1), suffix
, &names
);
3143 return log_error_errno(r
, "Failed to expand names: %m");
3146 if (!arg_no_block
) {
3147 r
= bus_wait_for_jobs_new(bus
, &w
);
3149 return log_error_errno(r
, "Could not watch jobs: %m");
3153 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3155 wait_context
.unit_paths
= set_new(&string_hash_ops
);
3156 if (!wait_context
.unit_paths
)
3159 r
= sd_bus_call_method(
3161 "org.freedesktop.systemd1",
3162 "/org/freedesktop/systemd1",
3163 "org.freedesktop.systemd1.Manager",
3168 return log_error_errno(r
, "Failed to enable subscription: %s", bus_error_message(&error
, r
));
3169 r
= sd_event_default(&wait_context
.event
);
3171 return log_error_errno(r
, "Failed to allocate event loop: %m");
3172 r
= sd_bus_attach_event(bus
, wait_context
.event
, 0);
3174 return log_error_errno(r
, "Failed to attach bus to event loop: %m");
3177 STRV_FOREACH(name
, names
) {
3178 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3181 q
= start_unit_one(bus
, method
, *name
, mode
, &error
, w
, arg_wait
? &wait_context
: NULL
);
3182 if (r
>= 0 && q
< 0)
3183 r
= translate_bus_error_to_exit_status(q
, &error
);
3186 if (!arg_no_block
) {
3187 int q
, arg_count
= 0;
3188 const char* extra_args
[4] = {};
3190 if (arg_scope
!= UNIT_FILE_SYSTEM
)
3191 extra_args
[arg_count
++] = "--user";
3193 assert(IN_SET(arg_transport
, BUS_TRANSPORT_LOCAL
, BUS_TRANSPORT_REMOTE
, BUS_TRANSPORT_MACHINE
));
3194 if (arg_transport
== BUS_TRANSPORT_REMOTE
) {
3195 extra_args
[arg_count
++] = "-H";
3196 extra_args
[arg_count
++] = arg_host
;
3197 } else if (arg_transport
== BUS_TRANSPORT_MACHINE
) {
3198 extra_args
[arg_count
++] = "-M";
3199 extra_args
[arg_count
++] = arg_host
;
3202 q
= bus_wait_for_jobs(w
, arg_quiet
, extra_args
);
3206 /* When stopping units, warn if they can still be triggered by
3207 * another active unit (socket, path, timer) */
3208 if (!arg_quiet
&& streq(method
, "StopUnit"))
3209 STRV_FOREACH(name
, names
)
3210 check_triggering_units(bus
, *name
);
3213 if (r
>= 0 && arg_wait
) {
3215 q
= sd_event_loop(wait_context
.event
);
3217 return log_error_errno(q
, "Failed to run event loop: %m");
3218 if (wait_context
.any_failed
)
3226 static int logind_set_wall_message(void) {
3227 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3229 _cleanup_free_
char *m
= NULL
;
3232 r
= acquire_bus(BUS_FULL
, &bus
);
3236 m
= strv_join(arg_wall
, " ");
3240 r
= sd_bus_call_method(
3242 "org.freedesktop.login1",
3243 "/org/freedesktop/login1",
3244 "org.freedesktop.login1.Manager",
3253 return log_warning_errno(r
, "Failed to set wall message, ignoring: %s", bus_error_message(&error
, r
));
3258 /* Ask systemd-logind, which might grant access to unprivileged users
3259 * through PolicyKit */
3260 static int logind_reboot(enum action a
) {
3262 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3263 const char *method
, *description
;
3267 r
= acquire_bus(BUS_FULL
, &bus
);
3273 case ACTION_POWEROFF
:
3274 method
= "PowerOff";
3275 description
= "power off system";
3280 description
= "reboot system";
3285 description
= "halt system";
3288 case ACTION_SUSPEND
:
3290 description
= "suspend system";
3293 case ACTION_HIBERNATE
:
3294 method
= "Hibernate";
3295 description
= "hibernate system";
3298 case ACTION_HYBRID_SLEEP
:
3299 method
= "HybridSleep";
3300 description
= "put system into hybrid sleep";
3307 polkit_agent_open_maybe();
3308 (void) logind_set_wall_message();
3310 r
= sd_bus_call_method(
3312 "org.freedesktop.login1",
3313 "/org/freedesktop/login1",
3314 "org.freedesktop.login1.Manager",
3318 "b", arg_ask_password
);
3320 return log_error_errno(r
, "Failed to %s via logind: %s", description
, bus_error_message(&error
, r
));
3328 static int logind_check_inhibitors(enum action a
) {
3330 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
3331 _cleanup_strv_free_
char **sessions
= NULL
;
3332 const char *what
, *who
, *why
, *mode
;
3339 if (arg_ignore_inhibitors
|| arg_force
> 0)
3351 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
3354 r
= acquire_bus(BUS_FULL
, &bus
);
3358 r
= sd_bus_call_method(
3360 "org.freedesktop.login1",
3361 "/org/freedesktop/login1",
3362 "org.freedesktop.login1.Manager",
3368 /* If logind is not around, then there are no inhibitors... */
3371 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssuu)");
3373 return bus_log_parse_error(r
);
3375 while ((r
= sd_bus_message_read(reply
, "(ssssuu)", &what
, &who
, &why
, &mode
, &uid
, &pid
)) > 0) {
3376 _cleanup_free_
char *comm
= NULL
, *user
= NULL
;
3377 _cleanup_strv_free_
char **sv
= NULL
;
3379 if (!streq(mode
, "block"))
3382 sv
= strv_split(what
, ":");
3386 if (!pid_is_valid((pid_t
) pid
)) {
3387 log_error("Invalid PID "PID_FMT
".", (pid_t
) pid
);
3391 if (!strv_contains(sv
,
3396 ACTION_KEXEC
) ? "shutdown" : "sleep"))
3399 get_process_comm(pid
, &comm
);
3400 user
= uid_to_name(uid
);
3402 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT
" \"%s\", user %s), reason is \"%s\".",
3403 who
, (pid_t
) pid
, strna(comm
), strna(user
), why
);
3408 return bus_log_parse_error(r
);
3410 r
= sd_bus_message_exit_container(reply
);
3412 return bus_log_parse_error(r
);
3414 /* Check for current sessions */
3415 sd_get_sessions(&sessions
);
3416 STRV_FOREACH(s
, sessions
) {
3417 _cleanup_free_
char *type
= NULL
, *tty
= NULL
, *seat
= NULL
, *user
= NULL
, *service
= NULL
, *class = NULL
;
3419 if (sd_session_get_uid(*s
, &uid
) < 0 || uid
== getuid())
3422 if (sd_session_get_class(*s
, &class) < 0 || !streq(class, "user"))
3425 if (sd_session_get_type(*s
, &type
) < 0 || !STR_IN_SET(type
, "x11", "wayland", "tty", "mir"))
3428 sd_session_get_tty(*s
, &tty
);
3429 sd_session_get_seat(*s
, &seat
);
3430 sd_session_get_service(*s
, &service
);
3431 user
= uid_to_name(uid
);
3433 log_warning("User %s is logged in on %s.", strna(user
), isempty(tty
) ? (isempty(seat
) ? strna(service
) : seat
) : tty
);
3440 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
3441 action_table
[a
].verb
);
3449 static int logind_prepare_firmware_setup(void) {
3451 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3455 r
= acquire_bus(BUS_FULL
, &bus
);
3459 r
= sd_bus_call_method(
3461 "org.freedesktop.login1",
3462 "/org/freedesktop/login1",
3463 "org.freedesktop.login1.Manager",
3464 "SetRebootToFirmwareSetup",
3469 return log_error_errno(r
, "Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error
, r
));
3473 log_error("Cannot remotely indicate to EFI to boot into setup mode.");
3478 static int prepare_firmware_setup(void) {
3481 if (!arg_firmware_setup
)
3484 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
3486 r
= efi_set_reboot_to_firmware(true);
3488 log_debug_errno(r
, "Cannot indicate to EFI to boot into setup mode, will retry via logind: %m");
3493 return logind_prepare_firmware_setup();
3496 static int load_kexec_kernel(void) {
3497 _cleanup_(boot_config_free
) BootConfig config
= {};
3498 _cleanup_free_
char *where
= NULL
, *kernel
= NULL
, *initrd
= NULL
, *options
= NULL
;
3503 if (kexec_loaded()) {
3504 log_debug("Kexec kernel already loaded.");
3508 r
= find_esp_and_warn(arg_esp_path
, false, &where
, NULL
, NULL
, NULL
, NULL
);
3509 if (r
== -ENOKEY
) /* find_esp_and_warn() doesn't warn about this case */
3510 return log_error_errno(r
, "Cannot find the ESP partition mount point.");
3511 if (r
< 0) /* But it logs about all these cases, hence don't log here again */
3514 r
= boot_entries_load_config(where
, &config
);
3516 return log_error_errno(r
, "Failed to load bootspec config from \"%s/loader\": %m", where
);
3518 if (config
.default_entry
< 0) {
3519 log_error("No entry suitable as default, refusing to guess.");
3522 e
= &config
.entries
[config
.default_entry
];
3524 if (strv_length(e
->initrd
) > 1) {
3525 log_error("Boot entry specifies multiple initrds, which is not supported currently.");
3529 kernel
= path_join(NULL
, where
, e
->kernel
);
3530 if (!strv_isempty(e
->initrd
))
3531 initrd
= path_join(NULL
, where
, *e
->initrd
);
3532 options
= strv_join(e
->options
, " ");
3536 log_debug("%s kexec kernel %s initrd %s options \"%s\".",
3537 arg_dry_run
? "Would load" : "loading",
3538 kernel
, initrd
, options
);
3542 r
= safe_fork("(kexec)", FORK_RESET_SIGNALS
|FORK_DEATHSIG
|FORK_LOG
, &pid
);
3547 const char* const args
[] = {
3550 "--append", options
,
3551 initrd
? "--initrd" : NULL
, initrd
,
3555 execv(args
[0], (char * const *) args
);
3556 _exit(EXIT_FAILURE
);
3559 return wait_for_terminate_and_check("kexec", pid
, WAIT_LOG
);
3562 static int set_exit_code(uint8_t code
) {
3563 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3567 r
= acquire_bus(BUS_MANAGER
, &bus
);
3571 r
= sd_bus_call_method(
3573 "org.freedesktop.systemd1",
3574 "/org/freedesktop/systemd1",
3575 "org.freedesktop.systemd1.Manager",
3581 return log_error_errno(r
, "Failed to set exit code: %s", bus_error_message(&error
, r
));
3586 static int start_special(int argc
, char *argv
[], void *userdata
) {
3589 bool termination_action
; /* an action that terminates the manager,
3590 * can be performed also by signal. */
3594 a
= verb_to_action(argv
[0]);
3596 r
= logind_check_inhibitors(a
);
3600 if (arg_force
>= 2) {
3606 r
= prepare_firmware_setup();
3610 if (a
== ACTION_REBOOT
&& argc
> 1) {
3611 r
= update_reboot_parameter_and_warn(argv
[1]);
3615 } else if (a
== ACTION_KEXEC
) {
3616 r
= load_kexec_kernel();
3620 } else if (a
== ACTION_EXIT
&& argc
> 1) {
3623 /* If the exit code is not given on the command line,
3624 * don't reset it to zero: just keep it as it might
3625 * have been set previously. */
3627 r
= safe_atou8(argv
[1], &code
);
3629 return log_error_errno(r
, "Invalid exit code.");
3631 r
= set_exit_code(code
);
3636 termination_action
= IN_SET(a
,
3640 if (termination_action
&& arg_force
>= 2)
3643 if (arg_force
>= 1 &&
3644 (termination_action
|| IN_SET(a
, ACTION_KEXEC
, ACTION_EXIT
)))
3645 r
= trivial_method(argc
, argv
, userdata
);
3647 /* First try logind, to allow authentication with polkit */
3654 ACTION_HYBRID_SLEEP
)) {
3656 r
= logind_reboot(a
);
3659 if (IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
3660 /* requested operation is not supported or already in progress */
3663 /* On all other errors, try low-level operation. In order to minimize the difference between
3664 * operation with and without logind, we explicitly enable non-blocking mode for this, as
3665 * logind's shutdown operations are always non-blocking. */
3667 arg_no_block
= true;
3669 } else if (IN_SET(a
, ACTION_EXIT
, ACTION_KEXEC
))
3670 /* Since exit/kexec are so close in behaviour to power-off/reboot, let's also make them
3671 * asynchronous, in order to not confuse the user needlessly with unexpected behaviour. */
3672 arg_no_block
= true;
3674 r
= start_unit(argc
, argv
, userdata
);
3677 if (termination_action
&& arg_force
< 2 &&
3678 IN_SET(r
, -ENOENT
, -ETIMEDOUT
))
3679 log_notice("It is possible to perform action directly, see discussion of --force --force in man:systemctl(1).");
3684 static int start_system_special(int argc
, char *argv
[], void *userdata
) {
3685 /* Like start_special above, but raises an error when running in user mode */
3687 if (arg_scope
!= UNIT_FILE_SYSTEM
) {
3688 log_error("Bad action for %s mode.",
3689 arg_scope
== UNIT_FILE_GLOBAL
? "--global" : "--user");
3693 return start_special(argc
, argv
, userdata
);
3696 static int check_unit_generic(int code
, const UnitActiveState good_states
[], int nb_states
, char **args
) {
3697 _cleanup_strv_free_
char **names
= NULL
;
3698 UnitActiveState active_state
;
3704 r
= acquire_bus(BUS_MANAGER
, &bus
);
3708 r
= expand_names(bus
, args
, NULL
, &names
);
3710 return log_error_errno(r
, "Failed to expand names: %m");
3712 STRV_FOREACH(name
, names
) {
3713 r
= get_state_one_unit(bus
, *name
, &active_state
);
3718 puts(unit_active_state_to_string(active_state
));
3720 for (i
= 0; i
< nb_states
; ++i
)
3721 if (good_states
[i
] == active_state
)
3725 /* use the given return code for the case that we won't find
3726 * any unit which matches the list */
3727 return found
? 0 : code
;
3730 static int check_unit_active(int argc
, char *argv
[], void *userdata
) {
3731 const UnitActiveState states
[] = { UNIT_ACTIVE
, UNIT_RELOADING
};
3732 /* According to LSB: 3, "program is not running" */
3733 return check_unit_generic(EXIT_PROGRAM_NOT_RUNNING
, states
, ELEMENTSOF(states
), strv_skip(argv
, 1));
3736 static int check_unit_failed(int argc
, char *argv
[], void *userdata
) {
3737 const UnitActiveState states
[] = { UNIT_FAILED
};
3738 return check_unit_generic(EXIT_PROGRAM_DEAD_AND_PID_EXISTS
, states
, ELEMENTSOF(states
), strv_skip(argv
, 1));
3741 static int kill_unit(int argc
, char *argv
[], void *userdata
) {
3742 _cleanup_strv_free_
char **names
= NULL
;
3743 char *kill_who
= NULL
, **name
;
3747 r
= acquire_bus(BUS_MANAGER
, &bus
);
3751 polkit_agent_open_maybe();
3754 arg_kill_who
= "all";
3756 /* --fail was specified */
3757 if (streq(arg_job_mode
, "fail"))
3758 kill_who
= strjoina(arg_kill_who
, "-fail");
3760 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
3762 return log_error_errno(r
, "Failed to expand names: %m");
3764 STRV_FOREACH(name
, names
) {
3765 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3767 q
= sd_bus_call_method(
3769 "org.freedesktop.systemd1",
3770 "/org/freedesktop/systemd1",
3771 "org.freedesktop.systemd1.Manager",
3775 "ssi", *name
, kill_who
? kill_who
: arg_kill_who
, arg_signal
);
3777 log_error_errno(q
, "Failed to kill unit %s: %s", *name
, bus_error_message(&error
, q
));
3786 typedef struct ExecStatusInfo
{
3794 usec_t start_timestamp
;
3795 usec_t exit_timestamp
;
3800 LIST_FIELDS(struct ExecStatusInfo
, exec
);
3803 static void exec_status_info_free(ExecStatusInfo
*i
) {
3812 static int exec_status_info_deserialize(sd_bus_message
*m
, ExecStatusInfo
*i
) {
3813 uint64_t start_timestamp
, exit_timestamp
, start_timestamp_monotonic
, exit_timestamp_monotonic
;
3816 int32_t code
, status
;
3822 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_STRUCT
, "sasbttttuii");
3824 return bus_log_parse_error(r
);
3828 r
= sd_bus_message_read(m
, "s", &path
);
3830 return bus_log_parse_error(r
);
3832 i
->path
= strdup(path
);
3836 r
= sd_bus_message_read_strv(m
, &i
->argv
);
3838 return bus_log_parse_error(r
);
3840 r
= sd_bus_message_read(m
,
3843 &start_timestamp
, &start_timestamp_monotonic
,
3844 &exit_timestamp
, &exit_timestamp_monotonic
,
3848 return bus_log_parse_error(r
);
3851 i
->start_timestamp
= (usec_t
) start_timestamp
;
3852 i
->exit_timestamp
= (usec_t
) exit_timestamp
;
3853 i
->pid
= (pid_t
) pid
;
3857 r
= sd_bus_message_exit_container(m
);
3859 return bus_log_parse_error(r
);
3864 typedef struct UnitCondition
{
3871 LIST_FIELDS(struct UnitCondition
, conditions
);
3874 static void unit_condition_free(UnitCondition
*c
) {
3883 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitCondition
*, unit_condition_free
);
3885 typedef struct UnitStatusInfo
{
3887 const char *load_state
;
3888 const char *active_state
;
3889 const char *sub_state
;
3890 const char *unit_file_state
;
3891 const char *unit_file_preset
;
3893 const char *description
;
3894 const char *following
;
3896 char **documentation
;
3898 const char *fragment_path
;
3899 const char *source_path
;
3900 const char *control_group
;
3902 char **dropin_paths
;
3904 const char *load_error
;
3907 usec_t inactive_exit_timestamp
;
3908 usec_t inactive_exit_timestamp_monotonic
;
3909 usec_t active_enter_timestamp
;
3910 usec_t active_exit_timestamp
;
3911 usec_t inactive_enter_timestamp
;
3913 bool need_daemon_reload
;
3919 const char *status_text
;
3920 const char *pid_file
;
3924 usec_t start_timestamp
;
3925 usec_t exit_timestamp
;
3927 int exit_code
, exit_status
;
3929 usec_t condition_timestamp
;
3930 bool condition_result
;
3931 LIST_HEAD(UnitCondition
, conditions
);
3933 usec_t assert_timestamp
;
3935 bool failed_assert_trigger
;
3936 bool failed_assert_negate
;
3937 const char *failed_assert
;
3938 const char *failed_assert_parameter
;
3939 usec_t next_elapse_real
;
3940 usec_t next_elapse_monotonic
;
3943 unsigned n_accepted
;
3944 unsigned n_connections
;
3947 /* Pairs of type, path */
3951 const char *sysfs_path
;
3953 /* Mount, Automount */
3960 uint64_t memory_current
;
3961 uint64_t memory_low
;
3962 uint64_t memory_high
;
3963 uint64_t memory_max
;
3964 uint64_t memory_swap_max
;
3965 uint64_t memory_limit
;
3966 uint64_t cpu_usage_nsec
;
3967 uint64_t tasks_current
;
3970 uint64_t ip_ingress_bytes
;
3971 uint64_t ip_egress_bytes
;
3973 LIST_HEAD(ExecStatusInfo
, exec
);
3976 static void unit_status_info_free(UnitStatusInfo
*info
) {
3980 strv_free(info
->documentation
);
3981 strv_free(info
->dropin_paths
);
3982 strv_free(info
->listen
);
3984 while ((c
= info
->conditions
)) {
3985 LIST_REMOVE(conditions
, info
->conditions
, c
);
3986 unit_condition_free(c
);
3989 while ((p
= info
->exec
)) {
3990 LIST_REMOVE(exec
, info
->exec
, p
);
3991 exec_status_info_free(p
);
3995 static void print_status_info(
4001 const char *active_on
, *active_off
, *on
, *off
, *ss
;
4003 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], *s1
;
4004 char since2
[FORMAT_TIMESTAMP_MAX
], *s2
;
4011 /* This shows pretty information about a unit. See
4012 * print_property() for a low-level property printer */
4014 if (streq_ptr(i
->active_state
, "failed")) {
4015 active_on
= ansi_highlight_red();
4016 active_off
= ansi_normal();
4017 } else if (STRPTR_IN_SET(i
->active_state
, "active", "reloading")) {
4018 active_on
= ansi_highlight_green();
4019 active_off
= ansi_normal();
4021 active_on
= active_off
= "";
4023 printf("%s%s%s %s", active_on
, special_glyph(BLACK_CIRCLE
), active_off
, strna(i
->id
));
4025 if (i
->description
&& !streq_ptr(i
->id
, i
->description
))
4026 printf(" - %s", i
->description
);
4031 printf(" Follow: unit currently follows state of %s\n", i
->following
);
4033 if (streq_ptr(i
->load_state
, "error")) {
4034 on
= ansi_highlight_red();
4035 off
= ansi_normal();
4039 path
= i
->source_path
? i
->source_path
: i
->fragment_path
;
4041 if (i
->load_error
!= 0)
4042 printf(" Loaded: %s%s%s (Reason: %s)\n",
4043 on
, strna(i
->load_state
), off
, i
->load_error
);
4044 else if (path
&& !isempty(i
->unit_file_state
) && !isempty(i
->unit_file_preset
) &&
4045 !STR_IN_SET(i
->unit_file_state
, "generated", "transient"))
4046 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
4047 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
, i
->unit_file_preset
);
4048 else if (path
&& !isempty(i
->unit_file_state
))
4049 printf(" Loaded: %s%s%s (%s; %s)\n",
4050 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
);
4052 printf(" Loaded: %s%s%s (%s)\n",
4053 on
, strna(i
->load_state
), off
, path
);
4055 printf(" Loaded: %s%s%s\n",
4056 on
, strna(i
->load_state
), off
);
4059 printf("Transient: yes\n");
4061 if (!strv_isempty(i
->dropin_paths
)) {
4062 _cleanup_free_
char *dir
= NULL
;
4066 STRV_FOREACH(dropin
, i
->dropin_paths
) {
4067 if (! dir
|| last
) {
4068 printf(dir
? " " : " Drop-In: ");
4072 dir
= dirname_malloc(*dropin
);
4078 printf("%s\n %s", dir
,
4079 special_glyph(TREE_RIGHT
));
4082 last
= ! (*(dropin
+ 1) && startswith(*(dropin
+ 1), dir
));
4084 printf("%s%s", basename(*dropin
), last
? "\n" : ", ");
4088 ss
= streq_ptr(i
->active_state
, i
->sub_state
) ? NULL
: i
->sub_state
;
4090 printf(" Active: %s%s (%s)%s",
4091 active_on
, strna(i
->active_state
), ss
, active_off
);
4093 printf(" Active: %s%s%s",
4094 active_on
, strna(i
->active_state
), active_off
);
4096 if (!isempty(i
->result
) && !streq(i
->result
, "success"))
4097 printf(" (Result: %s)", i
->result
);
4099 timestamp
= STRPTR_IN_SET(i
->active_state
, "active", "reloading") ? i
->active_enter_timestamp
:
4100 STRPTR_IN_SET(i
->active_state
, "inactive", "failed") ? i
->inactive_enter_timestamp
:
4101 STRPTR_IN_SET(i
->active_state
, "activating") ? i
->inactive_exit_timestamp
:
4102 i
->active_exit_timestamp
;
4104 s1
= format_timestamp_relative(since1
, sizeof(since1
), timestamp
);
4105 s2
= format_timestamp(since2
, sizeof(since2
), timestamp
);
4108 printf(" since %s; %s\n", s2
, s1
);
4110 printf(" since %s\n", s2
);
4114 if (endswith(i
->id
, ".timer")) {
4115 char tstamp1
[FORMAT_TIMESTAMP_RELATIVE_MAX
],
4116 tstamp2
[FORMAT_TIMESTAMP_MAX
];
4117 char *next_rel_time
, *next_time
;
4118 dual_timestamp nw
, next
= {i
->next_elapse_real
,
4119 i
->next_elapse_monotonic
};
4122 printf(" Trigger: ");
4124 dual_timestamp_get(&nw
);
4125 next_elapse
= calc_next_elapse(&nw
, &next
);
4126 next_rel_time
= format_timestamp_relative(tstamp1
,
4129 next_time
= format_timestamp(tstamp2
,
4133 if (next_time
&& next_rel_time
)
4134 printf("%s; %s\n", next_time
, next_rel_time
);
4139 if (!i
->condition_result
&& i
->condition_timestamp
> 0) {
4143 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->condition_timestamp
);
4144 s2
= format_timestamp(since2
, sizeof(since2
), i
->condition_timestamp
);
4146 printf("Condition: start %scondition failed%s at %s%s%s\n",
4147 ansi_highlight_yellow(), ansi_normal(),
4148 s2
, s1
? "; " : "", strempty(s1
));
4150 LIST_FOREACH(conditions
, c
, i
->conditions
)
4151 if (c
->tristate
< 0)
4154 LIST_FOREACH(conditions
, c
, i
->conditions
)
4155 if (c
->tristate
< 0)
4156 printf(" %s %s=%s%s%s was not met\n",
4157 --n
? special_glyph(TREE_BRANCH
) : special_glyph(TREE_RIGHT
),
4159 c
->trigger
? "|" : "",
4160 c
->negate
? "!" : "",
4164 if (!i
->assert_result
&& i
->assert_timestamp
> 0) {
4165 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->assert_timestamp
);
4166 s2
= format_timestamp(since2
, sizeof(since2
), i
->assert_timestamp
);
4168 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
4169 ansi_highlight_red(), ansi_normal(),
4170 s2
, s1
? "; " : "", strempty(s1
));
4171 if (i
->failed_assert_trigger
)
4172 printf(" none of the trigger assertions were met\n");
4173 else if (i
->failed_assert
)
4174 printf(" %s=%s%s was not met\n",
4176 i
->failed_assert_negate
? "!" : "",
4177 i
->failed_assert_parameter
);
4181 printf(" Device: %s\n", i
->sysfs_path
);
4183 printf(" Where: %s\n", i
->where
);
4185 printf(" What: %s\n", i
->what
);
4187 STRV_FOREACH(t
, i
->documentation
)
4188 printf(" %*s %s\n", 9, t
== i
->documentation
? "Docs:" : "", *t
);
4190 STRV_FOREACH_PAIR(t
, t2
, i
->listen
)
4191 printf(" %*s %s (%s)\n", 9, t
== i
->listen
? "Listen:" : "", *t2
, *t
);
4194 printf(" Accepted: %u; Connected: %u\n", i
->n_accepted
, i
->n_connections
);
4196 LIST_FOREACH(exec
, p
, i
->exec
) {
4197 _cleanup_free_
char *argv
= NULL
;
4200 /* Only show exited processes here */
4204 argv
= strv_join(p
->argv
, " ");
4205 printf(" Process: "PID_FMT
" %s=%s ", p
->pid
, p
->name
, strna(argv
));
4207 good
= is_clean_exit(p
->code
, p
->status
, EXIT_CLEAN_DAEMON
, NULL
);
4209 on
= ansi_highlight_red();
4210 off
= ansi_normal();
4214 printf("%s(code=%s, ", on
, sigchld_code_to_string(p
->code
));
4216 if (p
->code
== CLD_EXITED
) {
4219 printf("status=%i", p
->status
);
4221 c
= exit_status_to_string(p
->status
, EXIT_STATUS_SYSTEMD
);
4226 printf("signal=%s", signal_to_string(p
->status
));
4228 printf(")%s\n", off
);
4230 if (i
->main_pid
== p
->pid
&&
4231 i
->start_timestamp
== p
->start_timestamp
&&
4232 i
->exit_timestamp
== p
->start_timestamp
)
4233 /* Let's not show this twice */
4236 if (p
->pid
== i
->control_pid
)
4240 if (i
->main_pid
> 0 || i
->control_pid
> 0) {
4241 if (i
->main_pid
> 0) {
4242 printf(" Main PID: "PID_FMT
, i
->main_pid
);
4246 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
4247 _cleanup_free_
char *comm
= NULL
;
4249 (void) get_process_comm(i
->main_pid
, &comm
);
4251 printf(" (%s)", comm
);
4254 } else if (i
->exit_code
> 0) {
4255 printf(" (code=%s, ", sigchld_code_to_string(i
->exit_code
));
4257 if (i
->exit_code
== CLD_EXITED
) {
4260 printf("status=%i", i
->exit_status
);
4262 c
= exit_status_to_string(i
->exit_status
, EXIT_STATUS_SYSTEMD
);
4267 printf("signal=%s", signal_to_string(i
->exit_status
));
4272 if (i
->control_pid
> 0) {
4273 _cleanup_free_
char *c
= NULL
;
4275 if (i
->main_pid
> 0)
4276 fputs("; Control PID: ", stdout
);
4278 fputs("Cntrl PID: ", stdout
); /* if first in column, abbreviated so it fits alignment */
4280 printf(PID_FMT
, i
->control_pid
);
4282 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
4283 (void) get_process_comm(i
->control_pid
, &c
);
4293 printf(" Status: \"%s\"\n", i
->status_text
);
4294 if (i
->status_errno
> 0)
4295 printf(" Error: %i (%s)\n", i
->status_errno
, strerror(i
->status_errno
));
4297 if (i
->ip_ingress_bytes
!= (uint64_t) -1 && i
->ip_egress_bytes
!= (uint64_t) -1) {
4298 char buf_in
[FORMAT_BYTES_MAX
], buf_out
[FORMAT_BYTES_MAX
];
4300 printf(" IP: %s in, %s out\n",
4301 format_bytes(buf_in
, sizeof(buf_in
), i
->ip_ingress_bytes
),
4302 format_bytes(buf_out
, sizeof(buf_out
), i
->ip_egress_bytes
));
4305 if (i
->tasks_current
!= (uint64_t) -1) {
4306 printf(" Tasks: %" PRIu64
, i
->tasks_current
);
4308 if (i
->tasks_max
!= (uint64_t) -1)
4309 printf(" (limit: %" PRIu64
")\n", i
->tasks_max
);
4314 if (i
->memory_current
!= (uint64_t) -1) {
4315 char buf
[FORMAT_BYTES_MAX
];
4317 printf(" Memory: %s", format_bytes(buf
, sizeof(buf
), i
->memory_current
));
4319 if (i
->memory_low
> 0 || i
->memory_high
!= CGROUP_LIMIT_MAX
||
4320 i
->memory_max
!= CGROUP_LIMIT_MAX
|| i
->memory_swap_max
!= CGROUP_LIMIT_MAX
||
4321 i
->memory_limit
!= CGROUP_LIMIT_MAX
) {
4322 const char *prefix
= "";
4325 if (i
->memory_low
> 0) {
4326 printf("%slow: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_low
));
4329 if (i
->memory_high
!= CGROUP_LIMIT_MAX
) {
4330 printf("%shigh: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_high
));
4333 if (i
->memory_max
!= CGROUP_LIMIT_MAX
) {
4334 printf("%smax: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_max
));
4337 if (i
->memory_swap_max
!= CGROUP_LIMIT_MAX
) {
4338 printf("%sswap max: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_swap_max
));
4341 if (i
->memory_limit
!= CGROUP_LIMIT_MAX
) {
4342 printf("%slimit: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_limit
));
4350 if (i
->cpu_usage_nsec
!= (uint64_t) -1) {
4351 char buf
[FORMAT_TIMESPAN_MAX
];
4352 printf(" CPU: %s\n", format_timespan(buf
, sizeof(buf
), i
->cpu_usage_nsec
/ NSEC_PER_USEC
, USEC_PER_MSEC
));
4355 if (i
->control_group
) {
4356 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
4357 static const char prefix
[] = " ";
4360 printf(" CGroup: %s\n", i
->control_group
);
4363 if (c
> sizeof(prefix
) - 1)
4364 c
-= sizeof(prefix
) - 1;
4368 r
= unit_show_processes(bus
, i
->id
, i
->control_group
, prefix
, c
, get_output_flags(), &error
);
4373 /* Fallback for older systemd versions where the GetUnitProcesses() call is not yet available */
4375 if (i
->main_pid
> 0)
4376 extra
[k
++] = i
->main_pid
;
4378 if (i
->control_pid
> 0)
4379 extra
[k
++] = i
->control_pid
;
4381 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, prefix
, c
, extra
, k
, get_output_flags());
4383 log_warning_errno(r
, "Failed to dump process list, ignoring: %s", bus_error_message(&error
, r
));
4386 if (i
->id
&& arg_transport
== BUS_TRANSPORT_LOCAL
)
4387 show_journal_by_unit(
4392 i
->inactive_exit_timestamp_monotonic
,
4395 get_output_flags() | OUTPUT_BEGIN_NEWLINE
,
4396 SD_JOURNAL_LOCAL_ONLY
,
4397 arg_scope
== UNIT_FILE_SYSTEM
,
4400 if (i
->need_daemon_reload
)
4401 warn_unit_file_changed(i
->id
);
4404 static void show_unit_help(UnitStatusInfo
*i
) {
4409 if (!i
->documentation
) {
4410 log_info("Documentation for %s not known.", i
->id
);
4414 STRV_FOREACH(p
, i
->documentation
)
4415 if (startswith(*p
, "man:"))
4416 show_man_page(*p
+ 4, false);
4418 log_info("Can't show: %s", *p
);
4421 static int status_property(const char *name
, sd_bus_message
*m
, UnitStatusInfo
*i
, const char *contents
) {
4428 switch (contents
[0]) {
4430 case SD_BUS_TYPE_STRING
: {
4433 r
= sd_bus_message_read(m
, "s", &s
);
4435 return bus_log_parse_error(r
);
4438 if (streq(name
, "Id"))
4440 else if (streq(name
, "LoadState"))
4442 else if (streq(name
, "ActiveState"))
4443 i
->active_state
= s
;
4444 else if (streq(name
, "SubState"))
4446 else if (streq(name
, "Description"))
4448 else if (streq(name
, "FragmentPath"))
4449 i
->fragment_path
= s
;
4450 else if (streq(name
, "SourcePath"))
4453 else if (streq(name
, "DefaultControlGroup")) {
4455 e
= startswith(s
, SYSTEMD_CGROUP_CONTROLLER
":");
4457 i
->control_group
= e
;
4460 else if (streq(name
, "ControlGroup"))
4461 i
->control_group
= s
;
4462 else if (streq(name
, "StatusText"))
4464 else if (streq(name
, "PIDFile"))
4466 else if (streq(name
, "SysFSPath"))
4468 else if (streq(name
, "Where"))
4470 else if (streq(name
, "What"))
4472 else if (streq(name
, "Following"))
4474 else if (streq(name
, "UnitFileState"))
4475 i
->unit_file_state
= s
;
4476 else if (streq(name
, "UnitFilePreset"))
4477 i
->unit_file_preset
= s
;
4478 else if (streq(name
, "Result"))
4485 case SD_BUS_TYPE_BOOLEAN
: {
4488 r
= sd_bus_message_read(m
, "b", &b
);
4490 return bus_log_parse_error(r
);
4492 if (streq(name
, "Accept"))
4494 else if (streq(name
, "NeedDaemonReload"))
4495 i
->need_daemon_reload
= b
;
4496 else if (streq(name
, "ConditionResult"))
4497 i
->condition_result
= b
;
4498 else if (streq(name
, "AssertResult"))
4499 i
->assert_result
= b
;
4500 else if (streq(name
, "Transient"))
4506 case SD_BUS_TYPE_UINT32
: {
4509 r
= sd_bus_message_read(m
, "u", &u
);
4511 return bus_log_parse_error(r
);
4513 if (streq(name
, "MainPID")) {
4515 i
->main_pid
= (pid_t
) u
;
4518 } else if (streq(name
, "ControlPID"))
4519 i
->control_pid
= (pid_t
) u
;
4520 else if (streq(name
, "ExecMainPID")) {
4522 i
->main_pid
= (pid_t
) u
;
4523 } else if (streq(name
, "NAccepted"))
4525 else if (streq(name
, "NConnections"))
4526 i
->n_connections
= u
;
4531 case SD_BUS_TYPE_INT32
: {
4534 r
= sd_bus_message_read(m
, "i", &j
);
4536 return bus_log_parse_error(r
);
4538 if (streq(name
, "ExecMainCode"))
4539 i
->exit_code
= (int) j
;
4540 else if (streq(name
, "ExecMainStatus"))
4541 i
->exit_status
= (int) j
;
4542 else if (streq(name
, "StatusErrno"))
4543 i
->status_errno
= (int) j
;
4548 case SD_BUS_TYPE_UINT64
: {
4551 r
= sd_bus_message_read(m
, "t", &u
);
4553 return bus_log_parse_error(r
);
4555 if (streq(name
, "ExecMainStartTimestamp"))
4556 i
->start_timestamp
= (usec_t
) u
;
4557 else if (streq(name
, "ExecMainExitTimestamp"))
4558 i
->exit_timestamp
= (usec_t
) u
;
4559 else if (streq(name
, "ActiveEnterTimestamp"))
4560 i
->active_enter_timestamp
= (usec_t
) u
;
4561 else if (streq(name
, "InactiveEnterTimestamp"))
4562 i
->inactive_enter_timestamp
= (usec_t
) u
;
4563 else if (streq(name
, "InactiveExitTimestamp"))
4564 i
->inactive_exit_timestamp
= (usec_t
) u
;
4565 else if (streq(name
, "InactiveExitTimestampMonotonic"))
4566 i
->inactive_exit_timestamp_monotonic
= (usec_t
) u
;
4567 else if (streq(name
, "ActiveExitTimestamp"))
4568 i
->active_exit_timestamp
= (usec_t
) u
;
4569 else if (streq(name
, "ConditionTimestamp"))
4570 i
->condition_timestamp
= (usec_t
) u
;
4571 else if (streq(name
, "AssertTimestamp"))
4572 i
->assert_timestamp
= (usec_t
) u
;
4573 else if (streq(name
, "MemoryCurrent"))
4574 i
->memory_current
= u
;
4575 else if (streq(name
, "MemoryLow"))
4577 else if (streq(name
, "MemoryHigh"))
4579 else if (streq(name
, "MemoryMax"))
4581 else if (streq(name
, "MemorySwapMax"))
4582 i
->memory_swap_max
= u
;
4583 else if (streq(name
, "MemoryLimit"))
4584 i
->memory_limit
= u
;
4585 else if (streq(name
, "TasksCurrent"))
4586 i
->tasks_current
= u
;
4587 else if (streq(name
, "TasksMax"))
4589 else if (streq(name
, "CPUUsageNSec"))
4590 i
->cpu_usage_nsec
= u
;
4591 else if (streq(name
, "NextElapseUSecMonotonic"))
4592 i
->next_elapse_monotonic
= u
;
4593 else if (streq(name
, "NextElapseUSecRealtime"))
4594 i
->next_elapse_real
= u
;
4595 else if (streq(name
, "IPIngressBytes"))
4596 i
->ip_ingress_bytes
= u
;
4597 else if (streq(name
, "IPEgressBytes"))
4598 i
->ip_egress_bytes
= u
;
4603 case SD_BUS_TYPE_ARRAY
:
4605 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
4606 _cleanup_free_ ExecStatusInfo
*info
= NULL
;
4608 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4610 return bus_log_parse_error(r
);
4612 info
= new0(ExecStatusInfo
, 1);
4616 while ((r
= exec_status_info_deserialize(m
, info
)) > 0) {
4618 info
->name
= strdup(name
);
4622 LIST_PREPEND(exec
, i
->exec
, info
);
4624 info
= new0(ExecStatusInfo
, 1);
4630 return bus_log_parse_error(r
);
4632 r
= sd_bus_message_exit_container(m
);
4634 return bus_log_parse_error(r
);
4638 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
4639 const char *type
, *path
;
4641 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4643 return bus_log_parse_error(r
);
4645 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0) {
4647 r
= strv_extend(&i
->listen
, type
);
4651 r
= strv_extend(&i
->listen
, path
);
4656 return bus_log_parse_error(r
);
4658 r
= sd_bus_message_exit_container(m
);
4660 return bus_log_parse_error(r
);
4664 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "DropInPaths")) {
4666 r
= sd_bus_message_read_strv(m
, &i
->dropin_paths
);
4668 return bus_log_parse_error(r
);
4670 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Documentation")) {
4672 r
= sd_bus_message_read_strv(m
, &i
->documentation
);
4674 return bus_log_parse_error(r
);
4676 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Conditions")) {
4677 const char *cond
, *param
;
4678 int trigger
, negate
;
4681 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
4683 return bus_log_parse_error(r
);
4685 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
4686 _cleanup_(unit_condition_freep
) UnitCondition
*c
= NULL
;
4688 log_debug("%s trigger=%d negate=%d %s →%d", cond
, trigger
, negate
, param
, state
);
4690 c
= new0(UnitCondition
, 1);
4694 c
->name
= strdup(cond
);
4695 c
->param
= strdup(param
);
4696 if (!c
->name
|| !c
->param
)
4699 c
->trigger
= trigger
;
4701 c
->tristate
= state
;
4703 LIST_PREPEND(conditions
, i
->conditions
, c
);
4707 return bus_log_parse_error(r
);
4709 r
= sd_bus_message_exit_container(m
);
4711 return bus_log_parse_error(r
);
4713 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Asserts")) {
4714 const char *cond
, *param
;
4715 int trigger
, negate
;
4718 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
4720 return bus_log_parse_error(r
);
4722 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
4723 log_debug("%s %d %d %s %d", cond
, trigger
, negate
, param
, state
);
4724 if (state
< 0 && (!trigger
|| !i
->failed_assert
)) {
4725 i
->failed_assert
= cond
;
4726 i
->failed_assert_trigger
= trigger
;
4727 i
->failed_assert_negate
= negate
;
4728 i
->failed_assert_parameter
= param
;
4732 return bus_log_parse_error(r
);
4734 r
= sd_bus_message_exit_container(m
);
4736 return bus_log_parse_error(r
);
4743 case SD_BUS_TYPE_STRUCT_BEGIN
:
4745 if (streq(name
, "LoadError")) {
4746 const char *n
, *message
;
4748 r
= sd_bus_message_read(m
, "(ss)", &n
, &message
);
4750 return bus_log_parse_error(r
);
4752 if (!isempty(message
))
4753 i
->load_error
= message
;
4766 r
= sd_bus_message_skip(m
, contents
);
4768 return bus_log_parse_error(r
);
4773 #define print_prop(name, fmt, ...) \
4776 printf(fmt "\n", __VA_ARGS__); \
4778 printf("%s=" fmt "\n", name, __VA_ARGS__); \
4781 static int print_property(const char *name
, sd_bus_message
*m
, const char *contents
) {
4787 /* This is a low-level property printer, see
4788 * print_status_info() for the nicer output */
4790 if (arg_properties
&& !strv_find(arg_properties
, name
)) {
4791 /* skip what we didn't read */
4792 r
= sd_bus_message_skip(m
, contents
);
4796 switch (contents
[0]) {
4798 case SD_BUS_TYPE_STRUCT_BEGIN
:
4800 if (contents
[1] == SD_BUS_TYPE_UINT32
&& streq(name
, "Job")) {
4803 r
= sd_bus_message_read(m
, "(uo)", &u
, NULL
);
4805 return bus_log_parse_error(r
);
4808 print_prop(name
, "%"PRIu32
, u
);
4810 print_prop(name
, "%s", "");
4814 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Unit")) {
4817 r
= sd_bus_message_read(m
, "(so)", &s
, NULL
);
4819 return bus_log_parse_error(r
);
4821 if (arg_all
|| !isempty(s
))
4822 print_prop(name
, "%s", s
);
4826 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "LoadError")) {
4827 const char *a
= NULL
, *b
= NULL
;
4829 r
= sd_bus_message_read(m
, "(ss)", &a
, &b
);
4831 return bus_log_parse_error(r
);
4833 if (arg_all
|| !isempty(a
) || !isempty(b
))
4834 print_prop(name
, "%s \"%s\"", strempty(a
), strempty(b
));
4837 } else if (streq_ptr(name
, "SystemCallFilter")) {
4838 _cleanup_strv_free_
char **l
= NULL
;
4841 r
= sd_bus_message_enter_container(m
, 'r', "bas");
4843 return bus_log_parse_error(r
);
4845 r
= sd_bus_message_read(m
, "b", &whitelist
);
4847 return bus_log_parse_error(r
);
4849 r
= sd_bus_message_read_strv(m
, &l
);
4851 return bus_log_parse_error(r
);
4853 r
= sd_bus_message_exit_container(m
);
4855 return bus_log_parse_error(r
);
4857 if (arg_all
|| whitelist
|| !strv_isempty(l
)) {
4862 fputs(name
, stdout
);
4869 STRV_FOREACH(i
, l
) {
4877 fputc('\n', stdout
);
4885 case SD_BUS_TYPE_ARRAY
:
4887 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "EnvironmentFiles")) {
4891 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sb)");
4893 return bus_log_parse_error(r
);
4895 while ((r
= sd_bus_message_read(m
, "(sb)", &path
, &ignore
)) > 0)
4896 print_prop("EnvironmentFile", "%s (ignore_errors=%s)", path
, yes_no(ignore
));
4899 return bus_log_parse_error(r
);
4901 r
= sd_bus_message_exit_container(m
);
4903 return bus_log_parse_error(r
);
4907 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Paths")) {
4908 const char *type
, *path
;
4910 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4912 return bus_log_parse_error(r
);
4914 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4915 print_prop(type
, "%s", path
);
4917 return bus_log_parse_error(r
);
4919 r
= sd_bus_message_exit_container(m
);
4921 return bus_log_parse_error(r
);
4925 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
4926 const char *type
, *path
;
4928 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4930 return bus_log_parse_error(r
);
4932 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4936 printf("Listen%s=%s\n", type
, path
);
4938 return bus_log_parse_error(r
);
4940 r
= sd_bus_message_exit_container(m
);
4942 return bus_log_parse_error(r
);
4946 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Timers")) {
4948 uint64_t value
, next_elapse
;
4950 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(stt)");
4952 return bus_log_parse_error(r
);
4954 while ((r
= sd_bus_message_read(m
, "(stt)", &base
, &value
, &next_elapse
)) > 0) {
4955 char timespan1
[FORMAT_TIMESPAN_MAX
], timespan2
[FORMAT_TIMESPAN_MAX
];
4957 print_prop(base
, "{ value=%s ; next_elapse=%s }",
4958 format_timespan(timespan1
, sizeof(timespan1
), value
, 0),
4959 format_timespan(timespan2
, sizeof(timespan2
), next_elapse
, 0));
4962 return bus_log_parse_error(r
);
4964 r
= sd_bus_message_exit_container(m
);
4966 return bus_log_parse_error(r
);
4970 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
4971 ExecStatusInfo info
= {};
4973 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4975 return bus_log_parse_error(r
);
4977 while ((r
= exec_status_info_deserialize(m
, &info
)) > 0) {
4978 char timestamp1
[FORMAT_TIMESTAMP_MAX
], timestamp2
[FORMAT_TIMESTAMP_MAX
];
4979 _cleanup_free_
char *tt
;
4981 tt
= strv_join(info
.argv
, " ");
4984 "{ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT
" ; code=%s ; status=%i%s%s }",
4987 yes_no(info
.ignore
),
4988 strna(format_timestamp(timestamp1
, sizeof(timestamp1
), info
.start_timestamp
)),
4989 strna(format_timestamp(timestamp2
, sizeof(timestamp2
), info
.exit_timestamp
)),
4991 sigchld_code_to_string(info
.code
),
4993 info
.code
== CLD_EXITED
? "" : "/",
4994 strempty(info
.code
== CLD_EXITED
? NULL
: signal_to_string(info
.status
)));
4997 strv_free(info
.argv
);
5001 r
= sd_bus_message_exit_container(m
);
5003 return bus_log_parse_error(r
);
5007 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "DeviceAllow")) {
5008 const char *path
, *rwm
;
5010 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
5012 return bus_log_parse_error(r
);
5014 while ((r
= sd_bus_message_read(m
, "(ss)", &path
, &rwm
)) > 0)
5015 print_prop(name
, "%s %s", strna(path
), strna(rwm
));
5017 return bus_log_parse_error(r
);
5019 r
= sd_bus_message_exit_container(m
);
5021 return bus_log_parse_error(r
);
5025 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&&
5026 STR_IN_SET(name
, "IODeviceWeight", "BlockIODeviceWeight")) {
5030 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
5032 return bus_log_parse_error(r
);
5034 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &weight
)) > 0)
5035 print_prop(name
, "%s %"PRIu64
, strna(path
), weight
);
5037 return bus_log_parse_error(r
);
5039 r
= sd_bus_message_exit_container(m
);
5041 return bus_log_parse_error(r
);
5045 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&&
5046 (cgroup_io_limit_type_from_string(name
) >= 0 ||
5047 STR_IN_SET(name
, "BlockIOReadBandwidth", "BlockIOWriteBandwidth"))) {
5051 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
5053 return bus_log_parse_error(r
);
5055 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &bandwidth
)) > 0)
5056 print_prop(name
, "%s %"PRIu64
, strna(path
), bandwidth
);
5058 return bus_log_parse_error(r
);
5060 r
= sd_bus_message_exit_container(m
);
5062 return bus_log_parse_error(r
);
5066 } else if (contents
[1] == SD_BUS_TYPE_BYTE
&& streq(name
, "StandardInputData")) {
5067 _cleanup_free_
char *h
= NULL
;
5072 r
= sd_bus_message_read_array(m
, 'y', &p
, &sz
);
5074 return bus_log_parse_error(r
);
5076 n
= base64mem(p
, sz
, &h
);
5080 print_prop(name
, "%s", h
);
5088 r
= bus_print_property(name
, m
, arg_value
, arg_all
);
5090 return bus_log_parse_error(r
);
5093 r
= sd_bus_message_skip(m
, contents
);
5095 return bus_log_parse_error(r
);
5098 printf("%s=[unprintable]\n", name
);
5104 static int show_one(
5109 bool show_properties
,
5113 static const struct bus_properties_map property_map
[] = {
5114 { "LoadState", "s", map_string_no_copy
, offsetof(UnitStatusInfo
, load_state
) },
5115 { "ActiveState", "s", map_string_no_copy
, offsetof(UnitStatusInfo
, active_state
) },
5119 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5120 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5121 _cleanup_set_free_ Set
*found_properties
= NULL
;
5122 _cleanup_(unit_status_info_free
) UnitStatusInfo info
= {
5123 .memory_current
= (uint64_t) -1,
5124 .memory_high
= CGROUP_LIMIT_MAX
,
5125 .memory_max
= CGROUP_LIMIT_MAX
,
5126 .memory_swap_max
= CGROUP_LIMIT_MAX
,
5127 .memory_limit
= (uint64_t) -1,
5128 .cpu_usage_nsec
= (uint64_t) -1,
5129 .tasks_current
= (uint64_t) -1,
5130 .tasks_max
= (uint64_t) -1,
5131 .ip_ingress_bytes
= (uint64_t) -1,
5132 .ip_egress_bytes
= (uint64_t) -1,
5139 log_debug("Showing one %s", path
);
5141 r
= sd_bus_call_method(
5143 "org.freedesktop.systemd1",
5145 "org.freedesktop.DBus.Properties",
5151 return log_error_errno(r
, "Failed to get properties: %s", bus_error_message(&error
, r
));
5154 r
= bus_message_map_all_properties(reply
, property_map
, &error
, &info
);
5156 return log_error_errno(r
, "Failed to map properties: %s", bus_error_message(&error
, r
));
5158 if (streq_ptr(info
.load_state
, "not-found") && streq_ptr(info
.active_state
, "inactive")) {
5159 log_full(streq(verb
, "status") ? LOG_ERR
: LOG_DEBUG
,
5160 "Unit %s could not be found.", unit
);
5162 if (streq(verb
, "status"))
5163 return EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN
;
5165 if (!streq(verb
, "show"))
5169 r
= sd_bus_message_rewind(reply
, true);
5171 return log_error_errno(r
, "Failed to rewind: %s", bus_error_message(&error
, r
));
5174 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
5176 return bus_log_parse_error(r
);
5183 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
5184 const char *name
, *contents
;
5186 r
= sd_bus_message_read(reply
, "s", &name
);
5188 return bus_log_parse_error(r
);
5190 r
= sd_bus_message_peek_type(reply
, NULL
, &contents
);
5192 return bus_log_parse_error(r
);
5194 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, contents
);
5196 return bus_log_parse_error(r
);
5198 if (show_properties
) {
5199 r
= set_ensure_allocated(&found_properties
, &string_hash_ops
);
5203 r
= set_put(found_properties
, name
);
5204 if (r
< 0 && r
!= EEXIST
)
5207 r
= print_property(name
, reply
, contents
);
5209 r
= status_property(name
, reply
, &info
, contents
);
5213 r
= sd_bus_message_exit_container(reply
);
5215 return bus_log_parse_error(r
);
5217 r
= sd_bus_message_exit_container(reply
);
5219 return bus_log_parse_error(r
);
5222 return bus_log_parse_error(r
);
5224 r
= sd_bus_message_exit_container(reply
);
5226 return bus_log_parse_error(r
);
5229 if (show_properties
) {
5232 STRV_FOREACH(pp
, arg_properties
)
5233 if (!set_contains(found_properties
, *pp
))
5234 log_debug("Property %s does not exist.", *pp
);
5236 } else if (streq(verb
, "help"))
5237 show_unit_help(&info
);
5238 else if (streq(verb
, "status")) {
5239 print_status_info(bus
, &info
, ellipsized
);
5241 if (info
.active_state
&& !STR_IN_SET(info
.active_state
, "active", "reloading"))
5242 r
= EXIT_PROGRAM_NOT_RUNNING
;
5244 r
= EXIT_PROGRAM_RUNNING_OR_SERVICE_OK
;
5250 static int get_unit_dbus_path_by_pid(
5255 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5256 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5260 r
= sd_bus_call_method(
5262 "org.freedesktop.systemd1",
5263 "/org/freedesktop/systemd1",
5264 "org.freedesktop.systemd1.Manager",
5270 return log_error_errno(r
, "Failed to get unit for PID %"PRIu32
": %s", pid
, bus_error_message(&error
, r
));
5272 r
= sd_bus_message_read(reply
, "o", &u
);
5274 return bus_log_parse_error(r
);
5284 static int show_all(
5287 bool show_properties
,
5291 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5292 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
5297 r
= get_unit_list(bus
, NULL
, NULL
, &unit_infos
, 0, &reply
);
5301 pager_open(arg_no_pager
, false);
5305 qsort_safe(unit_infos
, c
, sizeof(UnitInfo
), compare_unit_info
);
5307 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
5308 _cleanup_free_
char *p
= NULL
;
5310 p
= unit_dbus_path_from_name(u
->id
);
5314 r
= show_one(verb
, bus
, p
, u
->id
, show_properties
, new_line
, ellipsized
);
5317 else if (r
> 0 && ret
== 0)
5324 static int show_system_status(sd_bus
*bus
) {
5325 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], since2
[FORMAT_TIMESTAMP_MAX
];
5326 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5327 _cleanup_(machine_info_clear
) struct machine_info mi
= {};
5328 _cleanup_free_
char *hn
= NULL
;
5329 const char *on
, *off
;
5332 hn
= gethostname_malloc();
5336 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, &error
, &mi
);
5338 return log_error_errno(r
, "Failed to read server status: %s", bus_error_message(&error
, r
));
5340 if (streq_ptr(mi
.state
, "degraded")) {
5341 on
= ansi_highlight_red();
5342 off
= ansi_normal();
5343 } else if (streq_ptr(mi
.state
, "running")) {
5344 on
= ansi_highlight_green();
5345 off
= ansi_normal();
5347 on
= ansi_highlight_yellow();
5348 off
= ansi_normal();
5351 printf("%s%s%s %s\n", on
, special_glyph(BLACK_CIRCLE
), off
, arg_host
? arg_host
: hn
);
5353 printf(" State: %s%s%s\n",
5354 on
, strna(mi
.state
), off
);
5356 printf(" Jobs: %" PRIu32
" queued\n", mi
.n_jobs
);
5357 printf(" Failed: %" PRIu32
" units\n", mi
.n_failed_units
);
5359 printf(" Since: %s; %s\n",
5360 format_timestamp(since2
, sizeof(since2
), mi
.timestamp
),
5361 format_timestamp_relative(since1
, sizeof(since1
), mi
.timestamp
));
5363 printf(" CGroup: %s\n", mi
.control_group
?: "/");
5364 if (IN_SET(arg_transport
,
5365 BUS_TRANSPORT_LOCAL
,
5366 BUS_TRANSPORT_MACHINE
)) {
5367 static const char prefix
[] = " ";
5371 if (c
> sizeof(prefix
) - 1)
5372 c
-= sizeof(prefix
) - 1;
5376 show_cgroup(SYSTEMD_CGROUP_CONTROLLER
, strempty(mi
.control_group
), prefix
, c
, get_output_flags());
5382 static int show(int argc
, char *argv
[], void *userdata
) {
5383 bool show_properties
, show_status
, show_help
, new_line
= false;
5384 bool ellipsized
= false;
5390 show_properties
= streq(argv
[0], "show");
5391 show_status
= streq(argv
[0], "status");
5392 show_help
= streq(argv
[0], "help");
5394 if (show_help
&& argc
<= 1) {
5395 log_error("This command expects one or more unit names. Did you mean --help?");
5399 r
= acquire_bus(BUS_MANAGER
, &bus
);
5403 pager_open(arg_no_pager
, false);
5406 /* Increase max number of open files to 16K if we can, we
5407 * might needs this when browsing journal files, which might
5408 * be split up into many files. */
5409 setrlimit_closest(RLIMIT_NOFILE
, &RLIMIT_MAKE_CONST(16384));
5411 /* If no argument is specified inspect the manager itself */
5412 if (show_properties
&& argc
<= 1)
5413 return show_one(argv
[0], bus
, "/org/freedesktop/systemd1", NULL
, show_properties
, &new_line
, &ellipsized
);
5415 if (show_status
&& argc
<= 1) {
5417 show_system_status(bus
);
5421 ret
= show_all(argv
[0], bus
, false, &new_line
, &ellipsized
);
5423 _cleanup_free_
char **patterns
= NULL
;
5426 STRV_FOREACH(name
, strv_skip(argv
, 1)) {
5427 _cleanup_free_
char *path
= NULL
, *unit
= NULL
;
5430 if (safe_atou32(*name
, &id
) < 0) {
5431 if (strv_push(&patterns
, *name
) < 0)
5435 } else if (show_properties
) {
5436 /* Interpret as job id */
5437 if (asprintf(&path
, "/org/freedesktop/systemd1/job/%u", id
) < 0)
5441 /* Interpret as PID */
5442 r
= get_unit_dbus_path_by_pid(bus
, id
, &path
);
5448 r
= unit_name_from_dbus_path(path
, &unit
);
5453 r
= show_one(argv
[0], bus
, path
, unit
, show_properties
, &new_line
, &ellipsized
);
5456 else if (r
> 0 && ret
== 0)
5460 if (!strv_isempty(patterns
)) {
5461 _cleanup_strv_free_
char **names
= NULL
;
5463 r
= expand_names(bus
, patterns
, NULL
, &names
);
5465 return log_error_errno(r
, "Failed to expand names: %m");
5467 STRV_FOREACH(name
, names
) {
5468 _cleanup_free_
char *path
;
5470 path
= unit_dbus_path_from_name(*name
);
5474 r
= show_one(argv
[0], bus
, path
, *name
, show_properties
, &new_line
, &ellipsized
);
5477 if (r
> 0 && ret
== 0)
5483 if (ellipsized
&& !arg_quiet
)
5484 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
5489 static int cat_file(const char *filename
, bool newline
) {
5490 _cleanup_close_
int fd
;
5492 fd
= open(filename
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
5496 printf("%s%s# %s%s\n",
5497 newline
? "\n" : "",
5498 ansi_highlight_blue(),
5503 return copy_bytes(fd
, STDOUT_FILENO
, (uint64_t) -1, 0);
5506 static int cat(int argc
, char *argv
[], void *userdata
) {
5507 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
5508 _cleanup_strv_free_
char **names
= NULL
;
5514 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
5515 log_error("Cannot remotely cat units.");
5519 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
5521 return log_error_errno(r
, "Failed to determine unit paths: %m");
5523 r
= acquire_bus(BUS_MANAGER
, &bus
);
5527 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
5529 return log_error_errno(r
, "Failed to expand names: %m");
5531 pager_open(arg_no_pager
, false);
5533 STRV_FOREACH(name
, names
) {
5534 _cleanup_free_
char *fragment_path
= NULL
;
5535 _cleanup_strv_free_
char **dropin_paths
= NULL
;
5538 r
= unit_find_paths(bus
, *name
, &lp
, &fragment_path
, &dropin_paths
);
5549 if (need_daemon_reload(bus
, *name
) > 0) /* ignore errors (<0), this is informational output */
5551 "%s# Warning: %s changed on disk, the version systemd has loaded is outdated.\n"
5552 "%s# This output shows the current version of the unit's original fragment and drop-in files.\n"
5553 "%s# If fragments or drop-ins were added or removed, they are not properly reflected in this output.\n"
5554 "%s# Run 'systemctl%s daemon-reload' to reload units.%s\n",
5555 ansi_highlight_red(),
5557 ansi_highlight_red(),
5558 ansi_highlight_red(),
5559 ansi_highlight_red(),
5560 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user",
5563 if (fragment_path
) {
5564 r
= cat_file(fragment_path
, false);
5566 return log_warning_errno(r
, "Failed to cat %s: %m", fragment_path
);
5569 STRV_FOREACH(path
, dropin_paths
) {
5570 r
= cat_file(*path
, path
== dropin_paths
);
5572 return log_warning_errno(r
, "Failed to cat %s: %m", *path
);
5579 static int set_property(int argc
, char *argv
[], void *userdata
) {
5580 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5581 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5582 _cleanup_free_
char *n
= NULL
;
5587 r
= acquire_bus(BUS_MANAGER
, &bus
);
5591 polkit_agent_open_maybe();
5593 r
= sd_bus_message_new_method_call(
5596 "org.freedesktop.systemd1",
5597 "/org/freedesktop/systemd1",
5598 "org.freedesktop.systemd1.Manager",
5599 "SetUnitProperties");
5601 return bus_log_create_error(r
);
5603 r
= unit_name_mangle(argv
[1], UNIT_NAME_NOGLOB
, &n
);
5605 return log_error_errno(r
, "Failed to mangle unit name: %m");
5607 t
= unit_name_to_type(n
);
5609 log_error("Invalid unit type: %s", n
);
5613 r
= sd_bus_message_append(m
, "sb", n
, arg_runtime
);
5615 return bus_log_create_error(r
);
5617 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, "(sv)");
5619 return bus_log_create_error(r
);
5621 r
= bus_append_unit_property_assignment_many(m
, t
, strv_skip(argv
, 2));
5625 r
= sd_bus_message_close_container(m
);
5627 return bus_log_create_error(r
);
5629 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5631 return log_error_errno(r
, "Failed to set unit properties on %s: %s", n
, bus_error_message(&error
, r
));
5636 static int daemon_reload(int argc
, char *argv
[], void *userdata
) {
5637 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5638 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5643 r
= acquire_bus(BUS_MANAGER
, &bus
);
5647 polkit_agent_open_maybe();
5649 switch (arg_action
) {
5656 method
= "Reexecute";
5659 case ACTION_SYSTEMCTL
:
5660 method
= streq(argv
[0], "daemon-reexec") ? "Reexecute" :
5661 /* "daemon-reload" */ "Reload";
5665 assert_not_reached("Unexpected action");
5668 r
= sd_bus_message_new_method_call(
5671 "org.freedesktop.systemd1",
5672 "/org/freedesktop/systemd1",
5673 "org.freedesktop.systemd1.Manager",
5676 return bus_log_create_error(r
);
5678 /* Note we use an extra-long timeout here. This is because a reload or reexec means generators are rerun which
5679 * are timed out after DEFAULT_TIMEOUT_USEC. Let's use twice that time here, so that the generators can have
5680 * their timeout, and for everything else there's the same time budget in place. */
5682 r
= sd_bus_call(bus
, m
, DEFAULT_TIMEOUT_USEC
* 2, &error
, NULL
);
5684 /* On reexecution, we expect a disconnect, not a reply */
5685 if (IN_SET(r
, -ETIMEDOUT
, -ECONNRESET
) && streq(method
, "Reexecute"))
5688 if (r
< 0 && arg_action
== ACTION_SYSTEMCTL
)
5689 return log_error_errno(r
, "Failed to reload daemon: %s", bus_error_message(&error
, r
));
5691 /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
5692 * old ways of doing things, hence don't log any error in that case here. */
5694 return r
< 0 ? r
: 0;
5697 static int trivial_method(int argc
, char *argv
[], void *userdata
) {
5698 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5706 r
= acquire_bus(BUS_MANAGER
, &bus
);
5710 polkit_agent_open_maybe();
5713 streq(argv
[0], "clear-jobs") ||
5714 streq(argv
[0], "cancel") ? "ClearJobs" :
5715 streq(argv
[0], "reset-failed") ? "ResetFailed" :
5716 streq(argv
[0], "halt") ? "Halt" :
5717 streq(argv
[0], "reboot") ? "Reboot" :
5718 streq(argv
[0], "kexec") ? "KExec" :
5719 streq(argv
[0], "exit") ? "Exit" :
5720 /* poweroff */ "PowerOff";
5722 r
= sd_bus_call_method(
5724 "org.freedesktop.systemd1",
5725 "/org/freedesktop/systemd1",
5726 "org.freedesktop.systemd1.Manager",
5731 if (r
< 0 && arg_action
== ACTION_SYSTEMCTL
)
5732 return log_error_errno(r
, "Failed to execute operation: %s", bus_error_message(&error
, r
));
5734 /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
5735 * old ways of doing things, hence don't log any error in that case here. */
5737 return r
< 0 ? r
: 0;
5740 static int reset_failed(int argc
, char *argv
[], void *userdata
) {
5741 _cleanup_strv_free_
char **names
= NULL
;
5747 return trivial_method(argc
, argv
, userdata
);
5749 r
= acquire_bus(BUS_MANAGER
, &bus
);
5753 polkit_agent_open_maybe();
5755 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
5757 return log_error_errno(r
, "Failed to expand names: %m");
5759 STRV_FOREACH(name
, names
) {
5760 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5762 q
= sd_bus_call_method(
5764 "org.freedesktop.systemd1",
5765 "/org/freedesktop/systemd1",
5766 "org.freedesktop.systemd1.Manager",
5772 log_error_errno(q
, "Failed to reset failed state of unit %s: %s", *name
, bus_error_message(&error
, q
));
5781 static int print_variable(const char *s
) {
5783 _cleanup_free_
char *esc
= NULL
;
5785 sep
= strchr(s
, '=');
5787 log_error("Invalid environment block");
5791 esc
= shell_maybe_quote(sep
+ 1, ESCAPE_POSIX
);
5795 printf("%.*s=%s\n", (int)(sep
-s
), s
, esc
);
5799 static int show_environment(int argc
, char *argv
[], void *userdata
) {
5800 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5801 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5806 r
= acquire_bus(BUS_MANAGER
, &bus
);
5810 pager_open(arg_no_pager
, false);
5812 r
= sd_bus_get_property(
5814 "org.freedesktop.systemd1",
5815 "/org/freedesktop/systemd1",
5816 "org.freedesktop.systemd1.Manager",
5822 return log_error_errno(r
, "Failed to get environment: %s", bus_error_message(&error
, r
));
5824 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
5826 return bus_log_parse_error(r
);
5828 while ((r
= sd_bus_message_read_basic(reply
, SD_BUS_TYPE_STRING
, &text
)) > 0) {
5829 r
= print_variable(text
);
5834 return bus_log_parse_error(r
);
5836 r
= sd_bus_message_exit_container(reply
);
5838 return bus_log_parse_error(r
);
5843 static int switch_root(int argc
, char *argv
[], void *userdata
) {
5844 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5845 _cleanup_free_
char *cmdline_init
= NULL
;
5846 const char *root
, *init
;
5850 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
5851 log_error("Cannot switch root remotely.");
5855 if (argc
< 2 || argc
> 3) {
5856 log_error("Wrong number of arguments.");
5865 r
= parse_env_file("/proc/cmdline", WHITESPACE
,
5866 "init", &cmdline_init
,
5869 log_debug_errno(r
, "Failed to parse /proc/cmdline: %m");
5871 init
= cmdline_init
;
5874 init
= empty_to_null(init
);
5876 const char *root_systemd_path
= NULL
, *root_init_path
= NULL
;
5878 root_systemd_path
= strjoina(root
, "/" SYSTEMD_BINARY_PATH
);
5879 root_init_path
= strjoina(root
, "/", init
);
5881 /* If the passed init is actually the same as the
5882 * systemd binary, then let's suppress it. */
5883 if (files_same(root_init_path
, root_systemd_path
, 0) > 0)
5887 /* Instruct PID1 to exclude us from its killing spree applied during
5888 * the transition. Otherwise we would exit with a failure status even
5889 * though the switch to the new root has succeed. */
5890 argv_cmdline
[0] = '@';
5892 r
= acquire_bus(BUS_MANAGER
, &bus
);
5896 /* If we are slow to exit after the root switch, the new systemd instance
5897 * will send us a signal to terminate. Just ignore it and exit normally.
5898 * This way the unit does not end up as failed.
5900 r
= ignore_signals(SIGTERM
, -1);
5902 log_warning_errno(r
, "Failed to change disposition of SIGTERM to ignore: %m");
5904 log_debug("Switching root - root: %s; init: %s", root
, strna(init
));
5906 r
= sd_bus_call_method(
5908 "org.freedesktop.systemd1",
5909 "/org/freedesktop/systemd1",
5910 "org.freedesktop.systemd1.Manager",
5916 (void) default_signals(SIGTERM
, -1);
5918 return log_error_errno(r
, "Failed to switch root: %s", bus_error_message(&error
, r
));
5924 static int set_environment(int argc
, char *argv
[], void *userdata
) {
5925 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5926 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5934 r
= acquire_bus(BUS_MANAGER
, &bus
);
5938 polkit_agent_open_maybe();
5940 method
= streq(argv
[0], "set-environment")
5942 : "UnsetEnvironment";
5944 r
= sd_bus_message_new_method_call(
5947 "org.freedesktop.systemd1",
5948 "/org/freedesktop/systemd1",
5949 "org.freedesktop.systemd1.Manager",
5952 return bus_log_create_error(r
);
5954 r
= sd_bus_message_append_strv(m
, strv_skip(argv
, 1));
5956 return bus_log_create_error(r
);
5958 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5960 return log_error_errno(r
, "Failed to set environment: %s", bus_error_message(&error
, r
));
5965 static int import_environment(int argc
, char *argv
[], void *userdata
) {
5966 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5967 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5971 r
= acquire_bus(BUS_MANAGER
, &bus
);
5975 polkit_agent_open_maybe();
5977 r
= sd_bus_message_new_method_call(
5980 "org.freedesktop.systemd1",
5981 "/org/freedesktop/systemd1",
5982 "org.freedesktop.systemd1.Manager",
5985 return bus_log_create_error(r
);
5988 r
= sd_bus_message_append_strv(m
, environ
);
5992 r
= sd_bus_message_open_container(m
, 'a', "s");
5994 return bus_log_create_error(r
);
5996 STRV_FOREACH(a
, strv_skip(argv
, 1)) {
5998 if (!env_name_is_valid(*a
)) {
5999 log_error("Not a valid environment variable name: %s", *a
);
6003 STRV_FOREACH(b
, environ
) {
6006 eq
= startswith(*b
, *a
);
6007 if (eq
&& *eq
== '=') {
6009 r
= sd_bus_message_append(m
, "s", *b
);
6011 return bus_log_create_error(r
);
6018 r
= sd_bus_message_close_container(m
);
6021 return bus_log_create_error(r
);
6023 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
6025 return log_error_errno(r
, "Failed to import environment: %s", bus_error_message(&error
, r
));
6030 static int enable_sysv_units(const char *verb
, char **args
) {
6033 #if HAVE_SYSV_COMPAT
6034 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
6037 /* Processes all SysV units, and reshuffles the array so that afterwards only the native units remain */
6039 if (arg_scope
!= UNIT_FILE_SYSTEM
)
6042 if (getenv_bool("SYSTEMCTL_SKIP_SYSV") > 0)
6045 if (!STR_IN_SET(verb
,
6051 r
= lookup_paths_init(&paths
, arg_scope
, LOOKUP_PATHS_EXCLUDE_GENERATED
, arg_root
);
6058 const char *argv
[] = {
6059 ROOTLIBEXECDIR
"/systemd-sysv-install",
6066 _cleanup_free_
char *p
= NULL
, *q
= NULL
, *l
= NULL
;
6067 bool found_native
= false, found_sysv
;
6076 if (!endswith(name
, ".service"))
6079 if (path_is_absolute(name
))
6082 j
= unit_file_exists(arg_scope
, &paths
, name
);
6083 if (j
< 0 && !IN_SET(j
, -ELOOP
, -ERFKILL
, -EADDRNOTAVAIL
))
6084 return log_error_errno(j
, "Failed to lookup unit file state: %m");
6085 found_native
= j
!= 0;
6087 /* If we have both a native unit and a SysV script, enable/disable them both (below); for is-enabled,
6088 * prefer the native unit */
6089 if (found_native
&& streq(verb
, "is-enabled"))
6092 p
= path_join(arg_root
, SYSTEM_SYSVINIT_PATH
, name
);
6096 p
[strlen(p
) - STRLEN(".service")] = 0;
6097 found_sysv
= access(p
, F_OK
) >= 0;
6103 log_info("Synchronizing state of %s with SysV service script with %s.", name
, argv
[0]);
6105 log_info("%s is not a native service, redirecting to systemd-sysv-install.", name
);
6108 if (!isempty(arg_root
))
6109 argv
[c
++] = q
= strappend("--root=", arg_root
);
6112 argv
[c
++] = basename(p
);
6115 l
= strv_join((char**)argv
, " ");
6120 log_info("Executing: %s", l
);
6122 j
= safe_fork("(sysv)", FORK_RESET_SIGNALS
|FORK_DEATHSIG
|FORK_LOG
, &pid
);
6127 execv(argv
[0], (char**) argv
);
6128 log_error_errno(errno
, "Failed to execute %s: %m", argv
[0]);
6129 _exit(EXIT_FAILURE
);
6132 j
= wait_for_terminate(pid
, &status
);
6134 return log_error_errno(j
, "Failed to wait for child: %m");
6136 if (status
.si_code
== CLD_EXITED
) {
6137 if (streq(verb
, "is-enabled")) {
6138 if (status
.si_status
== 0) {
6147 } else if (status
.si_status
!= 0)
6148 return -EBADE
; /* We don't warn here, under the assumption the script already showed an explanation */
6150 log_error("Unexpected waitid() result.");
6157 /* Remove this entry, so that we don't try enabling it as native unit */
6160 assert(args
[f
] == name
);
6161 strv_remove(args
, name
);
6168 static int mangle_names(char **original_names
, char ***mangled_names
) {
6169 char **i
, **l
, **name
;
6172 l
= i
= new(char*, strv_length(original_names
) + 1);
6176 STRV_FOREACH(name
, original_names
) {
6178 /* When enabling units qualified path names are OK,
6179 * too, hence allow them explicitly. */
6181 if (is_path(*name
)) {
6188 r
= unit_name_mangle(*name
, UNIT_NAME_NOGLOB
, i
);
6192 return log_error_errno(r
, "Failed to mangle unit name: %m");
6205 static int normalize_filenames(char **names
) {
6209 STRV_FOREACH(u
, names
)
6210 if (!path_is_absolute(*u
)) {
6211 char* normalized_path
;
6213 if (!isempty(arg_root
)) {
6214 log_error("Non-absolute paths are not allowed when --root is used: %s", *u
);
6218 if (!strchr(*u
,'/')) {
6219 log_error("Link argument does contain at least one directory separator: %s", *u
);
6223 r
= path_make_absolute_cwd(*u
, &normalized_path
);
6227 free_and_replace(*u
, normalized_path
);
6233 static int normalize_names(char **names
, bool warn_if_path
) {
6235 bool was_path
= false;
6237 STRV_FOREACH(u
, names
) {
6243 r
= free_and_strdup(u
, basename(*u
));
6245 return log_error_errno(r
, "Failed to normalize unit file path: %m");
6250 if (warn_if_path
&& was_path
)
6251 log_warning("Warning: Can't execute disable on the unit file path. Proceeding with the unit name.");
6256 static int unit_exists(LookupPaths
*lp
, const char *unit
) {
6257 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6258 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6259 _cleanup_free_
char *path
= NULL
;
6260 static const struct bus_properties_map property_map
[] = {
6261 { "LoadState", "s", map_string_no_copy
, offsetof(UnitStatusInfo
, load_state
) },
6262 { "ActiveState", "s", map_string_no_copy
, offsetof(UnitStatusInfo
, active_state
)},
6265 UnitStatusInfo info
= {};
6269 if (unit_name_is_valid(unit
, UNIT_NAME_TEMPLATE
))
6270 return unit_find_template_path(unit
, lp
, NULL
, NULL
);
6272 path
= unit_dbus_path_from_name(unit
);
6276 r
= acquire_bus(BUS_MANAGER
, &bus
);
6280 r
= sd_bus_call_method(
6282 "org.freedesktop.systemd1",
6284 "org.freedesktop.DBus.Properties",
6290 return log_error_errno(r
, "Failed to get properties: %s", bus_error_message(&error
, r
));
6292 r
= bus_message_map_all_properties(reply
, property_map
, &error
, &info
);
6294 return log_error_errno(r
, "Failed to map properties: %s", bus_error_message(&error
, r
));
6296 return !streq_ptr(info
.load_state
, "not-found") || !streq_ptr(info
.active_state
, "inactive");
6299 static int enable_unit(int argc
, char *argv
[], void *userdata
) {
6300 _cleanup_strv_free_
char **names
= NULL
;
6301 const char *verb
= argv
[0];
6302 UnitFileChange
*changes
= NULL
;
6303 unsigned n_changes
= 0;
6304 int carries_install_info
= -1;
6305 bool ignore_carries_install_info
= arg_quiet
;
6311 r
= mangle_names(strv_skip(argv
, 1), &names
);
6315 r
= enable_sysv_units(verb
, names
);
6319 /* If the operation was fully executed by the SysV compat, let's finish early */
6320 if (strv_isempty(names
)) {
6321 if (arg_no_reload
|| install_client_side())
6323 return daemon_reload(argc
, argv
, userdata
);
6326 if (streq(verb
, "disable")) {
6327 r
= normalize_names(names
, true);
6332 if (streq(verb
, "link")) {
6333 r
= normalize_filenames(names
);
6338 if (install_client_side()) {
6339 UnitFileFlags flags
;
6341 flags
= args_to_flags();
6342 if (streq(verb
, "enable")) {
6343 r
= unit_file_enable(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6344 carries_install_info
= r
;
6345 } else if (streq(verb
, "disable"))
6346 r
= unit_file_disable(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6347 else if (streq(verb
, "reenable")) {
6348 r
= unit_file_reenable(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6349 carries_install_info
= r
;
6350 } else if (streq(verb
, "link"))
6351 r
= unit_file_link(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6352 else if (streq(verb
, "preset")) {
6353 r
= unit_file_preset(arg_scope
, flags
, arg_root
, names
, arg_preset_mode
, &changes
, &n_changes
);
6354 } else if (streq(verb
, "mask"))
6355 r
= unit_file_mask(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6356 else if (streq(verb
, "unmask"))
6357 r
= unit_file_unmask(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6358 else if (streq(verb
, "revert"))
6359 r
= unit_file_revert(arg_scope
, arg_root
, names
, &changes
, &n_changes
);
6361 assert_not_reached("Unknown verb");
6363 unit_file_dump_changes(r
, verb
, changes
, n_changes
, arg_quiet
);
6368 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
, *m
= NULL
;
6369 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6370 bool expect_carries_install_info
= false;
6371 bool send_runtime
= true, send_force
= true, send_preset_mode
= false;
6375 if (STR_IN_SET(verb
, "mask", "unmask")) {
6377 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
6379 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
6383 STRV_FOREACH(name
, names
) {
6384 r
= unit_exists(&lp
, *name
);
6388 log_notice("Unit %s does not exist, proceeding anyway.", *names
);
6392 r
= acquire_bus(BUS_MANAGER
, &bus
);
6396 polkit_agent_open_maybe();
6398 if (streq(verb
, "enable")) {
6399 method
= "EnableUnitFiles";
6400 expect_carries_install_info
= true;
6401 } else if (streq(verb
, "disable")) {
6402 method
= "DisableUnitFiles";
6404 } else if (streq(verb
, "reenable")) {
6405 method
= "ReenableUnitFiles";
6406 expect_carries_install_info
= true;
6407 } else if (streq(verb
, "link"))
6408 method
= "LinkUnitFiles";
6409 else if (streq(verb
, "preset")) {
6411 if (arg_preset_mode
!= UNIT_FILE_PRESET_FULL
) {
6412 method
= "PresetUnitFilesWithMode";
6413 send_preset_mode
= true;
6415 method
= "PresetUnitFiles";
6417 expect_carries_install_info
= true;
6418 ignore_carries_install_info
= true;
6419 } else if (streq(verb
, "mask"))
6420 method
= "MaskUnitFiles";
6421 else if (streq(verb
, "unmask")) {
6422 method
= "UnmaskUnitFiles";
6424 } else if (streq(verb
, "revert")) {
6425 method
= "RevertUnitFiles";
6426 send_runtime
= send_force
= false;
6428 assert_not_reached("Unknown verb");
6430 r
= sd_bus_message_new_method_call(
6433 "org.freedesktop.systemd1",
6434 "/org/freedesktop/systemd1",
6435 "org.freedesktop.systemd1.Manager",
6438 return bus_log_create_error(r
);
6440 r
= sd_bus_message_append_strv(m
, names
);
6442 return bus_log_create_error(r
);
6444 if (send_preset_mode
) {
6445 r
= sd_bus_message_append(m
, "s", unit_file_preset_mode_to_string(arg_preset_mode
));
6447 return bus_log_create_error(r
);
6451 r
= sd_bus_message_append(m
, "b", arg_runtime
);
6453 return bus_log_create_error(r
);
6457 r
= sd_bus_message_append(m
, "b", arg_force
);
6459 return bus_log_create_error(r
);
6462 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
6464 return log_error_errno(r
, "Failed to %s unit: %s", verb
, bus_error_message(&error
, r
));
6466 if (expect_carries_install_info
) {
6467 r
= sd_bus_message_read(reply
, "b", &carries_install_info
);
6469 return bus_log_parse_error(r
);
6472 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
6476 /* Try to reload if enabled */
6478 r
= daemon_reload(argc
, argv
, userdata
);
6483 if (carries_install_info
== 0 && !ignore_carries_install_info
)
6484 log_warning("The unit files have no installation config (WantedBy, RequiredBy, Also, Alias\n"
6485 "settings in the [Install] section, and DefaultInstance for template units).\n"
6486 "This means they are not meant to be enabled using systemctl.\n"
6487 "Possible reasons for having this kind of units are:\n"
6488 "1) A unit may be statically enabled by being symlinked from another unit's\n"
6489 " .wants/ or .requires/ directory.\n"
6490 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
6491 " a requirement dependency on it.\n"
6492 "3) A unit may be started when needed via activation (socket, path, timer,\n"
6493 " D-Bus, udev, scripted systemctl call, ...).\n"
6494 "4) In case of template units, the unit is meant to be enabled with some\n"
6495 " instance name specified.");
6497 if (arg_now
&& STR_IN_SET(argv
[0], "enable", "disable", "mask")) {
6501 r
= acquire_bus(BUS_MANAGER
, &bus
);
6505 len
= strv_length(names
);
6507 char *new_args
[len
+ 2];
6509 new_args
[0] = (char*) (streq(argv
[0], "enable") ? "start" : "stop");
6510 for (i
= 0; i
< len
; i
++)
6511 new_args
[i
+ 1] = basename(names
[i
]);
6512 new_args
[i
+ 1] = NULL
;
6514 r
= start_unit(len
+ 1, new_args
, userdata
);
6519 unit_file_changes_free(changes
, n_changes
);
6524 static int add_dependency(int argc
, char *argv
[], void *userdata
) {
6525 _cleanup_strv_free_
char **names
= NULL
;
6526 _cleanup_free_
char *target
= NULL
;
6527 const char *verb
= argv
[0];
6528 UnitFileChange
*changes
= NULL
;
6529 unsigned n_changes
= 0;
6536 r
= unit_name_mangle_with_suffix(argv
[1], UNIT_NAME_NOGLOB
, ".target", &target
);
6538 return log_error_errno(r
, "Failed to mangle unit name: %m");
6540 r
= mangle_names(strv_skip(argv
, 2), &names
);
6544 if (streq(verb
, "add-wants"))
6546 else if (streq(verb
, "add-requires"))
6547 dep
= UNIT_REQUIRES
;
6549 assert_not_reached("Unknown verb");
6551 if (install_client_side()) {
6552 r
= unit_file_add_dependency(arg_scope
, args_to_flags(), arg_root
, names
, target
, dep
, &changes
, &n_changes
);
6553 unit_file_dump_changes(r
, "add dependency on", changes
, n_changes
, arg_quiet
);
6558 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
, *m
= NULL
;
6559 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6562 r
= acquire_bus(BUS_MANAGER
, &bus
);
6566 polkit_agent_open_maybe();
6568 r
= sd_bus_message_new_method_call(
6571 "org.freedesktop.systemd1",
6572 "/org/freedesktop/systemd1",
6573 "org.freedesktop.systemd1.Manager",
6574 "AddDependencyUnitFiles");
6576 return bus_log_create_error(r
);
6578 r
= sd_bus_message_append_strv(m
, names
);
6580 return bus_log_create_error(r
);
6582 r
= sd_bus_message_append(m
, "ssbb", target
, unit_dependency_to_string(dep
), arg_runtime
, arg_force
);
6584 return bus_log_create_error(r
);
6586 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
6588 return log_error_errno(r
, "Failed to add dependency: %s", bus_error_message(&error
, r
));
6590 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
6594 if (arg_no_reload
) {
6599 r
= daemon_reload(argc
, argv
, userdata
);
6603 unit_file_changes_free(changes
, n_changes
);
6608 static int preset_all(int argc
, char *argv
[], void *userdata
) {
6609 UnitFileChange
*changes
= NULL
;
6610 unsigned n_changes
= 0;
6613 if (install_client_side()) {
6614 r
= unit_file_preset_all(arg_scope
, args_to_flags(), arg_root
, arg_preset_mode
, &changes
, &n_changes
);
6615 unit_file_dump_changes(r
, "preset", changes
, n_changes
, arg_quiet
);
6620 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6621 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6624 r
= acquire_bus(BUS_MANAGER
, &bus
);
6628 polkit_agent_open_maybe();
6630 r
= sd_bus_call_method(
6632 "org.freedesktop.systemd1",
6633 "/org/freedesktop/systemd1",
6634 "org.freedesktop.systemd1.Manager",
6635 "PresetAllUnitFiles",
6639 unit_file_preset_mode_to_string(arg_preset_mode
),
6643 return log_error_errno(r
, "Failed to preset all units: %s", bus_error_message(&error
, r
));
6645 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
6649 if (arg_no_reload
) {
6654 r
= daemon_reload(argc
, argv
, userdata
);
6658 unit_file_changes_free(changes
, n_changes
);
6663 static int show_installation_targets_client_side(const char *name
) {
6664 UnitFileChange
*changes
= NULL
;
6665 unsigned n_changes
= 0, i
;
6666 UnitFileFlags flags
;
6670 p
= STRV_MAKE(name
);
6671 flags
= UNIT_FILE_DRY_RUN
|
6672 (arg_runtime
? UNIT_FILE_RUNTIME
: 0);
6674 r
= unit_file_disable(UNIT_FILE_SYSTEM
, flags
, NULL
, p
, &changes
, &n_changes
);
6676 return log_error_errno(r
, "Failed to get file links for %s: %m", name
);
6678 for (i
= 0; i
< n_changes
; i
++)
6679 if (changes
[i
].type
== UNIT_FILE_UNLINK
)
6680 printf(" %s\n", changes
[i
].path
);
6685 static int show_installation_targets(sd_bus
*bus
, const char *name
) {
6686 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6687 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6691 r
= sd_bus_call_method(
6693 "org.freedesktop.systemd1",
6694 "/org/freedesktop/systemd1",
6695 "org.freedesktop.systemd1.Manager",
6699 "sb", name
, arg_runtime
);
6701 return log_error_errno(r
, "Failed to get unit file links for %s: %s", name
, bus_error_message(&error
, r
));
6703 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
6705 return bus_log_parse_error(r
);
6707 while ((r
= sd_bus_message_read(reply
, "s", &link
)) > 0)
6708 printf(" %s\n", link
);
6711 return bus_log_parse_error(r
);
6713 r
= sd_bus_message_exit_container(reply
);
6715 return bus_log_parse_error(r
);
6720 static int unit_is_enabled(int argc
, char *argv
[], void *userdata
) {
6722 _cleanup_strv_free_
char **names
= NULL
;
6727 r
= mangle_names(strv_skip(argv
, 1), &names
);
6731 r
= enable_sysv_units(argv
[0], names
);
6737 if (install_client_side()) {
6738 STRV_FOREACH(name
, names
) {
6739 UnitFileState state
;
6741 r
= unit_file_get_state(arg_scope
, arg_root
, *name
, &state
);
6743 return log_error_errno(r
, "Failed to get unit file state for %s: %m", *name
);
6747 UNIT_FILE_ENABLED_RUNTIME
,
6750 UNIT_FILE_GENERATED
))
6754 puts(unit_file_state_to_string(state
));
6756 r
= show_installation_targets_client_side(*name
);
6765 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6768 r
= acquire_bus(BUS_MANAGER
, &bus
);
6772 STRV_FOREACH(name
, names
) {
6773 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6776 r
= sd_bus_call_method(
6778 "org.freedesktop.systemd1",
6779 "/org/freedesktop/systemd1",
6780 "org.freedesktop.systemd1.Manager",
6786 return log_error_errno(r
, "Failed to get unit file state for %s: %s", *name
, bus_error_message(&error
, r
));
6788 r
= sd_bus_message_read(reply
, "s", &s
);
6790 return bus_log_parse_error(r
);
6792 if (STR_IN_SET(s
, "enabled", "enabled-runtime", "static", "indirect", "generated"))
6798 r
= show_installation_targets(bus
, *name
);
6806 return enabled
? EXIT_SUCCESS
: EXIT_FAILURE
;
6809 static int is_system_running(int argc
, char *argv
[], void *userdata
) {
6810 _cleanup_free_
char *state
= NULL
;
6814 if (running_in_chroot() > 0 || (arg_transport
== BUS_TRANSPORT_LOCAL
&& !sd_booted())) {
6817 return EXIT_FAILURE
;
6820 r
= acquire_bus(BUS_MANAGER
, &bus
);
6824 r
= sd_bus_get_property_string(
6826 "org.freedesktop.systemd1",
6827 "/org/freedesktop/systemd1",
6828 "org.freedesktop.systemd1.Manager",
6841 return streq(state
, "running") ? EXIT_SUCCESS
: EXIT_FAILURE
;
6844 static int create_edit_temp_file(const char *new_path
, const char *original_path
, char **ret_tmp_fn
) {
6845 _cleanup_free_
char *t
= NULL
;
6849 assert(original_path
);
6852 r
= tempfn_random(new_path
, NULL
, &t
);
6854 return log_error_errno(r
, "Failed to determine temporary filename for \"%s\": %m", new_path
);
6856 r
= mkdir_parents(new_path
, 0755);
6858 return log_error_errno(r
, "Failed to create directories for \"%s\": %m", new_path
);
6860 r
= copy_file(original_path
, t
, 0, 0644, 0, COPY_REFLINK
);
6865 return log_error_errno(r
, "Failed to create temporary file \"%s\": %m", t
);
6868 return log_error_errno(r
, "Failed to create temporary file for \"%s\": %m", new_path
);
6876 static int get_file_to_edit(
6877 const LookupPaths
*paths
,
6881 _cleanup_free_
char *path
= NULL
, *run
= NULL
;
6886 path
= strjoin(paths
->persistent_config
, "/", name
);
6891 run
= strjoin(paths
->runtime_config
, "/", name
);
6897 if (access(path
, F_OK
) >= 0) {
6898 log_error("Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.", run
, path
);
6912 static int unit_file_create_new(
6913 const LookupPaths
*paths
,
6914 const char *unit_name
,
6916 char **ret_new_path
,
6917 char **ret_tmp_path
) {
6919 char *tmp_new_path
, *tmp_tmp_path
, *ending
;
6923 assert(ret_new_path
);
6924 assert(ret_tmp_path
);
6926 ending
= strjoina(unit_name
, suffix
);
6927 r
= get_file_to_edit(paths
, ending
, &tmp_new_path
);
6931 r
= create_edit_temp_file(tmp_new_path
, tmp_new_path
, &tmp_tmp_path
);
6937 *ret_new_path
= tmp_new_path
;
6938 *ret_tmp_path
= tmp_tmp_path
;
6943 static int unit_file_create_copy(
6944 const LookupPaths
*paths
,
6945 const char *unit_name
,
6946 const char *fragment_path
,
6947 char **ret_new_path
,
6948 char **ret_tmp_path
) {
6950 char *tmp_new_path
, *tmp_tmp_path
;
6953 assert(fragment_path
);
6955 assert(ret_new_path
);
6956 assert(ret_tmp_path
);
6958 r
= get_file_to_edit(paths
, unit_name
, &tmp_new_path
);
6962 if (!path_equal(fragment_path
, tmp_new_path
) && access(tmp_new_path
, F_OK
) == 0) {
6965 r
= ask_char(&response
, "yn", "\"%s\" already exists. Overwrite with \"%s\"? [(y)es, (n)o] ", tmp_new_path
, fragment_path
);
6970 if (response
!= 'y') {
6971 log_warning("%s ignored", unit_name
);
6973 return -EKEYREJECTED
;
6977 r
= create_edit_temp_file(tmp_new_path
, fragment_path
, &tmp_tmp_path
);
6983 *ret_new_path
= tmp_new_path
;
6984 *ret_tmp_path
= tmp_tmp_path
;
6989 static int run_editor(char **paths
) {
6995 r
= safe_fork("(editor)", FORK_RESET_SIGNALS
|FORK_DEATHSIG
|FORK_LOG
, &pid
);
7000 char *editor
, **editor_args
= NULL
;
7001 char **tmp_path
, **original_path
, *p
;
7002 unsigned n_editor_args
= 0, i
= 1;
7005 argc
= strv_length(paths
)/2 + 1;
7007 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
7008 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
7009 * we try to execute well known editors
7011 editor
= getenv("SYSTEMD_EDITOR");
7013 editor
= getenv("EDITOR");
7015 editor
= getenv("VISUAL");
7017 if (!isempty(editor
)) {
7018 editor_args
= strv_split(editor
, WHITESPACE
);
7021 _exit(EXIT_FAILURE
);
7023 n_editor_args
= strv_length(editor_args
);
7024 argc
+= n_editor_args
- 1;
7026 args
= newa(const char*, argc
+ 1);
7028 if (n_editor_args
> 0) {
7029 args
[0] = editor_args
[0];
7030 for (; i
< n_editor_args
; i
++)
7031 args
[i
] = editor_args
[i
];
7034 STRV_FOREACH_PAIR(original_path
, tmp_path
, paths
) {
7035 args
[i
] = *tmp_path
;
7040 if (n_editor_args
> 0)
7041 execvp(args
[0], (char* const*) args
);
7043 FOREACH_STRING(p
, "editor", "nano", "vim", "vi") {
7045 execvp(p
, (char* const*) args
);
7046 /* We do not fail if the editor doesn't exist
7047 * because we want to try each one of them before
7050 if (errno
!= ENOENT
) {
7051 log_error_errno(errno
, "Failed to execute %s: %m", editor
);
7052 _exit(EXIT_FAILURE
);
7056 log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR, $EDITOR or $VISUAL.");
7057 _exit(EXIT_FAILURE
);
7060 r
= wait_for_terminate_and_check("editor", pid
, WAIT_LOG
);
7067 static int find_paths_to_edit(sd_bus
*bus
, char **names
, char ***paths
) {
7068 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
7075 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
7079 STRV_FOREACH(name
, names
) {
7080 _cleanup_free_
char *path
= NULL
, *new_path
= NULL
, *tmp_path
= NULL
, *tmp_name
= NULL
;
7081 const char *unit_name
;
7083 r
= unit_find_paths(bus
, *name
, &lp
, &path
, NULL
);
7091 log_error("Run 'systemctl edit%s --force %s' to create a new unit.",
7092 arg_scope
== UNIT_FILE_GLOBAL
? " --global" :
7093 arg_scope
== UNIT_FILE_USER
? " --user" : "",
7098 /* Create a new unit from scratch */
7100 r
= unit_file_create_new(&lp
, unit_name
,
7101 arg_full
? NULL
: ".d/override.conf",
7102 &new_path
, &tmp_path
);
7106 unit_name
= basename(path
);
7107 /* We follow unit aliases, but we need to propagate the instance */
7108 if (unit_name_is_valid(*name
, UNIT_NAME_INSTANCE
) &&
7109 unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
7110 _cleanup_free_
char *instance
= NULL
;
7112 r
= unit_name_to_instance(*name
, &instance
);
7116 r
= unit_name_replace_instance(unit_name
, instance
, &tmp_name
);
7120 unit_name
= tmp_name
;
7124 r
= unit_file_create_copy(&lp
, unit_name
, path
, &new_path
, &tmp_path
);
7126 r
= unit_file_create_new(&lp
, unit_name
, ".d/override.conf", &new_path
, &tmp_path
);
7131 r
= strv_push_pair(paths
, new_path
, tmp_path
);
7134 new_path
= tmp_path
= NULL
;
7140 static int edit(int argc
, char *argv
[], void *userdata
) {
7141 _cleanup_strv_free_
char **names
= NULL
;
7142 _cleanup_strv_free_
char **paths
= NULL
;
7143 char **original
, **tmp
;
7148 log_error("Cannot edit units if not on a tty.");
7152 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
7153 log_error("Cannot edit units remotely.");
7157 r
= acquire_bus(BUS_MANAGER
, &bus
);
7161 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
7163 return log_error_errno(r
, "Failed to expand names: %m");
7165 r
= find_paths_to_edit(bus
, names
, &paths
);
7169 if (strv_isempty(paths
))
7172 r
= run_editor(paths
);
7176 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
7177 /* If the temporary file is empty we ignore it. It's
7178 * useful if the user wants to cancel its modification
7180 if (null_or_empty_path(*tmp
)) {
7181 log_warning("Editing \"%s\" canceled: temporary file is empty.", *original
);
7185 r
= rename(*tmp
, *original
);
7187 r
= log_error_errno(errno
, "Failed to rename \"%s\" to \"%s\": %m", *tmp
, *original
);
7194 if (!arg_no_reload
&& !install_client_side())
7195 r
= daemon_reload(argc
, argv
, userdata
);
7198 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
7199 (void) unlink(*tmp
);
7201 /* Removing empty dropin dirs */
7203 _cleanup_free_
char *dir
;
7205 dir
= dirname_malloc(*original
);
7209 /* no need to check if the dir is empty, rmdir
7210 * does nothing if it is not the case.
7219 static void systemctl_help(void) {
7221 pager_open(arg_no_pager
, false);
7223 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
7224 "Query or send control commands to the systemd manager.\n\n"
7225 " -h --help Show this help\n"
7226 " --version Show package version\n"
7227 " --system Connect to system manager\n"
7228 " --user Connect to user service manager\n"
7229 " -H --host=[USER@]HOST\n"
7230 " Operate on remote host\n"
7231 " -M --machine=CONTAINER\n"
7232 " Operate on local container\n"
7233 " -t --type=TYPE List units of a particular type\n"
7234 " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n"
7235 " -p --property=NAME Show only properties by this name\n"
7236 " -a --all Show all properties/all units currently in memory,\n"
7237 " including dead/empty ones. To list all units installed on\n"
7238 " the system, use the 'list-unit-files' command instead.\n"
7239 " --failed Same as --state=failed\n"
7240 " -l --full Don't ellipsize unit names on output\n"
7241 " -r --recursive Show unit list of host and local containers\n"
7242 " --reverse Show reverse dependencies with 'list-dependencies'\n"
7243 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
7244 " queueing a new job\n"
7245 " --show-types When showing sockets, explicitly show their type\n"
7246 " --value When showing properties, only print the value\n"
7247 " -i --ignore-inhibitors\n"
7248 " When shutting down or sleeping, ignore inhibitors\n"
7249 " --kill-who=WHO Who to send signal to\n"
7250 " -s --signal=SIGNAL Which signal to send\n"
7251 " --now Start or stop unit in addition to enabling or disabling it\n"
7252 " --dry-run Only print what would be done\n"
7253 " -q --quiet Suppress output\n"
7254 " --wait For (re)start, wait until service stopped again\n"
7255 " --no-block Do not wait until operation finished\n"
7256 " --no-wall Don't send wall message before halt/power-off/reboot\n"
7257 " --no-reload Don't reload daemon after en-/dis-abling unit files\n"
7258 " --no-legend Do not print a legend (column headers and hints)\n"
7259 " --no-pager Do not pipe output into a pager\n"
7260 " --no-ask-password\n"
7261 " Do not ask for system passwords\n"
7262 " --global Enable/disable/mask unit files globally\n"
7263 " --runtime Enable/disable/mask unit files temporarily until next\n"
7265 " -f --force When enabling unit files, override existing symlinks\n"
7266 " When shutting down, execute action immediately\n"
7267 " --preset-mode= Apply only enable, only disable, or all presets\n"
7268 " --root=PATH Enable/disable/mask unit files in the specified root\n"
7270 " -n --lines=INTEGER Number of journal entries to show\n"
7271 " -o --output=STRING Change journal output mode (short, short-precise,\n"
7272 " short-iso, short-iso-precise, short-full,\n"
7273 " short-monotonic, short-unix,\n"
7274 " verbose, export, json, json-pretty, json-sse, cat)\n"
7275 " --firmware-setup Tell the firmware to show the setup menu on next boot\n"
7276 " --plain Print unit dependencies as a list instead of a tree\n\n"
7278 " list-units [PATTERN...] List units currently in memory\n"
7279 " list-sockets [PATTERN...] List socket units currently in memory, ordered\n"
7281 " list-timers [PATTERN...] List timer units currently in memory, ordered\n"
7283 " start NAME... Start (activate) one or more units\n"
7284 " stop NAME... Stop (deactivate) one or more units\n"
7285 " reload NAME... Reload one or more units\n"
7286 " restart NAME... Start or restart one or more units\n"
7287 " try-restart NAME... Restart one or more units if active\n"
7288 " reload-or-restart NAME... Reload one or more units if possible,\n"
7289 " otherwise start or restart\n"
7290 " try-reload-or-restart NAME... If active, reload one or more units,\n"
7291 " if supported, otherwise restart\n"
7292 " isolate NAME Start one unit and stop all others\n"
7293 " kill NAME... Send signal to processes of a unit\n"
7294 " is-active PATTERN... Check whether units are active\n"
7295 " is-failed PATTERN... Check whether units are failed\n"
7296 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
7297 " show [PATTERN...|JOB...] Show properties of one or more\n"
7298 " units/jobs or the manager\n"
7299 " cat PATTERN... Show files and drop-ins of one or more units\n"
7300 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
7301 " help PATTERN...|PID... Show manual for one or more units\n"
7302 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
7304 " list-dependencies [NAME] Recursively show units which are required\n"
7305 " or wanted by this unit or by which this\n"
7306 " unit is required or wanted\n\n"
7307 "Unit File Commands:\n"
7308 " list-unit-files [PATTERN...] List installed unit files\n"
7309 " enable [NAME...|PATH...] Enable one or more unit files\n"
7310 " disable NAME... Disable one or more unit files\n"
7311 " reenable NAME... Reenable one or more unit files\n"
7312 " preset NAME... Enable/disable one or more unit files\n"
7313 " based on preset configuration\n"
7314 " preset-all Enable/disable all unit files based on\n"
7315 " preset configuration\n"
7316 " is-enabled NAME... Check whether unit files are enabled\n"
7317 " mask NAME... Mask one or more units\n"
7318 " unmask NAME... Unmask one or more units\n"
7319 " link PATH... Link one or more units files into\n"
7320 " the search path\n"
7321 " revert NAME... Revert one or more unit files to vendor\n"
7323 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
7324 " on specified one or more units\n"
7325 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
7326 " on specified one or more units\n"
7327 " edit NAME... Edit one or more unit files\n"
7328 " get-default Get the name of the default target\n"
7329 " set-default NAME Set the default target\n\n"
7330 "Machine Commands:\n"
7331 " list-machines [PATTERN...] List local containers and host\n\n"
7333 " list-jobs [PATTERN...] List jobs\n"
7334 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
7335 "Environment Commands:\n"
7336 " show-environment Dump environment\n"
7337 " set-environment NAME=VALUE... Set one or more environment variables\n"
7338 " unset-environment NAME... Unset one or more environment variables\n"
7339 " import-environment [NAME...] Import all or some environment variables\n\n"
7340 "Manager Lifecycle Commands:\n"
7341 " daemon-reload Reload systemd manager configuration\n"
7342 " daemon-reexec Reexecute systemd manager\n\n"
7343 "System Commands:\n"
7344 " is-system-running Check whether system is fully running\n"
7345 " default Enter system default mode\n"
7346 " rescue Enter system rescue mode\n"
7347 " emergency Enter system emergency mode\n"
7348 " halt Shut down and halt the system\n"
7349 " poweroff Shut down and power-off the system\n"
7350 " reboot [ARG] Shut down and reboot the system\n"
7351 " kexec Shut down and reboot the system with kexec\n"
7352 " exit [EXIT_CODE] Request user instance or container exit\n"
7353 " switch-root ROOT [INIT] Change to a different root file system\n"
7354 " suspend Suspend the system\n"
7355 " hibernate Hibernate the system\n"
7356 " hybrid-sleep Hibernate and suspend the system\n",
7357 program_invocation_short_name
);
7360 static void halt_help(void) {
7361 printf("%s [OPTIONS...]%s\n\n"
7362 "%s the system.\n\n"
7363 " --help Show this help\n"
7364 " --halt Halt the machine\n"
7365 " -p --poweroff Switch off the machine\n"
7366 " --reboot Reboot the machine\n"
7367 " -f --force Force immediate halt/power-off/reboot\n"
7368 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
7369 " -d --no-wtmp Don't write wtmp record\n"
7370 " --no-wall Don't send wall message before halt/power-off/reboot\n",
7371 program_invocation_short_name
,
7372 arg_action
== ACTION_REBOOT
? " [ARG]" : "",
7373 arg_action
== ACTION_REBOOT
? "Reboot" :
7374 arg_action
== ACTION_POWEROFF
? "Power off" :
7378 static void shutdown_help(void) {
7379 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
7380 "Shut down the system.\n\n"
7381 " --help Show this help\n"
7382 " -H --halt Halt the machine\n"
7383 " -P --poweroff Power-off the machine\n"
7384 " -r --reboot Reboot the machine\n"
7385 " -h Equivalent to --poweroff, overridden by --halt\n"
7386 " -k Don't halt/power-off/reboot, just send warnings\n"
7387 " --no-wall Don't send wall message before halt/power-off/reboot\n"
7388 " -c Cancel a pending shutdown\n",
7389 program_invocation_short_name
);
7392 static void telinit_help(void) {
7393 printf("%s [OPTIONS...] {COMMAND}\n\n"
7394 "Send control commands to the init daemon.\n\n"
7395 " --help Show this help\n"
7396 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
7398 " 0 Power-off the machine\n"
7399 " 6 Reboot the machine\n"
7400 " 2, 3, 4, 5 Start runlevelX.target unit\n"
7401 " 1, s, S Enter rescue mode\n"
7402 " q, Q Reload init daemon configuration\n"
7403 " u, U Reexecute init daemon\n",
7404 program_invocation_short_name
);
7407 static void runlevel_help(void) {
7408 printf("%s [OPTIONS...]\n\n"
7409 "Prints the previous and current runlevel of the init system.\n\n"
7410 " --help Show this help\n",
7411 program_invocation_short_name
);
7414 static void help_types(void) {
7418 puts("Available unit types:");
7419 for (i
= 0; i
< _UNIT_TYPE_MAX
; i
++)
7420 puts(unit_type_to_string(i
));
7423 static void help_states(void) {
7427 puts("Available unit load states:");
7428 for (i
= 0; i
< _UNIT_LOAD_STATE_MAX
; i
++)
7429 puts(unit_load_state_to_string(i
));
7432 puts("\nAvailable unit active states:");
7433 for (i
= 0; i
< _UNIT_ACTIVE_STATE_MAX
; i
++)
7434 puts(unit_active_state_to_string(i
));
7437 puts("\nAvailable automount unit substates:");
7438 for (i
= 0; i
< _AUTOMOUNT_STATE_MAX
; i
++)
7439 puts(automount_state_to_string(i
));
7442 puts("\nAvailable device unit substates:");
7443 for (i
= 0; i
< _DEVICE_STATE_MAX
; i
++)
7444 puts(device_state_to_string(i
));
7447 puts("\nAvailable mount unit substates:");
7448 for (i
= 0; i
< _MOUNT_STATE_MAX
; i
++)
7449 puts(mount_state_to_string(i
));
7452 puts("\nAvailable path unit substates:");
7453 for (i
= 0; i
< _PATH_STATE_MAX
; i
++)
7454 puts(path_state_to_string(i
));
7457 puts("\nAvailable scope unit substates:");
7458 for (i
= 0; i
< _SCOPE_STATE_MAX
; i
++)
7459 puts(scope_state_to_string(i
));
7462 puts("\nAvailable service unit substates:");
7463 for (i
= 0; i
< _SERVICE_STATE_MAX
; i
++)
7464 puts(service_state_to_string(i
));
7467 puts("\nAvailable slice unit substates:");
7468 for (i
= 0; i
< _SLICE_STATE_MAX
; i
++)
7469 puts(slice_state_to_string(i
));
7472 puts("\nAvailable socket unit substates:");
7473 for (i
= 0; i
< _SOCKET_STATE_MAX
; i
++)
7474 puts(socket_state_to_string(i
));
7477 puts("\nAvailable swap unit substates:");
7478 for (i
= 0; i
< _SWAP_STATE_MAX
; i
++)
7479 puts(swap_state_to_string(i
));
7482 puts("\nAvailable target unit substates:");
7483 for (i
= 0; i
< _TARGET_STATE_MAX
; i
++)
7484 puts(target_state_to_string(i
));
7487 puts("\nAvailable timer unit substates:");
7488 for (i
= 0; i
< _TIMER_STATE_MAX
; i
++)
7489 puts(timer_state_to_string(i
));
7492 static int systemctl_parse_argv(int argc
, char *argv
[]) {
7502 ARG_IGNORE_DEPENDENCIES
,
7515 ARG_NO_ASK_PASSWORD
,
7529 static const struct option options
[] = {
7530 { "help", no_argument
, NULL
, 'h' },
7531 { "version", no_argument
, NULL
, ARG_VERSION
},
7532 { "type", required_argument
, NULL
, 't' },
7533 { "property", required_argument
, NULL
, 'p' },
7534 { "all", no_argument
, NULL
, 'a' },
7535 { "reverse", no_argument
, NULL
, ARG_REVERSE
},
7536 { "after", no_argument
, NULL
, ARG_AFTER
},
7537 { "before", no_argument
, NULL
, ARG_BEFORE
},
7538 { "show-types", no_argument
, NULL
, ARG_SHOW_TYPES
},
7539 { "failed", no_argument
, NULL
, ARG_FAILED
}, /* compatibility only */
7540 { "full", no_argument
, NULL
, 'l' },
7541 { "job-mode", required_argument
, NULL
, ARG_JOB_MODE
},
7542 { "fail", no_argument
, NULL
, ARG_FAIL
}, /* compatibility only */
7543 { "irreversible", no_argument
, NULL
, ARG_IRREVERSIBLE
}, /* compatibility only */
7544 { "ignore-dependencies", no_argument
, NULL
, ARG_IGNORE_DEPENDENCIES
}, /* compatibility only */
7545 { "ignore-inhibitors", no_argument
, NULL
, 'i' },
7546 { "value", no_argument
, NULL
, ARG_VALUE
},
7547 { "user", no_argument
, NULL
, ARG_USER
},
7548 { "system", no_argument
, NULL
, ARG_SYSTEM
},
7549 { "global", no_argument
, NULL
, ARG_GLOBAL
},
7550 { "wait", no_argument
, NULL
, ARG_WAIT
},
7551 { "no-block", no_argument
, NULL
, ARG_NO_BLOCK
},
7552 { "no-legend", no_argument
, NULL
, ARG_NO_LEGEND
},
7553 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
7554 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7555 { "dry-run", no_argument
, NULL
, ARG_DRY_RUN
},
7556 { "quiet", no_argument
, NULL
, 'q' },
7557 { "root", required_argument
, NULL
, ARG_ROOT
},
7558 { "force", no_argument
, NULL
, ARG_FORCE
},
7559 { "no-reload", no_argument
, NULL
, ARG_NO_RELOAD
},
7560 { "kill-who", required_argument
, NULL
, ARG_KILL_WHO
},
7561 { "signal", required_argument
, NULL
, 's' },
7562 { "no-ask-password", no_argument
, NULL
, ARG_NO_ASK_PASSWORD
},
7563 { "host", required_argument
, NULL
, 'H' },
7564 { "machine", required_argument
, NULL
, 'M' },
7565 { "runtime", no_argument
, NULL
, ARG_RUNTIME
},
7566 { "lines", required_argument
, NULL
, 'n' },
7567 { "output", required_argument
, NULL
, 'o' },
7568 { "plain", no_argument
, NULL
, ARG_PLAIN
},
7569 { "state", required_argument
, NULL
, ARG_STATE
},
7570 { "recursive", no_argument
, NULL
, 'r' },
7571 { "preset-mode", required_argument
, NULL
, ARG_PRESET_MODE
},
7572 { "firmware-setup", no_argument
, NULL
, ARG_FIRMWARE_SETUP
},
7573 { "now", no_argument
, NULL
, ARG_NOW
},
7574 { "message", required_argument
, NULL
, ARG_MESSAGE
},
7584 /* we default to allowing interactive authorization only in systemctl (not in the legacy commands) */
7585 arg_ask_password
= true;
7587 while ((c
= getopt_long(argc
, argv
, "ht:p:alqfs:H:M:n:o:ir", options
, NULL
)) >= 0)
7599 if (isempty(optarg
)) {
7600 log_error("--type= requires arguments.");
7604 for (p
= optarg
;;) {
7605 _cleanup_free_
char *type
= NULL
;
7607 r
= extract_first_word(&p
, &type
, ",", 0);
7609 return log_error_errno(r
, "Failed to parse type: %s", optarg
);
7613 if (streq(type
, "help")) {
7618 if (unit_type_from_string(type
) >= 0) {
7619 if (strv_push(&arg_types
, type
) < 0)
7625 /* It's much nicer to use --state= for
7626 * load states, but let's support this
7627 * in --types= too for compatibility
7628 * with old versions */
7629 if (unit_load_state_from_string(type
) >= 0) {
7630 if (strv_push(&arg_states
, type
) < 0)
7636 log_error("Unknown unit type or load state '%s'.", type
);
7637 log_info("Use -t help to see a list of allowed values.");
7645 /* Make sure that if the empty property list
7646 was specified, we won't show any properties. */
7647 if (isempty(optarg
) && !arg_properties
) {
7648 arg_properties
= new0(char*, 1);
7649 if (!arg_properties
)
7652 for (p
= optarg
;;) {
7653 _cleanup_free_
char *prop
= NULL
;
7655 r
= extract_first_word(&p
, &prop
, ",", 0);
7657 return log_error_errno(r
, "Failed to parse property: %s", optarg
);
7661 if (strv_push(&arg_properties
, prop
) < 0)
7667 /* If the user asked for a particular
7668 * property, show it to him, even if it is
7680 arg_dependency
= DEPENDENCY_REVERSE
;
7684 arg_dependency
= DEPENDENCY_AFTER
;
7685 arg_jobs_after
= true;
7689 arg_dependency
= DEPENDENCY_BEFORE
;
7690 arg_jobs_before
= true;
7693 case ARG_SHOW_TYPES
:
7694 arg_show_types
= true;
7702 arg_job_mode
= optarg
;
7706 arg_job_mode
= "fail";
7709 case ARG_IRREVERSIBLE
:
7710 arg_job_mode
= "replace-irreversibly";
7713 case ARG_IGNORE_DEPENDENCIES
:
7714 arg_job_mode
= "ignore-dependencies";
7718 arg_scope
= UNIT_FILE_USER
;
7722 arg_scope
= UNIT_FILE_SYSTEM
;
7726 arg_scope
= UNIT_FILE_GLOBAL
;
7734 arg_no_block
= true;
7738 arg_no_legend
= true;
7742 arg_no_pager
= true;
7750 r
= parse_path_argument_and_warn(optarg
, false, &arg_root
);
7760 if (strv_extend(&arg_states
, "failed") < 0)
7782 arg_no_reload
= true;
7786 arg_kill_who
= optarg
;
7790 arg_signal
= signal_from_string_try_harder(optarg
);
7791 if (arg_signal
< 0) {
7792 log_error("Failed to parse signal string %s.", optarg
);
7797 case ARG_NO_ASK_PASSWORD
:
7798 arg_ask_password
= false;
7802 arg_transport
= BUS_TRANSPORT_REMOTE
;
7807 arg_transport
= BUS_TRANSPORT_MACHINE
;
7816 if (safe_atou(optarg
, &arg_lines
) < 0) {
7817 log_error("Failed to parse lines '%s'", optarg
);
7823 arg_output
= output_mode_from_string(optarg
);
7824 if (arg_output
< 0) {
7825 log_error("Unknown output '%s'.", optarg
);
7831 arg_ignore_inhibitors
= true;
7838 case ARG_FIRMWARE_SETUP
:
7839 arg_firmware_setup
= true;
7843 if (isempty(optarg
)) {
7844 log_error("--state= requires arguments.");
7848 for (p
= optarg
;;) {
7849 _cleanup_free_
char *s
= NULL
;
7851 r
= extract_first_word(&p
, &s
, ",", 0);
7853 return log_error_errno(r
, "Failed to parse state: %s", optarg
);
7857 if (streq(s
, "help")) {
7862 if (strv_push(&arg_states
, s
) < 0)
7871 if (geteuid() != 0) {
7872 log_error("--recursive requires root privileges.");
7876 arg_recursive
= true;
7879 case ARG_PRESET_MODE
:
7881 arg_preset_mode
= unit_file_preset_mode_from_string(optarg
);
7882 if (arg_preset_mode
< 0) {
7883 log_error("Failed to parse preset mode: %s.", optarg
);
7894 if (strv_extend(&arg_wall
, optarg
) < 0)
7902 assert_not_reached("Unhandled option");
7905 if (arg_transport
!= BUS_TRANSPORT_LOCAL
&& arg_scope
!= UNIT_FILE_SYSTEM
) {
7906 log_error("Cannot access user instance remotely.");
7910 if (arg_wait
&& arg_no_block
) {
7911 log_error("--wait may not be combined with --no-block.");
7918 static int halt_parse_argv(int argc
, char *argv
[]) {
7927 static const struct option options
[] = {
7928 { "help", no_argument
, NULL
, ARG_HELP
},
7929 { "halt", no_argument
, NULL
, ARG_HALT
},
7930 { "poweroff", no_argument
, NULL
, 'p' },
7931 { "reboot", no_argument
, NULL
, ARG_REBOOT
},
7932 { "force", no_argument
, NULL
, 'f' },
7933 { "wtmp-only", no_argument
, NULL
, 'w' },
7934 { "no-wtmp", no_argument
, NULL
, 'd' },
7935 { "no-sync", no_argument
, NULL
, 'n' },
7936 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7945 if (utmp_get_runlevel(&runlevel
, NULL
) >= 0)
7946 if (IN_SET(runlevel
, '0', '6'))
7949 while ((c
= getopt_long(argc
, argv
, "pfwdnih", options
, NULL
)) >= 0)
7957 arg_action
= ACTION_HALT
;
7961 if (arg_action
!= ACTION_REBOOT
)
7962 arg_action
= ACTION_POWEROFF
;
7966 arg_action
= ACTION_REBOOT
;
7991 /* Compatibility nops */
7998 assert_not_reached("Unhandled option");
8001 if (arg_action
== ACTION_REBOOT
&& (argc
== optind
|| argc
== optind
+ 1)) {
8002 r
= update_reboot_parameter_and_warn(argc
== optind
+ 1 ? argv
[optind
] : NULL
);
8005 } else if (optind
< argc
) {
8006 log_error("Too many arguments.");
8013 static int parse_shutdown_time_spec(const char *t
, usec_t
*_u
) {
8017 if (streq(t
, "now"))
8019 else if (!strchr(t
, ':')) {
8022 if (safe_atou64(t
, &u
) < 0)
8025 *_u
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
* u
;
8034 hour
= strtol(t
, &e
, 10);
8035 if (errno
> 0 || *e
!= ':' || hour
< 0 || hour
> 23)
8038 minute
= strtol(e
+1, &e
, 10);
8039 if (errno
> 0 || *e
!= 0 || minute
< 0 || minute
> 59)
8042 n
= now(CLOCK_REALTIME
);
8043 s
= (time_t) (n
/ USEC_PER_SEC
);
8045 assert_se(localtime_r(&s
, &tm
));
8047 tm
.tm_hour
= (int) hour
;
8048 tm
.tm_min
= (int) minute
;
8051 assert_se(s
= mktime(&tm
));
8053 *_u
= (usec_t
) s
* USEC_PER_SEC
;
8056 *_u
+= USEC_PER_DAY
;
8062 static int shutdown_parse_argv(int argc
, char *argv
[]) {
8069 static const struct option options
[] = {
8070 { "help", no_argument
, NULL
, ARG_HELP
},
8071 { "halt", no_argument
, NULL
, 'H' },
8072 { "poweroff", no_argument
, NULL
, 'P' },
8073 { "reboot", no_argument
, NULL
, 'r' },
8074 { "kexec", no_argument
, NULL
, 'K' }, /* not documented extension */
8075 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
8085 while ((c
= getopt_long(argc
, argv
, "HPrhkKat:fFc", options
, NULL
)) >= 0)
8093 arg_action
= ACTION_HALT
;
8097 arg_action
= ACTION_POWEROFF
;
8102 arg_action
= ACTION_KEXEC
;
8104 arg_action
= ACTION_REBOOT
;
8108 arg_action
= ACTION_KEXEC
;
8112 if (arg_action
!= ACTION_HALT
)
8113 arg_action
= ACTION_POWEROFF
;
8125 case 't': /* Note that we also ignore any passed argument to -t, not just the -t itself */
8128 /* Compatibility nops */
8132 arg_action
= ACTION_CANCEL_SHUTDOWN
;
8139 assert_not_reached("Unhandled option");
8142 if (argc
> optind
&& arg_action
!= ACTION_CANCEL_SHUTDOWN
) {
8143 r
= parse_shutdown_time_spec(argv
[optind
], &arg_when
);
8145 log_error("Failed to parse time specification: %s", argv
[optind
]);
8149 arg_when
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
;
8151 if (argc
> optind
&& arg_action
== ACTION_CANCEL_SHUTDOWN
)
8152 /* No time argument for shutdown cancel */
8153 wall
= argv
+ optind
;
8154 else if (argc
> optind
+ 1)
8155 /* We skip the time argument */
8156 wall
= argv
+ optind
+ 1;
8159 arg_wall
= strv_copy(wall
);
8169 static int telinit_parse_argv(int argc
, char *argv
[]) {
8176 static const struct option options
[] = {
8177 { "help", no_argument
, NULL
, ARG_HELP
},
8178 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
8182 static const struct {
8186 { '0', ACTION_POWEROFF
},
8187 { '6', ACTION_REBOOT
},
8188 { '1', ACTION_RESCUE
},
8189 { '2', ACTION_RUNLEVEL2
},
8190 { '3', ACTION_RUNLEVEL3
},
8191 { '4', ACTION_RUNLEVEL4
},
8192 { '5', ACTION_RUNLEVEL5
},
8193 { 's', ACTION_RESCUE
},
8194 { 'S', ACTION_RESCUE
},
8195 { 'q', ACTION_RELOAD
},
8196 { 'Q', ACTION_RELOAD
},
8197 { 'u', ACTION_REEXEC
},
8198 { 'U', ACTION_REEXEC
}
8207 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
8222 assert_not_reached("Unhandled option");
8225 if (optind
>= argc
) {
8226 log_error("%s: required argument missing.", program_invocation_short_name
);
8230 if (optind
+ 1 < argc
) {
8231 log_error("Too many arguments.");
8235 if (strlen(argv
[optind
]) != 1) {
8236 log_error("Expected single character argument.");
8240 for (i
= 0; i
< ELEMENTSOF(table
); i
++)
8241 if (table
[i
].from
== argv
[optind
][0])
8244 if (i
>= ELEMENTSOF(table
)) {
8245 log_error("Unknown command '%s'.", argv
[optind
]);
8249 arg_action
= table
[i
].to
;
8256 static int runlevel_parse_argv(int argc
, char *argv
[]) {
8262 static const struct option options
[] = {
8263 { "help", no_argument
, NULL
, ARG_HELP
},
8272 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
8283 assert_not_reached("Unhandled option");
8286 if (optind
< argc
) {
8287 log_error("Too many arguments.");
8294 static int parse_argv(int argc
, char *argv
[]) {
8298 if (program_invocation_short_name
) {
8300 if (strstr(program_invocation_short_name
, "halt")) {
8301 arg_action
= ACTION_HALT
;
8302 return halt_parse_argv(argc
, argv
);
8303 } else if (strstr(program_invocation_short_name
, "poweroff")) {
8304 arg_action
= ACTION_POWEROFF
;
8305 return halt_parse_argv(argc
, argv
);
8306 } else if (strstr(program_invocation_short_name
, "reboot")) {
8308 arg_action
= ACTION_KEXEC
;
8310 arg_action
= ACTION_REBOOT
;
8311 return halt_parse_argv(argc
, argv
);
8312 } else if (strstr(program_invocation_short_name
, "shutdown")) {
8313 arg_action
= ACTION_POWEROFF
;
8314 return shutdown_parse_argv(argc
, argv
);
8315 } else if (strstr(program_invocation_short_name
, "init")) {
8317 if (sd_booted() > 0) {
8318 arg_action
= _ACTION_INVALID
;
8319 return telinit_parse_argv(argc
, argv
);
8321 /* Hmm, so some other init system is
8322 * running, we need to forward this
8323 * request to it. For now we simply
8324 * guess that it is Upstart. */
8326 execv(TELINIT
, argv
);
8328 log_error("Couldn't find an alternative telinit implementation to spawn.");
8332 } else if (strstr(program_invocation_short_name
, "runlevel")) {
8333 arg_action
= ACTION_RUNLEVEL
;
8334 return runlevel_parse_argv(argc
, argv
);
8338 arg_action
= ACTION_SYSTEMCTL
;
8339 return systemctl_parse_argv(argc
, argv
);
8342 #if HAVE_SYSV_COMPAT
8343 _pure_
static int action_to_runlevel(void) {
8345 static const char table
[_ACTION_MAX
] = {
8346 [ACTION_HALT
] = '0',
8347 [ACTION_POWEROFF
] = '0',
8348 [ACTION_REBOOT
] = '6',
8349 [ACTION_RUNLEVEL2
] = '2',
8350 [ACTION_RUNLEVEL3
] = '3',
8351 [ACTION_RUNLEVEL4
] = '4',
8352 [ACTION_RUNLEVEL5
] = '5',
8353 [ACTION_RESCUE
] = '1'
8356 assert(arg_action
>= 0 && arg_action
< _ACTION_MAX
);
8358 return table
[arg_action
];
8362 static int talk_initctl(void) {
8363 #if HAVE_SYSV_COMPAT
8364 struct init_request request
= {
8365 .magic
= INIT_MAGIC
,
8367 .cmd
= INIT_CMD_RUNLVL
8370 _cleanup_close_
int fd
= -1;
8374 rl
= action_to_runlevel();
8378 request
.runlevel
= rl
;
8380 fd
= open(INIT_FIFO
, O_WRONLY
|O_NDELAY
|O_CLOEXEC
|O_NOCTTY
);
8382 if (errno
== ENOENT
)
8385 return log_error_errno(errno
, "Failed to open "INIT_FIFO
": %m");
8388 r
= loop_write(fd
, &request
, sizeof(request
), false);
8390 return log_error_errno(r
, "Failed to write to "INIT_FIFO
": %m");
8398 static int systemctl_main(int argc
, char *argv
[]) {
8400 static const Verb verbs
[] = {
8401 { "list-units", VERB_ANY
, VERB_ANY
, VERB_DEFAULT
|VERB_ONLINE_ONLY
, list_units
},
8402 { "list-unit-files", VERB_ANY
, VERB_ANY
, 0, list_unit_files
},
8403 { "list-sockets", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, list_sockets
},
8404 { "list-timers", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, list_timers
},
8405 { "list-jobs", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, list_jobs
},
8406 { "list-machines", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
|VERB_MUST_BE_ROOT
, list_machines
},
8407 { "clear-jobs", VERB_ANY
, 1, VERB_ONLINE_ONLY
, trivial_method
},
8408 { "cancel", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, cancel_job
},
8409 { "start", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8410 { "stop", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8411 { "condstop", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
}, /* For compatibility with ALTLinux */
8412 { "reload", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8413 { "restart", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8414 { "try-restart", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8415 { "reload-or-restart", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8416 { "reload-or-try-restart", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
}, /* For compatbility with old systemctl <= 228 */
8417 { "try-reload-or-restart", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8418 { "force-reload", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
}, /* For compatibility with SysV */
8419 { "condreload", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
}, /* For compatibility with ALTLinux */
8420 { "condrestart", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
}, /* For compatibility with RH */
8421 { "isolate", 2, 2, VERB_ONLINE_ONLY
, start_unit
},
8422 { "kill", 2, VERB_ANY
, VERB_ONLINE_ONLY
, kill_unit
},
8423 { "is-active", 2, VERB_ANY
, VERB_ONLINE_ONLY
, check_unit_active
},
8424 { "check", 2, VERB_ANY
, VERB_ONLINE_ONLY
, check_unit_active
},
8425 { "is-failed", 2, VERB_ANY
, VERB_ONLINE_ONLY
, check_unit_failed
},
8426 { "show", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, show
},
8427 { "cat", 2, VERB_ANY
, VERB_ONLINE_ONLY
, cat
},
8428 { "status", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, show
},
8429 { "help", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, show
},
8430 { "daemon-reload", VERB_ANY
, 1, VERB_ONLINE_ONLY
, daemon_reload
},
8431 { "daemon-reexec", VERB_ANY
, 1, VERB_ONLINE_ONLY
, daemon_reload
},
8432 { "show-environment", VERB_ANY
, 1, VERB_ONLINE_ONLY
, show_environment
},
8433 { "set-environment", 2, VERB_ANY
, VERB_ONLINE_ONLY
, set_environment
},
8434 { "unset-environment", 2, VERB_ANY
, VERB_ONLINE_ONLY
, set_environment
},
8435 { "import-environment", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, import_environment
},
8436 { "halt", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8437 { "poweroff", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8438 { "reboot", VERB_ANY
, 2, VERB_ONLINE_ONLY
, start_system_special
},
8439 { "kexec", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8440 { "suspend", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8441 { "hibernate", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8442 { "hybrid-sleep", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8443 { "default", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_special
},
8444 { "rescue", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8445 { "emergency", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8446 { "exit", VERB_ANY
, 2, VERB_ONLINE_ONLY
, start_special
},
8447 { "reset-failed", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, reset_failed
},
8448 { "enable", 2, VERB_ANY
, 0, enable_unit
},
8449 { "disable", 2, VERB_ANY
, 0, enable_unit
},
8450 { "is-enabled", 2, VERB_ANY
, 0, unit_is_enabled
},
8451 { "reenable", 2, VERB_ANY
, 0, enable_unit
},
8452 { "preset", 2, VERB_ANY
, 0, enable_unit
},
8453 { "preset-all", VERB_ANY
, 1, 0, preset_all
},
8454 { "mask", 2, VERB_ANY
, 0, enable_unit
},
8455 { "unmask", 2, VERB_ANY
, 0, enable_unit
},
8456 { "link", 2, VERB_ANY
, 0, enable_unit
},
8457 { "revert", 2, VERB_ANY
, 0, enable_unit
},
8458 { "switch-root", 2, VERB_ANY
, VERB_ONLINE_ONLY
, switch_root
},
8459 { "list-dependencies", VERB_ANY
, 2, VERB_ONLINE_ONLY
, list_dependencies
},
8460 { "set-default", 2, 2, 0, set_default
},
8461 { "get-default", VERB_ANY
, 1, 0, get_default
},
8462 { "set-property", 3, VERB_ANY
, VERB_ONLINE_ONLY
, set_property
},
8463 { "is-system-running", VERB_ANY
, 1, 0, is_system_running
},
8464 { "add-wants", 3, VERB_ANY
, 0, add_dependency
},
8465 { "add-requires", 3, VERB_ANY
, 0, add_dependency
},
8466 { "edit", 2, VERB_ANY
, VERB_ONLINE_ONLY
, edit
},
8470 return dispatch_verb(argc
, argv
, verbs
, NULL
);
8473 static int reload_with_fallback(void) {
8475 /* First, try systemd via D-Bus. */
8476 if (daemon_reload(0, NULL
, NULL
) >= 0)
8479 /* Nothing else worked, so let's try signals */
8480 assert(IN_SET(arg_action
, ACTION_RELOAD
, ACTION_REEXEC
));
8482 if (kill(1, arg_action
== ACTION_RELOAD
? SIGHUP
: SIGTERM
) < 0)
8483 return log_error_errno(errno
, "kill() failed: %m");
8488 static int start_with_fallback(void) {
8490 /* First, try systemd via D-Bus. */
8491 if (start_unit(0, NULL
, NULL
) >= 0)
8494 /* Nothing else worked, so let's try /dev/initctl */
8495 if (talk_initctl() > 0)
8498 log_error("Failed to talk to init daemon.");
8502 static int halt_now(enum action a
) {
8505 /* The kernel will automaticall flush ATA disks and suchlike
8506 * on reboot(), but the file systems need to be synce'd
8507 * explicitly in advance. */
8508 if (!arg_no_sync
&& !arg_dry_run
)
8511 /* Make sure C-A-D is handled by the kernel from this point on... */
8513 (void) reboot(RB_ENABLE_CAD
);
8519 log_info("Halting.");
8522 (void) reboot(RB_HALT_SYSTEM
);
8525 case ACTION_POWEROFF
:
8527 log_info("Powering off.");
8530 (void) reboot(RB_POWER_OFF
);
8534 case ACTION_REBOOT
: {
8535 _cleanup_free_
char *param
= NULL
;
8537 r
= read_one_line_file("/run/systemd/reboot-param", ¶m
);
8538 if (r
< 0 && r
!= -ENOENT
)
8539 log_warning_errno(r
, "Failed to read reboot parameter file: %m");
8541 if (!isempty(param
)) {
8543 log_info("Rebooting with argument '%s'.", param
);
8545 (void) syscall(SYS_reboot
, LINUX_REBOOT_MAGIC1
, LINUX_REBOOT_MAGIC2
,
8546 LINUX_REBOOT_CMD_RESTART2
, param
);
8547 log_warning_errno(errno
, "Failed to reboot with parameter, retrying without: %m");
8552 log_info("Rebooting.");
8555 (void) reboot(RB_AUTOBOOT
);
8560 assert_not_reached("Unknown action.");
8564 static int logind_schedule_shutdown(void) {
8567 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
8568 char date
[FORMAT_TIMESTAMP_MAX
];
8573 r
= acquire_bus(BUS_FULL
, &bus
);
8577 switch (arg_action
) {
8581 case ACTION_POWEROFF
:
8582 action
= "poweroff";
8597 action
= strjoina("dry-", action
);
8599 (void) logind_set_wall_message();
8601 r
= sd_bus_call_method(
8603 "org.freedesktop.login1",
8604 "/org/freedesktop/login1",
8605 "org.freedesktop.login1.Manager",
8613 return log_warning_errno(r
, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s", bus_error_message(&error
, r
));
8616 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.", format_timestamp(date
, sizeof(date
), arg_when
));
8619 log_error("Cannot schedule shutdown without logind support, proceeding with immediate shutdown.");
8624 static int halt_main(void) {
8627 r
= logind_check_inhibitors(arg_action
);
8632 return logind_schedule_shutdown();
8634 if (geteuid() != 0) {
8635 if (arg_dry_run
|| arg_force
> 0) {
8636 (void) must_be_root();
8640 /* Try logind if we are a normal user and no special
8641 * mode applies. Maybe PolicyKit allows us to shutdown
8643 if (IN_SET(arg_action
, ACTION_POWEROFF
, ACTION_REBOOT
, ACTION_HALT
)) {
8644 r
= logind_reboot(arg_action
);
8647 if (IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
8648 /* requested operation is not
8649 * supported on the local system or
8650 * already in progress */
8652 /* on all other errors, try low-level operation */
8656 if (!arg_dry_run
&& !arg_force
)
8657 return start_with_fallback();
8659 assert(geteuid() == 0);
8662 if (sd_booted() > 0)
8663 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
8665 r
= utmp_put_shutdown();
8667 log_warning_errno(r
, "Failed to write utmp record: %m");
8674 r
= halt_now(arg_action
);
8675 return log_error_errno(r
, "Failed to reboot: %m");
8678 static int runlevel_main(void) {
8679 int r
, runlevel
, previous
;
8681 r
= utmp_get_runlevel(&runlevel
, &previous
);
8688 previous
<= 0 ? 'N' : previous
,
8689 runlevel
<= 0 ? 'N' : runlevel
);
8694 static int logind_cancel_shutdown(void) {
8696 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
8700 r
= acquire_bus(BUS_FULL
, &bus
);
8704 (void) logind_set_wall_message();
8706 r
= sd_bus_call_method(
8708 "org.freedesktop.login1",
8709 "/org/freedesktop/login1",
8710 "org.freedesktop.login1.Manager",
8711 "CancelScheduledShutdown",
8715 return log_warning_errno(r
, "Failed to talk to logind, shutdown hasn't been cancelled: %s", bus_error_message(&error
, r
));
8719 log_error("Not compiled with logind support, cannot cancel scheduled shutdowns.");
8724 int main(int argc
, char*argv
[]) {
8727 argv_cmdline
= argv
[0];
8729 setlocale(LC_ALL
, "");
8730 log_parse_environment();
8734 /* Explicitly not on_tty() to avoid setting cached value.
8735 * This becomes relevant for piping output which might be
8737 original_stdout_is_tty
= isatty(STDOUT_FILENO
);
8739 r
= parse_argv(argc
, argv
);
8743 if (arg_action
!= ACTION_SYSTEMCTL
&& running_in_chroot() > 0) {
8746 log_info("Running in chroot, ignoring request.");
8751 /* systemctl_main() will print an error message for the bus
8752 * connection, but only if it needs to */
8754 switch (arg_action
) {
8756 case ACTION_SYSTEMCTL
:
8757 r
= systemctl_main(argc
, argv
);
8760 /* Legacy command aliases set arg_action. They provide some fallbacks,
8761 * e.g. to tell sysvinit to reboot after you have installed systemd
8765 case ACTION_POWEROFF
:
8771 case ACTION_RUNLEVEL2
:
8772 case ACTION_RUNLEVEL3
:
8773 case ACTION_RUNLEVEL4
:
8774 case ACTION_RUNLEVEL5
:
8776 r
= start_with_fallback();
8781 r
= reload_with_fallback();
8784 case ACTION_CANCEL_SHUTDOWN
:
8785 r
= logind_cancel_shutdown();
8788 case ACTION_RUNLEVEL
:
8789 r
= runlevel_main();
8793 case ACTION_SUSPEND
:
8794 case ACTION_HIBERNATE
:
8795 case ACTION_HYBRID_SLEEP
:
8796 case ACTION_EMERGENCY
:
8797 case ACTION_DEFAULT
:
8798 /* systemctl verbs with no equivalent in the legacy commands.
8799 * These cannot appear in arg_action. Fall through. */
8801 case _ACTION_INVALID
:
8803 assert_not_reached("Unknown action");
8810 ask_password_agent_close();
8811 polkit_agent_close();
8813 strv_free(arg_types
);
8814 strv_free(arg_states
);
8815 strv_free(arg_properties
);
8817 strv_free(arg_wall
);
8821 /* Note that we return r here, not EXIT_SUCCESS, so that we can implement the LSB-like return codes */
8822 return r
< 0 ? EXIT_FAILURE
: r
;