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"
87 #include "unit-name.h"
88 #include "user-util.h"
90 #include "utmp-wtmp.h"
94 /* The init script exit status codes
95 0 program is running or service is OK
96 1 program is dead and /var/run pid file exists
97 2 program is dead and /var/lock lock file exists
98 3 program is not running
99 4 program or service status is unknown
100 5-99 reserved for future LSB use
101 100-149 reserved for distribution use
102 150-199 reserved for application use
106 EXIT_PROGRAM_RUNNING_OR_SERVICE_OK
= 0,
107 EXIT_PROGRAM_DEAD_AND_PID_EXISTS
= 1,
108 EXIT_PROGRAM_DEAD_AND_LOCK_FILE_EXISTS
= 2,
109 EXIT_PROGRAM_NOT_RUNNING
= 3,
110 EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN
= 4,
113 static char **arg_types
= NULL
;
114 static char **arg_states
= NULL
;
115 static char **arg_properties
= NULL
;
116 static bool arg_all
= false;
117 static enum dependency
{
123 } arg_dependency
= DEPENDENCY_FORWARD
;
124 static const char *arg_job_mode
= "replace";
125 static UnitFileScope arg_scope
= UNIT_FILE_SYSTEM
;
126 static bool arg_wait
= false;
127 static bool arg_no_block
= false;
128 static bool arg_no_legend
= false;
129 static bool arg_no_pager
= false;
130 static bool arg_no_wtmp
= false;
131 static bool arg_no_sync
= false;
132 static bool arg_no_wall
= false;
133 static bool arg_no_reload
= false;
134 static bool arg_value
= false;
135 static bool arg_show_types
= false;
136 static bool arg_ignore_inhibitors
= false;
137 static bool arg_dry_run
= false;
138 static bool arg_quiet
= false;
139 static bool arg_full
= false;
140 static bool arg_recursive
= false;
141 static int arg_force
= 0;
142 static bool arg_ask_password
= false;
143 static bool arg_runtime
= false;
144 static UnitFilePresetMode arg_preset_mode
= UNIT_FILE_PRESET_FULL
;
145 static char **arg_wall
= NULL
;
146 static const char *arg_kill_who
= NULL
;
147 static int arg_signal
= SIGTERM
;
148 static char *arg_root
= NULL
;
149 static usec_t arg_when
= 0;
150 static char *arg_esp_path
= NULL
;
151 static char *argv_cmdline
= NULL
;
172 ACTION_CANCEL_SHUTDOWN
,
175 } arg_action
= ACTION_SYSTEMCTL
;
176 static BusTransport arg_transport
= BUS_TRANSPORT_LOCAL
;
177 static const char *arg_host
= NULL
;
178 static unsigned arg_lines
= 10;
179 static OutputMode arg_output
= OUTPUT_SHORT
;
180 static bool arg_plain
= false;
181 static bool arg_firmware_setup
= false;
182 static bool arg_now
= false;
183 static bool arg_jobs_before
= false;
184 static bool arg_jobs_after
= false;
186 static int daemon_reload(int argc
, char *argv
[], void* userdata
);
187 static int trivial_method(int argc
, char *argv
[], void *userdata
);
188 static int halt_now(enum action a
);
189 static int get_state_one_unit(sd_bus
*bus
, const char *name
, UnitActiveState
*active_state
);
191 static bool original_stdout_is_tty
;
193 typedef enum BusFocus
{
194 BUS_FULL
, /* The full bus indicated via --system or --user */
195 BUS_MANAGER
, /* The manager itself, possibly directly, possibly via the bus */
199 static sd_bus
*busses
[_BUS_FOCUS_MAX
] = {};
201 static UnitFileFlags
args_to_flags(void) {
202 return (arg_runtime
? UNIT_FILE_RUNTIME
: 0) |
203 (arg_force
? UNIT_FILE_FORCE
: 0);
206 static int acquire_bus(BusFocus focus
, sd_bus
**ret
) {
209 assert(focus
< _BUS_FOCUS_MAX
);
212 /* We only go directly to the manager, if we are using a local transport */
213 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
216 if (getenv_bool("SYSTEMCTL_FORCE_BUS") > 0)
219 if (!busses
[focus
]) {
222 user
= arg_scope
!= UNIT_FILE_SYSTEM
;
224 if (!user
&& sd_booted() <= 0) {
225 /* Print a friendly message when the local system is actually not running systemd as PID 1. */
226 log_error("System has not been booted with systemd as init system (PID 1). Can't operate.");
230 if (focus
== BUS_MANAGER
)
231 r
= bus_connect_transport_systemd(arg_transport
, arg_host
, user
, &busses
[focus
]);
233 r
= bus_connect_transport(arg_transport
, arg_host
, user
, &busses
[focus
]);
235 return log_error_errno(r
, "Failed to connect to bus: %m");
237 (void) sd_bus_set_allow_interactive_authorization(busses
[focus
], arg_ask_password
);
240 *ret
= busses
[focus
];
244 static void release_busses(void) {
247 for (w
= 0; w
< _BUS_FOCUS_MAX
; w
++)
248 busses
[w
] = sd_bus_flush_close_unref(busses
[w
]);
251 static int map_string_no_copy(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
253 const char **p
= userdata
;
256 r
= sd_bus_message_read_basic(m
, SD_BUS_TYPE_STRING
, &s
);
266 static void ask_password_agent_open_if_enabled(void) {
268 /* Open the password agent as a child process if necessary */
273 if (!arg_ask_password
)
276 if (arg_scope
!= UNIT_FILE_SYSTEM
)
279 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
282 ask_password_agent_open();
285 static void polkit_agent_open_maybe(void) {
286 /* Open the polkit agent as a child process if necessary */
288 if (arg_scope
!= UNIT_FILE_SYSTEM
)
291 polkit_agent_open_if_enabled(arg_transport
, arg_ask_password
);
294 static OutputFlags
get_output_flags(void) {
296 arg_all
* OUTPUT_SHOW_ALL
|
297 (arg_full
|| !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH
|
298 colors_enabled() * OUTPUT_COLOR
|
299 !arg_quiet
* OUTPUT_WARN_CUTOFF
;
302 static int translate_bus_error_to_exit_status(int r
, const sd_bus_error
*error
) {
305 if (!sd_bus_error_is_set(error
))
308 if (sd_bus_error_has_name(error
, SD_BUS_ERROR_ACCESS_DENIED
) ||
309 sd_bus_error_has_name(error
, BUS_ERROR_ONLY_BY_DEPENDENCY
) ||
310 sd_bus_error_has_name(error
, BUS_ERROR_NO_ISOLATION
) ||
311 sd_bus_error_has_name(error
, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE
))
312 return EXIT_NOPERMISSION
;
314 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
))
315 return EXIT_NOTINSTALLED
;
317 if (sd_bus_error_has_name(error
, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE
) ||
318 sd_bus_error_has_name(error
, SD_BUS_ERROR_NOT_SUPPORTED
))
319 return EXIT_NOTIMPLEMENTED
;
321 if (sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
))
322 return EXIT_NOTCONFIGURED
;
330 static bool install_client_side(void) {
332 /* Decides when to execute enable/disable/... operations
333 * client-side rather than server-side. */
335 if (running_in_chroot() > 0)
338 if (sd_booted() <= 0)
341 if (!isempty(arg_root
))
344 if (arg_scope
== UNIT_FILE_GLOBAL
)
347 /* Unsupported environment variable, mostly for debugging purposes */
348 if (getenv_bool("SYSTEMCTL_INSTALL_CLIENT_SIDE") > 0)
354 static int compare_unit_info(const void *a
, const void *b
) {
355 const UnitInfo
*u
= a
, *v
= b
;
359 /* First, order by machine */
360 if (!u
->machine
&& v
->machine
)
362 if (u
->machine
&& !v
->machine
)
364 if (u
->machine
&& v
->machine
) {
365 r
= strcasecmp(u
->machine
, v
->machine
);
370 /* Second, order by unit type */
371 d1
= strrchr(u
->id
, '.');
372 d2
= strrchr(v
->id
, '.');
374 r
= strcasecmp(d1
, d2
);
379 /* Third, order by name */
380 return strcasecmp(u
->id
, v
->id
);
383 static const char* unit_type_suffix(const char *name
) {
386 dot
= strrchr(name
, '.');
393 static bool output_show_unit(const UnitInfo
*u
, char **patterns
) {
396 if (!strv_fnmatch_or_empty(patterns
, u
->id
, FNM_NOESCAPE
))
399 if (arg_types
&& !strv_find(arg_types
, unit_type_suffix(u
->id
)))
405 /* Note that '--all' is not purely a state filter, but also a
406 * filter that hides units that "follow" other units (which is
407 * used for device units that appear under different names). */
408 if (!isempty(u
->following
))
411 if (!strv_isempty(arg_states
))
414 /* By default show all units except the ones in inactive
415 * state and with no pending job */
419 if (streq(u
->active_state
, "inactive"))
425 static int output_units_list(const UnitInfo
*unit_infos
, unsigned c
) {
426 unsigned circle_len
= 0, id_len
, max_id_len
, load_len
, active_len
, sub_len
, job_len
, desc_len
, max_desc_len
;
428 unsigned n_shown
= 0;
431 max_id_len
= strlen("UNIT");
432 load_len
= strlen("LOAD");
433 active_len
= strlen("ACTIVE");
434 sub_len
= strlen("SUB");
435 job_len
= strlen("JOB");
436 max_desc_len
= strlen("DESCRIPTION");
438 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
439 max_id_len
= MAX(max_id_len
, strlen(u
->id
) + (u
->machine
? strlen(u
->machine
)+1 : 0));
440 load_len
= MAX(load_len
, strlen(u
->load_state
));
441 active_len
= MAX(active_len
, strlen(u
->active_state
));
442 sub_len
= MAX(sub_len
, strlen(u
->sub_state
));
443 max_desc_len
= MAX(max_desc_len
, strlen(u
->description
));
445 if (u
->job_id
!= 0) {
446 job_len
= MAX(job_len
, strlen(u
->job_type
));
450 if (!arg_no_legend
&&
451 (streq(u
->active_state
, "failed") ||
452 STR_IN_SET(u
->load_state
, "error", "not-found", "masked")))
456 if (!arg_full
&& original_stdout_is_tty
) {
459 id_len
= MIN(max_id_len
, 25u); /* as much as it needs, but at most 25 for now */
460 basic_len
= circle_len
+ 1 + id_len
+ 1 + load_len
+ 1 + active_len
+ 1 + sub_len
+ 1;
463 basic_len
+= job_len
+ 1;
465 if (basic_len
< (unsigned) columns()) {
466 unsigned extra_len
, incr
;
467 extra_len
= columns() - basic_len
;
469 /* Either UNIT already got 25, or is fully satisfied.
470 * Grant up to 25 to DESC now. */
471 incr
= MIN(extra_len
, 25u);
475 /* Of the remainder give as much as the ID needs to the ID, and give the rest to the
476 * description but not more than it needs. */
478 incr
= MIN(max_id_len
- id_len
, extra_len
);
480 desc_len
+= MIN(extra_len
- incr
, max_desc_len
- desc_len
);
486 desc_len
= max_desc_len
;
489 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
490 _cleanup_free_
char *e
= NULL
, *j
= NULL
;
491 const char *on_underline
= "", *off_underline
= "";
492 const char *on_loaded
= "", *off_loaded
= "";
493 const char *on_active
= "", *off_active
= "";
494 const char *on_circle
= "", *off_circle
= "";
496 bool circle
= false, underline
= false;
498 if (!n_shown
&& !arg_no_legend
) {
503 printf("%s%-*s %-*s %-*s %-*s ",
507 active_len
, "ACTIVE",
511 printf("%-*s ", job_len
, "JOB");
515 !arg_full
&& arg_no_pager
? (int) desc_len
: -1,
522 if (u
+ 1 < unit_infos
+ c
&&
523 !streq(unit_type_suffix(u
->id
), unit_type_suffix((u
+ 1)->id
))) {
524 on_underline
= ansi_underline();
525 off_underline
= ansi_normal();
529 if (STR_IN_SET(u
->load_state
, "error", "not-found", "masked") && !arg_plain
) {
530 on_circle
= ansi_highlight_yellow();
531 off_circle
= ansi_normal();
533 on_loaded
= underline
? ansi_highlight_red_underline() : ansi_highlight_red();
534 off_loaded
= underline
? on_underline
: ansi_normal();
535 } else if (streq(u
->active_state
, "failed") && !arg_plain
) {
536 on_circle
= ansi_highlight_red();
537 off_circle
= ansi_normal();
539 on_active
= underline
? ansi_highlight_red_underline() : ansi_highlight_red();
540 off_active
= underline
? on_underline
: ansi_normal();
544 j
= strjoin(u
->machine
, ":", u
->id
);
553 e
= ellipsize(id
, id_len
, 33);
561 printf("%s%s%s ", on_circle
, circle
? special_glyph(BLACK_CIRCLE
) : " ", off_circle
);
563 printf("%s%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
565 on_active
, id_len
, id
, off_active
,
566 on_loaded
, load_len
, u
->load_state
, off_loaded
,
567 on_active
, active_len
, u
->active_state
,
568 sub_len
, u
->sub_state
, off_active
,
569 job_count
? job_len
+ 1 : 0, u
->job_id
? u
->job_type
: "");
573 !arg_full
&& arg_no_pager
? (int) desc_len
: -1,
578 if (!arg_no_legend
) {
579 const char *on
, *off
;
583 "LOAD = Reflects whether the unit definition was properly loaded.\n"
584 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
585 "SUB = The low-level unit activation state, values depend on unit type.");
586 puts(job_count
? "JOB = Pending job for the unit.\n" : "");
587 on
= ansi_highlight();
590 on
= ansi_highlight_red();
595 printf("%s%u loaded units listed.%s\n"
596 "To show all installed unit files use 'systemctl list-unit-files'.\n",
599 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
600 "To show all installed unit files use 'systemctl list-unit-files'.\n",
607 static int get_unit_list(
611 UnitInfo
**unit_infos
,
613 sd_bus_message
**_reply
) {
615 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
616 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
617 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
621 bool fallback
= false;
627 r
= sd_bus_message_new_method_call(
630 "org.freedesktop.systemd1",
631 "/org/freedesktop/systemd1",
632 "org.freedesktop.systemd1.Manager",
633 "ListUnitsByPatterns");
635 return bus_log_create_error(r
);
637 r
= sd_bus_message_append_strv(m
, arg_states
);
639 return bus_log_create_error(r
);
641 r
= sd_bus_message_append_strv(m
, patterns
);
643 return bus_log_create_error(r
);
645 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
646 if (r
< 0 && (sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_METHOD
) ||
647 sd_bus_error_has_name(&error
, SD_BUS_ERROR_ACCESS_DENIED
))) {
648 /* Fallback to legacy ListUnitsFiltered method */
650 log_debug_errno(r
, "Failed to list units: %s Falling back to ListUnitsFiltered method.", bus_error_message(&error
, r
));
651 m
= sd_bus_message_unref(m
);
652 sd_bus_error_free(&error
);
654 r
= sd_bus_message_new_method_call(
657 "org.freedesktop.systemd1",
658 "/org/freedesktop/systemd1",
659 "org.freedesktop.systemd1.Manager",
660 "ListUnitsFiltered");
662 return bus_log_create_error(r
);
664 r
= sd_bus_message_append_strv(m
, arg_states
);
666 return bus_log_create_error(r
);
668 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
671 return log_error_errno(r
, "Failed to list units: %s", bus_error_message(&error
, r
));
673 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssssouso)");
675 return bus_log_parse_error(r
);
677 while ((r
= bus_parse_unit_info(reply
, &u
)) > 0) {
680 if (!output_show_unit(&u
, fallback
? patterns
: NULL
))
683 if (!GREEDY_REALLOC(*unit_infos
, size
, c
+1))
686 (*unit_infos
)[c
++] = u
;
689 return bus_log_parse_error(r
);
691 r
= sd_bus_message_exit_container(reply
);
693 return bus_log_parse_error(r
);
701 static void message_set_freep(Set
**set
) {
702 set_free_with_destructor(*set
, sd_bus_message_unref
);
705 static int get_unit_list_recursive(
708 UnitInfo
**_unit_infos
,
712 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
713 _cleanup_(message_set_freep
) Set
*replies
;
714 sd_bus_message
*reply
;
722 replies
= set_new(NULL
);
726 c
= get_unit_list(bus
, NULL
, patterns
, &unit_infos
, 0, &reply
);
730 r
= set_put(replies
, reply
);
732 sd_bus_message_unref(reply
);
737 _cleanup_strv_free_
char **machines
= NULL
;
740 r
= sd_get_machine_names(&machines
);
742 return log_error_errno(r
, "Failed to get machine names: %m");
744 STRV_FOREACH(i
, machines
) {
745 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*container
= NULL
;
748 r
= sd_bus_open_system_machine(&container
, *i
);
750 log_warning_errno(r
, "Failed to connect to container %s, ignoring: %m", *i
);
754 k
= get_unit_list(container
, *i
, patterns
, &unit_infos
, c
, &reply
);
760 r
= set_put(replies
, reply
);
762 sd_bus_message_unref(reply
);
767 *_machines
= machines
;
772 *_unit_infos
= unit_infos
;
781 static int list_units(int argc
, char *argv
[], void *userdata
) {
782 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
783 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
784 _cleanup_strv_free_
char **machines
= NULL
;
788 r
= acquire_bus(BUS_MANAGER
, &bus
);
792 pager_open(arg_no_pager
, false);
794 r
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
798 qsort_safe(unit_infos
, r
, sizeof(UnitInfo
), compare_unit_info
);
799 return output_units_list(unit_infos
, r
);
802 static int get_triggered_units(
807 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
814 r
= sd_bus_get_property_strv(
816 "org.freedesktop.systemd1",
818 "org.freedesktop.systemd1.Unit",
823 return log_error_errno(r
, "Failed to determine triggers: %s", bus_error_message(&error
, r
));
828 static int get_listening(
830 const char* unit_path
,
833 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
834 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
835 const char *type
, *path
;
838 r
= sd_bus_get_property(
840 "org.freedesktop.systemd1",
842 "org.freedesktop.systemd1.Socket",
848 return log_error_errno(r
, "Failed to get list of listening sockets: %s", bus_error_message(&error
, r
));
850 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
852 return bus_log_parse_error(r
);
854 while ((r
= sd_bus_message_read(reply
, "(ss)", &type
, &path
)) > 0) {
856 r
= strv_extend(listening
, type
);
860 r
= strv_extend(listening
, path
);
867 return bus_log_parse_error(r
);
869 r
= sd_bus_message_exit_container(reply
);
871 return bus_log_parse_error(r
);
883 /* Note: triggered is a list here, although it almost certainly
884 * will always be one unit. Nevertheless, dbus API allows for multiple
885 * values, so let's follow that. */
888 /* The strv above is shared. free is set only in the first one. */
892 static int socket_info_compare(const struct socket_info
*a
, const struct socket_info
*b
) {
898 if (!a
->machine
&& b
->machine
)
900 if (a
->machine
&& !b
->machine
)
902 if (a
->machine
&& b
->machine
) {
903 o
= strcasecmp(a
->machine
, b
->machine
);
908 o
= strcmp(a
->path
, b
->path
);
910 o
= strcmp(a
->type
, b
->type
);
915 static int output_sockets_list(struct socket_info
*socket_infos
, unsigned cs
) {
916 struct socket_info
*s
;
917 unsigned pathlen
= strlen("LISTEN"),
918 typelen
= strlen("TYPE") * arg_show_types
,
919 socklen
= strlen("UNIT"),
920 servlen
= strlen("ACTIVATES");
921 const char *on
, *off
;
923 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
927 socklen
= MAX(socklen
, strlen(s
->id
));
929 typelen
= MAX(typelen
, strlen(s
->type
));
930 pathlen
= MAX(pathlen
, strlen(s
->path
) + (s
->machine
? strlen(s
->machine
)+1 : 0));
932 STRV_FOREACH(a
, s
->triggered
)
933 tmp
+= strlen(*a
) + 2*(a
!= s
->triggered
);
934 servlen
= MAX(servlen
, tmp
);
939 printf("%-*s %-*.*s%-*s %s\n",
941 typelen
+ arg_show_types
, typelen
+ arg_show_types
, "TYPE ",
945 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
946 _cleanup_free_
char *j
= NULL
;
951 j
= strjoin(s
->machine
, ":", s
->path
);
959 printf("%-*s %-*s %-*s",
960 pathlen
, path
, typelen
, s
->type
, socklen
, s
->id
);
963 pathlen
, path
, socklen
, s
->id
);
964 STRV_FOREACH(a
, s
->triggered
)
966 a
== s
->triggered
? "" : ",", *a
);
970 on
= ansi_highlight();
975 on
= ansi_highlight_red();
979 if (!arg_no_legend
) {
980 printf("%s%u sockets listed.%s\n", on
, cs
, off
);
982 printf("Pass --all to see loaded but inactive sockets, too.\n");
988 static int list_sockets(int argc
, char *argv
[], void *userdata
) {
989 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
990 _cleanup_strv_free_
char **machines
= NULL
;
991 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
992 _cleanup_free_
struct socket_info
*socket_infos
= NULL
;
994 struct socket_info
*s
;
1000 r
= acquire_bus(BUS_MANAGER
, &bus
);
1004 pager_open(arg_no_pager
, false);
1006 n
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
1010 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
1011 _cleanup_strv_free_
char **listening
= NULL
, **triggered
= NULL
;
1014 if (!endswith(u
->id
, ".socket"))
1017 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
1021 c
= get_listening(bus
, u
->unit_path
, &listening
);
1027 if (!GREEDY_REALLOC(socket_infos
, size
, cs
+ c
)) {
1032 for (i
= 0; i
< c
; i
++)
1033 socket_infos
[cs
+ i
] = (struct socket_info
) {
1034 .machine
= u
->machine
,
1036 .type
= listening
[i
*2],
1037 .path
= listening
[i
*2 + 1],
1038 .triggered
= triggered
,
1039 .own_triggered
= i
==0,
1042 /* from this point on we will cleanup those socket_infos */
1045 listening
= triggered
= NULL
; /* avoid cleanup */
1048 qsort_safe(socket_infos
, cs
, sizeof(struct socket_info
),
1049 (__compar_fn_t
) socket_info_compare
);
1051 output_sockets_list(socket_infos
, cs
);
1054 assert(cs
== 0 || socket_infos
);
1055 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
1058 if (s
->own_triggered
)
1059 strv_free(s
->triggered
);
1065 static int get_next_elapse(
1068 dual_timestamp
*next
) {
1070 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1078 r
= sd_bus_get_property_trivial(
1080 "org.freedesktop.systemd1",
1082 "org.freedesktop.systemd1.Timer",
1083 "NextElapseUSecMonotonic",
1088 return log_error_errno(r
, "Failed to get next elapse time: %s", bus_error_message(&error
, r
));
1090 r
= sd_bus_get_property_trivial(
1092 "org.freedesktop.systemd1",
1094 "org.freedesktop.systemd1.Timer",
1095 "NextElapseUSecRealtime",
1100 return log_error_errno(r
, "Failed to get next elapse time: %s", bus_error_message(&error
, r
));
1106 static int get_last_trigger(
1111 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1118 r
= sd_bus_get_property_trivial(
1120 "org.freedesktop.systemd1",
1122 "org.freedesktop.systemd1.Timer",
1128 return log_error_errno(r
, "Failed to get last trigger time: %s", bus_error_message(&error
, r
));
1134 const char* machine
;
1137 usec_t last_trigger
;
1141 static int timer_info_compare(const struct timer_info
*a
, const struct timer_info
*b
) {
1147 if (!a
->machine
&& b
->machine
)
1149 if (a
->machine
&& !b
->machine
)
1151 if (a
->machine
&& b
->machine
) {
1152 o
= strcasecmp(a
->machine
, b
->machine
);
1157 if (a
->next_elapse
< b
->next_elapse
)
1159 if (a
->next_elapse
> b
->next_elapse
)
1162 return strcmp(a
->id
, b
->id
);
1165 static int output_timers_list(struct timer_info
*timer_infos
, unsigned n
) {
1166 struct timer_info
*t
;
1168 nextlen
= strlen("NEXT"),
1169 leftlen
= strlen("LEFT"),
1170 lastlen
= strlen("LAST"),
1171 passedlen
= strlen("PASSED"),
1172 unitlen
= strlen("UNIT"),
1173 activatelen
= strlen("ACTIVATES");
1175 const char *on
, *off
;
1177 assert(timer_infos
|| n
== 0);
1179 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1183 if (t
->next_elapse
> 0) {
1184 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1186 format_timestamp(tstamp
, sizeof(tstamp
), t
->next_elapse
);
1187 nextlen
= MAX(nextlen
, strlen(tstamp
) + 1);
1189 format_timestamp_relative(trel
, sizeof(trel
), t
->next_elapse
);
1190 leftlen
= MAX(leftlen
, strlen(trel
));
1193 if (t
->last_trigger
> 0) {
1194 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1196 format_timestamp(tstamp
, sizeof(tstamp
), t
->last_trigger
);
1197 lastlen
= MAX(lastlen
, strlen(tstamp
) + 1);
1199 format_timestamp_relative(trel
, sizeof(trel
), t
->last_trigger
);
1200 passedlen
= MAX(passedlen
, strlen(trel
));
1203 unitlen
= MAX(unitlen
, strlen(t
->id
) + (t
->machine
? strlen(t
->machine
)+1 : 0));
1205 STRV_FOREACH(a
, t
->triggered
)
1206 ul
+= strlen(*a
) + 2*(a
!= t
->triggered
);
1208 activatelen
= MAX(activatelen
, ul
);
1213 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1217 passedlen
, "PASSED",
1221 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1222 _cleanup_free_
char *j
= NULL
;
1224 char tstamp1
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel1
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1225 char tstamp2
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel2
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1228 format_timestamp(tstamp1
, sizeof(tstamp1
), t
->next_elapse
);
1229 format_timestamp_relative(trel1
, sizeof(trel1
), t
->next_elapse
);
1231 format_timestamp(tstamp2
, sizeof(tstamp2
), t
->last_trigger
);
1232 format_timestamp_relative(trel2
, sizeof(trel2
), t
->last_trigger
);
1235 j
= strjoin(t
->machine
, ":", t
->id
);
1242 printf("%-*s %-*s %-*s %-*s %-*s",
1243 nextlen
, tstamp1
, leftlen
, trel1
, lastlen
, tstamp2
, passedlen
, trel2
, unitlen
, unit
);
1245 STRV_FOREACH(a
, t
->triggered
)
1247 a
== t
->triggered
? "" : ",", *a
);
1251 on
= ansi_highlight();
1252 off
= ansi_normal();
1256 on
= ansi_highlight_red();
1257 off
= ansi_normal();
1260 if (!arg_no_legend
) {
1261 printf("%s%u timers listed.%s\n", on
, n
, off
);
1263 printf("Pass --all to see loaded but inactive timers, too.\n");
1269 static usec_t
calc_next_elapse(dual_timestamp
*nw
, dual_timestamp
*next
) {
1275 if (next
->monotonic
!= USEC_INFINITY
&& next
->monotonic
> 0) {
1278 if (next
->monotonic
> nw
->monotonic
)
1279 converted
= nw
->realtime
+ (next
->monotonic
- nw
->monotonic
);
1281 converted
= nw
->realtime
- (nw
->monotonic
- next
->monotonic
);
1283 if (next
->realtime
!= USEC_INFINITY
&& next
->realtime
> 0)
1284 next_elapse
= MIN(converted
, next
->realtime
);
1286 next_elapse
= converted
;
1289 next_elapse
= next
->realtime
;
1294 static int list_timers(int argc
, char *argv
[], void *userdata
) {
1295 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
1296 _cleanup_strv_free_
char **machines
= NULL
;
1297 _cleanup_free_
struct timer_info
*timer_infos
= NULL
;
1298 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
1299 struct timer_info
*t
;
1307 r
= acquire_bus(BUS_MANAGER
, &bus
);
1311 pager_open(arg_no_pager
, false);
1313 n
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
1317 dual_timestamp_get(&nw
);
1319 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
1320 _cleanup_strv_free_
char **triggered
= NULL
;
1321 dual_timestamp next
= DUAL_TIMESTAMP_NULL
;
1324 if (!endswith(u
->id
, ".timer"))
1327 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
1331 r
= get_next_elapse(bus
, u
->unit_path
, &next
);
1335 get_last_trigger(bus
, u
->unit_path
, &last
);
1337 if (!GREEDY_REALLOC(timer_infos
, size
, c
+1)) {
1342 m
= calc_next_elapse(&nw
, &next
);
1344 timer_infos
[c
++] = (struct timer_info
) {
1345 .machine
= u
->machine
,
1348 .last_trigger
= last
,
1349 .triggered
= triggered
,
1352 triggered
= NULL
; /* avoid cleanup */
1355 qsort_safe(timer_infos
, c
, sizeof(struct timer_info
),
1356 (__compar_fn_t
) timer_info_compare
);
1358 output_timers_list(timer_infos
, c
);
1361 for (t
= timer_infos
; t
< timer_infos
+ c
; t
++)
1362 strv_free(t
->triggered
);
1367 static int compare_unit_file_list(const void *a
, const void *b
) {
1368 const char *d1
, *d2
;
1369 const UnitFileList
*u
= a
, *v
= b
;
1371 d1
= strrchr(u
->path
, '.');
1372 d2
= strrchr(v
->path
, '.');
1377 r
= strcasecmp(d1
, d2
);
1382 return strcasecmp(basename(u
->path
), basename(v
->path
));
1385 static bool output_show_unit_file(const UnitFileList
*u
, char **states
, char **patterns
) {
1388 if (!strv_fnmatch_or_empty(patterns
, basename(u
->path
), FNM_NOESCAPE
))
1391 if (!strv_isempty(arg_types
)) {
1394 dot
= strrchr(u
->path
, '.');
1398 if (!strv_find(arg_types
, dot
+1))
1402 if (!strv_isempty(states
) &&
1403 !strv_find(states
, unit_file_state_to_string(u
->state
)))
1409 static void output_unit_file_list(const UnitFileList
*units
, unsigned c
) {
1410 unsigned max_id_len
, id_cols
, state_cols
;
1411 const UnitFileList
*u
;
1413 max_id_len
= strlen("UNIT FILE");
1414 state_cols
= strlen("STATE");
1416 for (u
= units
; u
< units
+ c
; u
++) {
1417 max_id_len
= MAX(max_id_len
, strlen(basename(u
->path
)));
1418 state_cols
= MAX(state_cols
, strlen(unit_file_state_to_string(u
->state
)));
1422 unsigned basic_cols
;
1424 id_cols
= MIN(max_id_len
, 25u);
1425 basic_cols
= 1 + id_cols
+ state_cols
;
1426 if (basic_cols
< (unsigned) columns())
1427 id_cols
+= MIN(columns() - basic_cols
, max_id_len
- id_cols
);
1429 id_cols
= max_id_len
;
1431 if (!arg_no_legend
&& c
> 0)
1432 printf("%s%-*s %-*s%s\n",
1434 id_cols
, "UNIT FILE",
1435 state_cols
, "STATE",
1438 for (u
= units
; u
< units
+ c
; u
++) {
1439 const char *on_underline
= NULL
, *on_color
= NULL
, *off
= NULL
, *id
;
1440 _cleanup_free_
char *e
= NULL
;
1443 underline
= u
+ 1 < units
+ c
&&
1444 !streq(unit_type_suffix(u
->path
), unit_type_suffix((u
+ 1)->path
));
1447 on_underline
= ansi_underline();
1449 if (IN_SET(u
->state
,
1451 UNIT_FILE_MASKED_RUNTIME
,
1454 on_color
= underline
? ansi_highlight_red_underline() : ansi_highlight_red();
1455 else if (u
->state
== UNIT_FILE_ENABLED
)
1456 on_color
= underline
? ansi_highlight_green_underline() : ansi_highlight_green();
1458 if (on_underline
|| on_color
)
1459 off
= ansi_normal();
1461 id
= basename(u
->path
);
1463 e
= arg_full
? NULL
: ellipsize(id
, id_cols
, 33);
1465 printf("%s%-*s %s%-*s%s\n",
1466 strempty(on_underline
),
1467 id_cols
, e
? e
: id
,
1468 strempty(on_color
), state_cols
, unit_file_state_to_string(u
->state
), strempty(off
));
1472 printf("\n%u unit files listed.\n", c
);
1475 static int list_unit_files(int argc
, char *argv
[], void *userdata
) {
1476 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1477 _cleanup_free_ UnitFileList
*units
= NULL
;
1484 bool fallback
= false;
1486 if (install_client_side()) {
1492 h
= hashmap_new(&string_hash_ops
);
1496 r
= unit_file_get_list(arg_scope
, arg_root
, h
, arg_states
, strv_skip(argv
, 1));
1498 unit_file_list_free(h
);
1499 return log_error_errno(r
, "Failed to get unit file list: %m");
1502 n_units
= hashmap_size(h
);
1504 units
= new(UnitFileList
, n_units
?: 1); /* avoid malloc(0) */
1506 unit_file_list_free(h
);
1510 HASHMAP_FOREACH(u
, h
, i
) {
1511 if (!output_show_unit_file(u
, NULL
, NULL
))
1518 assert(c
<= n_units
);
1523 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
1524 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1527 r
= acquire_bus(BUS_MANAGER
, &bus
);
1531 r
= sd_bus_message_new_method_call(
1534 "org.freedesktop.systemd1",
1535 "/org/freedesktop/systemd1",
1536 "org.freedesktop.systemd1.Manager",
1537 "ListUnitFilesByPatterns");
1539 return bus_log_create_error(r
);
1541 r
= sd_bus_message_append_strv(m
, arg_states
);
1543 return bus_log_create_error(r
);
1545 r
= sd_bus_message_append_strv(m
, strv_skip(argv
, 1));
1547 return bus_log_create_error(r
);
1549 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
1550 if (r
< 0 && sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_METHOD
)) {
1551 /* Fallback to legacy ListUnitFiles method */
1553 log_debug_errno(r
, "Failed to list unit files: %s Falling back to ListUnitsFiles method.", bus_error_message(&error
, r
));
1554 m
= sd_bus_message_unref(m
);
1555 sd_bus_error_free(&error
);
1557 r
= sd_bus_message_new_method_call(
1560 "org.freedesktop.systemd1",
1561 "/org/freedesktop/systemd1",
1562 "org.freedesktop.systemd1.Manager",
1565 return bus_log_create_error(r
);
1567 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
1570 return log_error_errno(r
, "Failed to list unit files: %s", bus_error_message(&error
, r
));
1572 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
1574 return bus_log_parse_error(r
);
1576 while ((r
= sd_bus_message_read(reply
, "(ss)", &path
, &state
)) > 0) {
1578 if (!GREEDY_REALLOC(units
, size
, c
+ 1))
1581 units
[c
] = (struct UnitFileList
) {
1583 unit_file_state_from_string(state
)
1586 if (output_show_unit_file(&units
[c
],
1587 fallback
? arg_states
: NULL
,
1588 fallback
? strv_skip(argv
, 1) : NULL
))
1593 return bus_log_parse_error(r
);
1595 r
= sd_bus_message_exit_container(reply
);
1597 return bus_log_parse_error(r
);
1600 pager_open(arg_no_pager
, false);
1602 qsort_safe(units
, c
, sizeof(UnitFileList
), compare_unit_file_list
);
1603 output_unit_file_list(units
, c
);
1605 if (install_client_side())
1606 for (unit
= units
; unit
< units
+ c
; unit
++)
1612 static int list_dependencies_print(const char *name
, int level
, unsigned int branches
, bool last
) {
1613 _cleanup_free_
char *n
= NULL
;
1614 size_t max_len
= MAX(columns(),20u);
1620 for (i
= level
- 1; i
>= 0; i
--) {
1622 if (len
> max_len
- 3 && !arg_full
) {
1623 printf("%s...\n",max_len
% 2 ? "" : " ");
1626 printf("%s", special_glyph(branches
& (1 << i
) ? TREE_VERTICAL
: TREE_SPACE
));
1630 if (len
> max_len
- 3 && !arg_full
) {
1631 printf("%s...\n",max_len
% 2 ? "" : " ");
1635 printf("%s", special_glyph(last
? TREE_RIGHT
: TREE_BRANCH
));
1639 printf("%s\n", name
);
1643 n
= ellipsize(name
, max_len
-len
, 100);
1651 static int list_dependencies_get_dependencies(sd_bus
*bus
, const char *name
, char ***deps
) {
1653 static const char *dependencies
[_DEPENDENCY_MAX
] = {
1654 [DEPENDENCY_FORWARD
] = "Requires\0"
1659 [DEPENDENCY_REVERSE
] = "RequiredBy\0"
1664 [DEPENDENCY_AFTER
] = "After\0",
1665 [DEPENDENCY_BEFORE
] = "Before\0",
1668 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1669 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1670 _cleanup_strv_free_
char **ret
= NULL
;
1671 _cleanup_free_
char *path
= NULL
;
1677 assert_cc(ELEMENTSOF(dependencies
) == _DEPENDENCY_MAX
);
1679 path
= unit_dbus_path_from_name(name
);
1683 r
= sd_bus_call_method(
1685 "org.freedesktop.systemd1",
1687 "org.freedesktop.DBus.Properties",
1691 "s", "org.freedesktop.systemd1.Unit");
1693 return log_error_errno(r
, "Failed to get properties of %s: %s", name
, bus_error_message(&error
, r
));
1695 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
1697 return bus_log_parse_error(r
);
1699 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
1702 r
= sd_bus_message_read(reply
, "s", &prop
);
1704 return bus_log_parse_error(r
);
1706 if (!nulstr_contains(dependencies
[arg_dependency
], prop
)) {
1707 r
= sd_bus_message_skip(reply
, "v");
1709 return bus_log_parse_error(r
);
1712 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, "as");
1714 return bus_log_parse_error(r
);
1716 r
= bus_message_read_strv_extend(reply
, &ret
);
1718 return bus_log_parse_error(r
);
1720 r
= sd_bus_message_exit_container(reply
);
1722 return bus_log_parse_error(r
);
1725 r
= sd_bus_message_exit_container(reply
);
1727 return bus_log_parse_error(r
);
1731 return bus_log_parse_error(r
);
1733 r
= sd_bus_message_exit_container(reply
);
1735 return bus_log_parse_error(r
);
1737 *deps
= strv_uniq(ret
);
1743 static int list_dependencies_compare(const void *_a
, const void *_b
) {
1744 const char **a
= (const char**) _a
, **b
= (const char**) _b
;
1746 if (unit_name_to_type(*a
) == UNIT_TARGET
&& unit_name_to_type(*b
) != UNIT_TARGET
)
1748 if (unit_name_to_type(*a
) != UNIT_TARGET
&& unit_name_to_type(*b
) == UNIT_TARGET
)
1751 return strcasecmp(*a
, *b
);
1754 static int list_dependencies_one(
1759 unsigned int branches
) {
1761 _cleanup_strv_free_
char **deps
= NULL
;
1769 r
= strv_extend(units
, name
);
1773 r
= list_dependencies_get_dependencies(bus
, name
, &deps
);
1777 qsort_safe(deps
, strv_length(deps
), sizeof (char*), list_dependencies_compare
);
1779 STRV_FOREACH(c
, deps
) {
1780 if (strv_contains(*units
, *c
)) {
1783 r
= list_dependencies_print("...", level
+ 1, (branches
<< 1) | (c
[1] == NULL
? 0 : 1), 1);
1793 UnitActiveState active_state
= _UNIT_ACTIVE_STATE_INVALID
;
1796 (void) get_state_one_unit(bus
, *c
, &active_state
);
1798 switch (active_state
) {
1800 case UNIT_RELOADING
:
1801 case UNIT_ACTIVATING
:
1802 on
= ansi_highlight_green();
1806 case UNIT_DEACTIVATING
:
1811 on
= ansi_highlight_red();
1815 printf("%s%s%s ", on
, special_glyph(BLACK_CIRCLE
), ansi_normal());
1818 r
= list_dependencies_print(*c
, level
, branches
, c
[1] == NULL
);
1822 if (arg_all
|| unit_name_to_type(*c
) == UNIT_TARGET
) {
1823 r
= list_dependencies_one(bus
, *c
, level
+ 1, units
, (branches
<< 1) | (c
[1] == NULL
? 0 : 1));
1830 strv_remove(*units
, name
);
1835 static int list_dependencies(int argc
, char *argv
[], void *userdata
) {
1836 _cleanup_strv_free_
char **units
= NULL
;
1837 _cleanup_free_
char *unit
= NULL
;
1843 r
= unit_name_mangle(argv
[1], UNIT_NAME_NOGLOB
, &unit
);
1845 return log_error_errno(r
, "Failed to mangle unit name: %m");
1849 u
= SPECIAL_DEFAULT_TARGET
;
1851 r
= acquire_bus(BUS_MANAGER
, &bus
);
1855 pager_open(arg_no_pager
, false);
1859 return list_dependencies_one(bus
, u
, 0, &units
, 0);
1862 struct machine_info
{
1866 char *control_group
;
1867 uint32_t n_failed_units
;
1872 static const struct bus_properties_map machine_info_property_map
[] = {
1873 { "SystemState", "s", NULL
, offsetof(struct machine_info
, state
) },
1874 { "NJobs", "u", NULL
, offsetof(struct machine_info
, n_jobs
) },
1875 { "NFailedUnits", "u", NULL
, offsetof(struct machine_info
, n_failed_units
) },
1876 { "ControlGroup", "s", NULL
, offsetof(struct machine_info
, control_group
) },
1877 { "UserspaceTimestamp", "t", NULL
, offsetof(struct machine_info
, timestamp
) },
1881 static void machine_info_clear(struct machine_info
*info
) {
1886 free(info
->control_group
);
1890 static void free_machines_list(struct machine_info
*machine_infos
, int n
) {
1896 for (i
= 0; i
< n
; i
++)
1897 machine_info_clear(&machine_infos
[i
]);
1899 free(machine_infos
);
1902 static int compare_machine_info(const void *a
, const void *b
) {
1903 const struct machine_info
*u
= a
, *v
= b
;
1905 if (u
->is_host
!= v
->is_host
)
1906 return u
->is_host
> v
->is_host
? -1 : 1;
1908 return strcasecmp(u
->name
, v
->name
);
1911 static int get_machine_properties(sd_bus
*bus
, struct machine_info
*mi
) {
1912 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*container
= NULL
;
1918 r
= sd_bus_open_system_machine(&container
, mi
->name
);
1925 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, NULL
, mi
);
1932 static bool output_show_machine(const char *name
, char **patterns
) {
1933 return strv_fnmatch_or_empty(patterns
, name
, FNM_NOESCAPE
);
1936 static int get_machine_list(
1938 struct machine_info
**_machine_infos
,
1941 struct machine_info
*machine_infos
= NULL
;
1942 _cleanup_strv_free_
char **m
= NULL
;
1943 _cleanup_free_
char *hn
= NULL
;
1948 hn
= gethostname_malloc();
1952 if (output_show_machine(hn
, patterns
)) {
1953 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1))
1956 machine_infos
[c
].is_host
= true;
1957 machine_infos
[c
].name
= hn
;
1960 (void) get_machine_properties(bus
, &machine_infos
[c
]);
1964 r
= sd_get_machine_names(&m
);
1966 return log_error_errno(r
, "Failed to get machine list: %m");
1968 STRV_FOREACH(i
, m
) {
1969 _cleanup_free_
char *class = NULL
;
1971 if (!output_show_machine(*i
, patterns
))
1974 sd_machine_get_class(*i
, &class);
1975 if (!streq_ptr(class, "container"))
1978 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1)) {
1979 free_machines_list(machine_infos
, c
);
1983 machine_infos
[c
].is_host
= false;
1984 machine_infos
[c
].name
= strdup(*i
);
1985 if (!machine_infos
[c
].name
) {
1986 free_machines_list(machine_infos
, c
);
1990 (void) get_machine_properties(NULL
, &machine_infos
[c
]);
1994 *_machine_infos
= machine_infos
;
1998 static void output_machines_list(struct machine_info
*machine_infos
, unsigned n
) {
1999 struct machine_info
*m
;
2002 namelen
= sizeof("NAME") - 1,
2003 statelen
= sizeof("STATE") - 1,
2004 failedlen
= sizeof("FAILED") - 1,
2005 jobslen
= sizeof("JOBS") - 1;
2007 assert(machine_infos
|| n
== 0);
2009 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
2010 namelen
= MAX(namelen
, strlen(m
->name
) + (m
->is_host
? sizeof(" (host)") - 1 : 0));
2011 statelen
= MAX(statelen
, strlen_ptr(m
->state
));
2012 failedlen
= MAX(failedlen
, DECIMAL_STR_WIDTH(m
->n_failed_units
));
2013 jobslen
= MAX(jobslen
, DECIMAL_STR_WIDTH(m
->n_jobs
));
2015 if (!arg_plain
&& !streq_ptr(m
->state
, "running"))
2019 if (!arg_no_legend
) {
2023 printf("%-*s %-*s %-*s %-*s\n",
2026 failedlen
, "FAILED",
2030 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
2031 const char *on_state
= "", *off_state
= "";
2032 const char *on_failed
= "", *off_failed
= "";
2033 bool circle
= false;
2035 if (streq_ptr(m
->state
, "degraded")) {
2036 on_state
= ansi_highlight_red();
2037 off_state
= ansi_normal();
2039 } else if (!streq_ptr(m
->state
, "running")) {
2040 on_state
= ansi_highlight_yellow();
2041 off_state
= ansi_normal();
2045 if (m
->n_failed_units
> 0) {
2046 on_failed
= ansi_highlight_red();
2047 off_failed
= ansi_normal();
2049 on_failed
= off_failed
= "";
2052 printf("%s%s%s ", on_state
, circle
? special_glyph(BLACK_CIRCLE
) : " ", off_state
);
2055 printf("%-*s (host) %s%-*s%s %s%*" PRIu32
"%s %*" PRIu32
"\n",
2056 (int) (namelen
- (sizeof(" (host)")-1)), strna(m
->name
),
2057 on_state
, statelen
, strna(m
->state
), off_state
,
2058 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
2059 jobslen
, m
->n_jobs
);
2061 printf("%-*s %s%-*s%s %s%*" PRIu32
"%s %*" PRIu32
"\n",
2062 namelen
, strna(m
->name
),
2063 on_state
, statelen
, strna(m
->state
), off_state
,
2064 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
2065 jobslen
, m
->n_jobs
);
2069 printf("\n%u machines listed.\n", n
);
2072 static int list_machines(int argc
, char *argv
[], void *userdata
) {
2073 struct machine_info
*machine_infos
= NULL
;
2077 if (geteuid() != 0) {
2078 log_error("Must be root.");
2082 r
= acquire_bus(BUS_MANAGER
, &bus
);
2086 r
= get_machine_list(bus
, &machine_infos
, strv_skip(argv
, 1));
2090 pager_open(arg_no_pager
, false);
2092 qsort_safe(machine_infos
, r
, sizeof(struct machine_info
), compare_machine_info
);
2093 output_machines_list(machine_infos
, r
);
2094 free_machines_list(machine_infos
, r
);
2099 static int get_default(int argc
, char *argv
[], void *userdata
) {
2100 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2101 _cleanup_free_
char *_path
= NULL
;
2105 if (install_client_side()) {
2106 r
= unit_file_get_default(arg_scope
, arg_root
, &_path
);
2108 return log_error_errno(r
, "Failed to get default target: %m");
2113 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2116 r
= acquire_bus(BUS_MANAGER
, &bus
);
2120 r
= sd_bus_call_method(
2122 "org.freedesktop.systemd1",
2123 "/org/freedesktop/systemd1",
2124 "org.freedesktop.systemd1.Manager",
2130 return log_error_errno(r
, "Failed to get default target: %s", bus_error_message(&error
, r
));
2132 r
= sd_bus_message_read(reply
, "s", &path
);
2134 return bus_log_parse_error(r
);
2138 printf("%s\n", path
);
2143 static int set_default(int argc
, char *argv
[], void *userdata
) {
2144 _cleanup_free_
char *unit
= NULL
;
2145 UnitFileChange
*changes
= NULL
;
2146 unsigned n_changes
= 0;
2152 r
= unit_name_mangle_with_suffix(argv
[1], UNIT_NAME_NOGLOB
, ".target", &unit
);
2154 return log_error_errno(r
, "Failed to mangle unit name: %m");
2156 if (install_client_side()) {
2157 r
= unit_file_set_default(arg_scope
, UNIT_FILE_FORCE
, arg_root
, unit
, &changes
, &n_changes
);
2158 unit_file_dump_changes(r
, "set default", changes
, n_changes
, arg_quiet
);
2163 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2164 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2167 polkit_agent_open_maybe();
2169 r
= acquire_bus(BUS_MANAGER
, &bus
);
2173 r
= sd_bus_call_method(
2175 "org.freedesktop.systemd1",
2176 "/org/freedesktop/systemd1",
2177 "org.freedesktop.systemd1.Manager",
2183 return log_error_errno(r
, "Failed to set default target: %s", bus_error_message(&error
, r
));
2185 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
2189 /* Try to reload if enabled */
2191 r
= daemon_reload(argc
, argv
, userdata
);
2197 unit_file_changes_free(changes
, n_changes
);
2202 static int output_waiting_jobs(sd_bus
*bus
, uint32_t id
, const char *method
, const char *prefix
) {
2203 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2204 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2205 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2211 r
= sd_bus_call_method(
2213 "org.freedesktop.systemd1",
2214 "/org/freedesktop/systemd1",
2215 "org.freedesktop.systemd1.Manager",
2221 return log_debug_errno(r
, "Failed to get waiting jobs for job %" PRIu32
, id
);
2223 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2225 return bus_log_parse_error(r
);
2227 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &other_id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0)
2228 printf("%s %u (%s/%s)\n", prefix
, other_id
, name
, type
);
2230 return bus_log_parse_error(r
);
2232 r
= sd_bus_message_exit_container(reply
);
2234 return bus_log_parse_error(r
);
2241 const char *name
, *type
, *state
;
2244 static void output_jobs_list(sd_bus
*bus
, const struct job_info
* jobs
, unsigned n
, bool skipped
) {
2245 unsigned id_len
, unit_len
, type_len
, state_len
;
2246 const struct job_info
*j
;
2247 const char *on
, *off
;
2248 bool shorten
= false;
2250 assert(n
== 0 || jobs
);
2253 if (!arg_no_legend
) {
2254 on
= ansi_highlight_green();
2255 off
= ansi_normal();
2257 printf("%sNo jobs %s.%s\n", on
, skipped
? "listed" : "running", off
);
2262 pager_open(arg_no_pager
, false);
2264 id_len
= strlen("JOB");
2265 unit_len
= strlen("UNIT");
2266 type_len
= strlen("TYPE");
2267 state_len
= strlen("STATE");
2269 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2270 uint32_t id
= j
->id
;
2271 assert(j
->name
&& j
->type
&& j
->state
);
2273 id_len
= MAX(id_len
, DECIMAL_STR_WIDTH(id
));
2274 unit_len
= MAX(unit_len
, strlen(j
->name
));
2275 type_len
= MAX(type_len
, strlen(j
->type
));
2276 state_len
= MAX(state_len
, strlen(j
->state
));
2279 if (!arg_full
&& id_len
+ 1 + unit_len
+ type_len
+ 1 + state_len
> columns()) {
2280 unit_len
= MAX(33u, columns() - id_len
- type_len
- state_len
- 3);
2285 printf("%*s %-*s %-*s %-*s\n",
2289 state_len
, "STATE");
2291 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2292 _cleanup_free_
char *e
= NULL
;
2294 if (streq(j
->state
, "running")) {
2295 on
= ansi_highlight();
2296 off
= ansi_normal();
2300 e
= shorten
? ellipsize(j
->name
, unit_len
, 33) : NULL
;
2301 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2303 on
, unit_len
, e
? e
: j
->name
, off
,
2305 on
, state_len
, j
->state
, off
);
2308 output_waiting_jobs(bus
, j
->id
, "GetJobAfter", "\twaiting for job");
2309 if (arg_jobs_before
)
2310 output_waiting_jobs(bus
, j
->id
, "GetJobBefore", "\tblocking job");
2313 if (!arg_no_legend
) {
2314 on
= ansi_highlight();
2315 off
= ansi_normal();
2317 printf("\n%s%u jobs listed%s.\n", on
, n
, off
);
2321 static bool output_show_job(struct job_info
*job
, char **patterns
) {
2322 return strv_fnmatch_or_empty(patterns
, job
->name
, FNM_NOESCAPE
);
2325 static int list_jobs(int argc
, char *argv
[], void *userdata
) {
2326 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2327 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2328 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2329 _cleanup_free_
struct job_info
*jobs
= NULL
;
2335 bool skipped
= false;
2337 r
= acquire_bus(BUS_MANAGER
, &bus
);
2341 r
= sd_bus_call_method(
2343 "org.freedesktop.systemd1",
2344 "/org/freedesktop/systemd1",
2345 "org.freedesktop.systemd1.Manager",
2351 return log_error_errno(r
, "Failed to list jobs: %s", bus_error_message(&error
, r
));
2353 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2355 return bus_log_parse_error(r
);
2357 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0) {
2358 struct job_info job
= { id
, name
, type
, state
};
2360 if (!output_show_job(&job
, strv_skip(argv
, 1))) {
2365 if (!GREEDY_REALLOC(jobs
, size
, c
+ 1))
2371 return bus_log_parse_error(r
);
2373 r
= sd_bus_message_exit_container(reply
);
2375 return bus_log_parse_error(r
);
2377 pager_open(arg_no_pager
, false);
2379 output_jobs_list(bus
, jobs
, c
, skipped
);
2383 static int cancel_job(int argc
, char *argv
[], void *userdata
) {
2389 return trivial_method(argc
, argv
, userdata
);
2391 r
= acquire_bus(BUS_MANAGER
, &bus
);
2395 polkit_agent_open_maybe();
2397 STRV_FOREACH(name
, strv_skip(argv
, 1)) {
2398 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2402 q
= safe_atou32(*name
, &id
);
2404 return log_error_errno(q
, "Failed to parse job id \"%s\": %m", *name
);
2406 q
= sd_bus_call_method(
2408 "org.freedesktop.systemd1",
2409 "/org/freedesktop/systemd1",
2410 "org.freedesktop.systemd1.Manager",
2416 log_error_errno(q
, "Failed to cancel job %"PRIu32
": %s", id
, bus_error_message(&error
, q
));
2425 static int need_daemon_reload(sd_bus
*bus
, const char *unit
) {
2426 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2430 /* We ignore all errors here, since this is used to show a
2433 /* We don't use unit_dbus_path_from_name() directly since we
2434 * don't want to load the unit if it isn't loaded. */
2436 r
= sd_bus_call_method(
2438 "org.freedesktop.systemd1",
2439 "/org/freedesktop/systemd1",
2440 "org.freedesktop.systemd1.Manager",
2448 r
= sd_bus_message_read(reply
, "o", &path
);
2452 r
= sd_bus_get_property_trivial(
2454 "org.freedesktop.systemd1",
2456 "org.freedesktop.systemd1.Unit",
2466 static void warn_unit_file_changed(const char *name
) {
2469 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.",
2470 ansi_highlight_red(),
2473 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user");
2476 static int unit_file_find_path(LookupPaths
*lp
, const char *unit_name
, char **unit_path
) {
2482 STRV_FOREACH(p
, lp
->search_path
) {
2483 _cleanup_free_
char *path
= NULL
, *lpath
= NULL
;
2486 path
= path_join(NULL
, *p
, unit_name
);
2490 r
= chase_symlinks(path
, arg_root
, 0, &lpath
);
2496 return log_error_errno(r
, "Failed to access path '%s': %m", path
);
2508 static int unit_find_template_path(
2509 const char *unit_name
,
2511 char **fragment_path
,
2514 _cleanup_free_
char *_template
= NULL
;
2517 /* Returns 1 if a fragment was found, 0 if not found, negative on error. */
2519 r
= unit_file_find_path(lp
, unit_name
, fragment_path
);
2521 return r
; /* error or found a real unit */
2523 r
= unit_name_template(unit_name
, &_template
);
2525 return 0; /* not a template, does not exist */
2527 return log_error_errno(r
, "Failed to determine template name: %m");
2529 r
= unit_file_find_path(lp
, _template
, fragment_path
);
2534 *template = _template
;
2540 static int unit_find_paths(
2542 const char *unit_name
,
2544 char **fragment_path
,
2545 char ***dropin_paths
) {
2547 _cleanup_free_
char *path
= NULL
;
2548 _cleanup_strv_free_
char **dropins
= NULL
;
2552 * Finds where the unit is defined on disk. Returns 0 if the unit
2553 * is not found. Returns 1 if it is found, and sets
2554 * - the path to the unit in *path, if it exists on disk,
2555 * - and a strv of existing drop-ins in *dropins,
2556 * if the arg is not NULL and any dropins were found.
2560 assert(fragment_path
);
2563 if (!install_client_side() && !unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
2564 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2565 _cleanup_free_
char *unit
= NULL
;
2567 unit
= unit_dbus_path_from_name(unit_name
);
2571 r
= sd_bus_get_property_string(
2573 "org.freedesktop.systemd1",
2575 "org.freedesktop.systemd1.Unit",
2580 return log_error_errno(r
, "Failed to get FragmentPath: %s", bus_error_message(&error
, r
));
2583 r
= sd_bus_get_property_strv(
2585 "org.freedesktop.systemd1",
2587 "org.freedesktop.systemd1.Unit",
2592 return log_error_errno(r
, "Failed to get DropInPaths: %s", bus_error_message(&error
, r
));
2595 _cleanup_set_free_ Set
*names
= NULL
;
2596 _cleanup_free_
char *template = NULL
;
2598 names
= set_new(NULL
);
2602 r
= unit_find_template_path(unit_name
, lp
, &path
, &template);
2607 /* We found the unit file. If we followed symlinks, this name might be
2608 * different then the unit_name with started with. Look for dropins matching
2609 * that "final" name. */
2610 r
= set_put(names
, basename(path
));
2612 /* No unit file, let's look for dropins matching the original name.
2613 * systemd has fairly complicated rules (based on unit type and provenience),
2614 * which units are allowed not to have the main unit file. We err on the
2615 * side of including too many files, and always try to load dropins. */
2616 r
= set_put(names
, unit_name
);
2618 /* The cases where we allow a unit to exist without the main file are
2619 * never valid for templates. Don't try to load dropins in this case. */
2623 return log_error_errno(r
, "Failed to add unit name: %m");
2626 r
= unit_file_find_dropin_conf_paths(arg_root
, lp
->search_path
,
2627 NULL
, names
, &dropins
);
2635 if (!isempty(path
)) {
2636 *fragment_path
= path
;
2641 if (dropin_paths
&& !strv_isempty(dropins
)) {
2642 *dropin_paths
= dropins
;
2647 if (r
== 0 && !arg_force
)
2648 log_error("No files found for %s.", unit_name
);
2653 static int get_state_one_unit(sd_bus
*bus
, const char *name
, UnitActiveState
*active_state
) {
2654 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2655 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2656 _cleanup_free_
char *buf
= NULL
;
2657 UnitActiveState state
;
2662 assert(active_state
);
2664 /* We don't use unit_dbus_path_from_name() directly since we don't want to load the unit unnecessarily, if it
2666 r
= sd_bus_call_method(
2668 "org.freedesktop.systemd1",
2669 "/org/freedesktop/systemd1",
2670 "org.freedesktop.systemd1.Manager",
2676 if (!sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_UNIT
))
2677 return log_error_errno(r
, "Failed to retrieve unit: %s", bus_error_message(&error
, r
));
2679 /* The unit is currently not loaded, hence say it's "inactive", since all units that aren't loaded are
2680 * considered inactive. */
2681 state
= UNIT_INACTIVE
;
2684 r
= sd_bus_message_read(reply
, "o", &path
);
2686 return bus_log_parse_error(r
);
2688 r
= sd_bus_get_property_string(
2690 "org.freedesktop.systemd1",
2692 "org.freedesktop.systemd1.Unit",
2697 return log_error_errno(r
, "Failed to retrieve unit state: %s", bus_error_message(&error
, r
));
2699 state
= unit_active_state_from_string(buf
);
2700 if (state
== _UNIT_ACTIVE_STATE_INVALID
) {
2701 log_error("Invalid unit state '%s' for: %s", buf
, name
);
2706 *active_state
= state
;
2710 static int check_triggering_units(
2714 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2715 _cleanup_free_
char *path
= NULL
, *n
= NULL
, *load_state
= NULL
;
2716 _cleanup_strv_free_
char **triggered_by
= NULL
;
2717 bool print_warning_label
= true;
2718 UnitActiveState active_state
;
2722 r
= unit_name_mangle(name
, UNIT_NAME_NOGLOB
, &n
);
2724 return log_error_errno(r
, "Failed to mangle unit name: %m");
2726 path
= unit_dbus_path_from_name(n
);
2730 r
= sd_bus_get_property_string(
2732 "org.freedesktop.systemd1",
2734 "org.freedesktop.systemd1.Unit",
2739 return log_error_errno(r
, "Failed to get load state of %s: %s", n
, bus_error_message(&error
, r
));
2741 if (streq(load_state
, "masked"))
2744 r
= sd_bus_get_property_strv(
2746 "org.freedesktop.systemd1",
2748 "org.freedesktop.systemd1.Unit",
2753 return log_error_errno(r
, "Failed to get triggered by array of %s: %s", n
, bus_error_message(&error
, r
));
2755 STRV_FOREACH(i
, triggered_by
) {
2756 r
= get_state_one_unit(bus
, *i
, &active_state
);
2760 if (!IN_SET(active_state
, UNIT_ACTIVE
, UNIT_RELOADING
))
2763 if (print_warning_label
) {
2764 log_warning("Warning: Stopping %s, but it can still be activated by:", n
);
2765 print_warning_label
= false;
2768 log_warning(" %s", *i
);
2774 static const struct {
2777 } unit_actions
[] = {
2778 { "start", "StartUnit" },
2779 { "stop", "StopUnit" },
2780 { "condstop", "StopUnit" },
2781 { "reload", "ReloadUnit" },
2782 { "restart", "RestartUnit" },
2783 { "try-restart", "TryRestartUnit" },
2784 { "condrestart", "TryRestartUnit" },
2785 { "reload-or-restart", "ReloadOrRestartUnit" },
2786 { "try-reload-or-restart", "ReloadOrTryRestartUnit" },
2787 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2788 { "condreload", "ReloadOrTryRestartUnit" },
2789 { "force-reload", "ReloadOrTryRestartUnit" }
2792 static const char *verb_to_method(const char *verb
) {
2795 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2796 if (streq_ptr(unit_actions
[i
].verb
, verb
))
2797 return unit_actions
[i
].method
;
2802 static const char *method_to_verb(const char *method
) {
2805 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2806 if (streq_ptr(unit_actions
[i
].method
, method
))
2807 return unit_actions
[i
].verb
;
2819 static void wait_context_free(WaitContext
*c
) {
2820 c
->match
= sd_bus_slot_unref(c
->match
);
2821 c
->event
= sd_event_unref(c
->event
);
2822 c
->unit_paths
= set_free_free(c
->unit_paths
);
2825 static int on_properties_changed(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
2826 WaitContext
*c
= userdata
;
2830 path
= sd_bus_message_get_path(m
);
2831 if (!set_contains(c
->unit_paths
, path
))
2834 /* Check if ActiveState changed to inactive/failed */
2835 /* (s interface, a{sv} changed_properties, as invalidated_properties) */
2836 r
= sd_bus_message_skip(m
, "s");
2838 return bus_log_parse_error(r
);
2840 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "{sv}");
2842 return bus_log_parse_error(r
);
2844 while ((r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
2847 r
= sd_bus_message_read(m
, "s", &s
);
2849 return bus_log_parse_error(r
);
2851 if (streq(s
, "ActiveState")) {
2854 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, "s");
2856 return bus_log_parse_error(r
);
2858 r
= sd_bus_message_read(m
, "s", &s
);
2860 return bus_log_parse_error(r
);
2862 is_failed
= streq(s
, "failed");
2863 if (streq(s
, "inactive") || is_failed
) {
2864 log_debug("%s became %s, dropping from --wait tracking", path
, s
);
2865 free(set_remove(c
->unit_paths
, path
));
2866 c
->any_failed
= c
->any_failed
|| is_failed
;
2868 log_debug("ActiveState on %s changed to %s", path
, s
);
2870 break; /* no need to dissect the rest of the message */
2872 /* other property */
2873 r
= sd_bus_message_skip(m
, "v");
2875 return bus_log_parse_error(r
);
2877 r
= sd_bus_message_exit_container(m
);
2879 return bus_log_parse_error(r
);
2882 return bus_log_parse_error(r
);
2884 if (set_isempty(c
->unit_paths
))
2885 sd_event_exit(c
->event
, EXIT_SUCCESS
);
2890 static int start_unit_one(
2895 sd_bus_error
*error
,
2897 WaitContext
*wait_context
) {
2899 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2909 _cleanup_free_
char *unit_path
= NULL
;
2912 log_debug("Watching for property changes of %s", name
);
2913 r
= sd_bus_call_method(
2915 "org.freedesktop.systemd1",
2916 "/org/freedesktop/systemd1",
2917 "org.freedesktop.systemd1.Manager",
2923 return log_error_errno(r
, "Failed to RefUnit %s: %s", name
, bus_error_message(error
, r
));
2925 unit_path
= unit_dbus_path_from_name(name
);
2929 r
= set_put_strdup(wait_context
->unit_paths
, unit_path
);
2931 return log_error_errno(r
, "Failed to add unit path %s to set: %m", unit_path
);
2933 mt
= strjoina("type='signal',"
2934 "interface='org.freedesktop.DBus.Properties',"
2935 "path='", unit_path
, "',"
2936 "member='PropertiesChanged'");
2937 r
= sd_bus_add_match(bus
, &wait_context
->match
, mt
, on_properties_changed
, wait_context
);
2939 return log_error_errno(r
, "Failed to add match for PropertiesChanged signal: %m");
2942 log_debug("%s manager for %s on %s, %s",
2943 arg_dry_run
? "Would call" : "Calling",
2944 method
, name
, mode
);
2948 r
= sd_bus_call_method(
2950 "org.freedesktop.systemd1",
2951 "/org/freedesktop/systemd1",
2952 "org.freedesktop.systemd1.Manager",
2960 /* There's always a fallback possible for legacy actions. */
2961 if (arg_action
!= ACTION_SYSTEMCTL
)
2964 verb
= method_to_verb(method
);
2966 log_error("Failed to %s %s: %s", verb
, name
, bus_error_message(error
, r
));
2968 if (!sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) &&
2969 !sd_bus_error_has_name(error
, BUS_ERROR_UNIT_MASKED
))
2970 log_error("See %s logs and 'systemctl%s status%s %s' for details.",
2971 arg_scope
== UNIT_FILE_SYSTEM
? "system" : "user",
2972 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user",
2973 name
[0] == '-' ? " --" : "",
2979 r
= sd_bus_message_read(reply
, "o", &path
);
2981 return bus_log_parse_error(r
);
2983 if (need_daemon_reload(bus
, name
) > 0)
2984 warn_unit_file_changed(name
);
2987 log_debug("Adding %s to the set", path
);
2988 r
= bus_wait_for_jobs_add(w
, path
);
2996 static int expand_names(sd_bus
*bus
, char **names
, const char* suffix
, char ***ret
) {
2997 _cleanup_strv_free_
char **mangled
= NULL
, **globs
= NULL
;
3004 STRV_FOREACH(name
, names
) {
3008 r
= unit_name_mangle_with_suffix(*name
, UNIT_NAME_GLOB
, suffix
, &t
);
3010 r
= unit_name_mangle(*name
, UNIT_NAME_GLOB
, &t
);
3012 return log_error_errno(r
, "Failed to mangle name: %m");
3014 if (string_is_glob(t
))
3015 r
= strv_consume(&globs
, t
);
3017 r
= strv_consume(&mangled
, t
);
3022 /* Query the manager only if any of the names are a glob, since
3023 * this is fairly expensive */
3024 if (!strv_isempty(globs
)) {
3025 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
3026 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
3027 size_t allocated
, n
;
3029 r
= get_unit_list(bus
, NULL
, globs
, &unit_infos
, 0, &reply
);
3033 n
= strv_length(mangled
);
3036 for (i
= 0; i
< r
; i
++) {
3037 if (!GREEDY_REALLOC(mangled
, allocated
, n
+2))
3040 mangled
[n
] = strdup(unit_infos
[i
].id
);
3044 mangled
[++n
] = NULL
;
3049 mangled
= NULL
; /* do not free */
3054 static const struct {
3058 } action_table
[_ACTION_MAX
] = {
3059 [ACTION_HALT
] = { SPECIAL_HALT_TARGET
, "halt", "replace-irreversibly" },
3060 [ACTION_POWEROFF
] = { SPECIAL_POWEROFF_TARGET
, "poweroff", "replace-irreversibly" },
3061 [ACTION_REBOOT
] = { SPECIAL_REBOOT_TARGET
, "reboot", "replace-irreversibly" },
3062 [ACTION_KEXEC
] = { SPECIAL_KEXEC_TARGET
, "kexec", "replace-irreversibly" },
3063 [ACTION_RUNLEVEL2
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
3064 [ACTION_RUNLEVEL3
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
3065 [ACTION_RUNLEVEL4
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
3066 [ACTION_RUNLEVEL5
] = { SPECIAL_GRAPHICAL_TARGET
, NULL
, "isolate" },
3067 [ACTION_RESCUE
] = { SPECIAL_RESCUE_TARGET
, "rescue", "isolate" },
3068 [ACTION_EMERGENCY
] = { SPECIAL_EMERGENCY_TARGET
, "emergency", "isolate" },
3069 [ACTION_DEFAULT
] = { SPECIAL_DEFAULT_TARGET
, "default", "isolate" },
3070 [ACTION_EXIT
] = { SPECIAL_EXIT_TARGET
, "exit", "replace-irreversibly" },
3071 [ACTION_SUSPEND
] = { SPECIAL_SUSPEND_TARGET
, "suspend", "replace-irreversibly" },
3072 [ACTION_HIBERNATE
] = { SPECIAL_HIBERNATE_TARGET
, "hibernate", "replace-irreversibly" },
3073 [ACTION_HYBRID_SLEEP
] = { SPECIAL_HYBRID_SLEEP_TARGET
, "hybrid-sleep", "replace-irreversibly" },
3076 static enum action
verb_to_action(const char *verb
) {
3079 for (i
= 0; i
< _ACTION_MAX
; i
++)
3080 if (streq_ptr(action_table
[i
].verb
, verb
))
3083 return _ACTION_INVALID
;
3086 static int start_unit(int argc
, char *argv
[], void *userdata
) {
3087 _cleanup_(bus_wait_for_jobs_freep
) BusWaitForJobs
*w
= NULL
;
3088 const char *method
, *mode
, *one_name
, *suffix
= NULL
;
3089 _cleanup_strv_free_
char **names
= NULL
;
3091 _cleanup_(wait_context_free
) WaitContext wait_context
= {};
3095 if (arg_wait
&& !STR_IN_SET(argv
[0], "start", "restart")) {
3096 log_error("--wait may only be used with the 'start' or 'restart' commands.");
3100 /* we cannot do sender tracking on the private bus, so we need the full
3101 * one for RefUnit to implement --wait */
3102 r
= acquire_bus(arg_wait
? BUS_FULL
: BUS_MANAGER
, &bus
);
3106 ask_password_agent_open_if_enabled();
3107 polkit_agent_open_maybe();
3109 if (arg_action
== ACTION_SYSTEMCTL
) {
3112 action
= verb_to_action(argv
[0]);
3114 if (action
!= _ACTION_INVALID
) {
3115 method
= "StartUnit";
3116 mode
= action_table
[action
].mode
;
3117 one_name
= action_table
[action
].target
;
3119 if (streq(argv
[0], "isolate")) {
3120 method
= "StartUnit";
3125 method
= verb_to_method(argv
[0]);
3126 mode
= arg_job_mode
;
3131 assert(arg_action
>= 0 && arg_action
< _ACTION_MAX
);
3132 assert(action_table
[arg_action
].target
);
3133 assert(action_table
[arg_action
].mode
);
3135 method
= "StartUnit";
3136 mode
= action_table
[arg_action
].mode
;
3137 one_name
= action_table
[arg_action
].target
;
3141 names
= strv_new(one_name
, NULL
);
3143 r
= expand_names(bus
, strv_skip(argv
, 1), suffix
, &names
);
3145 return log_error_errno(r
, "Failed to expand names: %m");
3148 if (!arg_no_block
) {
3149 r
= bus_wait_for_jobs_new(bus
, &w
);
3151 return log_error_errno(r
, "Could not watch jobs: %m");
3155 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3157 wait_context
.unit_paths
= set_new(&string_hash_ops
);
3158 if (!wait_context
.unit_paths
)
3161 r
= sd_bus_call_method(
3163 "org.freedesktop.systemd1",
3164 "/org/freedesktop/systemd1",
3165 "org.freedesktop.systemd1.Manager",
3170 return log_error_errno(r
, "Failed to enable subscription: %s", bus_error_message(&error
, r
));
3171 r
= sd_event_default(&wait_context
.event
);
3173 return log_error_errno(r
, "Failed to allocate event loop: %m");
3174 r
= sd_bus_attach_event(bus
, wait_context
.event
, 0);
3176 return log_error_errno(r
, "Failed to attach bus to event loop: %m");
3179 STRV_FOREACH(name
, names
) {
3180 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3183 q
= start_unit_one(bus
, method
, *name
, mode
, &error
, w
, arg_wait
? &wait_context
: NULL
);
3184 if (r
>= 0 && q
< 0)
3185 r
= translate_bus_error_to_exit_status(q
, &error
);
3188 if (!arg_no_block
) {
3189 int q
, arg_count
= 0;
3190 const char* extra_args
[4] = {};
3192 if (arg_scope
!= UNIT_FILE_SYSTEM
)
3193 extra_args
[arg_count
++] = "--user";
3195 assert(IN_SET(arg_transport
, BUS_TRANSPORT_LOCAL
, BUS_TRANSPORT_REMOTE
, BUS_TRANSPORT_MACHINE
));
3196 if (arg_transport
== BUS_TRANSPORT_REMOTE
) {
3197 extra_args
[arg_count
++] = "-H";
3198 extra_args
[arg_count
++] = arg_host
;
3199 } else if (arg_transport
== BUS_TRANSPORT_MACHINE
) {
3200 extra_args
[arg_count
++] = "-M";
3201 extra_args
[arg_count
++] = arg_host
;
3204 q
= bus_wait_for_jobs(w
, arg_quiet
, extra_args
);
3208 /* When stopping units, warn if they can still be triggered by
3209 * another active unit (socket, path, timer) */
3210 if (!arg_quiet
&& streq(method
, "StopUnit"))
3211 STRV_FOREACH(name
, names
)
3212 check_triggering_units(bus
, *name
);
3215 if (r
>= 0 && arg_wait
) {
3217 q
= sd_event_loop(wait_context
.event
);
3219 return log_error_errno(q
, "Failed to run event loop: %m");
3220 if (wait_context
.any_failed
)
3228 static int logind_set_wall_message(void) {
3229 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3231 _cleanup_free_
char *m
= NULL
;
3234 r
= acquire_bus(BUS_FULL
, &bus
);
3238 m
= strv_join(arg_wall
, " ");
3242 r
= sd_bus_call_method(
3244 "org.freedesktop.login1",
3245 "/org/freedesktop/login1",
3246 "org.freedesktop.login1.Manager",
3255 return log_warning_errno(r
, "Failed to set wall message, ignoring: %s", bus_error_message(&error
, r
));
3260 /* Ask systemd-logind, which might grant access to unprivileged users
3261 * through PolicyKit */
3262 static int logind_reboot(enum action a
) {
3264 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3265 const char *method
, *description
;
3269 r
= acquire_bus(BUS_FULL
, &bus
);
3275 case ACTION_POWEROFF
:
3276 method
= "PowerOff";
3277 description
= "power off system";
3282 description
= "reboot system";
3287 description
= "halt system";
3290 case ACTION_SUSPEND
:
3292 description
= "suspend system";
3295 case ACTION_HIBERNATE
:
3296 method
= "Hibernate";
3297 description
= "hibernate system";
3300 case ACTION_HYBRID_SLEEP
:
3301 method
= "HybridSleep";
3302 description
= "put system into hybrid sleep";
3309 polkit_agent_open_maybe();
3310 (void) logind_set_wall_message();
3312 r
= sd_bus_call_method(
3314 "org.freedesktop.login1",
3315 "/org/freedesktop/login1",
3316 "org.freedesktop.login1.Manager",
3320 "b", arg_ask_password
);
3322 return log_error_errno(r
, "Failed to %s via logind: %s", description
, bus_error_message(&error
, r
));
3330 static int logind_check_inhibitors(enum action a
) {
3332 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
3333 _cleanup_strv_free_
char **sessions
= NULL
;
3334 const char *what
, *who
, *why
, *mode
;
3341 if (arg_ignore_inhibitors
|| arg_force
> 0)
3353 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
3356 r
= acquire_bus(BUS_FULL
, &bus
);
3360 r
= sd_bus_call_method(
3362 "org.freedesktop.login1",
3363 "/org/freedesktop/login1",
3364 "org.freedesktop.login1.Manager",
3370 /* If logind is not around, then there are no inhibitors... */
3373 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssuu)");
3375 return bus_log_parse_error(r
);
3377 while ((r
= sd_bus_message_read(reply
, "(ssssuu)", &what
, &who
, &why
, &mode
, &uid
, &pid
)) > 0) {
3378 _cleanup_free_
char *comm
= NULL
, *user
= NULL
;
3379 _cleanup_strv_free_
char **sv
= NULL
;
3381 if (!streq(mode
, "block"))
3384 sv
= strv_split(what
, ":");
3388 if (!pid_is_valid((pid_t
) pid
)) {
3389 log_error("Invalid PID "PID_FMT
".", (pid_t
) pid
);
3393 if (!strv_contains(sv
,
3398 ACTION_KEXEC
) ? "shutdown" : "sleep"))
3401 get_process_comm(pid
, &comm
);
3402 user
= uid_to_name(uid
);
3404 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT
" \"%s\", user %s), reason is \"%s\".",
3405 who
, (pid_t
) pid
, strna(comm
), strna(user
), why
);
3410 return bus_log_parse_error(r
);
3412 r
= sd_bus_message_exit_container(reply
);
3414 return bus_log_parse_error(r
);
3416 /* Check for current sessions */
3417 sd_get_sessions(&sessions
);
3418 STRV_FOREACH(s
, sessions
) {
3419 _cleanup_free_
char *type
= NULL
, *tty
= NULL
, *seat
= NULL
, *user
= NULL
, *service
= NULL
, *class = NULL
;
3421 if (sd_session_get_uid(*s
, &uid
) < 0 || uid
== getuid())
3424 if (sd_session_get_class(*s
, &class) < 0 || !streq(class, "user"))
3427 if (sd_session_get_type(*s
, &type
) < 0 || !STR_IN_SET(type
, "x11", "wayland", "tty", "mir"))
3430 sd_session_get_tty(*s
, &tty
);
3431 sd_session_get_seat(*s
, &seat
);
3432 sd_session_get_service(*s
, &service
);
3433 user
= uid_to_name(uid
);
3435 log_warning("User %s is logged in on %s.", strna(user
), isempty(tty
) ? (isempty(seat
) ? strna(service
) : seat
) : tty
);
3442 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
3443 action_table
[a
].verb
);
3451 static int logind_prepare_firmware_setup(void) {
3453 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3457 r
= acquire_bus(BUS_FULL
, &bus
);
3461 r
= sd_bus_call_method(
3463 "org.freedesktop.login1",
3464 "/org/freedesktop/login1",
3465 "org.freedesktop.login1.Manager",
3466 "SetRebootToFirmwareSetup",
3471 return log_error_errno(r
, "Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error
, r
));
3475 log_error("Cannot remotely indicate to EFI to boot into setup mode.");
3480 static int prepare_firmware_setup(void) {
3483 if (!arg_firmware_setup
)
3486 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
3488 r
= efi_set_reboot_to_firmware(true);
3490 log_debug_errno(r
, "Cannot indicate to EFI to boot into setup mode, will retry via logind: %m");
3495 return logind_prepare_firmware_setup();
3498 static int load_kexec_kernel(void) {
3499 _cleanup_(boot_config_free
) BootConfig config
= {};
3500 _cleanup_free_
char *kernel
= NULL
, *initrd
= NULL
, *options
= NULL
;
3505 if (kexec_loaded()) {
3506 log_debug("Kexec kernel already loaded.");
3510 r
= find_esp(&arg_esp_path
, NULL
, NULL
, NULL
, NULL
);
3512 return log_error_errno(r
, "Cannot find the ESP partition mount point: %m");
3514 r
= boot_entries_load_config(arg_esp_path
, &config
);
3516 return log_error_errno(r
, "Failed to load bootspec config from \"%s/loader\": %m",
3519 if (config
.default_entry
< 0) {
3520 log_error("No entry suitable as default, refusing to guess.");
3523 e
= &config
.entries
[config
.default_entry
];
3525 if (strv_length(e
->initrd
) > 1) {
3526 log_error("Boot entry specifies multiple initrds, which is not supported currently.");
3530 kernel
= path_join(NULL
, arg_esp_path
, e
->kernel
);
3531 if (!strv_isempty(e
->initrd
))
3532 initrd
= path_join(NULL
, arg_esp_path
, *e
->initrd
);
3533 options
= strv_join(e
->options
, " ");
3537 log_debug("%s kexec kernel %s initrd %s options \"%s\".",
3538 arg_dry_run
? "Would load" : "loading",
3539 kernel
, initrd
, options
);
3545 return log_error_errno(errno
, "Failed to fork: %m");
3546 else if (pid
== 0) {
3548 const char* const args
[] = {
3551 "--append", options
,
3552 initrd
? "--initrd" : NULL
, initrd
,
3557 (void) reset_all_signal_handlers();
3558 (void) reset_signal_mask();
3559 assert_se(prctl(PR_SET_PDEATHSIG
, SIGTERM
) == 0);
3561 execv(args
[0], (char * const *) args
);
3562 _exit(EXIT_FAILURE
);
3564 return wait_for_terminate_and_warn("kexec", pid
, true);
3567 static int set_exit_code(uint8_t code
) {
3568 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3572 r
= acquire_bus(BUS_MANAGER
, &bus
);
3576 r
= sd_bus_call_method(
3578 "org.freedesktop.systemd1",
3579 "/org/freedesktop/systemd1",
3580 "org.freedesktop.systemd1.Manager",
3586 return log_error_errno(r
, "Failed to set exit code: %s", bus_error_message(&error
, r
));
3591 static int start_special(int argc
, char *argv
[], void *userdata
) {
3594 bool termination_action
; /* an action that terminates the manager,
3595 * can be performed also by signal. */
3599 a
= verb_to_action(argv
[0]);
3601 r
= logind_check_inhibitors(a
);
3605 if (arg_force
>= 2 && geteuid() != 0) {
3606 log_error("Must be root.");
3610 r
= prepare_firmware_setup();
3614 if (a
== ACTION_REBOOT
&& argc
> 1) {
3615 r
= update_reboot_parameter_and_warn(argv
[1]);
3619 } else if (a
== ACTION_KEXEC
) {
3620 r
= load_kexec_kernel();
3624 } else if (a
== ACTION_EXIT
&& argc
> 1) {
3627 /* If the exit code is not given on the command line,
3628 * don't reset it to zero: just keep it as it might
3629 * have been set previously. */
3631 r
= safe_atou8(argv
[1], &code
);
3633 return log_error_errno(r
, "Invalid exit code.");
3635 r
= set_exit_code(code
);
3640 termination_action
= IN_SET(a
,
3644 if (termination_action
&& arg_force
>= 2)
3647 if (arg_force
>= 1 &&
3648 (termination_action
|| IN_SET(a
, ACTION_KEXEC
, ACTION_EXIT
)))
3649 r
= trivial_method(argc
, argv
, userdata
);
3651 /* First try logind, to allow authentication with polkit */
3658 ACTION_HYBRID_SLEEP
)) {
3660 r
= logind_reboot(a
);
3663 if (IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
3664 /* requested operation is not supported or already in progress */
3667 /* On all other errors, try low-level operation. In order to minimize the difference between
3668 * operation with and without logind, we explicitly enable non-blocking mode for this, as
3669 * logind's shutdown operations are always non-blocking. */
3671 arg_no_block
= true;
3673 } else if (IN_SET(a
, ACTION_EXIT
, ACTION_KEXEC
))
3674 /* Since exit/kexec are so close in behaviour to power-off/reboot, let's also make them
3675 * asynchronous, in order to not confuse the user needlessly with unexpected behaviour. */
3676 arg_no_block
= true;
3678 r
= start_unit(argc
, argv
, userdata
);
3681 if (termination_action
&& arg_force
< 2 &&
3682 IN_SET(r
, -ENOENT
, -ETIMEDOUT
))
3683 log_notice("It is possible to perform action directly, see discussion of --force --force in man:systemctl(1).");
3688 static int start_system_special(int argc
, char *argv
[], void *userdata
) {
3689 /* Like start_special above, but raises an error when running in user mode */
3691 if (arg_scope
!= UNIT_FILE_SYSTEM
) {
3692 log_error("Bad action for %s mode.",
3693 arg_scope
== UNIT_FILE_GLOBAL
? "--global" : "--user");
3697 return start_special(argc
, argv
, userdata
);
3700 static int check_unit_generic(int code
, const UnitActiveState good_states
[], int nb_states
, char **args
) {
3701 _cleanup_strv_free_
char **names
= NULL
;
3702 UnitActiveState active_state
;
3708 r
= acquire_bus(BUS_MANAGER
, &bus
);
3712 r
= expand_names(bus
, args
, NULL
, &names
);
3714 return log_error_errno(r
, "Failed to expand names: %m");
3716 STRV_FOREACH(name
, names
) {
3717 r
= get_state_one_unit(bus
, *name
, &active_state
);
3722 puts(unit_active_state_to_string(active_state
));
3724 for (i
= 0; i
< nb_states
; ++i
)
3725 if (good_states
[i
] == active_state
)
3729 /* use the given return code for the case that we won't find
3730 * any unit which matches the list */
3731 return found
? 0 : code
;
3734 static int check_unit_active(int argc
, char *argv
[], void *userdata
) {
3735 const UnitActiveState states
[] = { UNIT_ACTIVE
, UNIT_RELOADING
};
3736 /* According to LSB: 3, "program is not running" */
3737 return check_unit_generic(EXIT_PROGRAM_NOT_RUNNING
, states
, ELEMENTSOF(states
), strv_skip(argv
, 1));
3740 static int check_unit_failed(int argc
, char *argv
[], void *userdata
) {
3741 const UnitActiveState states
[] = { UNIT_FAILED
};
3742 return check_unit_generic(EXIT_PROGRAM_DEAD_AND_PID_EXISTS
, states
, ELEMENTSOF(states
), strv_skip(argv
, 1));
3745 static int kill_unit(int argc
, char *argv
[], void *userdata
) {
3746 _cleanup_strv_free_
char **names
= NULL
;
3747 char *kill_who
= NULL
, **name
;
3751 r
= acquire_bus(BUS_MANAGER
, &bus
);
3755 polkit_agent_open_maybe();
3758 arg_kill_who
= "all";
3760 /* --fail was specified */
3761 if (streq(arg_job_mode
, "fail"))
3762 kill_who
= strjoina(arg_kill_who
, "-fail");
3764 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
3766 return log_error_errno(r
, "Failed to expand names: %m");
3768 STRV_FOREACH(name
, names
) {
3769 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3771 q
= sd_bus_call_method(
3773 "org.freedesktop.systemd1",
3774 "/org/freedesktop/systemd1",
3775 "org.freedesktop.systemd1.Manager",
3779 "ssi", *name
, kill_who
? kill_who
: arg_kill_who
, arg_signal
);
3781 log_error_errno(q
, "Failed to kill unit %s: %s", *name
, bus_error_message(&error
, q
));
3790 typedef struct ExecStatusInfo
{
3798 usec_t start_timestamp
;
3799 usec_t exit_timestamp
;
3804 LIST_FIELDS(struct ExecStatusInfo
, exec
);
3807 static void exec_status_info_free(ExecStatusInfo
*i
) {
3816 static int exec_status_info_deserialize(sd_bus_message
*m
, ExecStatusInfo
*i
) {
3817 uint64_t start_timestamp
, exit_timestamp
, start_timestamp_monotonic
, exit_timestamp_monotonic
;
3820 int32_t code
, status
;
3826 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_STRUCT
, "sasbttttuii");
3828 return bus_log_parse_error(r
);
3832 r
= sd_bus_message_read(m
, "s", &path
);
3834 return bus_log_parse_error(r
);
3836 i
->path
= strdup(path
);
3840 r
= sd_bus_message_read_strv(m
, &i
->argv
);
3842 return bus_log_parse_error(r
);
3844 r
= sd_bus_message_read(m
,
3847 &start_timestamp
, &start_timestamp_monotonic
,
3848 &exit_timestamp
, &exit_timestamp_monotonic
,
3852 return bus_log_parse_error(r
);
3855 i
->start_timestamp
= (usec_t
) start_timestamp
;
3856 i
->exit_timestamp
= (usec_t
) exit_timestamp
;
3857 i
->pid
= (pid_t
) pid
;
3861 r
= sd_bus_message_exit_container(m
);
3863 return bus_log_parse_error(r
);
3868 typedef struct UnitCondition
{
3875 LIST_FIELDS(struct UnitCondition
, conditions
);
3878 static void unit_condition_free(UnitCondition
*c
) {
3887 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitCondition
*, unit_condition_free
);
3889 typedef struct UnitStatusInfo
{
3891 const char *load_state
;
3892 const char *active_state
;
3893 const char *sub_state
;
3894 const char *unit_file_state
;
3895 const char *unit_file_preset
;
3897 const char *description
;
3898 const char *following
;
3900 char **documentation
;
3902 const char *fragment_path
;
3903 const char *source_path
;
3904 const char *control_group
;
3906 char **dropin_paths
;
3908 const char *load_error
;
3911 usec_t inactive_exit_timestamp
;
3912 usec_t inactive_exit_timestamp_monotonic
;
3913 usec_t active_enter_timestamp
;
3914 usec_t active_exit_timestamp
;
3915 usec_t inactive_enter_timestamp
;
3917 bool need_daemon_reload
;
3923 const char *status_text
;
3924 const char *pid_file
;
3928 usec_t start_timestamp
;
3929 usec_t exit_timestamp
;
3931 int exit_code
, exit_status
;
3933 usec_t condition_timestamp
;
3934 bool condition_result
;
3935 LIST_HEAD(UnitCondition
, conditions
);
3937 usec_t assert_timestamp
;
3939 bool failed_assert_trigger
;
3940 bool failed_assert_negate
;
3941 const char *failed_assert
;
3942 const char *failed_assert_parameter
;
3943 usec_t next_elapse_real
;
3944 usec_t next_elapse_monotonic
;
3947 unsigned n_accepted
;
3948 unsigned n_connections
;
3951 /* Pairs of type, path */
3955 const char *sysfs_path
;
3957 /* Mount, Automount */
3964 uint64_t memory_current
;
3965 uint64_t memory_low
;
3966 uint64_t memory_high
;
3967 uint64_t memory_max
;
3968 uint64_t memory_swap_max
;
3969 uint64_t memory_limit
;
3970 uint64_t cpu_usage_nsec
;
3971 uint64_t tasks_current
;
3974 uint64_t ip_ingress_bytes
;
3975 uint64_t ip_egress_bytes
;
3977 LIST_HEAD(ExecStatusInfo
, exec
);
3980 static void unit_status_info_free(UnitStatusInfo
*info
) {
3984 strv_free(info
->documentation
);
3985 strv_free(info
->dropin_paths
);
3986 strv_free(info
->listen
);
3988 while ((c
= info
->conditions
)) {
3989 LIST_REMOVE(conditions
, info
->conditions
, c
);
3990 unit_condition_free(c
);
3993 while ((p
= info
->exec
)) {
3994 LIST_REMOVE(exec
, info
->exec
, p
);
3995 exec_status_info_free(p
);
3999 static void print_status_info(
4005 const char *active_on
, *active_off
, *on
, *off
, *ss
;
4007 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], *s1
;
4008 char since2
[FORMAT_TIMESTAMP_MAX
], *s2
;
4015 /* This shows pretty information about a unit. See
4016 * print_property() for a low-level property printer */
4018 if (streq_ptr(i
->active_state
, "failed")) {
4019 active_on
= ansi_highlight_red();
4020 active_off
= ansi_normal();
4021 } else if (STRPTR_IN_SET(i
->active_state
, "active", "reloading")) {
4022 active_on
= ansi_highlight_green();
4023 active_off
= ansi_normal();
4025 active_on
= active_off
= "";
4027 printf("%s%s%s %s", active_on
, special_glyph(BLACK_CIRCLE
), active_off
, strna(i
->id
));
4029 if (i
->description
&& !streq_ptr(i
->id
, i
->description
))
4030 printf(" - %s", i
->description
);
4035 printf(" Follow: unit currently follows state of %s\n", i
->following
);
4037 if (streq_ptr(i
->load_state
, "error")) {
4038 on
= ansi_highlight_red();
4039 off
= ansi_normal();
4043 path
= i
->source_path
? i
->source_path
: i
->fragment_path
;
4045 if (i
->load_error
!= 0)
4046 printf(" Loaded: %s%s%s (Reason: %s)\n",
4047 on
, strna(i
->load_state
), off
, i
->load_error
);
4048 else if (path
&& !isempty(i
->unit_file_state
) && !isempty(i
->unit_file_preset
))
4049 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
4050 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
, i
->unit_file_preset
);
4051 else if (path
&& !isempty(i
->unit_file_state
))
4052 printf(" Loaded: %s%s%s (%s; %s)\n",
4053 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
);
4055 printf(" Loaded: %s%s%s (%s)\n",
4056 on
, strna(i
->load_state
), off
, path
);
4058 printf(" Loaded: %s%s%s\n",
4059 on
, strna(i
->load_state
), off
);
4062 printf("Transient: yes\n");
4064 if (!strv_isempty(i
->dropin_paths
)) {
4065 _cleanup_free_
char *dir
= NULL
;
4069 STRV_FOREACH(dropin
, i
->dropin_paths
) {
4070 if (! dir
|| last
) {
4071 printf(dir
? " " : " Drop-In: ");
4075 dir
= dirname_malloc(*dropin
);
4081 printf("%s\n %s", dir
,
4082 special_glyph(TREE_RIGHT
));
4085 last
= ! (*(dropin
+ 1) && startswith(*(dropin
+ 1), dir
));
4087 printf("%s%s", basename(*dropin
), last
? "\n" : ", ");
4091 ss
= streq_ptr(i
->active_state
, i
->sub_state
) ? NULL
: i
->sub_state
;
4093 printf(" Active: %s%s (%s)%s",
4094 active_on
, strna(i
->active_state
), ss
, active_off
);
4096 printf(" Active: %s%s%s",
4097 active_on
, strna(i
->active_state
), active_off
);
4099 if (!isempty(i
->result
) && !streq(i
->result
, "success"))
4100 printf(" (Result: %s)", i
->result
);
4102 timestamp
= STRPTR_IN_SET(i
->active_state
, "active", "reloading") ? i
->active_enter_timestamp
:
4103 STRPTR_IN_SET(i
->active_state
, "inactive", "failed") ? i
->inactive_enter_timestamp
:
4104 STRPTR_IN_SET(i
->active_state
, "activating") ? i
->inactive_exit_timestamp
:
4105 i
->active_exit_timestamp
;
4107 s1
= format_timestamp_relative(since1
, sizeof(since1
), timestamp
);
4108 s2
= format_timestamp(since2
, sizeof(since2
), timestamp
);
4111 printf(" since %s; %s\n", s2
, s1
);
4113 printf(" since %s\n", s2
);
4117 if (endswith(i
->id
, ".timer")) {
4118 char tstamp1
[FORMAT_TIMESTAMP_RELATIVE_MAX
],
4119 tstamp2
[FORMAT_TIMESTAMP_MAX
];
4120 char *next_rel_time
, *next_time
;
4121 dual_timestamp nw
, next
= {i
->next_elapse_real
,
4122 i
->next_elapse_monotonic
};
4125 printf(" Trigger: ");
4127 dual_timestamp_get(&nw
);
4128 next_elapse
= calc_next_elapse(&nw
, &next
);
4129 next_rel_time
= format_timestamp_relative(tstamp1
,
4132 next_time
= format_timestamp(tstamp2
,
4136 if (next_time
&& next_rel_time
)
4137 printf("%s; %s\n", next_time
, next_rel_time
);
4142 if (!i
->condition_result
&& i
->condition_timestamp
> 0) {
4146 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->condition_timestamp
);
4147 s2
= format_timestamp(since2
, sizeof(since2
), i
->condition_timestamp
);
4149 printf("Condition: start %scondition failed%s at %s%s%s\n",
4150 ansi_highlight_yellow(), ansi_normal(),
4151 s2
, s1
? "; " : "", strempty(s1
));
4153 LIST_FOREACH(conditions
, c
, i
->conditions
)
4154 if (c
->tristate
< 0)
4157 LIST_FOREACH(conditions
, c
, i
->conditions
)
4158 if (c
->tristate
< 0)
4159 printf(" %s %s=%s%s%s was not met\n",
4160 --n
? special_glyph(TREE_BRANCH
) : special_glyph(TREE_RIGHT
),
4162 c
->trigger
? "|" : "",
4163 c
->negate
? "!" : "",
4167 if (!i
->assert_result
&& i
->assert_timestamp
> 0) {
4168 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->assert_timestamp
);
4169 s2
= format_timestamp(since2
, sizeof(since2
), i
->assert_timestamp
);
4171 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
4172 ansi_highlight_red(), ansi_normal(),
4173 s2
, s1
? "; " : "", strempty(s1
));
4174 if (i
->failed_assert_trigger
)
4175 printf(" none of the trigger assertions were met\n");
4176 else if (i
->failed_assert
)
4177 printf(" %s=%s%s was not met\n",
4179 i
->failed_assert_negate
? "!" : "",
4180 i
->failed_assert_parameter
);
4184 printf(" Device: %s\n", i
->sysfs_path
);
4186 printf(" Where: %s\n", i
->where
);
4188 printf(" What: %s\n", i
->what
);
4190 STRV_FOREACH(t
, i
->documentation
)
4191 printf(" %*s %s\n", 9, t
== i
->documentation
? "Docs:" : "", *t
);
4193 STRV_FOREACH_PAIR(t
, t2
, i
->listen
)
4194 printf(" %*s %s (%s)\n", 9, t
== i
->listen
? "Listen:" : "", *t2
, *t
);
4197 printf(" Accepted: %u; Connected: %u\n", i
->n_accepted
, i
->n_connections
);
4199 LIST_FOREACH(exec
, p
, i
->exec
) {
4200 _cleanup_free_
char *argv
= NULL
;
4203 /* Only show exited processes here */
4207 argv
= strv_join(p
->argv
, " ");
4208 printf(" Process: "PID_FMT
" %s=%s ", p
->pid
, p
->name
, strna(argv
));
4210 good
= is_clean_exit(p
->code
, p
->status
, EXIT_CLEAN_DAEMON
, NULL
);
4212 on
= ansi_highlight_red();
4213 off
= ansi_normal();
4217 printf("%s(code=%s, ", on
, sigchld_code_to_string(p
->code
));
4219 if (p
->code
== CLD_EXITED
) {
4222 printf("status=%i", p
->status
);
4224 c
= exit_status_to_string(p
->status
, EXIT_STATUS_SYSTEMD
);
4229 printf("signal=%s", signal_to_string(p
->status
));
4231 printf(")%s\n", off
);
4233 if (i
->main_pid
== p
->pid
&&
4234 i
->start_timestamp
== p
->start_timestamp
&&
4235 i
->exit_timestamp
== p
->start_timestamp
)
4236 /* Let's not show this twice */
4239 if (p
->pid
== i
->control_pid
)
4243 if (i
->main_pid
> 0 || i
->control_pid
> 0) {
4244 if (i
->main_pid
> 0) {
4245 printf(" Main PID: "PID_FMT
, i
->main_pid
);
4249 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
4250 _cleanup_free_
char *comm
= NULL
;
4252 (void) get_process_comm(i
->main_pid
, &comm
);
4254 printf(" (%s)", comm
);
4257 } else if (i
->exit_code
> 0) {
4258 printf(" (code=%s, ", sigchld_code_to_string(i
->exit_code
));
4260 if (i
->exit_code
== CLD_EXITED
) {
4263 printf("status=%i", i
->exit_status
);
4265 c
= exit_status_to_string(i
->exit_status
, EXIT_STATUS_SYSTEMD
);
4270 printf("signal=%s", signal_to_string(i
->exit_status
));
4275 if (i
->control_pid
> 0) {
4276 _cleanup_free_
char *c
= NULL
;
4278 if (i
->main_pid
> 0)
4279 fputs("; Control PID: ", stdout
);
4281 fputs("Cntrl PID: ", stdout
); /* if first in column, abbreviated so it fits alignment */
4283 printf(PID_FMT
, i
->control_pid
);
4285 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
4286 (void) get_process_comm(i
->control_pid
, &c
);
4296 printf(" Status: \"%s\"\n", i
->status_text
);
4297 if (i
->status_errno
> 0)
4298 printf(" Error: %i (%s)\n", i
->status_errno
, strerror(i
->status_errno
));
4300 if (i
->ip_ingress_bytes
!= (uint64_t) -1 && i
->ip_egress_bytes
!= (uint64_t) -1) {
4301 char buf_in
[FORMAT_BYTES_MAX
], buf_out
[FORMAT_BYTES_MAX
];
4303 printf(" IP: %s in, %s out\n",
4304 format_bytes(buf_in
, sizeof(buf_in
), i
->ip_ingress_bytes
),
4305 format_bytes(buf_out
, sizeof(buf_out
), i
->ip_egress_bytes
));
4308 if (i
->tasks_current
!= (uint64_t) -1) {
4309 printf(" Tasks: %" PRIu64
, i
->tasks_current
);
4311 if (i
->tasks_max
!= (uint64_t) -1)
4312 printf(" (limit: %" PRIu64
")\n", i
->tasks_max
);
4317 if (i
->memory_current
!= (uint64_t) -1) {
4318 char buf
[FORMAT_BYTES_MAX
];
4320 printf(" Memory: %s", format_bytes(buf
, sizeof(buf
), i
->memory_current
));
4322 if (i
->memory_low
> 0 || i
->memory_high
!= CGROUP_LIMIT_MAX
||
4323 i
->memory_max
!= CGROUP_LIMIT_MAX
|| i
->memory_swap_max
!= CGROUP_LIMIT_MAX
||
4324 i
->memory_limit
!= CGROUP_LIMIT_MAX
) {
4325 const char *prefix
= "";
4328 if (i
->memory_low
> 0) {
4329 printf("%slow: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_low
));
4332 if (i
->memory_high
!= CGROUP_LIMIT_MAX
) {
4333 printf("%shigh: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_high
));
4336 if (i
->memory_max
!= CGROUP_LIMIT_MAX
) {
4337 printf("%smax: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_max
));
4340 if (i
->memory_swap_max
!= CGROUP_LIMIT_MAX
) {
4341 printf("%sswap max: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_swap_max
));
4344 if (i
->memory_limit
!= CGROUP_LIMIT_MAX
) {
4345 printf("%slimit: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_limit
));
4353 if (i
->cpu_usage_nsec
!= (uint64_t) -1) {
4354 char buf
[FORMAT_TIMESPAN_MAX
];
4355 printf(" CPU: %s\n", format_timespan(buf
, sizeof(buf
), i
->cpu_usage_nsec
/ NSEC_PER_USEC
, USEC_PER_MSEC
));
4358 if (i
->control_group
) {
4359 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
4360 static const char prefix
[] = " ";
4363 printf(" CGroup: %s\n", i
->control_group
);
4366 if (c
> sizeof(prefix
) - 1)
4367 c
-= sizeof(prefix
) - 1;
4371 r
= unit_show_processes(bus
, i
->id
, i
->control_group
, prefix
, c
, get_output_flags(), &error
);
4376 /* Fallback for older systemd versions where the GetUnitProcesses() call is not yet available */
4378 if (i
->main_pid
> 0)
4379 extra
[k
++] = i
->main_pid
;
4381 if (i
->control_pid
> 0)
4382 extra
[k
++] = i
->control_pid
;
4384 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, prefix
, c
, extra
, k
, get_output_flags());
4386 log_warning_errno(r
, "Failed to dump process list, ignoring: %s", bus_error_message(&error
, r
));
4389 if (i
->id
&& arg_transport
== BUS_TRANSPORT_LOCAL
)
4390 show_journal_by_unit(
4395 i
->inactive_exit_timestamp_monotonic
,
4398 get_output_flags() | OUTPUT_BEGIN_NEWLINE
,
4399 SD_JOURNAL_LOCAL_ONLY
,
4400 arg_scope
== UNIT_FILE_SYSTEM
,
4403 if (i
->need_daemon_reload
)
4404 warn_unit_file_changed(i
->id
);
4407 static void show_unit_help(UnitStatusInfo
*i
) {
4412 if (!i
->documentation
) {
4413 log_info("Documentation for %s not known.", i
->id
);
4417 STRV_FOREACH(p
, i
->documentation
)
4418 if (startswith(*p
, "man:"))
4419 show_man_page(*p
+ 4, false);
4421 log_info("Can't show: %s", *p
);
4424 static int status_property(const char *name
, sd_bus_message
*m
, UnitStatusInfo
*i
, const char *contents
) {
4431 switch (contents
[0]) {
4433 case SD_BUS_TYPE_STRING
: {
4436 r
= sd_bus_message_read(m
, "s", &s
);
4438 return bus_log_parse_error(r
);
4441 if (streq(name
, "Id"))
4443 else if (streq(name
, "LoadState"))
4445 else if (streq(name
, "ActiveState"))
4446 i
->active_state
= s
;
4447 else if (streq(name
, "SubState"))
4449 else if (streq(name
, "Description"))
4451 else if (streq(name
, "FragmentPath"))
4452 i
->fragment_path
= s
;
4453 else if (streq(name
, "SourcePath"))
4456 else if (streq(name
, "DefaultControlGroup")) {
4458 e
= startswith(s
, SYSTEMD_CGROUP_CONTROLLER
":");
4460 i
->control_group
= e
;
4463 else if (streq(name
, "ControlGroup"))
4464 i
->control_group
= s
;
4465 else if (streq(name
, "StatusText"))
4467 else if (streq(name
, "PIDFile"))
4469 else if (streq(name
, "SysFSPath"))
4471 else if (streq(name
, "Where"))
4473 else if (streq(name
, "What"))
4475 else if (streq(name
, "Following"))
4477 else if (streq(name
, "UnitFileState"))
4478 i
->unit_file_state
= s
;
4479 else if (streq(name
, "UnitFilePreset"))
4480 i
->unit_file_preset
= s
;
4481 else if (streq(name
, "Result"))
4488 case SD_BUS_TYPE_BOOLEAN
: {
4491 r
= sd_bus_message_read(m
, "b", &b
);
4493 return bus_log_parse_error(r
);
4495 if (streq(name
, "Accept"))
4497 else if (streq(name
, "NeedDaemonReload"))
4498 i
->need_daemon_reload
= b
;
4499 else if (streq(name
, "ConditionResult"))
4500 i
->condition_result
= b
;
4501 else if (streq(name
, "AssertResult"))
4502 i
->assert_result
= b
;
4503 else if (streq(name
, "Transient"))
4509 case SD_BUS_TYPE_UINT32
: {
4512 r
= sd_bus_message_read(m
, "u", &u
);
4514 return bus_log_parse_error(r
);
4516 if (streq(name
, "MainPID")) {
4518 i
->main_pid
= (pid_t
) u
;
4521 } else if (streq(name
, "ControlPID"))
4522 i
->control_pid
= (pid_t
) u
;
4523 else if (streq(name
, "ExecMainPID")) {
4525 i
->main_pid
= (pid_t
) u
;
4526 } else if (streq(name
, "NAccepted"))
4528 else if (streq(name
, "NConnections"))
4529 i
->n_connections
= u
;
4534 case SD_BUS_TYPE_INT32
: {
4537 r
= sd_bus_message_read(m
, "i", &j
);
4539 return bus_log_parse_error(r
);
4541 if (streq(name
, "ExecMainCode"))
4542 i
->exit_code
= (int) j
;
4543 else if (streq(name
, "ExecMainStatus"))
4544 i
->exit_status
= (int) j
;
4545 else if (streq(name
, "StatusErrno"))
4546 i
->status_errno
= (int) j
;
4551 case SD_BUS_TYPE_UINT64
: {
4554 r
= sd_bus_message_read(m
, "t", &u
);
4556 return bus_log_parse_error(r
);
4558 if (streq(name
, "ExecMainStartTimestamp"))
4559 i
->start_timestamp
= (usec_t
) u
;
4560 else if (streq(name
, "ExecMainExitTimestamp"))
4561 i
->exit_timestamp
= (usec_t
) u
;
4562 else if (streq(name
, "ActiveEnterTimestamp"))
4563 i
->active_enter_timestamp
= (usec_t
) u
;
4564 else if (streq(name
, "InactiveEnterTimestamp"))
4565 i
->inactive_enter_timestamp
= (usec_t
) u
;
4566 else if (streq(name
, "InactiveExitTimestamp"))
4567 i
->inactive_exit_timestamp
= (usec_t
) u
;
4568 else if (streq(name
, "InactiveExitTimestampMonotonic"))
4569 i
->inactive_exit_timestamp_monotonic
= (usec_t
) u
;
4570 else if (streq(name
, "ActiveExitTimestamp"))
4571 i
->active_exit_timestamp
= (usec_t
) u
;
4572 else if (streq(name
, "ConditionTimestamp"))
4573 i
->condition_timestamp
= (usec_t
) u
;
4574 else if (streq(name
, "AssertTimestamp"))
4575 i
->assert_timestamp
= (usec_t
) u
;
4576 else if (streq(name
, "MemoryCurrent"))
4577 i
->memory_current
= u
;
4578 else if (streq(name
, "MemoryLow"))
4580 else if (streq(name
, "MemoryHigh"))
4582 else if (streq(name
, "MemoryMax"))
4584 else if (streq(name
, "MemorySwapMax"))
4585 i
->memory_swap_max
= u
;
4586 else if (streq(name
, "MemoryLimit"))
4587 i
->memory_limit
= u
;
4588 else if (streq(name
, "TasksCurrent"))
4589 i
->tasks_current
= u
;
4590 else if (streq(name
, "TasksMax"))
4592 else if (streq(name
, "CPUUsageNSec"))
4593 i
->cpu_usage_nsec
= u
;
4594 else if (streq(name
, "NextElapseUSecMonotonic"))
4595 i
->next_elapse_monotonic
= u
;
4596 else if (streq(name
, "NextElapseUSecRealtime"))
4597 i
->next_elapse_real
= u
;
4598 else if (streq(name
, "IPIngressBytes"))
4599 i
->ip_ingress_bytes
= u
;
4600 else if (streq(name
, "IPEgressBytes"))
4601 i
->ip_egress_bytes
= u
;
4606 case SD_BUS_TYPE_ARRAY
:
4608 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
4609 _cleanup_free_ ExecStatusInfo
*info
= NULL
;
4611 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4613 return bus_log_parse_error(r
);
4615 info
= new0(ExecStatusInfo
, 1);
4619 while ((r
= exec_status_info_deserialize(m
, info
)) > 0) {
4621 info
->name
= strdup(name
);
4625 LIST_PREPEND(exec
, i
->exec
, info
);
4627 info
= new0(ExecStatusInfo
, 1);
4633 return bus_log_parse_error(r
);
4635 r
= sd_bus_message_exit_container(m
);
4637 return bus_log_parse_error(r
);
4641 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
4642 const char *type
, *path
;
4644 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4646 return bus_log_parse_error(r
);
4648 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0) {
4650 r
= strv_extend(&i
->listen
, type
);
4654 r
= strv_extend(&i
->listen
, path
);
4659 return bus_log_parse_error(r
);
4661 r
= sd_bus_message_exit_container(m
);
4663 return bus_log_parse_error(r
);
4667 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "DropInPaths")) {
4669 r
= sd_bus_message_read_strv(m
, &i
->dropin_paths
);
4671 return bus_log_parse_error(r
);
4673 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Documentation")) {
4675 r
= sd_bus_message_read_strv(m
, &i
->documentation
);
4677 return bus_log_parse_error(r
);
4679 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Conditions")) {
4680 const char *cond
, *param
;
4681 int trigger
, negate
;
4684 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
4686 return bus_log_parse_error(r
);
4688 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
4689 _cleanup_(unit_condition_freep
) UnitCondition
*c
= NULL
;
4691 log_debug("%s trigger=%d negate=%d %s →%d", cond
, trigger
, negate
, param
, state
);
4693 c
= new0(UnitCondition
, 1);
4697 c
->name
= strdup(cond
);
4698 c
->param
= strdup(param
);
4699 if (!c
->name
|| !c
->param
)
4702 c
->trigger
= trigger
;
4704 c
->tristate
= state
;
4706 LIST_PREPEND(conditions
, i
->conditions
, c
);
4710 return bus_log_parse_error(r
);
4712 r
= sd_bus_message_exit_container(m
);
4714 return bus_log_parse_error(r
);
4716 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Asserts")) {
4717 const char *cond
, *param
;
4718 int trigger
, negate
;
4721 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
4723 return bus_log_parse_error(r
);
4725 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
4726 log_debug("%s %d %d %s %d", cond
, trigger
, negate
, param
, state
);
4727 if (state
< 0 && (!trigger
|| !i
->failed_assert
)) {
4728 i
->failed_assert
= cond
;
4729 i
->failed_assert_trigger
= trigger
;
4730 i
->failed_assert_negate
= negate
;
4731 i
->failed_assert_parameter
= param
;
4735 return bus_log_parse_error(r
);
4737 r
= sd_bus_message_exit_container(m
);
4739 return bus_log_parse_error(r
);
4746 case SD_BUS_TYPE_STRUCT_BEGIN
:
4748 if (streq(name
, "LoadError")) {
4749 const char *n
, *message
;
4751 r
= sd_bus_message_read(m
, "(ss)", &n
, &message
);
4753 return bus_log_parse_error(r
);
4755 if (!isempty(message
))
4756 i
->load_error
= message
;
4769 r
= sd_bus_message_skip(m
, contents
);
4771 return bus_log_parse_error(r
);
4776 #define print_prop(name, fmt, ...) \
4779 printf(fmt "\n", __VA_ARGS__); \
4781 printf("%s=" fmt "\n", name, __VA_ARGS__); \
4784 static int print_property(const char *name
, sd_bus_message
*m
, const char *contents
) {
4790 /* This is a low-level property printer, see
4791 * print_status_info() for the nicer output */
4793 if (arg_properties
&& !strv_find(arg_properties
, name
)) {
4794 /* skip what we didn't read */
4795 r
= sd_bus_message_skip(m
, contents
);
4799 switch (contents
[0]) {
4801 case SD_BUS_TYPE_STRUCT_BEGIN
:
4803 if (contents
[1] == SD_BUS_TYPE_UINT32
&& streq(name
, "Job")) {
4806 r
= sd_bus_message_read(m
, "(uo)", &u
, NULL
);
4808 return bus_log_parse_error(r
);
4811 print_prop(name
, "%"PRIu32
, u
);
4813 print_prop(name
, "%s", "");
4817 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Unit")) {
4820 r
= sd_bus_message_read(m
, "(so)", &s
, NULL
);
4822 return bus_log_parse_error(r
);
4824 if (arg_all
|| !isempty(s
))
4825 print_prop(name
, "%s", s
);
4829 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "LoadError")) {
4830 const char *a
= NULL
, *b
= NULL
;
4832 r
= sd_bus_message_read(m
, "(ss)", &a
, &b
);
4834 return bus_log_parse_error(r
);
4836 if (arg_all
|| !isempty(a
) || !isempty(b
))
4837 print_prop(name
, "%s \"%s\"", strempty(a
), strempty(b
));
4840 } else if (streq_ptr(name
, "SystemCallFilter")) {
4841 _cleanup_strv_free_
char **l
= NULL
;
4844 r
= sd_bus_message_enter_container(m
, 'r', "bas");
4846 return bus_log_parse_error(r
);
4848 r
= sd_bus_message_read(m
, "b", &whitelist
);
4850 return bus_log_parse_error(r
);
4852 r
= sd_bus_message_read_strv(m
, &l
);
4854 return bus_log_parse_error(r
);
4856 r
= sd_bus_message_exit_container(m
);
4858 return bus_log_parse_error(r
);
4860 if (arg_all
|| whitelist
|| !strv_isempty(l
)) {
4865 fputs(name
, stdout
);
4872 STRV_FOREACH(i
, l
) {
4880 fputc('\n', stdout
);
4888 case SD_BUS_TYPE_ARRAY
:
4890 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "EnvironmentFiles")) {
4894 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sb)");
4896 return bus_log_parse_error(r
);
4898 while ((r
= sd_bus_message_read(m
, "(sb)", &path
, &ignore
)) > 0)
4899 print_prop("EnvironmentFile", "%s (ignore_errors=%s)", path
, yes_no(ignore
));
4902 return bus_log_parse_error(r
);
4904 r
= sd_bus_message_exit_container(m
);
4906 return bus_log_parse_error(r
);
4910 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Paths")) {
4911 const char *type
, *path
;
4913 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4915 return bus_log_parse_error(r
);
4917 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4918 print_prop(type
, "%s", path
);
4920 return bus_log_parse_error(r
);
4922 r
= sd_bus_message_exit_container(m
);
4924 return bus_log_parse_error(r
);
4928 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
4929 const char *type
, *path
;
4931 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4933 return bus_log_parse_error(r
);
4935 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4939 printf("Listen%s=%s\n", type
, path
);
4941 return bus_log_parse_error(r
);
4943 r
= sd_bus_message_exit_container(m
);
4945 return bus_log_parse_error(r
);
4949 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Timers")) {
4951 uint64_t value
, next_elapse
;
4953 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(stt)");
4955 return bus_log_parse_error(r
);
4957 while ((r
= sd_bus_message_read(m
, "(stt)", &base
, &value
, &next_elapse
)) > 0) {
4958 char timespan1
[FORMAT_TIMESPAN_MAX
], timespan2
[FORMAT_TIMESPAN_MAX
];
4960 print_prop(base
, "{ value=%s ; next_elapse=%s }",
4961 format_timespan(timespan1
, sizeof(timespan1
), value
, 0),
4962 format_timespan(timespan2
, sizeof(timespan2
), next_elapse
, 0));
4965 return bus_log_parse_error(r
);
4967 r
= sd_bus_message_exit_container(m
);
4969 return bus_log_parse_error(r
);
4973 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
4974 ExecStatusInfo info
= {};
4976 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4978 return bus_log_parse_error(r
);
4980 while ((r
= exec_status_info_deserialize(m
, &info
)) > 0) {
4981 char timestamp1
[FORMAT_TIMESTAMP_MAX
], timestamp2
[FORMAT_TIMESTAMP_MAX
];
4982 _cleanup_free_
char *tt
;
4984 tt
= strv_join(info
.argv
, " ");
4987 "{ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT
" ; code=%s ; status=%i%s%s }",
4990 yes_no(info
.ignore
),
4991 strna(format_timestamp(timestamp1
, sizeof(timestamp1
), info
.start_timestamp
)),
4992 strna(format_timestamp(timestamp2
, sizeof(timestamp2
), info
.exit_timestamp
)),
4994 sigchld_code_to_string(info
.code
),
4996 info
.code
== CLD_EXITED
? "" : "/",
4997 strempty(info
.code
== CLD_EXITED
? NULL
: signal_to_string(info
.status
)));
5000 strv_free(info
.argv
);
5004 r
= sd_bus_message_exit_container(m
);
5006 return bus_log_parse_error(r
);
5010 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "DeviceAllow")) {
5011 const char *path
, *rwm
;
5013 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
5015 return bus_log_parse_error(r
);
5017 while ((r
= sd_bus_message_read(m
, "(ss)", &path
, &rwm
)) > 0)
5018 print_prop(name
, "%s %s", strna(path
), strna(rwm
));
5020 return bus_log_parse_error(r
);
5022 r
= sd_bus_message_exit_container(m
);
5024 return bus_log_parse_error(r
);
5028 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&&
5029 STR_IN_SET(name
, "IODeviceWeight", "BlockIODeviceWeight")) {
5033 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
5035 return bus_log_parse_error(r
);
5037 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &weight
)) > 0)
5038 print_prop(name
, "%s %"PRIu64
, strna(path
), weight
);
5040 return bus_log_parse_error(r
);
5042 r
= sd_bus_message_exit_container(m
);
5044 return bus_log_parse_error(r
);
5048 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&&
5049 (cgroup_io_limit_type_from_string(name
) >= 0 ||
5050 STR_IN_SET(name
, "BlockIOReadBandwidth", "BlockIOWriteBandwidth"))) {
5054 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
5056 return bus_log_parse_error(r
);
5058 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &bandwidth
)) > 0)
5059 print_prop(name
, "%s %"PRIu64
, strna(path
), bandwidth
);
5061 return bus_log_parse_error(r
);
5063 r
= sd_bus_message_exit_container(m
);
5065 return bus_log_parse_error(r
);
5069 } else if (contents
[1] == SD_BUS_TYPE_BYTE
&& streq(name
, "StandardInputData")) {
5070 _cleanup_free_
char *h
= NULL
;
5075 r
= sd_bus_message_read_array(m
, 'y', &p
, &sz
);
5077 return bus_log_parse_error(r
);
5079 n
= base64mem(p
, sz
, &h
);
5083 print_prop(name
, "%s", h
);
5091 r
= bus_print_property(name
, m
, arg_value
, arg_all
);
5093 return bus_log_parse_error(r
);
5096 r
= sd_bus_message_skip(m
, contents
);
5098 return bus_log_parse_error(r
);
5101 printf("%s=[unprintable]\n", name
);
5107 static int show_one(
5112 bool show_properties
,
5116 static const struct bus_properties_map property_map
[] = {
5117 { "LoadState", "s", map_string_no_copy
, offsetof(UnitStatusInfo
, load_state
) },
5118 { "ActiveState", "s", map_string_no_copy
, offsetof(UnitStatusInfo
, active_state
) },
5122 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5123 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5124 _cleanup_set_free_ Set
*found_properties
= NULL
;
5125 _cleanup_(unit_status_info_free
) UnitStatusInfo info
= {
5126 .memory_current
= (uint64_t) -1,
5127 .memory_high
= CGROUP_LIMIT_MAX
,
5128 .memory_max
= CGROUP_LIMIT_MAX
,
5129 .memory_swap_max
= CGROUP_LIMIT_MAX
,
5130 .memory_limit
= (uint64_t) -1,
5131 .cpu_usage_nsec
= (uint64_t) -1,
5132 .tasks_current
= (uint64_t) -1,
5133 .tasks_max
= (uint64_t) -1,
5134 .ip_ingress_bytes
= (uint64_t) -1,
5135 .ip_egress_bytes
= (uint64_t) -1,
5142 log_debug("Showing one %s", path
);
5144 r
= sd_bus_call_method(
5146 "org.freedesktop.systemd1",
5148 "org.freedesktop.DBus.Properties",
5154 return log_error_errno(r
, "Failed to get properties: %s", bus_error_message(&error
, r
));
5157 r
= bus_message_map_all_properties(reply
, property_map
, &error
, &info
);
5159 return log_error_errno(r
, "Failed to map properties: %s", bus_error_message(&error
, r
));
5161 if (streq_ptr(info
.load_state
, "not-found") && streq_ptr(info
.active_state
, "inactive")) {
5162 log_full(streq(verb
, "status") ? LOG_ERR
: LOG_DEBUG
,
5163 "Unit %s could not be found.", unit
);
5165 if (streq(verb
, "status"))
5166 return EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN
;
5168 if (!streq(verb
, "show"))
5172 r
= sd_bus_message_rewind(reply
, true);
5174 return log_error_errno(r
, "Failed to rewind: %s", bus_error_message(&error
, r
));
5177 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
5179 return bus_log_parse_error(r
);
5186 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
5187 const char *name
, *contents
;
5189 r
= sd_bus_message_read(reply
, "s", &name
);
5191 return bus_log_parse_error(r
);
5193 r
= sd_bus_message_peek_type(reply
, NULL
, &contents
);
5195 return bus_log_parse_error(r
);
5197 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, contents
);
5199 return bus_log_parse_error(r
);
5201 if (show_properties
) {
5202 r
= set_ensure_allocated(&found_properties
, &string_hash_ops
);
5206 r
= set_put(found_properties
, name
);
5207 if (r
< 0 && r
!= EEXIST
)
5210 r
= print_property(name
, reply
, contents
);
5212 r
= status_property(name
, reply
, &info
, contents
);
5216 r
= sd_bus_message_exit_container(reply
);
5218 return bus_log_parse_error(r
);
5220 r
= sd_bus_message_exit_container(reply
);
5222 return bus_log_parse_error(r
);
5225 return bus_log_parse_error(r
);
5227 r
= sd_bus_message_exit_container(reply
);
5229 return bus_log_parse_error(r
);
5232 if (show_properties
) {
5235 STRV_FOREACH(pp
, arg_properties
)
5236 if (!set_contains(found_properties
, *pp
))
5237 log_debug("Property %s does not exist.", *pp
);
5239 } else if (streq(verb
, "help"))
5240 show_unit_help(&info
);
5241 else if (streq(verb
, "status")) {
5242 print_status_info(bus
, &info
, ellipsized
);
5244 if (info
.active_state
&& !STR_IN_SET(info
.active_state
, "active", "reloading"))
5245 r
= EXIT_PROGRAM_NOT_RUNNING
;
5247 r
= EXIT_PROGRAM_RUNNING_OR_SERVICE_OK
;
5253 static int get_unit_dbus_path_by_pid(
5258 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5259 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5263 r
= sd_bus_call_method(
5265 "org.freedesktop.systemd1",
5266 "/org/freedesktop/systemd1",
5267 "org.freedesktop.systemd1.Manager",
5273 return log_error_errno(r
, "Failed to get unit for PID %"PRIu32
": %s", pid
, bus_error_message(&error
, r
));
5275 r
= sd_bus_message_read(reply
, "o", &u
);
5277 return bus_log_parse_error(r
);
5287 static int show_all(
5290 bool show_properties
,
5294 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5295 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
5300 r
= get_unit_list(bus
, NULL
, NULL
, &unit_infos
, 0, &reply
);
5304 pager_open(arg_no_pager
, false);
5308 qsort_safe(unit_infos
, c
, sizeof(UnitInfo
), compare_unit_info
);
5310 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
5311 _cleanup_free_
char *p
= NULL
;
5313 p
= unit_dbus_path_from_name(u
->id
);
5317 r
= show_one(verb
, bus
, p
, u
->id
, show_properties
, new_line
, ellipsized
);
5320 else if (r
> 0 && ret
== 0)
5327 static int show_system_status(sd_bus
*bus
) {
5328 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], since2
[FORMAT_TIMESTAMP_MAX
];
5329 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5330 _cleanup_(machine_info_clear
) struct machine_info mi
= {};
5331 _cleanup_free_
char *hn
= NULL
;
5332 const char *on
, *off
;
5335 hn
= gethostname_malloc();
5339 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, &error
, &mi
);
5341 return log_error_errno(r
, "Failed to read server status: %s", bus_error_message(&error
, r
));
5343 if (streq_ptr(mi
.state
, "degraded")) {
5344 on
= ansi_highlight_red();
5345 off
= ansi_normal();
5346 } else if (streq_ptr(mi
.state
, "running")) {
5347 on
= ansi_highlight_green();
5348 off
= ansi_normal();
5350 on
= ansi_highlight_yellow();
5351 off
= ansi_normal();
5354 printf("%s%s%s %s\n", on
, special_glyph(BLACK_CIRCLE
), off
, arg_host
? arg_host
: hn
);
5356 printf(" State: %s%s%s\n",
5357 on
, strna(mi
.state
), off
);
5359 printf(" Jobs: %" PRIu32
" queued\n", mi
.n_jobs
);
5360 printf(" Failed: %" PRIu32
" units\n", mi
.n_failed_units
);
5362 printf(" Since: %s; %s\n",
5363 format_timestamp(since2
, sizeof(since2
), mi
.timestamp
),
5364 format_timestamp_relative(since1
, sizeof(since1
), mi
.timestamp
));
5366 printf(" CGroup: %s\n", mi
.control_group
?: "/");
5367 if (IN_SET(arg_transport
,
5368 BUS_TRANSPORT_LOCAL
,
5369 BUS_TRANSPORT_MACHINE
)) {
5370 static const char prefix
[] = " ";
5374 if (c
> sizeof(prefix
) - 1)
5375 c
-= sizeof(prefix
) - 1;
5379 show_cgroup(SYSTEMD_CGROUP_CONTROLLER
, strempty(mi
.control_group
), prefix
, c
, get_output_flags());
5385 static int show(int argc
, char *argv
[], void *userdata
) {
5386 bool show_properties
, show_status
, show_help
, new_line
= false;
5387 bool ellipsized
= false;
5393 show_properties
= streq(argv
[0], "show");
5394 show_status
= streq(argv
[0], "status");
5395 show_help
= streq(argv
[0], "help");
5397 if (show_help
&& argc
<= 1) {
5398 log_error("This command expects one or more unit names. Did you mean --help?");
5402 r
= acquire_bus(BUS_MANAGER
, &bus
);
5406 pager_open(arg_no_pager
, false);
5409 /* Increase max number of open files to 16K if we can, we
5410 * might needs this when browsing journal files, which might
5411 * be split up into many files. */
5412 setrlimit_closest(RLIMIT_NOFILE
, &RLIMIT_MAKE_CONST(16384));
5414 /* If no argument is specified inspect the manager itself */
5415 if (show_properties
&& argc
<= 1)
5416 return show_one(argv
[0], bus
, "/org/freedesktop/systemd1", NULL
, show_properties
, &new_line
, &ellipsized
);
5418 if (show_status
&& argc
<= 1) {
5420 show_system_status(bus
);
5424 ret
= show_all(argv
[0], bus
, false, &new_line
, &ellipsized
);
5426 _cleanup_free_
char **patterns
= NULL
;
5429 STRV_FOREACH(name
, strv_skip(argv
, 1)) {
5430 _cleanup_free_
char *path
= NULL
, *unit
= NULL
;
5433 if (safe_atou32(*name
, &id
) < 0) {
5434 if (strv_push(&patterns
, *name
) < 0)
5438 } else if (show_properties
) {
5439 /* Interpret as job id */
5440 if (asprintf(&path
, "/org/freedesktop/systemd1/job/%u", id
) < 0)
5444 /* Interpret as PID */
5445 r
= get_unit_dbus_path_by_pid(bus
, id
, &path
);
5451 r
= unit_name_from_dbus_path(path
, &unit
);
5456 r
= show_one(argv
[0], bus
, path
, unit
, show_properties
, &new_line
, &ellipsized
);
5459 else if (r
> 0 && ret
== 0)
5463 if (!strv_isempty(patterns
)) {
5464 _cleanup_strv_free_
char **names
= NULL
;
5466 r
= expand_names(bus
, patterns
, NULL
, &names
);
5468 return log_error_errno(r
, "Failed to expand names: %m");
5470 STRV_FOREACH(name
, names
) {
5471 _cleanup_free_
char *path
;
5473 path
= unit_dbus_path_from_name(*name
);
5477 r
= show_one(argv
[0], bus
, path
, *name
, show_properties
, &new_line
, &ellipsized
);
5480 if (r
> 0 && ret
== 0)
5486 if (ellipsized
&& !arg_quiet
)
5487 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
5492 static int cat_file(const char *filename
, bool newline
) {
5493 _cleanup_close_
int fd
;
5495 fd
= open(filename
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
5499 printf("%s%s# %s%s\n",
5500 newline
? "\n" : "",
5501 ansi_highlight_blue(),
5506 return copy_bytes(fd
, STDOUT_FILENO
, (uint64_t) -1, 0);
5509 static int cat(int argc
, char *argv
[], void *userdata
) {
5510 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
5511 _cleanup_strv_free_
char **names
= NULL
;
5517 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
5518 log_error("Cannot remotely cat units.");
5522 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
5524 return log_error_errno(r
, "Failed to determine unit paths: %m");
5526 r
= acquire_bus(BUS_MANAGER
, &bus
);
5530 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
5532 return log_error_errno(r
, "Failed to expand names: %m");
5534 pager_open(arg_no_pager
, false);
5536 STRV_FOREACH(name
, names
) {
5537 _cleanup_free_
char *fragment_path
= NULL
;
5538 _cleanup_strv_free_
char **dropin_paths
= NULL
;
5541 r
= unit_find_paths(bus
, *name
, &lp
, &fragment_path
, &dropin_paths
);
5552 if (need_daemon_reload(bus
, *name
) > 0) /* ignore errors (<0), this is informational output */
5554 "%s# Warning: %s changed on disk, the version systemd has loaded is outdated.\n"
5555 "%s# This output shows the current version of the unit's original fragment and drop-in files.\n"
5556 "%s# If fragments or drop-ins were added or removed, they are not properly reflected in this output.\n"
5557 "%s# Run 'systemctl%s daemon-reload' to reload units.%s\n",
5558 ansi_highlight_red(),
5560 ansi_highlight_red(),
5561 ansi_highlight_red(),
5562 ansi_highlight_red(),
5563 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user",
5566 if (fragment_path
) {
5567 r
= cat_file(fragment_path
, false);
5569 return log_warning_errno(r
, "Failed to cat %s: %m", fragment_path
);
5572 STRV_FOREACH(path
, dropin_paths
) {
5573 r
= cat_file(*path
, path
== dropin_paths
);
5575 return log_warning_errno(r
, "Failed to cat %s: %m", *path
);
5582 static int set_property(int argc
, char *argv
[], void *userdata
) {
5583 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5584 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5585 _cleanup_free_
char *n
= NULL
;
5589 r
= acquire_bus(BUS_MANAGER
, &bus
);
5593 polkit_agent_open_maybe();
5595 r
= sd_bus_message_new_method_call(
5598 "org.freedesktop.systemd1",
5599 "/org/freedesktop/systemd1",
5600 "org.freedesktop.systemd1.Manager",
5601 "SetUnitProperties");
5603 return bus_log_create_error(r
);
5605 r
= unit_name_mangle(argv
[1], UNIT_NAME_NOGLOB
, &n
);
5607 return log_error_errno(r
, "Failed to mangle unit name: %m");
5609 r
= sd_bus_message_append(m
, "sb", n
, arg_runtime
);
5611 return bus_log_create_error(r
);
5613 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, "(sv)");
5615 return bus_log_create_error(r
);
5617 r
= bus_append_unit_property_assignment_many(m
, strv_skip(argv
, 2));
5621 r
= sd_bus_message_close_container(m
);
5623 return bus_log_create_error(r
);
5625 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5627 return log_error_errno(r
, "Failed to set unit properties on %s: %s", n
, bus_error_message(&error
, r
));
5632 static int daemon_reload(int argc
, char *argv
[], void *userdata
) {
5633 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5634 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5639 r
= acquire_bus(BUS_MANAGER
, &bus
);
5643 polkit_agent_open_maybe();
5645 switch (arg_action
) {
5652 method
= "Reexecute";
5655 case ACTION_SYSTEMCTL
:
5656 method
= streq(argv
[0], "daemon-reexec") ? "Reexecute" :
5657 /* "daemon-reload" */ "Reload";
5661 assert_not_reached("Unexpected action");
5664 r
= sd_bus_message_new_method_call(
5667 "org.freedesktop.systemd1",
5668 "/org/freedesktop/systemd1",
5669 "org.freedesktop.systemd1.Manager",
5672 return bus_log_create_error(r
);
5674 /* Note we use an extra-long timeout here. This is because a reload or reexec means generators are rerun which
5675 * are timed out after DEFAULT_TIMEOUT_USEC. Let's use twice that time here, so that the generators can have
5676 * their timeout, and for everything else there's the same time budget in place. */
5678 r
= sd_bus_call(bus
, m
, DEFAULT_TIMEOUT_USEC
* 2, &error
, NULL
);
5680 /* On reexecution, we expect a disconnect, not a reply */
5681 if (IN_SET(r
, -ETIMEDOUT
, -ECONNRESET
) && streq(method
, "Reexecute"))
5684 if (r
< 0 && arg_action
== ACTION_SYSTEMCTL
)
5685 return log_error_errno(r
, "Failed to reload daemon: %s", bus_error_message(&error
, r
));
5687 /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
5688 * old ways of doing things, hence don't log any error in that case here. */
5690 return r
< 0 ? r
: 0;
5693 static int trivial_method(int argc
, char *argv
[], void *userdata
) {
5694 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5702 r
= acquire_bus(BUS_MANAGER
, &bus
);
5706 polkit_agent_open_maybe();
5709 streq(argv
[0], "clear-jobs") ||
5710 streq(argv
[0], "cancel") ? "ClearJobs" :
5711 streq(argv
[0], "reset-failed") ? "ResetFailed" :
5712 streq(argv
[0], "halt") ? "Halt" :
5713 streq(argv
[0], "reboot") ? "Reboot" :
5714 streq(argv
[0], "kexec") ? "KExec" :
5715 streq(argv
[0], "exit") ? "Exit" :
5716 /* poweroff */ "PowerOff";
5718 r
= sd_bus_call_method(
5720 "org.freedesktop.systemd1",
5721 "/org/freedesktop/systemd1",
5722 "org.freedesktop.systemd1.Manager",
5727 if (r
< 0 && arg_action
== ACTION_SYSTEMCTL
)
5728 return log_error_errno(r
, "Failed to execute operation: %s", bus_error_message(&error
, r
));
5730 /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
5731 * old ways of doing things, hence don't log any error in that case here. */
5733 return r
< 0 ? r
: 0;
5736 static int reset_failed(int argc
, char *argv
[], void *userdata
) {
5737 _cleanup_strv_free_
char **names
= NULL
;
5743 return trivial_method(argc
, argv
, userdata
);
5745 r
= acquire_bus(BUS_MANAGER
, &bus
);
5749 polkit_agent_open_maybe();
5751 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
5753 return log_error_errno(r
, "Failed to expand names: %m");
5755 STRV_FOREACH(name
, names
) {
5756 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5758 q
= sd_bus_call_method(
5760 "org.freedesktop.systemd1",
5761 "/org/freedesktop/systemd1",
5762 "org.freedesktop.systemd1.Manager",
5768 log_error_errno(q
, "Failed to reset failed state of unit %s: %s", *name
, bus_error_message(&error
, q
));
5777 static int print_variable(const char *s
) {
5779 _cleanup_free_
char *esc
= NULL
;
5781 sep
= strchr(s
, '=');
5783 log_error("Invalid environment block");
5787 esc
= shell_maybe_quote(sep
+ 1, ESCAPE_POSIX
);
5791 printf("%.*s=%s\n", (int)(sep
-s
), s
, esc
);
5795 static int show_environment(int argc
, char *argv
[], void *userdata
) {
5796 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5797 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5802 r
= acquire_bus(BUS_MANAGER
, &bus
);
5806 pager_open(arg_no_pager
, false);
5808 r
= sd_bus_get_property(
5810 "org.freedesktop.systemd1",
5811 "/org/freedesktop/systemd1",
5812 "org.freedesktop.systemd1.Manager",
5818 return log_error_errno(r
, "Failed to get environment: %s", bus_error_message(&error
, r
));
5820 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
5822 return bus_log_parse_error(r
);
5824 while ((r
= sd_bus_message_read_basic(reply
, SD_BUS_TYPE_STRING
, &text
)) > 0) {
5825 r
= print_variable(text
);
5830 return bus_log_parse_error(r
);
5832 r
= sd_bus_message_exit_container(reply
);
5834 return bus_log_parse_error(r
);
5839 static int switch_root(int argc
, char *argv
[], void *userdata
) {
5840 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5841 _cleanup_free_
char *cmdline_init
= NULL
;
5842 const char *root
, *init
;
5846 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
5847 log_error("Cannot switch root remotely.");
5851 if (argc
< 2 || argc
> 3) {
5852 log_error("Wrong number of arguments.");
5861 r
= parse_env_file("/proc/cmdline", WHITESPACE
,
5862 "init", &cmdline_init
,
5865 log_debug_errno(r
, "Failed to parse /proc/cmdline: %m");
5867 init
= cmdline_init
;
5870 init
= empty_to_null(init
);
5872 const char *root_systemd_path
= NULL
, *root_init_path
= NULL
;
5874 root_systemd_path
= strjoina(root
, "/" SYSTEMD_BINARY_PATH
);
5875 root_init_path
= strjoina(root
, "/", init
);
5877 /* If the passed init is actually the same as the
5878 * systemd binary, then let's suppress it. */
5879 if (files_same(root_init_path
, root_systemd_path
, 0) > 0)
5883 /* Instruct PID1 to exclude us from its killing spree applied during
5884 * the transition. Otherwise we would exit with a failure status even
5885 * though the switch to the new root has succeed. */
5886 argv_cmdline
[0] = '@';
5888 r
= acquire_bus(BUS_MANAGER
, &bus
);
5892 /* If we are slow to exit after the root switch, the new systemd instance
5893 * will send us a signal to terminate. Just ignore it and exit normally.
5894 * This way the unit does not end up as failed.
5896 r
= ignore_signals(SIGTERM
, -1);
5898 log_warning_errno(r
, "Failed to change disposition of SIGTERM to ignore: %m");
5900 log_debug("Switching root - root: %s; init: %s", root
, strna(init
));
5902 r
= sd_bus_call_method(
5904 "org.freedesktop.systemd1",
5905 "/org/freedesktop/systemd1",
5906 "org.freedesktop.systemd1.Manager",
5912 (void) default_signals(SIGTERM
, -1);
5914 return log_error_errno(r
, "Failed to switch root: %s", bus_error_message(&error
, r
));
5920 static int set_environment(int argc
, char *argv
[], void *userdata
) {
5921 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5922 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5930 r
= acquire_bus(BUS_MANAGER
, &bus
);
5934 polkit_agent_open_maybe();
5936 method
= streq(argv
[0], "set-environment")
5938 : "UnsetEnvironment";
5940 r
= sd_bus_message_new_method_call(
5943 "org.freedesktop.systemd1",
5944 "/org/freedesktop/systemd1",
5945 "org.freedesktop.systemd1.Manager",
5948 return bus_log_create_error(r
);
5950 r
= sd_bus_message_append_strv(m
, strv_skip(argv
, 1));
5952 return bus_log_create_error(r
);
5954 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5956 return log_error_errno(r
, "Failed to set environment: %s", bus_error_message(&error
, r
));
5961 static int import_environment(int argc
, char *argv
[], void *userdata
) {
5962 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5963 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5967 r
= acquire_bus(BUS_MANAGER
, &bus
);
5971 polkit_agent_open_maybe();
5973 r
= sd_bus_message_new_method_call(
5976 "org.freedesktop.systemd1",
5977 "/org/freedesktop/systemd1",
5978 "org.freedesktop.systemd1.Manager",
5981 return bus_log_create_error(r
);
5984 r
= sd_bus_message_append_strv(m
, environ
);
5988 r
= sd_bus_message_open_container(m
, 'a', "s");
5990 return bus_log_create_error(r
);
5992 STRV_FOREACH(a
, strv_skip(argv
, 1)) {
5994 if (!env_name_is_valid(*a
)) {
5995 log_error("Not a valid environment variable name: %s", *a
);
5999 STRV_FOREACH(b
, environ
) {
6002 eq
= startswith(*b
, *a
);
6003 if (eq
&& *eq
== '=') {
6005 r
= sd_bus_message_append(m
, "s", *b
);
6007 return bus_log_create_error(r
);
6014 r
= sd_bus_message_close_container(m
);
6017 return bus_log_create_error(r
);
6019 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
6021 return log_error_errno(r
, "Failed to import environment: %s", bus_error_message(&error
, r
));
6026 static int enable_sysv_units(const char *verb
, char **args
) {
6029 #if HAVE_SYSV_COMPAT
6030 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
6033 /* Processes all SysV units, and reshuffles the array so that afterwards only the native units remain */
6035 if (arg_scope
!= UNIT_FILE_SYSTEM
)
6038 if (getenv_bool("SYSTEMCTL_SKIP_SYSV") > 0)
6041 if (!STR_IN_SET(verb
,
6047 r
= lookup_paths_init(&paths
, arg_scope
, LOOKUP_PATHS_EXCLUDE_GENERATED
, arg_root
);
6054 const char *argv
[] = {
6055 ROOTLIBEXECDIR
"/systemd-sysv-install",
6062 _cleanup_free_
char *p
= NULL
, *q
= NULL
, *l
= NULL
;
6063 bool found_native
= false, found_sysv
;
6072 if (!endswith(name
, ".service"))
6075 if (path_is_absolute(name
))
6078 j
= unit_file_exists(arg_scope
, &paths
, name
);
6079 if (j
< 0 && !IN_SET(j
, -ELOOP
, -ERFKILL
, -EADDRNOTAVAIL
))
6080 return log_error_errno(j
, "Failed to lookup unit file state: %m");
6081 found_native
= j
!= 0;
6083 /* If we have both a native unit and a SysV script, enable/disable them both (below); for is-enabled,
6084 * prefer the native unit */
6085 if (found_native
&& streq(verb
, "is-enabled"))
6088 p
= path_join(arg_root
, SYSTEM_SYSVINIT_PATH
, name
);
6092 p
[strlen(p
) - strlen(".service")] = 0;
6093 found_sysv
= access(p
, F_OK
) >= 0;
6099 log_info("Synchronizing state of %s with SysV service script with %s.", name
, argv
[0]);
6101 log_info("%s is not a native service, redirecting to systemd-sysv-install.", name
);
6104 if (!isempty(arg_root
))
6105 argv
[c
++] = q
= strappend("--root=", arg_root
);
6108 argv
[c
++] = basename(p
);
6111 l
= strv_join((char**)argv
, " ");
6116 log_info("Executing: %s", l
);
6120 return log_error_errno(errno
, "Failed to fork: %m");
6121 else if (pid
== 0) {
6124 (void) reset_all_signal_handlers();
6125 (void) reset_signal_mask();
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
) {
6997 return log_error_errno(errno
, "Failed to fork: %m");
7001 char *editor
, **editor_args
= NULL
;
7002 char **tmp_path
, **original_path
, *p
;
7003 unsigned n_editor_args
= 0, i
= 1;
7006 (void) reset_all_signal_handlers();
7007 (void) reset_signal_mask();
7009 argc
= strv_length(paths
)/2 + 1;
7011 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
7012 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
7013 * we try to execute well known editors
7015 editor
= getenv("SYSTEMD_EDITOR");
7017 editor
= getenv("EDITOR");
7019 editor
= getenv("VISUAL");
7021 if (!isempty(editor
)) {
7022 editor_args
= strv_split(editor
, WHITESPACE
);
7025 _exit(EXIT_FAILURE
);
7027 n_editor_args
= strv_length(editor_args
);
7028 argc
+= n_editor_args
- 1;
7030 args
= newa(const char*, argc
+ 1);
7032 if (n_editor_args
> 0) {
7033 args
[0] = editor_args
[0];
7034 for (; i
< n_editor_args
; i
++)
7035 args
[i
] = editor_args
[i
];
7038 STRV_FOREACH_PAIR(original_path
, tmp_path
, paths
) {
7039 args
[i
] = *tmp_path
;
7044 if (n_editor_args
> 0)
7045 execvp(args
[0], (char* const*) args
);
7047 FOREACH_STRING(p
, "editor", "nano", "vim", "vi") {
7049 execvp(p
, (char* const*) args
);
7050 /* We do not fail if the editor doesn't exist
7051 * because we want to try each one of them before
7054 if (errno
!= ENOENT
) {
7055 log_error_errno(errno
, "Failed to execute %s: %m", editor
);
7056 _exit(EXIT_FAILURE
);
7060 log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR, $EDITOR or $VISUAL.");
7061 _exit(EXIT_FAILURE
);
7064 r
= wait_for_terminate_and_warn("editor", pid
, true);
7066 return log_error_errno(r
, "Failed to wait for child: %m");
7071 static int find_paths_to_edit(sd_bus
*bus
, char **names
, char ***paths
) {
7072 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
7079 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
7083 STRV_FOREACH(name
, names
) {
7084 _cleanup_free_
char *path
= NULL
, *new_path
= NULL
, *tmp_path
= NULL
, *tmp_name
= NULL
;
7085 const char *unit_name
;
7087 r
= unit_find_paths(bus
, *name
, &lp
, &path
, NULL
);
7095 log_error("Run 'systemctl edit%s --force %s' to create a new unit.",
7096 arg_scope
== UNIT_FILE_GLOBAL
? " --global" :
7097 arg_scope
== UNIT_FILE_USER
? " --user" : "",
7102 /* Create a new unit from scratch */
7104 r
= unit_file_create_new(&lp
, unit_name
,
7105 arg_full
? NULL
: ".d/override.conf",
7106 &new_path
, &tmp_path
);
7110 unit_name
= basename(path
);
7111 /* We follow unit aliases, but we need to propagate the instance */
7112 if (unit_name_is_valid(*name
, UNIT_NAME_INSTANCE
) &&
7113 unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
7114 _cleanup_free_
char *instance
= NULL
;
7116 r
= unit_name_to_instance(*name
, &instance
);
7120 r
= unit_name_replace_instance(unit_name
, instance
, &tmp_name
);
7124 unit_name
= tmp_name
;
7128 r
= unit_file_create_copy(&lp
, unit_name
, path
, &new_path
, &tmp_path
);
7130 r
= unit_file_create_new(&lp
, unit_name
, ".d/override.conf", &new_path
, &tmp_path
);
7135 r
= strv_push_pair(paths
, new_path
, tmp_path
);
7138 new_path
= tmp_path
= NULL
;
7144 static int edit(int argc
, char *argv
[], void *userdata
) {
7145 _cleanup_strv_free_
char **names
= NULL
;
7146 _cleanup_strv_free_
char **paths
= NULL
;
7147 char **original
, **tmp
;
7152 log_error("Cannot edit units if not on a tty.");
7156 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
7157 log_error("Cannot edit units remotely.");
7161 r
= acquire_bus(BUS_MANAGER
, &bus
);
7165 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
7167 return log_error_errno(r
, "Failed to expand names: %m");
7169 r
= find_paths_to_edit(bus
, names
, &paths
);
7173 if (strv_isempty(paths
))
7176 r
= run_editor(paths
);
7180 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
7181 /* If the temporary file is empty we ignore it. It's
7182 * useful if the user wants to cancel its modification
7184 if (null_or_empty_path(*tmp
)) {
7185 log_warning("Editing \"%s\" canceled: temporary file is empty.", *original
);
7189 r
= rename(*tmp
, *original
);
7191 r
= log_error_errno(errno
, "Failed to rename \"%s\" to \"%s\": %m", *tmp
, *original
);
7198 if (!arg_no_reload
&& !install_client_side())
7199 r
= daemon_reload(argc
, argv
, userdata
);
7202 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
7203 (void) unlink(*tmp
);
7205 /* Removing empty dropin dirs */
7207 _cleanup_free_
char *dir
;
7209 dir
= dirname_malloc(*original
);
7213 /* no need to check if the dir is empty, rmdir
7214 * does nothing if it is not the case.
7223 static void systemctl_help(void) {
7225 pager_open(arg_no_pager
, false);
7227 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
7228 "Query or send control commands to the systemd manager.\n\n"
7229 " -h --help Show this help\n"
7230 " --version Show package version\n"
7231 " --system Connect to system manager\n"
7232 " --user Connect to user service manager\n"
7233 " -H --host=[USER@]HOST\n"
7234 " Operate on remote host\n"
7235 " -M --machine=CONTAINER\n"
7236 " Operate on local container\n"
7237 " -t --type=TYPE List units of a particular type\n"
7238 " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n"
7239 " -p --property=NAME Show only properties by this name\n"
7240 " -a --all Show all properties/all units currently in memory,\n"
7241 " including dead/empty ones. To list all units installed on\n"
7242 " the system, use the 'list-unit-files' command instead.\n"
7243 " --failed Same as --state=failed\n"
7244 " -l --full Don't ellipsize unit names on output\n"
7245 " -r --recursive Show unit list of host and local containers\n"
7246 " --reverse Show reverse dependencies with 'list-dependencies'\n"
7247 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
7248 " queueing a new job\n"
7249 " --show-types When showing sockets, explicitly show their type\n"
7250 " --value When showing properties, only print the value\n"
7251 " -i --ignore-inhibitors\n"
7252 " When shutting down or sleeping, ignore inhibitors\n"
7253 " --kill-who=WHO Who to send signal to\n"
7254 " -s --signal=SIGNAL Which signal to send\n"
7255 " --now Start or stop unit in addition to enabling or disabling it\n"
7256 " --dry-run Only print what would be done\n"
7257 " -q --quiet Suppress output\n"
7258 " --wait For (re)start, wait until service stopped again\n"
7259 " --no-block Do not wait until operation finished\n"
7260 " --no-wall Don't send wall message before halt/power-off/reboot\n"
7261 " --no-reload Don't reload daemon after en-/dis-abling unit files\n"
7262 " --no-legend Do not print a legend (column headers and hints)\n"
7263 " --no-pager Do not pipe output into a pager\n"
7264 " --no-ask-password\n"
7265 " Do not ask for system passwords\n"
7266 " --global Enable/disable/mask unit files globally\n"
7267 " --runtime Enable/disable/mask unit files temporarily until next\n"
7269 " -f --force When enabling unit files, override existing symlinks\n"
7270 " When shutting down, execute action immediately\n"
7271 " --preset-mode= Apply only enable, only disable, or all presets\n"
7272 " --root=PATH Enable/disable/mask unit files in the specified root\n"
7274 " -n --lines=INTEGER Number of journal entries to show\n"
7275 " -o --output=STRING Change journal output mode (short, short-precise,\n"
7276 " short-iso, short-iso-precise, short-full,\n"
7277 " short-monotonic, short-unix,\n"
7278 " verbose, export, json, json-pretty, json-sse, cat)\n"
7279 " --firmware-setup Tell the firmware to show the setup menu on next boot\n"
7280 " --plain Print unit dependencies as a list instead of a tree\n\n"
7282 " list-units [PATTERN...] List units currently in memory\n"
7283 " list-sockets [PATTERN...] List socket units currently in memory, ordered\n"
7285 " list-timers [PATTERN...] List timer units currently in memory, ordered\n"
7287 " start NAME... Start (activate) one or more units\n"
7288 " stop NAME... Stop (deactivate) one or more units\n"
7289 " reload NAME... Reload one or more units\n"
7290 " restart NAME... Start or restart one or more units\n"
7291 " try-restart NAME... Restart one or more units if active\n"
7292 " reload-or-restart NAME... Reload one or more units if possible,\n"
7293 " otherwise start or restart\n"
7294 " try-reload-or-restart NAME... If active, reload one or more units,\n"
7295 " if supported, otherwise restart\n"
7296 " isolate NAME Start one unit and stop all others\n"
7297 " kill NAME... Send signal to processes of a unit\n"
7298 " is-active PATTERN... Check whether units are active\n"
7299 " is-failed PATTERN... Check whether units are failed\n"
7300 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
7301 " show [PATTERN...|JOB...] Show properties of one or more\n"
7302 " units/jobs or the manager\n"
7303 " cat PATTERN... Show files and drop-ins of one or more units\n"
7304 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
7305 " help PATTERN...|PID... Show manual for one or more units\n"
7306 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
7308 " list-dependencies [NAME] Recursively show units which are required\n"
7309 " or wanted by this unit or by which this\n"
7310 " unit is required or wanted\n\n"
7311 "Unit File Commands:\n"
7312 " list-unit-files [PATTERN...] List installed unit files\n"
7313 " enable [NAME...|PATH...] Enable one or more unit files\n"
7314 " disable NAME... Disable one or more unit files\n"
7315 " reenable NAME... Reenable one or more unit files\n"
7316 " preset NAME... Enable/disable one or more unit files\n"
7317 " based on preset configuration\n"
7318 " preset-all Enable/disable all unit files based on\n"
7319 " preset configuration\n"
7320 " is-enabled NAME... Check whether unit files are enabled\n"
7321 " mask NAME... Mask one or more units\n"
7322 " unmask NAME... Unmask one or more units\n"
7323 " link PATH... Link one or more units files into\n"
7324 " the search path\n"
7325 " revert NAME... Revert one or more unit files to vendor\n"
7327 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
7328 " on specified one or more units\n"
7329 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
7330 " on specified one or more units\n"
7331 " edit NAME... Edit one or more unit files\n"
7332 " get-default Get the name of the default target\n"
7333 " set-default NAME Set the default target\n\n"
7334 "Machine Commands:\n"
7335 " list-machines [PATTERN...] List local containers and host\n\n"
7337 " list-jobs [PATTERN...] List jobs\n"
7338 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
7339 "Environment Commands:\n"
7340 " show-environment Dump environment\n"
7341 " set-environment NAME=VALUE... Set one or more environment variables\n"
7342 " unset-environment NAME... Unset one or more environment variables\n"
7343 " import-environment [NAME...] Import all or some environment variables\n\n"
7344 "Manager Lifecycle Commands:\n"
7345 " daemon-reload Reload systemd manager configuration\n"
7346 " daemon-reexec Reexecute systemd manager\n\n"
7347 "System Commands:\n"
7348 " is-system-running Check whether system is fully running\n"
7349 " default Enter system default mode\n"
7350 " rescue Enter system rescue mode\n"
7351 " emergency Enter system emergency mode\n"
7352 " halt Shut down and halt the system\n"
7353 " poweroff Shut down and power-off the system\n"
7354 " reboot [ARG] Shut down and reboot the system\n"
7355 " kexec Shut down and reboot the system with kexec\n"
7356 " exit [EXIT_CODE] Request user instance or container exit\n"
7357 " switch-root ROOT [INIT] Change to a different root file system\n"
7358 " suspend Suspend the system\n"
7359 " hibernate Hibernate the system\n"
7360 " hybrid-sleep Hibernate and suspend the system\n",
7361 program_invocation_short_name
);
7364 static void halt_help(void) {
7365 printf("%s [OPTIONS...]%s\n\n"
7366 "%s the system.\n\n"
7367 " --help Show this help\n"
7368 " --halt Halt the machine\n"
7369 " -p --poweroff Switch off the machine\n"
7370 " --reboot Reboot the machine\n"
7371 " -f --force Force immediate halt/power-off/reboot\n"
7372 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
7373 " -d --no-wtmp Don't write wtmp record\n"
7374 " --no-wall Don't send wall message before halt/power-off/reboot\n",
7375 program_invocation_short_name
,
7376 arg_action
== ACTION_REBOOT
? " [ARG]" : "",
7377 arg_action
== ACTION_REBOOT
? "Reboot" :
7378 arg_action
== ACTION_POWEROFF
? "Power off" :
7382 static void shutdown_help(void) {
7383 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
7384 "Shut down the system.\n\n"
7385 " --help Show this help\n"
7386 " -H --halt Halt the machine\n"
7387 " -P --poweroff Power-off the machine\n"
7388 " -r --reboot Reboot the machine\n"
7389 " -h Equivalent to --poweroff, overridden by --halt\n"
7390 " -k Don't halt/power-off/reboot, just send warnings\n"
7391 " --no-wall Don't send wall message before halt/power-off/reboot\n"
7392 " -c Cancel a pending shutdown\n",
7393 program_invocation_short_name
);
7396 static void telinit_help(void) {
7397 printf("%s [OPTIONS...] {COMMAND}\n\n"
7398 "Send control commands to the init daemon.\n\n"
7399 " --help Show this help\n"
7400 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
7402 " 0 Power-off the machine\n"
7403 " 6 Reboot the machine\n"
7404 " 2, 3, 4, 5 Start runlevelX.target unit\n"
7405 " 1, s, S Enter rescue mode\n"
7406 " q, Q Reload init daemon configuration\n"
7407 " u, U Reexecute init daemon\n",
7408 program_invocation_short_name
);
7411 static void runlevel_help(void) {
7412 printf("%s [OPTIONS...]\n\n"
7413 "Prints the previous and current runlevel of the init system.\n\n"
7414 " --help Show this help\n",
7415 program_invocation_short_name
);
7418 static void help_types(void) {
7422 puts("Available unit types:");
7423 for (i
= 0; i
< _UNIT_TYPE_MAX
; i
++)
7424 puts(unit_type_to_string(i
));
7427 static void help_states(void) {
7431 puts("Available unit load states:");
7432 for (i
= 0; i
< _UNIT_LOAD_STATE_MAX
; i
++)
7433 puts(unit_load_state_to_string(i
));
7436 puts("\nAvailable unit active states:");
7437 for (i
= 0; i
< _UNIT_ACTIVE_STATE_MAX
; i
++)
7438 puts(unit_active_state_to_string(i
));
7441 puts("\nAvailable automount unit substates:");
7442 for (i
= 0; i
< _AUTOMOUNT_STATE_MAX
; i
++)
7443 puts(automount_state_to_string(i
));
7446 puts("\nAvailable device unit substates:");
7447 for (i
= 0; i
< _DEVICE_STATE_MAX
; i
++)
7448 puts(device_state_to_string(i
));
7451 puts("\nAvailable mount unit substates:");
7452 for (i
= 0; i
< _MOUNT_STATE_MAX
; i
++)
7453 puts(mount_state_to_string(i
));
7456 puts("\nAvailable path unit substates:");
7457 for (i
= 0; i
< _PATH_STATE_MAX
; i
++)
7458 puts(path_state_to_string(i
));
7461 puts("\nAvailable scope unit substates:");
7462 for (i
= 0; i
< _SCOPE_STATE_MAX
; i
++)
7463 puts(scope_state_to_string(i
));
7466 puts("\nAvailable service unit substates:");
7467 for (i
= 0; i
< _SERVICE_STATE_MAX
; i
++)
7468 puts(service_state_to_string(i
));
7471 puts("\nAvailable slice unit substates:");
7472 for (i
= 0; i
< _SLICE_STATE_MAX
; i
++)
7473 puts(slice_state_to_string(i
));
7476 puts("\nAvailable socket unit substates:");
7477 for (i
= 0; i
< _SOCKET_STATE_MAX
; i
++)
7478 puts(socket_state_to_string(i
));
7481 puts("\nAvailable swap unit substates:");
7482 for (i
= 0; i
< _SWAP_STATE_MAX
; i
++)
7483 puts(swap_state_to_string(i
));
7486 puts("\nAvailable target unit substates:");
7487 for (i
= 0; i
< _TARGET_STATE_MAX
; i
++)
7488 puts(target_state_to_string(i
));
7491 puts("\nAvailable timer unit substates:");
7492 for (i
= 0; i
< _TIMER_STATE_MAX
; i
++)
7493 puts(timer_state_to_string(i
));
7496 static int systemctl_parse_argv(int argc
, char *argv
[]) {
7506 ARG_IGNORE_DEPENDENCIES
,
7519 ARG_NO_ASK_PASSWORD
,
7533 static const struct option options
[] = {
7534 { "help", no_argument
, NULL
, 'h' },
7535 { "version", no_argument
, NULL
, ARG_VERSION
},
7536 { "type", required_argument
, NULL
, 't' },
7537 { "property", required_argument
, NULL
, 'p' },
7538 { "all", no_argument
, NULL
, 'a' },
7539 { "reverse", no_argument
, NULL
, ARG_REVERSE
},
7540 { "after", no_argument
, NULL
, ARG_AFTER
},
7541 { "before", no_argument
, NULL
, ARG_BEFORE
},
7542 { "show-types", no_argument
, NULL
, ARG_SHOW_TYPES
},
7543 { "failed", no_argument
, NULL
, ARG_FAILED
}, /* compatibility only */
7544 { "full", no_argument
, NULL
, 'l' },
7545 { "job-mode", required_argument
, NULL
, ARG_JOB_MODE
},
7546 { "fail", no_argument
, NULL
, ARG_FAIL
}, /* compatibility only */
7547 { "irreversible", no_argument
, NULL
, ARG_IRREVERSIBLE
}, /* compatibility only */
7548 { "ignore-dependencies", no_argument
, NULL
, ARG_IGNORE_DEPENDENCIES
}, /* compatibility only */
7549 { "ignore-inhibitors", no_argument
, NULL
, 'i' },
7550 { "value", no_argument
, NULL
, ARG_VALUE
},
7551 { "user", no_argument
, NULL
, ARG_USER
},
7552 { "system", no_argument
, NULL
, ARG_SYSTEM
},
7553 { "global", no_argument
, NULL
, ARG_GLOBAL
},
7554 { "wait", no_argument
, NULL
, ARG_WAIT
},
7555 { "no-block", no_argument
, NULL
, ARG_NO_BLOCK
},
7556 { "no-legend", no_argument
, NULL
, ARG_NO_LEGEND
},
7557 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
7558 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7559 { "dry-run", no_argument
, NULL
, ARG_DRY_RUN
},
7560 { "quiet", no_argument
, NULL
, 'q' },
7561 { "root", required_argument
, NULL
, ARG_ROOT
},
7562 { "force", no_argument
, NULL
, ARG_FORCE
},
7563 { "no-reload", no_argument
, NULL
, ARG_NO_RELOAD
},
7564 { "kill-who", required_argument
, NULL
, ARG_KILL_WHO
},
7565 { "signal", required_argument
, NULL
, 's' },
7566 { "no-ask-password", no_argument
, NULL
, ARG_NO_ASK_PASSWORD
},
7567 { "host", required_argument
, NULL
, 'H' },
7568 { "machine", required_argument
, NULL
, 'M' },
7569 { "runtime", no_argument
, NULL
, ARG_RUNTIME
},
7570 { "lines", required_argument
, NULL
, 'n' },
7571 { "output", required_argument
, NULL
, 'o' },
7572 { "plain", no_argument
, NULL
, ARG_PLAIN
},
7573 { "state", required_argument
, NULL
, ARG_STATE
},
7574 { "recursive", no_argument
, NULL
, 'r' },
7575 { "preset-mode", required_argument
, NULL
, ARG_PRESET_MODE
},
7576 { "firmware-setup", no_argument
, NULL
, ARG_FIRMWARE_SETUP
},
7577 { "now", no_argument
, NULL
, ARG_NOW
},
7578 { "message", required_argument
, NULL
, ARG_MESSAGE
},
7588 /* we default to allowing interactive authorization only in systemctl (not in the legacy commands) */
7589 arg_ask_password
= true;
7591 while ((c
= getopt_long(argc
, argv
, "ht:p:alqfs:H:M:n:o:ir", options
, NULL
)) >= 0)
7603 if (isempty(optarg
)) {
7604 log_error("--type= requires arguments.");
7608 for (p
= optarg
;;) {
7609 _cleanup_free_
char *type
= NULL
;
7611 r
= extract_first_word(&p
, &type
, ",", 0);
7613 return log_error_errno(r
, "Failed to parse type: %s", optarg
);
7617 if (streq(type
, "help")) {
7622 if (unit_type_from_string(type
) >= 0) {
7623 if (strv_push(&arg_types
, type
) < 0)
7629 /* It's much nicer to use --state= for
7630 * load states, but let's support this
7631 * in --types= too for compatibility
7632 * with old versions */
7633 if (unit_load_state_from_string(type
) >= 0) {
7634 if (strv_push(&arg_states
, type
) < 0)
7640 log_error("Unknown unit type or load state '%s'.", type
);
7641 log_info("Use -t help to see a list of allowed values.");
7649 /* Make sure that if the empty property list
7650 was specified, we won't show any properties. */
7651 if (isempty(optarg
) && !arg_properties
) {
7652 arg_properties
= new0(char*, 1);
7653 if (!arg_properties
)
7656 for (p
= optarg
;;) {
7657 _cleanup_free_
char *prop
= NULL
;
7659 r
= extract_first_word(&p
, &prop
, ",", 0);
7661 return log_error_errno(r
, "Failed to parse property: %s", optarg
);
7665 if (strv_push(&arg_properties
, prop
) < 0)
7671 /* If the user asked for a particular
7672 * property, show it to him, even if it is
7684 arg_dependency
= DEPENDENCY_REVERSE
;
7688 arg_dependency
= DEPENDENCY_AFTER
;
7689 arg_jobs_after
= true;
7693 arg_dependency
= DEPENDENCY_BEFORE
;
7694 arg_jobs_before
= true;
7697 case ARG_SHOW_TYPES
:
7698 arg_show_types
= true;
7706 arg_job_mode
= optarg
;
7710 arg_job_mode
= "fail";
7713 case ARG_IRREVERSIBLE
:
7714 arg_job_mode
= "replace-irreversibly";
7717 case ARG_IGNORE_DEPENDENCIES
:
7718 arg_job_mode
= "ignore-dependencies";
7722 arg_scope
= UNIT_FILE_USER
;
7726 arg_scope
= UNIT_FILE_SYSTEM
;
7730 arg_scope
= UNIT_FILE_GLOBAL
;
7738 arg_no_block
= true;
7742 arg_no_legend
= true;
7746 arg_no_pager
= true;
7754 r
= parse_path_argument_and_warn(optarg
, false, &arg_root
);
7764 if (strv_extend(&arg_states
, "failed") < 0)
7786 arg_no_reload
= true;
7790 arg_kill_who
= optarg
;
7794 arg_signal
= signal_from_string_try_harder(optarg
);
7795 if (arg_signal
< 0) {
7796 log_error("Failed to parse signal string %s.", optarg
);
7801 case ARG_NO_ASK_PASSWORD
:
7802 arg_ask_password
= false;
7806 arg_transport
= BUS_TRANSPORT_REMOTE
;
7811 arg_transport
= BUS_TRANSPORT_MACHINE
;
7820 if (safe_atou(optarg
, &arg_lines
) < 0) {
7821 log_error("Failed to parse lines '%s'", optarg
);
7827 arg_output
= output_mode_from_string(optarg
);
7828 if (arg_output
< 0) {
7829 log_error("Unknown output '%s'.", optarg
);
7835 arg_ignore_inhibitors
= true;
7842 case ARG_FIRMWARE_SETUP
:
7843 arg_firmware_setup
= true;
7847 if (isempty(optarg
)) {
7848 log_error("--state= requires arguments.");
7852 for (p
= optarg
;;) {
7853 _cleanup_free_
char *s
= NULL
;
7855 r
= extract_first_word(&p
, &s
, ",", 0);
7857 return log_error_errno(r
, "Failed to parse state: %s", optarg
);
7861 if (streq(s
, "help")) {
7866 if (strv_push(&arg_states
, s
) < 0)
7875 if (geteuid() != 0) {
7876 log_error("--recursive requires root privileges.");
7880 arg_recursive
= true;
7883 case ARG_PRESET_MODE
:
7885 arg_preset_mode
= unit_file_preset_mode_from_string(optarg
);
7886 if (arg_preset_mode
< 0) {
7887 log_error("Failed to parse preset mode: %s.", optarg
);
7898 if (strv_extend(&arg_wall
, optarg
) < 0)
7906 assert_not_reached("Unhandled option");
7909 if (arg_transport
!= BUS_TRANSPORT_LOCAL
&& arg_scope
!= UNIT_FILE_SYSTEM
) {
7910 log_error("Cannot access user instance remotely.");
7914 if (arg_wait
&& arg_no_block
) {
7915 log_error("--wait may not be combined with --no-block.");
7922 static int halt_parse_argv(int argc
, char *argv
[]) {
7931 static const struct option options
[] = {
7932 { "help", no_argument
, NULL
, ARG_HELP
},
7933 { "halt", no_argument
, NULL
, ARG_HALT
},
7934 { "poweroff", no_argument
, NULL
, 'p' },
7935 { "reboot", no_argument
, NULL
, ARG_REBOOT
},
7936 { "force", no_argument
, NULL
, 'f' },
7937 { "wtmp-only", no_argument
, NULL
, 'w' },
7938 { "no-wtmp", no_argument
, NULL
, 'd' },
7939 { "no-sync", no_argument
, NULL
, 'n' },
7940 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7949 if (utmp_get_runlevel(&runlevel
, NULL
) >= 0)
7950 if (IN_SET(runlevel
, '0', '6'))
7953 while ((c
= getopt_long(argc
, argv
, "pfwdnih", options
, NULL
)) >= 0)
7961 arg_action
= ACTION_HALT
;
7965 if (arg_action
!= ACTION_REBOOT
)
7966 arg_action
= ACTION_POWEROFF
;
7970 arg_action
= ACTION_REBOOT
;
7995 /* Compatibility nops */
8002 assert_not_reached("Unhandled option");
8005 if (arg_action
== ACTION_REBOOT
&& (argc
== optind
|| argc
== optind
+ 1)) {
8006 r
= update_reboot_parameter_and_warn(argc
== optind
+ 1 ? argv
[optind
] : NULL
);
8009 } else if (optind
< argc
) {
8010 log_error("Too many arguments.");
8017 static int parse_shutdown_time_spec(const char *t
, usec_t
*_u
) {
8021 if (streq(t
, "now"))
8023 else if (!strchr(t
, ':')) {
8026 if (safe_atou64(t
, &u
) < 0)
8029 *_u
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
* u
;
8038 hour
= strtol(t
, &e
, 10);
8039 if (errno
> 0 || *e
!= ':' || hour
< 0 || hour
> 23)
8042 minute
= strtol(e
+1, &e
, 10);
8043 if (errno
> 0 || *e
!= 0 || minute
< 0 || minute
> 59)
8046 n
= now(CLOCK_REALTIME
);
8047 s
= (time_t) (n
/ USEC_PER_SEC
);
8049 assert_se(localtime_r(&s
, &tm
));
8051 tm
.tm_hour
= (int) hour
;
8052 tm
.tm_min
= (int) minute
;
8055 assert_se(s
= mktime(&tm
));
8057 *_u
= (usec_t
) s
* USEC_PER_SEC
;
8060 *_u
+= USEC_PER_DAY
;
8066 static int shutdown_parse_argv(int argc
, char *argv
[]) {
8073 static const struct option options
[] = {
8074 { "help", no_argument
, NULL
, ARG_HELP
},
8075 { "halt", no_argument
, NULL
, 'H' },
8076 { "poweroff", no_argument
, NULL
, 'P' },
8077 { "reboot", no_argument
, NULL
, 'r' },
8078 { "kexec", no_argument
, NULL
, 'K' }, /* not documented extension */
8079 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
8089 while ((c
= getopt_long(argc
, argv
, "HPrhkKat:fFc", options
, NULL
)) >= 0)
8097 arg_action
= ACTION_HALT
;
8101 arg_action
= ACTION_POWEROFF
;
8106 arg_action
= ACTION_KEXEC
;
8108 arg_action
= ACTION_REBOOT
;
8112 arg_action
= ACTION_KEXEC
;
8116 if (arg_action
!= ACTION_HALT
)
8117 arg_action
= ACTION_POWEROFF
;
8129 case 't': /* Note that we also ignore any passed argument to -t, not just the -t itself */
8132 /* Compatibility nops */
8136 arg_action
= ACTION_CANCEL_SHUTDOWN
;
8143 assert_not_reached("Unhandled option");
8146 if (argc
> optind
&& arg_action
!= ACTION_CANCEL_SHUTDOWN
) {
8147 r
= parse_shutdown_time_spec(argv
[optind
], &arg_when
);
8149 log_error("Failed to parse time specification: %s", argv
[optind
]);
8153 arg_when
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
;
8155 if (argc
> optind
&& arg_action
== ACTION_CANCEL_SHUTDOWN
)
8156 /* No time argument for shutdown cancel */
8157 wall
= argv
+ optind
;
8158 else if (argc
> optind
+ 1)
8159 /* We skip the time argument */
8160 wall
= argv
+ optind
+ 1;
8163 arg_wall
= strv_copy(wall
);
8173 static int telinit_parse_argv(int argc
, char *argv
[]) {
8180 static const struct option options
[] = {
8181 { "help", no_argument
, NULL
, ARG_HELP
},
8182 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
8186 static const struct {
8190 { '0', ACTION_POWEROFF
},
8191 { '6', ACTION_REBOOT
},
8192 { '1', ACTION_RESCUE
},
8193 { '2', ACTION_RUNLEVEL2
},
8194 { '3', ACTION_RUNLEVEL3
},
8195 { '4', ACTION_RUNLEVEL4
},
8196 { '5', ACTION_RUNLEVEL5
},
8197 { 's', ACTION_RESCUE
},
8198 { 'S', ACTION_RESCUE
},
8199 { 'q', ACTION_RELOAD
},
8200 { 'Q', ACTION_RELOAD
},
8201 { 'u', ACTION_REEXEC
},
8202 { 'U', ACTION_REEXEC
}
8211 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
8226 assert_not_reached("Unhandled option");
8229 if (optind
>= argc
) {
8230 log_error("%s: required argument missing.", program_invocation_short_name
);
8234 if (optind
+ 1 < argc
) {
8235 log_error("Too many arguments.");
8239 if (strlen(argv
[optind
]) != 1) {
8240 log_error("Expected single character argument.");
8244 for (i
= 0; i
< ELEMENTSOF(table
); i
++)
8245 if (table
[i
].from
== argv
[optind
][0])
8248 if (i
>= ELEMENTSOF(table
)) {
8249 log_error("Unknown command '%s'.", argv
[optind
]);
8253 arg_action
= table
[i
].to
;
8260 static int runlevel_parse_argv(int argc
, char *argv
[]) {
8266 static const struct option options
[] = {
8267 { "help", no_argument
, NULL
, ARG_HELP
},
8276 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
8287 assert_not_reached("Unhandled option");
8290 if (optind
< argc
) {
8291 log_error("Too many arguments.");
8298 static int parse_argv(int argc
, char *argv
[]) {
8302 if (program_invocation_short_name
) {
8304 if (strstr(program_invocation_short_name
, "halt")) {
8305 arg_action
= ACTION_HALT
;
8306 return halt_parse_argv(argc
, argv
);
8307 } else if (strstr(program_invocation_short_name
, "poweroff")) {
8308 arg_action
= ACTION_POWEROFF
;
8309 return halt_parse_argv(argc
, argv
);
8310 } else if (strstr(program_invocation_short_name
, "reboot")) {
8312 arg_action
= ACTION_KEXEC
;
8314 arg_action
= ACTION_REBOOT
;
8315 return halt_parse_argv(argc
, argv
);
8316 } else if (strstr(program_invocation_short_name
, "shutdown")) {
8317 arg_action
= ACTION_POWEROFF
;
8318 return shutdown_parse_argv(argc
, argv
);
8319 } else if (strstr(program_invocation_short_name
, "init")) {
8321 if (sd_booted() > 0) {
8322 arg_action
= _ACTION_INVALID
;
8323 return telinit_parse_argv(argc
, argv
);
8325 /* Hmm, so some other init system is
8326 * running, we need to forward this
8327 * request to it. For now we simply
8328 * guess that it is Upstart. */
8330 execv(TELINIT
, argv
);
8332 log_error("Couldn't find an alternative telinit implementation to spawn.");
8336 } else if (strstr(program_invocation_short_name
, "runlevel")) {
8337 arg_action
= ACTION_RUNLEVEL
;
8338 return runlevel_parse_argv(argc
, argv
);
8342 arg_action
= ACTION_SYSTEMCTL
;
8343 return systemctl_parse_argv(argc
, argv
);
8346 #if HAVE_SYSV_COMPAT
8347 _pure_
static int action_to_runlevel(void) {
8349 static const char table
[_ACTION_MAX
] = {
8350 [ACTION_HALT
] = '0',
8351 [ACTION_POWEROFF
] = '0',
8352 [ACTION_REBOOT
] = '6',
8353 [ACTION_RUNLEVEL2
] = '2',
8354 [ACTION_RUNLEVEL3
] = '3',
8355 [ACTION_RUNLEVEL4
] = '4',
8356 [ACTION_RUNLEVEL5
] = '5',
8357 [ACTION_RESCUE
] = '1'
8360 assert(arg_action
>= 0 && arg_action
< _ACTION_MAX
);
8362 return table
[arg_action
];
8366 static int talk_initctl(void) {
8367 #if HAVE_SYSV_COMPAT
8368 struct init_request request
= {
8369 .magic
= INIT_MAGIC
,
8371 .cmd
= INIT_CMD_RUNLVL
8374 _cleanup_close_
int fd
= -1;
8378 rl
= action_to_runlevel();
8382 request
.runlevel
= rl
;
8384 fd
= open(INIT_FIFO
, O_WRONLY
|O_NDELAY
|O_CLOEXEC
|O_NOCTTY
);
8386 if (errno
== ENOENT
)
8389 return log_error_errno(errno
, "Failed to open "INIT_FIFO
": %m");
8392 r
= loop_write(fd
, &request
, sizeof(request
), false);
8394 return log_error_errno(r
, "Failed to write to "INIT_FIFO
": %m");
8402 static int systemctl_main(int argc
, char *argv
[]) {
8404 static const Verb verbs
[] = {
8405 { "list-units", VERB_ANY
, VERB_ANY
, VERB_DEFAULT
|VERB_NOCHROOT
, list_units
},
8406 { "list-unit-files", VERB_ANY
, VERB_ANY
, 0, list_unit_files
},
8407 { "list-sockets", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_sockets
},
8408 { "list-timers", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_timers
},
8409 { "list-jobs", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_jobs
},
8410 { "list-machines", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_machines
},
8411 { "clear-jobs", VERB_ANY
, 1, VERB_NOCHROOT
, trivial_method
},
8412 { "cancel", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, cancel_job
},
8413 { "start", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8414 { "stop", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8415 { "condstop", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with ALTLinux */
8416 { "reload", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8417 { "restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8418 { "try-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8419 { "reload-or-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8420 { "reload-or-try-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatbility with old systemctl <= 228 */
8421 { "try-reload-or-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8422 { "force-reload", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with SysV */
8423 { "condreload", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with ALTLinux */
8424 { "condrestart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with RH */
8425 { "isolate", 2, 2, VERB_NOCHROOT
, start_unit
},
8426 { "kill", 2, VERB_ANY
, VERB_NOCHROOT
, kill_unit
},
8427 { "is-active", 2, VERB_ANY
, VERB_NOCHROOT
, check_unit_active
},
8428 { "check", 2, VERB_ANY
, VERB_NOCHROOT
, check_unit_active
},
8429 { "is-failed", 2, VERB_ANY
, VERB_NOCHROOT
, check_unit_failed
},
8430 { "show", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, show
},
8431 { "cat", 2, VERB_ANY
, VERB_NOCHROOT
, cat
},
8432 { "status", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, show
},
8433 { "help", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, show
},
8434 { "daemon-reload", VERB_ANY
, 1, VERB_NOCHROOT
, daemon_reload
},
8435 { "daemon-reexec", VERB_ANY
, 1, VERB_NOCHROOT
, daemon_reload
},
8436 { "show-environment", VERB_ANY
, 1, VERB_NOCHROOT
, show_environment
},
8437 { "set-environment", 2, VERB_ANY
, VERB_NOCHROOT
, set_environment
},
8438 { "unset-environment", 2, VERB_ANY
, VERB_NOCHROOT
, set_environment
},
8439 { "import-environment", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, import_environment
},
8440 { "halt", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8441 { "poweroff", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8442 { "reboot", VERB_ANY
, 2, VERB_NOCHROOT
, start_system_special
},
8443 { "kexec", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8444 { "suspend", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8445 { "hibernate", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8446 { "hybrid-sleep", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8447 { "default", VERB_ANY
, 1, VERB_NOCHROOT
, start_special
},
8448 { "rescue", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8449 { "emergency", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8450 { "exit", VERB_ANY
, 2, VERB_NOCHROOT
, start_special
},
8451 { "reset-failed", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, reset_failed
},
8452 { "enable", 2, VERB_ANY
, 0, enable_unit
},
8453 { "disable", 2, VERB_ANY
, 0, enable_unit
},
8454 { "is-enabled", 2, VERB_ANY
, 0, unit_is_enabled
},
8455 { "reenable", 2, VERB_ANY
, 0, enable_unit
},
8456 { "preset", 2, VERB_ANY
, 0, enable_unit
},
8457 { "preset-all", VERB_ANY
, 1, 0, preset_all
},
8458 { "mask", 2, VERB_ANY
, 0, enable_unit
},
8459 { "unmask", 2, VERB_ANY
, 0, enable_unit
},
8460 { "link", 2, VERB_ANY
, 0, enable_unit
},
8461 { "revert", 2, VERB_ANY
, 0, enable_unit
},
8462 { "switch-root", 2, VERB_ANY
, VERB_NOCHROOT
, switch_root
},
8463 { "list-dependencies", VERB_ANY
, 2, VERB_NOCHROOT
, list_dependencies
},
8464 { "set-default", 2, 2, 0, set_default
},
8465 { "get-default", VERB_ANY
, 1, 0, get_default
},
8466 { "set-property", 3, VERB_ANY
, VERB_NOCHROOT
, set_property
},
8467 { "is-system-running", VERB_ANY
, 1, 0, is_system_running
},
8468 { "add-wants", 3, VERB_ANY
, 0, add_dependency
},
8469 { "add-requires", 3, VERB_ANY
, 0, add_dependency
},
8470 { "edit", 2, VERB_ANY
, VERB_NOCHROOT
, edit
},
8474 return dispatch_verb(argc
, argv
, verbs
, NULL
);
8477 static int reload_with_fallback(void) {
8479 /* First, try systemd via D-Bus. */
8480 if (daemon_reload(0, NULL
, NULL
) >= 0)
8483 /* Nothing else worked, so let's try signals */
8484 assert(IN_SET(arg_action
, ACTION_RELOAD
, ACTION_REEXEC
));
8486 if (kill(1, arg_action
== ACTION_RELOAD
? SIGHUP
: SIGTERM
) < 0)
8487 return log_error_errno(errno
, "kill() failed: %m");
8492 static int start_with_fallback(void) {
8494 /* First, try systemd via D-Bus. */
8495 if (start_unit(0, NULL
, NULL
) >= 0)
8498 /* Nothing else worked, so let's try /dev/initctl */
8499 if (talk_initctl() > 0)
8502 log_error("Failed to talk to init daemon.");
8506 static int halt_now(enum action a
) {
8509 /* The kernel will automaticall flush ATA disks and suchlike
8510 * on reboot(), but the file systems need to be synce'd
8511 * explicitly in advance. */
8512 if (!arg_no_sync
&& !arg_dry_run
)
8515 /* Make sure C-A-D is handled by the kernel from this point on... */
8517 (void) reboot(RB_ENABLE_CAD
);
8523 log_info("Halting.");
8526 (void) reboot(RB_HALT_SYSTEM
);
8529 case ACTION_POWEROFF
:
8531 log_info("Powering off.");
8534 (void) reboot(RB_POWER_OFF
);
8538 case ACTION_REBOOT
: {
8539 _cleanup_free_
char *param
= NULL
;
8541 r
= read_one_line_file("/run/systemd/reboot-param", ¶m
);
8542 if (r
< 0 && r
!= -ENOENT
)
8543 log_warning_errno(r
, "Failed to read reboot parameter file: %m");
8545 if (!isempty(param
)) {
8547 log_info("Rebooting with argument '%s'.", param
);
8549 (void) syscall(SYS_reboot
, LINUX_REBOOT_MAGIC1
, LINUX_REBOOT_MAGIC2
,
8550 LINUX_REBOOT_CMD_RESTART2
, param
);
8551 log_warning_errno(errno
, "Failed to reboot with parameter, retrying without: %m");
8556 log_info("Rebooting.");
8559 (void) reboot(RB_AUTOBOOT
);
8564 assert_not_reached("Unknown action.");
8568 static int logind_schedule_shutdown(void) {
8571 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
8572 char date
[FORMAT_TIMESTAMP_MAX
];
8577 r
= acquire_bus(BUS_FULL
, &bus
);
8581 switch (arg_action
) {
8585 case ACTION_POWEROFF
:
8586 action
= "poweroff";
8601 action
= strjoina("dry-", action
);
8603 (void) logind_set_wall_message();
8605 r
= sd_bus_call_method(
8607 "org.freedesktop.login1",
8608 "/org/freedesktop/login1",
8609 "org.freedesktop.login1.Manager",
8617 return log_warning_errno(r
, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s", bus_error_message(&error
, r
));
8620 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.", format_timestamp(date
, sizeof(date
), arg_when
));
8623 log_error("Cannot schedule shutdown without logind support, proceeding with immediate shutdown.");
8628 static int halt_main(void) {
8631 r
= logind_check_inhibitors(arg_action
);
8636 return logind_schedule_shutdown();
8638 if (geteuid() != 0) {
8639 if (arg_dry_run
|| arg_force
> 0) {
8640 log_error("Must be root.");
8644 /* Try logind if we are a normal user and no special
8645 * mode applies. Maybe PolicyKit allows us to shutdown
8647 if (IN_SET(arg_action
, ACTION_POWEROFF
, ACTION_REBOOT
, ACTION_HALT
)) {
8648 r
= logind_reboot(arg_action
);
8651 if (IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
8652 /* requested operation is not
8653 * supported on the local system or
8654 * already in progress */
8656 /* on all other errors, try low-level operation */
8660 if (!arg_dry_run
&& !arg_force
)
8661 return start_with_fallback();
8663 assert(geteuid() == 0);
8666 if (sd_booted() > 0)
8667 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
8669 r
= utmp_put_shutdown();
8671 log_warning_errno(r
, "Failed to write utmp record: %m");
8678 r
= halt_now(arg_action
);
8679 return log_error_errno(r
, "Failed to reboot: %m");
8682 static int runlevel_main(void) {
8683 int r
, runlevel
, previous
;
8685 r
= utmp_get_runlevel(&runlevel
, &previous
);
8692 previous
<= 0 ? 'N' : previous
,
8693 runlevel
<= 0 ? 'N' : runlevel
);
8698 static int logind_cancel_shutdown(void) {
8700 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
8704 r
= acquire_bus(BUS_FULL
, &bus
);
8708 (void) logind_set_wall_message();
8710 r
= sd_bus_call_method(
8712 "org.freedesktop.login1",
8713 "/org/freedesktop/login1",
8714 "org.freedesktop.login1.Manager",
8715 "CancelScheduledShutdown",
8719 return log_warning_errno(r
, "Failed to talk to logind, shutdown hasn't been cancelled: %s", bus_error_message(&error
, r
));
8723 log_error("Not compiled with logind support, cannot cancel scheduled shutdowns.");
8728 int main(int argc
, char*argv
[]) {
8731 argv_cmdline
= argv
[0];
8733 setlocale(LC_ALL
, "");
8734 log_parse_environment();
8738 /* Explicitly not on_tty() to avoid setting cached value.
8739 * This becomes relevant for piping output which might be
8741 original_stdout_is_tty
= isatty(STDOUT_FILENO
);
8743 r
= parse_argv(argc
, argv
);
8747 if (arg_action
!= ACTION_SYSTEMCTL
&& running_in_chroot() > 0) {
8750 log_info("Running in chroot, ignoring request.");
8755 /* systemctl_main() will print an error message for the bus
8756 * connection, but only if it needs to */
8758 switch (arg_action
) {
8760 case ACTION_SYSTEMCTL
:
8761 r
= systemctl_main(argc
, argv
);
8764 /* Legacy command aliases set arg_action. They provide some fallbacks,
8765 * e.g. to tell sysvinit to reboot after you have installed systemd
8769 case ACTION_POWEROFF
:
8775 case ACTION_RUNLEVEL2
:
8776 case ACTION_RUNLEVEL3
:
8777 case ACTION_RUNLEVEL4
:
8778 case ACTION_RUNLEVEL5
:
8780 r
= start_with_fallback();
8785 r
= reload_with_fallback();
8788 case ACTION_CANCEL_SHUTDOWN
:
8789 r
= logind_cancel_shutdown();
8792 case ACTION_RUNLEVEL
:
8793 r
= runlevel_main();
8797 case ACTION_SUSPEND
:
8798 case ACTION_HIBERNATE
:
8799 case ACTION_HYBRID_SLEEP
:
8800 case ACTION_EMERGENCY
:
8801 case ACTION_DEFAULT
:
8802 /* systemctl verbs with no equivalent in the legacy commands.
8803 * These cannot appear in arg_action. Fall through. */
8805 case _ACTION_INVALID
:
8807 assert_not_reached("Unknown action");
8814 ask_password_agent_close();
8815 polkit_agent_close();
8817 strv_free(arg_types
);
8818 strv_free(arg_states
);
8819 strv_free(arg_properties
);
8821 strv_free(arg_wall
);
8825 /* Note that we return r here, not EXIT_SUCCESS, so that we can implement the LSB-like return codes */
8826 return r
< 0 ? EXIT_FAILURE
: r
;