1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2010 Lennart Poettering
6 Copyright 2013 Marc-Antoine Perennou
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
30 #include <sys/prctl.h>
31 #include <sys/reboot.h>
32 #include <sys/socket.h>
36 #include "sd-daemon.h"
39 #include "alloc-util.h"
41 #include "bus-common-errors.h"
42 #include "bus-error.h"
43 #include "bus-message.h"
44 #include "bus-unit-util.h"
46 #include "cgroup-show.h"
47 #include "cgroup-util.h"
53 #include "exit-status.h"
56 #include "format-util.h"
58 #include "glob-util.h"
59 #include "hexdecoct.h"
60 #include "hostname-util.h"
65 #include "locale-util.h"
67 #include "logs-show.h"
71 #include "parse-util.h"
72 #include "path-lookup.h"
73 #include "path-util.h"
74 #include "process-util.h"
75 #include "reboot-util.h"
76 #include "rlimit-util.h"
79 #include "signal-util.h"
80 #include "socket-util.h"
81 #include "spawn-ask-password-agent.h"
82 #include "spawn-polkit-agent.h"
84 #include "stat-util.h"
85 #include "string-table.h"
87 #include "terminal-util.h"
89 #include "unit-name.h"
90 #include "user-util.h"
92 #include "utmp-wtmp.h"
96 /* The init script exit status codes
97 0 program is running or service is OK
98 1 program is dead and /var/run pid file exists
99 2 program is dead and /var/lock lock file exists
100 3 program is not running
101 4 program or service status is unknown
102 5-99 reserved for future LSB use
103 100-149 reserved for distribution use
104 150-199 reserved for application use
108 EXIT_PROGRAM_RUNNING_OR_SERVICE_OK
= 0,
109 EXIT_PROGRAM_DEAD_AND_PID_EXISTS
= 1,
110 EXIT_PROGRAM_DEAD_AND_LOCK_FILE_EXISTS
= 2,
111 EXIT_PROGRAM_NOT_RUNNING
= 3,
112 EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN
= 4,
115 static char **arg_types
= NULL
;
116 static char **arg_states
= NULL
;
117 static char **arg_properties
= NULL
;
118 static bool arg_all
= false;
119 static enum dependency
{
125 } arg_dependency
= DEPENDENCY_FORWARD
;
126 static const char *arg_job_mode
= "replace";
127 static UnitFileScope arg_scope
= UNIT_FILE_SYSTEM
;
128 static bool arg_wait
= false;
129 static bool arg_no_block
= false;
130 static bool arg_no_legend
= false;
131 static bool arg_no_pager
= false;
132 static bool arg_no_wtmp
= false;
133 static bool arg_no_sync
= false;
134 static bool arg_no_wall
= false;
135 static bool arg_no_reload
= false;
136 static bool arg_value
= false;
137 static bool arg_show_types
= false;
138 static bool arg_ignore_inhibitors
= false;
139 static bool arg_dry_run
= false;
140 static bool arg_quiet
= false;
141 static bool arg_full
= false;
142 static bool arg_recursive
= false;
143 static int arg_force
= 0;
144 static bool arg_ask_password
= false;
145 static bool arg_runtime
= false;
146 static UnitFilePresetMode arg_preset_mode
= UNIT_FILE_PRESET_FULL
;
147 static char **arg_wall
= NULL
;
148 static const char *arg_kill_who
= NULL
;
149 static int arg_signal
= SIGTERM
;
150 static char *arg_root
= NULL
;
151 static usec_t arg_when
= 0;
152 static char *arg_esp_path
= NULL
;
153 static char *argv_cmdline
= NULL
;
164 ACTION_SUSPEND_THEN_HIBERNATE
,
175 ACTION_CANCEL_SHUTDOWN
,
178 } arg_action
= ACTION_SYSTEMCTL
;
179 static BusTransport arg_transport
= BUS_TRANSPORT_LOCAL
;
180 static const char *arg_host
= NULL
;
181 static unsigned arg_lines
= 10;
182 static OutputMode arg_output
= OUTPUT_SHORT
;
183 static bool arg_plain
= false;
184 static bool arg_firmware_setup
= false;
185 static bool arg_now
= false;
186 static bool arg_jobs_before
= false;
187 static bool arg_jobs_after
= false;
189 static int daemon_reload(int argc
, char *argv
[], void* userdata
);
190 static int trivial_method(int argc
, char *argv
[], void *userdata
);
191 static int halt_now(enum action a
);
192 static int get_state_one_unit(sd_bus
*bus
, const char *name
, UnitActiveState
*active_state
);
194 static bool original_stdout_is_tty
;
196 typedef enum BusFocus
{
197 BUS_FULL
, /* The full bus indicated via --system or --user */
198 BUS_MANAGER
, /* The manager itself, possibly directly, possibly via the bus */
202 static sd_bus
*busses
[_BUS_FOCUS_MAX
] = {};
204 static UnitFileFlags
args_to_flags(void) {
205 return (arg_runtime
? UNIT_FILE_RUNTIME
: 0) |
206 (arg_force
? UNIT_FILE_FORCE
: 0);
209 static int acquire_bus(BusFocus focus
, sd_bus
**ret
) {
212 assert(focus
< _BUS_FOCUS_MAX
);
215 /* We only go directly to the manager, if we are using a local transport */
216 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
219 if (getenv_bool("SYSTEMCTL_FORCE_BUS") > 0)
222 if (!busses
[focus
]) {
225 user
= arg_scope
!= UNIT_FILE_SYSTEM
;
227 if (!user
&& sd_booted() <= 0) {
228 /* Print a friendly message when the local system is actually not running systemd as PID 1. */
229 log_error("System has not been booted with systemd as init system (PID 1). Can't operate.");
233 if (focus
== BUS_MANAGER
)
234 r
= bus_connect_transport_systemd(arg_transport
, arg_host
, user
, &busses
[focus
]);
236 r
= bus_connect_transport(arg_transport
, arg_host
, user
, &busses
[focus
]);
238 return log_error_errno(r
, "Failed to connect to bus: %m");
240 (void) sd_bus_set_allow_interactive_authorization(busses
[focus
], arg_ask_password
);
243 *ret
= busses
[focus
];
247 static void release_busses(void) {
250 for (w
= 0; w
< _BUS_FOCUS_MAX
; w
++)
251 busses
[w
] = sd_bus_flush_close_unref(busses
[w
]);
254 static void ask_password_agent_open_if_enabled(void) {
256 /* Open the password agent as a child process if necessary */
261 if (!arg_ask_password
)
264 if (arg_scope
!= UNIT_FILE_SYSTEM
)
267 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
270 ask_password_agent_open();
273 static void polkit_agent_open_maybe(void) {
274 /* Open the polkit agent as a child process if necessary */
276 if (arg_scope
!= UNIT_FILE_SYSTEM
)
279 polkit_agent_open_if_enabled(arg_transport
, arg_ask_password
);
282 static OutputFlags
get_output_flags(void) {
284 arg_all
* OUTPUT_SHOW_ALL
|
285 (arg_full
|| !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH
|
286 colors_enabled() * OUTPUT_COLOR
|
287 !arg_quiet
* OUTPUT_WARN_CUTOFF
;
290 static int translate_bus_error_to_exit_status(int r
, const sd_bus_error
*error
) {
293 if (!sd_bus_error_is_set(error
))
296 if (sd_bus_error_has_name(error
, SD_BUS_ERROR_ACCESS_DENIED
) ||
297 sd_bus_error_has_name(error
, BUS_ERROR_ONLY_BY_DEPENDENCY
) ||
298 sd_bus_error_has_name(error
, BUS_ERROR_NO_ISOLATION
) ||
299 sd_bus_error_has_name(error
, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE
))
300 return EXIT_NOPERMISSION
;
302 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
))
303 return EXIT_NOTINSTALLED
;
305 if (sd_bus_error_has_name(error
, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE
) ||
306 sd_bus_error_has_name(error
, SD_BUS_ERROR_NOT_SUPPORTED
))
307 return EXIT_NOTIMPLEMENTED
;
309 if (sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
))
310 return EXIT_NOTCONFIGURED
;
318 static bool install_client_side(void) {
320 /* Decides when to execute enable/disable/... operations
321 * client-side rather than server-side. */
323 if (running_in_chroot_or_offline())
326 if (sd_booted() <= 0)
329 if (!isempty(arg_root
))
332 if (arg_scope
== UNIT_FILE_GLOBAL
)
335 /* Unsupported environment variable, mostly for debugging purposes */
336 if (getenv_bool("SYSTEMCTL_INSTALL_CLIENT_SIDE") > 0)
342 static int compare_unit_info(const void *a
, const void *b
) {
343 const UnitInfo
*u
= a
, *v
= b
;
347 /* First, order by machine */
348 if (!u
->machine
&& v
->machine
)
350 if (u
->machine
&& !v
->machine
)
352 if (u
->machine
&& v
->machine
) {
353 r
= strcasecmp(u
->machine
, v
->machine
);
358 /* Second, order by unit type */
359 d1
= strrchr(u
->id
, '.');
360 d2
= strrchr(v
->id
, '.');
362 r
= strcasecmp(d1
, d2
);
367 /* Third, order by name */
368 return strcasecmp(u
->id
, v
->id
);
371 static const char* unit_type_suffix(const char *name
) {
374 dot
= strrchr(name
, '.');
381 static bool output_show_unit(const UnitInfo
*u
, char **patterns
) {
384 if (!strv_fnmatch_or_empty(patterns
, u
->id
, FNM_NOESCAPE
))
387 if (arg_types
&& !strv_find(arg_types
, unit_type_suffix(u
->id
)))
393 /* Note that '--all' is not purely a state filter, but also a
394 * filter that hides units that "follow" other units (which is
395 * used for device units that appear under different names). */
396 if (!isempty(u
->following
))
399 if (!strv_isempty(arg_states
))
402 /* By default show all units except the ones in inactive
403 * state and with no pending job */
407 if (streq(u
->active_state
, "inactive"))
413 static int output_units_list(const UnitInfo
*unit_infos
, unsigned c
) {
414 unsigned circle_len
= 0, id_len
, max_id_len
, load_len
, active_len
, sub_len
, job_len
, desc_len
, max_desc_len
;
416 unsigned n_shown
= 0;
419 max_id_len
= STRLEN("UNIT");
420 load_len
= STRLEN("LOAD");
421 active_len
= STRLEN("ACTIVE");
422 sub_len
= STRLEN("SUB");
423 job_len
= STRLEN("JOB");
424 max_desc_len
= STRLEN("DESCRIPTION");
426 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
427 max_id_len
= MAX(max_id_len
, strlen(u
->id
) + (u
->machine
? strlen(u
->machine
)+1 : 0));
428 load_len
= MAX(load_len
, strlen(u
->load_state
));
429 active_len
= MAX(active_len
, strlen(u
->active_state
));
430 sub_len
= MAX(sub_len
, strlen(u
->sub_state
));
431 max_desc_len
= MAX(max_desc_len
, strlen(u
->description
));
433 if (u
->job_id
!= 0) {
434 job_len
= MAX(job_len
, strlen(u
->job_type
));
438 if (!arg_no_legend
&&
439 (streq(u
->active_state
, "failed") ||
440 STR_IN_SET(u
->load_state
, "error", "not-found", "masked")))
444 if (!arg_full
&& original_stdout_is_tty
) {
447 id_len
= MIN(max_id_len
, 25u); /* as much as it needs, but at most 25 for now */
448 basic_len
= circle_len
+ 1 + id_len
+ 1 + load_len
+ 1 + active_len
+ 1 + sub_len
+ 1;
451 basic_len
+= job_len
+ 1;
453 if (basic_len
< (unsigned) columns()) {
454 unsigned extra_len
, incr
;
455 extra_len
= columns() - basic_len
;
457 /* Either UNIT already got 25, or is fully satisfied.
458 * Grant up to 25 to DESC now. */
459 incr
= MIN(extra_len
, 25u);
463 /* Of the remainder give as much as the ID needs to the ID, and give the rest to the
464 * description but not more than it needs. */
466 incr
= MIN(max_id_len
- id_len
, extra_len
);
468 desc_len
+= MIN(extra_len
- incr
, max_desc_len
- desc_len
);
474 desc_len
= max_desc_len
;
477 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
478 _cleanup_free_
char *e
= NULL
, *j
= NULL
;
479 const char *on_underline
= "", *off_underline
= "";
480 const char *on_loaded
= "", *off_loaded
= "";
481 const char *on_active
= "", *off_active
= "";
482 const char *on_circle
= "", *off_circle
= "";
484 bool circle
= false, underline
= false;
486 if (!n_shown
&& !arg_no_legend
) {
491 printf("%s%-*s %-*s %-*s %-*s ",
495 active_len
, "ACTIVE",
499 printf("%-*s ", job_len
, "JOB");
503 !arg_full
&& arg_no_pager
? (int) desc_len
: -1,
510 if (u
+ 1 < unit_infos
+ c
&&
511 !streq(unit_type_suffix(u
->id
), unit_type_suffix((u
+ 1)->id
))) {
512 on_underline
= ansi_underline();
513 off_underline
= ansi_normal();
517 if (STR_IN_SET(u
->load_state
, "error", "not-found", "masked") && !arg_plain
) {
518 on_circle
= ansi_highlight_yellow();
519 off_circle
= ansi_normal();
521 on_loaded
= underline
? ansi_highlight_red_underline() : ansi_highlight_red();
522 off_loaded
= underline
? on_underline
: ansi_normal();
523 } else if (streq(u
->active_state
, "failed") && !arg_plain
) {
524 on_circle
= ansi_highlight_red();
525 off_circle
= ansi_normal();
527 on_active
= underline
? ansi_highlight_red_underline() : ansi_highlight_red();
528 off_active
= underline
? on_underline
: ansi_normal();
532 j
= strjoin(u
->machine
, ":", u
->id
);
541 e
= ellipsize(id
, id_len
, 33);
549 printf("%s%s%s ", on_circle
, circle
? special_glyph(BLACK_CIRCLE
) : " ", off_circle
);
551 printf("%s%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
553 on_active
, id_len
, id
, off_active
,
554 on_loaded
, load_len
, u
->load_state
, off_loaded
,
555 on_active
, active_len
, u
->active_state
,
556 sub_len
, u
->sub_state
, off_active
,
557 job_count
? job_len
+ 1 : 0, u
->job_id
? u
->job_type
: "");
561 !arg_full
&& arg_no_pager
? (int) desc_len
: -1,
566 if (!arg_no_legend
) {
567 const char *on
, *off
;
571 "LOAD = Reflects whether the unit definition was properly loaded.\n"
572 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
573 "SUB = The low-level unit activation state, values depend on unit type.");
574 puts(job_count
? "JOB = Pending job for the unit.\n" : "");
575 on
= ansi_highlight();
578 on
= ansi_highlight_red();
583 printf("%s%u loaded units listed.%s\n"
584 "To show all installed unit files use 'systemctl list-unit-files'.\n",
587 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
588 "To show all installed unit files use 'systemctl list-unit-files'.\n",
595 static int get_unit_list(
599 UnitInfo
**unit_infos
,
601 sd_bus_message
**_reply
) {
603 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
604 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
605 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
609 bool fallback
= false;
615 r
= sd_bus_message_new_method_call(
618 "org.freedesktop.systemd1",
619 "/org/freedesktop/systemd1",
620 "org.freedesktop.systemd1.Manager",
621 "ListUnitsByPatterns");
623 return bus_log_create_error(r
);
625 r
= sd_bus_message_append_strv(m
, arg_states
);
627 return bus_log_create_error(r
);
629 r
= sd_bus_message_append_strv(m
, patterns
);
631 return bus_log_create_error(r
);
633 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
634 if (r
< 0 && (sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_METHOD
) ||
635 sd_bus_error_has_name(&error
, SD_BUS_ERROR_ACCESS_DENIED
))) {
636 /* Fallback to legacy ListUnitsFiltered method */
638 log_debug_errno(r
, "Failed to list units: %s Falling back to ListUnitsFiltered method.", bus_error_message(&error
, r
));
639 m
= sd_bus_message_unref(m
);
640 sd_bus_error_free(&error
);
642 r
= sd_bus_message_new_method_call(
645 "org.freedesktop.systemd1",
646 "/org/freedesktop/systemd1",
647 "org.freedesktop.systemd1.Manager",
648 "ListUnitsFiltered");
650 return bus_log_create_error(r
);
652 r
= sd_bus_message_append_strv(m
, arg_states
);
654 return bus_log_create_error(r
);
656 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
659 return log_error_errno(r
, "Failed to list units: %s", bus_error_message(&error
, r
));
661 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssssouso)");
663 return bus_log_parse_error(r
);
665 while ((r
= bus_parse_unit_info(reply
, &u
)) > 0) {
668 if (!output_show_unit(&u
, fallback
? patterns
: NULL
))
671 if (!GREEDY_REALLOC(*unit_infos
, size
, c
+1))
674 (*unit_infos
)[c
++] = u
;
677 return bus_log_parse_error(r
);
679 r
= sd_bus_message_exit_container(reply
);
681 return bus_log_parse_error(r
);
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
],
1694 return log_error_errno(r
, "Failed to get properties of %s: %s", name
, bus_error_message(&error
, r
));
1696 if (IN_SET(arg_dependency
, DEPENDENCY_AFTER
, DEPENDENCY_BEFORE
)) {
1697 *deps
= info
.dep
[0];
1701 for (i
= 0; i
< 5; i
++) {
1702 r
= strv_extend_strv(&ret
, info
.dep
[i
], true);
1705 info
.dep
[i
] = strv_free(info
.dep
[i
]);
1714 static int list_dependencies_compare(const void *_a
, const void *_b
) {
1715 const char **a
= (const char**) _a
, **b
= (const char**) _b
;
1717 if (unit_name_to_type(*a
) == UNIT_TARGET
&& unit_name_to_type(*b
) != UNIT_TARGET
)
1719 if (unit_name_to_type(*a
) != UNIT_TARGET
&& unit_name_to_type(*b
) == UNIT_TARGET
)
1722 return strcasecmp(*a
, *b
);
1725 static int list_dependencies_one(
1730 unsigned int branches
) {
1732 _cleanup_strv_free_
char **deps
= NULL
;
1740 r
= strv_extend(units
, name
);
1744 r
= list_dependencies_get_dependencies(bus
, name
, &deps
);
1748 qsort_safe(deps
, strv_length(deps
), sizeof (char*), list_dependencies_compare
);
1750 STRV_FOREACH(c
, deps
) {
1751 if (strv_contains(*units
, *c
)) {
1754 r
= list_dependencies_print("...", level
+ 1, (branches
<< 1) | (c
[1] == NULL
? 0 : 1), 1);
1764 UnitActiveState active_state
= _UNIT_ACTIVE_STATE_INVALID
;
1767 (void) get_state_one_unit(bus
, *c
, &active_state
);
1769 switch (active_state
) {
1771 case UNIT_RELOADING
:
1772 case UNIT_ACTIVATING
:
1773 on
= ansi_highlight_green();
1777 case UNIT_DEACTIVATING
:
1782 on
= ansi_highlight_red();
1786 printf("%s%s%s ", on
, special_glyph(BLACK_CIRCLE
), ansi_normal());
1789 r
= list_dependencies_print(*c
, level
, branches
, c
[1] == NULL
);
1793 if (arg_all
|| unit_name_to_type(*c
) == UNIT_TARGET
) {
1794 r
= list_dependencies_one(bus
, *c
, level
+ 1, units
, (branches
<< 1) | (c
[1] == NULL
? 0 : 1));
1801 strv_remove(*units
, name
);
1806 static int list_dependencies(int argc
, char *argv
[], void *userdata
) {
1807 _cleanup_strv_free_
char **units
= NULL
;
1808 _cleanup_free_
char *unit
= NULL
;
1814 r
= unit_name_mangle(argv
[1], arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
, &unit
);
1816 return log_error_errno(r
, "Failed to mangle unit name: %m");
1820 u
= SPECIAL_DEFAULT_TARGET
;
1822 r
= acquire_bus(BUS_MANAGER
, &bus
);
1826 (void) pager_open(arg_no_pager
, false);
1830 return list_dependencies_one(bus
, u
, 0, &units
, 0);
1833 struct machine_info
{
1837 char *control_group
;
1838 uint32_t n_failed_units
;
1843 static const struct bus_properties_map machine_info_property_map
[] = {
1844 { "SystemState", "s", NULL
, offsetof(struct machine_info
, state
) },
1845 { "NJobs", "u", NULL
, offsetof(struct machine_info
, n_jobs
) },
1846 { "NFailedUnits", "u", NULL
, offsetof(struct machine_info
, n_failed_units
) },
1847 { "ControlGroup", "s", NULL
, offsetof(struct machine_info
, control_group
) },
1848 { "UserspaceTimestamp", "t", NULL
, offsetof(struct machine_info
, timestamp
) },
1852 static void machine_info_clear(struct machine_info
*info
) {
1857 free(info
->control_group
);
1861 static void free_machines_list(struct machine_info
*machine_infos
, int n
) {
1867 for (i
= 0; i
< n
; i
++)
1868 machine_info_clear(&machine_infos
[i
]);
1870 free(machine_infos
);
1873 static int compare_machine_info(const void *a
, const void *b
) {
1874 const struct machine_info
*u
= a
, *v
= b
;
1876 if (u
->is_host
!= v
->is_host
)
1877 return u
->is_host
> v
->is_host
? -1 : 1;
1879 return strcasecmp(u
->name
, v
->name
);
1882 static int get_machine_properties(sd_bus
*bus
, struct machine_info
*mi
) {
1883 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*container
= NULL
;
1889 r
= sd_bus_open_system_machine(&container
, mi
->name
);
1896 r
= bus_map_all_properties(
1898 "org.freedesktop.systemd1",
1899 "/org/freedesktop/systemd1",
1900 machine_info_property_map
,
1911 static bool output_show_machine(const char *name
, char **patterns
) {
1912 return strv_fnmatch_or_empty(patterns
, name
, FNM_NOESCAPE
);
1915 static int get_machine_list(
1917 struct machine_info
**_machine_infos
,
1920 struct machine_info
*machine_infos
= NULL
;
1921 _cleanup_strv_free_
char **m
= NULL
;
1922 _cleanup_free_
char *hn
= NULL
;
1927 hn
= gethostname_malloc();
1931 if (output_show_machine(hn
, patterns
)) {
1932 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1))
1935 machine_infos
[c
].is_host
= true;
1936 machine_infos
[c
].name
= TAKE_PTR(hn
);
1938 (void) get_machine_properties(bus
, &machine_infos
[c
]);
1942 r
= sd_get_machine_names(&m
);
1944 return log_error_errno(r
, "Failed to get machine list: %m");
1946 STRV_FOREACH(i
, m
) {
1947 _cleanup_free_
char *class = NULL
;
1949 if (!output_show_machine(*i
, patterns
))
1952 sd_machine_get_class(*i
, &class);
1953 if (!streq_ptr(class, "container"))
1956 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1)) {
1957 free_machines_list(machine_infos
, c
);
1961 machine_infos
[c
].is_host
= false;
1962 machine_infos
[c
].name
= strdup(*i
);
1963 if (!machine_infos
[c
].name
) {
1964 free_machines_list(machine_infos
, c
);
1968 (void) get_machine_properties(NULL
, &machine_infos
[c
]);
1972 *_machine_infos
= machine_infos
;
1976 static void output_machines_list(struct machine_info
*machine_infos
, unsigned n
) {
1977 struct machine_info
*m
;
1980 namelen
= STRLEN("NAME"),
1981 statelen
= STRLEN("STATE"),
1982 failedlen
= STRLEN("FAILED"),
1983 jobslen
= STRLEN("JOBS");
1985 assert(machine_infos
|| n
== 0);
1987 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
1988 namelen
= MAX(namelen
,
1989 strlen(m
->name
) + (m
->is_host
? STRLEN(" (host)") : 0));
1990 statelen
= MAX(statelen
, strlen_ptr(m
->state
));
1991 failedlen
= MAX(failedlen
, DECIMAL_STR_WIDTH(m
->n_failed_units
));
1992 jobslen
= MAX(jobslen
, DECIMAL_STR_WIDTH(m
->n_jobs
));
1994 if (!arg_plain
&& !streq_ptr(m
->state
, "running"))
1998 if (!arg_no_legend
) {
2002 printf("%-*s %-*s %-*s %-*s\n",
2005 failedlen
, "FAILED",
2009 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
2010 const char *on_state
= "", *off_state
= "";
2011 const char *on_failed
= "", *off_failed
= "";
2012 bool circle
= false;
2014 if (streq_ptr(m
->state
, "degraded")) {
2015 on_state
= ansi_highlight_red();
2016 off_state
= ansi_normal();
2018 } else if (!streq_ptr(m
->state
, "running")) {
2019 on_state
= ansi_highlight_yellow();
2020 off_state
= ansi_normal();
2024 if (m
->n_failed_units
> 0) {
2025 on_failed
= ansi_highlight_red();
2026 off_failed
= ansi_normal();
2028 on_failed
= off_failed
= "";
2031 printf("%s%s%s ", on_state
, circle
? special_glyph(BLACK_CIRCLE
) : " ", off_state
);
2034 printf("%-*s (host) %s%-*s%s %s%*" PRIu32
"%s %*" PRIu32
"\n",
2035 (int) (namelen
- (STRLEN(" (host)"))),
2037 on_state
, statelen
, strna(m
->state
), off_state
,
2038 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
2039 jobslen
, m
->n_jobs
);
2041 printf("%-*s %s%-*s%s %s%*" PRIu32
"%s %*" PRIu32
"\n",
2042 namelen
, strna(m
->name
),
2043 on_state
, statelen
, strna(m
->state
), off_state
,
2044 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
2045 jobslen
, m
->n_jobs
);
2049 printf("\n%u machines listed.\n", n
);
2052 static int list_machines(int argc
, char *argv
[], void *userdata
) {
2053 struct machine_info
*machine_infos
= NULL
;
2057 r
= acquire_bus(BUS_MANAGER
, &bus
);
2061 r
= get_machine_list(bus
, &machine_infos
, strv_skip(argv
, 1));
2065 (void) pager_open(arg_no_pager
, false);
2067 qsort_safe(machine_infos
, r
, sizeof(struct machine_info
), compare_machine_info
);
2068 output_machines_list(machine_infos
, r
);
2069 free_machines_list(machine_infos
, r
);
2074 static int get_default(int argc
, char *argv
[], void *userdata
) {
2075 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2076 _cleanup_free_
char *_path
= NULL
;
2080 if (install_client_side()) {
2081 r
= unit_file_get_default(arg_scope
, arg_root
, &_path
);
2083 return log_error_errno(r
, "Failed to get default target: %m");
2088 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2091 r
= acquire_bus(BUS_MANAGER
, &bus
);
2095 r
= sd_bus_call_method(
2097 "org.freedesktop.systemd1",
2098 "/org/freedesktop/systemd1",
2099 "org.freedesktop.systemd1.Manager",
2105 return log_error_errno(r
, "Failed to get default target: %s", bus_error_message(&error
, r
));
2107 r
= sd_bus_message_read(reply
, "s", &path
);
2109 return bus_log_parse_error(r
);
2113 printf("%s\n", path
);
2118 static int set_default(int argc
, char *argv
[], void *userdata
) {
2119 _cleanup_free_
char *unit
= NULL
;
2120 UnitFileChange
*changes
= NULL
;
2121 unsigned n_changes
= 0;
2127 r
= unit_name_mangle_with_suffix(argv
[1], arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
, ".target", &unit
);
2129 return log_error_errno(r
, "Failed to mangle unit name: %m");
2131 if (install_client_side()) {
2132 r
= unit_file_set_default(arg_scope
, UNIT_FILE_FORCE
, arg_root
, unit
, &changes
, &n_changes
);
2133 unit_file_dump_changes(r
, "set default", changes
, n_changes
, arg_quiet
);
2138 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2139 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2142 polkit_agent_open_maybe();
2144 r
= acquire_bus(BUS_MANAGER
, &bus
);
2148 r
= sd_bus_call_method(
2150 "org.freedesktop.systemd1",
2151 "/org/freedesktop/systemd1",
2152 "org.freedesktop.systemd1.Manager",
2158 return log_error_errno(r
, "Failed to set default target: %s", bus_error_message(&error
, r
));
2160 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
2164 /* Try to reload if enabled */
2166 r
= daemon_reload(argc
, argv
, userdata
);
2172 unit_file_changes_free(changes
, n_changes
);
2177 static int output_waiting_jobs(sd_bus
*bus
, uint32_t id
, const char *method
, const char *prefix
) {
2178 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2179 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2180 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2186 r
= sd_bus_call_method(
2188 "org.freedesktop.systemd1",
2189 "/org/freedesktop/systemd1",
2190 "org.freedesktop.systemd1.Manager",
2196 return log_debug_errno(r
, "Failed to get waiting jobs for job %" PRIu32
, id
);
2198 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2200 return bus_log_parse_error(r
);
2202 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &other_id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0)
2203 printf("%s %u (%s/%s)\n", prefix
, other_id
, name
, type
);
2205 return bus_log_parse_error(r
);
2207 r
= sd_bus_message_exit_container(reply
);
2209 return bus_log_parse_error(r
);
2216 const char *name
, *type
, *state
;
2219 static void output_jobs_list(sd_bus
*bus
, const struct job_info
* jobs
, unsigned n
, bool skipped
) {
2220 unsigned id_len
, unit_len
, type_len
, state_len
;
2221 const struct job_info
*j
;
2222 const char *on
, *off
;
2223 bool shorten
= false;
2225 assert(n
== 0 || jobs
);
2228 if (!arg_no_legend
) {
2229 on
= ansi_highlight_green();
2230 off
= ansi_normal();
2232 printf("%sNo jobs %s.%s\n", on
, skipped
? "listed" : "running", off
);
2237 (void) pager_open(arg_no_pager
, false);
2239 id_len
= STRLEN("JOB");
2240 unit_len
= STRLEN("UNIT");
2241 type_len
= STRLEN("TYPE");
2242 state_len
= STRLEN("STATE");
2244 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2245 uint32_t id
= j
->id
;
2246 assert(j
->name
&& j
->type
&& j
->state
);
2248 id_len
= MAX(id_len
, DECIMAL_STR_WIDTH(id
));
2249 unit_len
= MAX(unit_len
, strlen(j
->name
));
2250 type_len
= MAX(type_len
, strlen(j
->type
));
2251 state_len
= MAX(state_len
, strlen(j
->state
));
2254 if (!arg_full
&& id_len
+ 1 + unit_len
+ type_len
+ 1 + state_len
> columns()) {
2255 unit_len
= MAX(33u, columns() - id_len
- type_len
- state_len
- 3);
2260 printf("%*s %-*s %-*s %-*s\n",
2264 state_len
, "STATE");
2266 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2267 _cleanup_free_
char *e
= NULL
;
2269 if (streq(j
->state
, "running")) {
2270 on
= ansi_highlight();
2271 off
= ansi_normal();
2275 e
= shorten
? ellipsize(j
->name
, unit_len
, 33) : NULL
;
2276 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2278 on
, unit_len
, e
? e
: j
->name
, off
,
2280 on
, state_len
, j
->state
, off
);
2283 output_waiting_jobs(bus
, j
->id
, "GetJobAfter", "\twaiting for job");
2284 if (arg_jobs_before
)
2285 output_waiting_jobs(bus
, j
->id
, "GetJobBefore", "\tblocking job");
2288 if (!arg_no_legend
) {
2289 on
= ansi_highlight();
2290 off
= ansi_normal();
2292 printf("\n%s%u jobs listed%s.\n", on
, n
, off
);
2296 static bool output_show_job(struct job_info
*job
, char **patterns
) {
2297 return strv_fnmatch_or_empty(patterns
, job
->name
, FNM_NOESCAPE
);
2300 static int list_jobs(int argc
, char *argv
[], void *userdata
) {
2301 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2302 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2303 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2304 _cleanup_free_
struct job_info
*jobs
= NULL
;
2310 bool skipped
= false;
2312 r
= acquire_bus(BUS_MANAGER
, &bus
);
2316 r
= sd_bus_call_method(
2318 "org.freedesktop.systemd1",
2319 "/org/freedesktop/systemd1",
2320 "org.freedesktop.systemd1.Manager",
2326 return log_error_errno(r
, "Failed to list jobs: %s", bus_error_message(&error
, r
));
2328 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2330 return bus_log_parse_error(r
);
2332 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0) {
2333 struct job_info job
= { id
, name
, type
, state
};
2335 if (!output_show_job(&job
, strv_skip(argv
, 1))) {
2340 if (!GREEDY_REALLOC(jobs
, size
, c
+ 1))
2346 return bus_log_parse_error(r
);
2348 r
= sd_bus_message_exit_container(reply
);
2350 return bus_log_parse_error(r
);
2352 (void) pager_open(arg_no_pager
, false);
2354 output_jobs_list(bus
, jobs
, c
, skipped
);
2358 static int cancel_job(int argc
, char *argv
[], void *userdata
) {
2364 return trivial_method(argc
, argv
, userdata
);
2366 r
= acquire_bus(BUS_MANAGER
, &bus
);
2370 polkit_agent_open_maybe();
2372 STRV_FOREACH(name
, strv_skip(argv
, 1)) {
2373 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2377 q
= safe_atou32(*name
, &id
);
2379 return log_error_errno(q
, "Failed to parse job id \"%s\": %m", *name
);
2381 q
= sd_bus_call_method(
2383 "org.freedesktop.systemd1",
2384 "/org/freedesktop/systemd1",
2385 "org.freedesktop.systemd1.Manager",
2391 log_error_errno(q
, "Failed to cancel job %"PRIu32
": %s", id
, bus_error_message(&error
, q
));
2400 static int need_daemon_reload(sd_bus
*bus
, const char *unit
) {
2401 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2405 /* We ignore all errors here, since this is used to show a
2408 /* We don't use unit_dbus_path_from_name() directly since we
2409 * don't want to load the unit if it isn't loaded. */
2411 r
= sd_bus_call_method(
2413 "org.freedesktop.systemd1",
2414 "/org/freedesktop/systemd1",
2415 "org.freedesktop.systemd1.Manager",
2423 r
= sd_bus_message_read(reply
, "o", &path
);
2427 r
= sd_bus_get_property_trivial(
2429 "org.freedesktop.systemd1",
2431 "org.freedesktop.systemd1.Unit",
2441 static void warn_unit_file_changed(const char *name
) {
2444 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.",
2445 ansi_highlight_red(),
2448 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user");
2451 static int unit_file_find_path(LookupPaths
*lp
, const char *unit_name
, char **unit_path
) {
2457 STRV_FOREACH(p
, lp
->search_path
) {
2458 _cleanup_free_
char *path
= NULL
, *lpath
= NULL
;
2461 path
= path_join(NULL
, *p
, unit_name
);
2465 r
= chase_symlinks(path
, arg_root
, 0, &lpath
);
2471 return log_error_errno(r
, "Failed to access path '%s': %m", path
);
2474 *unit_path
= TAKE_PTR(lpath
);
2482 static int unit_find_template_path(
2483 const char *unit_name
,
2485 char **fragment_path
,
2488 _cleanup_free_
char *_template
= NULL
;
2491 /* Returns 1 if a fragment was found, 0 if not found, negative on error. */
2493 r
= unit_file_find_path(lp
, unit_name
, fragment_path
);
2495 return r
; /* error or found a real unit */
2497 r
= unit_name_template(unit_name
, &_template
);
2499 return 0; /* not a template, does not exist */
2501 return log_error_errno(r
, "Failed to determine template name: %m");
2503 r
= unit_file_find_path(lp
, _template
, fragment_path
);
2508 *template = TAKE_PTR(_template
);
2513 static int unit_find_paths(
2515 const char *unit_name
,
2517 char **fragment_path
,
2518 char ***dropin_paths
) {
2520 _cleanup_free_
char *path
= NULL
;
2521 _cleanup_strv_free_
char **dropins
= NULL
;
2525 * Finds where the unit is defined on disk. Returns 0 if the unit
2526 * is not found. Returns 1 if it is found, and sets
2527 * - the path to the unit in *path, if it exists on disk,
2528 * - and a strv of existing drop-ins in *dropins,
2529 * if the arg is not NULL and any dropins were found.
2533 assert(fragment_path
);
2536 if (!install_client_side() && !unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
2537 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2538 _cleanup_free_
char *unit
= NULL
;
2540 unit
= unit_dbus_path_from_name(unit_name
);
2544 r
= sd_bus_get_property_string(
2546 "org.freedesktop.systemd1",
2548 "org.freedesktop.systemd1.Unit",
2553 return log_error_errno(r
, "Failed to get FragmentPath: %s", bus_error_message(&error
, r
));
2556 r
= sd_bus_get_property_strv(
2558 "org.freedesktop.systemd1",
2560 "org.freedesktop.systemd1.Unit",
2565 return log_error_errno(r
, "Failed to get DropInPaths: %s", bus_error_message(&error
, r
));
2568 _cleanup_set_free_ Set
*names
= NULL
;
2569 _cleanup_free_
char *template = NULL
;
2571 names
= set_new(NULL
);
2575 r
= unit_find_template_path(unit_name
, lp
, &path
, &template);
2580 /* We found the unit file. If we followed symlinks, this name might be
2581 * different then the unit_name with started with. Look for dropins matching
2582 * that "final" name. */
2583 r
= set_put(names
, basename(path
));
2585 /* No unit file, let's look for dropins matching the original name.
2586 * systemd has fairly complicated rules (based on unit type and provenience),
2587 * which units are allowed not to have the main unit file. We err on the
2588 * side of including too many files, and always try to load dropins. */
2589 r
= set_put(names
, unit_name
);
2591 /* The cases where we allow a unit to exist without the main file are
2592 * never valid for templates. Don't try to load dropins in this case. */
2596 return log_error_errno(r
, "Failed to add unit name: %m");
2599 r
= unit_file_find_dropin_conf_paths(arg_root
, lp
->search_path
,
2600 NULL
, names
, &dropins
);
2608 if (!isempty(path
)) {
2609 *fragment_path
= path
;
2614 if (dropin_paths
&& !strv_isempty(dropins
)) {
2615 *dropin_paths
= dropins
;
2620 if (r
== 0 && !arg_force
)
2621 log_error("No files found for %s.", unit_name
);
2626 static int get_state_one_unit(sd_bus
*bus
, const char *name
, UnitActiveState
*active_state
) {
2627 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2628 _cleanup_free_
char *buf
= NULL
, *path
= NULL
;
2629 UnitActiveState state
;
2633 assert(active_state
);
2635 path
= unit_dbus_path_from_name(name
);
2639 r
= sd_bus_get_property_string(
2641 "org.freedesktop.systemd1",
2643 "org.freedesktop.systemd1.Unit",
2648 return log_error_errno(r
, "Failed to retrieve unit state: %s", bus_error_message(&error
, r
));
2650 state
= unit_active_state_from_string(buf
);
2651 if (state
== _UNIT_ACTIVE_STATE_INVALID
) {
2652 log_error("Invalid unit state '%s' for: %s", buf
, name
);
2656 *active_state
= state
;
2660 static int unit_is_masked(sd_bus
*bus
, const char *name
) {
2661 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2662 _cleanup_free_
char *path
= NULL
, *load_state
= NULL
;
2665 path
= unit_dbus_path_from_name(name
);
2669 r
= sd_bus_get_property_string(
2671 "org.freedesktop.systemd1",
2673 "org.freedesktop.systemd1.Unit",
2678 return log_error_errno(r
, "Failed to get load state of %s: %s", name
, bus_error_message(&error
, r
));
2680 return streq(load_state
, "masked");
2683 static int check_triggering_units(sd_bus
*bus
, const char *name
) {
2684 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2685 _cleanup_free_
char *n
= NULL
, *path
= NULL
;
2686 _cleanup_strv_free_
char **triggered_by
= NULL
;
2687 bool print_warning_label
= true;
2688 UnitActiveState active_state
;
2692 r
= unit_name_mangle(name
, 0, &n
);
2694 return log_error_errno(r
, "Failed to mangle unit name: %m");
2696 r
= unit_is_masked(bus
, n
);
2698 return r
< 0 ? r
: 0;
2700 path
= unit_dbus_path_from_name(n
);
2704 r
= sd_bus_get_property_strv(
2706 "org.freedesktop.systemd1",
2708 "org.freedesktop.systemd1.Unit",
2713 return log_error_errno(r
, "Failed to get triggered by array of %s: %s", n
, bus_error_message(&error
, r
));
2715 STRV_FOREACH(i
, triggered_by
) {
2716 r
= get_state_one_unit(bus
, *i
, &active_state
);
2720 if (!IN_SET(active_state
, UNIT_ACTIVE
, UNIT_RELOADING
))
2723 if (print_warning_label
) {
2724 log_warning("Warning: Stopping %s, but it can still be activated by:", n
);
2725 print_warning_label
= false;
2728 log_warning(" %s", *i
);
2734 static const struct {
2737 } unit_actions
[] = {
2738 { "start", "StartUnit" },
2739 { "stop", "StopUnit" },
2740 { "condstop", "StopUnit" },
2741 { "reload", "ReloadUnit" },
2742 { "restart", "RestartUnit" },
2743 { "try-restart", "TryRestartUnit" },
2744 { "condrestart", "TryRestartUnit" },
2745 { "reload-or-restart", "ReloadOrRestartUnit" },
2746 { "try-reload-or-restart", "ReloadOrTryRestartUnit" },
2747 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2748 { "condreload", "ReloadOrTryRestartUnit" },
2749 { "force-reload", "ReloadOrTryRestartUnit" }
2752 static const char *verb_to_method(const char *verb
) {
2755 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2756 if (streq_ptr(unit_actions
[i
].verb
, verb
))
2757 return unit_actions
[i
].method
;
2762 static const char *method_to_verb(const char *method
) {
2765 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2766 if (streq_ptr(unit_actions
[i
].method
, method
))
2767 return unit_actions
[i
].verb
;
2779 static void wait_context_free(WaitContext
*c
) {
2780 c
->match
= sd_bus_slot_unref(c
->match
);
2781 c
->event
= sd_event_unref(c
->event
);
2782 c
->unit_paths
= set_free_free(c
->unit_paths
);
2785 static int on_properties_changed(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
2786 WaitContext
*c
= userdata
;
2790 path
= sd_bus_message_get_path(m
);
2791 if (!set_contains(c
->unit_paths
, path
))
2794 /* Check if ActiveState changed to inactive/failed */
2795 /* (s interface, a{sv} changed_properties, as invalidated_properties) */
2796 r
= sd_bus_message_skip(m
, "s");
2798 return bus_log_parse_error(r
);
2800 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "{sv}");
2802 return bus_log_parse_error(r
);
2804 while ((r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
2807 r
= sd_bus_message_read(m
, "s", &s
);
2809 return bus_log_parse_error(r
);
2811 if (streq(s
, "ActiveState")) {
2814 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, "s");
2816 return bus_log_parse_error(r
);
2818 r
= sd_bus_message_read(m
, "s", &s
);
2820 return bus_log_parse_error(r
);
2822 is_failed
= streq(s
, "failed");
2823 if (streq(s
, "inactive") || is_failed
) {
2824 log_debug("%s became %s, dropping from --wait tracking", path
, s
);
2825 free(set_remove(c
->unit_paths
, path
));
2826 c
->any_failed
= c
->any_failed
|| is_failed
;
2828 log_debug("ActiveState on %s changed to %s", path
, s
);
2830 break; /* no need to dissect the rest of the message */
2832 /* other property */
2833 r
= sd_bus_message_skip(m
, "v");
2835 return bus_log_parse_error(r
);
2837 r
= sd_bus_message_exit_container(m
);
2839 return bus_log_parse_error(r
);
2842 return bus_log_parse_error(r
);
2844 if (set_isempty(c
->unit_paths
))
2845 sd_event_exit(c
->event
, EXIT_SUCCESS
);
2850 static int start_unit_one(
2855 sd_bus_error
*error
,
2857 WaitContext
*wait_context
) {
2859 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2869 _cleanup_free_
char *unit_path
= NULL
;
2871 log_debug("Watching for property changes of %s", name
);
2872 r
= sd_bus_call_method(
2874 "org.freedesktop.systemd1",
2875 "/org/freedesktop/systemd1",
2876 "org.freedesktop.systemd1.Manager",
2882 return log_error_errno(r
, "Failed to RefUnit %s: %s", name
, bus_error_message(error
, r
));
2884 unit_path
= unit_dbus_path_from_name(name
);
2888 r
= set_put_strdup(wait_context
->unit_paths
, unit_path
);
2890 return log_error_errno(r
, "Failed to add unit path %s to set: %m", unit_path
);
2892 r
= sd_bus_match_signal_async(bus
,
2893 &wait_context
->match
,
2896 "org.freedesktop.DBus.Properties",
2897 "PropertiesChanged",
2898 on_properties_changed
, NULL
, wait_context
);
2900 return log_error_errno(r
, "Failed to request match for PropertiesChanged signal: %m");
2903 log_debug("%s dbus call org.freedesktop.systemd1.Manager %s(%s, %s)",
2904 arg_dry_run
? "Would execute" : "Executing",
2905 method
, name
, mode
);
2909 r
= sd_bus_call_method(
2911 "org.freedesktop.systemd1",
2912 "/org/freedesktop/systemd1",
2913 "org.freedesktop.systemd1.Manager",
2921 /* There's always a fallback possible for legacy actions. */
2922 if (arg_action
!= ACTION_SYSTEMCTL
)
2925 verb
= method_to_verb(method
);
2927 log_error("Failed to %s %s: %s", verb
, name
, bus_error_message(error
, r
));
2929 if (!sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) &&
2930 !sd_bus_error_has_name(error
, BUS_ERROR_UNIT_MASKED
) &&
2931 !sd_bus_error_has_name(error
, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE
))
2932 log_error("See %s logs and 'systemctl%s status%s %s' for details.",
2933 arg_scope
== UNIT_FILE_SYSTEM
? "system" : "user",
2934 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user",
2935 name
[0] == '-' ? " --" : "",
2941 r
= sd_bus_message_read(reply
, "o", &path
);
2943 return bus_log_parse_error(r
);
2945 if (need_daemon_reload(bus
, name
) > 0)
2946 warn_unit_file_changed(name
);
2949 log_debug("Adding %s to the set", path
);
2950 r
= bus_wait_for_jobs_add(w
, path
);
2958 static int expand_names(sd_bus
*bus
, char **names
, const char* suffix
, char ***ret
) {
2959 _cleanup_strv_free_
char **mangled
= NULL
, **globs
= NULL
;
2966 STRV_FOREACH(name
, names
) {
2968 UnitNameMangle options
= UNIT_NAME_MANGLE_GLOB
| (arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
);
2971 r
= unit_name_mangle_with_suffix(*name
, options
, suffix
, &t
);
2973 r
= unit_name_mangle(*name
, options
, &t
);
2975 return log_error_errno(r
, "Failed to mangle name: %m");
2977 if (string_is_glob(t
))
2978 r
= strv_consume(&globs
, t
);
2980 r
= strv_consume(&mangled
, t
);
2985 /* Query the manager only if any of the names are a glob, since
2986 * this is fairly expensive */
2987 if (!strv_isempty(globs
)) {
2988 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2989 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
2990 size_t allocated
, n
;
2992 r
= get_unit_list(bus
, NULL
, globs
, &unit_infos
, 0, &reply
);
2996 n
= strv_length(mangled
);
2999 for (i
= 0; i
< r
; i
++) {
3000 if (!GREEDY_REALLOC(mangled
, allocated
, n
+2))
3003 mangled
[n
] = strdup(unit_infos
[i
].id
);
3007 mangled
[++n
] = NULL
;
3012 mangled
= NULL
; /* do not free */
3017 static const struct {
3021 } action_table
[_ACTION_MAX
] = {
3022 [ACTION_HALT
] = { SPECIAL_HALT_TARGET
, "halt", "replace-irreversibly" },
3023 [ACTION_POWEROFF
] = { SPECIAL_POWEROFF_TARGET
, "poweroff", "replace-irreversibly" },
3024 [ACTION_REBOOT
] = { SPECIAL_REBOOT_TARGET
, "reboot", "replace-irreversibly" },
3025 [ACTION_KEXEC
] = { SPECIAL_KEXEC_TARGET
, "kexec", "replace-irreversibly" },
3026 [ACTION_RUNLEVEL2
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
3027 [ACTION_RUNLEVEL3
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
3028 [ACTION_RUNLEVEL4
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
3029 [ACTION_RUNLEVEL5
] = { SPECIAL_GRAPHICAL_TARGET
, NULL
, "isolate" },
3030 [ACTION_RESCUE
] = { SPECIAL_RESCUE_TARGET
, "rescue", "isolate" },
3031 [ACTION_EMERGENCY
] = { SPECIAL_EMERGENCY_TARGET
, "emergency", "isolate" },
3032 [ACTION_DEFAULT
] = { SPECIAL_DEFAULT_TARGET
, "default", "isolate" },
3033 [ACTION_EXIT
] = { SPECIAL_EXIT_TARGET
, "exit", "replace-irreversibly" },
3034 [ACTION_SUSPEND
] = { SPECIAL_SUSPEND_TARGET
, "suspend", "replace-irreversibly" },
3035 [ACTION_HIBERNATE
] = { SPECIAL_HIBERNATE_TARGET
, "hibernate", "replace-irreversibly" },
3036 [ACTION_HYBRID_SLEEP
] = { SPECIAL_HYBRID_SLEEP_TARGET
, "hybrid-sleep", "replace-irreversibly" },
3037 [ACTION_SUSPEND_THEN_HIBERNATE
] = { SPECIAL_SUSPEND_THEN_HIBERNATE_TARGET
, "suspend-then-hibernate", "replace-irreversibly" },
3040 static enum action
verb_to_action(const char *verb
) {
3043 for (i
= 0; i
< _ACTION_MAX
; i
++)
3044 if (streq_ptr(action_table
[i
].verb
, verb
))
3047 return _ACTION_INVALID
;
3050 static int start_unit(int argc
, char *argv
[], void *userdata
) {
3051 _cleanup_(bus_wait_for_jobs_freep
) BusWaitForJobs
*w
= NULL
;
3052 const char *method
, *mode
, *one_name
, *suffix
= NULL
;
3053 _cleanup_strv_free_
char **names
= NULL
;
3055 _cleanup_(wait_context_free
) WaitContext wait_context
= {};
3059 if (arg_wait
&& !STR_IN_SET(argv
[0], "start", "restart")) {
3060 log_error("--wait may only be used with the 'start' or 'restart' commands.");
3064 /* we cannot do sender tracking on the private bus, so we need the full
3065 * one for RefUnit to implement --wait */
3066 r
= acquire_bus(arg_wait
? BUS_FULL
: BUS_MANAGER
, &bus
);
3070 ask_password_agent_open_if_enabled();
3071 polkit_agent_open_maybe();
3073 if (arg_action
== ACTION_SYSTEMCTL
) {
3076 action
= verb_to_action(argv
[0]);
3078 if (action
!= _ACTION_INVALID
) {
3079 method
= "StartUnit";
3080 mode
= action_table
[action
].mode
;
3081 one_name
= action_table
[action
].target
;
3083 if (streq(argv
[0], "isolate")) {
3084 method
= "StartUnit";
3089 method
= verb_to_method(argv
[0]);
3090 mode
= arg_job_mode
;
3095 assert(arg_action
>= 0 && arg_action
< _ACTION_MAX
);
3096 assert(action_table
[arg_action
].target
);
3097 assert(action_table
[arg_action
].mode
);
3099 method
= "StartUnit";
3100 mode
= action_table
[arg_action
].mode
;
3101 one_name
= action_table
[arg_action
].target
;
3105 names
= strv_new(one_name
, NULL
);
3107 r
= expand_names(bus
, strv_skip(argv
, 1), suffix
, &names
);
3109 return log_error_errno(r
, "Failed to expand names: %m");
3112 if (!arg_no_block
) {
3113 r
= bus_wait_for_jobs_new(bus
, &w
);
3115 return log_error_errno(r
, "Could not watch jobs: %m");
3119 wait_context
.unit_paths
= set_new(&string_hash_ops
);
3120 if (!wait_context
.unit_paths
)
3123 r
= sd_bus_call_method_async(
3126 "org.freedesktop.systemd1",
3127 "/org/freedesktop/systemd1",
3128 "org.freedesktop.systemd1.Manager",
3133 return log_error_errno(r
, "Failed to enable subscription: %m");
3134 r
= sd_event_default(&wait_context
.event
);
3136 return log_error_errno(r
, "Failed to allocate event loop: %m");
3137 r
= sd_bus_attach_event(bus
, wait_context
.event
, 0);
3139 return log_error_errno(r
, "Failed to attach bus to event loop: %m");
3142 STRV_FOREACH(name
, names
) {
3143 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3146 q
= start_unit_one(bus
, method
, *name
, mode
, &error
, w
, arg_wait
? &wait_context
: NULL
);
3147 if (r
>= 0 && q
< 0)
3148 r
= translate_bus_error_to_exit_status(q
, &error
);
3151 if (!arg_no_block
) {
3152 int q
, arg_count
= 0;
3153 const char* extra_args
[4] = {};
3155 if (arg_scope
!= UNIT_FILE_SYSTEM
)
3156 extra_args
[arg_count
++] = "--user";
3158 assert(IN_SET(arg_transport
, BUS_TRANSPORT_LOCAL
, BUS_TRANSPORT_REMOTE
, BUS_TRANSPORT_MACHINE
));
3159 if (arg_transport
== BUS_TRANSPORT_REMOTE
) {
3160 extra_args
[arg_count
++] = "-H";
3161 extra_args
[arg_count
++] = arg_host
;
3162 } else if (arg_transport
== BUS_TRANSPORT_MACHINE
) {
3163 extra_args
[arg_count
++] = "-M";
3164 extra_args
[arg_count
++] = arg_host
;
3167 q
= bus_wait_for_jobs(w
, arg_quiet
, extra_args
);
3171 /* When stopping units, warn if they can still be triggered by
3172 * another active unit (socket, path, timer) */
3173 if (!arg_quiet
&& streq(method
, "StopUnit"))
3174 STRV_FOREACH(name
, names
)
3175 check_triggering_units(bus
, *name
);
3178 if (r
>= 0 && arg_wait
) {
3180 q
= sd_event_loop(wait_context
.event
);
3182 return log_error_errno(q
, "Failed to run event loop: %m");
3183 if (wait_context
.any_failed
)
3191 static int logind_set_wall_message(void) {
3192 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3194 _cleanup_free_
char *m
= NULL
;
3197 r
= acquire_bus(BUS_FULL
, &bus
);
3201 m
= strv_join(arg_wall
, " ");
3205 log_debug("%s wall message \"%s\".", arg_dry_run
? "Would set" : "Setting", m
);
3209 r
= sd_bus_call_method(
3211 "org.freedesktop.login1",
3212 "/org/freedesktop/login1",
3213 "org.freedesktop.login1.Manager",
3222 return log_warning_errno(r
, "Failed to set wall message, ignoring: %s", bus_error_message(&error
, r
));
3227 /* Ask systemd-logind, which might grant access to unprivileged users
3228 * through PolicyKit */
3229 static int logind_reboot(enum action a
) {
3231 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3232 const char *method
, *description
;
3236 r
= acquire_bus(BUS_FULL
, &bus
);
3242 case ACTION_POWEROFF
:
3243 method
= "PowerOff";
3244 description
= "power off system";
3249 description
= "reboot system";
3254 description
= "halt system";
3257 case ACTION_SUSPEND
:
3259 description
= "suspend system";
3262 case ACTION_HIBERNATE
:
3263 method
= "Hibernate";
3264 description
= "hibernate system";
3267 case ACTION_HYBRID_SLEEP
:
3268 method
= "HybridSleep";
3269 description
= "put system into hybrid sleep";
3272 case ACTION_SUSPEND_THEN_HIBERNATE
:
3273 method
= "SuspendThenHibernate";
3274 description
= "put system into suspend followed by hibernate";
3281 polkit_agent_open_maybe();
3282 (void) logind_set_wall_message();
3284 log_debug("%s org.freedesktop.login1.Manager %s dbus call.", arg_dry_run
? "Would execute" : "Executing", method
);
3288 r
= sd_bus_call_method(
3290 "org.freedesktop.login1",
3291 "/org/freedesktop/login1",
3292 "org.freedesktop.login1.Manager",
3296 "b", arg_ask_password
);
3298 return log_error_errno(r
, "Failed to %s via logind: %s", description
, bus_error_message(&error
, r
));
3306 static int logind_check_inhibitors(enum action a
) {
3308 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
3309 _cleanup_strv_free_
char **sessions
= NULL
;
3310 const char *what
, *who
, *why
, *mode
;
3317 if (arg_ignore_inhibitors
|| arg_force
> 0)
3329 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
3332 r
= acquire_bus(BUS_FULL
, &bus
);
3336 r
= sd_bus_call_method(
3338 "org.freedesktop.login1",
3339 "/org/freedesktop/login1",
3340 "org.freedesktop.login1.Manager",
3346 /* If logind is not around, then there are no inhibitors... */
3349 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssuu)");
3351 return bus_log_parse_error(r
);
3353 while ((r
= sd_bus_message_read(reply
, "(ssssuu)", &what
, &who
, &why
, &mode
, &uid
, &pid
)) > 0) {
3354 _cleanup_free_
char *comm
= NULL
, *user
= NULL
;
3355 _cleanup_strv_free_
char **sv
= NULL
;
3357 if (!streq(mode
, "block"))
3360 sv
= strv_split(what
, ":");
3364 if (!pid_is_valid((pid_t
) pid
)) {
3365 log_error("Invalid PID "PID_FMT
".", (pid_t
) pid
);
3369 if (!strv_contains(sv
,
3374 ACTION_KEXEC
) ? "shutdown" : "sleep"))
3377 get_process_comm(pid
, &comm
);
3378 user
= uid_to_name(uid
);
3380 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT
" \"%s\", user %s), reason is \"%s\".",
3381 who
, (pid_t
) pid
, strna(comm
), strna(user
), why
);
3386 return bus_log_parse_error(r
);
3388 r
= sd_bus_message_exit_container(reply
);
3390 return bus_log_parse_error(r
);
3392 /* Check for current sessions */
3393 sd_get_sessions(&sessions
);
3394 STRV_FOREACH(s
, sessions
) {
3395 _cleanup_free_
char *type
= NULL
, *tty
= NULL
, *seat
= NULL
, *user
= NULL
, *service
= NULL
, *class = NULL
;
3397 if (sd_session_get_uid(*s
, &uid
) < 0 || uid
== getuid())
3400 if (sd_session_get_class(*s
, &class) < 0 || !streq(class, "user"))
3403 if (sd_session_get_type(*s
, &type
) < 0 || !STR_IN_SET(type
, "x11", "wayland", "tty", "mir"))
3406 sd_session_get_tty(*s
, &tty
);
3407 sd_session_get_seat(*s
, &seat
);
3408 sd_session_get_service(*s
, &service
);
3409 user
= uid_to_name(uid
);
3411 log_warning("User %s is logged in on %s.", strna(user
), isempty(tty
) ? (isempty(seat
) ? strna(service
) : seat
) : tty
);
3418 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
3419 action_table
[a
].verb
);
3427 static int logind_prepare_firmware_setup(void) {
3429 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3433 r
= acquire_bus(BUS_FULL
, &bus
);
3437 r
= sd_bus_call_method(
3439 "org.freedesktop.login1",
3440 "/org/freedesktop/login1",
3441 "org.freedesktop.login1.Manager",
3442 "SetRebootToFirmwareSetup",
3447 return log_error_errno(r
, "Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error
, r
));
3451 log_error("Cannot remotely indicate to EFI to boot into setup mode.");
3456 static int prepare_firmware_setup(void) {
3459 if (!arg_firmware_setup
)
3462 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
3464 r
= efi_set_reboot_to_firmware(true);
3466 log_debug_errno(r
, "Cannot indicate to EFI to boot into setup mode, will retry via logind: %m");
3471 return logind_prepare_firmware_setup();
3474 static int load_kexec_kernel(void) {
3475 _cleanup_(boot_config_free
) BootConfig config
= {};
3476 _cleanup_free_
char *where
= NULL
, *kernel
= NULL
, *initrd
= NULL
, *options
= NULL
;
3481 if (kexec_loaded()) {
3482 log_debug("Kexec kernel already loaded.");
3486 if (access(KEXEC
, X_OK
) < 0)
3487 return log_error_errno(errno
, KEXEC
" is not available: %m");
3489 r
= find_esp_and_warn(arg_esp_path
, false, &where
, NULL
, NULL
, NULL
, NULL
);
3490 if (r
== -ENOKEY
) /* find_esp_and_warn() doesn't warn about this case */
3491 return log_error_errno(r
, "Cannot find the ESP partition mount point.");
3492 if (r
< 0) /* But it logs about all these cases, hence don't log here again */
3495 r
= boot_entries_load_config(where
, &config
);
3497 return log_error_errno(r
, "Failed to load bootspec config from \"%s/loader\": %m", where
);
3499 if (config
.default_entry
< 0) {
3500 log_error("No entry suitable as default, refusing to guess.");
3503 e
= &config
.entries
[config
.default_entry
];
3505 if (strv_length(e
->initrd
) > 1) {
3506 log_error("Boot entry specifies multiple initrds, which is not supported currently.");
3510 kernel
= path_join(NULL
, where
, e
->kernel
);
3511 if (!strv_isempty(e
->initrd
))
3512 initrd
= path_join(NULL
, where
, *e
->initrd
);
3513 options
= strv_join(e
->options
, " ");
3517 log_full(arg_quiet
? LOG_DEBUG
: LOG_INFO
,
3518 "%s "KEXEC
" --load \"%s\" --append \"%s\"%s%s%s",
3519 arg_dry_run
? "Would run" : "Running",
3522 initrd
? " --initrd \"" : NULL
, strempty(initrd
), initrd
? "\"" : "");
3526 r
= safe_fork("(kexec)", FORK_RESET_SIGNALS
|FORK_DEATHSIG
|FORK_LOG
, &pid
);
3530 const char* const args
[] = {
3533 "--append", options
,
3534 initrd
? "--initrd" : NULL
, initrd
,
3538 execv(args
[0], (char * const *) args
);
3539 _exit(EXIT_FAILURE
);
3542 r
= wait_for_terminate_and_check("kexec", pid
, WAIT_LOG
);
3546 /* Command failed */
3551 static int set_exit_code(uint8_t code
) {
3552 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3556 r
= acquire_bus(BUS_MANAGER
, &bus
);
3560 r
= sd_bus_call_method(
3562 "org.freedesktop.systemd1",
3563 "/org/freedesktop/systemd1",
3564 "org.freedesktop.systemd1.Manager",
3570 return log_error_errno(r
, "Failed to set exit code: %s", bus_error_message(&error
, r
));
3575 static int start_special(int argc
, char *argv
[], void *userdata
) {
3578 bool termination_action
; /* an action that terminates the manager,
3579 * can be performed also by signal. */
3583 a
= verb_to_action(argv
[0]);
3585 r
= logind_check_inhibitors(a
);
3589 if (arg_force
>= 2) {
3595 r
= prepare_firmware_setup();
3599 if (a
== ACTION_REBOOT
&& argc
> 1) {
3600 r
= update_reboot_parameter_and_warn(argv
[1]);
3604 } else if (a
== ACTION_KEXEC
) {
3605 r
= load_kexec_kernel();
3606 if (r
< 0 && arg_force
>= 1)
3607 log_notice("Failed to load kexec kernel, continuing without.");
3611 } else if (a
== ACTION_EXIT
&& argc
> 1) {
3614 /* If the exit code is not given on the command line,
3615 * don't reset it to zero: just keep it as it might
3616 * have been set previously. */
3618 r
= safe_atou8(argv
[1], &code
);
3620 return log_error_errno(r
, "Invalid exit code.");
3622 r
= set_exit_code(code
);
3627 termination_action
= IN_SET(a
,
3631 if (termination_action
&& arg_force
>= 2)
3634 if (arg_force
>= 1 &&
3635 (termination_action
|| IN_SET(a
, ACTION_KEXEC
, ACTION_EXIT
)))
3636 r
= trivial_method(argc
, argv
, userdata
);
3638 /* First try logind, to allow authentication with polkit */
3645 ACTION_HYBRID_SLEEP
,
3646 ACTION_SUSPEND_THEN_HIBERNATE
)) {
3648 r
= logind_reboot(a
);
3651 if (IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
3652 /* requested operation is not supported or already in progress */
3655 /* On all other errors, try low-level operation. In order to minimize the difference between
3656 * operation with and without logind, we explicitly enable non-blocking mode for this, as
3657 * logind's shutdown operations are always non-blocking. */
3659 arg_no_block
= true;
3661 } else if (IN_SET(a
, ACTION_EXIT
, ACTION_KEXEC
))
3662 /* Since exit/kexec are so close in behaviour to power-off/reboot, let's also make them
3663 * asynchronous, in order to not confuse the user needlessly with unexpected behaviour. */
3664 arg_no_block
= true;
3666 r
= start_unit(argc
, argv
, userdata
);
3669 if (termination_action
&& arg_force
< 2 &&
3670 IN_SET(r
, -ENOENT
, -ETIMEDOUT
))
3671 log_notice("It is possible to perform action directly, see discussion of --force --force in man:systemctl(1).");
3676 static int start_system_special(int argc
, char *argv
[], void *userdata
) {
3677 /* Like start_special above, but raises an error when running in user mode */
3679 if (arg_scope
!= UNIT_FILE_SYSTEM
) {
3680 log_error("Bad action for %s mode.",
3681 arg_scope
== UNIT_FILE_GLOBAL
? "--global" : "--user");
3685 return start_special(argc
, argv
, userdata
);
3688 static int check_unit_generic(int code
, const UnitActiveState good_states
[], int nb_states
, char **args
) {
3689 _cleanup_strv_free_
char **names
= NULL
;
3690 UnitActiveState active_state
;
3696 r
= acquire_bus(BUS_MANAGER
, &bus
);
3700 r
= expand_names(bus
, args
, NULL
, &names
);
3702 return log_error_errno(r
, "Failed to expand names: %m");
3704 STRV_FOREACH(name
, names
) {
3705 r
= get_state_one_unit(bus
, *name
, &active_state
);
3710 puts(unit_active_state_to_string(active_state
));
3712 for (i
= 0; i
< nb_states
; ++i
)
3713 if (good_states
[i
] == active_state
)
3717 /* use the given return code for the case that we won't find
3718 * any unit which matches the list */
3719 return found
? 0 : code
;
3722 static int check_unit_active(int argc
, char *argv
[], void *userdata
) {
3723 const UnitActiveState states
[] = { UNIT_ACTIVE
, UNIT_RELOADING
};
3724 /* According to LSB: 3, "program is not running" */
3725 return check_unit_generic(EXIT_PROGRAM_NOT_RUNNING
, states
, ELEMENTSOF(states
), strv_skip(argv
, 1));
3728 static int check_unit_failed(int argc
, char *argv
[], void *userdata
) {
3729 const UnitActiveState states
[] = { UNIT_FAILED
};
3730 return check_unit_generic(EXIT_PROGRAM_DEAD_AND_PID_EXISTS
, states
, ELEMENTSOF(states
), strv_skip(argv
, 1));
3733 static int kill_unit(int argc
, char *argv
[], void *userdata
) {
3734 _cleanup_strv_free_
char **names
= NULL
;
3735 char *kill_who
= NULL
, **name
;
3739 r
= acquire_bus(BUS_MANAGER
, &bus
);
3743 polkit_agent_open_maybe();
3746 arg_kill_who
= "all";
3748 /* --fail was specified */
3749 if (streq(arg_job_mode
, "fail"))
3750 kill_who
= strjoina(arg_kill_who
, "-fail");
3752 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
3754 return log_error_errno(r
, "Failed to expand names: %m");
3756 STRV_FOREACH(name
, names
) {
3757 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3759 q
= sd_bus_call_method(
3761 "org.freedesktop.systemd1",
3762 "/org/freedesktop/systemd1",
3763 "org.freedesktop.systemd1.Manager",
3767 "ssi", *name
, kill_who
? kill_who
: arg_kill_who
, arg_signal
);
3769 log_error_errno(q
, "Failed to kill unit %s: %s", *name
, bus_error_message(&error
, q
));
3778 typedef struct ExecStatusInfo
{
3786 usec_t start_timestamp
;
3787 usec_t exit_timestamp
;
3792 LIST_FIELDS(struct ExecStatusInfo
, exec
);
3795 static void exec_status_info_free(ExecStatusInfo
*i
) {
3804 static int exec_status_info_deserialize(sd_bus_message
*m
, ExecStatusInfo
*i
) {
3805 uint64_t start_timestamp
, exit_timestamp
, start_timestamp_monotonic
, exit_timestamp_monotonic
;
3808 int32_t code
, status
;
3814 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_STRUCT
, "sasbttttuii");
3816 return bus_log_parse_error(r
);
3820 r
= sd_bus_message_read(m
, "s", &path
);
3822 return bus_log_parse_error(r
);
3824 i
->path
= strdup(path
);
3828 r
= sd_bus_message_read_strv(m
, &i
->argv
);
3830 return bus_log_parse_error(r
);
3832 r
= sd_bus_message_read(m
,
3835 &start_timestamp
, &start_timestamp_monotonic
,
3836 &exit_timestamp
, &exit_timestamp_monotonic
,
3840 return bus_log_parse_error(r
);
3843 i
->start_timestamp
= (usec_t
) start_timestamp
;
3844 i
->exit_timestamp
= (usec_t
) exit_timestamp
;
3845 i
->pid
= (pid_t
) pid
;
3849 r
= sd_bus_message_exit_container(m
);
3851 return bus_log_parse_error(r
);
3856 typedef struct UnitCondition
{
3863 LIST_FIELDS(struct UnitCondition
, conditions
);
3866 static void unit_condition_free(UnitCondition
*c
) {
3875 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitCondition
*, unit_condition_free
);
3877 typedef struct UnitStatusInfo
{
3879 const char *load_state
;
3880 const char *active_state
;
3881 const char *sub_state
;
3882 const char *unit_file_state
;
3883 const char *unit_file_preset
;
3885 const char *description
;
3886 const char *following
;
3888 char **documentation
;
3890 const char *fragment_path
;
3891 const char *source_path
;
3892 const char *control_group
;
3894 char **dropin_paths
;
3896 const char *load_error
;
3899 usec_t inactive_exit_timestamp
;
3900 usec_t inactive_exit_timestamp_monotonic
;
3901 usec_t active_enter_timestamp
;
3902 usec_t active_exit_timestamp
;
3903 usec_t inactive_enter_timestamp
;
3905 bool need_daemon_reload
;
3911 const char *status_text
;
3912 const char *pid_file
;
3916 usec_t start_timestamp
;
3917 usec_t exit_timestamp
;
3919 int exit_code
, exit_status
;
3921 usec_t condition_timestamp
;
3922 bool condition_result
;
3923 LIST_HEAD(UnitCondition
, conditions
);
3925 usec_t assert_timestamp
;
3927 bool failed_assert_trigger
;
3928 bool failed_assert_negate
;
3929 const char *failed_assert
;
3930 const char *failed_assert_parameter
;
3931 usec_t next_elapse_real
;
3932 usec_t next_elapse_monotonic
;
3935 unsigned n_accepted
;
3936 unsigned n_connections
;
3939 /* Pairs of type, path */
3943 const char *sysfs_path
;
3945 /* Mount, Automount */
3952 uint64_t memory_current
;
3953 uint64_t memory_low
;
3954 uint64_t memory_high
;
3955 uint64_t memory_max
;
3956 uint64_t memory_swap_max
;
3957 uint64_t memory_limit
;
3958 uint64_t cpu_usage_nsec
;
3959 uint64_t tasks_current
;
3962 uint64_t ip_ingress_bytes
;
3963 uint64_t ip_egress_bytes
;
3965 LIST_HEAD(ExecStatusInfo
, exec
);
3968 static void unit_status_info_free(UnitStatusInfo
*info
) {
3972 strv_free(info
->documentation
);
3973 strv_free(info
->dropin_paths
);
3974 strv_free(info
->listen
);
3976 while ((c
= info
->conditions
)) {
3977 LIST_REMOVE(conditions
, info
->conditions
, c
);
3978 unit_condition_free(c
);
3981 while ((p
= info
->exec
)) {
3982 LIST_REMOVE(exec
, info
->exec
, p
);
3983 exec_status_info_free(p
);
3987 static void print_status_info(
3993 const char *active_on
, *active_off
, *on
, *off
, *ss
;
3995 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], *s1
;
3996 char since2
[FORMAT_TIMESTAMP_MAX
], *s2
;
4003 /* This shows pretty information about a unit. See
4004 * print_property() for a low-level property printer */
4006 if (streq_ptr(i
->active_state
, "failed")) {
4007 active_on
= ansi_highlight_red();
4008 active_off
= ansi_normal();
4009 } else if (STRPTR_IN_SET(i
->active_state
, "active", "reloading")) {
4010 active_on
= ansi_highlight_green();
4011 active_off
= ansi_normal();
4013 active_on
= active_off
= "";
4015 printf("%s%s%s %s", active_on
, special_glyph(BLACK_CIRCLE
), active_off
, strna(i
->id
));
4017 if (i
->description
&& !streq_ptr(i
->id
, i
->description
))
4018 printf(" - %s", i
->description
);
4023 printf(" Follow: unit currently follows state of %s\n", i
->following
);
4025 if (streq_ptr(i
->load_state
, "error")) {
4026 on
= ansi_highlight_red();
4027 off
= ansi_normal();
4031 path
= i
->source_path
? i
->source_path
: i
->fragment_path
;
4033 if (i
->load_error
!= 0)
4034 printf(" Loaded: %s%s%s (Reason: %s)\n",
4035 on
, strna(i
->load_state
), off
, i
->load_error
);
4036 else if (path
&& !isempty(i
->unit_file_state
) && !isempty(i
->unit_file_preset
) &&
4037 !STR_IN_SET(i
->unit_file_state
, "generated", "transient"))
4038 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
4039 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
, i
->unit_file_preset
);
4040 else if (path
&& !isempty(i
->unit_file_state
))
4041 printf(" Loaded: %s%s%s (%s; %s)\n",
4042 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
);
4044 printf(" Loaded: %s%s%s (%s)\n",
4045 on
, strna(i
->load_state
), off
, path
);
4047 printf(" Loaded: %s%s%s\n",
4048 on
, strna(i
->load_state
), off
);
4051 printf("Transient: yes\n");
4053 if (!strv_isempty(i
->dropin_paths
)) {
4054 _cleanup_free_
char *dir
= NULL
;
4058 STRV_FOREACH(dropin
, i
->dropin_paths
) {
4059 if (! dir
|| last
) {
4060 printf(dir
? " " : " Drop-In: ");
4064 dir
= dirname_malloc(*dropin
);
4070 printf("%s\n %s", dir
,
4071 special_glyph(TREE_RIGHT
));
4074 last
= ! (*(dropin
+ 1) && startswith(*(dropin
+ 1), dir
));
4076 printf("%s%s", basename(*dropin
), last
? "\n" : ", ");
4080 ss
= streq_ptr(i
->active_state
, i
->sub_state
) ? NULL
: i
->sub_state
;
4082 printf(" Active: %s%s (%s)%s",
4083 active_on
, strna(i
->active_state
), ss
, active_off
);
4085 printf(" Active: %s%s%s",
4086 active_on
, strna(i
->active_state
), active_off
);
4088 if (!isempty(i
->result
) && !streq(i
->result
, "success"))
4089 printf(" (Result: %s)", i
->result
);
4091 timestamp
= STRPTR_IN_SET(i
->active_state
, "active", "reloading") ? i
->active_enter_timestamp
:
4092 STRPTR_IN_SET(i
->active_state
, "inactive", "failed") ? i
->inactive_enter_timestamp
:
4093 STRPTR_IN_SET(i
->active_state
, "activating") ? i
->inactive_exit_timestamp
:
4094 i
->active_exit_timestamp
;
4096 s1
= format_timestamp_relative(since1
, sizeof(since1
), timestamp
);
4097 s2
= format_timestamp(since2
, sizeof(since2
), timestamp
);
4100 printf(" since %s; %s\n", s2
, s1
);
4102 printf(" since %s\n", s2
);
4106 if (endswith(i
->id
, ".timer")) {
4107 char tstamp1
[FORMAT_TIMESTAMP_RELATIVE_MAX
],
4108 tstamp2
[FORMAT_TIMESTAMP_MAX
];
4109 char *next_rel_time
, *next_time
;
4110 dual_timestamp nw
, next
= {i
->next_elapse_real
,
4111 i
->next_elapse_monotonic
};
4114 printf(" Trigger: ");
4116 dual_timestamp_get(&nw
);
4117 next_elapse
= calc_next_elapse(&nw
, &next
);
4118 next_rel_time
= format_timestamp_relative(tstamp1
,
4121 next_time
= format_timestamp(tstamp2
,
4125 if (next_time
&& next_rel_time
)
4126 printf("%s; %s\n", next_time
, next_rel_time
);
4131 if (!i
->condition_result
&& i
->condition_timestamp
> 0) {
4135 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->condition_timestamp
);
4136 s2
= format_timestamp(since2
, sizeof(since2
), i
->condition_timestamp
);
4138 printf("Condition: start %scondition failed%s at %s%s%s\n",
4139 ansi_highlight_yellow(), ansi_normal(),
4140 s2
, s1
? "; " : "", strempty(s1
));
4142 LIST_FOREACH(conditions
, c
, i
->conditions
)
4143 if (c
->tristate
< 0)
4146 LIST_FOREACH(conditions
, c
, i
->conditions
)
4147 if (c
->tristate
< 0)
4148 printf(" %s %s=%s%s%s was not met\n",
4149 --n
? special_glyph(TREE_BRANCH
) : special_glyph(TREE_RIGHT
),
4151 c
->trigger
? "|" : "",
4152 c
->negate
? "!" : "",
4156 if (!i
->assert_result
&& i
->assert_timestamp
> 0) {
4157 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->assert_timestamp
);
4158 s2
= format_timestamp(since2
, sizeof(since2
), i
->assert_timestamp
);
4160 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
4161 ansi_highlight_red(), ansi_normal(),
4162 s2
, s1
? "; " : "", strempty(s1
));
4163 if (i
->failed_assert_trigger
)
4164 printf(" none of the trigger assertions were met\n");
4165 else if (i
->failed_assert
)
4166 printf(" %s=%s%s was not met\n",
4168 i
->failed_assert_negate
? "!" : "",
4169 i
->failed_assert_parameter
);
4173 printf(" Device: %s\n", i
->sysfs_path
);
4175 printf(" Where: %s\n", i
->where
);
4177 printf(" What: %s\n", i
->what
);
4179 STRV_FOREACH(t
, i
->documentation
)
4180 printf(" %*s %s\n", 9, t
== i
->documentation
? "Docs:" : "", *t
);
4182 STRV_FOREACH_PAIR(t
, t2
, i
->listen
)
4183 printf(" %*s %s (%s)\n", 9, t
== i
->listen
? "Listen:" : "", *t2
, *t
);
4186 printf(" Accepted: %u; Connected: %u\n", i
->n_accepted
, i
->n_connections
);
4188 LIST_FOREACH(exec
, p
, i
->exec
) {
4189 _cleanup_free_
char *argv
= NULL
;
4192 /* Only show exited processes here */
4196 argv
= strv_join(p
->argv
, " ");
4197 printf(" Process: "PID_FMT
" %s=%s ", p
->pid
, p
->name
, strna(argv
));
4199 good
= is_clean_exit(p
->code
, p
->status
, EXIT_CLEAN_DAEMON
, NULL
);
4201 on
= ansi_highlight_red();
4202 off
= ansi_normal();
4206 printf("%s(code=%s, ", on
, sigchld_code_to_string(p
->code
));
4208 if (p
->code
== CLD_EXITED
) {
4211 printf("status=%i", p
->status
);
4213 c
= exit_status_to_string(p
->status
, EXIT_STATUS_SYSTEMD
);
4218 printf("signal=%s", signal_to_string(p
->status
));
4220 printf(")%s\n", off
);
4222 if (i
->main_pid
== p
->pid
&&
4223 i
->start_timestamp
== p
->start_timestamp
&&
4224 i
->exit_timestamp
== p
->start_timestamp
)
4225 /* Let's not show this twice */
4228 if (p
->pid
== i
->control_pid
)
4232 if (i
->main_pid
> 0 || i
->control_pid
> 0) {
4233 if (i
->main_pid
> 0) {
4234 printf(" Main PID: "PID_FMT
, i
->main_pid
);
4238 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
4239 _cleanup_free_
char *comm
= NULL
;
4241 (void) get_process_comm(i
->main_pid
, &comm
);
4243 printf(" (%s)", comm
);
4246 } else if (i
->exit_code
> 0) {
4247 printf(" (code=%s, ", sigchld_code_to_string(i
->exit_code
));
4249 if (i
->exit_code
== CLD_EXITED
) {
4252 printf("status=%i", i
->exit_status
);
4254 c
= exit_status_to_string(i
->exit_status
, EXIT_STATUS_SYSTEMD
);
4259 printf("signal=%s", signal_to_string(i
->exit_status
));
4264 if (i
->control_pid
> 0) {
4265 _cleanup_free_
char *c
= NULL
;
4267 if (i
->main_pid
> 0)
4268 fputs("; Control PID: ", stdout
);
4270 fputs("Cntrl PID: ", stdout
); /* if first in column, abbreviated so it fits alignment */
4272 printf(PID_FMT
, i
->control_pid
);
4274 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
4275 (void) get_process_comm(i
->control_pid
, &c
);
4285 printf(" Status: \"%s\"\n", i
->status_text
);
4286 if (i
->status_errno
> 0)
4287 printf(" Error: %i (%s)\n", i
->status_errno
, strerror(i
->status_errno
));
4289 if (i
->ip_ingress_bytes
!= (uint64_t) -1 && i
->ip_egress_bytes
!= (uint64_t) -1) {
4290 char buf_in
[FORMAT_BYTES_MAX
], buf_out
[FORMAT_BYTES_MAX
];
4292 printf(" IP: %s in, %s out\n",
4293 format_bytes(buf_in
, sizeof(buf_in
), i
->ip_ingress_bytes
),
4294 format_bytes(buf_out
, sizeof(buf_out
), i
->ip_egress_bytes
));
4297 if (i
->tasks_current
!= (uint64_t) -1) {
4298 printf(" Tasks: %" PRIu64
, i
->tasks_current
);
4300 if (i
->tasks_max
!= (uint64_t) -1)
4301 printf(" (limit: %" PRIu64
")\n", i
->tasks_max
);
4306 if (i
->memory_current
!= (uint64_t) -1) {
4307 char buf
[FORMAT_BYTES_MAX
];
4309 printf(" Memory: %s", format_bytes(buf
, sizeof(buf
), i
->memory_current
));
4311 if (i
->memory_low
> 0 || i
->memory_high
!= CGROUP_LIMIT_MAX
||
4312 i
->memory_max
!= CGROUP_LIMIT_MAX
|| i
->memory_swap_max
!= CGROUP_LIMIT_MAX
||
4313 i
->memory_limit
!= CGROUP_LIMIT_MAX
) {
4314 const char *prefix
= "";
4317 if (i
->memory_low
> 0) {
4318 printf("%slow: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_low
));
4321 if (i
->memory_high
!= CGROUP_LIMIT_MAX
) {
4322 printf("%shigh: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_high
));
4325 if (i
->memory_max
!= CGROUP_LIMIT_MAX
) {
4326 printf("%smax: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_max
));
4329 if (i
->memory_swap_max
!= CGROUP_LIMIT_MAX
) {
4330 printf("%sswap max: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_swap_max
));
4333 if (i
->memory_limit
!= CGROUP_LIMIT_MAX
) {
4334 printf("%slimit: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_limit
));
4342 if (i
->cpu_usage_nsec
!= (uint64_t) -1) {
4343 char buf
[FORMAT_TIMESPAN_MAX
];
4344 printf(" CPU: %s\n", format_timespan(buf
, sizeof(buf
), i
->cpu_usage_nsec
/ NSEC_PER_USEC
, USEC_PER_MSEC
));
4347 if (i
->control_group
) {
4348 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
4349 static const char prefix
[] = " ";
4352 printf(" CGroup: %s\n", i
->control_group
);
4355 if (c
> sizeof(prefix
) - 1)
4356 c
-= sizeof(prefix
) - 1;
4360 r
= unit_show_processes(bus
, i
->id
, i
->control_group
, prefix
, c
, get_output_flags(), &error
);
4365 /* Fallback for older systemd versions where the GetUnitProcesses() call is not yet available */
4367 if (i
->main_pid
> 0)
4368 extra
[k
++] = i
->main_pid
;
4370 if (i
->control_pid
> 0)
4371 extra
[k
++] = i
->control_pid
;
4373 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, prefix
, c
, extra
, k
, get_output_flags());
4375 log_warning_errno(r
, "Failed to dump process list, ignoring: %s", bus_error_message(&error
, r
));
4378 if (i
->id
&& arg_transport
== BUS_TRANSPORT_LOCAL
)
4379 show_journal_by_unit(
4384 i
->inactive_exit_timestamp_monotonic
,
4387 get_output_flags() | OUTPUT_BEGIN_NEWLINE
,
4388 SD_JOURNAL_LOCAL_ONLY
,
4389 arg_scope
== UNIT_FILE_SYSTEM
,
4392 if (i
->need_daemon_reload
)
4393 warn_unit_file_changed(i
->id
);
4396 static void show_unit_help(UnitStatusInfo
*i
) {
4401 if (!i
->documentation
) {
4402 log_info("Documentation for %s not known.", i
->id
);
4406 STRV_FOREACH(p
, i
->documentation
)
4407 if (startswith(*p
, "man:"))
4408 show_man_page(*p
+ 4, false);
4410 log_info("Can't show: %s", *p
);
4413 static int map_main_pid(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
4414 UnitStatusInfo
*i
= userdata
;
4418 r
= sd_bus_message_read(m
, "u", &u
);
4422 i
->main_pid
= (pid_t
) u
;
4428 static int map_load_error(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
4429 const char *n
, *message
;
4430 const char **p
= userdata
;
4433 r
= sd_bus_message_read(m
, "(ss)", &n
, &message
);
4437 if (!isempty(message
))
4443 static int map_listen(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
4444 const char *type
, *path
;
4445 char ***p
= userdata
;
4448 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4452 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0) {
4454 r
= strv_extend(p
, type
);
4458 r
= strv_extend(p
, path
);
4465 r
= sd_bus_message_exit_container(m
);
4472 static int map_conditions(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
4473 UnitStatusInfo
*i
= userdata
;
4474 const char *cond
, *param
;
4475 int trigger
, negate
;
4479 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
4483 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
4484 _cleanup_(unit_condition_freep
) UnitCondition
*c
= NULL
;
4486 c
= new0(UnitCondition
, 1);
4490 c
->name
= strdup(cond
);
4491 c
->param
= strdup(param
);
4492 if (!c
->name
|| !c
->param
)
4495 c
->trigger
= trigger
;
4497 c
->tristate
= state
;
4499 LIST_PREPEND(conditions
, i
->conditions
, c
);
4505 r
= sd_bus_message_exit_container(m
);
4512 static int map_asserts(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
4513 UnitStatusInfo
*i
= userdata
;
4514 const char *cond
, *param
;
4515 int trigger
, negate
;
4519 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
4523 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
4524 if (state
< 0 && (!trigger
|| !i
->failed_assert
)) {
4525 i
->failed_assert
= cond
;
4526 i
->failed_assert_trigger
= trigger
;
4527 i
->failed_assert_negate
= negate
;
4528 i
->failed_assert_parameter
= param
;
4534 r
= sd_bus_message_exit_container(m
);
4541 static int map_exec(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
4542 _cleanup_free_ ExecStatusInfo
*info
= NULL
;
4543 UnitStatusInfo
*i
= userdata
;
4546 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4550 info
= new0(ExecStatusInfo
, 1);
4554 while ((r
= exec_status_info_deserialize(m
, info
)) > 0) {
4556 info
->name
= strdup(member
);
4560 LIST_PREPEND(exec
, i
->exec
, info
);
4562 info
= new0(ExecStatusInfo
, 1);
4569 r
= sd_bus_message_exit_container(m
);
4576 #define print_prop(name, fmt, ...) \
4579 printf(fmt "\n", __VA_ARGS__); \
4581 printf("%s=" fmt "\n", name, __VA_ARGS__); \
4584 static int print_property(const char *name
, sd_bus_message
*m
, bool value
, bool all
) {
4586 const char *contents
;
4592 /* This is a low-level property printer, see
4593 * print_status_info() for the nicer output */
4595 r
= sd_bus_message_peek_type(m
, &bus_type
, &contents
);
4601 case SD_BUS_TYPE_STRUCT
:
4603 if (contents
[0] == SD_BUS_TYPE_UINT32
&& streq(name
, "Job")) {
4606 r
= sd_bus_message_read(m
, "(uo)", &u
, NULL
);
4608 return bus_log_parse_error(r
);
4611 print_prop(name
, "%"PRIu32
, u
);
4613 print_prop(name
, "%s", "");
4617 } else if (contents
[0] == SD_BUS_TYPE_STRING
&& streq(name
, "Unit")) {
4620 r
= sd_bus_message_read(m
, "(so)", &s
, NULL
);
4622 return bus_log_parse_error(r
);
4624 if (all
|| !isempty(s
))
4625 print_prop(name
, "%s", s
);
4629 } else if (contents
[0] == SD_BUS_TYPE_STRING
&& streq(name
, "LoadError")) {
4630 const char *a
= NULL
, *b
= NULL
;
4632 r
= sd_bus_message_read(m
, "(ss)", &a
, &b
);
4634 return bus_log_parse_error(r
);
4636 if (all
|| !isempty(a
) || !isempty(b
))
4637 print_prop(name
, "%s \"%s\"", strempty(a
), strempty(b
));
4640 } else if (streq_ptr(name
, "SystemCallFilter")) {
4641 _cleanup_strv_free_
char **l
= NULL
;
4644 r
= sd_bus_message_enter_container(m
, 'r', "bas");
4646 return bus_log_parse_error(r
);
4648 r
= sd_bus_message_read(m
, "b", &whitelist
);
4650 return bus_log_parse_error(r
);
4652 r
= sd_bus_message_read_strv(m
, &l
);
4654 return bus_log_parse_error(r
);
4656 r
= sd_bus_message_exit_container(m
);
4658 return bus_log_parse_error(r
);
4660 if (all
|| whitelist
|| !strv_isempty(l
)) {
4665 fputs(name
, stdout
);
4672 STRV_FOREACH(i
, l
) {
4680 fputc('\n', stdout
);
4688 case SD_BUS_TYPE_ARRAY
:
4690 if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "EnvironmentFiles")) {
4694 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sb)");
4696 return bus_log_parse_error(r
);
4698 while ((r
= sd_bus_message_read(m
, "(sb)", &path
, &ignore
)) > 0)
4699 print_prop(name
, "%s (ignore_errors=%s)", path
, yes_no(ignore
));
4702 return bus_log_parse_error(r
);
4704 r
= sd_bus_message_exit_container(m
);
4706 return bus_log_parse_error(r
);
4710 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Paths")) {
4711 const char *type
, *path
;
4713 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4715 return bus_log_parse_error(r
);
4717 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4718 print_prop(name
, "%s (%s)", path
, type
);
4720 return bus_log_parse_error(r
);
4722 r
= sd_bus_message_exit_container(m
);
4724 return bus_log_parse_error(r
);
4728 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
4729 const char *type
, *path
;
4731 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4733 return bus_log_parse_error(r
);
4735 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4736 print_prop(name
, "%s (%s)", path
, type
);
4738 return bus_log_parse_error(r
);
4740 r
= sd_bus_message_exit_container(m
);
4742 return bus_log_parse_error(r
);
4746 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "TimersMonotonic")) {
4748 uint64_t v
, next_elapse
;
4750 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(stt)");
4752 return bus_log_parse_error(r
);
4754 while ((r
= sd_bus_message_read(m
, "(stt)", &base
, &v
, &next_elapse
)) > 0) {
4755 char timespan1
[FORMAT_TIMESPAN_MAX
], timespan2
[FORMAT_TIMESPAN_MAX
];
4757 print_prop(name
, "{ %s=%s ; next_elapse=%s }", base
,
4758 format_timespan(timespan1
, sizeof(timespan1
), v
, 0),
4759 format_timespan(timespan2
, sizeof(timespan2
), next_elapse
, 0));
4762 return bus_log_parse_error(r
);
4764 r
= sd_bus_message_exit_container(m
);
4766 return bus_log_parse_error(r
);
4770 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "TimersCalendar")) {
4771 const char *base
, *spec
;
4772 uint64_t next_elapse
;
4774 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sst)");
4776 return bus_log_parse_error(r
);
4778 while ((r
= sd_bus_message_read(m
, "(sst)", &base
, &spec
, &next_elapse
)) > 0) {
4779 char timestamp
[FORMAT_TIMESTAMP_MAX
];
4781 print_prop(name
, "{ %s=%s ; next_elapse=%s }", base
, spec
,
4782 format_timestamp(timestamp
, sizeof(timestamp
), next_elapse
));
4785 return bus_log_parse_error(r
);
4787 r
= sd_bus_message_exit_container(m
);
4789 return bus_log_parse_error(r
);
4793 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
4794 ExecStatusInfo info
= {};
4796 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4798 return bus_log_parse_error(r
);
4800 while ((r
= exec_status_info_deserialize(m
, &info
)) > 0) {
4801 char timestamp1
[FORMAT_TIMESTAMP_MAX
], timestamp2
[FORMAT_TIMESTAMP_MAX
];
4802 _cleanup_free_
char *tt
;
4804 tt
= strv_join(info
.argv
, " ");
4807 "{ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT
" ; code=%s ; status=%i%s%s }",
4810 yes_no(info
.ignore
),
4811 strna(format_timestamp(timestamp1
, sizeof(timestamp1
), info
.start_timestamp
)),
4812 strna(format_timestamp(timestamp2
, sizeof(timestamp2
), info
.exit_timestamp
)),
4814 sigchld_code_to_string(info
.code
),
4816 info
.code
== CLD_EXITED
? "" : "/",
4817 strempty(info
.code
== CLD_EXITED
? NULL
: signal_to_string(info
.status
)));
4820 strv_free(info
.argv
);
4824 r
= sd_bus_message_exit_container(m
);
4826 return bus_log_parse_error(r
);
4830 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "DeviceAllow")) {
4831 const char *path
, *rwm
;
4833 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4835 return bus_log_parse_error(r
);
4837 while ((r
= sd_bus_message_read(m
, "(ss)", &path
, &rwm
)) > 0)
4838 print_prop(name
, "%s %s", strna(path
), strna(rwm
));
4840 return bus_log_parse_error(r
);
4842 r
= sd_bus_message_exit_container(m
);
4844 return bus_log_parse_error(r
);
4848 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&&
4849 STR_IN_SET(name
, "IODeviceWeight", "BlockIODeviceWeight")) {
4853 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4855 return bus_log_parse_error(r
);
4857 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &weight
)) > 0)
4858 print_prop(name
, "%s %"PRIu64
, strna(path
), weight
);
4860 return bus_log_parse_error(r
);
4862 r
= sd_bus_message_exit_container(m
);
4864 return bus_log_parse_error(r
);
4868 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&&
4869 (cgroup_io_limit_type_from_string(name
) >= 0 ||
4870 STR_IN_SET(name
, "BlockIOReadBandwidth", "BlockIOWriteBandwidth"))) {
4874 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4876 return bus_log_parse_error(r
);
4878 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &bandwidth
)) > 0)
4879 print_prop(name
, "%s %"PRIu64
, strna(path
), bandwidth
);
4881 return bus_log_parse_error(r
);
4883 r
= sd_bus_message_exit_container(m
);
4885 return bus_log_parse_error(r
);
4889 } else if (contents
[0] == SD_BUS_TYPE_BYTE
&& streq(name
, "StandardInputData")) {
4890 _cleanup_free_
char *h
= NULL
;
4895 r
= sd_bus_message_read_array(m
, 'y', &p
, &sz
);
4897 return bus_log_parse_error(r
);
4899 n
= base64mem(p
, sz
, &h
);
4903 print_prop(name
, "%s", h
);
4914 typedef enum SystemctlShowMode
{
4915 SYSTEMCTL_SHOW_PROPERTIES
,
4916 SYSTEMCTL_SHOW_STATUS
,
4917 SYSTEMCTL_SHOW_HELP
,
4918 _SYSTEMCTL_SHOW_MODE_MAX
,
4919 _SYSTEMCTL_SHOW_MODE_INVALID
= -1,
4920 } SystemctlShowMode
;
4922 static const char* const systemctl_show_mode_table
[] = {
4923 [SYSTEMCTL_SHOW_PROPERTIES
] = "show",
4924 [SYSTEMCTL_SHOW_STATUS
] = "status",
4925 [SYSTEMCTL_SHOW_HELP
] = "help",
4928 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(systemctl_show_mode
, SystemctlShowMode
);
4930 static int show_one(
4934 SystemctlShowMode show_mode
,
4938 static const struct bus_properties_map property_map
[] = {
4939 { "LoadState", "s", NULL
, offsetof(UnitStatusInfo
, load_state
) },
4940 { "ActiveState", "s", NULL
, offsetof(UnitStatusInfo
, active_state
) },
4941 { "Documentation", "as", NULL
, offsetof(UnitStatusInfo
, documentation
) },
4944 { "Id", "s", NULL
, offsetof(UnitStatusInfo
, id
) },
4945 { "LoadState", "s", NULL
, offsetof(UnitStatusInfo
, load_state
) },
4946 { "ActiveState", "s", NULL
, offsetof(UnitStatusInfo
, active_state
) },
4947 { "SubState", "s", NULL
, offsetof(UnitStatusInfo
, sub_state
) },
4948 { "UnitFileState", "s", NULL
, offsetof(UnitStatusInfo
, unit_file_state
) },
4949 { "UnitFilePreset", "s", NULL
, offsetof(UnitStatusInfo
, unit_file_preset
) },
4950 { "Description", "s", NULL
, offsetof(UnitStatusInfo
, description
) },
4951 { "Following", "s", NULL
, offsetof(UnitStatusInfo
, following
) },
4952 { "Documentation", "as", NULL
, offsetof(UnitStatusInfo
, documentation
) },
4953 { "FragmentPath", "s", NULL
, offsetof(UnitStatusInfo
, fragment_path
) },
4954 { "SourcePath", "s", NULL
, offsetof(UnitStatusInfo
, source_path
) },
4955 { "ControlGroup", "s", NULL
, offsetof(UnitStatusInfo
, control_group
) },
4956 { "DropInPaths", "as", NULL
, offsetof(UnitStatusInfo
, dropin_paths
) },
4957 { "LoadError", "(ss)", map_load_error
, offsetof(UnitStatusInfo
, load_error
) },
4958 { "Result", "s", NULL
, offsetof(UnitStatusInfo
, result
) },
4959 { "InactiveExitTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, inactive_exit_timestamp
) },
4960 { "InactiveExitTimestampMonotonic", "t", NULL
, offsetof(UnitStatusInfo
, inactive_exit_timestamp_monotonic
) },
4961 { "ActiveEnterTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, active_enter_timestamp
) },
4962 { "ActiveExitTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, active_exit_timestamp
) },
4963 { "InactiveEnterTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, inactive_enter_timestamp
) },
4964 { "NeedDaemonReload", "b", NULL
, offsetof(UnitStatusInfo
, need_daemon_reload
) },
4965 { "Transient", "b", NULL
, offsetof(UnitStatusInfo
, transient
) },
4966 { "ExecMainPID", "u", NULL
, offsetof(UnitStatusInfo
, main_pid
) },
4967 { "MainPID", "u", map_main_pid
, 0 },
4968 { "ControlPID", "u", NULL
, offsetof(UnitStatusInfo
, control_pid
) },
4969 { "StatusText", "s", NULL
, offsetof(UnitStatusInfo
, status_text
) },
4970 { "PIDFile", "s", NULL
, offsetof(UnitStatusInfo
, pid_file
) },
4971 { "StatusErrno", "i", NULL
, offsetof(UnitStatusInfo
, status_errno
) },
4972 { "ExecMainStartTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, start_timestamp
) },
4973 { "ExecMainExitTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, exit_timestamp
) },
4974 { "ExecMainCode", "i", NULL
, offsetof(UnitStatusInfo
, exit_code
) },
4975 { "ExecMainStatus", "i", NULL
, offsetof(UnitStatusInfo
, exit_status
) },
4976 { "ConditionTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, condition_timestamp
) },
4977 { "ConditionResult", "b", NULL
, offsetof(UnitStatusInfo
, condition_result
) },
4978 { "Conditions", "a(sbbsi)", map_conditions
, 0 },
4979 { "AssertTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, assert_timestamp
) },
4980 { "AssertResult", "b", NULL
, offsetof(UnitStatusInfo
, assert_result
) },
4981 { "Asserts", "a(sbbsi)", map_asserts
, 0 },
4982 { "NextElapseUSecRealtime", "t", NULL
, offsetof(UnitStatusInfo
, next_elapse_real
) },
4983 { "NextElapseUSecMonotonic", "t", NULL
, offsetof(UnitStatusInfo
, next_elapse_monotonic
) },
4984 { "NAccepted", "u", NULL
, offsetof(UnitStatusInfo
, n_accepted
) },
4985 { "NConnections", "u", NULL
, offsetof(UnitStatusInfo
, n_connections
) },
4986 { "Accept", "b", NULL
, offsetof(UnitStatusInfo
, accept
) },
4987 { "Listen", "a(ss)", map_listen
, offsetof(UnitStatusInfo
, listen
) },
4988 { "SysFSPath", "s", NULL
, offsetof(UnitStatusInfo
, sysfs_path
) },
4989 { "Where", "s", NULL
, offsetof(UnitStatusInfo
, where
) },
4990 { "What", "s", NULL
, offsetof(UnitStatusInfo
, what
) },
4991 { "MemoryCurrent", "t", NULL
, offsetof(UnitStatusInfo
, memory_current
) },
4992 { "MemoryLow", "t", NULL
, offsetof(UnitStatusInfo
, memory_low
) },
4993 { "MemoryHigh", "t", NULL
, offsetof(UnitStatusInfo
, memory_high
) },
4994 { "MemoryMax", "t", NULL
, offsetof(UnitStatusInfo
, memory_max
) },
4995 { "MemorySwapMax", "t", NULL
, offsetof(UnitStatusInfo
, memory_swap_max
) },
4996 { "MemoryLimit", "t", NULL
, offsetof(UnitStatusInfo
, memory_limit
) },
4997 { "CPUUsageNSec", "t", NULL
, offsetof(UnitStatusInfo
, cpu_usage_nsec
) },
4998 { "TasksCurrent", "t", NULL
, offsetof(UnitStatusInfo
, tasks_current
) },
4999 { "TasksMax", "t", NULL
, offsetof(UnitStatusInfo
, tasks_max
) },
5000 { "IPIngressBytes", "t", NULL
, offsetof(UnitStatusInfo
, ip_ingress_bytes
) },
5001 { "IPEgressBytes", "t", NULL
, offsetof(UnitStatusInfo
, ip_egress_bytes
) },
5002 { "ExecStartPre", "a(sasbttttuii)", map_exec
, 0 },
5003 { "ExecStart", "a(sasbttttuii)", map_exec
, 0 },
5004 { "ExecStartPost", "a(sasbttttuii)", map_exec
, 0 },
5005 { "ExecReload", "a(sasbttttuii)", map_exec
, 0 },
5006 { "ExecStopPre", "a(sasbttttuii)", map_exec
, 0 },
5007 { "ExecStop", "a(sasbttttuii)", map_exec
, 0 },
5008 { "ExecStopPost", "a(sasbttttuii)", map_exec
, 0 },
5012 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5013 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5014 _cleanup_set_free_ Set
*found_properties
= NULL
;
5015 _cleanup_(unit_status_info_free
) UnitStatusInfo info
= {
5016 .memory_current
= (uint64_t) -1,
5017 .memory_high
= CGROUP_LIMIT_MAX
,
5018 .memory_max
= CGROUP_LIMIT_MAX
,
5019 .memory_swap_max
= CGROUP_LIMIT_MAX
,
5020 .memory_limit
= (uint64_t) -1,
5021 .cpu_usage_nsec
= (uint64_t) -1,
5022 .tasks_current
= (uint64_t) -1,
5023 .tasks_max
= (uint64_t) -1,
5024 .ip_ingress_bytes
= (uint64_t) -1,
5025 .ip_egress_bytes
= (uint64_t) -1,
5033 log_debug("Showing one %s", path
);
5035 r
= bus_map_all_properties(
5037 "org.freedesktop.systemd1",
5039 show_mode
== SYSTEMCTL_SHOW_STATUS
? status_map
: property_map
,
5040 BUS_MAP_BOOLEAN_AS_BOOL
,
5045 return log_error_errno(r
, "Failed to get properties: %s", bus_error_message(&error
, r
));
5047 if (unit
&& streq_ptr(info
.load_state
, "not-found") && streq_ptr(info
.active_state
, "inactive")) {
5048 log_full(show_mode
== SYSTEMCTL_SHOW_STATUS
? LOG_ERR
: LOG_DEBUG
,
5049 "Unit %s could not be found.", unit
);
5051 if (show_mode
== SYSTEMCTL_SHOW_STATUS
)
5052 return EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN
;
5053 else if (show_mode
== SYSTEMCTL_SHOW_HELP
)
5062 if (show_mode
== SYSTEMCTL_SHOW_STATUS
) {
5063 print_status_info(bus
, &info
, ellipsized
);
5065 if (info
.active_state
&& !STR_IN_SET(info
.active_state
, "active", "reloading"))
5066 return EXIT_PROGRAM_NOT_RUNNING
;
5068 return EXIT_PROGRAM_RUNNING_OR_SERVICE_OK
;
5070 } else if (show_mode
== SYSTEMCTL_SHOW_HELP
) {
5071 show_unit_help(&info
);
5075 r
= sd_bus_message_rewind(reply
, true);
5077 return log_error_errno(r
, "Failed to rewind: %s", bus_error_message(&error
, r
));
5079 r
= bus_message_print_all_properties(reply
, print_property
, arg_properties
, arg_value
, arg_all
, &found_properties
);
5081 return bus_log_parse_error(r
);
5083 STRV_FOREACH(pp
, arg_properties
)
5084 if (!set_contains(found_properties
, *pp
))
5085 log_debug("Property %s does not exist.", *pp
);
5090 static int get_unit_dbus_path_by_pid(
5095 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5096 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5100 r
= sd_bus_call_method(
5102 "org.freedesktop.systemd1",
5103 "/org/freedesktop/systemd1",
5104 "org.freedesktop.systemd1.Manager",
5110 return log_error_errno(r
, "Failed to get unit for PID %"PRIu32
": %s", pid
, bus_error_message(&error
, r
));
5112 r
= sd_bus_message_read(reply
, "o", &u
);
5114 return bus_log_parse_error(r
);
5124 static int show_all(
5129 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5130 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
5135 r
= get_unit_list(bus
, NULL
, NULL
, &unit_infos
, 0, &reply
);
5139 (void) pager_open(arg_no_pager
, false);
5143 qsort_safe(unit_infos
, c
, sizeof(UnitInfo
), compare_unit_info
);
5145 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
5146 _cleanup_free_
char *p
= NULL
;
5148 p
= unit_dbus_path_from_name(u
->id
);
5152 r
= show_one(bus
, p
, u
->id
, SYSTEMCTL_SHOW_STATUS
, new_line
, ellipsized
);
5155 else if (r
> 0 && ret
== 0)
5162 static int show_system_status(sd_bus
*bus
) {
5163 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], since2
[FORMAT_TIMESTAMP_MAX
];
5164 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5165 _cleanup_(machine_info_clear
) struct machine_info mi
= {};
5166 _cleanup_free_
char *hn
= NULL
;
5167 const char *on
, *off
;
5170 hn
= gethostname_malloc();
5174 r
= bus_map_all_properties(
5176 "org.freedesktop.systemd1",
5177 "/org/freedesktop/systemd1",
5178 machine_info_property_map
,
5184 return log_error_errno(r
, "Failed to read server status: %s", bus_error_message(&error
, r
));
5186 if (streq_ptr(mi
.state
, "degraded")) {
5187 on
= ansi_highlight_red();
5188 off
= ansi_normal();
5189 } else if (streq_ptr(mi
.state
, "running")) {
5190 on
= ansi_highlight_green();
5191 off
= ansi_normal();
5193 on
= ansi_highlight_yellow();
5194 off
= ansi_normal();
5197 printf("%s%s%s %s\n", on
, special_glyph(BLACK_CIRCLE
), off
, arg_host
? arg_host
: hn
);
5199 printf(" State: %s%s%s\n",
5200 on
, strna(mi
.state
), off
);
5202 printf(" Jobs: %" PRIu32
" queued\n", mi
.n_jobs
);
5203 printf(" Failed: %" PRIu32
" units\n", mi
.n_failed_units
);
5205 printf(" Since: %s; %s\n",
5206 format_timestamp(since2
, sizeof(since2
), mi
.timestamp
),
5207 format_timestamp_relative(since1
, sizeof(since1
), mi
.timestamp
));
5209 printf(" CGroup: %s\n", mi
.control_group
?: "/");
5210 if (IN_SET(arg_transport
,
5211 BUS_TRANSPORT_LOCAL
,
5212 BUS_TRANSPORT_MACHINE
)) {
5213 static const char prefix
[] = " ";
5217 if (c
> sizeof(prefix
) - 1)
5218 c
-= sizeof(prefix
) - 1;
5222 show_cgroup(SYSTEMD_CGROUP_CONTROLLER
, strempty(mi
.control_group
), prefix
, c
, get_output_flags());
5228 static int show(int argc
, char *argv
[], void *userdata
) {
5229 bool new_line
= false, ellipsized
= false;
5230 SystemctlShowMode show_mode
;
5236 show_mode
= systemctl_show_mode_from_string(argv
[0]);
5237 if (show_mode
< 0) {
5238 log_error("Invalid argument.");
5242 if (show_mode
== SYSTEMCTL_SHOW_HELP
&& argc
<= 1) {
5243 log_error("This command expects one or more unit names. Did you mean --help?");
5247 r
= acquire_bus(BUS_MANAGER
, &bus
);
5251 (void) pager_open(arg_no_pager
, false);
5253 if (show_mode
== SYSTEMCTL_SHOW_STATUS
)
5254 /* Increase max number of open files to 16K if we can, we
5255 * might needs this when browsing journal files, which might
5256 * be split up into many files. */
5257 setrlimit_closest(RLIMIT_NOFILE
, &RLIMIT_MAKE_CONST(16384));
5259 /* If no argument is specified inspect the manager itself */
5260 if (show_mode
== SYSTEMCTL_SHOW_PROPERTIES
&& argc
<= 1)
5261 return show_one(bus
, "/org/freedesktop/systemd1", NULL
, show_mode
, &new_line
, &ellipsized
);
5263 if (show_mode
== SYSTEMCTL_SHOW_STATUS
&& argc
<= 1) {
5265 show_system_status(bus
);
5269 ret
= show_all(bus
, &new_line
, &ellipsized
);
5271 _cleanup_free_
char **patterns
= NULL
;
5274 STRV_FOREACH(name
, strv_skip(argv
, 1)) {
5275 _cleanup_free_
char *path
= NULL
, *unit
= NULL
;
5278 if (safe_atou32(*name
, &id
) < 0) {
5279 if (strv_push(&patterns
, *name
) < 0)
5283 } else if (show_mode
== SYSTEMCTL_SHOW_PROPERTIES
) {
5284 /* Interpret as job id */
5285 if (asprintf(&path
, "/org/freedesktop/systemd1/job/%u", id
) < 0)
5289 /* Interpret as PID */
5290 r
= get_unit_dbus_path_by_pid(bus
, id
, &path
);
5296 r
= unit_name_from_dbus_path(path
, &unit
);
5301 r
= show_one(bus
, path
, unit
, show_mode
, &new_line
, &ellipsized
);
5304 else if (r
> 0 && ret
== 0)
5308 if (!strv_isempty(patterns
)) {
5309 _cleanup_strv_free_
char **names
= NULL
;
5311 r
= expand_names(bus
, patterns
, NULL
, &names
);
5313 return log_error_errno(r
, "Failed to expand names: %m");
5315 STRV_FOREACH(name
, names
) {
5316 _cleanup_free_
char *path
;
5318 path
= unit_dbus_path_from_name(*name
);
5322 r
= show_one(bus
, path
, *name
, show_mode
, &new_line
, &ellipsized
);
5325 if (r
> 0 && ret
== 0)
5331 if (ellipsized
&& !arg_quiet
)
5332 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
5337 static int cat_file(const char *filename
, bool newline
) {
5338 _cleanup_close_
int fd
;
5340 fd
= open(filename
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
5344 printf("%s%s# %s%s\n",
5345 newline
? "\n" : "",
5346 ansi_highlight_blue(),
5351 return copy_bytes(fd
, STDOUT_FILENO
, (uint64_t) -1, 0);
5354 static int cat(int argc
, char *argv
[], void *userdata
) {
5355 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
5356 _cleanup_strv_free_
char **names
= NULL
;
5362 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
5363 log_error("Cannot remotely cat units.");
5367 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
5369 return log_error_errno(r
, "Failed to determine unit paths: %m");
5371 r
= acquire_bus(BUS_MANAGER
, &bus
);
5375 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
5377 return log_error_errno(r
, "Failed to expand names: %m");
5379 (void) pager_open(arg_no_pager
, false);
5381 STRV_FOREACH(name
, names
) {
5382 _cleanup_free_
char *fragment_path
= NULL
;
5383 _cleanup_strv_free_
char **dropin_paths
= NULL
;
5386 r
= unit_find_paths(bus
, *name
, &lp
, &fragment_path
, &dropin_paths
);
5397 if (need_daemon_reload(bus
, *name
) > 0) /* ignore errors (<0), this is informational output */
5399 "%s# Warning: %s changed on disk, the version systemd has loaded is outdated.\n"
5400 "%s# This output shows the current version of the unit's original fragment and drop-in files.\n"
5401 "%s# If fragments or drop-ins were added or removed, they are not properly reflected in this output.\n"
5402 "%s# Run 'systemctl%s daemon-reload' to reload units.%s\n",
5403 ansi_highlight_red(),
5405 ansi_highlight_red(),
5406 ansi_highlight_red(),
5407 ansi_highlight_red(),
5408 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user",
5411 if (fragment_path
) {
5412 r
= cat_file(fragment_path
, false);
5414 return log_warning_errno(r
, "Failed to cat %s: %m", fragment_path
);
5417 STRV_FOREACH(path
, dropin_paths
) {
5418 r
= cat_file(*path
, path
== dropin_paths
);
5420 return log_warning_errno(r
, "Failed to cat %s: %m", *path
);
5427 static int set_property(int argc
, char *argv
[], void *userdata
) {
5428 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5429 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5430 _cleanup_free_
char *n
= NULL
;
5435 r
= acquire_bus(BUS_MANAGER
, &bus
);
5439 polkit_agent_open_maybe();
5441 r
= sd_bus_message_new_method_call(
5444 "org.freedesktop.systemd1",
5445 "/org/freedesktop/systemd1",
5446 "org.freedesktop.systemd1.Manager",
5447 "SetUnitProperties");
5449 return bus_log_create_error(r
);
5451 r
= unit_name_mangle(argv
[1], arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
, &n
);
5453 return log_error_errno(r
, "Failed to mangle unit name: %m");
5455 t
= unit_name_to_type(n
);
5457 log_error("Invalid unit type: %s", n
);
5461 r
= sd_bus_message_append(m
, "sb", n
, arg_runtime
);
5463 return bus_log_create_error(r
);
5465 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, "(sv)");
5467 return bus_log_create_error(r
);
5469 r
= bus_append_unit_property_assignment_many(m
, t
, strv_skip(argv
, 2));
5473 r
= sd_bus_message_close_container(m
);
5475 return bus_log_create_error(r
);
5477 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5479 return log_error_errno(r
, "Failed to set unit properties on %s: %s", n
, bus_error_message(&error
, r
));
5484 static int daemon_reload(int argc
, char *argv
[], void *userdata
) {
5485 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5486 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5491 r
= acquire_bus(BUS_MANAGER
, &bus
);
5495 polkit_agent_open_maybe();
5497 switch (arg_action
) {
5504 method
= "Reexecute";
5507 case ACTION_SYSTEMCTL
:
5508 method
= streq(argv
[0], "daemon-reexec") ? "Reexecute" :
5509 /* "daemon-reload" */ "Reload";
5513 assert_not_reached("Unexpected action");
5516 r
= sd_bus_message_new_method_call(
5519 "org.freedesktop.systemd1",
5520 "/org/freedesktop/systemd1",
5521 "org.freedesktop.systemd1.Manager",
5524 return bus_log_create_error(r
);
5526 /* Note we use an extra-long timeout here. This is because a reload or reexec means generators are rerun which
5527 * are timed out after DEFAULT_TIMEOUT_USEC. Let's use twice that time here, so that the generators can have
5528 * their timeout, and for everything else there's the same time budget in place. */
5530 r
= sd_bus_call(bus
, m
, DEFAULT_TIMEOUT_USEC
* 2, &error
, NULL
);
5532 /* On reexecution, we expect a disconnect, not a reply */
5533 if (IN_SET(r
, -ETIMEDOUT
, -ECONNRESET
) && streq(method
, "Reexecute"))
5536 if (r
< 0 && arg_action
== ACTION_SYSTEMCTL
)
5537 return log_error_errno(r
, "Failed to reload daemon: %s", bus_error_message(&error
, r
));
5539 /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
5540 * old ways of doing things, hence don't log any error in that case here. */
5542 return r
< 0 ? r
: 0;
5545 static int trivial_method(int argc
, char *argv
[], void *userdata
) {
5546 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5554 r
= acquire_bus(BUS_MANAGER
, &bus
);
5558 polkit_agent_open_maybe();
5561 streq(argv
[0], "clear-jobs") ||
5562 streq(argv
[0], "cancel") ? "ClearJobs" :
5563 streq(argv
[0], "reset-failed") ? "ResetFailed" :
5564 streq(argv
[0], "halt") ? "Halt" :
5565 streq(argv
[0], "reboot") ? "Reboot" :
5566 streq(argv
[0], "kexec") ? "KExec" :
5567 streq(argv
[0], "exit") ? "Exit" :
5568 /* poweroff */ "PowerOff";
5570 r
= sd_bus_call_method(
5572 "org.freedesktop.systemd1",
5573 "/org/freedesktop/systemd1",
5574 "org.freedesktop.systemd1.Manager",
5579 if (r
< 0 && arg_action
== ACTION_SYSTEMCTL
)
5580 return log_error_errno(r
, "Failed to execute operation: %s", bus_error_message(&error
, r
));
5582 /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
5583 * old ways of doing things, hence don't log any error in that case here. */
5585 return r
< 0 ? r
: 0;
5588 static int reset_failed(int argc
, char *argv
[], void *userdata
) {
5589 _cleanup_strv_free_
char **names
= NULL
;
5595 return trivial_method(argc
, argv
, userdata
);
5597 r
= acquire_bus(BUS_MANAGER
, &bus
);
5601 polkit_agent_open_maybe();
5603 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
5605 return log_error_errno(r
, "Failed to expand names: %m");
5607 STRV_FOREACH(name
, names
) {
5608 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5610 q
= sd_bus_call_method(
5612 "org.freedesktop.systemd1",
5613 "/org/freedesktop/systemd1",
5614 "org.freedesktop.systemd1.Manager",
5620 log_error_errno(q
, "Failed to reset failed state of unit %s: %s", *name
, bus_error_message(&error
, q
));
5629 static int print_variable(const char *s
) {
5631 _cleanup_free_
char *esc
= NULL
;
5633 sep
= strchr(s
, '=');
5635 log_error("Invalid environment block");
5639 esc
= shell_maybe_quote(sep
+ 1, ESCAPE_POSIX
);
5643 printf("%.*s=%s\n", (int)(sep
-s
), s
, esc
);
5647 static int show_environment(int argc
, char *argv
[], void *userdata
) {
5648 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5649 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5654 r
= acquire_bus(BUS_MANAGER
, &bus
);
5658 (void) pager_open(arg_no_pager
, false);
5660 r
= sd_bus_get_property(
5662 "org.freedesktop.systemd1",
5663 "/org/freedesktop/systemd1",
5664 "org.freedesktop.systemd1.Manager",
5670 return log_error_errno(r
, "Failed to get environment: %s", bus_error_message(&error
, r
));
5672 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
5674 return bus_log_parse_error(r
);
5676 while ((r
= sd_bus_message_read_basic(reply
, SD_BUS_TYPE_STRING
, &text
)) > 0) {
5677 r
= print_variable(text
);
5682 return bus_log_parse_error(r
);
5684 r
= sd_bus_message_exit_container(reply
);
5686 return bus_log_parse_error(r
);
5691 static int switch_root(int argc
, char *argv
[], void *userdata
) {
5692 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5693 _cleanup_free_
char *cmdline_init
= NULL
;
5694 const char *root
, *init
;
5698 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
5699 log_error("Cannot switch root remotely.");
5703 if (argc
< 2 || argc
> 3) {
5704 log_error("Wrong number of arguments.");
5713 r
= parse_env_file("/proc/cmdline", WHITESPACE
,
5714 "init", &cmdline_init
,
5717 log_debug_errno(r
, "Failed to parse /proc/cmdline: %m");
5719 init
= cmdline_init
;
5722 init
= empty_to_null(init
);
5724 const char *root_systemd_path
= NULL
, *root_init_path
= NULL
;
5726 root_systemd_path
= strjoina(root
, "/" SYSTEMD_BINARY_PATH
);
5727 root_init_path
= strjoina(root
, "/", init
);
5729 /* If the passed init is actually the same as the
5730 * systemd binary, then let's suppress it. */
5731 if (files_same(root_init_path
, root_systemd_path
, 0) > 0)
5735 /* Instruct PID1 to exclude us from its killing spree applied during
5736 * the transition. Otherwise we would exit with a failure status even
5737 * though the switch to the new root has succeed. */
5738 argv_cmdline
[0] = '@';
5740 r
= acquire_bus(BUS_MANAGER
, &bus
);
5744 /* If we are slow to exit after the root switch, the new systemd instance
5745 * will send us a signal to terminate. Just ignore it and exit normally.
5746 * This way the unit does not end up as failed.
5748 r
= ignore_signals(SIGTERM
, -1);
5750 log_warning_errno(r
, "Failed to change disposition of SIGTERM to ignore: %m");
5752 log_debug("Switching root - root: %s; init: %s", root
, strna(init
));
5754 r
= sd_bus_call_method(
5756 "org.freedesktop.systemd1",
5757 "/org/freedesktop/systemd1",
5758 "org.freedesktop.systemd1.Manager",
5764 (void) default_signals(SIGTERM
, -1);
5766 return log_error_errno(r
, "Failed to switch root: %s", bus_error_message(&error
, r
));
5772 static int set_environment(int argc
, char *argv
[], void *userdata
) {
5773 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5774 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5782 r
= acquire_bus(BUS_MANAGER
, &bus
);
5786 polkit_agent_open_maybe();
5788 method
= streq(argv
[0], "set-environment")
5790 : "UnsetEnvironment";
5792 r
= sd_bus_message_new_method_call(
5795 "org.freedesktop.systemd1",
5796 "/org/freedesktop/systemd1",
5797 "org.freedesktop.systemd1.Manager",
5800 return bus_log_create_error(r
);
5802 r
= sd_bus_message_append_strv(m
, strv_skip(argv
, 1));
5804 return bus_log_create_error(r
);
5806 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5808 return log_error_errno(r
, "Failed to set environment: %s", bus_error_message(&error
, r
));
5813 static int import_environment(int argc
, char *argv
[], void *userdata
) {
5814 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5815 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5819 r
= acquire_bus(BUS_MANAGER
, &bus
);
5823 polkit_agent_open_maybe();
5825 r
= sd_bus_message_new_method_call(
5828 "org.freedesktop.systemd1",
5829 "/org/freedesktop/systemd1",
5830 "org.freedesktop.systemd1.Manager",
5833 return bus_log_create_error(r
);
5836 r
= sd_bus_message_append_strv(m
, environ
);
5840 r
= sd_bus_message_open_container(m
, 'a', "s");
5842 return bus_log_create_error(r
);
5844 STRV_FOREACH(a
, strv_skip(argv
, 1)) {
5846 if (!env_name_is_valid(*a
)) {
5847 log_error("Not a valid environment variable name: %s", *a
);
5851 STRV_FOREACH(b
, environ
) {
5854 eq
= startswith(*b
, *a
);
5855 if (eq
&& *eq
== '=') {
5857 r
= sd_bus_message_append(m
, "s", *b
);
5859 return bus_log_create_error(r
);
5866 r
= sd_bus_message_close_container(m
);
5869 return bus_log_create_error(r
);
5871 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5873 return log_error_errno(r
, "Failed to import environment: %s", bus_error_message(&error
, r
));
5878 static int enable_sysv_units(const char *verb
, char **args
) {
5881 #if HAVE_SYSV_COMPAT
5882 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
5885 /* Processes all SysV units, and reshuffles the array so that afterwards only the native units remain */
5887 if (arg_scope
!= UNIT_FILE_SYSTEM
)
5890 if (getenv_bool("SYSTEMCTL_SKIP_SYSV") > 0)
5893 if (!STR_IN_SET(verb
,
5899 r
= lookup_paths_init(&paths
, arg_scope
, LOOKUP_PATHS_EXCLUDE_GENERATED
, arg_root
);
5906 const char *argv
[] = {
5907 ROOTLIBEXECDIR
"/systemd-sysv-install",
5914 _cleanup_free_
char *p
= NULL
, *q
= NULL
, *l
= NULL
;
5915 bool found_native
= false, found_sysv
;
5923 if (!endswith(name
, ".service"))
5926 if (path_is_absolute(name
))
5929 j
= unit_file_exists(arg_scope
, &paths
, name
);
5930 if (j
< 0 && !IN_SET(j
, -ELOOP
, -ERFKILL
, -EADDRNOTAVAIL
))
5931 return log_error_errno(j
, "Failed to lookup unit file state: %m");
5932 found_native
= j
!= 0;
5934 /* If we have both a native unit and a SysV script, enable/disable them both (below); for is-enabled,
5935 * prefer the native unit */
5936 if (found_native
&& streq(verb
, "is-enabled"))
5939 p
= path_join(arg_root
, SYSTEM_SYSVINIT_PATH
, name
);
5943 p
[strlen(p
) - STRLEN(".service")] = 0;
5944 found_sysv
= access(p
, F_OK
) >= 0;
5950 log_info("Synchronizing state of %s with SysV service script with %s.", name
, argv
[0]);
5952 log_info("%s is not a native service, redirecting to systemd-sysv-install.", name
);
5955 if (!isempty(arg_root
))
5956 argv
[c
++] = q
= strappend("--root=", arg_root
);
5959 argv
[c
++] = basename(p
);
5962 l
= strv_join((char**)argv
, " ");
5967 log_info("Executing: %s", l
);
5969 j
= safe_fork("(sysv-install)", FORK_RESET_SIGNALS
|FORK_DEATHSIG
|FORK_LOG
, &pid
);
5974 execv(argv
[0], (char**) argv
);
5975 log_error_errno(errno
, "Failed to execute %s: %m", argv
[0]);
5976 _exit(EXIT_FAILURE
);
5979 j
= wait_for_terminate_and_check("sysv-install", pid
, WAIT_LOG_ABNORMAL
);
5982 if (streq(verb
, "is-enabled")) {
5983 if (j
== EXIT_SUCCESS
) {
5992 } else if (j
!= EXIT_SUCCESS
)
5993 return -EBADE
; /* We don't warn here, under the assumption the script already showed an explanation */
5998 /* Remove this entry, so that we don't try enabling it as native unit */
6001 assert(args
[f
] == name
);
6002 strv_remove(args
, name
);
6009 static int mangle_names(char **original_names
, char ***mangled_names
) {
6010 char **i
, **l
, **name
;
6013 l
= i
= new(char*, strv_length(original_names
) + 1);
6017 STRV_FOREACH(name
, original_names
) {
6019 /* When enabling units qualified path names are OK,
6020 * too, hence allow them explicitly. */
6022 if (is_path(*name
)) {
6029 r
= unit_name_mangle(*name
, arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
, i
);
6033 return log_error_errno(r
, "Failed to mangle unit name: %m");
6046 static int normalize_filenames(char **names
) {
6050 STRV_FOREACH(u
, names
)
6051 if (!path_is_absolute(*u
)) {
6052 char* normalized_path
;
6054 if (!isempty(arg_root
)) {
6055 log_error("Non-absolute paths are not allowed when --root is used: %s", *u
);
6059 if (!strchr(*u
,'/')) {
6060 log_error("Link argument does contain at least one directory separator: %s", *u
);
6064 r
= path_make_absolute_cwd(*u
, &normalized_path
);
6068 free_and_replace(*u
, normalized_path
);
6074 static int normalize_names(char **names
, bool warn_if_path
) {
6076 bool was_path
= false;
6078 STRV_FOREACH(u
, names
) {
6084 r
= free_and_strdup(u
, basename(*u
));
6086 return log_error_errno(r
, "Failed to normalize unit file path: %m");
6091 if (warn_if_path
&& was_path
)
6092 log_warning("Warning: Can't execute disable on the unit file path. Proceeding with the unit name.");
6097 static int unit_exists(LookupPaths
*lp
, const char *unit
) {
6098 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6099 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
6100 _cleanup_free_
char *path
= NULL
;
6101 static const struct bus_properties_map property_map
[] = {
6102 { "LoadState", "s", NULL
, offsetof(UnitStatusInfo
, load_state
) },
6103 { "ActiveState", "s", NULL
, offsetof(UnitStatusInfo
, active_state
)},
6106 UnitStatusInfo info
= {};
6110 if (unit_name_is_valid(unit
, UNIT_NAME_TEMPLATE
))
6111 return unit_find_template_path(unit
, lp
, NULL
, NULL
);
6113 path
= unit_dbus_path_from_name(unit
);
6117 r
= acquire_bus(BUS_MANAGER
, &bus
);
6121 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", path
, property_map
, 0, &error
, &m
, &info
);
6123 return log_error_errno(r
, "Failed to get properties: %s", bus_error_message(&error
, r
));
6125 return !streq_ptr(info
.load_state
, "not-found") || !streq_ptr(info
.active_state
, "inactive");
6128 static int enable_unit(int argc
, char *argv
[], void *userdata
) {
6129 _cleanup_strv_free_
char **names
= NULL
;
6130 const char *verb
= argv
[0];
6131 UnitFileChange
*changes
= NULL
;
6132 unsigned n_changes
= 0;
6133 int carries_install_info
= -1;
6134 bool ignore_carries_install_info
= arg_quiet
;
6140 r
= mangle_names(strv_skip(argv
, 1), &names
);
6144 r
= enable_sysv_units(verb
, names
);
6148 /* If the operation was fully executed by the SysV compat, let's finish early */
6149 if (strv_isempty(names
)) {
6150 if (arg_no_reload
|| install_client_side())
6152 return daemon_reload(argc
, argv
, userdata
);
6155 if (streq(verb
, "disable")) {
6156 r
= normalize_names(names
, true);
6161 if (streq(verb
, "link")) {
6162 r
= normalize_filenames(names
);
6167 if (install_client_side()) {
6168 UnitFileFlags flags
;
6170 flags
= args_to_flags();
6171 if (streq(verb
, "enable")) {
6172 r
= unit_file_enable(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6173 carries_install_info
= r
;
6174 } else if (streq(verb
, "disable"))
6175 r
= unit_file_disable(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6176 else if (streq(verb
, "reenable")) {
6177 r
= unit_file_reenable(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6178 carries_install_info
= r
;
6179 } else if (streq(verb
, "link"))
6180 r
= unit_file_link(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6181 else if (streq(verb
, "preset")) {
6182 r
= unit_file_preset(arg_scope
, flags
, arg_root
, names
, arg_preset_mode
, &changes
, &n_changes
);
6183 } else if (streq(verb
, "mask"))
6184 r
= unit_file_mask(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6185 else if (streq(verb
, "unmask"))
6186 r
= unit_file_unmask(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6187 else if (streq(verb
, "revert"))
6188 r
= unit_file_revert(arg_scope
, arg_root
, names
, &changes
, &n_changes
);
6190 assert_not_reached("Unknown verb");
6192 unit_file_dump_changes(r
, verb
, changes
, n_changes
, arg_quiet
);
6197 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
, *m
= NULL
;
6198 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6199 bool expect_carries_install_info
= false;
6200 bool send_runtime
= true, send_force
= true, send_preset_mode
= false;
6204 if (STR_IN_SET(verb
, "mask", "unmask")) {
6206 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
6208 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
6212 STRV_FOREACH(name
, names
) {
6213 r
= unit_exists(&lp
, *name
);
6217 log_notice("Unit %s does not exist, proceeding anyway.", *names
);
6221 r
= acquire_bus(BUS_MANAGER
, &bus
);
6225 polkit_agent_open_maybe();
6227 if (streq(verb
, "enable")) {
6228 method
= "EnableUnitFiles";
6229 expect_carries_install_info
= true;
6230 } else if (streq(verb
, "disable")) {
6231 method
= "DisableUnitFiles";
6233 } else if (streq(verb
, "reenable")) {
6234 method
= "ReenableUnitFiles";
6235 expect_carries_install_info
= true;
6236 } else if (streq(verb
, "link"))
6237 method
= "LinkUnitFiles";
6238 else if (streq(verb
, "preset")) {
6240 if (arg_preset_mode
!= UNIT_FILE_PRESET_FULL
) {
6241 method
= "PresetUnitFilesWithMode";
6242 send_preset_mode
= true;
6244 method
= "PresetUnitFiles";
6246 expect_carries_install_info
= true;
6247 ignore_carries_install_info
= true;
6248 } else if (streq(verb
, "mask"))
6249 method
= "MaskUnitFiles";
6250 else if (streq(verb
, "unmask")) {
6251 method
= "UnmaskUnitFiles";
6253 } else if (streq(verb
, "revert")) {
6254 method
= "RevertUnitFiles";
6255 send_runtime
= send_force
= false;
6257 assert_not_reached("Unknown verb");
6259 r
= sd_bus_message_new_method_call(
6262 "org.freedesktop.systemd1",
6263 "/org/freedesktop/systemd1",
6264 "org.freedesktop.systemd1.Manager",
6267 return bus_log_create_error(r
);
6269 r
= sd_bus_message_append_strv(m
, names
);
6271 return bus_log_create_error(r
);
6273 if (send_preset_mode
) {
6274 r
= sd_bus_message_append(m
, "s", unit_file_preset_mode_to_string(arg_preset_mode
));
6276 return bus_log_create_error(r
);
6280 r
= sd_bus_message_append(m
, "b", arg_runtime
);
6282 return bus_log_create_error(r
);
6286 r
= sd_bus_message_append(m
, "b", arg_force
);
6288 return bus_log_create_error(r
);
6291 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
6293 return log_error_errno(r
, "Failed to %s unit: %s", verb
, bus_error_message(&error
, r
));
6295 if (expect_carries_install_info
) {
6296 r
= sd_bus_message_read(reply
, "b", &carries_install_info
);
6298 return bus_log_parse_error(r
);
6301 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
6305 /* Try to reload if enabled */
6307 r
= daemon_reload(argc
, argv
, userdata
);
6312 if (carries_install_info
== 0 && !ignore_carries_install_info
)
6313 log_warning("The unit files have no installation config (WantedBy, RequiredBy, Also, Alias\n"
6314 "settings in the [Install] section, and DefaultInstance for template units).\n"
6315 "This means they are not meant to be enabled using systemctl.\n"
6316 "Possible reasons for having this kind of units are:\n"
6317 "1) A unit may be statically enabled by being symlinked from another unit's\n"
6318 " .wants/ or .requires/ directory.\n"
6319 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
6320 " a requirement dependency on it.\n"
6321 "3) A unit may be started when needed via activation (socket, path, timer,\n"
6322 " D-Bus, udev, scripted systemctl call, ...).\n"
6323 "4) In case of template units, the unit is meant to be enabled with some\n"
6324 " instance name specified.");
6326 if (arg_now
&& STR_IN_SET(argv
[0], "enable", "disable", "mask")) {
6330 r
= acquire_bus(BUS_MANAGER
, &bus
);
6334 len
= strv_length(names
);
6336 char *new_args
[len
+ 2];
6338 new_args
[0] = (char*) (streq(argv
[0], "enable") ? "start" : "stop");
6339 for (i
= 0; i
< len
; i
++)
6340 new_args
[i
+ 1] = basename(names
[i
]);
6341 new_args
[i
+ 1] = NULL
;
6343 r
= start_unit(len
+ 1, new_args
, userdata
);
6348 unit_file_changes_free(changes
, n_changes
);
6353 static int add_dependency(int argc
, char *argv
[], void *userdata
) {
6354 _cleanup_strv_free_
char **names
= NULL
;
6355 _cleanup_free_
char *target
= NULL
;
6356 const char *verb
= argv
[0];
6357 UnitFileChange
*changes
= NULL
;
6358 unsigned n_changes
= 0;
6365 r
= unit_name_mangle_with_suffix(argv
[1], arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
, ".target", &target
);
6367 return log_error_errno(r
, "Failed to mangle unit name: %m");
6369 r
= mangle_names(strv_skip(argv
, 2), &names
);
6373 if (streq(verb
, "add-wants"))
6375 else if (streq(verb
, "add-requires"))
6376 dep
= UNIT_REQUIRES
;
6378 assert_not_reached("Unknown verb");
6380 if (install_client_side()) {
6381 r
= unit_file_add_dependency(arg_scope
, args_to_flags(), arg_root
, names
, target
, dep
, &changes
, &n_changes
);
6382 unit_file_dump_changes(r
, "add dependency on", changes
, n_changes
, arg_quiet
);
6387 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
, *m
= NULL
;
6388 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6391 r
= acquire_bus(BUS_MANAGER
, &bus
);
6395 polkit_agent_open_maybe();
6397 r
= sd_bus_message_new_method_call(
6400 "org.freedesktop.systemd1",
6401 "/org/freedesktop/systemd1",
6402 "org.freedesktop.systemd1.Manager",
6403 "AddDependencyUnitFiles");
6405 return bus_log_create_error(r
);
6407 r
= sd_bus_message_append_strv(m
, names
);
6409 return bus_log_create_error(r
);
6411 r
= sd_bus_message_append(m
, "ssbb", target
, unit_dependency_to_string(dep
), arg_runtime
, arg_force
);
6413 return bus_log_create_error(r
);
6415 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
6417 return log_error_errno(r
, "Failed to add dependency: %s", bus_error_message(&error
, r
));
6419 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
6423 if (arg_no_reload
) {
6428 r
= daemon_reload(argc
, argv
, userdata
);
6432 unit_file_changes_free(changes
, n_changes
);
6437 static int preset_all(int argc
, char *argv
[], void *userdata
) {
6438 UnitFileChange
*changes
= NULL
;
6439 unsigned n_changes
= 0;
6442 if (install_client_side()) {
6443 r
= unit_file_preset_all(arg_scope
, args_to_flags(), arg_root
, arg_preset_mode
, &changes
, &n_changes
);
6444 unit_file_dump_changes(r
, "preset", changes
, n_changes
, arg_quiet
);
6449 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6450 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6453 r
= acquire_bus(BUS_MANAGER
, &bus
);
6457 polkit_agent_open_maybe();
6459 r
= sd_bus_call_method(
6461 "org.freedesktop.systemd1",
6462 "/org/freedesktop/systemd1",
6463 "org.freedesktop.systemd1.Manager",
6464 "PresetAllUnitFiles",
6468 unit_file_preset_mode_to_string(arg_preset_mode
),
6472 return log_error_errno(r
, "Failed to preset all units: %s", bus_error_message(&error
, r
));
6474 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
6478 if (arg_no_reload
) {
6483 r
= daemon_reload(argc
, argv
, userdata
);
6487 unit_file_changes_free(changes
, n_changes
);
6492 static int show_installation_targets_client_side(const char *name
) {
6493 UnitFileChange
*changes
= NULL
;
6494 unsigned n_changes
= 0, i
;
6495 UnitFileFlags flags
;
6499 p
= STRV_MAKE(name
);
6500 flags
= UNIT_FILE_DRY_RUN
|
6501 (arg_runtime
? UNIT_FILE_RUNTIME
: 0);
6503 r
= unit_file_disable(UNIT_FILE_SYSTEM
, flags
, NULL
, p
, &changes
, &n_changes
);
6505 return log_error_errno(r
, "Failed to get file links for %s: %m", name
);
6507 for (i
= 0; i
< n_changes
; i
++)
6508 if (changes
[i
].type
== UNIT_FILE_UNLINK
)
6509 printf(" %s\n", changes
[i
].path
);
6514 static int show_installation_targets(sd_bus
*bus
, const char *name
) {
6515 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6516 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6520 r
= sd_bus_call_method(
6522 "org.freedesktop.systemd1",
6523 "/org/freedesktop/systemd1",
6524 "org.freedesktop.systemd1.Manager",
6528 "sb", name
, arg_runtime
);
6530 return log_error_errno(r
, "Failed to get unit file links for %s: %s", name
, bus_error_message(&error
, r
));
6532 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
6534 return bus_log_parse_error(r
);
6536 while ((r
= sd_bus_message_read(reply
, "s", &link
)) > 0)
6537 printf(" %s\n", link
);
6540 return bus_log_parse_error(r
);
6542 r
= sd_bus_message_exit_container(reply
);
6544 return bus_log_parse_error(r
);
6549 static int unit_is_enabled(int argc
, char *argv
[], void *userdata
) {
6551 _cleanup_strv_free_
char **names
= NULL
;
6556 r
= mangle_names(strv_skip(argv
, 1), &names
);
6560 r
= enable_sysv_units(argv
[0], names
);
6566 if (install_client_side()) {
6567 STRV_FOREACH(name
, names
) {
6568 UnitFileState state
;
6570 r
= unit_file_get_state(arg_scope
, arg_root
, *name
, &state
);
6572 return log_error_errno(r
, "Failed to get unit file state for %s: %m", *name
);
6576 UNIT_FILE_ENABLED_RUNTIME
,
6579 UNIT_FILE_GENERATED
))
6583 puts(unit_file_state_to_string(state
));
6585 r
= show_installation_targets_client_side(*name
);
6594 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6597 r
= acquire_bus(BUS_MANAGER
, &bus
);
6601 STRV_FOREACH(name
, names
) {
6602 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6605 r
= sd_bus_call_method(
6607 "org.freedesktop.systemd1",
6608 "/org/freedesktop/systemd1",
6609 "org.freedesktop.systemd1.Manager",
6615 return log_error_errno(r
, "Failed to get unit file state for %s: %s", *name
, bus_error_message(&error
, r
));
6617 r
= sd_bus_message_read(reply
, "s", &s
);
6619 return bus_log_parse_error(r
);
6621 if (STR_IN_SET(s
, "enabled", "enabled-runtime", "static", "indirect", "generated"))
6627 r
= show_installation_targets(bus
, *name
);
6635 return enabled
? EXIT_SUCCESS
: EXIT_FAILURE
;
6638 static int is_system_running(int argc
, char *argv
[], void *userdata
) {
6639 _cleanup_free_
char *state
= NULL
;
6643 if (running_in_chroot() > 0 || (arg_transport
== BUS_TRANSPORT_LOCAL
&& !sd_booted())) {
6646 return EXIT_FAILURE
;
6649 r
= acquire_bus(BUS_MANAGER
, &bus
);
6653 r
= sd_bus_get_property_string(
6655 "org.freedesktop.systemd1",
6656 "/org/freedesktop/systemd1",
6657 "org.freedesktop.systemd1.Manager",
6670 return streq(state
, "running") ? EXIT_SUCCESS
: EXIT_FAILURE
;
6673 static int create_edit_temp_file(const char *new_path
, const char *original_path
, char **ret_tmp_fn
) {
6674 _cleanup_free_
char *t
= NULL
;
6678 assert(original_path
);
6681 r
= tempfn_random(new_path
, NULL
, &t
);
6683 return log_error_errno(r
, "Failed to determine temporary filename for \"%s\": %m", new_path
);
6685 r
= mkdir_parents(new_path
, 0755);
6687 return log_error_errno(r
, "Failed to create directories for \"%s\": %m", new_path
);
6689 r
= copy_file(original_path
, t
, 0, 0644, 0, COPY_REFLINK
);
6694 return log_error_errno(r
, "Failed to create temporary file \"%s\": %m", t
);
6697 return log_error_errno(r
, "Failed to create temporary file for \"%s\": %m", new_path
);
6699 *ret_tmp_fn
= TAKE_PTR(t
);
6704 static int get_file_to_edit(
6705 const LookupPaths
*paths
,
6709 _cleanup_free_
char *path
= NULL
, *run
= NULL
;
6714 path
= strjoin(paths
->persistent_config
, "/", name
);
6719 run
= strjoin(paths
->runtime_config
, "/", name
);
6725 if (access(path
, F_OK
) >= 0) {
6726 log_error("Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.", run
, path
);
6730 *ret_path
= TAKE_PTR(run
);
6732 *ret_path
= TAKE_PTR(path
);
6737 static int unit_file_create_new(
6738 const LookupPaths
*paths
,
6739 const char *unit_name
,
6741 char **ret_new_path
,
6742 char **ret_tmp_path
) {
6744 char *tmp_new_path
, *tmp_tmp_path
, *ending
;
6748 assert(ret_new_path
);
6749 assert(ret_tmp_path
);
6751 ending
= strjoina(unit_name
, suffix
);
6752 r
= get_file_to_edit(paths
, ending
, &tmp_new_path
);
6756 r
= create_edit_temp_file(tmp_new_path
, tmp_new_path
, &tmp_tmp_path
);
6762 *ret_new_path
= tmp_new_path
;
6763 *ret_tmp_path
= tmp_tmp_path
;
6768 static int unit_file_create_copy(
6769 const LookupPaths
*paths
,
6770 const char *unit_name
,
6771 const char *fragment_path
,
6772 char **ret_new_path
,
6773 char **ret_tmp_path
) {
6775 char *tmp_new_path
, *tmp_tmp_path
;
6778 assert(fragment_path
);
6780 assert(ret_new_path
);
6781 assert(ret_tmp_path
);
6783 r
= get_file_to_edit(paths
, unit_name
, &tmp_new_path
);
6787 if (!path_equal(fragment_path
, tmp_new_path
) && access(tmp_new_path
, F_OK
) == 0) {
6790 r
= ask_char(&response
, "yn", "\"%s\" already exists. Overwrite with \"%s\"? [(y)es, (n)o] ", tmp_new_path
, fragment_path
);
6795 if (response
!= 'y') {
6796 log_warning("%s ignored", unit_name
);
6798 return -EKEYREJECTED
;
6802 r
= create_edit_temp_file(tmp_new_path
, fragment_path
, &tmp_tmp_path
);
6808 *ret_new_path
= tmp_new_path
;
6809 *ret_tmp_path
= tmp_tmp_path
;
6814 static int run_editor(char **paths
) {
6819 r
= safe_fork("(editor)", FORK_RESET_SIGNALS
|FORK_DEATHSIG
|FORK_LOG
|FORK_WAIT
, NULL
);
6824 char *editor
, **editor_args
= NULL
;
6825 char **tmp_path
, **original_path
, *p
;
6826 unsigned n_editor_args
= 0, i
= 1;
6829 argc
= strv_length(paths
)/2 + 1;
6831 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
6832 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
6833 * we try to execute well known editors
6835 editor
= getenv("SYSTEMD_EDITOR");
6837 editor
= getenv("EDITOR");
6839 editor
= getenv("VISUAL");
6841 if (!isempty(editor
)) {
6842 editor_args
= strv_split(editor
, WHITESPACE
);
6845 _exit(EXIT_FAILURE
);
6847 n_editor_args
= strv_length(editor_args
);
6848 argc
+= n_editor_args
- 1;
6850 args
= newa(const char*, argc
+ 1);
6852 if (n_editor_args
> 0) {
6853 args
[0] = editor_args
[0];
6854 for (; i
< n_editor_args
; i
++)
6855 args
[i
] = editor_args
[i
];
6858 STRV_FOREACH_PAIR(original_path
, tmp_path
, paths
) {
6859 args
[i
] = *tmp_path
;
6864 if (n_editor_args
> 0)
6865 execvp(args
[0], (char* const*) args
);
6867 FOREACH_STRING(p
, "editor", "nano", "vim", "vi") {
6869 execvp(p
, (char* const*) args
);
6870 /* We do not fail if the editor doesn't exist
6871 * because we want to try each one of them before
6874 if (errno
!= ENOENT
) {
6875 log_error_errno(errno
, "Failed to execute %s: %m", editor
);
6876 _exit(EXIT_FAILURE
);
6880 log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR, $EDITOR or $VISUAL.");
6881 _exit(EXIT_FAILURE
);
6887 static int find_paths_to_edit(sd_bus
*bus
, char **names
, char ***paths
) {
6888 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
6895 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
6899 STRV_FOREACH(name
, names
) {
6900 _cleanup_free_
char *path
= NULL
, *new_path
= NULL
, *tmp_path
= NULL
, *tmp_name
= NULL
;
6901 const char *unit_name
;
6903 r
= unit_find_paths(bus
, *name
, &lp
, &path
, NULL
);
6911 log_error("Run 'systemctl edit%s --force %s' to create a new unit.",
6912 arg_scope
== UNIT_FILE_GLOBAL
? " --global" :
6913 arg_scope
== UNIT_FILE_USER
? " --user" : "",
6918 /* Create a new unit from scratch */
6920 r
= unit_file_create_new(&lp
, unit_name
,
6921 arg_full
? NULL
: ".d/override.conf",
6922 &new_path
, &tmp_path
);
6926 unit_name
= basename(path
);
6927 /* We follow unit aliases, but we need to propagate the instance */
6928 if (unit_name_is_valid(*name
, UNIT_NAME_INSTANCE
) &&
6929 unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
6930 _cleanup_free_
char *instance
= NULL
;
6932 r
= unit_name_to_instance(*name
, &instance
);
6936 r
= unit_name_replace_instance(unit_name
, instance
, &tmp_name
);
6940 unit_name
= tmp_name
;
6944 r
= unit_file_create_copy(&lp
, unit_name
, path
, &new_path
, &tmp_path
);
6946 r
= unit_file_create_new(&lp
, unit_name
, ".d/override.conf", &new_path
, &tmp_path
);
6951 r
= strv_push_pair(paths
, new_path
, tmp_path
);
6954 new_path
= tmp_path
= NULL
;
6960 static int edit(int argc
, char *argv
[], void *userdata
) {
6961 _cleanup_strv_free_
char **names
= NULL
;
6962 _cleanup_strv_free_
char **paths
= NULL
;
6963 char **original
, **tmp
;
6968 log_error("Cannot edit units if not on a tty.");
6972 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
6973 log_error("Cannot edit units remotely.");
6977 r
= acquire_bus(BUS_MANAGER
, &bus
);
6981 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
6983 return log_error_errno(r
, "Failed to expand names: %m");
6985 STRV_FOREACH(tmp
, names
) {
6986 r
= unit_is_masked(bus
, *tmp
);
6991 log_error("Cannot edit %s: unit is masked.", *tmp
);
6996 r
= find_paths_to_edit(bus
, names
, &paths
);
7000 if (strv_isempty(paths
))
7003 r
= run_editor(paths
);
7007 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
7008 /* If the temporary file is empty we ignore it.
7009 * This allows the user to cancel the modification.
7011 if (null_or_empty_path(*tmp
)) {
7012 log_warning("Editing \"%s\" canceled: temporary file is empty.", *original
);
7016 r
= rename(*tmp
, *original
);
7018 r
= log_error_errno(errno
, "Failed to rename \"%s\" to \"%s\": %m", *tmp
, *original
);
7025 if (!arg_no_reload
&& !install_client_side())
7026 r
= daemon_reload(argc
, argv
, userdata
);
7029 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
7030 (void) unlink(*tmp
);
7032 /* Removing empty dropin dirs */
7034 _cleanup_free_
char *dir
;
7036 dir
= dirname_malloc(*original
);
7040 /* no need to check if the dir is empty, rmdir
7041 * does nothing if it is not the case.
7050 static void systemctl_help(void) {
7052 (void) pager_open(arg_no_pager
, false);
7054 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
7055 "Query or send control commands to the systemd manager.\n\n"
7056 " -h --help Show this help\n"
7057 " --version Show package version\n"
7058 " --system Connect to system manager\n"
7059 " --user Connect to user service manager\n"
7060 " -H --host=[USER@]HOST\n"
7061 " Operate on remote host\n"
7062 " -M --machine=CONTAINER\n"
7063 " Operate on local container\n"
7064 " -t --type=TYPE List units of a particular type\n"
7065 " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n"
7066 " -p --property=NAME Show only properties by this name\n"
7067 " -a --all Show all properties/all units currently in memory,\n"
7068 " including dead/empty ones. To list all units installed on\n"
7069 " the system, use the 'list-unit-files' command instead.\n"
7070 " --failed Same as --state=failed\n"
7071 " -l --full Don't ellipsize unit names on output\n"
7072 " -r --recursive Show unit list of host and local containers\n"
7073 " --reverse Show reverse dependencies with 'list-dependencies'\n"
7074 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
7075 " queueing a new job\n"
7076 " --show-types When showing sockets, explicitly show their type\n"
7077 " --value When showing properties, only print the value\n"
7078 " -i --ignore-inhibitors\n"
7079 " When shutting down or sleeping, ignore inhibitors\n"
7080 " --kill-who=WHO Who to send signal to\n"
7081 " -s --signal=SIGNAL Which signal to send\n"
7082 " --now Start or stop unit in addition to enabling or disabling it\n"
7083 " --dry-run Only print what would be done\n"
7084 " -q --quiet Suppress output\n"
7085 " --wait For (re)start, wait until service stopped again\n"
7086 " --no-block Do not wait until operation finished\n"
7087 " --no-wall Don't send wall message before halt/power-off/reboot\n"
7088 " --no-reload Don't reload daemon after en-/dis-abling unit files\n"
7089 " --no-legend Do not print a legend (column headers and hints)\n"
7090 " --no-pager Do not pipe output into a pager\n"
7091 " --no-ask-password\n"
7092 " Do not ask for system passwords\n"
7093 " --global Enable/disable/mask unit files globally\n"
7094 " --runtime Enable/disable/mask unit files temporarily until next\n"
7096 " -f --force When enabling unit files, override existing symlinks\n"
7097 " When shutting down, execute action immediately\n"
7098 " --preset-mode= Apply only enable, only disable, or all presets\n"
7099 " --root=PATH Enable/disable/mask unit files in the specified root\n"
7101 " -n --lines=INTEGER Number of journal entries to show\n"
7102 " -o --output=STRING Change journal output mode (short, short-precise,\n"
7103 " short-iso, short-iso-precise, short-full,\n"
7104 " short-monotonic, short-unix,\n"
7105 " verbose, export, json, json-pretty, json-sse, cat)\n"
7106 " --firmware-setup Tell the firmware to show the setup menu on next boot\n"
7107 " --plain Print unit dependencies as a list instead of a tree\n\n"
7109 " list-units [PATTERN...] List units currently in memory\n"
7110 " list-sockets [PATTERN...] List socket units currently in memory,\n"
7111 " ordered by address\n"
7112 " list-timers [PATTERN...] List timer units currently in memory,\n"
7113 " ordered by next elapse\n"
7114 " start UNIT... Start (activate) one or more units\n"
7115 " stop UNIT... Stop (deactivate) one or more units\n"
7116 " reload UNIT... Reload one or more units\n"
7117 " restart UNIT... Start or restart one or more units\n"
7118 " try-restart UNIT... Restart one or more units if active\n"
7119 " reload-or-restart UNIT... Reload one or more units if possible,\n"
7120 " otherwise start or restart\n"
7121 " try-reload-or-restart UNIT... If active, reload one or more units,\n"
7122 " if supported, otherwise restart\n"
7123 " isolate UNIT Start one unit and stop all others\n"
7124 " kill UNIT... Send signal to processes of a unit\n"
7125 " is-active PATTERN... Check whether units are active\n"
7126 " is-failed PATTERN... Check whether units are failed\n"
7127 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
7128 " show [PATTERN...|JOB...] Show properties of one or more\n"
7129 " units/jobs or the manager\n"
7130 " cat PATTERN... Show files and drop-ins of specified units\n"
7131 " set-property UNIT PROPERTY=VALUE... Sets one or more properties of a unit\n"
7132 " help PATTERN...|PID... Show manual for one or more units\n"
7133 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
7135 " list-dependencies [UNIT] Recursively show units which are required\n"
7136 " or wanted by this unit or by which this\n"
7137 " unit is required or wanted\n\n"
7138 "Unit File Commands:\n"
7139 " list-unit-files [PATTERN...] List installed unit files\n"
7140 " enable [UNIT...|PATH...] Enable one or more unit files\n"
7141 " disable UNIT... Disable one or more unit files\n"
7142 " reenable UNIT... Reenable one or more unit files\n"
7143 " preset UNIT... Enable/disable one or more unit files\n"
7144 " based on preset configuration\n"
7145 " preset-all Enable/disable all unit files based on\n"
7146 " preset configuration\n"
7147 " is-enabled UNIT... Check whether unit files are enabled\n"
7148 " mask UNIT... Mask one or more units\n"
7149 " unmask UNIT... Unmask one or more units\n"
7150 " link PATH... Link one or more units files into\n"
7151 " the search path\n"
7152 " revert UNIT... Revert one or more unit files to vendor\n"
7154 " add-wants TARGET UNIT... Add 'Wants' dependency for the target\n"
7155 " on specified one or more units\n"
7156 " add-requires TARGET UNIT... Add 'Requires' dependency for the target\n"
7157 " on specified one or more units\n"
7158 " edit UNIT... Edit one or more unit files\n"
7159 " get-default Get the name of the default target\n"
7160 " set-default TARGET Set the default target\n\n"
7161 "Machine Commands:\n"
7162 " list-machines [PATTERN...] List local containers and host\n\n"
7164 " list-jobs [PATTERN...] List jobs\n"
7165 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
7166 "Environment Commands:\n"
7167 " show-environment Dump environment\n"
7168 " set-environment VARIABLE=VALUE... Set one or more environment variables\n"
7169 " unset-environment VARIABLE... Unset one or more environment variables\n"
7170 " import-environment [VARIABLE...] Import all or some environment variables\n\n"
7171 "Manager Lifecycle Commands:\n"
7172 " daemon-reload Reload systemd manager configuration\n"
7173 " daemon-reexec Reexecute systemd manager\n\n"
7174 "System Commands:\n"
7175 " is-system-running Check whether system is fully running\n"
7176 " default Enter system default mode\n"
7177 " rescue Enter system rescue mode\n"
7178 " emergency Enter system emergency mode\n"
7179 " halt Shut down and halt the system\n"
7180 " poweroff Shut down and power-off the system\n"
7181 " reboot [ARG] Shut down and reboot the system\n"
7182 " kexec Shut down and reboot the system with kexec\n"
7183 " exit [EXIT_CODE] Request user instance or container exit\n"
7184 " switch-root ROOT [INIT] Change to a different root file system\n"
7185 " suspend Suspend the system\n"
7186 " hibernate Hibernate the system\n"
7187 " hybrid-sleep Hibernate and suspend the system\n"
7188 " suspend-then-hibernate Suspend the system, wake after a period of\n"
7189 " time and put it into hibernate\n",
7190 program_invocation_short_name
);
7193 static void halt_help(void) {
7194 printf("%s [OPTIONS...]%s\n\n"
7195 "%s the system.\n\n"
7196 " --help Show this help\n"
7197 " --halt Halt the machine\n"
7198 " -p --poweroff Switch off the machine\n"
7199 " --reboot Reboot the machine\n"
7200 " -f --force Force immediate halt/power-off/reboot\n"
7201 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
7202 " -d --no-wtmp Don't write wtmp record\n"
7203 " --no-wall Don't send wall message before halt/power-off/reboot\n",
7204 program_invocation_short_name
,
7205 arg_action
== ACTION_REBOOT
? " [ARG]" : "",
7206 arg_action
== ACTION_REBOOT
? "Reboot" :
7207 arg_action
== ACTION_POWEROFF
? "Power off" :
7211 static void shutdown_help(void) {
7212 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
7213 "Shut down the system.\n\n"
7214 " --help Show this help\n"
7215 " -H --halt Halt the machine\n"
7216 " -P --poweroff Power-off the machine\n"
7217 " -r --reboot Reboot the machine\n"
7218 " -h Equivalent to --poweroff, overridden by --halt\n"
7219 " -k Don't halt/power-off/reboot, just send warnings\n"
7220 " --no-wall Don't send wall message before halt/power-off/reboot\n"
7221 " -c Cancel a pending shutdown\n",
7222 program_invocation_short_name
);
7225 static void telinit_help(void) {
7226 printf("%s [OPTIONS...] {COMMAND}\n\n"
7227 "Send control commands to the init daemon.\n\n"
7228 " --help Show this help\n"
7229 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
7231 " 0 Power-off the machine\n"
7232 " 6 Reboot the machine\n"
7233 " 2, 3, 4, 5 Start runlevelX.target unit\n"
7234 " 1, s, S Enter rescue mode\n"
7235 " q, Q Reload init daemon configuration\n"
7236 " u, U Reexecute init daemon\n",
7237 program_invocation_short_name
);
7240 static void runlevel_help(void) {
7241 printf("%s [OPTIONS...]\n\n"
7242 "Prints the previous and current runlevel of the init system.\n\n"
7243 " --help Show this help\n",
7244 program_invocation_short_name
);
7247 static void help_types(void) {
7251 puts("Available unit types:");
7252 for (i
= 0; i
< _UNIT_TYPE_MAX
; i
++)
7253 puts(unit_type_to_string(i
));
7256 static void help_states(void) {
7260 puts("Available unit load states:");
7261 for (i
= 0; i
< _UNIT_LOAD_STATE_MAX
; i
++)
7262 puts(unit_load_state_to_string(i
));
7265 puts("\nAvailable unit active states:");
7266 for (i
= 0; i
< _UNIT_ACTIVE_STATE_MAX
; i
++)
7267 puts(unit_active_state_to_string(i
));
7270 puts("\nAvailable automount unit substates:");
7271 for (i
= 0; i
< _AUTOMOUNT_STATE_MAX
; i
++)
7272 puts(automount_state_to_string(i
));
7275 puts("\nAvailable device unit substates:");
7276 for (i
= 0; i
< _DEVICE_STATE_MAX
; i
++)
7277 puts(device_state_to_string(i
));
7280 puts("\nAvailable mount unit substates:");
7281 for (i
= 0; i
< _MOUNT_STATE_MAX
; i
++)
7282 puts(mount_state_to_string(i
));
7285 puts("\nAvailable path unit substates:");
7286 for (i
= 0; i
< _PATH_STATE_MAX
; i
++)
7287 puts(path_state_to_string(i
));
7290 puts("\nAvailable scope unit substates:");
7291 for (i
= 0; i
< _SCOPE_STATE_MAX
; i
++)
7292 puts(scope_state_to_string(i
));
7295 puts("\nAvailable service unit substates:");
7296 for (i
= 0; i
< _SERVICE_STATE_MAX
; i
++)
7297 puts(service_state_to_string(i
));
7300 puts("\nAvailable slice unit substates:");
7301 for (i
= 0; i
< _SLICE_STATE_MAX
; i
++)
7302 puts(slice_state_to_string(i
));
7305 puts("\nAvailable socket unit substates:");
7306 for (i
= 0; i
< _SOCKET_STATE_MAX
; i
++)
7307 puts(socket_state_to_string(i
));
7310 puts("\nAvailable swap unit substates:");
7311 for (i
= 0; i
< _SWAP_STATE_MAX
; i
++)
7312 puts(swap_state_to_string(i
));
7315 puts("\nAvailable target unit substates:");
7316 for (i
= 0; i
< _TARGET_STATE_MAX
; i
++)
7317 puts(target_state_to_string(i
));
7320 puts("\nAvailable timer unit substates:");
7321 for (i
= 0; i
< _TIMER_STATE_MAX
; i
++)
7322 puts(timer_state_to_string(i
));
7325 static int systemctl_parse_argv(int argc
, char *argv
[]) {
7335 ARG_IGNORE_DEPENDENCIES
,
7348 ARG_NO_ASK_PASSWORD
,
7361 static const struct option options
[] = {
7362 { "help", no_argument
, NULL
, 'h' },
7363 { "version", no_argument
, NULL
, ARG_VERSION
},
7364 { "type", required_argument
, NULL
, 't' },
7365 { "property", required_argument
, NULL
, 'p' },
7366 { "all", no_argument
, NULL
, 'a' },
7367 { "reverse", no_argument
, NULL
, ARG_REVERSE
},
7368 { "after", no_argument
, NULL
, ARG_AFTER
},
7369 { "before", no_argument
, NULL
, ARG_BEFORE
},
7370 { "show-types", no_argument
, NULL
, ARG_SHOW_TYPES
},
7371 { "failed", no_argument
, NULL
, ARG_FAILED
}, /* compatibility only */
7372 { "full", no_argument
, NULL
, 'l' },
7373 { "job-mode", required_argument
, NULL
, ARG_JOB_MODE
},
7374 { "fail", no_argument
, NULL
, ARG_FAIL
}, /* compatibility only */
7375 { "irreversible", no_argument
, NULL
, ARG_IRREVERSIBLE
}, /* compatibility only */
7376 { "ignore-dependencies", no_argument
, NULL
, ARG_IGNORE_DEPENDENCIES
}, /* compatibility only */
7377 { "ignore-inhibitors", no_argument
, NULL
, 'i' },
7378 { "value", no_argument
, NULL
, ARG_VALUE
},
7379 { "user", no_argument
, NULL
, ARG_USER
},
7380 { "system", no_argument
, NULL
, ARG_SYSTEM
},
7381 { "global", no_argument
, NULL
, ARG_GLOBAL
},
7382 { "wait", no_argument
, NULL
, ARG_WAIT
},
7383 { "no-block", no_argument
, NULL
, ARG_NO_BLOCK
},
7384 { "no-legend", no_argument
, NULL
, ARG_NO_LEGEND
},
7385 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
7386 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7387 { "dry-run", no_argument
, NULL
, ARG_DRY_RUN
},
7388 { "quiet", no_argument
, NULL
, 'q' },
7389 { "root", required_argument
, NULL
, ARG_ROOT
},
7390 { "force", no_argument
, NULL
, 'f' },
7391 { "no-reload", no_argument
, NULL
, ARG_NO_RELOAD
},
7392 { "kill-who", required_argument
, NULL
, ARG_KILL_WHO
},
7393 { "signal", required_argument
, NULL
, 's' },
7394 { "no-ask-password", no_argument
, NULL
, ARG_NO_ASK_PASSWORD
},
7395 { "host", required_argument
, NULL
, 'H' },
7396 { "machine", required_argument
, NULL
, 'M' },
7397 { "runtime", no_argument
, NULL
, ARG_RUNTIME
},
7398 { "lines", required_argument
, NULL
, 'n' },
7399 { "output", required_argument
, NULL
, 'o' },
7400 { "plain", no_argument
, NULL
, ARG_PLAIN
},
7401 { "state", required_argument
, NULL
, ARG_STATE
},
7402 { "recursive", no_argument
, NULL
, 'r' },
7403 { "preset-mode", required_argument
, NULL
, ARG_PRESET_MODE
},
7404 { "firmware-setup", no_argument
, NULL
, ARG_FIRMWARE_SETUP
},
7405 { "now", no_argument
, NULL
, ARG_NOW
},
7406 { "message", required_argument
, NULL
, ARG_MESSAGE
},
7416 /* we default to allowing interactive authorization only in systemctl (not in the legacy commands) */
7417 arg_ask_password
= true;
7419 while ((c
= getopt_long(argc
, argv
, "ht:p:alqfs:H:M:n:o:ir", options
, NULL
)) >= 0)
7431 if (isempty(optarg
)) {
7432 log_error("--type= requires arguments.");
7436 for (p
= optarg
;;) {
7437 _cleanup_free_
char *type
= NULL
;
7439 r
= extract_first_word(&p
, &type
, ",", 0);
7441 return log_error_errno(r
, "Failed to parse type: %s", optarg
);
7445 if (streq(type
, "help")) {
7450 if (unit_type_from_string(type
) >= 0) {
7451 if (strv_push(&arg_types
, type
) < 0)
7457 /* It's much nicer to use --state= for
7458 * load states, but let's support this
7459 * in --types= too for compatibility
7460 * with old versions */
7461 if (unit_load_state_from_string(type
) >= 0) {
7462 if (strv_push(&arg_states
, type
) < 0)
7468 log_error("Unknown unit type or load state '%s'.", type
);
7469 log_info("Use -t help to see a list of allowed values.");
7477 /* Make sure that if the empty property list
7478 was specified, we won't show any properties. */
7479 if (isempty(optarg
) && !arg_properties
) {
7480 arg_properties
= new0(char*, 1);
7481 if (!arg_properties
)
7484 for (p
= optarg
;;) {
7485 _cleanup_free_
char *prop
= NULL
;
7487 r
= extract_first_word(&p
, &prop
, ",", 0);
7489 return log_error_errno(r
, "Failed to parse property: %s", optarg
);
7493 if (strv_push(&arg_properties
, prop
) < 0)
7499 /* If the user asked for a particular
7500 * property, show it to him, even if it is
7512 arg_dependency
= DEPENDENCY_REVERSE
;
7516 arg_dependency
= DEPENDENCY_AFTER
;
7517 arg_jobs_after
= true;
7521 arg_dependency
= DEPENDENCY_BEFORE
;
7522 arg_jobs_before
= true;
7525 case ARG_SHOW_TYPES
:
7526 arg_show_types
= true;
7534 arg_job_mode
= optarg
;
7538 arg_job_mode
= "fail";
7541 case ARG_IRREVERSIBLE
:
7542 arg_job_mode
= "replace-irreversibly";
7545 case ARG_IGNORE_DEPENDENCIES
:
7546 arg_job_mode
= "ignore-dependencies";
7550 arg_scope
= UNIT_FILE_USER
;
7554 arg_scope
= UNIT_FILE_SYSTEM
;
7558 arg_scope
= UNIT_FILE_GLOBAL
;
7566 arg_no_block
= true;
7570 arg_no_legend
= true;
7574 arg_no_pager
= true;
7582 r
= parse_path_argument_and_warn(optarg
, false, &arg_root
);
7592 if (strv_extend(&arg_states
, "failed") < 0)
7610 arg_no_reload
= true;
7614 arg_kill_who
= optarg
;
7618 arg_signal
= signal_from_string_try_harder(optarg
);
7619 if (arg_signal
< 0) {
7620 log_error("Failed to parse signal string %s.", optarg
);
7625 case ARG_NO_ASK_PASSWORD
:
7626 arg_ask_password
= false;
7630 arg_transport
= BUS_TRANSPORT_REMOTE
;
7635 arg_transport
= BUS_TRANSPORT_MACHINE
;
7644 if (safe_atou(optarg
, &arg_lines
) < 0) {
7645 log_error("Failed to parse lines '%s'", optarg
);
7651 arg_output
= output_mode_from_string(optarg
);
7652 if (arg_output
< 0) {
7653 log_error("Unknown output '%s'.", optarg
);
7659 arg_ignore_inhibitors
= true;
7666 case ARG_FIRMWARE_SETUP
:
7667 arg_firmware_setup
= true;
7671 if (isempty(optarg
)) {
7672 log_error("--state= requires arguments.");
7676 for (p
= optarg
;;) {
7677 _cleanup_free_
char *s
= NULL
;
7679 r
= extract_first_word(&p
, &s
, ",", 0);
7681 return log_error_errno(r
, "Failed to parse state: %s", optarg
);
7685 if (streq(s
, "help")) {
7690 if (strv_push(&arg_states
, s
) < 0)
7699 if (geteuid() != 0) {
7700 log_error("--recursive requires root privileges.");
7704 arg_recursive
= true;
7707 case ARG_PRESET_MODE
:
7709 arg_preset_mode
= unit_file_preset_mode_from_string(optarg
);
7710 if (arg_preset_mode
< 0) {
7711 log_error("Failed to parse preset mode: %s.", optarg
);
7722 if (strv_extend(&arg_wall
, optarg
) < 0)
7730 assert_not_reached("Unhandled option");
7733 if (arg_transport
!= BUS_TRANSPORT_LOCAL
&& arg_scope
!= UNIT_FILE_SYSTEM
) {
7734 log_error("Cannot access user instance remotely.");
7738 if (arg_wait
&& arg_no_block
) {
7739 log_error("--wait may not be combined with --no-block.");
7746 static int halt_parse_argv(int argc
, char *argv
[]) {
7755 static const struct option options
[] = {
7756 { "help", no_argument
, NULL
, ARG_HELP
},
7757 { "halt", no_argument
, NULL
, ARG_HALT
},
7758 { "poweroff", no_argument
, NULL
, 'p' },
7759 { "reboot", no_argument
, NULL
, ARG_REBOOT
},
7760 { "force", no_argument
, NULL
, 'f' },
7761 { "wtmp-only", no_argument
, NULL
, 'w' },
7762 { "no-wtmp", no_argument
, NULL
, 'd' },
7763 { "no-sync", no_argument
, NULL
, 'n' },
7764 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7773 if (utmp_get_runlevel(&runlevel
, NULL
) >= 0)
7774 if (IN_SET(runlevel
, '0', '6'))
7777 while ((c
= getopt_long(argc
, argv
, "pfwdnih", options
, NULL
)) >= 0)
7785 arg_action
= ACTION_HALT
;
7789 if (arg_action
!= ACTION_REBOOT
)
7790 arg_action
= ACTION_POWEROFF
;
7794 arg_action
= ACTION_REBOOT
;
7819 /* Compatibility nops */
7826 assert_not_reached("Unhandled option");
7829 if (arg_action
== ACTION_REBOOT
&& (argc
== optind
|| argc
== optind
+ 1)) {
7830 r
= update_reboot_parameter_and_warn(argc
== optind
+ 1 ? argv
[optind
] : NULL
);
7833 } else if (optind
< argc
) {
7834 log_error("Too many arguments.");
7841 static int parse_shutdown_time_spec(const char *t
, usec_t
*_u
) {
7845 if (streq(t
, "now"))
7847 else if (!strchr(t
, ':')) {
7850 if (safe_atou64(t
, &u
) < 0)
7853 *_u
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
* u
;
7862 hour
= strtol(t
, &e
, 10);
7863 if (errno
> 0 || *e
!= ':' || hour
< 0 || hour
> 23)
7866 minute
= strtol(e
+1, &e
, 10);
7867 if (errno
> 0 || *e
!= 0 || minute
< 0 || minute
> 59)
7870 n
= now(CLOCK_REALTIME
);
7871 s
= (time_t) (n
/ USEC_PER_SEC
);
7873 assert_se(localtime_r(&s
, &tm
));
7875 tm
.tm_hour
= (int) hour
;
7876 tm
.tm_min
= (int) minute
;
7879 assert_se(s
= mktime(&tm
));
7881 *_u
= (usec_t
) s
* USEC_PER_SEC
;
7884 *_u
+= USEC_PER_DAY
;
7890 static int shutdown_parse_argv(int argc
, char *argv
[]) {
7897 static const struct option options
[] = {
7898 { "help", no_argument
, NULL
, ARG_HELP
},
7899 { "halt", no_argument
, NULL
, 'H' },
7900 { "poweroff", no_argument
, NULL
, 'P' },
7901 { "reboot", no_argument
, NULL
, 'r' },
7902 { "kexec", no_argument
, NULL
, 'K' }, /* not documented extension */
7903 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7913 while ((c
= getopt_long(argc
, argv
, "HPrhkKat:fFc", options
, NULL
)) >= 0)
7921 arg_action
= ACTION_HALT
;
7925 arg_action
= ACTION_POWEROFF
;
7930 arg_action
= ACTION_KEXEC
;
7932 arg_action
= ACTION_REBOOT
;
7936 arg_action
= ACTION_KEXEC
;
7940 if (arg_action
!= ACTION_HALT
)
7941 arg_action
= ACTION_POWEROFF
;
7953 case 't': /* Note that we also ignore any passed argument to -t, not just the -t itself */
7956 /* Compatibility nops */
7960 arg_action
= ACTION_CANCEL_SHUTDOWN
;
7967 assert_not_reached("Unhandled option");
7970 if (argc
> optind
&& arg_action
!= ACTION_CANCEL_SHUTDOWN
) {
7971 r
= parse_shutdown_time_spec(argv
[optind
], &arg_when
);
7973 log_error("Failed to parse time specification: %s", argv
[optind
]);
7977 arg_when
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
;
7979 if (argc
> optind
&& arg_action
== ACTION_CANCEL_SHUTDOWN
)
7980 /* No time argument for shutdown cancel */
7981 wall
= argv
+ optind
;
7982 else if (argc
> optind
+ 1)
7983 /* We skip the time argument */
7984 wall
= argv
+ optind
+ 1;
7987 arg_wall
= strv_copy(wall
);
7997 static int telinit_parse_argv(int argc
, char *argv
[]) {
8004 static const struct option options
[] = {
8005 { "help", no_argument
, NULL
, ARG_HELP
},
8006 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
8010 static const struct {
8014 { '0', ACTION_POWEROFF
},
8015 { '6', ACTION_REBOOT
},
8016 { '1', ACTION_RESCUE
},
8017 { '2', ACTION_RUNLEVEL2
},
8018 { '3', ACTION_RUNLEVEL3
},
8019 { '4', ACTION_RUNLEVEL4
},
8020 { '5', ACTION_RUNLEVEL5
},
8021 { 's', ACTION_RESCUE
},
8022 { 'S', ACTION_RESCUE
},
8023 { 'q', ACTION_RELOAD
},
8024 { 'Q', ACTION_RELOAD
},
8025 { 'u', ACTION_REEXEC
},
8026 { 'U', ACTION_REEXEC
}
8035 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
8050 assert_not_reached("Unhandled option");
8053 if (optind
>= argc
) {
8054 log_error("%s: required argument missing.", program_invocation_short_name
);
8058 if (optind
+ 1 < argc
) {
8059 log_error("Too many arguments.");
8063 if (strlen(argv
[optind
]) != 1) {
8064 log_error("Expected single character argument.");
8068 for (i
= 0; i
< ELEMENTSOF(table
); i
++)
8069 if (table
[i
].from
== argv
[optind
][0])
8072 if (i
>= ELEMENTSOF(table
)) {
8073 log_error("Unknown command '%s'.", argv
[optind
]);
8077 arg_action
= table
[i
].to
;
8084 static int runlevel_parse_argv(int argc
, char *argv
[]) {
8090 static const struct option options
[] = {
8091 { "help", no_argument
, NULL
, ARG_HELP
},
8100 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
8111 assert_not_reached("Unhandled option");
8114 if (optind
< argc
) {
8115 log_error("Too many arguments.");
8122 static int parse_argv(int argc
, char *argv
[]) {
8126 if (program_invocation_short_name
) {
8128 if (strstr(program_invocation_short_name
, "halt")) {
8129 arg_action
= ACTION_HALT
;
8130 return halt_parse_argv(argc
, argv
);
8132 } else if (strstr(program_invocation_short_name
, "poweroff")) {
8133 arg_action
= ACTION_POWEROFF
;
8134 return halt_parse_argv(argc
, argv
);
8136 } else if (strstr(program_invocation_short_name
, "reboot")) {
8138 arg_action
= ACTION_KEXEC
;
8140 arg_action
= ACTION_REBOOT
;
8141 return halt_parse_argv(argc
, argv
);
8143 } else if (strstr(program_invocation_short_name
, "shutdown")) {
8144 arg_action
= ACTION_POWEROFF
;
8145 return shutdown_parse_argv(argc
, argv
);
8147 } else if (strstr(program_invocation_short_name
, "init")) {
8149 /* Matches invocations as "init" as well as "telinit", which are synonymous when run as PID !=
8152 * On SysV "telinit" was the official command to communicate with PID 1, but "init" would
8153 * redirect itself to "telinit" if called with PID != 1. We follow the same logic here still,
8154 * though we add one level of indirection, as we implement "telinit" in "systemctl". Hence, for
8155 * us if you invoke "init" you get "systemd", but it will execve() "systemctl" immediately with
8156 * argv[] unmodified if PID is != 1. If you invoke "telinit" you directly get "systemctl". In
8157 * both cases we shall do the same thing, which is why we do strstr(p_i_s_n, "init") here, as a
8158 * quick way to match both.
8160 * Also see redirect_telinit() in src/core/main.c. */
8162 if (sd_booted() > 0) {
8163 arg_action
= _ACTION_INVALID
;
8164 return telinit_parse_argv(argc
, argv
);
8166 /* Hmm, so some other init system is running, we need to forward this request to
8167 * it. For now we simply guess that it is Upstart. */
8169 execv(TELINIT
, argv
);
8171 log_error("Couldn't find an alternative telinit implementation to spawn.");
8175 } else if (strstr(program_invocation_short_name
, "runlevel")) {
8176 arg_action
= ACTION_RUNLEVEL
;
8177 return runlevel_parse_argv(argc
, argv
);
8181 arg_action
= ACTION_SYSTEMCTL
;
8182 return systemctl_parse_argv(argc
, argv
);
8185 #if HAVE_SYSV_COMPAT
8186 _pure_
static int action_to_runlevel(void) {
8188 static const char table
[_ACTION_MAX
] = {
8189 [ACTION_HALT
] = '0',
8190 [ACTION_POWEROFF
] = '0',
8191 [ACTION_REBOOT
] = '6',
8192 [ACTION_RUNLEVEL2
] = '2',
8193 [ACTION_RUNLEVEL3
] = '3',
8194 [ACTION_RUNLEVEL4
] = '4',
8195 [ACTION_RUNLEVEL5
] = '5',
8196 [ACTION_RESCUE
] = '1'
8199 assert(arg_action
>= 0 && arg_action
< _ACTION_MAX
);
8201 return table
[arg_action
];
8205 static int talk_initctl(void) {
8206 #if HAVE_SYSV_COMPAT
8207 struct init_request request
= {
8208 .magic
= INIT_MAGIC
,
8210 .cmd
= INIT_CMD_RUNLVL
8213 _cleanup_close_
int fd
= -1;
8218 rl
= action_to_runlevel();
8222 request
.runlevel
= rl
;
8224 FOREACH_STRING(p
, "/run/initctl", "/dev/initctl") {
8225 fd
= open(p
, O_WRONLY
|O_NONBLOCK
|O_CLOEXEC
|O_NOCTTY
);
8226 if (fd
>= 0 || errno
!= ENOENT
)
8230 if (errno
== ENOENT
)
8233 return log_error_errno(errno
, "Failed to open initctl fifo: %m");
8236 r
= loop_write(fd
, &request
, sizeof(request
), false);
8238 return log_error_errno(r
, "Failed to write to %s: %m", p
);
8246 static int systemctl_main(int argc
, char *argv
[]) {
8248 static const Verb verbs
[] = {
8249 { "list-units", VERB_ANY
, VERB_ANY
, VERB_DEFAULT
|VERB_ONLINE_ONLY
, list_units
},
8250 { "list-unit-files", VERB_ANY
, VERB_ANY
, 0, list_unit_files
},
8251 { "list-sockets", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, list_sockets
},
8252 { "list-timers", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, list_timers
},
8253 { "list-jobs", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, list_jobs
},
8254 { "list-machines", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
|VERB_MUST_BE_ROOT
, list_machines
},
8255 { "clear-jobs", VERB_ANY
, 1, VERB_ONLINE_ONLY
, trivial_method
},
8256 { "cancel", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, cancel_job
},
8257 { "start", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8258 { "stop", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8259 { "condstop", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
}, /* For compatibility with ALTLinux */
8260 { "reload", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8261 { "restart", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8262 { "try-restart", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8263 { "reload-or-restart", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8264 { "reload-or-try-restart", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
}, /* For compatbility with old systemctl <= 228 */
8265 { "try-reload-or-restart", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8266 { "force-reload", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
}, /* For compatibility with SysV */
8267 { "condreload", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
}, /* For compatibility with ALTLinux */
8268 { "condrestart", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
}, /* For compatibility with RH */
8269 { "isolate", 2, 2, VERB_ONLINE_ONLY
, start_unit
},
8270 { "kill", 2, VERB_ANY
, VERB_ONLINE_ONLY
, kill_unit
},
8271 { "is-active", 2, VERB_ANY
, VERB_ONLINE_ONLY
, check_unit_active
},
8272 { "check", 2, VERB_ANY
, VERB_ONLINE_ONLY
, check_unit_active
}, /* deprecated alias of is-active */
8273 { "is-failed", 2, VERB_ANY
, VERB_ONLINE_ONLY
, check_unit_failed
},
8274 { "show", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, show
},
8275 { "cat", 2, VERB_ANY
, VERB_ONLINE_ONLY
, cat
},
8276 { "status", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, show
},
8277 { "help", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, show
},
8278 { "daemon-reload", VERB_ANY
, 1, VERB_ONLINE_ONLY
, daemon_reload
},
8279 { "daemon-reexec", VERB_ANY
, 1, VERB_ONLINE_ONLY
, daemon_reload
},
8280 { "show-environment", VERB_ANY
, 1, VERB_ONLINE_ONLY
, show_environment
},
8281 { "set-environment", 2, VERB_ANY
, VERB_ONLINE_ONLY
, set_environment
},
8282 { "unset-environment", 2, VERB_ANY
, VERB_ONLINE_ONLY
, set_environment
},
8283 { "import-environment", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, import_environment
},
8284 { "halt", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8285 { "poweroff", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8286 { "reboot", VERB_ANY
, 2, VERB_ONLINE_ONLY
, start_system_special
},
8287 { "kexec", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8288 { "suspend", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8289 { "hibernate", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8290 { "hybrid-sleep", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8291 { "suspend-then-hibernate",VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8292 { "default", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_special
},
8293 { "rescue", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8294 { "emergency", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8295 { "exit", VERB_ANY
, 2, VERB_ONLINE_ONLY
, start_special
},
8296 { "reset-failed", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, reset_failed
},
8297 { "enable", 2, VERB_ANY
, 0, enable_unit
},
8298 { "disable", 2, VERB_ANY
, 0, enable_unit
},
8299 { "is-enabled", 2, VERB_ANY
, 0, unit_is_enabled
},
8300 { "reenable", 2, VERB_ANY
, 0, enable_unit
},
8301 { "preset", 2, VERB_ANY
, 0, enable_unit
},
8302 { "preset-all", VERB_ANY
, 1, 0, preset_all
},
8303 { "mask", 2, VERB_ANY
, 0, enable_unit
},
8304 { "unmask", 2, VERB_ANY
, 0, enable_unit
},
8305 { "link", 2, VERB_ANY
, 0, enable_unit
},
8306 { "revert", 2, VERB_ANY
, 0, enable_unit
},
8307 { "switch-root", 2, VERB_ANY
, VERB_ONLINE_ONLY
, switch_root
},
8308 { "list-dependencies", VERB_ANY
, 2, VERB_ONLINE_ONLY
, list_dependencies
},
8309 { "set-default", 2, 2, 0, set_default
},
8310 { "get-default", VERB_ANY
, 1, 0, get_default
},
8311 { "set-property", 3, VERB_ANY
, VERB_ONLINE_ONLY
, set_property
},
8312 { "is-system-running", VERB_ANY
, 1, 0, is_system_running
},
8313 { "add-wants", 3, VERB_ANY
, 0, add_dependency
},
8314 { "add-requires", 3, VERB_ANY
, 0, add_dependency
},
8315 { "edit", 2, VERB_ANY
, VERB_ONLINE_ONLY
, edit
},
8319 return dispatch_verb(argc
, argv
, verbs
, NULL
);
8322 static int reload_with_fallback(void) {
8324 /* First, try systemd via D-Bus. */
8325 if (daemon_reload(0, NULL
, NULL
) >= 0)
8328 /* Nothing else worked, so let's try signals */
8329 assert(IN_SET(arg_action
, ACTION_RELOAD
, ACTION_REEXEC
));
8331 if (kill(1, arg_action
== ACTION_RELOAD
? SIGHUP
: SIGTERM
) < 0)
8332 return log_error_errno(errno
, "kill() failed: %m");
8337 static int start_with_fallback(void) {
8339 /* First, try systemd via D-Bus. */
8340 if (start_unit(0, NULL
, NULL
) >= 0)
8343 /* Nothing else worked, so let's try /dev/initctl */
8344 if (talk_initctl() > 0)
8347 log_error("Failed to talk to init daemon.");
8351 static int halt_now(enum action a
) {
8353 /* The kernel will automatically flush ATA disks and suchlike on reboot(), but the file systems need to be
8354 * synce'd explicitly in advance. */
8355 if (!arg_no_sync
&& !arg_dry_run
)
8358 /* Make sure C-A-D is handled by the kernel from this point on... */
8360 (void) reboot(RB_ENABLE_CAD
);
8366 log_info("Halting.");
8369 (void) reboot(RB_HALT_SYSTEM
);
8372 case ACTION_POWEROFF
:
8374 log_info("Powering off.");
8377 (void) reboot(RB_POWER_OFF
);
8382 return reboot_with_parameter(REBOOT_FALLBACK
|
8383 (arg_quiet
? 0 : REBOOT_LOG
) |
8384 (arg_dry_run
? REBOOT_DRY_RUN
: 0));
8387 assert_not_reached("Unknown action.");
8391 static int logind_schedule_shutdown(void) {
8394 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
8395 char date
[FORMAT_TIMESTAMP_MAX
];
8400 r
= acquire_bus(BUS_FULL
, &bus
);
8404 switch (arg_action
) {
8408 case ACTION_POWEROFF
:
8409 action
= "poweroff";
8424 action
= strjoina("dry-", action
);
8426 (void) logind_set_wall_message();
8428 r
= sd_bus_call_method(
8430 "org.freedesktop.login1",
8431 "/org/freedesktop/login1",
8432 "org.freedesktop.login1.Manager",
8440 return log_warning_errno(r
, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s", bus_error_message(&error
, r
));
8443 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.", format_timestamp(date
, sizeof(date
), arg_when
));
8446 log_error("Cannot schedule shutdown without logind support, proceeding with immediate shutdown.");
8451 static int halt_main(void) {
8454 r
= logind_check_inhibitors(arg_action
);
8459 return logind_schedule_shutdown();
8461 if (geteuid() != 0) {
8462 if (arg_dry_run
|| arg_force
> 0) {
8463 (void) must_be_root();
8467 /* Try logind if we are a normal user and no special
8468 * mode applies. Maybe PolicyKit allows us to shutdown
8470 if (IN_SET(arg_action
, ACTION_POWEROFF
, ACTION_REBOOT
, ACTION_HALT
)) {
8471 r
= logind_reboot(arg_action
);
8474 if (IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
8475 /* requested operation is not
8476 * supported on the local system or
8477 * already in progress */
8479 /* on all other errors, try low-level operation */
8483 if (!arg_dry_run
&& !arg_force
)
8484 return start_with_fallback();
8486 assert(geteuid() == 0);
8489 if (sd_booted() > 0)
8490 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
8492 r
= utmp_put_shutdown();
8494 log_warning_errno(r
, "Failed to write utmp record: %m");
8501 r
= halt_now(arg_action
);
8502 return log_error_errno(r
, "Failed to reboot: %m");
8505 static int runlevel_main(void) {
8506 int r
, runlevel
, previous
;
8508 r
= utmp_get_runlevel(&runlevel
, &previous
);
8515 previous
<= 0 ? 'N' : previous
,
8516 runlevel
<= 0 ? 'N' : runlevel
);
8521 static int logind_cancel_shutdown(void) {
8523 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
8527 r
= acquire_bus(BUS_FULL
, &bus
);
8531 (void) logind_set_wall_message();
8533 r
= sd_bus_call_method(
8535 "org.freedesktop.login1",
8536 "/org/freedesktop/login1",
8537 "org.freedesktop.login1.Manager",
8538 "CancelScheduledShutdown",
8542 return log_warning_errno(r
, "Failed to talk to logind, shutdown hasn't been cancelled: %s", bus_error_message(&error
, r
));
8546 log_error("Not compiled with logind support, cannot cancel scheduled shutdowns.");
8551 int main(int argc
, char*argv
[]) {
8554 argv_cmdline
= argv
[0];
8556 setlocale(LC_ALL
, "");
8557 log_parse_environment();
8561 /* Explicitly not on_tty() to avoid setting cached value.
8562 * This becomes relevant for piping output which might be
8564 original_stdout_is_tty
= isatty(STDOUT_FILENO
);
8566 r
= parse_argv(argc
, argv
);
8570 if (arg_action
!= ACTION_SYSTEMCTL
&& running_in_chroot() > 0) {
8573 log_info("Running in chroot, ignoring request.");
8578 /* systemctl_main() will print an error message for the bus
8579 * connection, but only if it needs to */
8581 switch (arg_action
) {
8583 case ACTION_SYSTEMCTL
:
8584 r
= systemctl_main(argc
, argv
);
8587 /* Legacy command aliases set arg_action. They provide some fallbacks,
8588 * e.g. to tell sysvinit to reboot after you have installed systemd
8592 case ACTION_POWEROFF
:
8598 case ACTION_RUNLEVEL2
:
8599 case ACTION_RUNLEVEL3
:
8600 case ACTION_RUNLEVEL4
:
8601 case ACTION_RUNLEVEL5
:
8603 r
= start_with_fallback();
8608 r
= reload_with_fallback();
8611 case ACTION_CANCEL_SHUTDOWN
:
8612 r
= logind_cancel_shutdown();
8615 case ACTION_RUNLEVEL
:
8616 r
= runlevel_main();
8620 case ACTION_SUSPEND
:
8621 case ACTION_HIBERNATE
:
8622 case ACTION_HYBRID_SLEEP
:
8623 case ACTION_SUSPEND_THEN_HIBERNATE
:
8624 case ACTION_EMERGENCY
:
8625 case ACTION_DEFAULT
:
8626 /* systemctl verbs with no equivalent in the legacy commands.
8627 * These cannot appear in arg_action. Fall through. */
8629 case _ACTION_INVALID
:
8631 assert_not_reached("Unknown action");
8638 ask_password_agent_close();
8639 polkit_agent_close();
8641 strv_free(arg_types
);
8642 strv_free(arg_states
);
8643 strv_free(arg_properties
);
8645 strv_free(arg_wall
);
8649 /* Note that we return r here, not EXIT_SUCCESS, so that we can implement the LSB-like return codes */
8650 return r
< 0 ? EXIT_FAILURE
: r
;