1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2010 Lennart Poettering
6 Copyright 2013 Marc-Antoine Perennou
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
30 #include <sys/prctl.h>
31 #include <sys/reboot.h>
32 #include <sys/socket.h>
36 #include "sd-daemon.h"
39 #include "alloc-util.h"
41 #include "bus-common-errors.h"
42 #include "bus-error.h"
43 #include "bus-message.h"
44 #include "bus-unit-util.h"
46 #include "cgroup-show.h"
47 #include "cgroup-util.h"
53 #include "exit-status.h"
56 #include "format-util.h"
58 #include "glob-util.h"
59 #include "hexdecoct.h"
60 #include "hostname-util.h"
65 #include "locale-util.h"
67 #include "logs-show.h"
71 #include "parse-util.h"
72 #include "path-lookup.h"
73 #include "path-util.h"
74 #include "process-util.h"
75 #include "reboot-util.h"
76 #include "rlimit-util.h"
79 #include "signal-util.h"
80 #include "socket-util.h"
81 #include "spawn-ask-password-agent.h"
82 #include "spawn-polkit-agent.h"
84 #include "stat-util.h"
85 #include "string-table.h"
87 #include "terminal-util.h"
89 #include "unit-name.h"
90 #include "user-util.h"
92 #include "utmp-wtmp.h"
96 /* The init script exit status codes
97 0 program is running or service is OK
98 1 program is dead and /var/run pid file exists
99 2 program is dead and /var/lock lock file exists
100 3 program is not running
101 4 program or service status is unknown
102 5-99 reserved for future LSB use
103 100-149 reserved for distribution use
104 150-199 reserved for application use
108 EXIT_PROGRAM_RUNNING_OR_SERVICE_OK
= 0,
109 EXIT_PROGRAM_DEAD_AND_PID_EXISTS
= 1,
110 EXIT_PROGRAM_DEAD_AND_LOCK_FILE_EXISTS
= 2,
111 EXIT_PROGRAM_NOT_RUNNING
= 3,
112 EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN
= 4,
115 static char **arg_types
= NULL
;
116 static char **arg_states
= NULL
;
117 static char **arg_properties
= NULL
;
118 static bool arg_all
= false;
119 static enum dependency
{
125 } arg_dependency
= DEPENDENCY_FORWARD
;
126 static const char *arg_job_mode
= "replace";
127 static UnitFileScope arg_scope
= UNIT_FILE_SYSTEM
;
128 static bool arg_wait
= false;
129 static bool arg_no_block
= false;
130 static bool arg_no_legend
= false;
131 static bool arg_no_pager
= false;
132 static bool arg_no_wtmp
= false;
133 static bool arg_no_sync
= false;
134 static bool arg_no_wall
= false;
135 static bool arg_no_reload
= false;
136 static bool arg_value
= false;
137 static bool arg_show_types
= false;
138 static bool arg_ignore_inhibitors
= false;
139 static bool arg_dry_run
= false;
140 static bool arg_quiet
= false;
141 static bool arg_full
= false;
142 static bool arg_recursive
= false;
143 static int arg_force
= 0;
144 static bool arg_ask_password
= false;
145 static bool arg_runtime
= false;
146 static UnitFilePresetMode arg_preset_mode
= UNIT_FILE_PRESET_FULL
;
147 static char **arg_wall
= NULL
;
148 static const char *arg_kill_who
= NULL
;
149 static int arg_signal
= SIGTERM
;
150 static char *arg_root
= NULL
;
151 static usec_t arg_when
= 0;
152 static char *arg_esp_path
= NULL
;
153 static char *argv_cmdline
= NULL
;
164 ACTION_SUSPEND_TO_HIBERNATE
,
175 ACTION_CANCEL_SHUTDOWN
,
178 } arg_action
= ACTION_SYSTEMCTL
;
179 static BusTransport arg_transport
= BUS_TRANSPORT_LOCAL
;
180 static const char *arg_host
= NULL
;
181 static unsigned arg_lines
= 10;
182 static OutputMode arg_output
= OUTPUT_SHORT
;
183 static bool arg_plain
= false;
184 static bool arg_firmware_setup
= false;
185 static bool arg_now
= false;
186 static bool arg_jobs_before
= false;
187 static bool arg_jobs_after
= false;
189 static int daemon_reload(int argc
, char *argv
[], void* userdata
);
190 static int trivial_method(int argc
, char *argv
[], void *userdata
);
191 static int halt_now(enum action a
);
192 static int get_state_one_unit(sd_bus
*bus
, const char *name
, UnitActiveState
*active_state
);
194 static bool original_stdout_is_tty
;
196 typedef enum BusFocus
{
197 BUS_FULL
, /* The full bus indicated via --system or --user */
198 BUS_MANAGER
, /* The manager itself, possibly directly, possibly via the bus */
202 static sd_bus
*busses
[_BUS_FOCUS_MAX
] = {};
204 static UnitFileFlags
args_to_flags(void) {
205 return (arg_runtime
? UNIT_FILE_RUNTIME
: 0) |
206 (arg_force
? UNIT_FILE_FORCE
: 0);
209 static int acquire_bus(BusFocus focus
, sd_bus
**ret
) {
212 assert(focus
< _BUS_FOCUS_MAX
);
215 /* We only go directly to the manager, if we are using a local transport */
216 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
219 if (getenv_bool("SYSTEMCTL_FORCE_BUS") > 0)
222 if (!busses
[focus
]) {
225 user
= arg_scope
!= UNIT_FILE_SYSTEM
;
227 if (!user
&& sd_booted() <= 0) {
228 /* Print a friendly message when the local system is actually not running systemd as PID 1. */
229 log_error("System has not been booted with systemd as init system (PID 1). Can't operate.");
233 if (focus
== BUS_MANAGER
)
234 r
= bus_connect_transport_systemd(arg_transport
, arg_host
, user
, &busses
[focus
]);
236 r
= bus_connect_transport(arg_transport
, arg_host
, user
, &busses
[focus
]);
238 return log_error_errno(r
, "Failed to connect to bus: %m");
240 (void) sd_bus_set_allow_interactive_authorization(busses
[focus
], arg_ask_password
);
243 *ret
= busses
[focus
];
247 static void release_busses(void) {
250 for (w
= 0; w
< _BUS_FOCUS_MAX
; w
++)
251 busses
[w
] = sd_bus_flush_close_unref(busses
[w
]);
254 static void ask_password_agent_open_if_enabled(void) {
256 /* Open the password agent as a child process if necessary */
261 if (!arg_ask_password
)
264 if (arg_scope
!= UNIT_FILE_SYSTEM
)
267 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
270 ask_password_agent_open();
273 static void polkit_agent_open_maybe(void) {
274 /* Open the polkit agent as a child process if necessary */
276 if (arg_scope
!= UNIT_FILE_SYSTEM
)
279 polkit_agent_open_if_enabled(arg_transport
, arg_ask_password
);
282 static OutputFlags
get_output_flags(void) {
284 arg_all
* OUTPUT_SHOW_ALL
|
285 (arg_full
|| !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH
|
286 colors_enabled() * OUTPUT_COLOR
|
287 !arg_quiet
* OUTPUT_WARN_CUTOFF
;
290 static int translate_bus_error_to_exit_status(int r
, const sd_bus_error
*error
) {
293 if (!sd_bus_error_is_set(error
))
296 if (sd_bus_error_has_name(error
, SD_BUS_ERROR_ACCESS_DENIED
) ||
297 sd_bus_error_has_name(error
, BUS_ERROR_ONLY_BY_DEPENDENCY
) ||
298 sd_bus_error_has_name(error
, BUS_ERROR_NO_ISOLATION
) ||
299 sd_bus_error_has_name(error
, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE
))
300 return EXIT_NOPERMISSION
;
302 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
))
303 return EXIT_NOTINSTALLED
;
305 if (sd_bus_error_has_name(error
, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE
) ||
306 sd_bus_error_has_name(error
, SD_BUS_ERROR_NOT_SUPPORTED
))
307 return EXIT_NOTIMPLEMENTED
;
309 if (sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
))
310 return EXIT_NOTCONFIGURED
;
318 static bool install_client_side(void) {
320 /* Decides when to execute enable/disable/... operations
321 * client-side rather than server-side. */
323 if (running_in_chroot_or_offline())
326 if (sd_booted() <= 0)
329 if (!isempty(arg_root
))
332 if (arg_scope
== UNIT_FILE_GLOBAL
)
335 /* Unsupported environment variable, mostly for debugging purposes */
336 if (getenv_bool("SYSTEMCTL_INSTALL_CLIENT_SIDE") > 0)
342 static int compare_unit_info(const void *a
, const void *b
) {
343 const UnitInfo
*u
= a
, *v
= b
;
347 /* First, order by machine */
348 if (!u
->machine
&& v
->machine
)
350 if (u
->machine
&& !v
->machine
)
352 if (u
->machine
&& v
->machine
) {
353 r
= strcasecmp(u
->machine
, v
->machine
);
358 /* Second, order by unit type */
359 d1
= strrchr(u
->id
, '.');
360 d2
= strrchr(v
->id
, '.');
362 r
= strcasecmp(d1
, d2
);
367 /* Third, order by name */
368 return strcasecmp(u
->id
, v
->id
);
371 static const char* unit_type_suffix(const char *name
) {
374 dot
= strrchr(name
, '.');
381 static bool output_show_unit(const UnitInfo
*u
, char **patterns
) {
384 if (!strv_fnmatch_or_empty(patterns
, u
->id
, FNM_NOESCAPE
))
387 if (arg_types
&& !strv_find(arg_types
, unit_type_suffix(u
->id
)))
393 /* Note that '--all' is not purely a state filter, but also a
394 * filter that hides units that "follow" other units (which is
395 * used for device units that appear under different names). */
396 if (!isempty(u
->following
))
399 if (!strv_isempty(arg_states
))
402 /* By default show all units except the ones in inactive
403 * state and with no pending job */
407 if (streq(u
->active_state
, "inactive"))
413 static int output_units_list(const UnitInfo
*unit_infos
, unsigned c
) {
414 unsigned circle_len
= 0, id_len
, max_id_len
, load_len
, active_len
, sub_len
, job_len
, desc_len
, max_desc_len
;
416 unsigned n_shown
= 0;
419 max_id_len
= STRLEN("UNIT");
420 load_len
= STRLEN("LOAD");
421 active_len
= STRLEN("ACTIVE");
422 sub_len
= STRLEN("SUB");
423 job_len
= STRLEN("JOB");
424 max_desc_len
= STRLEN("DESCRIPTION");
426 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
427 max_id_len
= MAX(max_id_len
, strlen(u
->id
) + (u
->machine
? strlen(u
->machine
)+1 : 0));
428 load_len
= MAX(load_len
, strlen(u
->load_state
));
429 active_len
= MAX(active_len
, strlen(u
->active_state
));
430 sub_len
= MAX(sub_len
, strlen(u
->sub_state
));
431 max_desc_len
= MAX(max_desc_len
, strlen(u
->description
));
433 if (u
->job_id
!= 0) {
434 job_len
= MAX(job_len
, strlen(u
->job_type
));
438 if (!arg_no_legend
&&
439 (streq(u
->active_state
, "failed") ||
440 STR_IN_SET(u
->load_state
, "error", "not-found", "masked")))
444 if (!arg_full
&& original_stdout_is_tty
) {
447 id_len
= MIN(max_id_len
, 25u); /* as much as it needs, but at most 25 for now */
448 basic_len
= circle_len
+ 1 + id_len
+ 1 + load_len
+ 1 + active_len
+ 1 + sub_len
+ 1;
451 basic_len
+= job_len
+ 1;
453 if (basic_len
< (unsigned) columns()) {
454 unsigned extra_len
, incr
;
455 extra_len
= columns() - basic_len
;
457 /* Either UNIT already got 25, or is fully satisfied.
458 * Grant up to 25 to DESC now. */
459 incr
= MIN(extra_len
, 25u);
463 /* Of the remainder give as much as the ID needs to the ID, and give the rest to the
464 * description but not more than it needs. */
466 incr
= MIN(max_id_len
- id_len
, extra_len
);
468 desc_len
+= MIN(extra_len
- incr
, max_desc_len
- desc_len
);
474 desc_len
= max_desc_len
;
477 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
478 _cleanup_free_
char *e
= NULL
, *j
= NULL
;
479 const char *on_underline
= "", *off_underline
= "";
480 const char *on_loaded
= "", *off_loaded
= "";
481 const char *on_active
= "", *off_active
= "";
482 const char *on_circle
= "", *off_circle
= "";
484 bool circle
= false, underline
= false;
486 if (!n_shown
&& !arg_no_legend
) {
491 printf("%s%-*s %-*s %-*s %-*s ",
495 active_len
, "ACTIVE",
499 printf("%-*s ", job_len
, "JOB");
503 !arg_full
&& arg_no_pager
? (int) desc_len
: -1,
510 if (u
+ 1 < unit_infos
+ c
&&
511 !streq(unit_type_suffix(u
->id
), unit_type_suffix((u
+ 1)->id
))) {
512 on_underline
= ansi_underline();
513 off_underline
= ansi_normal();
517 if (STR_IN_SET(u
->load_state
, "error", "not-found", "masked") && !arg_plain
) {
518 on_circle
= ansi_highlight_yellow();
519 off_circle
= ansi_normal();
521 on_loaded
= underline
? ansi_highlight_red_underline() : ansi_highlight_red();
522 off_loaded
= underline
? on_underline
: ansi_normal();
523 } else if (streq(u
->active_state
, "failed") && !arg_plain
) {
524 on_circle
= ansi_highlight_red();
525 off_circle
= ansi_normal();
527 on_active
= underline
? ansi_highlight_red_underline() : ansi_highlight_red();
528 off_active
= underline
? on_underline
: ansi_normal();
532 j
= strjoin(u
->machine
, ":", u
->id
);
541 e
= ellipsize(id
, id_len
, 33);
549 printf("%s%s%s ", on_circle
, circle
? special_glyph(BLACK_CIRCLE
) : " ", off_circle
);
551 printf("%s%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
553 on_active
, id_len
, id
, off_active
,
554 on_loaded
, load_len
, u
->load_state
, off_loaded
,
555 on_active
, active_len
, u
->active_state
,
556 sub_len
, u
->sub_state
, off_active
,
557 job_count
? job_len
+ 1 : 0, u
->job_id
? u
->job_type
: "");
561 !arg_full
&& arg_no_pager
? (int) desc_len
: -1,
566 if (!arg_no_legend
) {
567 const char *on
, *off
;
571 "LOAD = Reflects whether the unit definition was properly loaded.\n"
572 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
573 "SUB = The low-level unit activation state, values depend on unit type.");
574 puts(job_count
? "JOB = Pending job for the unit.\n" : "");
575 on
= ansi_highlight();
578 on
= ansi_highlight_red();
583 printf("%s%u loaded units listed.%s\n"
584 "To show all installed unit files use 'systemctl list-unit-files'.\n",
587 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
588 "To show all installed unit files use 'systemctl list-unit-files'.\n",
595 static int get_unit_list(
599 UnitInfo
**unit_infos
,
601 sd_bus_message
**_reply
) {
603 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
604 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
605 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
609 bool fallback
= false;
615 r
= sd_bus_message_new_method_call(
618 "org.freedesktop.systemd1",
619 "/org/freedesktop/systemd1",
620 "org.freedesktop.systemd1.Manager",
621 "ListUnitsByPatterns");
623 return bus_log_create_error(r
);
625 r
= sd_bus_message_append_strv(m
, arg_states
);
627 return bus_log_create_error(r
);
629 r
= sd_bus_message_append_strv(m
, patterns
);
631 return bus_log_create_error(r
);
633 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
634 if (r
< 0 && (sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_METHOD
) ||
635 sd_bus_error_has_name(&error
, SD_BUS_ERROR_ACCESS_DENIED
))) {
636 /* Fallback to legacy ListUnitsFiltered method */
638 log_debug_errno(r
, "Failed to list units: %s Falling back to ListUnitsFiltered method.", bus_error_message(&error
, r
));
639 m
= sd_bus_message_unref(m
);
640 sd_bus_error_free(&error
);
642 r
= sd_bus_message_new_method_call(
645 "org.freedesktop.systemd1",
646 "/org/freedesktop/systemd1",
647 "org.freedesktop.systemd1.Manager",
648 "ListUnitsFiltered");
650 return bus_log_create_error(r
);
652 r
= sd_bus_message_append_strv(m
, arg_states
);
654 return bus_log_create_error(r
);
656 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
659 return log_error_errno(r
, "Failed to list units: %s", bus_error_message(&error
, r
));
661 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssssouso)");
663 return bus_log_parse_error(r
);
665 while ((r
= bus_parse_unit_info(reply
, &u
)) > 0) {
668 if (!output_show_unit(&u
, fallback
? patterns
: NULL
))
671 if (!GREEDY_REALLOC(*unit_infos
, size
, c
+1))
674 (*unit_infos
)[c
++] = u
;
677 return bus_log_parse_error(r
);
679 r
= sd_bus_message_exit_container(reply
);
681 return bus_log_parse_error(r
);
689 static void message_set_freep(Set
**set
) {
690 set_free_with_destructor(*set
, sd_bus_message_unref
);
693 static int get_unit_list_recursive(
696 UnitInfo
**_unit_infos
,
700 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
701 _cleanup_(message_set_freep
) Set
*replies
;
702 sd_bus_message
*reply
;
710 replies
= set_new(NULL
);
714 c
= get_unit_list(bus
, NULL
, patterns
, &unit_infos
, 0, &reply
);
718 r
= set_put(replies
, reply
);
720 sd_bus_message_unref(reply
);
725 _cleanup_strv_free_
char **machines
= NULL
;
728 r
= sd_get_machine_names(&machines
);
730 return log_error_errno(r
, "Failed to get machine names: %m");
732 STRV_FOREACH(i
, machines
) {
733 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*container
= NULL
;
736 r
= sd_bus_open_system_machine(&container
, *i
);
738 log_warning_errno(r
, "Failed to connect to container %s, ignoring: %m", *i
);
742 k
= get_unit_list(container
, *i
, patterns
, &unit_infos
, c
, &reply
);
748 r
= set_put(replies
, reply
);
750 sd_bus_message_unref(reply
);
755 *_machines
= machines
;
760 *_unit_infos
= unit_infos
;
769 static int list_units(int argc
, char *argv
[], void *userdata
) {
770 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
771 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
772 _cleanup_strv_free_
char **machines
= NULL
;
776 r
= acquire_bus(BUS_MANAGER
, &bus
);
780 (void) pager_open(arg_no_pager
, false);
782 r
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
786 qsort_safe(unit_infos
, r
, sizeof(UnitInfo
), compare_unit_info
);
787 return output_units_list(unit_infos
, r
);
790 static int get_triggered_units(
795 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
802 r
= sd_bus_get_property_strv(
804 "org.freedesktop.systemd1",
806 "org.freedesktop.systemd1.Unit",
811 return log_error_errno(r
, "Failed to determine triggers: %s", bus_error_message(&error
, r
));
816 static int get_listening(
818 const char* unit_path
,
821 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
822 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
823 const char *type
, *path
;
826 r
= sd_bus_get_property(
828 "org.freedesktop.systemd1",
830 "org.freedesktop.systemd1.Socket",
836 return log_error_errno(r
, "Failed to get list of listening sockets: %s", bus_error_message(&error
, r
));
838 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
840 return bus_log_parse_error(r
);
842 while ((r
= sd_bus_message_read(reply
, "(ss)", &type
, &path
)) > 0) {
844 r
= strv_extend(listening
, type
);
848 r
= strv_extend(listening
, path
);
855 return bus_log_parse_error(r
);
857 r
= sd_bus_message_exit_container(reply
);
859 return bus_log_parse_error(r
);
871 /* Note: triggered is a list here, although it almost certainly
872 * will always be one unit. Nevertheless, dbus API allows for multiple
873 * values, so let's follow that. */
876 /* The strv above is shared. free is set only in the first one. */
880 static int socket_info_compare(const struct socket_info
*a
, const struct socket_info
*b
) {
886 if (!a
->machine
&& b
->machine
)
888 if (a
->machine
&& !b
->machine
)
890 if (a
->machine
&& b
->machine
) {
891 o
= strcasecmp(a
->machine
, b
->machine
);
896 o
= strcmp(a
->path
, b
->path
);
898 o
= strcmp(a
->type
, b
->type
);
903 static int output_sockets_list(struct socket_info
*socket_infos
, unsigned cs
) {
904 struct socket_info
*s
;
905 unsigned pathlen
= STRLEN("LISTEN"),
906 typelen
= STRLEN("TYPE") * arg_show_types
,
907 socklen
= STRLEN("UNIT"),
908 servlen
= STRLEN("ACTIVATES");
909 const char *on
, *off
;
911 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
915 socklen
= MAX(socklen
, strlen(s
->id
));
917 typelen
= MAX(typelen
, strlen(s
->type
));
918 pathlen
= MAX(pathlen
, strlen(s
->path
) + (s
->machine
? strlen(s
->machine
)+1 : 0));
920 STRV_FOREACH(a
, s
->triggered
)
921 tmp
+= strlen(*a
) + 2*(a
!= s
->triggered
);
922 servlen
= MAX(servlen
, tmp
);
927 printf("%-*s %-*.*s%-*s %s\n",
929 typelen
+ arg_show_types
, typelen
+ arg_show_types
, "TYPE ",
933 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
934 _cleanup_free_
char *j
= NULL
;
939 j
= strjoin(s
->machine
, ":", s
->path
);
947 printf("%-*s %-*s %-*s",
948 pathlen
, path
, typelen
, s
->type
, socklen
, s
->id
);
951 pathlen
, path
, socklen
, s
->id
);
952 STRV_FOREACH(a
, s
->triggered
)
954 a
== s
->triggered
? "" : ",", *a
);
958 on
= ansi_highlight();
963 on
= ansi_highlight_red();
967 if (!arg_no_legend
) {
968 printf("%s%u sockets listed.%s\n", on
, cs
, off
);
970 printf("Pass --all to see loaded but inactive sockets, too.\n");
976 static int list_sockets(int argc
, char *argv
[], void *userdata
) {
977 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
978 _cleanup_strv_free_
char **machines
= NULL
;
979 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
980 _cleanup_free_
struct socket_info
*socket_infos
= NULL
;
982 struct socket_info
*s
;
988 r
= acquire_bus(BUS_MANAGER
, &bus
);
992 (void) pager_open(arg_no_pager
, false);
994 n
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
998 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
999 _cleanup_strv_free_
char **listening
= NULL
, **triggered
= NULL
;
1002 if (!endswith(u
->id
, ".socket"))
1005 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
1009 c
= get_listening(bus
, u
->unit_path
, &listening
);
1015 if (!GREEDY_REALLOC(socket_infos
, size
, cs
+ c
)) {
1020 for (i
= 0; i
< c
; i
++)
1021 socket_infos
[cs
+ i
] = (struct socket_info
) {
1022 .machine
= u
->machine
,
1024 .type
= listening
[i
*2],
1025 .path
= listening
[i
*2 + 1],
1026 .triggered
= triggered
,
1027 .own_triggered
= i
==0,
1030 /* from this point on we will cleanup those socket_infos */
1033 listening
= triggered
= NULL
; /* avoid cleanup */
1036 qsort_safe(socket_infos
, cs
, sizeof(struct socket_info
),
1037 (__compar_fn_t
) socket_info_compare
);
1039 output_sockets_list(socket_infos
, cs
);
1042 assert(cs
== 0 || socket_infos
);
1043 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
1046 if (s
->own_triggered
)
1047 strv_free(s
->triggered
);
1053 static int get_next_elapse(
1056 dual_timestamp
*next
) {
1058 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1066 r
= sd_bus_get_property_trivial(
1068 "org.freedesktop.systemd1",
1070 "org.freedesktop.systemd1.Timer",
1071 "NextElapseUSecMonotonic",
1076 return log_error_errno(r
, "Failed to get next elapse time: %s", bus_error_message(&error
, r
));
1078 r
= sd_bus_get_property_trivial(
1080 "org.freedesktop.systemd1",
1082 "org.freedesktop.systemd1.Timer",
1083 "NextElapseUSecRealtime",
1088 return log_error_errno(r
, "Failed to get next elapse time: %s", bus_error_message(&error
, r
));
1094 static int get_last_trigger(
1099 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1106 r
= sd_bus_get_property_trivial(
1108 "org.freedesktop.systemd1",
1110 "org.freedesktop.systemd1.Timer",
1116 return log_error_errno(r
, "Failed to get last trigger time: %s", bus_error_message(&error
, r
));
1122 const char* machine
;
1125 usec_t last_trigger
;
1129 static int timer_info_compare(const struct timer_info
*a
, const struct timer_info
*b
) {
1135 if (!a
->machine
&& b
->machine
)
1137 if (a
->machine
&& !b
->machine
)
1139 if (a
->machine
&& b
->machine
) {
1140 o
= strcasecmp(a
->machine
, b
->machine
);
1145 if (a
->next_elapse
< b
->next_elapse
)
1147 if (a
->next_elapse
> b
->next_elapse
)
1150 return strcmp(a
->id
, b
->id
);
1153 static int output_timers_list(struct timer_info
*timer_infos
, unsigned n
) {
1154 struct timer_info
*t
;
1156 nextlen
= STRLEN("NEXT"),
1157 leftlen
= STRLEN("LEFT"),
1158 lastlen
= STRLEN("LAST"),
1159 passedlen
= STRLEN("PASSED"),
1160 unitlen
= STRLEN("UNIT"),
1161 activatelen
= STRLEN("ACTIVATES");
1163 const char *on
, *off
;
1165 assert(timer_infos
|| n
== 0);
1167 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1171 if (t
->next_elapse
> 0) {
1172 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1174 format_timestamp(tstamp
, sizeof(tstamp
), t
->next_elapse
);
1175 nextlen
= MAX(nextlen
, strlen(tstamp
) + 1);
1177 format_timestamp_relative(trel
, sizeof(trel
), t
->next_elapse
);
1178 leftlen
= MAX(leftlen
, strlen(trel
));
1181 if (t
->last_trigger
> 0) {
1182 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1184 format_timestamp(tstamp
, sizeof(tstamp
), t
->last_trigger
);
1185 lastlen
= MAX(lastlen
, strlen(tstamp
) + 1);
1187 format_timestamp_relative(trel
, sizeof(trel
), t
->last_trigger
);
1188 passedlen
= MAX(passedlen
, strlen(trel
));
1191 unitlen
= MAX(unitlen
, strlen(t
->id
) + (t
->machine
? strlen(t
->machine
)+1 : 0));
1193 STRV_FOREACH(a
, t
->triggered
)
1194 ul
+= strlen(*a
) + 2*(a
!= t
->triggered
);
1196 activatelen
= MAX(activatelen
, ul
);
1201 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1205 passedlen
, "PASSED",
1209 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1210 _cleanup_free_
char *j
= NULL
;
1212 char tstamp1
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel1
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1213 char tstamp2
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel2
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1216 format_timestamp(tstamp1
, sizeof(tstamp1
), t
->next_elapse
);
1217 format_timestamp_relative(trel1
, sizeof(trel1
), t
->next_elapse
);
1219 format_timestamp(tstamp2
, sizeof(tstamp2
), t
->last_trigger
);
1220 format_timestamp_relative(trel2
, sizeof(trel2
), t
->last_trigger
);
1223 j
= strjoin(t
->machine
, ":", t
->id
);
1230 printf("%-*s %-*s %-*s %-*s %-*s",
1231 nextlen
, tstamp1
, leftlen
, trel1
, lastlen
, tstamp2
, passedlen
, trel2
, unitlen
, unit
);
1233 STRV_FOREACH(a
, t
->triggered
)
1235 a
== t
->triggered
? "" : ",", *a
);
1239 on
= ansi_highlight();
1240 off
= ansi_normal();
1244 on
= ansi_highlight_red();
1245 off
= ansi_normal();
1248 if (!arg_no_legend
) {
1249 printf("%s%u timers listed.%s\n", on
, n
, off
);
1251 printf("Pass --all to see loaded but inactive timers, too.\n");
1257 static usec_t
calc_next_elapse(dual_timestamp
*nw
, dual_timestamp
*next
) {
1263 if (next
->monotonic
!= USEC_INFINITY
&& next
->monotonic
> 0) {
1266 if (next
->monotonic
> nw
->monotonic
)
1267 converted
= nw
->realtime
+ (next
->monotonic
- nw
->monotonic
);
1269 converted
= nw
->realtime
- (nw
->monotonic
- next
->monotonic
);
1271 if (next
->realtime
!= USEC_INFINITY
&& next
->realtime
> 0)
1272 next_elapse
= MIN(converted
, next
->realtime
);
1274 next_elapse
= converted
;
1277 next_elapse
= next
->realtime
;
1282 static int list_timers(int argc
, char *argv
[], void *userdata
) {
1283 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
1284 _cleanup_strv_free_
char **machines
= NULL
;
1285 _cleanup_free_
struct timer_info
*timer_infos
= NULL
;
1286 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
1287 struct timer_info
*t
;
1295 r
= acquire_bus(BUS_MANAGER
, &bus
);
1299 (void) pager_open(arg_no_pager
, false);
1301 n
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
1305 dual_timestamp_get(&nw
);
1307 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
1308 _cleanup_strv_free_
char **triggered
= NULL
;
1309 dual_timestamp next
= DUAL_TIMESTAMP_NULL
;
1312 if (!endswith(u
->id
, ".timer"))
1315 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
1319 r
= get_next_elapse(bus
, u
->unit_path
, &next
);
1323 get_last_trigger(bus
, u
->unit_path
, &last
);
1325 if (!GREEDY_REALLOC(timer_infos
, size
, c
+1)) {
1330 m
= calc_next_elapse(&nw
, &next
);
1332 timer_infos
[c
++] = (struct timer_info
) {
1333 .machine
= u
->machine
,
1336 .last_trigger
= last
,
1337 .triggered
= triggered
,
1340 triggered
= NULL
; /* avoid cleanup */
1343 qsort_safe(timer_infos
, c
, sizeof(struct timer_info
),
1344 (__compar_fn_t
) timer_info_compare
);
1346 output_timers_list(timer_infos
, c
);
1349 for (t
= timer_infos
; t
< timer_infos
+ c
; t
++)
1350 strv_free(t
->triggered
);
1355 static int compare_unit_file_list(const void *a
, const void *b
) {
1356 const char *d1
, *d2
;
1357 const UnitFileList
*u
= a
, *v
= b
;
1359 d1
= strrchr(u
->path
, '.');
1360 d2
= strrchr(v
->path
, '.');
1365 r
= strcasecmp(d1
, d2
);
1370 return strcasecmp(basename(u
->path
), basename(v
->path
));
1373 static bool output_show_unit_file(const UnitFileList
*u
, char **states
, char **patterns
) {
1376 if (!strv_fnmatch_or_empty(patterns
, basename(u
->path
), FNM_NOESCAPE
))
1379 if (!strv_isempty(arg_types
)) {
1382 dot
= strrchr(u
->path
, '.');
1386 if (!strv_find(arg_types
, dot
+1))
1390 if (!strv_isempty(states
) &&
1391 !strv_find(states
, unit_file_state_to_string(u
->state
)))
1397 static void output_unit_file_list(const UnitFileList
*units
, unsigned c
) {
1398 unsigned max_id_len
, id_cols
, state_cols
;
1399 const UnitFileList
*u
;
1401 max_id_len
= STRLEN("UNIT FILE");
1402 state_cols
= STRLEN("STATE");
1404 for (u
= units
; u
< units
+ c
; u
++) {
1405 max_id_len
= MAX(max_id_len
, strlen(basename(u
->path
)));
1406 state_cols
= MAX(state_cols
, strlen(unit_file_state_to_string(u
->state
)));
1410 unsigned basic_cols
;
1412 id_cols
= MIN(max_id_len
, 25u);
1413 basic_cols
= 1 + id_cols
+ state_cols
;
1414 if (basic_cols
< (unsigned) columns())
1415 id_cols
+= MIN(columns() - basic_cols
, max_id_len
- id_cols
);
1417 id_cols
= max_id_len
;
1419 if (!arg_no_legend
&& c
> 0)
1420 printf("%s%-*s %-*s%s\n",
1422 id_cols
, "UNIT FILE",
1423 state_cols
, "STATE",
1426 for (u
= units
; u
< units
+ c
; u
++) {
1427 const char *on_underline
= NULL
, *on_color
= NULL
, *off
= NULL
, *id
;
1428 _cleanup_free_
char *e
= NULL
;
1431 underline
= u
+ 1 < units
+ c
&&
1432 !streq(unit_type_suffix(u
->path
), unit_type_suffix((u
+ 1)->path
));
1435 on_underline
= ansi_underline();
1437 if (IN_SET(u
->state
,
1439 UNIT_FILE_MASKED_RUNTIME
,
1442 on_color
= underline
? ansi_highlight_red_underline() : ansi_highlight_red();
1443 else if (u
->state
== UNIT_FILE_ENABLED
)
1444 on_color
= underline
? ansi_highlight_green_underline() : ansi_highlight_green();
1446 if (on_underline
|| on_color
)
1447 off
= ansi_normal();
1449 id
= basename(u
->path
);
1451 e
= arg_full
? NULL
: ellipsize(id
, id_cols
, 33);
1453 printf("%s%-*s %s%-*s%s\n",
1454 strempty(on_underline
),
1455 id_cols
, e
? e
: id
,
1456 strempty(on_color
), state_cols
, unit_file_state_to_string(u
->state
), strempty(off
));
1460 printf("\n%u unit files listed.\n", c
);
1463 static int list_unit_files(int argc
, char *argv
[], void *userdata
) {
1464 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1465 _cleanup_free_ UnitFileList
*units
= NULL
;
1472 bool fallback
= false;
1474 if (install_client_side()) {
1480 h
= hashmap_new(&string_hash_ops
);
1484 r
= unit_file_get_list(arg_scope
, arg_root
, h
, arg_states
, strv_skip(argv
, 1));
1486 unit_file_list_free(h
);
1487 return log_error_errno(r
, "Failed to get unit file list: %m");
1490 n_units
= hashmap_size(h
);
1492 units
= new(UnitFileList
, n_units
?: 1); /* avoid malloc(0) */
1494 unit_file_list_free(h
);
1498 HASHMAP_FOREACH(u
, h
, i
) {
1499 if (!output_show_unit_file(u
, NULL
, NULL
))
1506 assert(c
<= n_units
);
1511 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
1512 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1515 r
= acquire_bus(BUS_MANAGER
, &bus
);
1519 r
= sd_bus_message_new_method_call(
1522 "org.freedesktop.systemd1",
1523 "/org/freedesktop/systemd1",
1524 "org.freedesktop.systemd1.Manager",
1525 "ListUnitFilesByPatterns");
1527 return bus_log_create_error(r
);
1529 r
= sd_bus_message_append_strv(m
, arg_states
);
1531 return bus_log_create_error(r
);
1533 r
= sd_bus_message_append_strv(m
, strv_skip(argv
, 1));
1535 return bus_log_create_error(r
);
1537 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
1538 if (r
< 0 && sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_METHOD
)) {
1539 /* Fallback to legacy ListUnitFiles method */
1541 log_debug_errno(r
, "Failed to list unit files: %s Falling back to ListUnitsFiles method.", bus_error_message(&error
, r
));
1542 m
= sd_bus_message_unref(m
);
1543 sd_bus_error_free(&error
);
1545 r
= sd_bus_message_new_method_call(
1548 "org.freedesktop.systemd1",
1549 "/org/freedesktop/systemd1",
1550 "org.freedesktop.systemd1.Manager",
1553 return bus_log_create_error(r
);
1555 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
1558 return log_error_errno(r
, "Failed to list unit files: %s", bus_error_message(&error
, r
));
1560 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
1562 return bus_log_parse_error(r
);
1564 while ((r
= sd_bus_message_read(reply
, "(ss)", &path
, &state
)) > 0) {
1566 if (!GREEDY_REALLOC(units
, size
, c
+ 1))
1569 units
[c
] = (struct UnitFileList
) {
1571 unit_file_state_from_string(state
)
1574 if (output_show_unit_file(&units
[c
],
1575 fallback
? arg_states
: NULL
,
1576 fallback
? strv_skip(argv
, 1) : NULL
))
1581 return bus_log_parse_error(r
);
1583 r
= sd_bus_message_exit_container(reply
);
1585 return bus_log_parse_error(r
);
1588 (void) pager_open(arg_no_pager
, false);
1590 qsort_safe(units
, c
, sizeof(UnitFileList
), compare_unit_file_list
);
1591 output_unit_file_list(units
, c
);
1593 if (install_client_side())
1594 for (unit
= units
; unit
< units
+ c
; unit
++)
1600 static int list_dependencies_print(const char *name
, int level
, unsigned int branches
, bool last
) {
1601 _cleanup_free_
char *n
= NULL
;
1602 size_t max_len
= MAX(columns(),20u);
1608 for (i
= level
- 1; i
>= 0; i
--) {
1610 if (len
> max_len
- 3 && !arg_full
) {
1611 printf("%s...\n",max_len
% 2 ? "" : " ");
1614 printf("%s", special_glyph(branches
& (1 << i
) ? TREE_VERTICAL
: TREE_SPACE
));
1618 if (len
> max_len
- 3 && !arg_full
) {
1619 printf("%s...\n",max_len
% 2 ? "" : " ");
1623 printf("%s", special_glyph(last
? TREE_RIGHT
: TREE_BRANCH
));
1627 printf("%s\n", name
);
1631 n
= ellipsize(name
, max_len
-len
, 100);
1639 static int list_dependencies_get_dependencies(sd_bus
*bus
, const char *name
, char ***deps
) {
1641 struct DependencyStatusInfo
{
1645 static const struct bus_properties_map map
[_DEPENDENCY_MAX
][6] = {
1646 [DEPENDENCY_FORWARD
] = {
1647 { "Requires", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[0]) },
1648 { "Requisite", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[1]) },
1649 { "Wants", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[2]) },
1650 { "ConsistsOf", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[3]) },
1651 { "BindsTo", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[4]) },
1654 [DEPENDENCY_REVERSE
] = {
1655 { "RequiredBy", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[0]) },
1656 { "RequisiteOf", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[1]) },
1657 { "WantedBy", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[2]) },
1658 { "PartOf", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[3]) },
1659 { "BoundBy", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[4]) },
1662 [DEPENDENCY_AFTER
] = {
1663 { "After", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[0]) },
1666 [DEPENDENCY_BEFORE
] = {
1667 { "Before", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[0]) },
1672 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1673 _cleanup_strv_free_
char **ret
= NULL
;
1674 _cleanup_free_
char *path
= NULL
;
1681 path
= unit_dbus_path_from_name(name
);
1685 r
= bus_map_all_properties(bus
,
1686 "org.freedesktop.systemd1",
1688 map
[arg_dependency
],
1693 return log_error_errno(r
, "Failed to get properties of %s: %s", name
, bus_error_message(&error
, r
));
1695 if (IN_SET(arg_dependency
, DEPENDENCY_AFTER
, DEPENDENCY_BEFORE
)) {
1696 *deps
= info
.dep
[0];
1700 for (i
= 0; i
< 5; i
++) {
1701 r
= strv_extend_strv(&ret
, info
.dep
[i
], true);
1704 info
.dep
[i
] = strv_free(info
.dep
[i
]);
1713 static int list_dependencies_compare(const void *_a
, const void *_b
) {
1714 const char **a
= (const char**) _a
, **b
= (const char**) _b
;
1716 if (unit_name_to_type(*a
) == UNIT_TARGET
&& unit_name_to_type(*b
) != UNIT_TARGET
)
1718 if (unit_name_to_type(*a
) != UNIT_TARGET
&& unit_name_to_type(*b
) == UNIT_TARGET
)
1721 return strcasecmp(*a
, *b
);
1724 static int list_dependencies_one(
1729 unsigned int branches
) {
1731 _cleanup_strv_free_
char **deps
= NULL
;
1739 r
= strv_extend(units
, name
);
1743 r
= list_dependencies_get_dependencies(bus
, name
, &deps
);
1747 qsort_safe(deps
, strv_length(deps
), sizeof (char*), list_dependencies_compare
);
1749 STRV_FOREACH(c
, deps
) {
1750 if (strv_contains(*units
, *c
)) {
1753 r
= list_dependencies_print("...", level
+ 1, (branches
<< 1) | (c
[1] == NULL
? 0 : 1), 1);
1763 UnitActiveState active_state
= _UNIT_ACTIVE_STATE_INVALID
;
1766 (void) get_state_one_unit(bus
, *c
, &active_state
);
1768 switch (active_state
) {
1770 case UNIT_RELOADING
:
1771 case UNIT_ACTIVATING
:
1772 on
= ansi_highlight_green();
1776 case UNIT_DEACTIVATING
:
1781 on
= ansi_highlight_red();
1785 printf("%s%s%s ", on
, special_glyph(BLACK_CIRCLE
), ansi_normal());
1788 r
= list_dependencies_print(*c
, level
, branches
, c
[1] == NULL
);
1792 if (arg_all
|| unit_name_to_type(*c
) == UNIT_TARGET
) {
1793 r
= list_dependencies_one(bus
, *c
, level
+ 1, units
, (branches
<< 1) | (c
[1] == NULL
? 0 : 1));
1800 strv_remove(*units
, name
);
1805 static int list_dependencies(int argc
, char *argv
[], void *userdata
) {
1806 _cleanup_strv_free_
char **units
= NULL
;
1807 _cleanup_free_
char *unit
= NULL
;
1813 r
= unit_name_mangle(argv
[1], arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
, &unit
);
1815 return log_error_errno(r
, "Failed to mangle unit name: %m");
1819 u
= SPECIAL_DEFAULT_TARGET
;
1821 r
= acquire_bus(BUS_MANAGER
, &bus
);
1825 (void) pager_open(arg_no_pager
, false);
1829 return list_dependencies_one(bus
, u
, 0, &units
, 0);
1832 struct machine_info
{
1836 char *control_group
;
1837 uint32_t n_failed_units
;
1842 static const struct bus_properties_map machine_info_property_map
[] = {
1843 { "SystemState", "s", NULL
, offsetof(struct machine_info
, state
) },
1844 { "NJobs", "u", NULL
, offsetof(struct machine_info
, n_jobs
) },
1845 { "NFailedUnits", "u", NULL
, offsetof(struct machine_info
, n_failed_units
) },
1846 { "ControlGroup", "s", NULL
, offsetof(struct machine_info
, control_group
) },
1847 { "UserspaceTimestamp", "t", NULL
, offsetof(struct machine_info
, timestamp
) },
1851 static void machine_info_clear(struct machine_info
*info
) {
1856 free(info
->control_group
);
1860 static void free_machines_list(struct machine_info
*machine_infos
, int n
) {
1866 for (i
= 0; i
< n
; i
++)
1867 machine_info_clear(&machine_infos
[i
]);
1869 free(machine_infos
);
1872 static int compare_machine_info(const void *a
, const void *b
) {
1873 const struct machine_info
*u
= a
, *v
= b
;
1875 if (u
->is_host
!= v
->is_host
)
1876 return u
->is_host
> v
->is_host
? -1 : 1;
1878 return strcasecmp(u
->name
, v
->name
);
1881 static int get_machine_properties(sd_bus
*bus
, struct machine_info
*mi
) {
1882 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*container
= NULL
;
1888 r
= sd_bus_open_system_machine(&container
, mi
->name
);
1895 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, NULL
, NULL
, mi
);
1902 static bool output_show_machine(const char *name
, char **patterns
) {
1903 return strv_fnmatch_or_empty(patterns
, name
, FNM_NOESCAPE
);
1906 static int get_machine_list(
1908 struct machine_info
**_machine_infos
,
1911 struct machine_info
*machine_infos
= NULL
;
1912 _cleanup_strv_free_
char **m
= NULL
;
1913 _cleanup_free_
char *hn
= NULL
;
1918 hn
= gethostname_malloc();
1922 if (output_show_machine(hn
, patterns
)) {
1923 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1))
1926 machine_infos
[c
].is_host
= true;
1927 machine_infos
[c
].name
= TAKE_PTR(hn
);
1929 (void) get_machine_properties(bus
, &machine_infos
[c
]);
1933 r
= sd_get_machine_names(&m
);
1935 return log_error_errno(r
, "Failed to get machine list: %m");
1937 STRV_FOREACH(i
, m
) {
1938 _cleanup_free_
char *class = NULL
;
1940 if (!output_show_machine(*i
, patterns
))
1943 sd_machine_get_class(*i
, &class);
1944 if (!streq_ptr(class, "container"))
1947 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1)) {
1948 free_machines_list(machine_infos
, c
);
1952 machine_infos
[c
].is_host
= false;
1953 machine_infos
[c
].name
= strdup(*i
);
1954 if (!machine_infos
[c
].name
) {
1955 free_machines_list(machine_infos
, c
);
1959 (void) get_machine_properties(NULL
, &machine_infos
[c
]);
1963 *_machine_infos
= machine_infos
;
1967 static void output_machines_list(struct machine_info
*machine_infos
, unsigned n
) {
1968 struct machine_info
*m
;
1971 namelen
= STRLEN("NAME"),
1972 statelen
= STRLEN("STATE"),
1973 failedlen
= STRLEN("FAILED"),
1974 jobslen
= STRLEN("JOBS");
1976 assert(machine_infos
|| n
== 0);
1978 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
1979 namelen
= MAX(namelen
,
1980 strlen(m
->name
) + (m
->is_host
? STRLEN(" (host)") : 0));
1981 statelen
= MAX(statelen
, strlen_ptr(m
->state
));
1982 failedlen
= MAX(failedlen
, DECIMAL_STR_WIDTH(m
->n_failed_units
));
1983 jobslen
= MAX(jobslen
, DECIMAL_STR_WIDTH(m
->n_jobs
));
1985 if (!arg_plain
&& !streq_ptr(m
->state
, "running"))
1989 if (!arg_no_legend
) {
1993 printf("%-*s %-*s %-*s %-*s\n",
1996 failedlen
, "FAILED",
2000 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
2001 const char *on_state
= "", *off_state
= "";
2002 const char *on_failed
= "", *off_failed
= "";
2003 bool circle
= false;
2005 if (streq_ptr(m
->state
, "degraded")) {
2006 on_state
= ansi_highlight_red();
2007 off_state
= ansi_normal();
2009 } else if (!streq_ptr(m
->state
, "running")) {
2010 on_state
= ansi_highlight_yellow();
2011 off_state
= ansi_normal();
2015 if (m
->n_failed_units
> 0) {
2016 on_failed
= ansi_highlight_red();
2017 off_failed
= ansi_normal();
2019 on_failed
= off_failed
= "";
2022 printf("%s%s%s ", on_state
, circle
? special_glyph(BLACK_CIRCLE
) : " ", off_state
);
2025 printf("%-*s (host) %s%-*s%s %s%*" PRIu32
"%s %*" PRIu32
"\n",
2026 (int) (namelen
- (STRLEN(" (host)"))),
2028 on_state
, statelen
, strna(m
->state
), off_state
,
2029 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
2030 jobslen
, m
->n_jobs
);
2032 printf("%-*s %s%-*s%s %s%*" PRIu32
"%s %*" PRIu32
"\n",
2033 namelen
, strna(m
->name
),
2034 on_state
, statelen
, strna(m
->state
), off_state
,
2035 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
2036 jobslen
, m
->n_jobs
);
2040 printf("\n%u machines listed.\n", n
);
2043 static int list_machines(int argc
, char *argv
[], void *userdata
) {
2044 struct machine_info
*machine_infos
= NULL
;
2048 r
= acquire_bus(BUS_MANAGER
, &bus
);
2052 r
= get_machine_list(bus
, &machine_infos
, strv_skip(argv
, 1));
2056 (void) pager_open(arg_no_pager
, false);
2058 qsort_safe(machine_infos
, r
, sizeof(struct machine_info
), compare_machine_info
);
2059 output_machines_list(machine_infos
, r
);
2060 free_machines_list(machine_infos
, r
);
2065 static int get_default(int argc
, char *argv
[], void *userdata
) {
2066 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2067 _cleanup_free_
char *_path
= NULL
;
2071 if (install_client_side()) {
2072 r
= unit_file_get_default(arg_scope
, arg_root
, &_path
);
2074 return log_error_errno(r
, "Failed to get default target: %m");
2079 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2082 r
= acquire_bus(BUS_MANAGER
, &bus
);
2086 r
= sd_bus_call_method(
2088 "org.freedesktop.systemd1",
2089 "/org/freedesktop/systemd1",
2090 "org.freedesktop.systemd1.Manager",
2096 return log_error_errno(r
, "Failed to get default target: %s", bus_error_message(&error
, r
));
2098 r
= sd_bus_message_read(reply
, "s", &path
);
2100 return bus_log_parse_error(r
);
2104 printf("%s\n", path
);
2109 static int set_default(int argc
, char *argv
[], void *userdata
) {
2110 _cleanup_free_
char *unit
= NULL
;
2111 UnitFileChange
*changes
= NULL
;
2112 unsigned n_changes
= 0;
2118 r
= unit_name_mangle_with_suffix(argv
[1], arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
, ".target", &unit
);
2120 return log_error_errno(r
, "Failed to mangle unit name: %m");
2122 if (install_client_side()) {
2123 r
= unit_file_set_default(arg_scope
, UNIT_FILE_FORCE
, arg_root
, unit
, &changes
, &n_changes
);
2124 unit_file_dump_changes(r
, "set default", changes
, n_changes
, arg_quiet
);
2129 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2130 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2133 polkit_agent_open_maybe();
2135 r
= acquire_bus(BUS_MANAGER
, &bus
);
2139 r
= sd_bus_call_method(
2141 "org.freedesktop.systemd1",
2142 "/org/freedesktop/systemd1",
2143 "org.freedesktop.systemd1.Manager",
2149 return log_error_errno(r
, "Failed to set default target: %s", bus_error_message(&error
, r
));
2151 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
2155 /* Try to reload if enabled */
2157 r
= daemon_reload(argc
, argv
, userdata
);
2163 unit_file_changes_free(changes
, n_changes
);
2168 static int output_waiting_jobs(sd_bus
*bus
, uint32_t id
, const char *method
, const char *prefix
) {
2169 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2170 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2171 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2177 r
= sd_bus_call_method(
2179 "org.freedesktop.systemd1",
2180 "/org/freedesktop/systemd1",
2181 "org.freedesktop.systemd1.Manager",
2187 return log_debug_errno(r
, "Failed to get waiting jobs for job %" PRIu32
, id
);
2189 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2191 return bus_log_parse_error(r
);
2193 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &other_id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0)
2194 printf("%s %u (%s/%s)\n", prefix
, other_id
, name
, type
);
2196 return bus_log_parse_error(r
);
2198 r
= sd_bus_message_exit_container(reply
);
2200 return bus_log_parse_error(r
);
2207 const char *name
, *type
, *state
;
2210 static void output_jobs_list(sd_bus
*bus
, const struct job_info
* jobs
, unsigned n
, bool skipped
) {
2211 unsigned id_len
, unit_len
, type_len
, state_len
;
2212 const struct job_info
*j
;
2213 const char *on
, *off
;
2214 bool shorten
= false;
2216 assert(n
== 0 || jobs
);
2219 if (!arg_no_legend
) {
2220 on
= ansi_highlight_green();
2221 off
= ansi_normal();
2223 printf("%sNo jobs %s.%s\n", on
, skipped
? "listed" : "running", off
);
2228 (void) pager_open(arg_no_pager
, false);
2230 id_len
= STRLEN("JOB");
2231 unit_len
= STRLEN("UNIT");
2232 type_len
= STRLEN("TYPE");
2233 state_len
= STRLEN("STATE");
2235 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2236 uint32_t id
= j
->id
;
2237 assert(j
->name
&& j
->type
&& j
->state
);
2239 id_len
= MAX(id_len
, DECIMAL_STR_WIDTH(id
));
2240 unit_len
= MAX(unit_len
, strlen(j
->name
));
2241 type_len
= MAX(type_len
, strlen(j
->type
));
2242 state_len
= MAX(state_len
, strlen(j
->state
));
2245 if (!arg_full
&& id_len
+ 1 + unit_len
+ type_len
+ 1 + state_len
> columns()) {
2246 unit_len
= MAX(33u, columns() - id_len
- type_len
- state_len
- 3);
2251 printf("%*s %-*s %-*s %-*s\n",
2255 state_len
, "STATE");
2257 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2258 _cleanup_free_
char *e
= NULL
;
2260 if (streq(j
->state
, "running")) {
2261 on
= ansi_highlight();
2262 off
= ansi_normal();
2266 e
= shorten
? ellipsize(j
->name
, unit_len
, 33) : NULL
;
2267 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2269 on
, unit_len
, e
? e
: j
->name
, off
,
2271 on
, state_len
, j
->state
, off
);
2274 output_waiting_jobs(bus
, j
->id
, "GetJobAfter", "\twaiting for job");
2275 if (arg_jobs_before
)
2276 output_waiting_jobs(bus
, j
->id
, "GetJobBefore", "\tblocking job");
2279 if (!arg_no_legend
) {
2280 on
= ansi_highlight();
2281 off
= ansi_normal();
2283 printf("\n%s%u jobs listed%s.\n", on
, n
, off
);
2287 static bool output_show_job(struct job_info
*job
, char **patterns
) {
2288 return strv_fnmatch_or_empty(patterns
, job
->name
, FNM_NOESCAPE
);
2291 static int list_jobs(int argc
, char *argv
[], void *userdata
) {
2292 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2293 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2294 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2295 _cleanup_free_
struct job_info
*jobs
= NULL
;
2301 bool skipped
= false;
2303 r
= acquire_bus(BUS_MANAGER
, &bus
);
2307 r
= sd_bus_call_method(
2309 "org.freedesktop.systemd1",
2310 "/org/freedesktop/systemd1",
2311 "org.freedesktop.systemd1.Manager",
2317 return log_error_errno(r
, "Failed to list jobs: %s", bus_error_message(&error
, r
));
2319 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2321 return bus_log_parse_error(r
);
2323 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0) {
2324 struct job_info job
= { id
, name
, type
, state
};
2326 if (!output_show_job(&job
, strv_skip(argv
, 1))) {
2331 if (!GREEDY_REALLOC(jobs
, size
, c
+ 1))
2337 return bus_log_parse_error(r
);
2339 r
= sd_bus_message_exit_container(reply
);
2341 return bus_log_parse_error(r
);
2343 (void) pager_open(arg_no_pager
, false);
2345 output_jobs_list(bus
, jobs
, c
, skipped
);
2349 static int cancel_job(int argc
, char *argv
[], void *userdata
) {
2355 return trivial_method(argc
, argv
, userdata
);
2357 r
= acquire_bus(BUS_MANAGER
, &bus
);
2361 polkit_agent_open_maybe();
2363 STRV_FOREACH(name
, strv_skip(argv
, 1)) {
2364 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2368 q
= safe_atou32(*name
, &id
);
2370 return log_error_errno(q
, "Failed to parse job id \"%s\": %m", *name
);
2372 q
= sd_bus_call_method(
2374 "org.freedesktop.systemd1",
2375 "/org/freedesktop/systemd1",
2376 "org.freedesktop.systemd1.Manager",
2382 log_error_errno(q
, "Failed to cancel job %"PRIu32
": %s", id
, bus_error_message(&error
, q
));
2391 static int need_daemon_reload(sd_bus
*bus
, const char *unit
) {
2392 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2396 /* We ignore all errors here, since this is used to show a
2399 /* We don't use unit_dbus_path_from_name() directly since we
2400 * don't want to load the unit if it isn't loaded. */
2402 r
= sd_bus_call_method(
2404 "org.freedesktop.systemd1",
2405 "/org/freedesktop/systemd1",
2406 "org.freedesktop.systemd1.Manager",
2414 r
= sd_bus_message_read(reply
, "o", &path
);
2418 r
= sd_bus_get_property_trivial(
2420 "org.freedesktop.systemd1",
2422 "org.freedesktop.systemd1.Unit",
2432 static void warn_unit_file_changed(const char *name
) {
2435 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.",
2436 ansi_highlight_red(),
2439 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user");
2442 static int unit_file_find_path(LookupPaths
*lp
, const char *unit_name
, char **unit_path
) {
2448 STRV_FOREACH(p
, lp
->search_path
) {
2449 _cleanup_free_
char *path
= NULL
, *lpath
= NULL
;
2452 path
= path_join(NULL
, *p
, unit_name
);
2456 r
= chase_symlinks(path
, arg_root
, 0, &lpath
);
2462 return log_error_errno(r
, "Failed to access path '%s': %m", path
);
2465 *unit_path
= TAKE_PTR(lpath
);
2473 static int unit_find_template_path(
2474 const char *unit_name
,
2476 char **fragment_path
,
2479 _cleanup_free_
char *_template
= NULL
;
2482 /* Returns 1 if a fragment was found, 0 if not found, negative on error. */
2484 r
= unit_file_find_path(lp
, unit_name
, fragment_path
);
2486 return r
; /* error or found a real unit */
2488 r
= unit_name_template(unit_name
, &_template
);
2490 return 0; /* not a template, does not exist */
2492 return log_error_errno(r
, "Failed to determine template name: %m");
2494 r
= unit_file_find_path(lp
, _template
, fragment_path
);
2499 *template = TAKE_PTR(_template
);
2504 static int unit_find_paths(
2506 const char *unit_name
,
2508 char **fragment_path
,
2509 char ***dropin_paths
) {
2511 _cleanup_free_
char *path
= NULL
;
2512 _cleanup_strv_free_
char **dropins
= NULL
;
2516 * Finds where the unit is defined on disk. Returns 0 if the unit
2517 * is not found. Returns 1 if it is found, and sets
2518 * - the path to the unit in *path, if it exists on disk,
2519 * - and a strv of existing drop-ins in *dropins,
2520 * if the arg is not NULL and any dropins were found.
2524 assert(fragment_path
);
2527 if (!install_client_side() && !unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
2528 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2529 _cleanup_free_
char *unit
= NULL
;
2531 unit
= unit_dbus_path_from_name(unit_name
);
2535 r
= sd_bus_get_property_string(
2537 "org.freedesktop.systemd1",
2539 "org.freedesktop.systemd1.Unit",
2544 return log_error_errno(r
, "Failed to get FragmentPath: %s", bus_error_message(&error
, r
));
2547 r
= sd_bus_get_property_strv(
2549 "org.freedesktop.systemd1",
2551 "org.freedesktop.systemd1.Unit",
2556 return log_error_errno(r
, "Failed to get DropInPaths: %s", bus_error_message(&error
, r
));
2559 _cleanup_set_free_ Set
*names
= NULL
;
2560 _cleanup_free_
char *template = NULL
;
2562 names
= set_new(NULL
);
2566 r
= unit_find_template_path(unit_name
, lp
, &path
, &template);
2571 /* We found the unit file. If we followed symlinks, this name might be
2572 * different then the unit_name with started with. Look for dropins matching
2573 * that "final" name. */
2574 r
= set_put(names
, basename(path
));
2576 /* No unit file, let's look for dropins matching the original name.
2577 * systemd has fairly complicated rules (based on unit type and provenience),
2578 * which units are allowed not to have the main unit file. We err on the
2579 * side of including too many files, and always try to load dropins. */
2580 r
= set_put(names
, unit_name
);
2582 /* The cases where we allow a unit to exist without the main file are
2583 * never valid for templates. Don't try to load dropins in this case. */
2587 return log_error_errno(r
, "Failed to add unit name: %m");
2590 r
= unit_file_find_dropin_conf_paths(arg_root
, lp
->search_path
,
2591 NULL
, names
, &dropins
);
2599 if (!isempty(path
)) {
2600 *fragment_path
= path
;
2605 if (dropin_paths
&& !strv_isempty(dropins
)) {
2606 *dropin_paths
= dropins
;
2611 if (r
== 0 && !arg_force
)
2612 log_error("No files found for %s.", unit_name
);
2617 static int get_state_one_unit(sd_bus
*bus
, const char *name
, UnitActiveState
*active_state
) {
2618 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2619 _cleanup_free_
char *buf
= NULL
, *path
= NULL
;
2620 UnitActiveState state
;
2624 assert(active_state
);
2626 path
= unit_dbus_path_from_name(name
);
2630 r
= sd_bus_get_property_string(
2632 "org.freedesktop.systemd1",
2634 "org.freedesktop.systemd1.Unit",
2639 return log_error_errno(r
, "Failed to retrieve unit state: %s", bus_error_message(&error
, r
));
2641 state
= unit_active_state_from_string(buf
);
2642 if (state
== _UNIT_ACTIVE_STATE_INVALID
) {
2643 log_error("Invalid unit state '%s' for: %s", buf
, name
);
2647 *active_state
= state
;
2651 static int check_triggering_units(
2655 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2656 _cleanup_free_
char *path
= NULL
, *n
= NULL
, *load_state
= NULL
;
2657 _cleanup_strv_free_
char **triggered_by
= NULL
;
2658 bool print_warning_label
= true;
2659 UnitActiveState active_state
;
2663 r
= unit_name_mangle(name
, 0, &n
);
2665 return log_error_errno(r
, "Failed to mangle unit name: %m");
2667 path
= unit_dbus_path_from_name(n
);
2671 r
= sd_bus_get_property_string(
2673 "org.freedesktop.systemd1",
2675 "org.freedesktop.systemd1.Unit",
2680 return log_error_errno(r
, "Failed to get load state of %s: %s", n
, bus_error_message(&error
, r
));
2682 if (streq(load_state
, "masked"))
2685 r
= sd_bus_get_property_strv(
2687 "org.freedesktop.systemd1",
2689 "org.freedesktop.systemd1.Unit",
2694 return log_error_errno(r
, "Failed to get triggered by array of %s: %s", n
, bus_error_message(&error
, r
));
2696 STRV_FOREACH(i
, triggered_by
) {
2697 r
= get_state_one_unit(bus
, *i
, &active_state
);
2701 if (!IN_SET(active_state
, UNIT_ACTIVE
, UNIT_RELOADING
))
2704 if (print_warning_label
) {
2705 log_warning("Warning: Stopping %s, but it can still be activated by:", n
);
2706 print_warning_label
= false;
2709 log_warning(" %s", *i
);
2715 static const struct {
2718 } unit_actions
[] = {
2719 { "start", "StartUnit" },
2720 { "stop", "StopUnit" },
2721 { "condstop", "StopUnit" },
2722 { "reload", "ReloadUnit" },
2723 { "restart", "RestartUnit" },
2724 { "try-restart", "TryRestartUnit" },
2725 { "condrestart", "TryRestartUnit" },
2726 { "reload-or-restart", "ReloadOrRestartUnit" },
2727 { "try-reload-or-restart", "ReloadOrTryRestartUnit" },
2728 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2729 { "condreload", "ReloadOrTryRestartUnit" },
2730 { "force-reload", "ReloadOrTryRestartUnit" }
2733 static const char *verb_to_method(const char *verb
) {
2736 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2737 if (streq_ptr(unit_actions
[i
].verb
, verb
))
2738 return unit_actions
[i
].method
;
2743 static const char *method_to_verb(const char *method
) {
2746 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2747 if (streq_ptr(unit_actions
[i
].method
, method
))
2748 return unit_actions
[i
].verb
;
2760 static void wait_context_free(WaitContext
*c
) {
2761 c
->match
= sd_bus_slot_unref(c
->match
);
2762 c
->event
= sd_event_unref(c
->event
);
2763 c
->unit_paths
= set_free_free(c
->unit_paths
);
2766 static int on_properties_changed(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
2767 WaitContext
*c
= userdata
;
2771 path
= sd_bus_message_get_path(m
);
2772 if (!set_contains(c
->unit_paths
, path
))
2775 /* Check if ActiveState changed to inactive/failed */
2776 /* (s interface, a{sv} changed_properties, as invalidated_properties) */
2777 r
= sd_bus_message_skip(m
, "s");
2779 return bus_log_parse_error(r
);
2781 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "{sv}");
2783 return bus_log_parse_error(r
);
2785 while ((r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
2788 r
= sd_bus_message_read(m
, "s", &s
);
2790 return bus_log_parse_error(r
);
2792 if (streq(s
, "ActiveState")) {
2795 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, "s");
2797 return bus_log_parse_error(r
);
2799 r
= sd_bus_message_read(m
, "s", &s
);
2801 return bus_log_parse_error(r
);
2803 is_failed
= streq(s
, "failed");
2804 if (streq(s
, "inactive") || is_failed
) {
2805 log_debug("%s became %s, dropping from --wait tracking", path
, s
);
2806 free(set_remove(c
->unit_paths
, path
));
2807 c
->any_failed
= c
->any_failed
|| is_failed
;
2809 log_debug("ActiveState on %s changed to %s", path
, s
);
2811 break; /* no need to dissect the rest of the message */
2813 /* other property */
2814 r
= sd_bus_message_skip(m
, "v");
2816 return bus_log_parse_error(r
);
2818 r
= sd_bus_message_exit_container(m
);
2820 return bus_log_parse_error(r
);
2823 return bus_log_parse_error(r
);
2825 if (set_isempty(c
->unit_paths
))
2826 sd_event_exit(c
->event
, EXIT_SUCCESS
);
2831 static int start_unit_one(
2836 sd_bus_error
*error
,
2838 WaitContext
*wait_context
) {
2840 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2850 _cleanup_free_
char *unit_path
= NULL
;
2852 log_debug("Watching for property changes of %s", name
);
2853 r
= sd_bus_call_method(
2855 "org.freedesktop.systemd1",
2856 "/org/freedesktop/systemd1",
2857 "org.freedesktop.systemd1.Manager",
2863 return log_error_errno(r
, "Failed to RefUnit %s: %s", name
, bus_error_message(error
, r
));
2865 unit_path
= unit_dbus_path_from_name(name
);
2869 r
= set_put_strdup(wait_context
->unit_paths
, unit_path
);
2871 return log_error_errno(r
, "Failed to add unit path %s to set: %m", unit_path
);
2873 r
= sd_bus_match_signal_async(bus
,
2874 &wait_context
->match
,
2877 "org.freedesktop.DBus.Properties",
2878 "PropertiesChanged",
2879 on_properties_changed
, NULL
, wait_context
);
2881 return log_error_errno(r
, "Failed to request match for PropertiesChanged signal: %m");
2884 log_debug("%s dbus call org.freedesktop.systemd1.Manager %s(%s, %s)",
2885 arg_dry_run
? "Would execute" : "Executing",
2886 method
, name
, mode
);
2890 r
= sd_bus_call_method(
2892 "org.freedesktop.systemd1",
2893 "/org/freedesktop/systemd1",
2894 "org.freedesktop.systemd1.Manager",
2902 /* There's always a fallback possible for legacy actions. */
2903 if (arg_action
!= ACTION_SYSTEMCTL
)
2906 verb
= method_to_verb(method
);
2908 log_error("Failed to %s %s: %s", verb
, name
, bus_error_message(error
, r
));
2910 if (!sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) &&
2911 !sd_bus_error_has_name(error
, BUS_ERROR_UNIT_MASKED
) &&
2912 !sd_bus_error_has_name(error
, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE
))
2913 log_error("See %s logs and 'systemctl%s status%s %s' for details.",
2914 arg_scope
== UNIT_FILE_SYSTEM
? "system" : "user",
2915 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user",
2916 name
[0] == '-' ? " --" : "",
2922 r
= sd_bus_message_read(reply
, "o", &path
);
2924 return bus_log_parse_error(r
);
2926 if (need_daemon_reload(bus
, name
) > 0)
2927 warn_unit_file_changed(name
);
2930 log_debug("Adding %s to the set", path
);
2931 r
= bus_wait_for_jobs_add(w
, path
);
2939 static int expand_names(sd_bus
*bus
, char **names
, const char* suffix
, char ***ret
) {
2940 _cleanup_strv_free_
char **mangled
= NULL
, **globs
= NULL
;
2947 STRV_FOREACH(name
, names
) {
2949 UnitNameMangle options
= UNIT_NAME_MANGLE_GLOB
| (arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
);
2952 r
= unit_name_mangle_with_suffix(*name
, options
, suffix
, &t
);
2954 r
= unit_name_mangle(*name
, options
, &t
);
2956 return log_error_errno(r
, "Failed to mangle name: %m");
2958 if (string_is_glob(t
))
2959 r
= strv_consume(&globs
, t
);
2961 r
= strv_consume(&mangled
, t
);
2966 /* Query the manager only if any of the names are a glob, since
2967 * this is fairly expensive */
2968 if (!strv_isempty(globs
)) {
2969 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2970 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
2971 size_t allocated
, n
;
2973 r
= get_unit_list(bus
, NULL
, globs
, &unit_infos
, 0, &reply
);
2977 n
= strv_length(mangled
);
2980 for (i
= 0; i
< r
; i
++) {
2981 if (!GREEDY_REALLOC(mangled
, allocated
, n
+2))
2984 mangled
[n
] = strdup(unit_infos
[i
].id
);
2988 mangled
[++n
] = NULL
;
2993 mangled
= NULL
; /* do not free */
2998 static const struct {
3002 } action_table
[_ACTION_MAX
] = {
3003 [ACTION_HALT
] = { SPECIAL_HALT_TARGET
, "halt", "replace-irreversibly" },
3004 [ACTION_POWEROFF
] = { SPECIAL_POWEROFF_TARGET
, "poweroff", "replace-irreversibly" },
3005 [ACTION_REBOOT
] = { SPECIAL_REBOOT_TARGET
, "reboot", "replace-irreversibly" },
3006 [ACTION_KEXEC
] = { SPECIAL_KEXEC_TARGET
, "kexec", "replace-irreversibly" },
3007 [ACTION_RUNLEVEL2
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
3008 [ACTION_RUNLEVEL3
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
3009 [ACTION_RUNLEVEL4
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
3010 [ACTION_RUNLEVEL5
] = { SPECIAL_GRAPHICAL_TARGET
, NULL
, "isolate" },
3011 [ACTION_RESCUE
] = { SPECIAL_RESCUE_TARGET
, "rescue", "isolate" },
3012 [ACTION_EMERGENCY
] = { SPECIAL_EMERGENCY_TARGET
, "emergency", "isolate" },
3013 [ACTION_DEFAULT
] = { SPECIAL_DEFAULT_TARGET
, "default", "isolate" },
3014 [ACTION_EXIT
] = { SPECIAL_EXIT_TARGET
, "exit", "replace-irreversibly" },
3015 [ACTION_SUSPEND
] = { SPECIAL_SUSPEND_TARGET
, "suspend", "replace-irreversibly" },
3016 [ACTION_HIBERNATE
] = { SPECIAL_HIBERNATE_TARGET
, "hibernate", "replace-irreversibly" },
3017 [ACTION_HYBRID_SLEEP
] = { SPECIAL_HYBRID_SLEEP_TARGET
, "hybrid-sleep", "replace-irreversibly" },
3018 [ACTION_SUSPEND_TO_HIBERNATE
] = { SPECIAL_SUSPEND_TO_HIBERNATE_TARGET
, "suspend-to-hibernate", "replace-irreversibly" },
3021 static enum action
verb_to_action(const char *verb
) {
3024 for (i
= 0; i
< _ACTION_MAX
; i
++)
3025 if (streq_ptr(action_table
[i
].verb
, verb
))
3028 return _ACTION_INVALID
;
3031 static int start_unit(int argc
, char *argv
[], void *userdata
) {
3032 _cleanup_(bus_wait_for_jobs_freep
) BusWaitForJobs
*w
= NULL
;
3033 const char *method
, *mode
, *one_name
, *suffix
= NULL
;
3034 _cleanup_strv_free_
char **names
= NULL
;
3036 _cleanup_(wait_context_free
) WaitContext wait_context
= {};
3040 if (arg_wait
&& !STR_IN_SET(argv
[0], "start", "restart")) {
3041 log_error("--wait may only be used with the 'start' or 'restart' commands.");
3045 /* we cannot do sender tracking on the private bus, so we need the full
3046 * one for RefUnit to implement --wait */
3047 r
= acquire_bus(arg_wait
? BUS_FULL
: BUS_MANAGER
, &bus
);
3051 ask_password_agent_open_if_enabled();
3052 polkit_agent_open_maybe();
3054 if (arg_action
== ACTION_SYSTEMCTL
) {
3057 action
= verb_to_action(argv
[0]);
3059 if (action
!= _ACTION_INVALID
) {
3060 method
= "StartUnit";
3061 mode
= action_table
[action
].mode
;
3062 one_name
= action_table
[action
].target
;
3064 if (streq(argv
[0], "isolate")) {
3065 method
= "StartUnit";
3070 method
= verb_to_method(argv
[0]);
3071 mode
= arg_job_mode
;
3076 assert(arg_action
>= 0 && arg_action
< _ACTION_MAX
);
3077 assert(action_table
[arg_action
].target
);
3078 assert(action_table
[arg_action
].mode
);
3080 method
= "StartUnit";
3081 mode
= action_table
[arg_action
].mode
;
3082 one_name
= action_table
[arg_action
].target
;
3086 names
= strv_new(one_name
, NULL
);
3088 r
= expand_names(bus
, strv_skip(argv
, 1), suffix
, &names
);
3090 return log_error_errno(r
, "Failed to expand names: %m");
3093 if (!arg_no_block
) {
3094 r
= bus_wait_for_jobs_new(bus
, &w
);
3096 return log_error_errno(r
, "Could not watch jobs: %m");
3100 wait_context
.unit_paths
= set_new(&string_hash_ops
);
3101 if (!wait_context
.unit_paths
)
3104 r
= sd_bus_call_method_async(
3107 "org.freedesktop.systemd1",
3108 "/org/freedesktop/systemd1",
3109 "org.freedesktop.systemd1.Manager",
3114 return log_error_errno(r
, "Failed to enable subscription: %m");
3115 r
= sd_event_default(&wait_context
.event
);
3117 return log_error_errno(r
, "Failed to allocate event loop: %m");
3118 r
= sd_bus_attach_event(bus
, wait_context
.event
, 0);
3120 return log_error_errno(r
, "Failed to attach bus to event loop: %m");
3123 STRV_FOREACH(name
, names
) {
3124 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3127 q
= start_unit_one(bus
, method
, *name
, mode
, &error
, w
, arg_wait
? &wait_context
: NULL
);
3128 if (r
>= 0 && q
< 0)
3129 r
= translate_bus_error_to_exit_status(q
, &error
);
3132 if (!arg_no_block
) {
3133 int q
, arg_count
= 0;
3134 const char* extra_args
[4] = {};
3136 if (arg_scope
!= UNIT_FILE_SYSTEM
)
3137 extra_args
[arg_count
++] = "--user";
3139 assert(IN_SET(arg_transport
, BUS_TRANSPORT_LOCAL
, BUS_TRANSPORT_REMOTE
, BUS_TRANSPORT_MACHINE
));
3140 if (arg_transport
== BUS_TRANSPORT_REMOTE
) {
3141 extra_args
[arg_count
++] = "-H";
3142 extra_args
[arg_count
++] = arg_host
;
3143 } else if (arg_transport
== BUS_TRANSPORT_MACHINE
) {
3144 extra_args
[arg_count
++] = "-M";
3145 extra_args
[arg_count
++] = arg_host
;
3148 q
= bus_wait_for_jobs(w
, arg_quiet
, extra_args
);
3152 /* When stopping units, warn if they can still be triggered by
3153 * another active unit (socket, path, timer) */
3154 if (!arg_quiet
&& streq(method
, "StopUnit"))
3155 STRV_FOREACH(name
, names
)
3156 check_triggering_units(bus
, *name
);
3159 if (r
>= 0 && arg_wait
) {
3161 q
= sd_event_loop(wait_context
.event
);
3163 return log_error_errno(q
, "Failed to run event loop: %m");
3164 if (wait_context
.any_failed
)
3172 static int logind_set_wall_message(void) {
3173 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3175 _cleanup_free_
char *m
= NULL
;
3178 r
= acquire_bus(BUS_FULL
, &bus
);
3182 m
= strv_join(arg_wall
, " ");
3186 log_debug("%s wall message \"%s\".", arg_dry_run
? "Would set" : "Setting", m
);
3190 r
= sd_bus_call_method(
3192 "org.freedesktop.login1",
3193 "/org/freedesktop/login1",
3194 "org.freedesktop.login1.Manager",
3203 return log_warning_errno(r
, "Failed to set wall message, ignoring: %s", bus_error_message(&error
, r
));
3208 /* Ask systemd-logind, which might grant access to unprivileged users
3209 * through PolicyKit */
3210 static int logind_reboot(enum action a
) {
3212 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3213 const char *method
, *description
;
3217 r
= acquire_bus(BUS_FULL
, &bus
);
3223 case ACTION_POWEROFF
:
3224 method
= "PowerOff";
3225 description
= "power off system";
3230 description
= "reboot system";
3235 description
= "halt system";
3238 case ACTION_SUSPEND
:
3240 description
= "suspend system";
3243 case ACTION_HIBERNATE
:
3244 method
= "Hibernate";
3245 description
= "hibernate system";
3248 case ACTION_HYBRID_SLEEP
:
3249 method
= "HybridSleep";
3250 description
= "put system into hybrid sleep";
3253 case ACTION_SUSPEND_TO_HIBERNATE
:
3254 method
= "SuspendToHibernate";
3255 description
= "put system into suspend followed by hibernate";
3262 polkit_agent_open_maybe();
3263 (void) logind_set_wall_message();
3265 log_debug("%s org.freedesktop.login1.Manager %s dbus call.", arg_dry_run
? "Would execute" : "Executing", method
);
3269 r
= sd_bus_call_method(
3271 "org.freedesktop.login1",
3272 "/org/freedesktop/login1",
3273 "org.freedesktop.login1.Manager",
3277 "b", arg_ask_password
);
3279 return log_error_errno(r
, "Failed to %s via logind: %s", description
, bus_error_message(&error
, r
));
3287 static int logind_check_inhibitors(enum action a
) {
3289 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
3290 _cleanup_strv_free_
char **sessions
= NULL
;
3291 const char *what
, *who
, *why
, *mode
;
3298 if (arg_ignore_inhibitors
|| arg_force
> 0)
3310 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
3313 r
= acquire_bus(BUS_FULL
, &bus
);
3317 r
= sd_bus_call_method(
3319 "org.freedesktop.login1",
3320 "/org/freedesktop/login1",
3321 "org.freedesktop.login1.Manager",
3327 /* If logind is not around, then there are no inhibitors... */
3330 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssuu)");
3332 return bus_log_parse_error(r
);
3334 while ((r
= sd_bus_message_read(reply
, "(ssssuu)", &what
, &who
, &why
, &mode
, &uid
, &pid
)) > 0) {
3335 _cleanup_free_
char *comm
= NULL
, *user
= NULL
;
3336 _cleanup_strv_free_
char **sv
= NULL
;
3338 if (!streq(mode
, "block"))
3341 sv
= strv_split(what
, ":");
3345 if (!pid_is_valid((pid_t
) pid
)) {
3346 log_error("Invalid PID "PID_FMT
".", (pid_t
) pid
);
3350 if (!strv_contains(sv
,
3355 ACTION_KEXEC
) ? "shutdown" : "sleep"))
3358 get_process_comm(pid
, &comm
);
3359 user
= uid_to_name(uid
);
3361 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT
" \"%s\", user %s), reason is \"%s\".",
3362 who
, (pid_t
) pid
, strna(comm
), strna(user
), why
);
3367 return bus_log_parse_error(r
);
3369 r
= sd_bus_message_exit_container(reply
);
3371 return bus_log_parse_error(r
);
3373 /* Check for current sessions */
3374 sd_get_sessions(&sessions
);
3375 STRV_FOREACH(s
, sessions
) {
3376 _cleanup_free_
char *type
= NULL
, *tty
= NULL
, *seat
= NULL
, *user
= NULL
, *service
= NULL
, *class = NULL
;
3378 if (sd_session_get_uid(*s
, &uid
) < 0 || uid
== getuid())
3381 if (sd_session_get_class(*s
, &class) < 0 || !streq(class, "user"))
3384 if (sd_session_get_type(*s
, &type
) < 0 || !STR_IN_SET(type
, "x11", "wayland", "tty", "mir"))
3387 sd_session_get_tty(*s
, &tty
);
3388 sd_session_get_seat(*s
, &seat
);
3389 sd_session_get_service(*s
, &service
);
3390 user
= uid_to_name(uid
);
3392 log_warning("User %s is logged in on %s.", strna(user
), isempty(tty
) ? (isempty(seat
) ? strna(service
) : seat
) : tty
);
3399 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
3400 action_table
[a
].verb
);
3408 static int logind_prepare_firmware_setup(void) {
3410 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3414 r
= acquire_bus(BUS_FULL
, &bus
);
3418 r
= sd_bus_call_method(
3420 "org.freedesktop.login1",
3421 "/org/freedesktop/login1",
3422 "org.freedesktop.login1.Manager",
3423 "SetRebootToFirmwareSetup",
3428 return log_error_errno(r
, "Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error
, r
));
3432 log_error("Cannot remotely indicate to EFI to boot into setup mode.");
3437 static int prepare_firmware_setup(void) {
3440 if (!arg_firmware_setup
)
3443 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
3445 r
= efi_set_reboot_to_firmware(true);
3447 log_debug_errno(r
, "Cannot indicate to EFI to boot into setup mode, will retry via logind: %m");
3452 return logind_prepare_firmware_setup();
3455 static int load_kexec_kernel(void) {
3456 _cleanup_(boot_config_free
) BootConfig config
= {};
3457 _cleanup_free_
char *where
= NULL
, *kernel
= NULL
, *initrd
= NULL
, *options
= NULL
;
3462 if (kexec_loaded()) {
3463 log_debug("Kexec kernel already loaded.");
3467 if (access(KEXEC
, X_OK
) < 0)
3468 return log_error_errno(errno
, KEXEC
" is not available: %m");
3470 r
= find_esp_and_warn(arg_esp_path
, false, &where
, NULL
, NULL
, NULL
, NULL
);
3471 if (r
== -ENOKEY
) /* find_esp_and_warn() doesn't warn about this case */
3472 return log_error_errno(r
, "Cannot find the ESP partition mount point.");
3473 if (r
< 0) /* But it logs about all these cases, hence don't log here again */
3476 r
= boot_entries_load_config(where
, &config
);
3478 return log_error_errno(r
, "Failed to load bootspec config from \"%s/loader\": %m", where
);
3480 if (config
.default_entry
< 0) {
3481 log_error("No entry suitable as default, refusing to guess.");
3484 e
= &config
.entries
[config
.default_entry
];
3486 if (strv_length(e
->initrd
) > 1) {
3487 log_error("Boot entry specifies multiple initrds, which is not supported currently.");
3491 kernel
= path_join(NULL
, where
, e
->kernel
);
3492 if (!strv_isempty(e
->initrd
))
3493 initrd
= path_join(NULL
, where
, *e
->initrd
);
3494 options
= strv_join(e
->options
, " ");
3498 log_full(arg_quiet
? LOG_DEBUG
: LOG_INFO
,
3499 "%s "KEXEC
" --load \"%s\" --append \"%s\"%s%s%s",
3500 arg_dry_run
? "Would run" : "Running",
3503 initrd
? " --initrd \"" : NULL
, strempty(initrd
), initrd
? "\"" : "");
3507 r
= safe_fork("(kexec)", FORK_RESET_SIGNALS
|FORK_DEATHSIG
|FORK_LOG
, &pid
);
3511 const char* const args
[] = {
3514 "--append", options
,
3515 initrd
? "--initrd" : NULL
, initrd
,
3519 execv(args
[0], (char * const *) args
);
3520 _exit(EXIT_FAILURE
);
3523 r
= wait_for_terminate_and_check("kexec", pid
, WAIT_LOG
);
3527 /* Command failed */
3532 static int set_exit_code(uint8_t code
) {
3533 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3537 r
= acquire_bus(BUS_MANAGER
, &bus
);
3541 r
= sd_bus_call_method(
3543 "org.freedesktop.systemd1",
3544 "/org/freedesktop/systemd1",
3545 "org.freedesktop.systemd1.Manager",
3551 return log_error_errno(r
, "Failed to set exit code: %s", bus_error_message(&error
, r
));
3556 static int start_special(int argc
, char *argv
[], void *userdata
) {
3559 bool termination_action
; /* an action that terminates the manager,
3560 * can be performed also by signal. */
3564 a
= verb_to_action(argv
[0]);
3566 r
= logind_check_inhibitors(a
);
3570 if (arg_force
>= 2) {
3576 r
= prepare_firmware_setup();
3580 if (a
== ACTION_REBOOT
&& argc
> 1) {
3581 r
= update_reboot_parameter_and_warn(argv
[1]);
3585 } else if (a
== ACTION_KEXEC
) {
3586 r
= load_kexec_kernel();
3587 if (r
< 0 && arg_force
>= 1)
3588 log_notice("Failed to load kexec kernel, continuing without.");
3592 } else if (a
== ACTION_EXIT
&& argc
> 1) {
3595 /* If the exit code is not given on the command line,
3596 * don't reset it to zero: just keep it as it might
3597 * have been set previously. */
3599 r
= safe_atou8(argv
[1], &code
);
3601 return log_error_errno(r
, "Invalid exit code.");
3603 r
= set_exit_code(code
);
3608 termination_action
= IN_SET(a
,
3612 if (termination_action
&& arg_force
>= 2)
3615 if (arg_force
>= 1 &&
3616 (termination_action
|| IN_SET(a
, ACTION_KEXEC
, ACTION_EXIT
)))
3617 r
= trivial_method(argc
, argv
, userdata
);
3619 /* First try logind, to allow authentication with polkit */
3626 ACTION_HYBRID_SLEEP
,
3627 ACTION_SUSPEND_TO_HIBERNATE
)) {
3629 r
= logind_reboot(a
);
3632 if (IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
3633 /* requested operation is not supported or already in progress */
3636 /* On all other errors, try low-level operation. In order to minimize the difference between
3637 * operation with and without logind, we explicitly enable non-blocking mode for this, as
3638 * logind's shutdown operations are always non-blocking. */
3640 arg_no_block
= true;
3642 } else if (IN_SET(a
, ACTION_EXIT
, ACTION_KEXEC
))
3643 /* Since exit/kexec are so close in behaviour to power-off/reboot, let's also make them
3644 * asynchronous, in order to not confuse the user needlessly with unexpected behaviour. */
3645 arg_no_block
= true;
3647 r
= start_unit(argc
, argv
, userdata
);
3650 if (termination_action
&& arg_force
< 2 &&
3651 IN_SET(r
, -ENOENT
, -ETIMEDOUT
))
3652 log_notice("It is possible to perform action directly, see discussion of --force --force in man:systemctl(1).");
3657 static int start_system_special(int argc
, char *argv
[], void *userdata
) {
3658 /* Like start_special above, but raises an error when running in user mode */
3660 if (arg_scope
!= UNIT_FILE_SYSTEM
) {
3661 log_error("Bad action for %s mode.",
3662 arg_scope
== UNIT_FILE_GLOBAL
? "--global" : "--user");
3666 return start_special(argc
, argv
, userdata
);
3669 static int check_unit_generic(int code
, const UnitActiveState good_states
[], int nb_states
, char **args
) {
3670 _cleanup_strv_free_
char **names
= NULL
;
3671 UnitActiveState active_state
;
3677 r
= acquire_bus(BUS_MANAGER
, &bus
);
3681 r
= expand_names(bus
, args
, NULL
, &names
);
3683 return log_error_errno(r
, "Failed to expand names: %m");
3685 STRV_FOREACH(name
, names
) {
3686 r
= get_state_one_unit(bus
, *name
, &active_state
);
3691 puts(unit_active_state_to_string(active_state
));
3693 for (i
= 0; i
< nb_states
; ++i
)
3694 if (good_states
[i
] == active_state
)
3698 /* use the given return code for the case that we won't find
3699 * any unit which matches the list */
3700 return found
? 0 : code
;
3703 static int check_unit_active(int argc
, char *argv
[], void *userdata
) {
3704 const UnitActiveState states
[] = { UNIT_ACTIVE
, UNIT_RELOADING
};
3705 /* According to LSB: 3, "program is not running" */
3706 return check_unit_generic(EXIT_PROGRAM_NOT_RUNNING
, states
, ELEMENTSOF(states
), strv_skip(argv
, 1));
3709 static int check_unit_failed(int argc
, char *argv
[], void *userdata
) {
3710 const UnitActiveState states
[] = { UNIT_FAILED
};
3711 return check_unit_generic(EXIT_PROGRAM_DEAD_AND_PID_EXISTS
, states
, ELEMENTSOF(states
), strv_skip(argv
, 1));
3714 static int kill_unit(int argc
, char *argv
[], void *userdata
) {
3715 _cleanup_strv_free_
char **names
= NULL
;
3716 char *kill_who
= NULL
, **name
;
3720 r
= acquire_bus(BUS_MANAGER
, &bus
);
3724 polkit_agent_open_maybe();
3727 arg_kill_who
= "all";
3729 /* --fail was specified */
3730 if (streq(arg_job_mode
, "fail"))
3731 kill_who
= strjoina(arg_kill_who
, "-fail");
3733 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
3735 return log_error_errno(r
, "Failed to expand names: %m");
3737 STRV_FOREACH(name
, names
) {
3738 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3740 q
= sd_bus_call_method(
3742 "org.freedesktop.systemd1",
3743 "/org/freedesktop/systemd1",
3744 "org.freedesktop.systemd1.Manager",
3748 "ssi", *name
, kill_who
? kill_who
: arg_kill_who
, arg_signal
);
3750 log_error_errno(q
, "Failed to kill unit %s: %s", *name
, bus_error_message(&error
, q
));
3759 typedef struct ExecStatusInfo
{
3767 usec_t start_timestamp
;
3768 usec_t exit_timestamp
;
3773 LIST_FIELDS(struct ExecStatusInfo
, exec
);
3776 static void exec_status_info_free(ExecStatusInfo
*i
) {
3785 static int exec_status_info_deserialize(sd_bus_message
*m
, ExecStatusInfo
*i
) {
3786 uint64_t start_timestamp
, exit_timestamp
, start_timestamp_monotonic
, exit_timestamp_monotonic
;
3789 int32_t code
, status
;
3795 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_STRUCT
, "sasbttttuii");
3797 return bus_log_parse_error(r
);
3801 r
= sd_bus_message_read(m
, "s", &path
);
3803 return bus_log_parse_error(r
);
3805 i
->path
= strdup(path
);
3809 r
= sd_bus_message_read_strv(m
, &i
->argv
);
3811 return bus_log_parse_error(r
);
3813 r
= sd_bus_message_read(m
,
3816 &start_timestamp
, &start_timestamp_monotonic
,
3817 &exit_timestamp
, &exit_timestamp_monotonic
,
3821 return bus_log_parse_error(r
);
3824 i
->start_timestamp
= (usec_t
) start_timestamp
;
3825 i
->exit_timestamp
= (usec_t
) exit_timestamp
;
3826 i
->pid
= (pid_t
) pid
;
3830 r
= sd_bus_message_exit_container(m
);
3832 return bus_log_parse_error(r
);
3837 typedef struct UnitCondition
{
3844 LIST_FIELDS(struct UnitCondition
, conditions
);
3847 static void unit_condition_free(UnitCondition
*c
) {
3856 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitCondition
*, unit_condition_free
);
3858 typedef struct UnitStatusInfo
{
3860 const char *load_state
;
3861 const char *active_state
;
3862 const char *sub_state
;
3863 const char *unit_file_state
;
3864 const char *unit_file_preset
;
3866 const char *description
;
3867 const char *following
;
3869 char **documentation
;
3871 const char *fragment_path
;
3872 const char *source_path
;
3873 const char *control_group
;
3875 char **dropin_paths
;
3877 const char *load_error
;
3880 usec_t inactive_exit_timestamp
;
3881 usec_t inactive_exit_timestamp_monotonic
;
3882 usec_t active_enter_timestamp
;
3883 usec_t active_exit_timestamp
;
3884 usec_t inactive_enter_timestamp
;
3886 bool need_daemon_reload
;
3892 const char *status_text
;
3893 const char *pid_file
;
3897 usec_t start_timestamp
;
3898 usec_t exit_timestamp
;
3900 int exit_code
, exit_status
;
3902 usec_t condition_timestamp
;
3903 bool condition_result
;
3904 LIST_HEAD(UnitCondition
, conditions
);
3906 usec_t assert_timestamp
;
3908 bool failed_assert_trigger
;
3909 bool failed_assert_negate
;
3910 const char *failed_assert
;
3911 const char *failed_assert_parameter
;
3912 usec_t next_elapse_real
;
3913 usec_t next_elapse_monotonic
;
3916 unsigned n_accepted
;
3917 unsigned n_connections
;
3920 /* Pairs of type, path */
3924 const char *sysfs_path
;
3926 /* Mount, Automount */
3933 uint64_t memory_current
;
3934 uint64_t memory_low
;
3935 uint64_t memory_high
;
3936 uint64_t memory_max
;
3937 uint64_t memory_swap_max
;
3938 uint64_t memory_limit
;
3939 uint64_t cpu_usage_nsec
;
3940 uint64_t tasks_current
;
3943 uint64_t ip_ingress_bytes
;
3944 uint64_t ip_egress_bytes
;
3946 LIST_HEAD(ExecStatusInfo
, exec
);
3949 static void unit_status_info_free(UnitStatusInfo
*info
) {
3953 strv_free(info
->documentation
);
3954 strv_free(info
->dropin_paths
);
3955 strv_free(info
->listen
);
3957 while ((c
= info
->conditions
)) {
3958 LIST_REMOVE(conditions
, info
->conditions
, c
);
3959 unit_condition_free(c
);
3962 while ((p
= info
->exec
)) {
3963 LIST_REMOVE(exec
, info
->exec
, p
);
3964 exec_status_info_free(p
);
3968 static void print_status_info(
3974 const char *active_on
, *active_off
, *on
, *off
, *ss
;
3976 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], *s1
;
3977 char since2
[FORMAT_TIMESTAMP_MAX
], *s2
;
3984 /* This shows pretty information about a unit. See
3985 * print_property() for a low-level property printer */
3987 if (streq_ptr(i
->active_state
, "failed")) {
3988 active_on
= ansi_highlight_red();
3989 active_off
= ansi_normal();
3990 } else if (STRPTR_IN_SET(i
->active_state
, "active", "reloading")) {
3991 active_on
= ansi_highlight_green();
3992 active_off
= ansi_normal();
3994 active_on
= active_off
= "";
3996 printf("%s%s%s %s", active_on
, special_glyph(BLACK_CIRCLE
), active_off
, strna(i
->id
));
3998 if (i
->description
&& !streq_ptr(i
->id
, i
->description
))
3999 printf(" - %s", i
->description
);
4004 printf(" Follow: unit currently follows state of %s\n", i
->following
);
4006 if (streq_ptr(i
->load_state
, "error")) {
4007 on
= ansi_highlight_red();
4008 off
= ansi_normal();
4012 path
= i
->source_path
? i
->source_path
: i
->fragment_path
;
4014 if (i
->load_error
!= 0)
4015 printf(" Loaded: %s%s%s (Reason: %s)\n",
4016 on
, strna(i
->load_state
), off
, i
->load_error
);
4017 else if (path
&& !isempty(i
->unit_file_state
) && !isempty(i
->unit_file_preset
) &&
4018 !STR_IN_SET(i
->unit_file_state
, "generated", "transient"))
4019 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
4020 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
, i
->unit_file_preset
);
4021 else if (path
&& !isempty(i
->unit_file_state
))
4022 printf(" Loaded: %s%s%s (%s; %s)\n",
4023 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
);
4025 printf(" Loaded: %s%s%s (%s)\n",
4026 on
, strna(i
->load_state
), off
, path
);
4028 printf(" Loaded: %s%s%s\n",
4029 on
, strna(i
->load_state
), off
);
4032 printf("Transient: yes\n");
4034 if (!strv_isempty(i
->dropin_paths
)) {
4035 _cleanup_free_
char *dir
= NULL
;
4039 STRV_FOREACH(dropin
, i
->dropin_paths
) {
4040 if (! dir
|| last
) {
4041 printf(dir
? " " : " Drop-In: ");
4045 dir
= dirname_malloc(*dropin
);
4051 printf("%s\n %s", dir
,
4052 special_glyph(TREE_RIGHT
));
4055 last
= ! (*(dropin
+ 1) && startswith(*(dropin
+ 1), dir
));
4057 printf("%s%s", basename(*dropin
), last
? "\n" : ", ");
4061 ss
= streq_ptr(i
->active_state
, i
->sub_state
) ? NULL
: i
->sub_state
;
4063 printf(" Active: %s%s (%s)%s",
4064 active_on
, strna(i
->active_state
), ss
, active_off
);
4066 printf(" Active: %s%s%s",
4067 active_on
, strna(i
->active_state
), active_off
);
4069 if (!isempty(i
->result
) && !streq(i
->result
, "success"))
4070 printf(" (Result: %s)", i
->result
);
4072 timestamp
= STRPTR_IN_SET(i
->active_state
, "active", "reloading") ? i
->active_enter_timestamp
:
4073 STRPTR_IN_SET(i
->active_state
, "inactive", "failed") ? i
->inactive_enter_timestamp
:
4074 STRPTR_IN_SET(i
->active_state
, "activating") ? i
->inactive_exit_timestamp
:
4075 i
->active_exit_timestamp
;
4077 s1
= format_timestamp_relative(since1
, sizeof(since1
), timestamp
);
4078 s2
= format_timestamp(since2
, sizeof(since2
), timestamp
);
4081 printf(" since %s; %s\n", s2
, s1
);
4083 printf(" since %s\n", s2
);
4087 if (endswith(i
->id
, ".timer")) {
4088 char tstamp1
[FORMAT_TIMESTAMP_RELATIVE_MAX
],
4089 tstamp2
[FORMAT_TIMESTAMP_MAX
];
4090 char *next_rel_time
, *next_time
;
4091 dual_timestamp nw
, next
= {i
->next_elapse_real
,
4092 i
->next_elapse_monotonic
};
4095 printf(" Trigger: ");
4097 dual_timestamp_get(&nw
);
4098 next_elapse
= calc_next_elapse(&nw
, &next
);
4099 next_rel_time
= format_timestamp_relative(tstamp1
,
4102 next_time
= format_timestamp(tstamp2
,
4106 if (next_time
&& next_rel_time
)
4107 printf("%s; %s\n", next_time
, next_rel_time
);
4112 if (!i
->condition_result
&& i
->condition_timestamp
> 0) {
4116 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->condition_timestamp
);
4117 s2
= format_timestamp(since2
, sizeof(since2
), i
->condition_timestamp
);
4119 printf("Condition: start %scondition failed%s at %s%s%s\n",
4120 ansi_highlight_yellow(), ansi_normal(),
4121 s2
, s1
? "; " : "", strempty(s1
));
4123 LIST_FOREACH(conditions
, c
, i
->conditions
)
4124 if (c
->tristate
< 0)
4127 LIST_FOREACH(conditions
, c
, i
->conditions
)
4128 if (c
->tristate
< 0)
4129 printf(" %s %s=%s%s%s was not met\n",
4130 --n
? special_glyph(TREE_BRANCH
) : special_glyph(TREE_RIGHT
),
4132 c
->trigger
? "|" : "",
4133 c
->negate
? "!" : "",
4137 if (!i
->assert_result
&& i
->assert_timestamp
> 0) {
4138 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->assert_timestamp
);
4139 s2
= format_timestamp(since2
, sizeof(since2
), i
->assert_timestamp
);
4141 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
4142 ansi_highlight_red(), ansi_normal(),
4143 s2
, s1
? "; " : "", strempty(s1
));
4144 if (i
->failed_assert_trigger
)
4145 printf(" none of the trigger assertions were met\n");
4146 else if (i
->failed_assert
)
4147 printf(" %s=%s%s was not met\n",
4149 i
->failed_assert_negate
? "!" : "",
4150 i
->failed_assert_parameter
);
4154 printf(" Device: %s\n", i
->sysfs_path
);
4156 printf(" Where: %s\n", i
->where
);
4158 printf(" What: %s\n", i
->what
);
4160 STRV_FOREACH(t
, i
->documentation
)
4161 printf(" %*s %s\n", 9, t
== i
->documentation
? "Docs:" : "", *t
);
4163 STRV_FOREACH_PAIR(t
, t2
, i
->listen
)
4164 printf(" %*s %s (%s)\n", 9, t
== i
->listen
? "Listen:" : "", *t2
, *t
);
4167 printf(" Accepted: %u; Connected: %u\n", i
->n_accepted
, i
->n_connections
);
4169 LIST_FOREACH(exec
, p
, i
->exec
) {
4170 _cleanup_free_
char *argv
= NULL
;
4173 /* Only show exited processes here */
4177 argv
= strv_join(p
->argv
, " ");
4178 printf(" Process: "PID_FMT
" %s=%s ", p
->pid
, p
->name
, strna(argv
));
4180 good
= is_clean_exit(p
->code
, p
->status
, EXIT_CLEAN_DAEMON
, NULL
);
4182 on
= ansi_highlight_red();
4183 off
= ansi_normal();
4187 printf("%s(code=%s, ", on
, sigchld_code_to_string(p
->code
));
4189 if (p
->code
== CLD_EXITED
) {
4192 printf("status=%i", p
->status
);
4194 c
= exit_status_to_string(p
->status
, EXIT_STATUS_SYSTEMD
);
4199 printf("signal=%s", signal_to_string(p
->status
));
4201 printf(")%s\n", off
);
4203 if (i
->main_pid
== p
->pid
&&
4204 i
->start_timestamp
== p
->start_timestamp
&&
4205 i
->exit_timestamp
== p
->start_timestamp
)
4206 /* Let's not show this twice */
4209 if (p
->pid
== i
->control_pid
)
4213 if (i
->main_pid
> 0 || i
->control_pid
> 0) {
4214 if (i
->main_pid
> 0) {
4215 printf(" Main PID: "PID_FMT
, i
->main_pid
);
4219 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
4220 _cleanup_free_
char *comm
= NULL
;
4222 (void) get_process_comm(i
->main_pid
, &comm
);
4224 printf(" (%s)", comm
);
4227 } else if (i
->exit_code
> 0) {
4228 printf(" (code=%s, ", sigchld_code_to_string(i
->exit_code
));
4230 if (i
->exit_code
== CLD_EXITED
) {
4233 printf("status=%i", i
->exit_status
);
4235 c
= exit_status_to_string(i
->exit_status
, EXIT_STATUS_SYSTEMD
);
4240 printf("signal=%s", signal_to_string(i
->exit_status
));
4245 if (i
->control_pid
> 0) {
4246 _cleanup_free_
char *c
= NULL
;
4248 if (i
->main_pid
> 0)
4249 fputs("; Control PID: ", stdout
);
4251 fputs("Cntrl PID: ", stdout
); /* if first in column, abbreviated so it fits alignment */
4253 printf(PID_FMT
, i
->control_pid
);
4255 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
4256 (void) get_process_comm(i
->control_pid
, &c
);
4266 printf(" Status: \"%s\"\n", i
->status_text
);
4267 if (i
->status_errno
> 0)
4268 printf(" Error: %i (%s)\n", i
->status_errno
, strerror(i
->status_errno
));
4270 if (i
->ip_ingress_bytes
!= (uint64_t) -1 && i
->ip_egress_bytes
!= (uint64_t) -1) {
4271 char buf_in
[FORMAT_BYTES_MAX
], buf_out
[FORMAT_BYTES_MAX
];
4273 printf(" IP: %s in, %s out\n",
4274 format_bytes(buf_in
, sizeof(buf_in
), i
->ip_ingress_bytes
),
4275 format_bytes(buf_out
, sizeof(buf_out
), i
->ip_egress_bytes
));
4278 if (i
->tasks_current
!= (uint64_t) -1) {
4279 printf(" Tasks: %" PRIu64
, i
->tasks_current
);
4281 if (i
->tasks_max
!= (uint64_t) -1)
4282 printf(" (limit: %" PRIu64
")\n", i
->tasks_max
);
4287 if (i
->memory_current
!= (uint64_t) -1) {
4288 char buf
[FORMAT_BYTES_MAX
];
4290 printf(" Memory: %s", format_bytes(buf
, sizeof(buf
), i
->memory_current
));
4292 if (i
->memory_low
> 0 || i
->memory_high
!= CGROUP_LIMIT_MAX
||
4293 i
->memory_max
!= CGROUP_LIMIT_MAX
|| i
->memory_swap_max
!= CGROUP_LIMIT_MAX
||
4294 i
->memory_limit
!= CGROUP_LIMIT_MAX
) {
4295 const char *prefix
= "";
4298 if (i
->memory_low
> 0) {
4299 printf("%slow: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_low
));
4302 if (i
->memory_high
!= CGROUP_LIMIT_MAX
) {
4303 printf("%shigh: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_high
));
4306 if (i
->memory_max
!= CGROUP_LIMIT_MAX
) {
4307 printf("%smax: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_max
));
4310 if (i
->memory_swap_max
!= CGROUP_LIMIT_MAX
) {
4311 printf("%sswap max: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_swap_max
));
4314 if (i
->memory_limit
!= CGROUP_LIMIT_MAX
) {
4315 printf("%slimit: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_limit
));
4323 if (i
->cpu_usage_nsec
!= (uint64_t) -1) {
4324 char buf
[FORMAT_TIMESPAN_MAX
];
4325 printf(" CPU: %s\n", format_timespan(buf
, sizeof(buf
), i
->cpu_usage_nsec
/ NSEC_PER_USEC
, USEC_PER_MSEC
));
4328 if (i
->control_group
) {
4329 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
4330 static const char prefix
[] = " ";
4333 printf(" CGroup: %s\n", i
->control_group
);
4336 if (c
> sizeof(prefix
) - 1)
4337 c
-= sizeof(prefix
) - 1;
4341 r
= unit_show_processes(bus
, i
->id
, i
->control_group
, prefix
, c
, get_output_flags(), &error
);
4346 /* Fallback for older systemd versions where the GetUnitProcesses() call is not yet available */
4348 if (i
->main_pid
> 0)
4349 extra
[k
++] = i
->main_pid
;
4351 if (i
->control_pid
> 0)
4352 extra
[k
++] = i
->control_pid
;
4354 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, prefix
, c
, extra
, k
, get_output_flags());
4356 log_warning_errno(r
, "Failed to dump process list, ignoring: %s", bus_error_message(&error
, r
));
4359 if (i
->id
&& arg_transport
== BUS_TRANSPORT_LOCAL
)
4360 show_journal_by_unit(
4365 i
->inactive_exit_timestamp_monotonic
,
4368 get_output_flags() | OUTPUT_BEGIN_NEWLINE
,
4369 SD_JOURNAL_LOCAL_ONLY
,
4370 arg_scope
== UNIT_FILE_SYSTEM
,
4373 if (i
->need_daemon_reload
)
4374 warn_unit_file_changed(i
->id
);
4377 static void show_unit_help(UnitStatusInfo
*i
) {
4382 if (!i
->documentation
) {
4383 log_info("Documentation for %s not known.", i
->id
);
4387 STRV_FOREACH(p
, i
->documentation
)
4388 if (startswith(*p
, "man:"))
4389 show_man_page(*p
+ 4, false);
4391 log_info("Can't show: %s", *p
);
4394 static int map_main_pid(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
4395 UnitStatusInfo
*i
= userdata
;
4399 r
= sd_bus_message_read(m
, "u", &u
);
4403 i
->main_pid
= (pid_t
) u
;
4409 static int map_load_error(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
4410 const char *n
, *message
;
4411 const char **p
= userdata
;
4414 r
= sd_bus_message_read(m
, "(ss)", &n
, &message
);
4418 if (!isempty(message
))
4424 static int map_listen(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
4425 const char *type
, *path
;
4426 char ***p
= userdata
;
4429 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4433 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0) {
4435 r
= strv_extend(p
, type
);
4439 r
= strv_extend(p
, path
);
4446 r
= sd_bus_message_exit_container(m
);
4453 static int map_conditions(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
4454 UnitStatusInfo
*i
= userdata
;
4455 const char *cond
, *param
;
4456 int trigger
, negate
;
4460 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
4464 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
4465 _cleanup_(unit_condition_freep
) UnitCondition
*c
= NULL
;
4467 c
= new0(UnitCondition
, 1);
4471 c
->name
= strdup(cond
);
4472 c
->param
= strdup(param
);
4473 if (!c
->name
|| !c
->param
)
4476 c
->trigger
= trigger
;
4478 c
->tristate
= state
;
4480 LIST_PREPEND(conditions
, i
->conditions
, c
);
4486 r
= sd_bus_message_exit_container(m
);
4493 static int map_asserts(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
4494 UnitStatusInfo
*i
= userdata
;
4495 const char *cond
, *param
;
4496 int trigger
, negate
;
4500 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
4504 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
4505 if (state
< 0 && (!trigger
|| !i
->failed_assert
)) {
4506 i
->failed_assert
= cond
;
4507 i
->failed_assert_trigger
= trigger
;
4508 i
->failed_assert_negate
= negate
;
4509 i
->failed_assert_parameter
= param
;
4515 r
= sd_bus_message_exit_container(m
);
4522 static int map_exec(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
4523 _cleanup_free_ ExecStatusInfo
*info
= NULL
;
4524 UnitStatusInfo
*i
= userdata
;
4527 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4531 info
= new0(ExecStatusInfo
, 1);
4535 while ((r
= exec_status_info_deserialize(m
, info
)) > 0) {
4537 info
->name
= strdup(member
);
4541 LIST_PREPEND(exec
, i
->exec
, info
);
4543 info
= new0(ExecStatusInfo
, 1);
4550 r
= sd_bus_message_exit_container(m
);
4557 #define print_prop(name, fmt, ...) \
4560 printf(fmt "\n", __VA_ARGS__); \
4562 printf("%s=" fmt "\n", name, __VA_ARGS__); \
4565 static int print_property(const char *name
, sd_bus_message
*m
, bool value
, bool all
) {
4567 const char *contents
;
4573 /* This is a low-level property printer, see
4574 * print_status_info() for the nicer output */
4576 r
= sd_bus_message_peek_type(m
, &bus_type
, &contents
);
4582 case SD_BUS_TYPE_STRUCT
:
4584 if (contents
[0] == SD_BUS_TYPE_UINT32
&& streq(name
, "Job")) {
4587 r
= sd_bus_message_read(m
, "(uo)", &u
, NULL
);
4589 return bus_log_parse_error(r
);
4592 print_prop(name
, "%"PRIu32
, u
);
4594 print_prop(name
, "%s", "");
4598 } else if (contents
[0] == SD_BUS_TYPE_STRING
&& streq(name
, "Unit")) {
4601 r
= sd_bus_message_read(m
, "(so)", &s
, NULL
);
4603 return bus_log_parse_error(r
);
4605 if (all
|| !isempty(s
))
4606 print_prop(name
, "%s", s
);
4610 } else if (contents
[0] == SD_BUS_TYPE_STRING
&& streq(name
, "LoadError")) {
4611 const char *a
= NULL
, *b
= NULL
;
4613 r
= sd_bus_message_read(m
, "(ss)", &a
, &b
);
4615 return bus_log_parse_error(r
);
4617 if (all
|| !isempty(a
) || !isempty(b
))
4618 print_prop(name
, "%s \"%s\"", strempty(a
), strempty(b
));
4621 } else if (streq_ptr(name
, "SystemCallFilter")) {
4622 _cleanup_strv_free_
char **l
= NULL
;
4625 r
= sd_bus_message_enter_container(m
, 'r', "bas");
4627 return bus_log_parse_error(r
);
4629 r
= sd_bus_message_read(m
, "b", &whitelist
);
4631 return bus_log_parse_error(r
);
4633 r
= sd_bus_message_read_strv(m
, &l
);
4635 return bus_log_parse_error(r
);
4637 r
= sd_bus_message_exit_container(m
);
4639 return bus_log_parse_error(r
);
4641 if (all
|| whitelist
|| !strv_isempty(l
)) {
4646 fputs(name
, stdout
);
4653 STRV_FOREACH(i
, l
) {
4661 fputc('\n', stdout
);
4669 case SD_BUS_TYPE_ARRAY
:
4671 if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "EnvironmentFiles")) {
4675 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sb)");
4677 return bus_log_parse_error(r
);
4679 while ((r
= sd_bus_message_read(m
, "(sb)", &path
, &ignore
)) > 0)
4680 print_prop(name
, "%s (ignore_errors=%s)", path
, yes_no(ignore
));
4683 return bus_log_parse_error(r
);
4685 r
= sd_bus_message_exit_container(m
);
4687 return bus_log_parse_error(r
);
4691 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Paths")) {
4692 const char *type
, *path
;
4694 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4696 return bus_log_parse_error(r
);
4698 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4699 print_prop(name
, "%s (%s)", path
, type
);
4701 return bus_log_parse_error(r
);
4703 r
= sd_bus_message_exit_container(m
);
4705 return bus_log_parse_error(r
);
4709 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
4710 const char *type
, *path
;
4712 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4714 return bus_log_parse_error(r
);
4716 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4717 print_prop(name
, "%s (%s)", path
, type
);
4719 return bus_log_parse_error(r
);
4721 r
= sd_bus_message_exit_container(m
);
4723 return bus_log_parse_error(r
);
4727 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "TimersMonotonic")) {
4729 uint64_t v
, next_elapse
;
4731 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(stt)");
4733 return bus_log_parse_error(r
);
4735 while ((r
= sd_bus_message_read(m
, "(stt)", &base
, &v
, &next_elapse
)) > 0) {
4736 char timespan1
[FORMAT_TIMESPAN_MAX
], timespan2
[FORMAT_TIMESPAN_MAX
];
4738 print_prop(name
, "{ %s=%s ; next_elapse=%s }", base
,
4739 format_timespan(timespan1
, sizeof(timespan1
), v
, 0),
4740 format_timespan(timespan2
, sizeof(timespan2
), next_elapse
, 0));
4743 return bus_log_parse_error(r
);
4745 r
= sd_bus_message_exit_container(m
);
4747 return bus_log_parse_error(r
);
4751 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "TimersCalendar")) {
4752 const char *base
, *spec
;
4753 uint64_t next_elapse
;
4755 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sst)");
4757 return bus_log_parse_error(r
);
4759 while ((r
= sd_bus_message_read(m
, "(sst)", &base
, &spec
, &next_elapse
)) > 0) {
4760 char timestamp
[FORMAT_TIMESTAMP_MAX
];
4762 print_prop(name
, "{ %s=%s ; next_elapse=%s }", base
, spec
,
4763 format_timestamp(timestamp
, sizeof(timestamp
), next_elapse
));
4766 return bus_log_parse_error(r
);
4768 r
= sd_bus_message_exit_container(m
);
4770 return bus_log_parse_error(r
);
4774 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
4775 ExecStatusInfo info
= {};
4777 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4779 return bus_log_parse_error(r
);
4781 while ((r
= exec_status_info_deserialize(m
, &info
)) > 0) {
4782 char timestamp1
[FORMAT_TIMESTAMP_MAX
], timestamp2
[FORMAT_TIMESTAMP_MAX
];
4783 _cleanup_free_
char *tt
;
4785 tt
= strv_join(info
.argv
, " ");
4788 "{ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT
" ; code=%s ; status=%i%s%s }",
4791 yes_no(info
.ignore
),
4792 strna(format_timestamp(timestamp1
, sizeof(timestamp1
), info
.start_timestamp
)),
4793 strna(format_timestamp(timestamp2
, sizeof(timestamp2
), info
.exit_timestamp
)),
4795 sigchld_code_to_string(info
.code
),
4797 info
.code
== CLD_EXITED
? "" : "/",
4798 strempty(info
.code
== CLD_EXITED
? NULL
: signal_to_string(info
.status
)));
4801 strv_free(info
.argv
);
4805 r
= sd_bus_message_exit_container(m
);
4807 return bus_log_parse_error(r
);
4811 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "DeviceAllow")) {
4812 const char *path
, *rwm
;
4814 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4816 return bus_log_parse_error(r
);
4818 while ((r
= sd_bus_message_read(m
, "(ss)", &path
, &rwm
)) > 0)
4819 print_prop(name
, "%s %s", strna(path
), strna(rwm
));
4821 return bus_log_parse_error(r
);
4823 r
= sd_bus_message_exit_container(m
);
4825 return bus_log_parse_error(r
);
4829 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&&
4830 STR_IN_SET(name
, "IODeviceWeight", "BlockIODeviceWeight")) {
4834 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4836 return bus_log_parse_error(r
);
4838 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &weight
)) > 0)
4839 print_prop(name
, "%s %"PRIu64
, strna(path
), weight
);
4841 return bus_log_parse_error(r
);
4843 r
= sd_bus_message_exit_container(m
);
4845 return bus_log_parse_error(r
);
4849 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&&
4850 (cgroup_io_limit_type_from_string(name
) >= 0 ||
4851 STR_IN_SET(name
, "BlockIOReadBandwidth", "BlockIOWriteBandwidth"))) {
4855 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4857 return bus_log_parse_error(r
);
4859 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &bandwidth
)) > 0)
4860 print_prop(name
, "%s %"PRIu64
, strna(path
), bandwidth
);
4862 return bus_log_parse_error(r
);
4864 r
= sd_bus_message_exit_container(m
);
4866 return bus_log_parse_error(r
);
4870 } else if (contents
[0] == SD_BUS_TYPE_BYTE
&& streq(name
, "StandardInputData")) {
4871 _cleanup_free_
char *h
= NULL
;
4876 r
= sd_bus_message_read_array(m
, 'y', &p
, &sz
);
4878 return bus_log_parse_error(r
);
4880 n
= base64mem(p
, sz
, &h
);
4884 print_prop(name
, "%s", h
);
4895 typedef enum SystemctlShowMode
{
4896 SYSTEMCTL_SHOW_PROPERTIES
,
4897 SYSTEMCTL_SHOW_STATUS
,
4898 SYSTEMCTL_SHOW_HELP
,
4899 _SYSTEMCTL_SHOW_MODE_MAX
,
4900 _SYSTEMCTL_SHOW_MODE_INVALID
= -1,
4901 } SystemctlShowMode
;
4903 static const char* const systemctl_show_mode_table
[] = {
4904 [SYSTEMCTL_SHOW_PROPERTIES
] = "show",
4905 [SYSTEMCTL_SHOW_STATUS
] = "status",
4906 [SYSTEMCTL_SHOW_HELP
] = "help",
4909 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(systemctl_show_mode
, SystemctlShowMode
);
4911 static int show_one(
4915 SystemctlShowMode show_mode
,
4919 static const struct bus_properties_map property_map
[] = {
4920 { "LoadState", "s", NULL
, offsetof(UnitStatusInfo
, load_state
) },
4921 { "ActiveState", "s", NULL
, offsetof(UnitStatusInfo
, active_state
) },
4922 { "Documentation", "as", NULL
, offsetof(UnitStatusInfo
, documentation
) },
4925 { "Id", "s", NULL
, offsetof(UnitStatusInfo
, id
) },
4926 { "LoadState", "s", NULL
, offsetof(UnitStatusInfo
, load_state
) },
4927 { "ActiveState", "s", NULL
, offsetof(UnitStatusInfo
, active_state
) },
4928 { "SubState", "s", NULL
, offsetof(UnitStatusInfo
, sub_state
) },
4929 { "UnitFileState", "s", NULL
, offsetof(UnitStatusInfo
, unit_file_state
) },
4930 { "UnitFilePreset", "s", NULL
, offsetof(UnitStatusInfo
, unit_file_preset
) },
4931 { "Description", "s", NULL
, offsetof(UnitStatusInfo
, description
) },
4932 { "Following", "s", NULL
, offsetof(UnitStatusInfo
, following
) },
4933 { "Documentation", "as", NULL
, offsetof(UnitStatusInfo
, documentation
) },
4934 { "FragmentPath", "s", NULL
, offsetof(UnitStatusInfo
, fragment_path
) },
4935 { "SourcePath", "s", NULL
, offsetof(UnitStatusInfo
, source_path
) },
4936 { "ControlGroup", "s", NULL
, offsetof(UnitStatusInfo
, control_group
) },
4937 { "DropInPaths", "as", NULL
, offsetof(UnitStatusInfo
, dropin_paths
) },
4938 { "LoadError", "(ss)", map_load_error
, offsetof(UnitStatusInfo
, load_error
) },
4939 { "Result", "s", NULL
, offsetof(UnitStatusInfo
, result
) },
4940 { "InactiveExitTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, inactive_exit_timestamp
) },
4941 { "InactiveExitTimestampMonotonic", "t", NULL
, offsetof(UnitStatusInfo
, inactive_exit_timestamp_monotonic
) },
4942 { "ActiveEnterTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, active_enter_timestamp
) },
4943 { "ActiveExitTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, active_exit_timestamp
) },
4944 { "InactiveEnterTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, inactive_enter_timestamp
) },
4945 { "NeedDaemonReload", "b", NULL
, offsetof(UnitStatusInfo
, need_daemon_reload
) },
4946 { "Transient", "b", NULL
, offsetof(UnitStatusInfo
, transient
) },
4947 { "ExecMainPID", "u", NULL
, offsetof(UnitStatusInfo
, main_pid
) },
4948 { "MainPID", "u", map_main_pid
, 0 },
4949 { "ControlPID", "u", NULL
, offsetof(UnitStatusInfo
, control_pid
) },
4950 { "StatusText", "s", NULL
, offsetof(UnitStatusInfo
, status_text
) },
4951 { "PIDFile", "s", NULL
, offsetof(UnitStatusInfo
, pid_file
) },
4952 { "StatusErrno", "i", NULL
, offsetof(UnitStatusInfo
, status_errno
) },
4953 { "ExecMainStartTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, start_timestamp
) },
4954 { "ExecMainExitTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, exit_timestamp
) },
4955 { "ExecMainCode", "i", NULL
, offsetof(UnitStatusInfo
, exit_code
) },
4956 { "ExecMainStatus", "i", NULL
, offsetof(UnitStatusInfo
, exit_status
) },
4957 { "ConditionTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, condition_timestamp
) },
4958 { "ConditionResult", "b", NULL
, offsetof(UnitStatusInfo
, condition_result
) },
4959 { "Conditions", "a(sbbsi)", map_conditions
, 0 },
4960 { "AssertTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, assert_timestamp
) },
4961 { "AssertResult", "b", NULL
, offsetof(UnitStatusInfo
, assert_result
) },
4962 { "Asserts", "a(sbbsi)", map_asserts
, 0 },
4963 { "NextElapseUSecRealtime", "t", NULL
, offsetof(UnitStatusInfo
, next_elapse_real
) },
4964 { "NextElapseUSecMonotonic", "t", NULL
, offsetof(UnitStatusInfo
, next_elapse_monotonic
) },
4965 { "NAccepted", "u", NULL
, offsetof(UnitStatusInfo
, n_accepted
) },
4966 { "NConnections", "u", NULL
, offsetof(UnitStatusInfo
, n_connections
) },
4967 { "Accept", "b", NULL
, offsetof(UnitStatusInfo
, accept
) },
4968 { "Listen", "a(ss)", map_listen
, offsetof(UnitStatusInfo
, listen
) },
4969 { "SysFSPath", "s", NULL
, offsetof(UnitStatusInfo
, sysfs_path
) },
4970 { "Where", "s", NULL
, offsetof(UnitStatusInfo
, where
) },
4971 { "What", "s", NULL
, offsetof(UnitStatusInfo
, what
) },
4972 { "MemoryCurrent", "t", NULL
, offsetof(UnitStatusInfo
, memory_current
) },
4973 { "MemoryLow", "t", NULL
, offsetof(UnitStatusInfo
, memory_low
) },
4974 { "MemoryHigh", "t", NULL
, offsetof(UnitStatusInfo
, memory_high
) },
4975 { "MemoryMax", "t", NULL
, offsetof(UnitStatusInfo
, memory_max
) },
4976 { "MemorySwapMax", "t", NULL
, offsetof(UnitStatusInfo
, memory_swap_max
) },
4977 { "MemoryLimit", "t", NULL
, offsetof(UnitStatusInfo
, memory_limit
) },
4978 { "CPUUsageNSec", "t", NULL
, offsetof(UnitStatusInfo
, cpu_usage_nsec
) },
4979 { "TasksCurrent", "t", NULL
, offsetof(UnitStatusInfo
, tasks_current
) },
4980 { "TasksMax", "t", NULL
, offsetof(UnitStatusInfo
, tasks_max
) },
4981 { "IPIngressBytes", "t", NULL
, offsetof(UnitStatusInfo
, ip_ingress_bytes
) },
4982 { "IPEgressBytes", "t", NULL
, offsetof(UnitStatusInfo
, ip_egress_bytes
) },
4983 { "ExecStartPre", "a(sasbttttuii)", map_exec
, 0 },
4984 { "ExecStart", "a(sasbttttuii)", map_exec
, 0 },
4985 { "ExecStartPost", "a(sasbttttuii)", map_exec
, 0 },
4986 { "ExecReload", "a(sasbttttuii)", map_exec
, 0 },
4987 { "ExecStopPre", "a(sasbttttuii)", map_exec
, 0 },
4988 { "ExecStop", "a(sasbttttuii)", map_exec
, 0 },
4989 { "ExecStopPost", "a(sasbttttuii)", map_exec
, 0 },
4993 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
4994 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
4995 _cleanup_set_free_ Set
*found_properties
= NULL
;
4996 _cleanup_(unit_status_info_free
) UnitStatusInfo info
= {
4997 .memory_current
= (uint64_t) -1,
4998 .memory_high
= CGROUP_LIMIT_MAX
,
4999 .memory_max
= CGROUP_LIMIT_MAX
,
5000 .memory_swap_max
= CGROUP_LIMIT_MAX
,
5001 .memory_limit
= (uint64_t) -1,
5002 .cpu_usage_nsec
= (uint64_t) -1,
5003 .tasks_current
= (uint64_t) -1,
5004 .tasks_max
= (uint64_t) -1,
5005 .ip_ingress_bytes
= (uint64_t) -1,
5006 .ip_egress_bytes
= (uint64_t) -1,
5014 log_debug("Showing one %s", path
);
5016 r
= bus_map_all_properties(
5018 "org.freedesktop.systemd1",
5020 show_mode
== SYSTEMCTL_SHOW_STATUS
? status_map
: property_map
,
5025 return log_error_errno(r
, "Failed to get properties: %s", bus_error_message(&error
, r
));
5027 if (unit
&& streq_ptr(info
.load_state
, "not-found") && streq_ptr(info
.active_state
, "inactive")) {
5028 log_full(show_mode
== SYSTEMCTL_SHOW_STATUS
? LOG_ERR
: LOG_DEBUG
,
5029 "Unit %s could not be found.", unit
);
5031 if (show_mode
== SYSTEMCTL_SHOW_STATUS
)
5032 return EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN
;
5033 else if (show_mode
== SYSTEMCTL_SHOW_HELP
)
5042 if (show_mode
== SYSTEMCTL_SHOW_STATUS
) {
5043 print_status_info(bus
, &info
, ellipsized
);
5045 if (info
.active_state
&& !STR_IN_SET(info
.active_state
, "active", "reloading"))
5046 return EXIT_PROGRAM_NOT_RUNNING
;
5048 return EXIT_PROGRAM_RUNNING_OR_SERVICE_OK
;
5050 } else if (show_mode
== SYSTEMCTL_SHOW_HELP
) {
5051 show_unit_help(&info
);
5055 r
= sd_bus_message_rewind(reply
, true);
5057 return log_error_errno(r
, "Failed to rewind: %s", bus_error_message(&error
, r
));
5059 r
= bus_message_print_all_properties(reply
, print_property
, arg_properties
, arg_value
, arg_all
, &found_properties
);
5061 return bus_log_parse_error(r
);
5063 STRV_FOREACH(pp
, arg_properties
)
5064 if (!set_contains(found_properties
, *pp
))
5065 log_debug("Property %s does not exist.", *pp
);
5070 static int get_unit_dbus_path_by_pid(
5075 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5076 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5080 r
= sd_bus_call_method(
5082 "org.freedesktop.systemd1",
5083 "/org/freedesktop/systemd1",
5084 "org.freedesktop.systemd1.Manager",
5090 return log_error_errno(r
, "Failed to get unit for PID %"PRIu32
": %s", pid
, bus_error_message(&error
, r
));
5092 r
= sd_bus_message_read(reply
, "o", &u
);
5094 return bus_log_parse_error(r
);
5104 static int show_all(
5109 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5110 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
5115 r
= get_unit_list(bus
, NULL
, NULL
, &unit_infos
, 0, &reply
);
5119 (void) pager_open(arg_no_pager
, false);
5123 qsort_safe(unit_infos
, c
, sizeof(UnitInfo
), compare_unit_info
);
5125 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
5126 _cleanup_free_
char *p
= NULL
;
5128 p
= unit_dbus_path_from_name(u
->id
);
5132 r
= show_one(bus
, p
, u
->id
, SYSTEMCTL_SHOW_STATUS
, new_line
, ellipsized
);
5135 else if (r
> 0 && ret
== 0)
5142 static int show_system_status(sd_bus
*bus
) {
5143 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], since2
[FORMAT_TIMESTAMP_MAX
];
5144 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5145 _cleanup_(machine_info_clear
) struct machine_info mi
= {};
5146 _cleanup_free_
char *hn
= NULL
;
5147 const char *on
, *off
;
5150 hn
= gethostname_malloc();
5154 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, &error
, NULL
, &mi
);
5156 return log_error_errno(r
, "Failed to read server status: %s", bus_error_message(&error
, r
));
5158 if (streq_ptr(mi
.state
, "degraded")) {
5159 on
= ansi_highlight_red();
5160 off
= ansi_normal();
5161 } else if (streq_ptr(mi
.state
, "running")) {
5162 on
= ansi_highlight_green();
5163 off
= ansi_normal();
5165 on
= ansi_highlight_yellow();
5166 off
= ansi_normal();
5169 printf("%s%s%s %s\n", on
, special_glyph(BLACK_CIRCLE
), off
, arg_host
? arg_host
: hn
);
5171 printf(" State: %s%s%s\n",
5172 on
, strna(mi
.state
), off
);
5174 printf(" Jobs: %" PRIu32
" queued\n", mi
.n_jobs
);
5175 printf(" Failed: %" PRIu32
" units\n", mi
.n_failed_units
);
5177 printf(" Since: %s; %s\n",
5178 format_timestamp(since2
, sizeof(since2
), mi
.timestamp
),
5179 format_timestamp_relative(since1
, sizeof(since1
), mi
.timestamp
));
5181 printf(" CGroup: %s\n", mi
.control_group
?: "/");
5182 if (IN_SET(arg_transport
,
5183 BUS_TRANSPORT_LOCAL
,
5184 BUS_TRANSPORT_MACHINE
)) {
5185 static const char prefix
[] = " ";
5189 if (c
> sizeof(prefix
) - 1)
5190 c
-= sizeof(prefix
) - 1;
5194 show_cgroup(SYSTEMD_CGROUP_CONTROLLER
, strempty(mi
.control_group
), prefix
, c
, get_output_flags());
5200 static int show(int argc
, char *argv
[], void *userdata
) {
5201 bool new_line
= false, ellipsized
= false;
5202 SystemctlShowMode show_mode
;
5208 show_mode
= systemctl_show_mode_from_string(argv
[0]);
5209 if (show_mode
< 0) {
5210 log_error("Invalid argument.");
5214 if (show_mode
== SYSTEMCTL_SHOW_HELP
&& argc
<= 1) {
5215 log_error("This command expects one or more unit names. Did you mean --help?");
5219 r
= acquire_bus(BUS_MANAGER
, &bus
);
5223 (void) pager_open(arg_no_pager
, false);
5225 if (show_mode
== SYSTEMCTL_SHOW_STATUS
)
5226 /* Increase max number of open files to 16K if we can, we
5227 * might needs this when browsing journal files, which might
5228 * be split up into many files. */
5229 setrlimit_closest(RLIMIT_NOFILE
, &RLIMIT_MAKE_CONST(16384));
5231 /* If no argument is specified inspect the manager itself */
5232 if (show_mode
== SYSTEMCTL_SHOW_PROPERTIES
&& argc
<= 1)
5233 return show_one(bus
, "/org/freedesktop/systemd1", NULL
, show_mode
, &new_line
, &ellipsized
);
5235 if (show_mode
== SYSTEMCTL_SHOW_STATUS
&& argc
<= 1) {
5237 show_system_status(bus
);
5241 ret
= show_all(bus
, &new_line
, &ellipsized
);
5243 _cleanup_free_
char **patterns
= NULL
;
5246 STRV_FOREACH(name
, strv_skip(argv
, 1)) {
5247 _cleanup_free_
char *path
= NULL
, *unit
= NULL
;
5250 if (safe_atou32(*name
, &id
) < 0) {
5251 if (strv_push(&patterns
, *name
) < 0)
5255 } else if (show_mode
== SYSTEMCTL_SHOW_PROPERTIES
) {
5256 /* Interpret as job id */
5257 if (asprintf(&path
, "/org/freedesktop/systemd1/job/%u", id
) < 0)
5261 /* Interpret as PID */
5262 r
= get_unit_dbus_path_by_pid(bus
, id
, &path
);
5268 r
= unit_name_from_dbus_path(path
, &unit
);
5273 r
= show_one(bus
, path
, unit
, show_mode
, &new_line
, &ellipsized
);
5276 else if (r
> 0 && ret
== 0)
5280 if (!strv_isempty(patterns
)) {
5281 _cleanup_strv_free_
char **names
= NULL
;
5283 r
= expand_names(bus
, patterns
, NULL
, &names
);
5285 return log_error_errno(r
, "Failed to expand names: %m");
5287 STRV_FOREACH(name
, names
) {
5288 _cleanup_free_
char *path
;
5290 path
= unit_dbus_path_from_name(*name
);
5294 r
= show_one(bus
, path
, *name
, show_mode
, &new_line
, &ellipsized
);
5297 if (r
> 0 && ret
== 0)
5303 if (ellipsized
&& !arg_quiet
)
5304 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
5309 static int cat_file(const char *filename
, bool newline
) {
5310 _cleanup_close_
int fd
;
5312 fd
= open(filename
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
5316 printf("%s%s# %s%s\n",
5317 newline
? "\n" : "",
5318 ansi_highlight_blue(),
5323 return copy_bytes(fd
, STDOUT_FILENO
, (uint64_t) -1, 0);
5326 static int cat(int argc
, char *argv
[], void *userdata
) {
5327 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
5328 _cleanup_strv_free_
char **names
= NULL
;
5334 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
5335 log_error("Cannot remotely cat units.");
5339 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
5341 return log_error_errno(r
, "Failed to determine unit paths: %m");
5343 r
= acquire_bus(BUS_MANAGER
, &bus
);
5347 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
5349 return log_error_errno(r
, "Failed to expand names: %m");
5351 (void) pager_open(arg_no_pager
, false);
5353 STRV_FOREACH(name
, names
) {
5354 _cleanup_free_
char *fragment_path
= NULL
;
5355 _cleanup_strv_free_
char **dropin_paths
= NULL
;
5358 r
= unit_find_paths(bus
, *name
, &lp
, &fragment_path
, &dropin_paths
);
5369 if (need_daemon_reload(bus
, *name
) > 0) /* ignore errors (<0), this is informational output */
5371 "%s# Warning: %s changed on disk, the version systemd has loaded is outdated.\n"
5372 "%s# This output shows the current version of the unit's original fragment and drop-in files.\n"
5373 "%s# If fragments or drop-ins were added or removed, they are not properly reflected in this output.\n"
5374 "%s# Run 'systemctl%s daemon-reload' to reload units.%s\n",
5375 ansi_highlight_red(),
5377 ansi_highlight_red(),
5378 ansi_highlight_red(),
5379 ansi_highlight_red(),
5380 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user",
5383 if (fragment_path
) {
5384 r
= cat_file(fragment_path
, false);
5386 return log_warning_errno(r
, "Failed to cat %s: %m", fragment_path
);
5389 STRV_FOREACH(path
, dropin_paths
) {
5390 r
= cat_file(*path
, path
== dropin_paths
);
5392 return log_warning_errno(r
, "Failed to cat %s: %m", *path
);
5399 static int set_property(int argc
, char *argv
[], void *userdata
) {
5400 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5401 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5402 _cleanup_free_
char *n
= NULL
;
5407 r
= acquire_bus(BUS_MANAGER
, &bus
);
5411 polkit_agent_open_maybe();
5413 r
= sd_bus_message_new_method_call(
5416 "org.freedesktop.systemd1",
5417 "/org/freedesktop/systemd1",
5418 "org.freedesktop.systemd1.Manager",
5419 "SetUnitProperties");
5421 return bus_log_create_error(r
);
5423 r
= unit_name_mangle(argv
[1], arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
, &n
);
5425 return log_error_errno(r
, "Failed to mangle unit name: %m");
5427 t
= unit_name_to_type(n
);
5429 log_error("Invalid unit type: %s", n
);
5433 r
= sd_bus_message_append(m
, "sb", n
, arg_runtime
);
5435 return bus_log_create_error(r
);
5437 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, "(sv)");
5439 return bus_log_create_error(r
);
5441 r
= bus_append_unit_property_assignment_many(m
, t
, strv_skip(argv
, 2));
5445 r
= sd_bus_message_close_container(m
);
5447 return bus_log_create_error(r
);
5449 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5451 return log_error_errno(r
, "Failed to set unit properties on %s: %s", n
, bus_error_message(&error
, r
));
5456 static int daemon_reload(int argc
, char *argv
[], void *userdata
) {
5457 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5458 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5463 r
= acquire_bus(BUS_MANAGER
, &bus
);
5467 polkit_agent_open_maybe();
5469 switch (arg_action
) {
5476 method
= "Reexecute";
5479 case ACTION_SYSTEMCTL
:
5480 method
= streq(argv
[0], "daemon-reexec") ? "Reexecute" :
5481 /* "daemon-reload" */ "Reload";
5485 assert_not_reached("Unexpected action");
5488 r
= sd_bus_message_new_method_call(
5491 "org.freedesktop.systemd1",
5492 "/org/freedesktop/systemd1",
5493 "org.freedesktop.systemd1.Manager",
5496 return bus_log_create_error(r
);
5498 /* Note we use an extra-long timeout here. This is because a reload or reexec means generators are rerun which
5499 * are timed out after DEFAULT_TIMEOUT_USEC. Let's use twice that time here, so that the generators can have
5500 * their timeout, and for everything else there's the same time budget in place. */
5502 r
= sd_bus_call(bus
, m
, DEFAULT_TIMEOUT_USEC
* 2, &error
, NULL
);
5504 /* On reexecution, we expect a disconnect, not a reply */
5505 if (IN_SET(r
, -ETIMEDOUT
, -ECONNRESET
) && streq(method
, "Reexecute"))
5508 if (r
< 0 && arg_action
== ACTION_SYSTEMCTL
)
5509 return log_error_errno(r
, "Failed to reload daemon: %s", bus_error_message(&error
, r
));
5511 /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
5512 * old ways of doing things, hence don't log any error in that case here. */
5514 return r
< 0 ? r
: 0;
5517 static int trivial_method(int argc
, char *argv
[], void *userdata
) {
5518 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5526 r
= acquire_bus(BUS_MANAGER
, &bus
);
5530 polkit_agent_open_maybe();
5533 streq(argv
[0], "clear-jobs") ||
5534 streq(argv
[0], "cancel") ? "ClearJobs" :
5535 streq(argv
[0], "reset-failed") ? "ResetFailed" :
5536 streq(argv
[0], "halt") ? "Halt" :
5537 streq(argv
[0], "reboot") ? "Reboot" :
5538 streq(argv
[0], "kexec") ? "KExec" :
5539 streq(argv
[0], "exit") ? "Exit" :
5540 /* poweroff */ "PowerOff";
5542 r
= sd_bus_call_method(
5544 "org.freedesktop.systemd1",
5545 "/org/freedesktop/systemd1",
5546 "org.freedesktop.systemd1.Manager",
5551 if (r
< 0 && arg_action
== ACTION_SYSTEMCTL
)
5552 return log_error_errno(r
, "Failed to execute operation: %s", bus_error_message(&error
, r
));
5554 /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
5555 * old ways of doing things, hence don't log any error in that case here. */
5557 return r
< 0 ? r
: 0;
5560 static int reset_failed(int argc
, char *argv
[], void *userdata
) {
5561 _cleanup_strv_free_
char **names
= NULL
;
5567 return trivial_method(argc
, argv
, userdata
);
5569 r
= acquire_bus(BUS_MANAGER
, &bus
);
5573 polkit_agent_open_maybe();
5575 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
5577 return log_error_errno(r
, "Failed to expand names: %m");
5579 STRV_FOREACH(name
, names
) {
5580 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5582 q
= sd_bus_call_method(
5584 "org.freedesktop.systemd1",
5585 "/org/freedesktop/systemd1",
5586 "org.freedesktop.systemd1.Manager",
5592 log_error_errno(q
, "Failed to reset failed state of unit %s: %s", *name
, bus_error_message(&error
, q
));
5601 static int print_variable(const char *s
) {
5603 _cleanup_free_
char *esc
= NULL
;
5605 sep
= strchr(s
, '=');
5607 log_error("Invalid environment block");
5611 esc
= shell_maybe_quote(sep
+ 1, ESCAPE_POSIX
);
5615 printf("%.*s=%s\n", (int)(sep
-s
), s
, esc
);
5619 static int show_environment(int argc
, char *argv
[], void *userdata
) {
5620 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5621 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5626 r
= acquire_bus(BUS_MANAGER
, &bus
);
5630 (void) pager_open(arg_no_pager
, false);
5632 r
= sd_bus_get_property(
5634 "org.freedesktop.systemd1",
5635 "/org/freedesktop/systemd1",
5636 "org.freedesktop.systemd1.Manager",
5642 return log_error_errno(r
, "Failed to get environment: %s", bus_error_message(&error
, r
));
5644 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
5646 return bus_log_parse_error(r
);
5648 while ((r
= sd_bus_message_read_basic(reply
, SD_BUS_TYPE_STRING
, &text
)) > 0) {
5649 r
= print_variable(text
);
5654 return bus_log_parse_error(r
);
5656 r
= sd_bus_message_exit_container(reply
);
5658 return bus_log_parse_error(r
);
5663 static int switch_root(int argc
, char *argv
[], void *userdata
) {
5664 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5665 _cleanup_free_
char *cmdline_init
= NULL
;
5666 const char *root
, *init
;
5670 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
5671 log_error("Cannot switch root remotely.");
5675 if (argc
< 2 || argc
> 3) {
5676 log_error("Wrong number of arguments.");
5685 r
= parse_env_file("/proc/cmdline", WHITESPACE
,
5686 "init", &cmdline_init
,
5689 log_debug_errno(r
, "Failed to parse /proc/cmdline: %m");
5691 init
= cmdline_init
;
5694 init
= empty_to_null(init
);
5696 const char *root_systemd_path
= NULL
, *root_init_path
= NULL
;
5698 root_systemd_path
= strjoina(root
, "/" SYSTEMD_BINARY_PATH
);
5699 root_init_path
= strjoina(root
, "/", init
);
5701 /* If the passed init is actually the same as the
5702 * systemd binary, then let's suppress it. */
5703 if (files_same(root_init_path
, root_systemd_path
, 0) > 0)
5707 /* Instruct PID1 to exclude us from its killing spree applied during
5708 * the transition. Otherwise we would exit with a failure status even
5709 * though the switch to the new root has succeed. */
5710 argv_cmdline
[0] = '@';
5712 r
= acquire_bus(BUS_MANAGER
, &bus
);
5716 /* If we are slow to exit after the root switch, the new systemd instance
5717 * will send us a signal to terminate. Just ignore it and exit normally.
5718 * This way the unit does not end up as failed.
5720 r
= ignore_signals(SIGTERM
, -1);
5722 log_warning_errno(r
, "Failed to change disposition of SIGTERM to ignore: %m");
5724 log_debug("Switching root - root: %s; init: %s", root
, strna(init
));
5726 r
= sd_bus_call_method(
5728 "org.freedesktop.systemd1",
5729 "/org/freedesktop/systemd1",
5730 "org.freedesktop.systemd1.Manager",
5736 (void) default_signals(SIGTERM
, -1);
5738 return log_error_errno(r
, "Failed to switch root: %s", bus_error_message(&error
, r
));
5744 static int set_environment(int argc
, char *argv
[], void *userdata
) {
5745 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5746 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5754 r
= acquire_bus(BUS_MANAGER
, &bus
);
5758 polkit_agent_open_maybe();
5760 method
= streq(argv
[0], "set-environment")
5762 : "UnsetEnvironment";
5764 r
= sd_bus_message_new_method_call(
5767 "org.freedesktop.systemd1",
5768 "/org/freedesktop/systemd1",
5769 "org.freedesktop.systemd1.Manager",
5772 return bus_log_create_error(r
);
5774 r
= sd_bus_message_append_strv(m
, strv_skip(argv
, 1));
5776 return bus_log_create_error(r
);
5778 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5780 return log_error_errno(r
, "Failed to set environment: %s", bus_error_message(&error
, r
));
5785 static int import_environment(int argc
, char *argv
[], void *userdata
) {
5786 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5787 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5791 r
= acquire_bus(BUS_MANAGER
, &bus
);
5795 polkit_agent_open_maybe();
5797 r
= sd_bus_message_new_method_call(
5800 "org.freedesktop.systemd1",
5801 "/org/freedesktop/systemd1",
5802 "org.freedesktop.systemd1.Manager",
5805 return bus_log_create_error(r
);
5808 r
= sd_bus_message_append_strv(m
, environ
);
5812 r
= sd_bus_message_open_container(m
, 'a', "s");
5814 return bus_log_create_error(r
);
5816 STRV_FOREACH(a
, strv_skip(argv
, 1)) {
5818 if (!env_name_is_valid(*a
)) {
5819 log_error("Not a valid environment variable name: %s", *a
);
5823 STRV_FOREACH(b
, environ
) {
5826 eq
= startswith(*b
, *a
);
5827 if (eq
&& *eq
== '=') {
5829 r
= sd_bus_message_append(m
, "s", *b
);
5831 return bus_log_create_error(r
);
5838 r
= sd_bus_message_close_container(m
);
5841 return bus_log_create_error(r
);
5843 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5845 return log_error_errno(r
, "Failed to import environment: %s", bus_error_message(&error
, r
));
5850 static int enable_sysv_units(const char *verb
, char **args
) {
5853 #if HAVE_SYSV_COMPAT
5854 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
5857 /* Processes all SysV units, and reshuffles the array so that afterwards only the native units remain */
5859 if (arg_scope
!= UNIT_FILE_SYSTEM
)
5862 if (getenv_bool("SYSTEMCTL_SKIP_SYSV") > 0)
5865 if (!STR_IN_SET(verb
,
5871 r
= lookup_paths_init(&paths
, arg_scope
, LOOKUP_PATHS_EXCLUDE_GENERATED
, arg_root
);
5878 const char *argv
[] = {
5879 ROOTLIBEXECDIR
"/systemd-sysv-install",
5886 _cleanup_free_
char *p
= NULL
, *q
= NULL
, *l
= NULL
;
5887 bool found_native
= false, found_sysv
;
5895 if (!endswith(name
, ".service"))
5898 if (path_is_absolute(name
))
5901 j
= unit_file_exists(arg_scope
, &paths
, name
);
5902 if (j
< 0 && !IN_SET(j
, -ELOOP
, -ERFKILL
, -EADDRNOTAVAIL
))
5903 return log_error_errno(j
, "Failed to lookup unit file state: %m");
5904 found_native
= j
!= 0;
5906 /* If we have both a native unit and a SysV script, enable/disable them both (below); for is-enabled,
5907 * prefer the native unit */
5908 if (found_native
&& streq(verb
, "is-enabled"))
5911 p
= path_join(arg_root
, SYSTEM_SYSVINIT_PATH
, name
);
5915 p
[strlen(p
) - STRLEN(".service")] = 0;
5916 found_sysv
= access(p
, F_OK
) >= 0;
5922 log_info("Synchronizing state of %s with SysV service script with %s.", name
, argv
[0]);
5924 log_info("%s is not a native service, redirecting to systemd-sysv-install.", name
);
5927 if (!isempty(arg_root
))
5928 argv
[c
++] = q
= strappend("--root=", arg_root
);
5931 argv
[c
++] = basename(p
);
5934 l
= strv_join((char**)argv
, " ");
5939 log_info("Executing: %s", l
);
5941 j
= safe_fork("(sysv-install)", FORK_RESET_SIGNALS
|FORK_DEATHSIG
|FORK_LOG
, &pid
);
5946 execv(argv
[0], (char**) argv
);
5947 log_error_errno(errno
, "Failed to execute %s: %m", argv
[0]);
5948 _exit(EXIT_FAILURE
);
5951 j
= wait_for_terminate_and_check("sysv-install", pid
, WAIT_LOG_ABNORMAL
);
5954 if (streq(verb
, "is-enabled")) {
5955 if (j
== EXIT_SUCCESS
) {
5964 } else if (j
!= EXIT_SUCCESS
)
5965 return -EBADE
; /* We don't warn here, under the assumption the script already showed an explanation */
5970 /* Remove this entry, so that we don't try enabling it as native unit */
5973 assert(args
[f
] == name
);
5974 strv_remove(args
, name
);
5981 static int mangle_names(char **original_names
, char ***mangled_names
) {
5982 char **i
, **l
, **name
;
5985 l
= i
= new(char*, strv_length(original_names
) + 1);
5989 STRV_FOREACH(name
, original_names
) {
5991 /* When enabling units qualified path names are OK,
5992 * too, hence allow them explicitly. */
5994 if (is_path(*name
)) {
6001 r
= unit_name_mangle(*name
, arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
, i
);
6005 return log_error_errno(r
, "Failed to mangle unit name: %m");
6018 static int normalize_filenames(char **names
) {
6022 STRV_FOREACH(u
, names
)
6023 if (!path_is_absolute(*u
)) {
6024 char* normalized_path
;
6026 if (!isempty(arg_root
)) {
6027 log_error("Non-absolute paths are not allowed when --root is used: %s", *u
);
6031 if (!strchr(*u
,'/')) {
6032 log_error("Link argument does contain at least one directory separator: %s", *u
);
6036 r
= path_make_absolute_cwd(*u
, &normalized_path
);
6040 free_and_replace(*u
, normalized_path
);
6046 static int normalize_names(char **names
, bool warn_if_path
) {
6048 bool was_path
= false;
6050 STRV_FOREACH(u
, names
) {
6056 r
= free_and_strdup(u
, basename(*u
));
6058 return log_error_errno(r
, "Failed to normalize unit file path: %m");
6063 if (warn_if_path
&& was_path
)
6064 log_warning("Warning: Can't execute disable on the unit file path. Proceeding with the unit name.");
6069 static int unit_exists(LookupPaths
*lp
, const char *unit
) {
6070 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6071 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
6072 _cleanup_free_
char *path
= NULL
;
6073 static const struct bus_properties_map property_map
[] = {
6074 { "LoadState", "s", NULL
, offsetof(UnitStatusInfo
, load_state
) },
6075 { "ActiveState", "s", NULL
, offsetof(UnitStatusInfo
, active_state
)},
6078 UnitStatusInfo info
= {};
6082 if (unit_name_is_valid(unit
, UNIT_NAME_TEMPLATE
))
6083 return unit_find_template_path(unit
, lp
, NULL
, NULL
);
6085 path
= unit_dbus_path_from_name(unit
);
6089 r
= acquire_bus(BUS_MANAGER
, &bus
);
6093 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", path
, property_map
, &error
, &m
, &info
);
6095 return log_error_errno(r
, "Failed to get properties: %s", bus_error_message(&error
, r
));
6097 return !streq_ptr(info
.load_state
, "not-found") || !streq_ptr(info
.active_state
, "inactive");
6100 static int enable_unit(int argc
, char *argv
[], void *userdata
) {
6101 _cleanup_strv_free_
char **names
= NULL
;
6102 const char *verb
= argv
[0];
6103 UnitFileChange
*changes
= NULL
;
6104 unsigned n_changes
= 0;
6105 int carries_install_info
= -1;
6106 bool ignore_carries_install_info
= arg_quiet
;
6112 r
= mangle_names(strv_skip(argv
, 1), &names
);
6116 r
= enable_sysv_units(verb
, names
);
6120 /* If the operation was fully executed by the SysV compat, let's finish early */
6121 if (strv_isempty(names
)) {
6122 if (arg_no_reload
|| install_client_side())
6124 return daemon_reload(argc
, argv
, userdata
);
6127 if (streq(verb
, "disable")) {
6128 r
= normalize_names(names
, true);
6133 if (streq(verb
, "link")) {
6134 r
= normalize_filenames(names
);
6139 if (install_client_side()) {
6140 UnitFileFlags flags
;
6142 flags
= args_to_flags();
6143 if (streq(verb
, "enable")) {
6144 r
= unit_file_enable(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6145 carries_install_info
= r
;
6146 } else if (streq(verb
, "disable"))
6147 r
= unit_file_disable(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6148 else if (streq(verb
, "reenable")) {
6149 r
= unit_file_reenable(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6150 carries_install_info
= r
;
6151 } else if (streq(verb
, "link"))
6152 r
= unit_file_link(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6153 else if (streq(verb
, "preset")) {
6154 r
= unit_file_preset(arg_scope
, flags
, arg_root
, names
, arg_preset_mode
, &changes
, &n_changes
);
6155 } else if (streq(verb
, "mask"))
6156 r
= unit_file_mask(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6157 else if (streq(verb
, "unmask"))
6158 r
= unit_file_unmask(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6159 else if (streq(verb
, "revert"))
6160 r
= unit_file_revert(arg_scope
, arg_root
, names
, &changes
, &n_changes
);
6162 assert_not_reached("Unknown verb");
6164 unit_file_dump_changes(r
, verb
, changes
, n_changes
, arg_quiet
);
6169 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
, *m
= NULL
;
6170 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6171 bool expect_carries_install_info
= false;
6172 bool send_runtime
= true, send_force
= true, send_preset_mode
= false;
6176 if (STR_IN_SET(verb
, "mask", "unmask")) {
6178 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
6180 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
6184 STRV_FOREACH(name
, names
) {
6185 r
= unit_exists(&lp
, *name
);
6189 log_notice("Unit %s does not exist, proceeding anyway.", *names
);
6193 r
= acquire_bus(BUS_MANAGER
, &bus
);
6197 polkit_agent_open_maybe();
6199 if (streq(verb
, "enable")) {
6200 method
= "EnableUnitFiles";
6201 expect_carries_install_info
= true;
6202 } else if (streq(verb
, "disable")) {
6203 method
= "DisableUnitFiles";
6205 } else if (streq(verb
, "reenable")) {
6206 method
= "ReenableUnitFiles";
6207 expect_carries_install_info
= true;
6208 } else if (streq(verb
, "link"))
6209 method
= "LinkUnitFiles";
6210 else if (streq(verb
, "preset")) {
6212 if (arg_preset_mode
!= UNIT_FILE_PRESET_FULL
) {
6213 method
= "PresetUnitFilesWithMode";
6214 send_preset_mode
= true;
6216 method
= "PresetUnitFiles";
6218 expect_carries_install_info
= true;
6219 ignore_carries_install_info
= true;
6220 } else if (streq(verb
, "mask"))
6221 method
= "MaskUnitFiles";
6222 else if (streq(verb
, "unmask")) {
6223 method
= "UnmaskUnitFiles";
6225 } else if (streq(verb
, "revert")) {
6226 method
= "RevertUnitFiles";
6227 send_runtime
= send_force
= false;
6229 assert_not_reached("Unknown verb");
6231 r
= sd_bus_message_new_method_call(
6234 "org.freedesktop.systemd1",
6235 "/org/freedesktop/systemd1",
6236 "org.freedesktop.systemd1.Manager",
6239 return bus_log_create_error(r
);
6241 r
= sd_bus_message_append_strv(m
, names
);
6243 return bus_log_create_error(r
);
6245 if (send_preset_mode
) {
6246 r
= sd_bus_message_append(m
, "s", unit_file_preset_mode_to_string(arg_preset_mode
));
6248 return bus_log_create_error(r
);
6252 r
= sd_bus_message_append(m
, "b", arg_runtime
);
6254 return bus_log_create_error(r
);
6258 r
= sd_bus_message_append(m
, "b", arg_force
);
6260 return bus_log_create_error(r
);
6263 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
6265 return log_error_errno(r
, "Failed to %s unit: %s", verb
, bus_error_message(&error
, r
));
6267 if (expect_carries_install_info
) {
6268 r
= sd_bus_message_read(reply
, "b", &carries_install_info
);
6270 return bus_log_parse_error(r
);
6273 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
6277 /* Try to reload if enabled */
6279 r
= daemon_reload(argc
, argv
, userdata
);
6284 if (carries_install_info
== 0 && !ignore_carries_install_info
)
6285 log_warning("The unit files have no installation config (WantedBy, RequiredBy, Also, Alias\n"
6286 "settings in the [Install] section, and DefaultInstance for template units).\n"
6287 "This means they are not meant to be enabled using systemctl.\n"
6288 "Possible reasons for having this kind of units are:\n"
6289 "1) A unit may be statically enabled by being symlinked from another unit's\n"
6290 " .wants/ or .requires/ directory.\n"
6291 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
6292 " a requirement dependency on it.\n"
6293 "3) A unit may be started when needed via activation (socket, path, timer,\n"
6294 " D-Bus, udev, scripted systemctl call, ...).\n"
6295 "4) In case of template units, the unit is meant to be enabled with some\n"
6296 " instance name specified.");
6298 if (arg_now
&& STR_IN_SET(argv
[0], "enable", "disable", "mask")) {
6302 r
= acquire_bus(BUS_MANAGER
, &bus
);
6306 len
= strv_length(names
);
6308 char *new_args
[len
+ 2];
6310 new_args
[0] = (char*) (streq(argv
[0], "enable") ? "start" : "stop");
6311 for (i
= 0; i
< len
; i
++)
6312 new_args
[i
+ 1] = basename(names
[i
]);
6313 new_args
[i
+ 1] = NULL
;
6315 r
= start_unit(len
+ 1, new_args
, userdata
);
6320 unit_file_changes_free(changes
, n_changes
);
6325 static int add_dependency(int argc
, char *argv
[], void *userdata
) {
6326 _cleanup_strv_free_
char **names
= NULL
;
6327 _cleanup_free_
char *target
= NULL
;
6328 const char *verb
= argv
[0];
6329 UnitFileChange
*changes
= NULL
;
6330 unsigned n_changes
= 0;
6337 r
= unit_name_mangle_with_suffix(argv
[1], arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
, ".target", &target
);
6339 return log_error_errno(r
, "Failed to mangle unit name: %m");
6341 r
= mangle_names(strv_skip(argv
, 2), &names
);
6345 if (streq(verb
, "add-wants"))
6347 else if (streq(verb
, "add-requires"))
6348 dep
= UNIT_REQUIRES
;
6350 assert_not_reached("Unknown verb");
6352 if (install_client_side()) {
6353 r
= unit_file_add_dependency(arg_scope
, args_to_flags(), arg_root
, names
, target
, dep
, &changes
, &n_changes
);
6354 unit_file_dump_changes(r
, "add dependency on", changes
, n_changes
, arg_quiet
);
6359 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
, *m
= NULL
;
6360 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6363 r
= acquire_bus(BUS_MANAGER
, &bus
);
6367 polkit_agent_open_maybe();
6369 r
= sd_bus_message_new_method_call(
6372 "org.freedesktop.systemd1",
6373 "/org/freedesktop/systemd1",
6374 "org.freedesktop.systemd1.Manager",
6375 "AddDependencyUnitFiles");
6377 return bus_log_create_error(r
);
6379 r
= sd_bus_message_append_strv(m
, names
);
6381 return bus_log_create_error(r
);
6383 r
= sd_bus_message_append(m
, "ssbb", target
, unit_dependency_to_string(dep
), arg_runtime
, arg_force
);
6385 return bus_log_create_error(r
);
6387 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
6389 return log_error_errno(r
, "Failed to add dependency: %s", bus_error_message(&error
, r
));
6391 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
6395 if (arg_no_reload
) {
6400 r
= daemon_reload(argc
, argv
, userdata
);
6404 unit_file_changes_free(changes
, n_changes
);
6409 static int preset_all(int argc
, char *argv
[], void *userdata
) {
6410 UnitFileChange
*changes
= NULL
;
6411 unsigned n_changes
= 0;
6414 if (install_client_side()) {
6415 r
= unit_file_preset_all(arg_scope
, args_to_flags(), arg_root
, arg_preset_mode
, &changes
, &n_changes
);
6416 unit_file_dump_changes(r
, "preset", changes
, n_changes
, arg_quiet
);
6421 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6422 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6425 r
= acquire_bus(BUS_MANAGER
, &bus
);
6429 polkit_agent_open_maybe();
6431 r
= sd_bus_call_method(
6433 "org.freedesktop.systemd1",
6434 "/org/freedesktop/systemd1",
6435 "org.freedesktop.systemd1.Manager",
6436 "PresetAllUnitFiles",
6440 unit_file_preset_mode_to_string(arg_preset_mode
),
6444 return log_error_errno(r
, "Failed to preset all units: %s", bus_error_message(&error
, r
));
6446 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
6450 if (arg_no_reload
) {
6455 r
= daemon_reload(argc
, argv
, userdata
);
6459 unit_file_changes_free(changes
, n_changes
);
6464 static int show_installation_targets_client_side(const char *name
) {
6465 UnitFileChange
*changes
= NULL
;
6466 unsigned n_changes
= 0, i
;
6467 UnitFileFlags flags
;
6471 p
= STRV_MAKE(name
);
6472 flags
= UNIT_FILE_DRY_RUN
|
6473 (arg_runtime
? UNIT_FILE_RUNTIME
: 0);
6475 r
= unit_file_disable(UNIT_FILE_SYSTEM
, flags
, NULL
, p
, &changes
, &n_changes
);
6477 return log_error_errno(r
, "Failed to get file links for %s: %m", name
);
6479 for (i
= 0; i
< n_changes
; i
++)
6480 if (changes
[i
].type
== UNIT_FILE_UNLINK
)
6481 printf(" %s\n", changes
[i
].path
);
6486 static int show_installation_targets(sd_bus
*bus
, const char *name
) {
6487 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6488 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6492 r
= sd_bus_call_method(
6494 "org.freedesktop.systemd1",
6495 "/org/freedesktop/systemd1",
6496 "org.freedesktop.systemd1.Manager",
6500 "sb", name
, arg_runtime
);
6502 return log_error_errno(r
, "Failed to get unit file links for %s: %s", name
, bus_error_message(&error
, r
));
6504 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
6506 return bus_log_parse_error(r
);
6508 while ((r
= sd_bus_message_read(reply
, "s", &link
)) > 0)
6509 printf(" %s\n", link
);
6512 return bus_log_parse_error(r
);
6514 r
= sd_bus_message_exit_container(reply
);
6516 return bus_log_parse_error(r
);
6521 static int unit_is_enabled(int argc
, char *argv
[], void *userdata
) {
6523 _cleanup_strv_free_
char **names
= NULL
;
6528 r
= mangle_names(strv_skip(argv
, 1), &names
);
6532 r
= enable_sysv_units(argv
[0], names
);
6538 if (install_client_side()) {
6539 STRV_FOREACH(name
, names
) {
6540 UnitFileState state
;
6542 r
= unit_file_get_state(arg_scope
, arg_root
, *name
, &state
);
6544 return log_error_errno(r
, "Failed to get unit file state for %s: %m", *name
);
6548 UNIT_FILE_ENABLED_RUNTIME
,
6551 UNIT_FILE_GENERATED
))
6555 puts(unit_file_state_to_string(state
));
6557 r
= show_installation_targets_client_side(*name
);
6566 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6569 r
= acquire_bus(BUS_MANAGER
, &bus
);
6573 STRV_FOREACH(name
, names
) {
6574 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6577 r
= sd_bus_call_method(
6579 "org.freedesktop.systemd1",
6580 "/org/freedesktop/systemd1",
6581 "org.freedesktop.systemd1.Manager",
6587 return log_error_errno(r
, "Failed to get unit file state for %s: %s", *name
, bus_error_message(&error
, r
));
6589 r
= sd_bus_message_read(reply
, "s", &s
);
6591 return bus_log_parse_error(r
);
6593 if (STR_IN_SET(s
, "enabled", "enabled-runtime", "static", "indirect", "generated"))
6599 r
= show_installation_targets(bus
, *name
);
6607 return enabled
? EXIT_SUCCESS
: EXIT_FAILURE
;
6610 static int is_system_running(int argc
, char *argv
[], void *userdata
) {
6611 _cleanup_free_
char *state
= NULL
;
6615 if (running_in_chroot() > 0 || (arg_transport
== BUS_TRANSPORT_LOCAL
&& !sd_booted())) {
6618 return EXIT_FAILURE
;
6621 r
= acquire_bus(BUS_MANAGER
, &bus
);
6625 r
= sd_bus_get_property_string(
6627 "org.freedesktop.systemd1",
6628 "/org/freedesktop/systemd1",
6629 "org.freedesktop.systemd1.Manager",
6642 return streq(state
, "running") ? EXIT_SUCCESS
: EXIT_FAILURE
;
6645 static int create_edit_temp_file(const char *new_path
, const char *original_path
, char **ret_tmp_fn
) {
6646 _cleanup_free_
char *t
= NULL
;
6650 assert(original_path
);
6653 r
= tempfn_random(new_path
, NULL
, &t
);
6655 return log_error_errno(r
, "Failed to determine temporary filename for \"%s\": %m", new_path
);
6657 r
= mkdir_parents(new_path
, 0755);
6659 return log_error_errno(r
, "Failed to create directories for \"%s\": %m", new_path
);
6661 r
= copy_file(original_path
, t
, 0, 0644, 0, COPY_REFLINK
);
6666 return log_error_errno(r
, "Failed to create temporary file \"%s\": %m", t
);
6669 return log_error_errno(r
, "Failed to create temporary file for \"%s\": %m", new_path
);
6671 *ret_tmp_fn
= TAKE_PTR(t
);
6676 static int get_file_to_edit(
6677 const LookupPaths
*paths
,
6681 _cleanup_free_
char *path
= NULL
, *run
= NULL
;
6686 path
= strjoin(paths
->persistent_config
, "/", name
);
6691 run
= strjoin(paths
->runtime_config
, "/", name
);
6697 if (access(path
, F_OK
) >= 0) {
6698 log_error("Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.", run
, path
);
6702 *ret_path
= TAKE_PTR(run
);
6704 *ret_path
= TAKE_PTR(path
);
6709 static int unit_file_create_new(
6710 const LookupPaths
*paths
,
6711 const char *unit_name
,
6713 char **ret_new_path
,
6714 char **ret_tmp_path
) {
6716 char *tmp_new_path
, *tmp_tmp_path
, *ending
;
6720 assert(ret_new_path
);
6721 assert(ret_tmp_path
);
6723 ending
= strjoina(unit_name
, suffix
);
6724 r
= get_file_to_edit(paths
, ending
, &tmp_new_path
);
6728 r
= create_edit_temp_file(tmp_new_path
, tmp_new_path
, &tmp_tmp_path
);
6734 *ret_new_path
= tmp_new_path
;
6735 *ret_tmp_path
= tmp_tmp_path
;
6740 static int unit_file_create_copy(
6741 const LookupPaths
*paths
,
6742 const char *unit_name
,
6743 const char *fragment_path
,
6744 char **ret_new_path
,
6745 char **ret_tmp_path
) {
6747 char *tmp_new_path
, *tmp_tmp_path
;
6750 assert(fragment_path
);
6752 assert(ret_new_path
);
6753 assert(ret_tmp_path
);
6755 r
= get_file_to_edit(paths
, unit_name
, &tmp_new_path
);
6759 if (!path_equal(fragment_path
, tmp_new_path
) && access(tmp_new_path
, F_OK
) == 0) {
6762 r
= ask_char(&response
, "yn", "\"%s\" already exists. Overwrite with \"%s\"? [(y)es, (n)o] ", tmp_new_path
, fragment_path
);
6767 if (response
!= 'y') {
6768 log_warning("%s ignored", unit_name
);
6770 return -EKEYREJECTED
;
6774 r
= create_edit_temp_file(tmp_new_path
, fragment_path
, &tmp_tmp_path
);
6780 *ret_new_path
= tmp_new_path
;
6781 *ret_tmp_path
= tmp_tmp_path
;
6786 static int run_editor(char **paths
) {
6791 r
= safe_fork("(editor)", FORK_RESET_SIGNALS
|FORK_DEATHSIG
|FORK_LOG
|FORK_WAIT
, NULL
);
6796 char *editor
, **editor_args
= NULL
;
6797 char **tmp_path
, **original_path
, *p
;
6798 unsigned n_editor_args
= 0, i
= 1;
6801 argc
= strv_length(paths
)/2 + 1;
6803 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
6804 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
6805 * we try to execute well known editors
6807 editor
= getenv("SYSTEMD_EDITOR");
6809 editor
= getenv("EDITOR");
6811 editor
= getenv("VISUAL");
6813 if (!isempty(editor
)) {
6814 editor_args
= strv_split(editor
, WHITESPACE
);
6817 _exit(EXIT_FAILURE
);
6819 n_editor_args
= strv_length(editor_args
);
6820 argc
+= n_editor_args
- 1;
6822 args
= newa(const char*, argc
+ 1);
6824 if (n_editor_args
> 0) {
6825 args
[0] = editor_args
[0];
6826 for (; i
< n_editor_args
; i
++)
6827 args
[i
] = editor_args
[i
];
6830 STRV_FOREACH_PAIR(original_path
, tmp_path
, paths
) {
6831 args
[i
] = *tmp_path
;
6836 if (n_editor_args
> 0)
6837 execvp(args
[0], (char* const*) args
);
6839 FOREACH_STRING(p
, "editor", "nano", "vim", "vi") {
6841 execvp(p
, (char* const*) args
);
6842 /* We do not fail if the editor doesn't exist
6843 * because we want to try each one of them before
6846 if (errno
!= ENOENT
) {
6847 log_error_errno(errno
, "Failed to execute %s: %m", editor
);
6848 _exit(EXIT_FAILURE
);
6852 log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR, $EDITOR or $VISUAL.");
6853 _exit(EXIT_FAILURE
);
6859 static int find_paths_to_edit(sd_bus
*bus
, char **names
, char ***paths
) {
6860 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
6867 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
6871 STRV_FOREACH(name
, names
) {
6872 _cleanup_free_
char *path
= NULL
, *new_path
= NULL
, *tmp_path
= NULL
, *tmp_name
= NULL
;
6873 const char *unit_name
;
6875 r
= unit_find_paths(bus
, *name
, &lp
, &path
, NULL
);
6883 log_error("Run 'systemctl edit%s --force %s' to create a new unit.",
6884 arg_scope
== UNIT_FILE_GLOBAL
? " --global" :
6885 arg_scope
== UNIT_FILE_USER
? " --user" : "",
6890 /* Create a new unit from scratch */
6892 r
= unit_file_create_new(&lp
, unit_name
,
6893 arg_full
? NULL
: ".d/override.conf",
6894 &new_path
, &tmp_path
);
6898 unit_name
= basename(path
);
6899 /* We follow unit aliases, but we need to propagate the instance */
6900 if (unit_name_is_valid(*name
, UNIT_NAME_INSTANCE
) &&
6901 unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
6902 _cleanup_free_
char *instance
= NULL
;
6904 r
= unit_name_to_instance(*name
, &instance
);
6908 r
= unit_name_replace_instance(unit_name
, instance
, &tmp_name
);
6912 unit_name
= tmp_name
;
6916 r
= unit_file_create_copy(&lp
, unit_name
, path
, &new_path
, &tmp_path
);
6918 r
= unit_file_create_new(&lp
, unit_name
, ".d/override.conf", &new_path
, &tmp_path
);
6923 r
= strv_push_pair(paths
, new_path
, tmp_path
);
6926 new_path
= tmp_path
= NULL
;
6932 static int edit(int argc
, char *argv
[], void *userdata
) {
6933 _cleanup_strv_free_
char **names
= NULL
;
6934 _cleanup_strv_free_
char **paths
= NULL
;
6935 char **original
, **tmp
;
6940 log_error("Cannot edit units if not on a tty.");
6944 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
6945 log_error("Cannot edit units remotely.");
6949 r
= acquire_bus(BUS_MANAGER
, &bus
);
6953 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
6955 return log_error_errno(r
, "Failed to expand names: %m");
6957 r
= find_paths_to_edit(bus
, names
, &paths
);
6961 if (strv_isempty(paths
))
6964 r
= run_editor(paths
);
6968 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
6969 /* If the temporary file is empty we ignore it. It's
6970 * useful if the user wants to cancel its modification
6972 if (null_or_empty_path(*tmp
)) {
6973 log_warning("Editing \"%s\" canceled: temporary file is empty.", *original
);
6977 r
= rename(*tmp
, *original
);
6979 r
= log_error_errno(errno
, "Failed to rename \"%s\" to \"%s\": %m", *tmp
, *original
);
6986 if (!arg_no_reload
&& !install_client_side())
6987 r
= daemon_reload(argc
, argv
, userdata
);
6990 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
6991 (void) unlink(*tmp
);
6993 /* Removing empty dropin dirs */
6995 _cleanup_free_
char *dir
;
6997 dir
= dirname_malloc(*original
);
7001 /* no need to check if the dir is empty, rmdir
7002 * does nothing if it is not the case.
7011 static void systemctl_help(void) {
7013 (void) pager_open(arg_no_pager
, false);
7015 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
7016 "Query or send control commands to the systemd manager.\n\n"
7017 " -h --help Show this help\n"
7018 " --version Show package version\n"
7019 " --system Connect to system manager\n"
7020 " --user Connect to user service manager\n"
7021 " -H --host=[USER@]HOST\n"
7022 " Operate on remote host\n"
7023 " -M --machine=CONTAINER\n"
7024 " Operate on local container\n"
7025 " -t --type=TYPE List units of a particular type\n"
7026 " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n"
7027 " -p --property=NAME Show only properties by this name\n"
7028 " -a --all Show all properties/all units currently in memory,\n"
7029 " including dead/empty ones. To list all units installed on\n"
7030 " the system, use the 'list-unit-files' command instead.\n"
7031 " --failed Same as --state=failed\n"
7032 " -l --full Don't ellipsize unit names on output\n"
7033 " -r --recursive Show unit list of host and local containers\n"
7034 " --reverse Show reverse dependencies with 'list-dependencies'\n"
7035 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
7036 " queueing a new job\n"
7037 " --show-types When showing sockets, explicitly show their type\n"
7038 " --value When showing properties, only print the value\n"
7039 " -i --ignore-inhibitors\n"
7040 " When shutting down or sleeping, ignore inhibitors\n"
7041 " --kill-who=WHO Who to send signal to\n"
7042 " -s --signal=SIGNAL Which signal to send\n"
7043 " --now Start or stop unit in addition to enabling or disabling it\n"
7044 " --dry-run Only print what would be done\n"
7045 " -q --quiet Suppress output\n"
7046 " --wait For (re)start, wait until service stopped again\n"
7047 " --no-block Do not wait until operation finished\n"
7048 " --no-wall Don't send wall message before halt/power-off/reboot\n"
7049 " --no-reload Don't reload daemon after en-/dis-abling unit files\n"
7050 " --no-legend Do not print a legend (column headers and hints)\n"
7051 " --no-pager Do not pipe output into a pager\n"
7052 " --no-ask-password\n"
7053 " Do not ask for system passwords\n"
7054 " --global Enable/disable/mask unit files globally\n"
7055 " --runtime Enable/disable/mask unit files temporarily until next\n"
7057 " -f --force When enabling unit files, override existing symlinks\n"
7058 " When shutting down, execute action immediately\n"
7059 " --preset-mode= Apply only enable, only disable, or all presets\n"
7060 " --root=PATH Enable/disable/mask unit files in the specified root\n"
7062 " -n --lines=INTEGER Number of journal entries to show\n"
7063 " -o --output=STRING Change journal output mode (short, short-precise,\n"
7064 " short-iso, short-iso-precise, short-full,\n"
7065 " short-monotonic, short-unix,\n"
7066 " verbose, export, json, json-pretty, json-sse, cat)\n"
7067 " --firmware-setup Tell the firmware to show the setup menu on next boot\n"
7068 " --plain Print unit dependencies as a list instead of a tree\n\n"
7070 " list-units [PATTERN...] List units currently in memory\n"
7071 " list-sockets [PATTERN...] List socket units currently in memory,\n"
7072 " ordered by address\n"
7073 " list-timers [PATTERN...] List timer units currently in memory,\n"
7074 " ordered by next elapse\n"
7075 " start UNIT... Start (activate) one or more units\n"
7076 " stop UNIT... Stop (deactivate) one or more units\n"
7077 " reload UNIT... Reload one or more units\n"
7078 " restart UNIT... Start or restart one or more units\n"
7079 " try-restart UNIT... Restart one or more units if active\n"
7080 " reload-or-restart UNIT... Reload one or more units if possible,\n"
7081 " otherwise start or restart\n"
7082 " try-reload-or-restart UNIT... If active, reload one or more units,\n"
7083 " if supported, otherwise restart\n"
7084 " isolate UNIT Start one unit and stop all others\n"
7085 " kill UNIT... Send signal to processes of a unit\n"
7086 " is-active PATTERN... Check whether units are active\n"
7087 " is-failed PATTERN... Check whether units are failed\n"
7088 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
7089 " show [PATTERN...|JOB...] Show properties of one or more\n"
7090 " units/jobs or the manager\n"
7091 " cat PATTERN... Show files and drop-ins of specified units\n"
7092 " set-property UNIT PROPERTY=VALUE... Sets one or more properties of a unit\n"
7093 " help PATTERN...|PID... Show manual for one or more units\n"
7094 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
7096 " list-dependencies [UNIT] Recursively show units which are required\n"
7097 " or wanted by this unit or by which this\n"
7098 " unit is required or wanted\n\n"
7099 "Unit File Commands:\n"
7100 " list-unit-files [PATTERN...] List installed unit files\n"
7101 " enable [UNIT...|PATH...] Enable one or more unit files\n"
7102 " disable UNIT... Disable one or more unit files\n"
7103 " reenable UNIT... Reenable one or more unit files\n"
7104 " preset UNIT... Enable/disable one or more unit files\n"
7105 " based on preset configuration\n"
7106 " preset-all Enable/disable all unit files based on\n"
7107 " preset configuration\n"
7108 " is-enabled UNIT... Check whether unit files are enabled\n"
7109 " mask UNIT... Mask one or more units\n"
7110 " unmask UNIT... Unmask one or more units\n"
7111 " link PATH... Link one or more units files into\n"
7112 " the search path\n"
7113 " revert UNIT... Revert one or more unit files to vendor\n"
7115 " add-wants TARGET UNIT... Add 'Wants' dependency for the target\n"
7116 " on specified one or more units\n"
7117 " add-requires TARGET UNIT... Add 'Requires' dependency for the target\n"
7118 " on specified one or more units\n"
7119 " edit UNIT... Edit one or more unit files\n"
7120 " get-default Get the name of the default target\n"
7121 " set-default TARGET Set the default target\n\n"
7122 "Machine Commands:\n"
7123 " list-machines [PATTERN...] List local containers and host\n\n"
7125 " list-jobs [PATTERN...] List jobs\n"
7126 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
7127 "Environment Commands:\n"
7128 " show-environment Dump environment\n"
7129 " set-environment VARIABLE=VALUE... Set one or more environment variables\n"
7130 " unset-environment VARIABLE... Unset one or more environment variables\n"
7131 " import-environment [VARIABLE...] Import all or some environment variables\n\n"
7132 "Manager Lifecycle Commands:\n"
7133 " daemon-reload Reload systemd manager configuration\n"
7134 " daemon-reexec Reexecute systemd manager\n\n"
7135 "System Commands:\n"
7136 " is-system-running Check whether system is fully running\n"
7137 " default Enter system default mode\n"
7138 " rescue Enter system rescue mode\n"
7139 " emergency Enter system emergency mode\n"
7140 " halt Shut down and halt the system\n"
7141 " poweroff Shut down and power-off the system\n"
7142 " reboot [ARG] Shut down and reboot the system\n"
7143 " kexec Shut down and reboot the system with kexec\n"
7144 " exit [EXIT_CODE] Request user instance or container exit\n"
7145 " switch-root ROOT [INIT] Change to a different root file system\n"
7146 " suspend Suspend the system\n"
7147 " hibernate Hibernate the system\n"
7148 " hybrid-sleep Hibernate and suspend the system\n"
7149 " suspend-to-hibernate Suspend the system, wake after a period of\n"
7150 " time and put it into hibernate\n",
7151 program_invocation_short_name
);
7154 static void halt_help(void) {
7155 printf("%s [OPTIONS...]%s\n\n"
7156 "%s the system.\n\n"
7157 " --help Show this help\n"
7158 " --halt Halt the machine\n"
7159 " -p --poweroff Switch off the machine\n"
7160 " --reboot Reboot the machine\n"
7161 " -f --force Force immediate halt/power-off/reboot\n"
7162 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
7163 " -d --no-wtmp Don't write wtmp record\n"
7164 " --no-wall Don't send wall message before halt/power-off/reboot\n",
7165 program_invocation_short_name
,
7166 arg_action
== ACTION_REBOOT
? " [ARG]" : "",
7167 arg_action
== ACTION_REBOOT
? "Reboot" :
7168 arg_action
== ACTION_POWEROFF
? "Power off" :
7172 static void shutdown_help(void) {
7173 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
7174 "Shut down the system.\n\n"
7175 " --help Show this help\n"
7176 " -H --halt Halt the machine\n"
7177 " -P --poweroff Power-off the machine\n"
7178 " -r --reboot Reboot the machine\n"
7179 " -h Equivalent to --poweroff, overridden by --halt\n"
7180 " -k Don't halt/power-off/reboot, just send warnings\n"
7181 " --no-wall Don't send wall message before halt/power-off/reboot\n"
7182 " -c Cancel a pending shutdown\n",
7183 program_invocation_short_name
);
7186 static void telinit_help(void) {
7187 printf("%s [OPTIONS...] {COMMAND}\n\n"
7188 "Send control commands to the init daemon.\n\n"
7189 " --help Show this help\n"
7190 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
7192 " 0 Power-off the machine\n"
7193 " 6 Reboot the machine\n"
7194 " 2, 3, 4, 5 Start runlevelX.target unit\n"
7195 " 1, s, S Enter rescue mode\n"
7196 " q, Q Reload init daemon configuration\n"
7197 " u, U Reexecute init daemon\n",
7198 program_invocation_short_name
);
7201 static void runlevel_help(void) {
7202 printf("%s [OPTIONS...]\n\n"
7203 "Prints the previous and current runlevel of the init system.\n\n"
7204 " --help Show this help\n",
7205 program_invocation_short_name
);
7208 static void help_types(void) {
7212 puts("Available unit types:");
7213 for (i
= 0; i
< _UNIT_TYPE_MAX
; i
++)
7214 puts(unit_type_to_string(i
));
7217 static void help_states(void) {
7221 puts("Available unit load states:");
7222 for (i
= 0; i
< _UNIT_LOAD_STATE_MAX
; i
++)
7223 puts(unit_load_state_to_string(i
));
7226 puts("\nAvailable unit active states:");
7227 for (i
= 0; i
< _UNIT_ACTIVE_STATE_MAX
; i
++)
7228 puts(unit_active_state_to_string(i
));
7231 puts("\nAvailable automount unit substates:");
7232 for (i
= 0; i
< _AUTOMOUNT_STATE_MAX
; i
++)
7233 puts(automount_state_to_string(i
));
7236 puts("\nAvailable device unit substates:");
7237 for (i
= 0; i
< _DEVICE_STATE_MAX
; i
++)
7238 puts(device_state_to_string(i
));
7241 puts("\nAvailable mount unit substates:");
7242 for (i
= 0; i
< _MOUNT_STATE_MAX
; i
++)
7243 puts(mount_state_to_string(i
));
7246 puts("\nAvailable path unit substates:");
7247 for (i
= 0; i
< _PATH_STATE_MAX
; i
++)
7248 puts(path_state_to_string(i
));
7251 puts("\nAvailable scope unit substates:");
7252 for (i
= 0; i
< _SCOPE_STATE_MAX
; i
++)
7253 puts(scope_state_to_string(i
));
7256 puts("\nAvailable service unit substates:");
7257 for (i
= 0; i
< _SERVICE_STATE_MAX
; i
++)
7258 puts(service_state_to_string(i
));
7261 puts("\nAvailable slice unit substates:");
7262 for (i
= 0; i
< _SLICE_STATE_MAX
; i
++)
7263 puts(slice_state_to_string(i
));
7266 puts("\nAvailable socket unit substates:");
7267 for (i
= 0; i
< _SOCKET_STATE_MAX
; i
++)
7268 puts(socket_state_to_string(i
));
7271 puts("\nAvailable swap unit substates:");
7272 for (i
= 0; i
< _SWAP_STATE_MAX
; i
++)
7273 puts(swap_state_to_string(i
));
7276 puts("\nAvailable target unit substates:");
7277 for (i
= 0; i
< _TARGET_STATE_MAX
; i
++)
7278 puts(target_state_to_string(i
));
7281 puts("\nAvailable timer unit substates:");
7282 for (i
= 0; i
< _TIMER_STATE_MAX
; i
++)
7283 puts(timer_state_to_string(i
));
7286 static int systemctl_parse_argv(int argc
, char *argv
[]) {
7296 ARG_IGNORE_DEPENDENCIES
,
7309 ARG_NO_ASK_PASSWORD
,
7322 static const struct option options
[] = {
7323 { "help", no_argument
, NULL
, 'h' },
7324 { "version", no_argument
, NULL
, ARG_VERSION
},
7325 { "type", required_argument
, NULL
, 't' },
7326 { "property", required_argument
, NULL
, 'p' },
7327 { "all", no_argument
, NULL
, 'a' },
7328 { "reverse", no_argument
, NULL
, ARG_REVERSE
},
7329 { "after", no_argument
, NULL
, ARG_AFTER
},
7330 { "before", no_argument
, NULL
, ARG_BEFORE
},
7331 { "show-types", no_argument
, NULL
, ARG_SHOW_TYPES
},
7332 { "failed", no_argument
, NULL
, ARG_FAILED
}, /* compatibility only */
7333 { "full", no_argument
, NULL
, 'l' },
7334 { "job-mode", required_argument
, NULL
, ARG_JOB_MODE
},
7335 { "fail", no_argument
, NULL
, ARG_FAIL
}, /* compatibility only */
7336 { "irreversible", no_argument
, NULL
, ARG_IRREVERSIBLE
}, /* compatibility only */
7337 { "ignore-dependencies", no_argument
, NULL
, ARG_IGNORE_DEPENDENCIES
}, /* compatibility only */
7338 { "ignore-inhibitors", no_argument
, NULL
, 'i' },
7339 { "value", no_argument
, NULL
, ARG_VALUE
},
7340 { "user", no_argument
, NULL
, ARG_USER
},
7341 { "system", no_argument
, NULL
, ARG_SYSTEM
},
7342 { "global", no_argument
, NULL
, ARG_GLOBAL
},
7343 { "wait", no_argument
, NULL
, ARG_WAIT
},
7344 { "no-block", no_argument
, NULL
, ARG_NO_BLOCK
},
7345 { "no-legend", no_argument
, NULL
, ARG_NO_LEGEND
},
7346 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
7347 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7348 { "dry-run", no_argument
, NULL
, ARG_DRY_RUN
},
7349 { "quiet", no_argument
, NULL
, 'q' },
7350 { "root", required_argument
, NULL
, ARG_ROOT
},
7351 { "force", no_argument
, NULL
, 'f' },
7352 { "no-reload", no_argument
, NULL
, ARG_NO_RELOAD
},
7353 { "kill-who", required_argument
, NULL
, ARG_KILL_WHO
},
7354 { "signal", required_argument
, NULL
, 's' },
7355 { "no-ask-password", no_argument
, NULL
, ARG_NO_ASK_PASSWORD
},
7356 { "host", required_argument
, NULL
, 'H' },
7357 { "machine", required_argument
, NULL
, 'M' },
7358 { "runtime", no_argument
, NULL
, ARG_RUNTIME
},
7359 { "lines", required_argument
, NULL
, 'n' },
7360 { "output", required_argument
, NULL
, 'o' },
7361 { "plain", no_argument
, NULL
, ARG_PLAIN
},
7362 { "state", required_argument
, NULL
, ARG_STATE
},
7363 { "recursive", no_argument
, NULL
, 'r' },
7364 { "preset-mode", required_argument
, NULL
, ARG_PRESET_MODE
},
7365 { "firmware-setup", no_argument
, NULL
, ARG_FIRMWARE_SETUP
},
7366 { "now", no_argument
, NULL
, ARG_NOW
},
7367 { "message", required_argument
, NULL
, ARG_MESSAGE
},
7377 /* we default to allowing interactive authorization only in systemctl (not in the legacy commands) */
7378 arg_ask_password
= true;
7380 while ((c
= getopt_long(argc
, argv
, "ht:p:alqfs:H:M:n:o:ir", options
, NULL
)) >= 0)
7392 if (isempty(optarg
)) {
7393 log_error("--type= requires arguments.");
7397 for (p
= optarg
;;) {
7398 _cleanup_free_
char *type
= NULL
;
7400 r
= extract_first_word(&p
, &type
, ",", 0);
7402 return log_error_errno(r
, "Failed to parse type: %s", optarg
);
7406 if (streq(type
, "help")) {
7411 if (unit_type_from_string(type
) >= 0) {
7412 if (strv_push(&arg_types
, type
) < 0)
7418 /* It's much nicer to use --state= for
7419 * load states, but let's support this
7420 * in --types= too for compatibility
7421 * with old versions */
7422 if (unit_load_state_from_string(type
) >= 0) {
7423 if (strv_push(&arg_states
, type
) < 0)
7429 log_error("Unknown unit type or load state '%s'.", type
);
7430 log_info("Use -t help to see a list of allowed values.");
7438 /* Make sure that if the empty property list
7439 was specified, we won't show any properties. */
7440 if (isempty(optarg
) && !arg_properties
) {
7441 arg_properties
= new0(char*, 1);
7442 if (!arg_properties
)
7445 for (p
= optarg
;;) {
7446 _cleanup_free_
char *prop
= NULL
;
7448 r
= extract_first_word(&p
, &prop
, ",", 0);
7450 return log_error_errno(r
, "Failed to parse property: %s", optarg
);
7454 if (strv_push(&arg_properties
, prop
) < 0)
7460 /* If the user asked for a particular
7461 * property, show it to him, even if it is
7473 arg_dependency
= DEPENDENCY_REVERSE
;
7477 arg_dependency
= DEPENDENCY_AFTER
;
7478 arg_jobs_after
= true;
7482 arg_dependency
= DEPENDENCY_BEFORE
;
7483 arg_jobs_before
= true;
7486 case ARG_SHOW_TYPES
:
7487 arg_show_types
= true;
7495 arg_job_mode
= optarg
;
7499 arg_job_mode
= "fail";
7502 case ARG_IRREVERSIBLE
:
7503 arg_job_mode
= "replace-irreversibly";
7506 case ARG_IGNORE_DEPENDENCIES
:
7507 arg_job_mode
= "ignore-dependencies";
7511 arg_scope
= UNIT_FILE_USER
;
7515 arg_scope
= UNIT_FILE_SYSTEM
;
7519 arg_scope
= UNIT_FILE_GLOBAL
;
7527 arg_no_block
= true;
7531 arg_no_legend
= true;
7535 arg_no_pager
= true;
7543 r
= parse_path_argument_and_warn(optarg
, false, &arg_root
);
7553 if (strv_extend(&arg_states
, "failed") < 0)
7571 arg_no_reload
= true;
7575 arg_kill_who
= optarg
;
7579 arg_signal
= signal_from_string_try_harder(optarg
);
7580 if (arg_signal
< 0) {
7581 log_error("Failed to parse signal string %s.", optarg
);
7586 case ARG_NO_ASK_PASSWORD
:
7587 arg_ask_password
= false;
7591 arg_transport
= BUS_TRANSPORT_REMOTE
;
7596 arg_transport
= BUS_TRANSPORT_MACHINE
;
7605 if (safe_atou(optarg
, &arg_lines
) < 0) {
7606 log_error("Failed to parse lines '%s'", optarg
);
7612 arg_output
= output_mode_from_string(optarg
);
7613 if (arg_output
< 0) {
7614 log_error("Unknown output '%s'.", optarg
);
7620 arg_ignore_inhibitors
= true;
7627 case ARG_FIRMWARE_SETUP
:
7628 arg_firmware_setup
= true;
7632 if (isempty(optarg
)) {
7633 log_error("--state= requires arguments.");
7637 for (p
= optarg
;;) {
7638 _cleanup_free_
char *s
= NULL
;
7640 r
= extract_first_word(&p
, &s
, ",", 0);
7642 return log_error_errno(r
, "Failed to parse state: %s", optarg
);
7646 if (streq(s
, "help")) {
7651 if (strv_push(&arg_states
, s
) < 0)
7660 if (geteuid() != 0) {
7661 log_error("--recursive requires root privileges.");
7665 arg_recursive
= true;
7668 case ARG_PRESET_MODE
:
7670 arg_preset_mode
= unit_file_preset_mode_from_string(optarg
);
7671 if (arg_preset_mode
< 0) {
7672 log_error("Failed to parse preset mode: %s.", optarg
);
7683 if (strv_extend(&arg_wall
, optarg
) < 0)
7691 assert_not_reached("Unhandled option");
7694 if (arg_transport
!= BUS_TRANSPORT_LOCAL
&& arg_scope
!= UNIT_FILE_SYSTEM
) {
7695 log_error("Cannot access user instance remotely.");
7699 if (arg_wait
&& arg_no_block
) {
7700 log_error("--wait may not be combined with --no-block.");
7707 static int halt_parse_argv(int argc
, char *argv
[]) {
7716 static const struct option options
[] = {
7717 { "help", no_argument
, NULL
, ARG_HELP
},
7718 { "halt", no_argument
, NULL
, ARG_HALT
},
7719 { "poweroff", no_argument
, NULL
, 'p' },
7720 { "reboot", no_argument
, NULL
, ARG_REBOOT
},
7721 { "force", no_argument
, NULL
, 'f' },
7722 { "wtmp-only", no_argument
, NULL
, 'w' },
7723 { "no-wtmp", no_argument
, NULL
, 'd' },
7724 { "no-sync", no_argument
, NULL
, 'n' },
7725 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7734 if (utmp_get_runlevel(&runlevel
, NULL
) >= 0)
7735 if (IN_SET(runlevel
, '0', '6'))
7738 while ((c
= getopt_long(argc
, argv
, "pfwdnih", options
, NULL
)) >= 0)
7746 arg_action
= ACTION_HALT
;
7750 if (arg_action
!= ACTION_REBOOT
)
7751 arg_action
= ACTION_POWEROFF
;
7755 arg_action
= ACTION_REBOOT
;
7780 /* Compatibility nops */
7787 assert_not_reached("Unhandled option");
7790 if (arg_action
== ACTION_REBOOT
&& (argc
== optind
|| argc
== optind
+ 1)) {
7791 r
= update_reboot_parameter_and_warn(argc
== optind
+ 1 ? argv
[optind
] : NULL
);
7794 } else if (optind
< argc
) {
7795 log_error("Too many arguments.");
7802 static int parse_shutdown_time_spec(const char *t
, usec_t
*_u
) {
7806 if (streq(t
, "now"))
7808 else if (!strchr(t
, ':')) {
7811 if (safe_atou64(t
, &u
) < 0)
7814 *_u
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
* u
;
7823 hour
= strtol(t
, &e
, 10);
7824 if (errno
> 0 || *e
!= ':' || hour
< 0 || hour
> 23)
7827 minute
= strtol(e
+1, &e
, 10);
7828 if (errno
> 0 || *e
!= 0 || minute
< 0 || minute
> 59)
7831 n
= now(CLOCK_REALTIME
);
7832 s
= (time_t) (n
/ USEC_PER_SEC
);
7834 assert_se(localtime_r(&s
, &tm
));
7836 tm
.tm_hour
= (int) hour
;
7837 tm
.tm_min
= (int) minute
;
7840 assert_se(s
= mktime(&tm
));
7842 *_u
= (usec_t
) s
* USEC_PER_SEC
;
7845 *_u
+= USEC_PER_DAY
;
7851 static int shutdown_parse_argv(int argc
, char *argv
[]) {
7858 static const struct option options
[] = {
7859 { "help", no_argument
, NULL
, ARG_HELP
},
7860 { "halt", no_argument
, NULL
, 'H' },
7861 { "poweroff", no_argument
, NULL
, 'P' },
7862 { "reboot", no_argument
, NULL
, 'r' },
7863 { "kexec", no_argument
, NULL
, 'K' }, /* not documented extension */
7864 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7874 while ((c
= getopt_long(argc
, argv
, "HPrhkKat:fFc", options
, NULL
)) >= 0)
7882 arg_action
= ACTION_HALT
;
7886 arg_action
= ACTION_POWEROFF
;
7891 arg_action
= ACTION_KEXEC
;
7893 arg_action
= ACTION_REBOOT
;
7897 arg_action
= ACTION_KEXEC
;
7901 if (arg_action
!= ACTION_HALT
)
7902 arg_action
= ACTION_POWEROFF
;
7914 case 't': /* Note that we also ignore any passed argument to -t, not just the -t itself */
7917 /* Compatibility nops */
7921 arg_action
= ACTION_CANCEL_SHUTDOWN
;
7928 assert_not_reached("Unhandled option");
7931 if (argc
> optind
&& arg_action
!= ACTION_CANCEL_SHUTDOWN
) {
7932 r
= parse_shutdown_time_spec(argv
[optind
], &arg_when
);
7934 log_error("Failed to parse time specification: %s", argv
[optind
]);
7938 arg_when
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
;
7940 if (argc
> optind
&& arg_action
== ACTION_CANCEL_SHUTDOWN
)
7941 /* No time argument for shutdown cancel */
7942 wall
= argv
+ optind
;
7943 else if (argc
> optind
+ 1)
7944 /* We skip the time argument */
7945 wall
= argv
+ optind
+ 1;
7948 arg_wall
= strv_copy(wall
);
7958 static int telinit_parse_argv(int argc
, char *argv
[]) {
7965 static const struct option options
[] = {
7966 { "help", no_argument
, NULL
, ARG_HELP
},
7967 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7971 static const struct {
7975 { '0', ACTION_POWEROFF
},
7976 { '6', ACTION_REBOOT
},
7977 { '1', ACTION_RESCUE
},
7978 { '2', ACTION_RUNLEVEL2
},
7979 { '3', ACTION_RUNLEVEL3
},
7980 { '4', ACTION_RUNLEVEL4
},
7981 { '5', ACTION_RUNLEVEL5
},
7982 { 's', ACTION_RESCUE
},
7983 { 'S', ACTION_RESCUE
},
7984 { 'q', ACTION_RELOAD
},
7985 { 'Q', ACTION_RELOAD
},
7986 { 'u', ACTION_REEXEC
},
7987 { 'U', ACTION_REEXEC
}
7996 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
8011 assert_not_reached("Unhandled option");
8014 if (optind
>= argc
) {
8015 log_error("%s: required argument missing.", program_invocation_short_name
);
8019 if (optind
+ 1 < argc
) {
8020 log_error("Too many arguments.");
8024 if (strlen(argv
[optind
]) != 1) {
8025 log_error("Expected single character argument.");
8029 for (i
= 0; i
< ELEMENTSOF(table
); i
++)
8030 if (table
[i
].from
== argv
[optind
][0])
8033 if (i
>= ELEMENTSOF(table
)) {
8034 log_error("Unknown command '%s'.", argv
[optind
]);
8038 arg_action
= table
[i
].to
;
8045 static int runlevel_parse_argv(int argc
, char *argv
[]) {
8051 static const struct option options
[] = {
8052 { "help", no_argument
, NULL
, ARG_HELP
},
8061 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
8072 assert_not_reached("Unhandled option");
8075 if (optind
< argc
) {
8076 log_error("Too many arguments.");
8083 static int parse_argv(int argc
, char *argv
[]) {
8087 if (program_invocation_short_name
) {
8089 if (strstr(program_invocation_short_name
, "halt")) {
8090 arg_action
= ACTION_HALT
;
8091 return halt_parse_argv(argc
, argv
);
8093 } else if (strstr(program_invocation_short_name
, "poweroff")) {
8094 arg_action
= ACTION_POWEROFF
;
8095 return halt_parse_argv(argc
, argv
);
8097 } else if (strstr(program_invocation_short_name
, "reboot")) {
8099 arg_action
= ACTION_KEXEC
;
8101 arg_action
= ACTION_REBOOT
;
8102 return halt_parse_argv(argc
, argv
);
8104 } else if (strstr(program_invocation_short_name
, "shutdown")) {
8105 arg_action
= ACTION_POWEROFF
;
8106 return shutdown_parse_argv(argc
, argv
);
8108 } else if (strstr(program_invocation_short_name
, "init")) {
8110 /* Matches invocations as "init" as well as "telinit", which are synonymous when run as PID !=
8113 * On SysV "telinit" was the official command to communicate with PID 1, but "init" would
8114 * redirect itself to "telinit" if called with PID != 1. We follow the same logic here still,
8115 * though we add one level of indirection, as we implement "telinit" in "systemctl". Hence, for
8116 * us if you invoke "init" you get "systemd", but it will execve() "systemctl" immediately with
8117 * argv[] unmodified if PID is != 1. If you invoke "telinit" you directly get "systemctl". In
8118 * both cases we shall do the same thing, which is why we do strstr(p_i_s_n, "init") here, as a
8119 * quick way to match both.
8121 * Also see redirect_telinit() in src/core/main.c. */
8123 if (sd_booted() > 0) {
8124 arg_action
= _ACTION_INVALID
;
8125 return telinit_parse_argv(argc
, argv
);
8127 /* Hmm, so some other init system is running, we need to forward this request to
8128 * it. For now we simply guess that it is Upstart. */
8130 execv(TELINIT
, argv
);
8132 log_error("Couldn't find an alternative telinit implementation to spawn.");
8136 } else if (strstr(program_invocation_short_name
, "runlevel")) {
8137 arg_action
= ACTION_RUNLEVEL
;
8138 return runlevel_parse_argv(argc
, argv
);
8142 arg_action
= ACTION_SYSTEMCTL
;
8143 return systemctl_parse_argv(argc
, argv
);
8146 #if HAVE_SYSV_COMPAT
8147 _pure_
static int action_to_runlevel(void) {
8149 static const char table
[_ACTION_MAX
] = {
8150 [ACTION_HALT
] = '0',
8151 [ACTION_POWEROFF
] = '0',
8152 [ACTION_REBOOT
] = '6',
8153 [ACTION_RUNLEVEL2
] = '2',
8154 [ACTION_RUNLEVEL3
] = '3',
8155 [ACTION_RUNLEVEL4
] = '4',
8156 [ACTION_RUNLEVEL5
] = '5',
8157 [ACTION_RESCUE
] = '1'
8160 assert(arg_action
>= 0 && arg_action
< _ACTION_MAX
);
8162 return table
[arg_action
];
8166 static int talk_initctl(void) {
8167 #if HAVE_SYSV_COMPAT
8168 struct init_request request
= {
8169 .magic
= INIT_MAGIC
,
8171 .cmd
= INIT_CMD_RUNLVL
8174 _cleanup_close_
int fd
= -1;
8178 rl
= action_to_runlevel();
8182 request
.runlevel
= rl
;
8184 fd
= open(INIT_FIFO
, O_WRONLY
|O_NONBLOCK
|O_CLOEXEC
|O_NOCTTY
);
8186 if (errno
== ENOENT
)
8189 return log_error_errno(errno
, "Failed to open "INIT_FIFO
": %m");
8192 r
= loop_write(fd
, &request
, sizeof(request
), false);
8194 return log_error_errno(r
, "Failed to write to "INIT_FIFO
": %m");
8202 static int systemctl_main(int argc
, char *argv
[]) {
8204 static const Verb verbs
[] = {
8205 { "list-units", VERB_ANY
, VERB_ANY
, VERB_DEFAULT
|VERB_ONLINE_ONLY
, list_units
},
8206 { "list-unit-files", VERB_ANY
, VERB_ANY
, 0, list_unit_files
},
8207 { "list-sockets", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, list_sockets
},
8208 { "list-timers", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, list_timers
},
8209 { "list-jobs", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, list_jobs
},
8210 { "list-machines", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
|VERB_MUST_BE_ROOT
, list_machines
},
8211 { "clear-jobs", VERB_ANY
, 1, VERB_ONLINE_ONLY
, trivial_method
},
8212 { "cancel", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, cancel_job
},
8213 { "start", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8214 { "stop", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8215 { "condstop", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
}, /* For compatibility with ALTLinux */
8216 { "reload", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8217 { "restart", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8218 { "try-restart", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8219 { "reload-or-restart", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8220 { "reload-or-try-restart", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
}, /* For compatbility with old systemctl <= 228 */
8221 { "try-reload-or-restart", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8222 { "force-reload", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
}, /* For compatibility with SysV */
8223 { "condreload", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
}, /* For compatibility with ALTLinux */
8224 { "condrestart", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
}, /* For compatibility with RH */
8225 { "isolate", 2, 2, VERB_ONLINE_ONLY
, start_unit
},
8226 { "kill", 2, VERB_ANY
, VERB_ONLINE_ONLY
, kill_unit
},
8227 { "is-active", 2, VERB_ANY
, VERB_ONLINE_ONLY
, check_unit_active
},
8228 { "check", 2, VERB_ANY
, VERB_ONLINE_ONLY
, check_unit_active
}, /* deprecated alias of is-active */
8229 { "is-failed", 2, VERB_ANY
, VERB_ONLINE_ONLY
, check_unit_failed
},
8230 { "show", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, show
},
8231 { "cat", 2, VERB_ANY
, VERB_ONLINE_ONLY
, cat
},
8232 { "status", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, show
},
8233 { "help", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, show
},
8234 { "daemon-reload", VERB_ANY
, 1, VERB_ONLINE_ONLY
, daemon_reload
},
8235 { "daemon-reexec", VERB_ANY
, 1, VERB_ONLINE_ONLY
, daemon_reload
},
8236 { "show-environment", VERB_ANY
, 1, VERB_ONLINE_ONLY
, show_environment
},
8237 { "set-environment", 2, VERB_ANY
, VERB_ONLINE_ONLY
, set_environment
},
8238 { "unset-environment", 2, VERB_ANY
, VERB_ONLINE_ONLY
, set_environment
},
8239 { "import-environment", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, import_environment
},
8240 { "halt", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8241 { "poweroff", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8242 { "reboot", VERB_ANY
, 2, VERB_ONLINE_ONLY
, start_system_special
},
8243 { "kexec", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8244 { "suspend", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8245 { "hibernate", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8246 { "hybrid-sleep", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8247 { "suspend-to-hibernate", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8248 { "default", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_special
},
8249 { "rescue", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8250 { "emergency", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8251 { "exit", VERB_ANY
, 2, VERB_ONLINE_ONLY
, start_special
},
8252 { "reset-failed", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, reset_failed
},
8253 { "enable", 2, VERB_ANY
, 0, enable_unit
},
8254 { "disable", 2, VERB_ANY
, 0, enable_unit
},
8255 { "is-enabled", 2, VERB_ANY
, 0, unit_is_enabled
},
8256 { "reenable", 2, VERB_ANY
, 0, enable_unit
},
8257 { "preset", 2, VERB_ANY
, 0, enable_unit
},
8258 { "preset-all", VERB_ANY
, 1, 0, preset_all
},
8259 { "mask", 2, VERB_ANY
, 0, enable_unit
},
8260 { "unmask", 2, VERB_ANY
, 0, enable_unit
},
8261 { "link", 2, VERB_ANY
, 0, enable_unit
},
8262 { "revert", 2, VERB_ANY
, 0, enable_unit
},
8263 { "switch-root", 2, VERB_ANY
, VERB_ONLINE_ONLY
, switch_root
},
8264 { "list-dependencies", VERB_ANY
, 2, VERB_ONLINE_ONLY
, list_dependencies
},
8265 { "set-default", 2, 2, 0, set_default
},
8266 { "get-default", VERB_ANY
, 1, 0, get_default
},
8267 { "set-property", 3, VERB_ANY
, VERB_ONLINE_ONLY
, set_property
},
8268 { "is-system-running", VERB_ANY
, 1, 0, is_system_running
},
8269 { "add-wants", 3, VERB_ANY
, 0, add_dependency
},
8270 { "add-requires", 3, VERB_ANY
, 0, add_dependency
},
8271 { "edit", 2, VERB_ANY
, VERB_ONLINE_ONLY
, edit
},
8275 return dispatch_verb(argc
, argv
, verbs
, NULL
);
8278 static int reload_with_fallback(void) {
8280 /* First, try systemd via D-Bus. */
8281 if (daemon_reload(0, NULL
, NULL
) >= 0)
8284 /* Nothing else worked, so let's try signals */
8285 assert(IN_SET(arg_action
, ACTION_RELOAD
, ACTION_REEXEC
));
8287 if (kill(1, arg_action
== ACTION_RELOAD
? SIGHUP
: SIGTERM
) < 0)
8288 return log_error_errno(errno
, "kill() failed: %m");
8293 static int start_with_fallback(void) {
8295 /* First, try systemd via D-Bus. */
8296 if (start_unit(0, NULL
, NULL
) >= 0)
8299 /* Nothing else worked, so let's try /dev/initctl */
8300 if (talk_initctl() > 0)
8303 log_error("Failed to talk to init daemon.");
8307 static int halt_now(enum action a
) {
8309 /* The kernel will automatically flush ATA disks and suchlike on reboot(), but the file systems need to be
8310 * synce'd explicitly in advance. */
8311 if (!arg_no_sync
&& !arg_dry_run
)
8314 /* Make sure C-A-D is handled by the kernel from this point on... */
8316 (void) reboot(RB_ENABLE_CAD
);
8322 log_info("Halting.");
8325 (void) reboot(RB_HALT_SYSTEM
);
8328 case ACTION_POWEROFF
:
8330 log_info("Powering off.");
8333 (void) reboot(RB_POWER_OFF
);
8338 return reboot_with_parameter(REBOOT_FALLBACK
|
8339 (arg_quiet
? 0 : REBOOT_LOG
) |
8340 (arg_dry_run
? REBOOT_DRY_RUN
: 0));
8343 assert_not_reached("Unknown action.");
8347 static int logind_schedule_shutdown(void) {
8350 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
8351 char date
[FORMAT_TIMESTAMP_MAX
];
8356 r
= acquire_bus(BUS_FULL
, &bus
);
8360 switch (arg_action
) {
8364 case ACTION_POWEROFF
:
8365 action
= "poweroff";
8380 action
= strjoina("dry-", action
);
8382 (void) logind_set_wall_message();
8384 r
= sd_bus_call_method(
8386 "org.freedesktop.login1",
8387 "/org/freedesktop/login1",
8388 "org.freedesktop.login1.Manager",
8396 return log_warning_errno(r
, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s", bus_error_message(&error
, r
));
8399 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.", format_timestamp(date
, sizeof(date
), arg_when
));
8402 log_error("Cannot schedule shutdown without logind support, proceeding with immediate shutdown.");
8407 static int halt_main(void) {
8410 r
= logind_check_inhibitors(arg_action
);
8415 return logind_schedule_shutdown();
8417 if (geteuid() != 0) {
8418 if (arg_dry_run
|| arg_force
> 0) {
8419 (void) must_be_root();
8423 /* Try logind if we are a normal user and no special
8424 * mode applies. Maybe PolicyKit allows us to shutdown
8426 if (IN_SET(arg_action
, ACTION_POWEROFF
, ACTION_REBOOT
, ACTION_HALT
)) {
8427 r
= logind_reboot(arg_action
);
8430 if (IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
8431 /* requested operation is not
8432 * supported on the local system or
8433 * already in progress */
8435 /* on all other errors, try low-level operation */
8439 if (!arg_dry_run
&& !arg_force
)
8440 return start_with_fallback();
8442 assert(geteuid() == 0);
8445 if (sd_booted() > 0)
8446 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
8448 r
= utmp_put_shutdown();
8450 log_warning_errno(r
, "Failed to write utmp record: %m");
8457 r
= halt_now(arg_action
);
8458 return log_error_errno(r
, "Failed to reboot: %m");
8461 static int runlevel_main(void) {
8462 int r
, runlevel
, previous
;
8464 r
= utmp_get_runlevel(&runlevel
, &previous
);
8471 previous
<= 0 ? 'N' : previous
,
8472 runlevel
<= 0 ? 'N' : runlevel
);
8477 static int logind_cancel_shutdown(void) {
8479 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
8483 r
= acquire_bus(BUS_FULL
, &bus
);
8487 (void) logind_set_wall_message();
8489 r
= sd_bus_call_method(
8491 "org.freedesktop.login1",
8492 "/org/freedesktop/login1",
8493 "org.freedesktop.login1.Manager",
8494 "CancelScheduledShutdown",
8498 return log_warning_errno(r
, "Failed to talk to logind, shutdown hasn't been cancelled: %s", bus_error_message(&error
, r
));
8502 log_error("Not compiled with logind support, cannot cancel scheduled shutdowns.");
8507 int main(int argc
, char*argv
[]) {
8510 argv_cmdline
= argv
[0];
8512 setlocale(LC_ALL
, "");
8513 log_parse_environment();
8517 /* Explicitly not on_tty() to avoid setting cached value.
8518 * This becomes relevant for piping output which might be
8520 original_stdout_is_tty
= isatty(STDOUT_FILENO
);
8522 r
= parse_argv(argc
, argv
);
8526 if (arg_action
!= ACTION_SYSTEMCTL
&& running_in_chroot() > 0) {
8529 log_info("Running in chroot, ignoring request.");
8534 /* systemctl_main() will print an error message for the bus
8535 * connection, but only if it needs to */
8537 switch (arg_action
) {
8539 case ACTION_SYSTEMCTL
:
8540 r
= systemctl_main(argc
, argv
);
8543 /* Legacy command aliases set arg_action. They provide some fallbacks,
8544 * e.g. to tell sysvinit to reboot after you have installed systemd
8548 case ACTION_POWEROFF
:
8554 case ACTION_RUNLEVEL2
:
8555 case ACTION_RUNLEVEL3
:
8556 case ACTION_RUNLEVEL4
:
8557 case ACTION_RUNLEVEL5
:
8559 r
= start_with_fallback();
8564 r
= reload_with_fallback();
8567 case ACTION_CANCEL_SHUTDOWN
:
8568 r
= logind_cancel_shutdown();
8571 case ACTION_RUNLEVEL
:
8572 r
= runlevel_main();
8576 case ACTION_SUSPEND
:
8577 case ACTION_HIBERNATE
:
8578 case ACTION_HYBRID_SLEEP
:
8579 case ACTION_SUSPEND_TO_HIBERNATE
:
8580 case ACTION_EMERGENCY
:
8581 case ACTION_DEFAULT
:
8582 /* systemctl verbs with no equivalent in the legacy commands.
8583 * These cannot appear in arg_action. Fall through. */
8585 case _ACTION_INVALID
:
8587 assert_not_reached("Unknown action");
8594 ask_password_agent_close();
8595 polkit_agent_close();
8597 strv_free(arg_types
);
8598 strv_free(arg_states
);
8599 strv_free(arg_properties
);
8601 strv_free(arg_wall
);
8605 /* Note that we return r here, not EXIT_SUCCESS, so that we can implement the LSB-like return codes */
8606 return r
< 0 ? EXIT_FAILURE
: r
;