1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2010 Lennart Poettering
6 Copyright 2013 Marc-Antoine Perennou
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
30 #include <sys/prctl.h>
31 #include <sys/reboot.h>
32 #include <sys/socket.h>
36 #include "sd-daemon.h"
39 #include "alloc-util.h"
41 #include "bus-common-errors.h"
42 #include "bus-error.h"
43 #include "bus-message.h"
44 #include "bus-unit-util.h"
46 #include "cgroup-show.h"
47 #include "cgroup-util.h"
53 #include "exit-status.h"
56 #include "format-util.h"
58 #include "glob-util.h"
59 #include "hexdecoct.h"
60 #include "hostname-util.h"
65 #include "locale-util.h"
67 #include "logs-show.h"
71 #include "parse-util.h"
72 #include "path-lookup.h"
73 #include "path-util.h"
74 #include "process-util.h"
75 #include "reboot-util.h"
76 #include "rlimit-util.h"
79 #include "signal-util.h"
80 #include "socket-util.h"
81 #include "spawn-ask-password-agent.h"
82 #include "spawn-polkit-agent.h"
84 #include "stat-util.h"
85 #include "string-table.h"
87 #include "terminal-util.h"
89 #include "unit-name.h"
90 #include "user-util.h"
92 #include "utmp-wtmp.h"
96 /* The init script exit status codes
97 0 program is running or service is OK
98 1 program is dead and /var/run pid file exists
99 2 program is dead and /var/lock lock file exists
100 3 program is not running
101 4 program or service status is unknown
102 5-99 reserved for future LSB use
103 100-149 reserved for distribution use
104 150-199 reserved for application use
108 EXIT_PROGRAM_RUNNING_OR_SERVICE_OK
= 0,
109 EXIT_PROGRAM_DEAD_AND_PID_EXISTS
= 1,
110 EXIT_PROGRAM_DEAD_AND_LOCK_FILE_EXISTS
= 2,
111 EXIT_PROGRAM_NOT_RUNNING
= 3,
112 EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN
= 4,
115 static char **arg_types
= NULL
;
116 static char **arg_states
= NULL
;
117 static char **arg_properties
= NULL
;
118 static bool arg_all
= false;
119 static enum dependency
{
125 } arg_dependency
= DEPENDENCY_FORWARD
;
126 static const char *arg_job_mode
= "replace";
127 static UnitFileScope arg_scope
= UNIT_FILE_SYSTEM
;
128 static bool arg_wait
= false;
129 static bool arg_no_block
= false;
130 static bool arg_no_legend
= false;
131 static bool arg_no_pager
= false;
132 static bool arg_no_wtmp
= false;
133 static bool arg_no_sync
= false;
134 static bool arg_no_wall
= false;
135 static bool arg_no_reload
= false;
136 static bool arg_value
= false;
137 static bool arg_show_types
= false;
138 static bool arg_ignore_inhibitors
= false;
139 static bool arg_dry_run
= false;
140 static bool arg_quiet
= false;
141 static bool arg_full
= false;
142 static bool arg_recursive
= false;
143 static int arg_force
= 0;
144 static bool arg_ask_password
= false;
145 static bool arg_runtime
= false;
146 static UnitFilePresetMode arg_preset_mode
= UNIT_FILE_PRESET_FULL
;
147 static char **arg_wall
= NULL
;
148 static const char *arg_kill_who
= NULL
;
149 static int arg_signal
= SIGTERM
;
150 static char *arg_root
= NULL
;
151 static usec_t arg_when
= 0;
152 static char *arg_esp_path
= NULL
;
153 static char *argv_cmdline
= NULL
;
164 ACTION_SUSPEND_TO_HIBERNATE
,
175 ACTION_CANCEL_SHUTDOWN
,
178 } arg_action
= ACTION_SYSTEMCTL
;
179 static BusTransport arg_transport
= BUS_TRANSPORT_LOCAL
;
180 static const char *arg_host
= NULL
;
181 static unsigned arg_lines
= 10;
182 static OutputMode arg_output
= OUTPUT_SHORT
;
183 static bool arg_plain
= false;
184 static bool arg_firmware_setup
= false;
185 static bool arg_now
= false;
186 static bool arg_jobs_before
= false;
187 static bool arg_jobs_after
= false;
189 static int daemon_reload(int argc
, char *argv
[], void* userdata
);
190 static int trivial_method(int argc
, char *argv
[], void *userdata
);
191 static int halt_now(enum action a
);
192 static int get_state_one_unit(sd_bus
*bus
, const char *name
, UnitActiveState
*active_state
);
194 static bool original_stdout_is_tty
;
196 typedef enum BusFocus
{
197 BUS_FULL
, /* The full bus indicated via --system or --user */
198 BUS_MANAGER
, /* The manager itself, possibly directly, possibly via the bus */
202 static sd_bus
*busses
[_BUS_FOCUS_MAX
] = {};
204 static UnitFileFlags
args_to_flags(void) {
205 return (arg_runtime
? UNIT_FILE_RUNTIME
: 0) |
206 (arg_force
? UNIT_FILE_FORCE
: 0);
209 static int acquire_bus(BusFocus focus
, sd_bus
**ret
) {
212 assert(focus
< _BUS_FOCUS_MAX
);
215 /* We only go directly to the manager, if we are using a local transport */
216 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
219 if (getenv_bool("SYSTEMCTL_FORCE_BUS") > 0)
222 if (!busses
[focus
]) {
225 user
= arg_scope
!= UNIT_FILE_SYSTEM
;
227 if (!user
&& sd_booted() <= 0) {
228 /* Print a friendly message when the local system is actually not running systemd as PID 1. */
229 log_error("System has not been booted with systemd as init system (PID 1). Can't operate.");
233 if (focus
== BUS_MANAGER
)
234 r
= bus_connect_transport_systemd(arg_transport
, arg_host
, user
, &busses
[focus
]);
236 r
= bus_connect_transport(arg_transport
, arg_host
, user
, &busses
[focus
]);
238 return log_error_errno(r
, "Failed to connect to bus: %m");
240 (void) sd_bus_set_allow_interactive_authorization(busses
[focus
], arg_ask_password
);
243 *ret
= busses
[focus
];
247 static void release_busses(void) {
250 for (w
= 0; w
< _BUS_FOCUS_MAX
; w
++)
251 busses
[w
] = sd_bus_flush_close_unref(busses
[w
]);
254 static void ask_password_agent_open_if_enabled(void) {
256 /* Open the password agent as a child process if necessary */
261 if (!arg_ask_password
)
264 if (arg_scope
!= UNIT_FILE_SYSTEM
)
267 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
270 ask_password_agent_open();
273 static void polkit_agent_open_maybe(void) {
274 /* Open the polkit agent as a child process if necessary */
276 if (arg_scope
!= UNIT_FILE_SYSTEM
)
279 polkit_agent_open_if_enabled(arg_transport
, arg_ask_password
);
282 static OutputFlags
get_output_flags(void) {
284 arg_all
* OUTPUT_SHOW_ALL
|
285 (arg_full
|| !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH
|
286 colors_enabled() * OUTPUT_COLOR
|
287 !arg_quiet
* OUTPUT_WARN_CUTOFF
;
290 static int translate_bus_error_to_exit_status(int r
, const sd_bus_error
*error
) {
293 if (!sd_bus_error_is_set(error
))
296 if (sd_bus_error_has_name(error
, SD_BUS_ERROR_ACCESS_DENIED
) ||
297 sd_bus_error_has_name(error
, BUS_ERROR_ONLY_BY_DEPENDENCY
) ||
298 sd_bus_error_has_name(error
, BUS_ERROR_NO_ISOLATION
) ||
299 sd_bus_error_has_name(error
, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE
))
300 return EXIT_NOPERMISSION
;
302 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
))
303 return EXIT_NOTINSTALLED
;
305 if (sd_bus_error_has_name(error
, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE
) ||
306 sd_bus_error_has_name(error
, SD_BUS_ERROR_NOT_SUPPORTED
))
307 return EXIT_NOTIMPLEMENTED
;
309 if (sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
))
310 return EXIT_NOTCONFIGURED
;
318 static bool install_client_side(void) {
320 /* Decides when to execute enable/disable/... operations
321 * client-side rather than server-side. */
323 if (running_in_chroot_or_offline())
326 if (sd_booted() <= 0)
329 if (!isempty(arg_root
))
332 if (arg_scope
== UNIT_FILE_GLOBAL
)
335 /* Unsupported environment variable, mostly for debugging purposes */
336 if (getenv_bool("SYSTEMCTL_INSTALL_CLIENT_SIDE") > 0)
342 static int compare_unit_info(const void *a
, const void *b
) {
343 const UnitInfo
*u
= a
, *v
= b
;
347 /* First, order by machine */
348 if (!u
->machine
&& v
->machine
)
350 if (u
->machine
&& !v
->machine
)
352 if (u
->machine
&& v
->machine
) {
353 r
= strcasecmp(u
->machine
, v
->machine
);
358 /* Second, order by unit type */
359 d1
= strrchr(u
->id
, '.');
360 d2
= strrchr(v
->id
, '.');
362 r
= strcasecmp(d1
, d2
);
367 /* Third, order by name */
368 return strcasecmp(u
->id
, v
->id
);
371 static const char* unit_type_suffix(const char *name
) {
374 dot
= strrchr(name
, '.');
381 static bool output_show_unit(const UnitInfo
*u
, char **patterns
) {
384 if (!strv_fnmatch_or_empty(patterns
, u
->id
, FNM_NOESCAPE
))
387 if (arg_types
&& !strv_find(arg_types
, unit_type_suffix(u
->id
)))
393 /* Note that '--all' is not purely a state filter, but also a
394 * filter that hides units that "follow" other units (which is
395 * used for device units that appear under different names). */
396 if (!isempty(u
->following
))
399 if (!strv_isempty(arg_states
))
402 /* By default show all units except the ones in inactive
403 * state and with no pending job */
407 if (streq(u
->active_state
, "inactive"))
413 static int output_units_list(const UnitInfo
*unit_infos
, unsigned c
) {
414 unsigned circle_len
= 0, id_len
, max_id_len
, load_len
, active_len
, sub_len
, job_len
, desc_len
, max_desc_len
;
416 unsigned n_shown
= 0;
419 max_id_len
= STRLEN("UNIT");
420 load_len
= STRLEN("LOAD");
421 active_len
= STRLEN("ACTIVE");
422 sub_len
= STRLEN("SUB");
423 job_len
= STRLEN("JOB");
424 max_desc_len
= STRLEN("DESCRIPTION");
426 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
427 max_id_len
= MAX(max_id_len
, strlen(u
->id
) + (u
->machine
? strlen(u
->machine
)+1 : 0));
428 load_len
= MAX(load_len
, strlen(u
->load_state
));
429 active_len
= MAX(active_len
, strlen(u
->active_state
));
430 sub_len
= MAX(sub_len
, strlen(u
->sub_state
));
431 max_desc_len
= MAX(max_desc_len
, strlen(u
->description
));
433 if (u
->job_id
!= 0) {
434 job_len
= MAX(job_len
, strlen(u
->job_type
));
438 if (!arg_no_legend
&&
439 (streq(u
->active_state
, "failed") ||
440 STR_IN_SET(u
->load_state
, "error", "not-found", "masked")))
444 if (!arg_full
&& original_stdout_is_tty
) {
447 id_len
= MIN(max_id_len
, 25u); /* as much as it needs, but at most 25 for now */
448 basic_len
= circle_len
+ 1 + id_len
+ 1 + load_len
+ 1 + active_len
+ 1 + sub_len
+ 1;
451 basic_len
+= job_len
+ 1;
453 if (basic_len
< (unsigned) columns()) {
454 unsigned extra_len
, incr
;
455 extra_len
= columns() - basic_len
;
457 /* Either UNIT already got 25, or is fully satisfied.
458 * Grant up to 25 to DESC now. */
459 incr
= MIN(extra_len
, 25u);
463 /* Of the remainder give as much as the ID needs to the ID, and give the rest to the
464 * description but not more than it needs. */
466 incr
= MIN(max_id_len
- id_len
, extra_len
);
468 desc_len
+= MIN(extra_len
- incr
, max_desc_len
- desc_len
);
474 desc_len
= max_desc_len
;
477 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
478 _cleanup_free_
char *e
= NULL
, *j
= NULL
;
479 const char *on_underline
= "", *off_underline
= "";
480 const char *on_loaded
= "", *off_loaded
= "";
481 const char *on_active
= "", *off_active
= "";
482 const char *on_circle
= "", *off_circle
= "";
484 bool circle
= false, underline
= false;
486 if (!n_shown
&& !arg_no_legend
) {
491 printf("%s%-*s %-*s %-*s %-*s ",
495 active_len
, "ACTIVE",
499 printf("%-*s ", job_len
, "JOB");
503 !arg_full
&& arg_no_pager
? (int) desc_len
: -1,
510 if (u
+ 1 < unit_infos
+ c
&&
511 !streq(unit_type_suffix(u
->id
), unit_type_suffix((u
+ 1)->id
))) {
512 on_underline
= ansi_underline();
513 off_underline
= ansi_normal();
517 if (STR_IN_SET(u
->load_state
, "error", "not-found", "masked") && !arg_plain
) {
518 on_circle
= ansi_highlight_yellow();
519 off_circle
= ansi_normal();
521 on_loaded
= underline
? ansi_highlight_red_underline() : ansi_highlight_red();
522 off_loaded
= underline
? on_underline
: ansi_normal();
523 } else if (streq(u
->active_state
, "failed") && !arg_plain
) {
524 on_circle
= ansi_highlight_red();
525 off_circle
= ansi_normal();
527 on_active
= underline
? ansi_highlight_red_underline() : ansi_highlight_red();
528 off_active
= underline
? on_underline
: ansi_normal();
532 j
= strjoin(u
->machine
, ":", u
->id
);
541 e
= ellipsize(id
, id_len
, 33);
549 printf("%s%s%s ", on_circle
, circle
? special_glyph(BLACK_CIRCLE
) : " ", off_circle
);
551 printf("%s%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
553 on_active
, id_len
, id
, off_active
,
554 on_loaded
, load_len
, u
->load_state
, off_loaded
,
555 on_active
, active_len
, u
->active_state
,
556 sub_len
, u
->sub_state
, off_active
,
557 job_count
? job_len
+ 1 : 0, u
->job_id
? u
->job_type
: "");
561 !arg_full
&& arg_no_pager
? (int) desc_len
: -1,
566 if (!arg_no_legend
) {
567 const char *on
, *off
;
571 "LOAD = Reflects whether the unit definition was properly loaded.\n"
572 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
573 "SUB = The low-level unit activation state, values depend on unit type.");
574 puts(job_count
? "JOB = Pending job for the unit.\n" : "");
575 on
= ansi_highlight();
578 on
= ansi_highlight_red();
583 printf("%s%u loaded units listed.%s\n"
584 "To show all installed unit files use 'systemctl list-unit-files'.\n",
587 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
588 "To show all installed unit files use 'systemctl list-unit-files'.\n",
595 static int get_unit_list(
599 UnitInfo
**unit_infos
,
601 sd_bus_message
**_reply
) {
603 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
604 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
605 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
609 bool fallback
= false;
615 r
= sd_bus_message_new_method_call(
618 "org.freedesktop.systemd1",
619 "/org/freedesktop/systemd1",
620 "org.freedesktop.systemd1.Manager",
621 "ListUnitsByPatterns");
623 return bus_log_create_error(r
);
625 r
= sd_bus_message_append_strv(m
, arg_states
);
627 return bus_log_create_error(r
);
629 r
= sd_bus_message_append_strv(m
, patterns
);
631 return bus_log_create_error(r
);
633 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
634 if (r
< 0 && (sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_METHOD
) ||
635 sd_bus_error_has_name(&error
, SD_BUS_ERROR_ACCESS_DENIED
))) {
636 /* Fallback to legacy ListUnitsFiltered method */
638 log_debug_errno(r
, "Failed to list units: %s Falling back to ListUnitsFiltered method.", bus_error_message(&error
, r
));
639 m
= sd_bus_message_unref(m
);
640 sd_bus_error_free(&error
);
642 r
= sd_bus_message_new_method_call(
645 "org.freedesktop.systemd1",
646 "/org/freedesktop/systemd1",
647 "org.freedesktop.systemd1.Manager",
648 "ListUnitsFiltered");
650 return bus_log_create_error(r
);
652 r
= sd_bus_message_append_strv(m
, arg_states
);
654 return bus_log_create_error(r
);
656 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
659 return log_error_errno(r
, "Failed to list units: %s", bus_error_message(&error
, r
));
661 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssssouso)");
663 return bus_log_parse_error(r
);
665 while ((r
= bus_parse_unit_info(reply
, &u
)) > 0) {
668 if (!output_show_unit(&u
, fallback
? patterns
: NULL
))
671 if (!GREEDY_REALLOC(*unit_infos
, size
, c
+1))
674 (*unit_infos
)[c
++] = u
;
677 return bus_log_parse_error(r
);
679 r
= sd_bus_message_exit_container(reply
);
681 return bus_log_parse_error(r
);
689 static void message_set_freep(Set
**set
) {
690 set_free_with_destructor(*set
, sd_bus_message_unref
);
693 static int get_unit_list_recursive(
696 UnitInfo
**_unit_infos
,
700 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
701 _cleanup_(message_set_freep
) Set
*replies
;
702 sd_bus_message
*reply
;
710 replies
= set_new(NULL
);
714 c
= get_unit_list(bus
, NULL
, patterns
, &unit_infos
, 0, &reply
);
718 r
= set_put(replies
, reply
);
720 sd_bus_message_unref(reply
);
725 _cleanup_strv_free_
char **machines
= NULL
;
728 r
= sd_get_machine_names(&machines
);
730 return log_error_errno(r
, "Failed to get machine names: %m");
732 STRV_FOREACH(i
, machines
) {
733 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*container
= NULL
;
736 r
= sd_bus_open_system_machine(&container
, *i
);
738 log_warning_errno(r
, "Failed to connect to container %s, ignoring: %m", *i
);
742 k
= get_unit_list(container
, *i
, patterns
, &unit_infos
, c
, &reply
);
748 r
= set_put(replies
, reply
);
750 sd_bus_message_unref(reply
);
755 *_machines
= machines
;
760 *_unit_infos
= unit_infos
;
769 static int list_units(int argc
, char *argv
[], void *userdata
) {
770 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
771 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
772 _cleanup_strv_free_
char **machines
= NULL
;
776 r
= acquire_bus(BUS_MANAGER
, &bus
);
780 (void) pager_open(arg_no_pager
, false);
782 r
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
786 qsort_safe(unit_infos
, r
, sizeof(UnitInfo
), compare_unit_info
);
787 return output_units_list(unit_infos
, r
);
790 static int get_triggered_units(
795 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
802 r
= sd_bus_get_property_strv(
804 "org.freedesktop.systemd1",
806 "org.freedesktop.systemd1.Unit",
811 return log_error_errno(r
, "Failed to determine triggers: %s", bus_error_message(&error
, r
));
816 static int get_listening(
818 const char* unit_path
,
821 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
822 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
823 const char *type
, *path
;
826 r
= sd_bus_get_property(
828 "org.freedesktop.systemd1",
830 "org.freedesktop.systemd1.Socket",
836 return log_error_errno(r
, "Failed to get list of listening sockets: %s", bus_error_message(&error
, r
));
838 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
840 return bus_log_parse_error(r
);
842 while ((r
= sd_bus_message_read(reply
, "(ss)", &type
, &path
)) > 0) {
844 r
= strv_extend(listening
, type
);
848 r
= strv_extend(listening
, path
);
855 return bus_log_parse_error(r
);
857 r
= sd_bus_message_exit_container(reply
);
859 return bus_log_parse_error(r
);
871 /* Note: triggered is a list here, although it almost certainly
872 * will always be one unit. Nevertheless, dbus API allows for multiple
873 * values, so let's follow that. */
876 /* The strv above is shared. free is set only in the first one. */
880 static int socket_info_compare(const struct socket_info
*a
, const struct socket_info
*b
) {
886 if (!a
->machine
&& b
->machine
)
888 if (a
->machine
&& !b
->machine
)
890 if (a
->machine
&& b
->machine
) {
891 o
= strcasecmp(a
->machine
, b
->machine
);
896 o
= strcmp(a
->path
, b
->path
);
898 o
= strcmp(a
->type
, b
->type
);
903 static int output_sockets_list(struct socket_info
*socket_infos
, unsigned cs
) {
904 struct socket_info
*s
;
905 unsigned pathlen
= STRLEN("LISTEN"),
906 typelen
= STRLEN("TYPE") * arg_show_types
,
907 socklen
= STRLEN("UNIT"),
908 servlen
= STRLEN("ACTIVATES");
909 const char *on
, *off
;
911 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
915 socklen
= MAX(socklen
, strlen(s
->id
));
917 typelen
= MAX(typelen
, strlen(s
->type
));
918 pathlen
= MAX(pathlen
, strlen(s
->path
) + (s
->machine
? strlen(s
->machine
)+1 : 0));
920 STRV_FOREACH(a
, s
->triggered
)
921 tmp
+= strlen(*a
) + 2*(a
!= s
->triggered
);
922 servlen
= MAX(servlen
, tmp
);
927 printf("%-*s %-*.*s%-*s %s\n",
929 typelen
+ arg_show_types
, typelen
+ arg_show_types
, "TYPE ",
933 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
934 _cleanup_free_
char *j
= NULL
;
939 j
= strjoin(s
->machine
, ":", s
->path
);
947 printf("%-*s %-*s %-*s",
948 pathlen
, path
, typelen
, s
->type
, socklen
, s
->id
);
951 pathlen
, path
, socklen
, s
->id
);
952 STRV_FOREACH(a
, s
->triggered
)
954 a
== s
->triggered
? "" : ",", *a
);
958 on
= ansi_highlight();
963 on
= ansi_highlight_red();
967 if (!arg_no_legend
) {
968 printf("%s%u sockets listed.%s\n", on
, cs
, off
);
970 printf("Pass --all to see loaded but inactive sockets, too.\n");
976 static int list_sockets(int argc
, char *argv
[], void *userdata
) {
977 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
978 _cleanup_strv_free_
char **machines
= NULL
;
979 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
980 _cleanup_free_
struct socket_info
*socket_infos
= NULL
;
982 struct socket_info
*s
;
988 r
= acquire_bus(BUS_MANAGER
, &bus
);
992 (void) pager_open(arg_no_pager
, false);
994 n
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
998 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
999 _cleanup_strv_free_
char **listening
= NULL
, **triggered
= NULL
;
1002 if (!endswith(u
->id
, ".socket"))
1005 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
1009 c
= get_listening(bus
, u
->unit_path
, &listening
);
1015 if (!GREEDY_REALLOC(socket_infos
, size
, cs
+ c
)) {
1020 for (i
= 0; i
< c
; i
++)
1021 socket_infos
[cs
+ i
] = (struct socket_info
) {
1022 .machine
= u
->machine
,
1024 .type
= listening
[i
*2],
1025 .path
= listening
[i
*2 + 1],
1026 .triggered
= triggered
,
1027 .own_triggered
= i
==0,
1030 /* from this point on we will cleanup those socket_infos */
1033 listening
= triggered
= NULL
; /* avoid cleanup */
1036 qsort_safe(socket_infos
, cs
, sizeof(struct socket_info
),
1037 (__compar_fn_t
) socket_info_compare
);
1039 output_sockets_list(socket_infos
, cs
);
1042 assert(cs
== 0 || socket_infos
);
1043 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
1046 if (s
->own_triggered
)
1047 strv_free(s
->triggered
);
1053 static int get_next_elapse(
1056 dual_timestamp
*next
) {
1058 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1066 r
= sd_bus_get_property_trivial(
1068 "org.freedesktop.systemd1",
1070 "org.freedesktop.systemd1.Timer",
1071 "NextElapseUSecMonotonic",
1076 return log_error_errno(r
, "Failed to get next elapse time: %s", bus_error_message(&error
, r
));
1078 r
= sd_bus_get_property_trivial(
1080 "org.freedesktop.systemd1",
1082 "org.freedesktop.systemd1.Timer",
1083 "NextElapseUSecRealtime",
1088 return log_error_errno(r
, "Failed to get next elapse time: %s", bus_error_message(&error
, r
));
1094 static int get_last_trigger(
1099 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1106 r
= sd_bus_get_property_trivial(
1108 "org.freedesktop.systemd1",
1110 "org.freedesktop.systemd1.Timer",
1116 return log_error_errno(r
, "Failed to get last trigger time: %s", bus_error_message(&error
, r
));
1122 const char* machine
;
1125 usec_t last_trigger
;
1129 static int timer_info_compare(const struct timer_info
*a
, const struct timer_info
*b
) {
1135 if (!a
->machine
&& b
->machine
)
1137 if (a
->machine
&& !b
->machine
)
1139 if (a
->machine
&& b
->machine
) {
1140 o
= strcasecmp(a
->machine
, b
->machine
);
1145 if (a
->next_elapse
< b
->next_elapse
)
1147 if (a
->next_elapse
> b
->next_elapse
)
1150 return strcmp(a
->id
, b
->id
);
1153 static int output_timers_list(struct timer_info
*timer_infos
, unsigned n
) {
1154 struct timer_info
*t
;
1156 nextlen
= STRLEN("NEXT"),
1157 leftlen
= STRLEN("LEFT"),
1158 lastlen
= STRLEN("LAST"),
1159 passedlen
= STRLEN("PASSED"),
1160 unitlen
= STRLEN("UNIT"),
1161 activatelen
= STRLEN("ACTIVATES");
1163 const char *on
, *off
;
1165 assert(timer_infos
|| n
== 0);
1167 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1171 if (t
->next_elapse
> 0) {
1172 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1174 format_timestamp(tstamp
, sizeof(tstamp
), t
->next_elapse
);
1175 nextlen
= MAX(nextlen
, strlen(tstamp
) + 1);
1177 format_timestamp_relative(trel
, sizeof(trel
), t
->next_elapse
);
1178 leftlen
= MAX(leftlen
, strlen(trel
));
1181 if (t
->last_trigger
> 0) {
1182 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1184 format_timestamp(tstamp
, sizeof(tstamp
), t
->last_trigger
);
1185 lastlen
= MAX(lastlen
, strlen(tstamp
) + 1);
1187 format_timestamp_relative(trel
, sizeof(trel
), t
->last_trigger
);
1188 passedlen
= MAX(passedlen
, strlen(trel
));
1191 unitlen
= MAX(unitlen
, strlen(t
->id
) + (t
->machine
? strlen(t
->machine
)+1 : 0));
1193 STRV_FOREACH(a
, t
->triggered
)
1194 ul
+= strlen(*a
) + 2*(a
!= t
->triggered
);
1196 activatelen
= MAX(activatelen
, ul
);
1201 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1205 passedlen
, "PASSED",
1209 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1210 _cleanup_free_
char *j
= NULL
;
1212 char tstamp1
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel1
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1213 char tstamp2
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel2
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1216 format_timestamp(tstamp1
, sizeof(tstamp1
), t
->next_elapse
);
1217 format_timestamp_relative(trel1
, sizeof(trel1
), t
->next_elapse
);
1219 format_timestamp(tstamp2
, sizeof(tstamp2
), t
->last_trigger
);
1220 format_timestamp_relative(trel2
, sizeof(trel2
), t
->last_trigger
);
1223 j
= strjoin(t
->machine
, ":", t
->id
);
1230 printf("%-*s %-*s %-*s %-*s %-*s",
1231 nextlen
, tstamp1
, leftlen
, trel1
, lastlen
, tstamp2
, passedlen
, trel2
, unitlen
, unit
);
1233 STRV_FOREACH(a
, t
->triggered
)
1235 a
== t
->triggered
? "" : ",", *a
);
1239 on
= ansi_highlight();
1240 off
= ansi_normal();
1244 on
= ansi_highlight_red();
1245 off
= ansi_normal();
1248 if (!arg_no_legend
) {
1249 printf("%s%u timers listed.%s\n", on
, n
, off
);
1251 printf("Pass --all to see loaded but inactive timers, too.\n");
1257 static usec_t
calc_next_elapse(dual_timestamp
*nw
, dual_timestamp
*next
) {
1263 if (next
->monotonic
!= USEC_INFINITY
&& next
->monotonic
> 0) {
1266 if (next
->monotonic
> nw
->monotonic
)
1267 converted
= nw
->realtime
+ (next
->monotonic
- nw
->monotonic
);
1269 converted
= nw
->realtime
- (nw
->monotonic
- next
->monotonic
);
1271 if (next
->realtime
!= USEC_INFINITY
&& next
->realtime
> 0)
1272 next_elapse
= MIN(converted
, next
->realtime
);
1274 next_elapse
= converted
;
1277 next_elapse
= next
->realtime
;
1282 static int list_timers(int argc
, char *argv
[], void *userdata
) {
1283 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
1284 _cleanup_strv_free_
char **machines
= NULL
;
1285 _cleanup_free_
struct timer_info
*timer_infos
= NULL
;
1286 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
1287 struct timer_info
*t
;
1295 r
= acquire_bus(BUS_MANAGER
, &bus
);
1299 (void) pager_open(arg_no_pager
, false);
1301 n
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
1305 dual_timestamp_get(&nw
);
1307 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
1308 _cleanup_strv_free_
char **triggered
= NULL
;
1309 dual_timestamp next
= DUAL_TIMESTAMP_NULL
;
1312 if (!endswith(u
->id
, ".timer"))
1315 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
1319 r
= get_next_elapse(bus
, u
->unit_path
, &next
);
1323 get_last_trigger(bus
, u
->unit_path
, &last
);
1325 if (!GREEDY_REALLOC(timer_infos
, size
, c
+1)) {
1330 m
= calc_next_elapse(&nw
, &next
);
1332 timer_infos
[c
++] = (struct timer_info
) {
1333 .machine
= u
->machine
,
1336 .last_trigger
= last
,
1337 .triggered
= triggered
,
1340 triggered
= NULL
; /* avoid cleanup */
1343 qsort_safe(timer_infos
, c
, sizeof(struct timer_info
),
1344 (__compar_fn_t
) timer_info_compare
);
1346 output_timers_list(timer_infos
, c
);
1349 for (t
= timer_infos
; t
< timer_infos
+ c
; t
++)
1350 strv_free(t
->triggered
);
1355 static int compare_unit_file_list(const void *a
, const void *b
) {
1356 const char *d1
, *d2
;
1357 const UnitFileList
*u
= a
, *v
= b
;
1359 d1
= strrchr(u
->path
, '.');
1360 d2
= strrchr(v
->path
, '.');
1365 r
= strcasecmp(d1
, d2
);
1370 return strcasecmp(basename(u
->path
), basename(v
->path
));
1373 static bool output_show_unit_file(const UnitFileList
*u
, char **states
, char **patterns
) {
1376 if (!strv_fnmatch_or_empty(patterns
, basename(u
->path
), FNM_NOESCAPE
))
1379 if (!strv_isempty(arg_types
)) {
1382 dot
= strrchr(u
->path
, '.');
1386 if (!strv_find(arg_types
, dot
+1))
1390 if (!strv_isempty(states
) &&
1391 !strv_find(states
, unit_file_state_to_string(u
->state
)))
1397 static void output_unit_file_list(const UnitFileList
*units
, unsigned c
) {
1398 unsigned max_id_len
, id_cols
, state_cols
;
1399 const UnitFileList
*u
;
1401 max_id_len
= STRLEN("UNIT FILE");
1402 state_cols
= STRLEN("STATE");
1404 for (u
= units
; u
< units
+ c
; u
++) {
1405 max_id_len
= MAX(max_id_len
, strlen(basename(u
->path
)));
1406 state_cols
= MAX(state_cols
, strlen(unit_file_state_to_string(u
->state
)));
1410 unsigned basic_cols
;
1412 id_cols
= MIN(max_id_len
, 25u);
1413 basic_cols
= 1 + id_cols
+ state_cols
;
1414 if (basic_cols
< (unsigned) columns())
1415 id_cols
+= MIN(columns() - basic_cols
, max_id_len
- id_cols
);
1417 id_cols
= max_id_len
;
1419 if (!arg_no_legend
&& c
> 0)
1420 printf("%s%-*s %-*s%s\n",
1422 id_cols
, "UNIT FILE",
1423 state_cols
, "STATE",
1426 for (u
= units
; u
< units
+ c
; u
++) {
1427 const char *on_underline
= NULL
, *on_color
= NULL
, *off
= NULL
, *id
;
1428 _cleanup_free_
char *e
= NULL
;
1431 underline
= u
+ 1 < units
+ c
&&
1432 !streq(unit_type_suffix(u
->path
), unit_type_suffix((u
+ 1)->path
));
1435 on_underline
= ansi_underline();
1437 if (IN_SET(u
->state
,
1439 UNIT_FILE_MASKED_RUNTIME
,
1442 on_color
= underline
? ansi_highlight_red_underline() : ansi_highlight_red();
1443 else if (u
->state
== UNIT_FILE_ENABLED
)
1444 on_color
= underline
? ansi_highlight_green_underline() : ansi_highlight_green();
1446 if (on_underline
|| on_color
)
1447 off
= ansi_normal();
1449 id
= basename(u
->path
);
1451 e
= arg_full
? NULL
: ellipsize(id
, id_cols
, 33);
1453 printf("%s%-*s %s%-*s%s\n",
1454 strempty(on_underline
),
1455 id_cols
, e
? e
: id
,
1456 strempty(on_color
), state_cols
, unit_file_state_to_string(u
->state
), strempty(off
));
1460 printf("\n%u unit files listed.\n", c
);
1463 static int list_unit_files(int argc
, char *argv
[], void *userdata
) {
1464 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1465 _cleanup_free_ UnitFileList
*units
= NULL
;
1472 bool fallback
= false;
1474 if (install_client_side()) {
1480 h
= hashmap_new(&string_hash_ops
);
1484 r
= unit_file_get_list(arg_scope
, arg_root
, h
, arg_states
, strv_skip(argv
, 1));
1486 unit_file_list_free(h
);
1487 return log_error_errno(r
, "Failed to get unit file list: %m");
1490 n_units
= hashmap_size(h
);
1492 units
= new(UnitFileList
, n_units
?: 1); /* avoid malloc(0) */
1494 unit_file_list_free(h
);
1498 HASHMAP_FOREACH(u
, h
, i
) {
1499 if (!output_show_unit_file(u
, NULL
, NULL
))
1506 assert(c
<= n_units
);
1511 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
1512 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1515 r
= acquire_bus(BUS_MANAGER
, &bus
);
1519 r
= sd_bus_message_new_method_call(
1522 "org.freedesktop.systemd1",
1523 "/org/freedesktop/systemd1",
1524 "org.freedesktop.systemd1.Manager",
1525 "ListUnitFilesByPatterns");
1527 return bus_log_create_error(r
);
1529 r
= sd_bus_message_append_strv(m
, arg_states
);
1531 return bus_log_create_error(r
);
1533 r
= sd_bus_message_append_strv(m
, strv_skip(argv
, 1));
1535 return bus_log_create_error(r
);
1537 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
1538 if (r
< 0 && sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_METHOD
)) {
1539 /* Fallback to legacy ListUnitFiles method */
1541 log_debug_errno(r
, "Failed to list unit files: %s Falling back to ListUnitsFiles method.", bus_error_message(&error
, r
));
1542 m
= sd_bus_message_unref(m
);
1543 sd_bus_error_free(&error
);
1545 r
= sd_bus_message_new_method_call(
1548 "org.freedesktop.systemd1",
1549 "/org/freedesktop/systemd1",
1550 "org.freedesktop.systemd1.Manager",
1553 return bus_log_create_error(r
);
1555 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
1558 return log_error_errno(r
, "Failed to list unit files: %s", bus_error_message(&error
, r
));
1560 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
1562 return bus_log_parse_error(r
);
1564 while ((r
= sd_bus_message_read(reply
, "(ss)", &path
, &state
)) > 0) {
1566 if (!GREEDY_REALLOC(units
, size
, c
+ 1))
1569 units
[c
] = (struct UnitFileList
) {
1571 unit_file_state_from_string(state
)
1574 if (output_show_unit_file(&units
[c
],
1575 fallback
? arg_states
: NULL
,
1576 fallback
? strv_skip(argv
, 1) : NULL
))
1581 return bus_log_parse_error(r
);
1583 r
= sd_bus_message_exit_container(reply
);
1585 return bus_log_parse_error(r
);
1588 (void) pager_open(arg_no_pager
, false);
1590 qsort_safe(units
, c
, sizeof(UnitFileList
), compare_unit_file_list
);
1591 output_unit_file_list(units
, c
);
1593 if (install_client_side())
1594 for (unit
= units
; unit
< units
+ c
; unit
++)
1600 static int list_dependencies_print(const char *name
, int level
, unsigned int branches
, bool last
) {
1601 _cleanup_free_
char *n
= NULL
;
1602 size_t max_len
= MAX(columns(),20u);
1608 for (i
= level
- 1; i
>= 0; i
--) {
1610 if (len
> max_len
- 3 && !arg_full
) {
1611 printf("%s...\n",max_len
% 2 ? "" : " ");
1614 printf("%s", special_glyph(branches
& (1 << i
) ? TREE_VERTICAL
: TREE_SPACE
));
1618 if (len
> max_len
- 3 && !arg_full
) {
1619 printf("%s...\n",max_len
% 2 ? "" : " ");
1623 printf("%s", special_glyph(last
? TREE_RIGHT
: TREE_BRANCH
));
1627 printf("%s\n", name
);
1631 n
= ellipsize(name
, max_len
-len
, 100);
1639 static int list_dependencies_get_dependencies(sd_bus
*bus
, const char *name
, char ***deps
) {
1641 struct DependencyStatusInfo
{
1645 static const struct bus_properties_map map
[_DEPENDENCY_MAX
][6] = {
1646 [DEPENDENCY_FORWARD
] = {
1647 { "Requires", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[0]) },
1648 { "Requisite", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[1]) },
1649 { "Wants", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[2]) },
1650 { "ConsistsOf", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[3]) },
1651 { "BindsTo", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[4]) },
1654 [DEPENDENCY_REVERSE
] = {
1655 { "RequiredBy", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[0]) },
1656 { "RequisiteOf", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[1]) },
1657 { "WantedBy", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[2]) },
1658 { "PartOf", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[3]) },
1659 { "BoundBy", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[4]) },
1662 [DEPENDENCY_AFTER
] = {
1663 { "After", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[0]) },
1666 [DEPENDENCY_BEFORE
] = {
1667 { "Before", "as", NULL
, offsetof(struct DependencyStatusInfo
, dep
[0]) },
1672 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1673 _cleanup_strv_free_
char **ret
= NULL
;
1674 _cleanup_free_
char *path
= NULL
;
1681 path
= unit_dbus_path_from_name(name
);
1685 r
= bus_map_all_properties(bus
,
1686 "org.freedesktop.systemd1",
1688 map
[arg_dependency
],
1693 return log_error_errno(r
, "Failed to get properties of %s: %s", name
, bus_error_message(&error
, r
));
1695 if (IN_SET(arg_dependency
, DEPENDENCY_AFTER
, DEPENDENCY_BEFORE
)) {
1696 *deps
= info
.dep
[0];
1700 for (i
= 0; i
< 5; i
++) {
1701 r
= strv_extend_strv(&ret
, info
.dep
[i
], true);
1704 info
.dep
[i
] = strv_free(info
.dep
[i
]);
1713 static int list_dependencies_compare(const void *_a
, const void *_b
) {
1714 const char **a
= (const char**) _a
, **b
= (const char**) _b
;
1716 if (unit_name_to_type(*a
) == UNIT_TARGET
&& unit_name_to_type(*b
) != UNIT_TARGET
)
1718 if (unit_name_to_type(*a
) != UNIT_TARGET
&& unit_name_to_type(*b
) == UNIT_TARGET
)
1721 return strcasecmp(*a
, *b
);
1724 static int list_dependencies_one(
1729 unsigned int branches
) {
1731 _cleanup_strv_free_
char **deps
= NULL
;
1739 r
= strv_extend(units
, name
);
1743 r
= list_dependencies_get_dependencies(bus
, name
, &deps
);
1747 qsort_safe(deps
, strv_length(deps
), sizeof (char*), list_dependencies_compare
);
1749 STRV_FOREACH(c
, deps
) {
1750 if (strv_contains(*units
, *c
)) {
1753 r
= list_dependencies_print("...", level
+ 1, (branches
<< 1) | (c
[1] == NULL
? 0 : 1), 1);
1763 UnitActiveState active_state
= _UNIT_ACTIVE_STATE_INVALID
;
1766 (void) get_state_one_unit(bus
, *c
, &active_state
);
1768 switch (active_state
) {
1770 case UNIT_RELOADING
:
1771 case UNIT_ACTIVATING
:
1772 on
= ansi_highlight_green();
1776 case UNIT_DEACTIVATING
:
1781 on
= ansi_highlight_red();
1785 printf("%s%s%s ", on
, special_glyph(BLACK_CIRCLE
), ansi_normal());
1788 r
= list_dependencies_print(*c
, level
, branches
, c
[1] == NULL
);
1792 if (arg_all
|| unit_name_to_type(*c
) == UNIT_TARGET
) {
1793 r
= list_dependencies_one(bus
, *c
, level
+ 1, units
, (branches
<< 1) | (c
[1] == NULL
? 0 : 1));
1800 strv_remove(*units
, name
);
1805 static int list_dependencies(int argc
, char *argv
[], void *userdata
) {
1806 _cleanup_strv_free_
char **units
= NULL
;
1807 _cleanup_free_
char *unit
= NULL
;
1813 r
= unit_name_mangle(argv
[1], UNIT_NAME_NOGLOB
, &unit
);
1815 return log_error_errno(r
, "Failed to mangle unit name: %m");
1819 u
= SPECIAL_DEFAULT_TARGET
;
1821 r
= acquire_bus(BUS_MANAGER
, &bus
);
1825 (void) pager_open(arg_no_pager
, false);
1829 return list_dependencies_one(bus
, u
, 0, &units
, 0);
1832 struct machine_info
{
1836 char *control_group
;
1837 uint32_t n_failed_units
;
1842 static const struct bus_properties_map machine_info_property_map
[] = {
1843 { "SystemState", "s", NULL
, offsetof(struct machine_info
, state
) },
1844 { "NJobs", "u", NULL
, offsetof(struct machine_info
, n_jobs
) },
1845 { "NFailedUnits", "u", NULL
, offsetof(struct machine_info
, n_failed_units
) },
1846 { "ControlGroup", "s", NULL
, offsetof(struct machine_info
, control_group
) },
1847 { "UserspaceTimestamp", "t", NULL
, offsetof(struct machine_info
, timestamp
) },
1851 static void machine_info_clear(struct machine_info
*info
) {
1856 free(info
->control_group
);
1860 static void free_machines_list(struct machine_info
*machine_infos
, int n
) {
1866 for (i
= 0; i
< n
; i
++)
1867 machine_info_clear(&machine_infos
[i
]);
1869 free(machine_infos
);
1872 static int compare_machine_info(const void *a
, const void *b
) {
1873 const struct machine_info
*u
= a
, *v
= b
;
1875 if (u
->is_host
!= v
->is_host
)
1876 return u
->is_host
> v
->is_host
? -1 : 1;
1878 return strcasecmp(u
->name
, v
->name
);
1881 static int get_machine_properties(sd_bus
*bus
, struct machine_info
*mi
) {
1882 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*container
= NULL
;
1888 r
= sd_bus_open_system_machine(&container
, mi
->name
);
1895 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, NULL
, NULL
, mi
);
1902 static bool output_show_machine(const char *name
, char **patterns
) {
1903 return strv_fnmatch_or_empty(patterns
, name
, FNM_NOESCAPE
);
1906 static int get_machine_list(
1908 struct machine_info
**_machine_infos
,
1911 struct machine_info
*machine_infos
= NULL
;
1912 _cleanup_strv_free_
char **m
= NULL
;
1913 _cleanup_free_
char *hn
= NULL
;
1918 hn
= gethostname_malloc();
1922 if (output_show_machine(hn
, patterns
)) {
1923 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1))
1926 machine_infos
[c
].is_host
= true;
1927 machine_infos
[c
].name
= hn
;
1930 (void) get_machine_properties(bus
, &machine_infos
[c
]);
1934 r
= sd_get_machine_names(&m
);
1936 return log_error_errno(r
, "Failed to get machine list: %m");
1938 STRV_FOREACH(i
, m
) {
1939 _cleanup_free_
char *class = NULL
;
1941 if (!output_show_machine(*i
, patterns
))
1944 sd_machine_get_class(*i
, &class);
1945 if (!streq_ptr(class, "container"))
1948 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1)) {
1949 free_machines_list(machine_infos
, c
);
1953 machine_infos
[c
].is_host
= false;
1954 machine_infos
[c
].name
= strdup(*i
);
1955 if (!machine_infos
[c
].name
) {
1956 free_machines_list(machine_infos
, c
);
1960 (void) get_machine_properties(NULL
, &machine_infos
[c
]);
1964 *_machine_infos
= machine_infos
;
1968 static void output_machines_list(struct machine_info
*machine_infos
, unsigned n
) {
1969 struct machine_info
*m
;
1972 namelen
= STRLEN("NAME"),
1973 statelen
= STRLEN("STATE"),
1974 failedlen
= STRLEN("FAILED"),
1975 jobslen
= STRLEN("JOBS");
1977 assert(machine_infos
|| n
== 0);
1979 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
1980 namelen
= MAX(namelen
,
1981 strlen(m
->name
) + (m
->is_host
? STRLEN(" (host)") : 0));
1982 statelen
= MAX(statelen
, strlen_ptr(m
->state
));
1983 failedlen
= MAX(failedlen
, DECIMAL_STR_WIDTH(m
->n_failed_units
));
1984 jobslen
= MAX(jobslen
, DECIMAL_STR_WIDTH(m
->n_jobs
));
1986 if (!arg_plain
&& !streq_ptr(m
->state
, "running"))
1990 if (!arg_no_legend
) {
1994 printf("%-*s %-*s %-*s %-*s\n",
1997 failedlen
, "FAILED",
2001 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
2002 const char *on_state
= "", *off_state
= "";
2003 const char *on_failed
= "", *off_failed
= "";
2004 bool circle
= false;
2006 if (streq_ptr(m
->state
, "degraded")) {
2007 on_state
= ansi_highlight_red();
2008 off_state
= ansi_normal();
2010 } else if (!streq_ptr(m
->state
, "running")) {
2011 on_state
= ansi_highlight_yellow();
2012 off_state
= ansi_normal();
2016 if (m
->n_failed_units
> 0) {
2017 on_failed
= ansi_highlight_red();
2018 off_failed
= ansi_normal();
2020 on_failed
= off_failed
= "";
2023 printf("%s%s%s ", on_state
, circle
? special_glyph(BLACK_CIRCLE
) : " ", off_state
);
2026 printf("%-*s (host) %s%-*s%s %s%*" PRIu32
"%s %*" PRIu32
"\n",
2027 (int) (namelen
- (STRLEN(" (host)"))),
2029 on_state
, statelen
, strna(m
->state
), off_state
,
2030 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
2031 jobslen
, m
->n_jobs
);
2033 printf("%-*s %s%-*s%s %s%*" PRIu32
"%s %*" PRIu32
"\n",
2034 namelen
, strna(m
->name
),
2035 on_state
, statelen
, strna(m
->state
), off_state
,
2036 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
2037 jobslen
, m
->n_jobs
);
2041 printf("\n%u machines listed.\n", n
);
2044 static int list_machines(int argc
, char *argv
[], void *userdata
) {
2045 struct machine_info
*machine_infos
= NULL
;
2049 r
= acquire_bus(BUS_MANAGER
, &bus
);
2053 r
= get_machine_list(bus
, &machine_infos
, strv_skip(argv
, 1));
2057 (void) pager_open(arg_no_pager
, false);
2059 qsort_safe(machine_infos
, r
, sizeof(struct machine_info
), compare_machine_info
);
2060 output_machines_list(machine_infos
, r
);
2061 free_machines_list(machine_infos
, r
);
2066 static int get_default(int argc
, char *argv
[], void *userdata
) {
2067 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2068 _cleanup_free_
char *_path
= NULL
;
2072 if (install_client_side()) {
2073 r
= unit_file_get_default(arg_scope
, arg_root
, &_path
);
2075 return log_error_errno(r
, "Failed to get default target: %m");
2080 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2083 r
= acquire_bus(BUS_MANAGER
, &bus
);
2087 r
= sd_bus_call_method(
2089 "org.freedesktop.systemd1",
2090 "/org/freedesktop/systemd1",
2091 "org.freedesktop.systemd1.Manager",
2097 return log_error_errno(r
, "Failed to get default target: %s", bus_error_message(&error
, r
));
2099 r
= sd_bus_message_read(reply
, "s", &path
);
2101 return bus_log_parse_error(r
);
2105 printf("%s\n", path
);
2110 static int set_default(int argc
, char *argv
[], void *userdata
) {
2111 _cleanup_free_
char *unit
= NULL
;
2112 UnitFileChange
*changes
= NULL
;
2113 unsigned n_changes
= 0;
2119 r
= unit_name_mangle_with_suffix(argv
[1], UNIT_NAME_NOGLOB
, ".target", &unit
);
2121 return log_error_errno(r
, "Failed to mangle unit name: %m");
2123 if (install_client_side()) {
2124 r
= unit_file_set_default(arg_scope
, UNIT_FILE_FORCE
, arg_root
, unit
, &changes
, &n_changes
);
2125 unit_file_dump_changes(r
, "set default", changes
, n_changes
, arg_quiet
);
2130 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2131 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2134 polkit_agent_open_maybe();
2136 r
= acquire_bus(BUS_MANAGER
, &bus
);
2140 r
= sd_bus_call_method(
2142 "org.freedesktop.systemd1",
2143 "/org/freedesktop/systemd1",
2144 "org.freedesktop.systemd1.Manager",
2150 return log_error_errno(r
, "Failed to set default target: %s", bus_error_message(&error
, r
));
2152 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
2156 /* Try to reload if enabled */
2158 r
= daemon_reload(argc
, argv
, userdata
);
2164 unit_file_changes_free(changes
, n_changes
);
2169 static int output_waiting_jobs(sd_bus
*bus
, uint32_t id
, const char *method
, const char *prefix
) {
2170 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2171 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2172 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2178 r
= sd_bus_call_method(
2180 "org.freedesktop.systemd1",
2181 "/org/freedesktop/systemd1",
2182 "org.freedesktop.systemd1.Manager",
2188 return log_debug_errno(r
, "Failed to get waiting jobs for job %" PRIu32
, id
);
2190 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2192 return bus_log_parse_error(r
);
2194 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &other_id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0)
2195 printf("%s %u (%s/%s)\n", prefix
, other_id
, name
, type
);
2197 return bus_log_parse_error(r
);
2199 r
= sd_bus_message_exit_container(reply
);
2201 return bus_log_parse_error(r
);
2208 const char *name
, *type
, *state
;
2211 static void output_jobs_list(sd_bus
*bus
, const struct job_info
* jobs
, unsigned n
, bool skipped
) {
2212 unsigned id_len
, unit_len
, type_len
, state_len
;
2213 const struct job_info
*j
;
2214 const char *on
, *off
;
2215 bool shorten
= false;
2217 assert(n
== 0 || jobs
);
2220 if (!arg_no_legend
) {
2221 on
= ansi_highlight_green();
2222 off
= ansi_normal();
2224 printf("%sNo jobs %s.%s\n", on
, skipped
? "listed" : "running", off
);
2229 (void) pager_open(arg_no_pager
, false);
2231 id_len
= STRLEN("JOB");
2232 unit_len
= STRLEN("UNIT");
2233 type_len
= STRLEN("TYPE");
2234 state_len
= STRLEN("STATE");
2236 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2237 uint32_t id
= j
->id
;
2238 assert(j
->name
&& j
->type
&& j
->state
);
2240 id_len
= MAX(id_len
, DECIMAL_STR_WIDTH(id
));
2241 unit_len
= MAX(unit_len
, strlen(j
->name
));
2242 type_len
= MAX(type_len
, strlen(j
->type
));
2243 state_len
= MAX(state_len
, strlen(j
->state
));
2246 if (!arg_full
&& id_len
+ 1 + unit_len
+ type_len
+ 1 + state_len
> columns()) {
2247 unit_len
= MAX(33u, columns() - id_len
- type_len
- state_len
- 3);
2252 printf("%*s %-*s %-*s %-*s\n",
2256 state_len
, "STATE");
2258 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2259 _cleanup_free_
char *e
= NULL
;
2261 if (streq(j
->state
, "running")) {
2262 on
= ansi_highlight();
2263 off
= ansi_normal();
2267 e
= shorten
? ellipsize(j
->name
, unit_len
, 33) : NULL
;
2268 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2270 on
, unit_len
, e
? e
: j
->name
, off
,
2272 on
, state_len
, j
->state
, off
);
2275 output_waiting_jobs(bus
, j
->id
, "GetJobAfter", "\twaiting for job");
2276 if (arg_jobs_before
)
2277 output_waiting_jobs(bus
, j
->id
, "GetJobBefore", "\tblocking job");
2280 if (!arg_no_legend
) {
2281 on
= ansi_highlight();
2282 off
= ansi_normal();
2284 printf("\n%s%u jobs listed%s.\n", on
, n
, off
);
2288 static bool output_show_job(struct job_info
*job
, char **patterns
) {
2289 return strv_fnmatch_or_empty(patterns
, job
->name
, FNM_NOESCAPE
);
2292 static int list_jobs(int argc
, char *argv
[], void *userdata
) {
2293 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2294 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2295 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2296 _cleanup_free_
struct job_info
*jobs
= NULL
;
2302 bool skipped
= false;
2304 r
= acquire_bus(BUS_MANAGER
, &bus
);
2308 r
= sd_bus_call_method(
2310 "org.freedesktop.systemd1",
2311 "/org/freedesktop/systemd1",
2312 "org.freedesktop.systemd1.Manager",
2318 return log_error_errno(r
, "Failed to list jobs: %s", bus_error_message(&error
, r
));
2320 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2322 return bus_log_parse_error(r
);
2324 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0) {
2325 struct job_info job
= { id
, name
, type
, state
};
2327 if (!output_show_job(&job
, strv_skip(argv
, 1))) {
2332 if (!GREEDY_REALLOC(jobs
, size
, c
+ 1))
2338 return bus_log_parse_error(r
);
2340 r
= sd_bus_message_exit_container(reply
);
2342 return bus_log_parse_error(r
);
2344 (void) pager_open(arg_no_pager
, false);
2346 output_jobs_list(bus
, jobs
, c
, skipped
);
2350 static int cancel_job(int argc
, char *argv
[], void *userdata
) {
2356 return trivial_method(argc
, argv
, userdata
);
2358 r
= acquire_bus(BUS_MANAGER
, &bus
);
2362 polkit_agent_open_maybe();
2364 STRV_FOREACH(name
, strv_skip(argv
, 1)) {
2365 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2369 q
= safe_atou32(*name
, &id
);
2371 return log_error_errno(q
, "Failed to parse job id \"%s\": %m", *name
);
2373 q
= sd_bus_call_method(
2375 "org.freedesktop.systemd1",
2376 "/org/freedesktop/systemd1",
2377 "org.freedesktop.systemd1.Manager",
2383 log_error_errno(q
, "Failed to cancel job %"PRIu32
": %s", id
, bus_error_message(&error
, q
));
2392 static int need_daemon_reload(sd_bus
*bus
, const char *unit
) {
2393 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2397 /* We ignore all errors here, since this is used to show a
2400 /* We don't use unit_dbus_path_from_name() directly since we
2401 * don't want to load the unit if it isn't loaded. */
2403 r
= sd_bus_call_method(
2405 "org.freedesktop.systemd1",
2406 "/org/freedesktop/systemd1",
2407 "org.freedesktop.systemd1.Manager",
2415 r
= sd_bus_message_read(reply
, "o", &path
);
2419 r
= sd_bus_get_property_trivial(
2421 "org.freedesktop.systemd1",
2423 "org.freedesktop.systemd1.Unit",
2433 static void warn_unit_file_changed(const char *name
) {
2436 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.",
2437 ansi_highlight_red(),
2440 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user");
2443 static int unit_file_find_path(LookupPaths
*lp
, const char *unit_name
, char **unit_path
) {
2449 STRV_FOREACH(p
, lp
->search_path
) {
2450 _cleanup_free_
char *path
= NULL
, *lpath
= NULL
;
2453 path
= path_join(NULL
, *p
, unit_name
);
2457 r
= chase_symlinks(path
, arg_root
, 0, &lpath
);
2463 return log_error_errno(r
, "Failed to access path '%s': %m", path
);
2475 static int unit_find_template_path(
2476 const char *unit_name
,
2478 char **fragment_path
,
2481 _cleanup_free_
char *_template
= NULL
;
2484 /* Returns 1 if a fragment was found, 0 if not found, negative on error. */
2486 r
= unit_file_find_path(lp
, unit_name
, fragment_path
);
2488 return r
; /* error or found a real unit */
2490 r
= unit_name_template(unit_name
, &_template
);
2492 return 0; /* not a template, does not exist */
2494 return log_error_errno(r
, "Failed to determine template name: %m");
2496 r
= unit_file_find_path(lp
, _template
, fragment_path
);
2501 *template = _template
;
2507 static int unit_find_paths(
2509 const char *unit_name
,
2511 char **fragment_path
,
2512 char ***dropin_paths
) {
2514 _cleanup_free_
char *path
= NULL
;
2515 _cleanup_strv_free_
char **dropins
= NULL
;
2519 * Finds where the unit is defined on disk. Returns 0 if the unit
2520 * is not found. Returns 1 if it is found, and sets
2521 * - the path to the unit in *path, if it exists on disk,
2522 * - and a strv of existing drop-ins in *dropins,
2523 * if the arg is not NULL and any dropins were found.
2527 assert(fragment_path
);
2530 if (!install_client_side() && !unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
2531 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2532 _cleanup_free_
char *unit
= NULL
;
2534 unit
= unit_dbus_path_from_name(unit_name
);
2538 r
= sd_bus_get_property_string(
2540 "org.freedesktop.systemd1",
2542 "org.freedesktop.systemd1.Unit",
2547 return log_error_errno(r
, "Failed to get FragmentPath: %s", bus_error_message(&error
, r
));
2550 r
= sd_bus_get_property_strv(
2552 "org.freedesktop.systemd1",
2554 "org.freedesktop.systemd1.Unit",
2559 return log_error_errno(r
, "Failed to get DropInPaths: %s", bus_error_message(&error
, r
));
2562 _cleanup_set_free_ Set
*names
= NULL
;
2563 _cleanup_free_
char *template = NULL
;
2565 names
= set_new(NULL
);
2569 r
= unit_find_template_path(unit_name
, lp
, &path
, &template);
2574 /* We found the unit file. If we followed symlinks, this name might be
2575 * different then the unit_name with started with. Look for dropins matching
2576 * that "final" name. */
2577 r
= set_put(names
, basename(path
));
2579 /* No unit file, let's look for dropins matching the original name.
2580 * systemd has fairly complicated rules (based on unit type and provenience),
2581 * which units are allowed not to have the main unit file. We err on the
2582 * side of including too many files, and always try to load dropins. */
2583 r
= set_put(names
, unit_name
);
2585 /* The cases where we allow a unit to exist without the main file are
2586 * never valid for templates. Don't try to load dropins in this case. */
2590 return log_error_errno(r
, "Failed to add unit name: %m");
2593 r
= unit_file_find_dropin_conf_paths(arg_root
, lp
->search_path
,
2594 NULL
, names
, &dropins
);
2602 if (!isempty(path
)) {
2603 *fragment_path
= path
;
2608 if (dropin_paths
&& !strv_isempty(dropins
)) {
2609 *dropin_paths
= dropins
;
2614 if (r
== 0 && !arg_force
)
2615 log_error("No files found for %s.", unit_name
);
2620 static int get_state_one_unit(sd_bus
*bus
, const char *name
, UnitActiveState
*active_state
) {
2621 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2622 _cleanup_free_
char *buf
= NULL
, *path
= NULL
;
2623 UnitActiveState state
;
2627 assert(active_state
);
2629 path
= unit_dbus_path_from_name(name
);
2633 r
= sd_bus_get_property_string(
2635 "org.freedesktop.systemd1",
2637 "org.freedesktop.systemd1.Unit",
2642 return log_error_errno(r
, "Failed to retrieve unit state: %s", bus_error_message(&error
, r
));
2644 state
= unit_active_state_from_string(buf
);
2645 if (state
== _UNIT_ACTIVE_STATE_INVALID
) {
2646 log_error("Invalid unit state '%s' for: %s", buf
, name
);
2650 *active_state
= state
;
2654 static int check_triggering_units(
2658 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2659 _cleanup_free_
char *path
= NULL
, *n
= NULL
, *load_state
= NULL
;
2660 _cleanup_strv_free_
char **triggered_by
= NULL
;
2661 bool print_warning_label
= true;
2662 UnitActiveState active_state
;
2666 r
= unit_name_mangle(name
, UNIT_NAME_NOGLOB
, &n
);
2668 return log_error_errno(r
, "Failed to mangle unit name: %m");
2670 path
= unit_dbus_path_from_name(n
);
2674 r
= sd_bus_get_property_string(
2676 "org.freedesktop.systemd1",
2678 "org.freedesktop.systemd1.Unit",
2683 return log_error_errno(r
, "Failed to get load state of %s: %s", n
, bus_error_message(&error
, r
));
2685 if (streq(load_state
, "masked"))
2688 r
= sd_bus_get_property_strv(
2690 "org.freedesktop.systemd1",
2692 "org.freedesktop.systemd1.Unit",
2697 return log_error_errno(r
, "Failed to get triggered by array of %s: %s", n
, bus_error_message(&error
, r
));
2699 STRV_FOREACH(i
, triggered_by
) {
2700 r
= get_state_one_unit(bus
, *i
, &active_state
);
2704 if (!IN_SET(active_state
, UNIT_ACTIVE
, UNIT_RELOADING
))
2707 if (print_warning_label
) {
2708 log_warning("Warning: Stopping %s, but it can still be activated by:", n
);
2709 print_warning_label
= false;
2712 log_warning(" %s", *i
);
2718 static const struct {
2721 } unit_actions
[] = {
2722 { "start", "StartUnit" },
2723 { "stop", "StopUnit" },
2724 { "condstop", "StopUnit" },
2725 { "reload", "ReloadUnit" },
2726 { "restart", "RestartUnit" },
2727 { "try-restart", "TryRestartUnit" },
2728 { "condrestart", "TryRestartUnit" },
2729 { "reload-or-restart", "ReloadOrRestartUnit" },
2730 { "try-reload-or-restart", "ReloadOrTryRestartUnit" },
2731 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2732 { "condreload", "ReloadOrTryRestartUnit" },
2733 { "force-reload", "ReloadOrTryRestartUnit" }
2736 static const char *verb_to_method(const char *verb
) {
2739 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2740 if (streq_ptr(unit_actions
[i
].verb
, verb
))
2741 return unit_actions
[i
].method
;
2746 static const char *method_to_verb(const char *method
) {
2749 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2750 if (streq_ptr(unit_actions
[i
].method
, method
))
2751 return unit_actions
[i
].verb
;
2763 static void wait_context_free(WaitContext
*c
) {
2764 c
->match
= sd_bus_slot_unref(c
->match
);
2765 c
->event
= sd_event_unref(c
->event
);
2766 c
->unit_paths
= set_free_free(c
->unit_paths
);
2769 static int on_properties_changed(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
2770 WaitContext
*c
= userdata
;
2774 path
= sd_bus_message_get_path(m
);
2775 if (!set_contains(c
->unit_paths
, path
))
2778 /* Check if ActiveState changed to inactive/failed */
2779 /* (s interface, a{sv} changed_properties, as invalidated_properties) */
2780 r
= sd_bus_message_skip(m
, "s");
2782 return bus_log_parse_error(r
);
2784 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "{sv}");
2786 return bus_log_parse_error(r
);
2788 while ((r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
2791 r
= sd_bus_message_read(m
, "s", &s
);
2793 return bus_log_parse_error(r
);
2795 if (streq(s
, "ActiveState")) {
2798 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, "s");
2800 return bus_log_parse_error(r
);
2802 r
= sd_bus_message_read(m
, "s", &s
);
2804 return bus_log_parse_error(r
);
2806 is_failed
= streq(s
, "failed");
2807 if (streq(s
, "inactive") || is_failed
) {
2808 log_debug("%s became %s, dropping from --wait tracking", path
, s
);
2809 free(set_remove(c
->unit_paths
, path
));
2810 c
->any_failed
= c
->any_failed
|| is_failed
;
2812 log_debug("ActiveState on %s changed to %s", path
, s
);
2814 break; /* no need to dissect the rest of the message */
2816 /* other property */
2817 r
= sd_bus_message_skip(m
, "v");
2819 return bus_log_parse_error(r
);
2821 r
= sd_bus_message_exit_container(m
);
2823 return bus_log_parse_error(r
);
2826 return bus_log_parse_error(r
);
2828 if (set_isempty(c
->unit_paths
))
2829 sd_event_exit(c
->event
, EXIT_SUCCESS
);
2834 static int start_unit_one(
2839 sd_bus_error
*error
,
2841 WaitContext
*wait_context
) {
2843 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2853 _cleanup_free_
char *unit_path
= NULL
;
2855 log_debug("Watching for property changes of %s", name
);
2856 r
= sd_bus_call_method(
2858 "org.freedesktop.systemd1",
2859 "/org/freedesktop/systemd1",
2860 "org.freedesktop.systemd1.Manager",
2866 return log_error_errno(r
, "Failed to RefUnit %s: %s", name
, bus_error_message(error
, r
));
2868 unit_path
= unit_dbus_path_from_name(name
);
2872 r
= set_put_strdup(wait_context
->unit_paths
, unit_path
);
2874 return log_error_errno(r
, "Failed to add unit path %s to set: %m", unit_path
);
2876 r
= sd_bus_match_signal_async(bus
,
2877 &wait_context
->match
,
2880 "org.freedesktop.DBus.Properties",
2881 "PropertiesChanged",
2882 on_properties_changed
, NULL
, wait_context
);
2884 return log_error_errno(r
, "Failed to request match for PropertiesChanged signal: %m");
2887 log_debug("%s dbus call org.freedesktop.systemd1.Manager %s(%s, %s)",
2888 arg_dry_run
? "Would execute" : "Executing",
2889 method
, name
, mode
);
2893 r
= sd_bus_call_method(
2895 "org.freedesktop.systemd1",
2896 "/org/freedesktop/systemd1",
2897 "org.freedesktop.systemd1.Manager",
2905 /* There's always a fallback possible for legacy actions. */
2906 if (arg_action
!= ACTION_SYSTEMCTL
)
2909 verb
= method_to_verb(method
);
2911 log_error("Failed to %s %s: %s", verb
, name
, bus_error_message(error
, r
));
2913 if (!sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) &&
2914 !sd_bus_error_has_name(error
, BUS_ERROR_UNIT_MASKED
) &&
2915 !sd_bus_error_has_name(error
, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE
))
2916 log_error("See %s logs and 'systemctl%s status%s %s' for details.",
2917 arg_scope
== UNIT_FILE_SYSTEM
? "system" : "user",
2918 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user",
2919 name
[0] == '-' ? " --" : "",
2925 r
= sd_bus_message_read(reply
, "o", &path
);
2927 return bus_log_parse_error(r
);
2929 if (need_daemon_reload(bus
, name
) > 0)
2930 warn_unit_file_changed(name
);
2933 log_debug("Adding %s to the set", path
);
2934 r
= bus_wait_for_jobs_add(w
, path
);
2942 static int expand_names(sd_bus
*bus
, char **names
, const char* suffix
, char ***ret
) {
2943 _cleanup_strv_free_
char **mangled
= NULL
, **globs
= NULL
;
2950 STRV_FOREACH(name
, names
) {
2954 r
= unit_name_mangle_with_suffix(*name
, UNIT_NAME_GLOB
, suffix
, &t
);
2956 r
= unit_name_mangle(*name
, UNIT_NAME_GLOB
, &t
);
2958 return log_error_errno(r
, "Failed to mangle name: %m");
2960 if (string_is_glob(t
))
2961 r
= strv_consume(&globs
, t
);
2963 r
= strv_consume(&mangled
, t
);
2968 /* Query the manager only if any of the names are a glob, since
2969 * this is fairly expensive */
2970 if (!strv_isempty(globs
)) {
2971 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2972 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
2973 size_t allocated
, n
;
2975 r
= get_unit_list(bus
, NULL
, globs
, &unit_infos
, 0, &reply
);
2979 n
= strv_length(mangled
);
2982 for (i
= 0; i
< r
; i
++) {
2983 if (!GREEDY_REALLOC(mangled
, allocated
, n
+2))
2986 mangled
[n
] = strdup(unit_infos
[i
].id
);
2990 mangled
[++n
] = NULL
;
2995 mangled
= NULL
; /* do not free */
3000 static const struct {
3004 } action_table
[_ACTION_MAX
] = {
3005 [ACTION_HALT
] = { SPECIAL_HALT_TARGET
, "halt", "replace-irreversibly" },
3006 [ACTION_POWEROFF
] = { SPECIAL_POWEROFF_TARGET
, "poweroff", "replace-irreversibly" },
3007 [ACTION_REBOOT
] = { SPECIAL_REBOOT_TARGET
, "reboot", "replace-irreversibly" },
3008 [ACTION_KEXEC
] = { SPECIAL_KEXEC_TARGET
, "kexec", "replace-irreversibly" },
3009 [ACTION_RUNLEVEL2
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
3010 [ACTION_RUNLEVEL3
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
3011 [ACTION_RUNLEVEL4
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
3012 [ACTION_RUNLEVEL5
] = { SPECIAL_GRAPHICAL_TARGET
, NULL
, "isolate" },
3013 [ACTION_RESCUE
] = { SPECIAL_RESCUE_TARGET
, "rescue", "isolate" },
3014 [ACTION_EMERGENCY
] = { SPECIAL_EMERGENCY_TARGET
, "emergency", "isolate" },
3015 [ACTION_DEFAULT
] = { SPECIAL_DEFAULT_TARGET
, "default", "isolate" },
3016 [ACTION_EXIT
] = { SPECIAL_EXIT_TARGET
, "exit", "replace-irreversibly" },
3017 [ACTION_SUSPEND
] = { SPECIAL_SUSPEND_TARGET
, "suspend", "replace-irreversibly" },
3018 [ACTION_HIBERNATE
] = { SPECIAL_HIBERNATE_TARGET
, "hibernate", "replace-irreversibly" },
3019 [ACTION_HYBRID_SLEEP
] = { SPECIAL_HYBRID_SLEEP_TARGET
, "hybrid-sleep", "replace-irreversibly" },
3020 [ACTION_SUSPEND_TO_HIBERNATE
] = { SPECIAL_SUSPEND_TO_HIBERNATE_TARGET
, "suspend-to-hibernate", "replace-irreversibly" },
3023 static enum action
verb_to_action(const char *verb
) {
3026 for (i
= 0; i
< _ACTION_MAX
; i
++)
3027 if (streq_ptr(action_table
[i
].verb
, verb
))
3030 return _ACTION_INVALID
;
3033 static int start_unit(int argc
, char *argv
[], void *userdata
) {
3034 _cleanup_(bus_wait_for_jobs_freep
) BusWaitForJobs
*w
= NULL
;
3035 const char *method
, *mode
, *one_name
, *suffix
= NULL
;
3036 _cleanup_strv_free_
char **names
= NULL
;
3038 _cleanup_(wait_context_free
) WaitContext wait_context
= {};
3042 if (arg_wait
&& !STR_IN_SET(argv
[0], "start", "restart")) {
3043 log_error("--wait may only be used with the 'start' or 'restart' commands.");
3047 /* we cannot do sender tracking on the private bus, so we need the full
3048 * one for RefUnit to implement --wait */
3049 r
= acquire_bus(arg_wait
? BUS_FULL
: BUS_MANAGER
, &bus
);
3053 ask_password_agent_open_if_enabled();
3054 polkit_agent_open_maybe();
3056 if (arg_action
== ACTION_SYSTEMCTL
) {
3059 action
= verb_to_action(argv
[0]);
3061 if (action
!= _ACTION_INVALID
) {
3062 method
= "StartUnit";
3063 mode
= action_table
[action
].mode
;
3064 one_name
= action_table
[action
].target
;
3066 if (streq(argv
[0], "isolate")) {
3067 method
= "StartUnit";
3072 method
= verb_to_method(argv
[0]);
3073 mode
= arg_job_mode
;
3078 assert(arg_action
>= 0 && arg_action
< _ACTION_MAX
);
3079 assert(action_table
[arg_action
].target
);
3080 assert(action_table
[arg_action
].mode
);
3082 method
= "StartUnit";
3083 mode
= action_table
[arg_action
].mode
;
3084 one_name
= action_table
[arg_action
].target
;
3088 names
= strv_new(one_name
, NULL
);
3090 r
= expand_names(bus
, strv_skip(argv
, 1), suffix
, &names
);
3092 return log_error_errno(r
, "Failed to expand names: %m");
3095 if (!arg_no_block
) {
3096 r
= bus_wait_for_jobs_new(bus
, &w
);
3098 return log_error_errno(r
, "Could not watch jobs: %m");
3102 wait_context
.unit_paths
= set_new(&string_hash_ops
);
3103 if (!wait_context
.unit_paths
)
3106 r
= sd_bus_call_method_async(
3109 "org.freedesktop.systemd1",
3110 "/org/freedesktop/systemd1",
3111 "org.freedesktop.systemd1.Manager",
3116 return log_error_errno(r
, "Failed to enable subscription: %m");
3117 r
= sd_event_default(&wait_context
.event
);
3119 return log_error_errno(r
, "Failed to allocate event loop: %m");
3120 r
= sd_bus_attach_event(bus
, wait_context
.event
, 0);
3122 return log_error_errno(r
, "Failed to attach bus to event loop: %m");
3125 STRV_FOREACH(name
, names
) {
3126 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3129 q
= start_unit_one(bus
, method
, *name
, mode
, &error
, w
, arg_wait
? &wait_context
: NULL
);
3130 if (r
>= 0 && q
< 0)
3131 r
= translate_bus_error_to_exit_status(q
, &error
);
3134 if (!arg_no_block
) {
3135 int q
, arg_count
= 0;
3136 const char* extra_args
[4] = {};
3138 if (arg_scope
!= UNIT_FILE_SYSTEM
)
3139 extra_args
[arg_count
++] = "--user";
3141 assert(IN_SET(arg_transport
, BUS_TRANSPORT_LOCAL
, BUS_TRANSPORT_REMOTE
, BUS_TRANSPORT_MACHINE
));
3142 if (arg_transport
== BUS_TRANSPORT_REMOTE
) {
3143 extra_args
[arg_count
++] = "-H";
3144 extra_args
[arg_count
++] = arg_host
;
3145 } else if (arg_transport
== BUS_TRANSPORT_MACHINE
) {
3146 extra_args
[arg_count
++] = "-M";
3147 extra_args
[arg_count
++] = arg_host
;
3150 q
= bus_wait_for_jobs(w
, arg_quiet
, extra_args
);
3154 /* When stopping units, warn if they can still be triggered by
3155 * another active unit (socket, path, timer) */
3156 if (!arg_quiet
&& streq(method
, "StopUnit"))
3157 STRV_FOREACH(name
, names
)
3158 check_triggering_units(bus
, *name
);
3161 if (r
>= 0 && arg_wait
) {
3163 q
= sd_event_loop(wait_context
.event
);
3165 return log_error_errno(q
, "Failed to run event loop: %m");
3166 if (wait_context
.any_failed
)
3174 static int logind_set_wall_message(void) {
3175 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3177 _cleanup_free_
char *m
= NULL
;
3180 r
= acquire_bus(BUS_FULL
, &bus
);
3184 m
= strv_join(arg_wall
, " ");
3188 log_debug("%s wall message \"%s\".", arg_dry_run
? "Would set" : "Setting", m
);
3192 r
= sd_bus_call_method(
3194 "org.freedesktop.login1",
3195 "/org/freedesktop/login1",
3196 "org.freedesktop.login1.Manager",
3205 return log_warning_errno(r
, "Failed to set wall message, ignoring: %s", bus_error_message(&error
, r
));
3210 /* Ask systemd-logind, which might grant access to unprivileged users
3211 * through PolicyKit */
3212 static int logind_reboot(enum action a
) {
3214 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3215 const char *method
, *description
;
3219 r
= acquire_bus(BUS_FULL
, &bus
);
3225 case ACTION_POWEROFF
:
3226 method
= "PowerOff";
3227 description
= "power off system";
3232 description
= "reboot system";
3237 description
= "halt system";
3240 case ACTION_SUSPEND
:
3242 description
= "suspend system";
3245 case ACTION_HIBERNATE
:
3246 method
= "Hibernate";
3247 description
= "hibernate system";
3250 case ACTION_HYBRID_SLEEP
:
3251 method
= "HybridSleep";
3252 description
= "put system into hybrid sleep";
3255 case ACTION_SUSPEND_TO_HIBERNATE
:
3256 method
= "SuspendToHibernate";
3257 description
= "put system into suspend followed by hibernate";
3264 polkit_agent_open_maybe();
3265 (void) logind_set_wall_message();
3267 log_debug("%s org.freedesktop.login1.Manager %s dbus call.", arg_dry_run
? "Would execute" : "Executing", method
);
3271 r
= sd_bus_call_method(
3273 "org.freedesktop.login1",
3274 "/org/freedesktop/login1",
3275 "org.freedesktop.login1.Manager",
3279 "b", arg_ask_password
);
3281 return log_error_errno(r
, "Failed to %s via logind: %s", description
, bus_error_message(&error
, r
));
3289 static int logind_check_inhibitors(enum action a
) {
3291 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
3292 _cleanup_strv_free_
char **sessions
= NULL
;
3293 const char *what
, *who
, *why
, *mode
;
3300 if (arg_ignore_inhibitors
|| arg_force
> 0)
3312 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
3315 r
= acquire_bus(BUS_FULL
, &bus
);
3319 r
= sd_bus_call_method(
3321 "org.freedesktop.login1",
3322 "/org/freedesktop/login1",
3323 "org.freedesktop.login1.Manager",
3329 /* If logind is not around, then there are no inhibitors... */
3332 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssuu)");
3334 return bus_log_parse_error(r
);
3336 while ((r
= sd_bus_message_read(reply
, "(ssssuu)", &what
, &who
, &why
, &mode
, &uid
, &pid
)) > 0) {
3337 _cleanup_free_
char *comm
= NULL
, *user
= NULL
;
3338 _cleanup_strv_free_
char **sv
= NULL
;
3340 if (!streq(mode
, "block"))
3343 sv
= strv_split(what
, ":");
3347 if (!pid_is_valid((pid_t
) pid
)) {
3348 log_error("Invalid PID "PID_FMT
".", (pid_t
) pid
);
3352 if (!strv_contains(sv
,
3357 ACTION_KEXEC
) ? "shutdown" : "sleep"))
3360 get_process_comm(pid
, &comm
);
3361 user
= uid_to_name(uid
);
3363 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT
" \"%s\", user %s), reason is \"%s\".",
3364 who
, (pid_t
) pid
, strna(comm
), strna(user
), why
);
3369 return bus_log_parse_error(r
);
3371 r
= sd_bus_message_exit_container(reply
);
3373 return bus_log_parse_error(r
);
3375 /* Check for current sessions */
3376 sd_get_sessions(&sessions
);
3377 STRV_FOREACH(s
, sessions
) {
3378 _cleanup_free_
char *type
= NULL
, *tty
= NULL
, *seat
= NULL
, *user
= NULL
, *service
= NULL
, *class = NULL
;
3380 if (sd_session_get_uid(*s
, &uid
) < 0 || uid
== getuid())
3383 if (sd_session_get_class(*s
, &class) < 0 || !streq(class, "user"))
3386 if (sd_session_get_type(*s
, &type
) < 0 || !STR_IN_SET(type
, "x11", "wayland", "tty", "mir"))
3389 sd_session_get_tty(*s
, &tty
);
3390 sd_session_get_seat(*s
, &seat
);
3391 sd_session_get_service(*s
, &service
);
3392 user
= uid_to_name(uid
);
3394 log_warning("User %s is logged in on %s.", strna(user
), isempty(tty
) ? (isempty(seat
) ? strna(service
) : seat
) : tty
);
3401 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
3402 action_table
[a
].verb
);
3410 static int logind_prepare_firmware_setup(void) {
3412 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3416 r
= acquire_bus(BUS_FULL
, &bus
);
3420 r
= sd_bus_call_method(
3422 "org.freedesktop.login1",
3423 "/org/freedesktop/login1",
3424 "org.freedesktop.login1.Manager",
3425 "SetRebootToFirmwareSetup",
3430 return log_error_errno(r
, "Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error
, r
));
3434 log_error("Cannot remotely indicate to EFI to boot into setup mode.");
3439 static int prepare_firmware_setup(void) {
3442 if (!arg_firmware_setup
)
3445 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
3447 r
= efi_set_reboot_to_firmware(true);
3449 log_debug_errno(r
, "Cannot indicate to EFI to boot into setup mode, will retry via logind: %m");
3454 return logind_prepare_firmware_setup();
3457 static int load_kexec_kernel(void) {
3458 _cleanup_(boot_config_free
) BootConfig config
= {};
3459 _cleanup_free_
char *where
= NULL
, *kernel
= NULL
, *initrd
= NULL
, *options
= NULL
;
3464 if (kexec_loaded()) {
3465 log_debug("Kexec kernel already loaded.");
3469 if (access(KEXEC
, X_OK
) < 0)
3470 return log_error_errno(errno
, KEXEC
" is not available: %m");
3472 r
= find_esp_and_warn(arg_esp_path
, false, &where
, NULL
, NULL
, NULL
, NULL
);
3473 if (r
== -ENOKEY
) /* find_esp_and_warn() doesn't warn about this case */
3474 return log_error_errno(r
, "Cannot find the ESP partition mount point.");
3475 if (r
< 0) /* But it logs about all these cases, hence don't log here again */
3478 r
= boot_entries_load_config(where
, &config
);
3480 return log_error_errno(r
, "Failed to load bootspec config from \"%s/loader\": %m", where
);
3482 if (config
.default_entry
< 0) {
3483 log_error("No entry suitable as default, refusing to guess.");
3486 e
= &config
.entries
[config
.default_entry
];
3488 if (strv_length(e
->initrd
) > 1) {
3489 log_error("Boot entry specifies multiple initrds, which is not supported currently.");
3493 kernel
= path_join(NULL
, where
, e
->kernel
);
3494 if (!strv_isempty(e
->initrd
))
3495 initrd
= path_join(NULL
, where
, *e
->initrd
);
3496 options
= strv_join(e
->options
, " ");
3500 log_full(arg_quiet
? LOG_DEBUG
: LOG_INFO
,
3501 "%s "KEXEC
" --load \"%s\" --append \"%s\"%s%s%s",
3502 arg_dry_run
? "Would run" : "Running",
3505 initrd
? " --initrd \"" : NULL
, strempty(initrd
), initrd
? "\"" : "");
3509 r
= safe_fork("(kexec)", FORK_RESET_SIGNALS
|FORK_DEATHSIG
|FORK_LOG
, &pid
);
3513 const char* const args
[] = {
3516 "--append", options
,
3517 initrd
? "--initrd" : NULL
, initrd
,
3521 execv(args
[0], (char * const *) args
);
3522 _exit(EXIT_FAILURE
);
3525 r
= wait_for_terminate_and_check("kexec", pid
, WAIT_LOG
);
3529 /* Command failed */
3534 static int set_exit_code(uint8_t code
) {
3535 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3539 r
= acquire_bus(BUS_MANAGER
, &bus
);
3543 r
= sd_bus_call_method(
3545 "org.freedesktop.systemd1",
3546 "/org/freedesktop/systemd1",
3547 "org.freedesktop.systemd1.Manager",
3553 return log_error_errno(r
, "Failed to set exit code: %s", bus_error_message(&error
, r
));
3558 static int start_special(int argc
, char *argv
[], void *userdata
) {
3561 bool termination_action
; /* an action that terminates the manager,
3562 * can be performed also by signal. */
3566 a
= verb_to_action(argv
[0]);
3568 r
= logind_check_inhibitors(a
);
3572 if (arg_force
>= 2) {
3578 r
= prepare_firmware_setup();
3582 if (a
== ACTION_REBOOT
&& argc
> 1) {
3583 r
= update_reboot_parameter_and_warn(argv
[1]);
3587 } else if (a
== ACTION_KEXEC
) {
3588 r
= load_kexec_kernel();
3589 if (r
< 0 && arg_force
>= 1)
3590 log_notice("Failed to load kexec kernel, continuing without.");
3594 } else if (a
== ACTION_EXIT
&& argc
> 1) {
3597 /* If the exit code is not given on the command line,
3598 * don't reset it to zero: just keep it as it might
3599 * have been set previously. */
3601 r
= safe_atou8(argv
[1], &code
);
3603 return log_error_errno(r
, "Invalid exit code.");
3605 r
= set_exit_code(code
);
3610 termination_action
= IN_SET(a
,
3614 if (termination_action
&& arg_force
>= 2)
3617 if (arg_force
>= 1 &&
3618 (termination_action
|| IN_SET(a
, ACTION_KEXEC
, ACTION_EXIT
)))
3619 r
= trivial_method(argc
, argv
, userdata
);
3621 /* First try logind, to allow authentication with polkit */
3628 ACTION_HYBRID_SLEEP
,
3629 ACTION_SUSPEND_TO_HIBERNATE
)) {
3631 r
= logind_reboot(a
);
3634 if (IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
3635 /* requested operation is not supported or already in progress */
3638 /* On all other errors, try low-level operation. In order to minimize the difference between
3639 * operation with and without logind, we explicitly enable non-blocking mode for this, as
3640 * logind's shutdown operations are always non-blocking. */
3642 arg_no_block
= true;
3644 } else if (IN_SET(a
, ACTION_EXIT
, ACTION_KEXEC
))
3645 /* Since exit/kexec are so close in behaviour to power-off/reboot, let's also make them
3646 * asynchronous, in order to not confuse the user needlessly with unexpected behaviour. */
3647 arg_no_block
= true;
3649 r
= start_unit(argc
, argv
, userdata
);
3652 if (termination_action
&& arg_force
< 2 &&
3653 IN_SET(r
, -ENOENT
, -ETIMEDOUT
))
3654 log_notice("It is possible to perform action directly, see discussion of --force --force in man:systemctl(1).");
3659 static int start_system_special(int argc
, char *argv
[], void *userdata
) {
3660 /* Like start_special above, but raises an error when running in user mode */
3662 if (arg_scope
!= UNIT_FILE_SYSTEM
) {
3663 log_error("Bad action for %s mode.",
3664 arg_scope
== UNIT_FILE_GLOBAL
? "--global" : "--user");
3668 return start_special(argc
, argv
, userdata
);
3671 static int check_unit_generic(int code
, const UnitActiveState good_states
[], int nb_states
, char **args
) {
3672 _cleanup_strv_free_
char **names
= NULL
;
3673 UnitActiveState active_state
;
3679 r
= acquire_bus(BUS_MANAGER
, &bus
);
3683 r
= expand_names(bus
, args
, NULL
, &names
);
3685 return log_error_errno(r
, "Failed to expand names: %m");
3687 STRV_FOREACH(name
, names
) {
3688 r
= get_state_one_unit(bus
, *name
, &active_state
);
3693 puts(unit_active_state_to_string(active_state
));
3695 for (i
= 0; i
< nb_states
; ++i
)
3696 if (good_states
[i
] == active_state
)
3700 /* use the given return code for the case that we won't find
3701 * any unit which matches the list */
3702 return found
? 0 : code
;
3705 static int check_unit_active(int argc
, char *argv
[], void *userdata
) {
3706 const UnitActiveState states
[] = { UNIT_ACTIVE
, UNIT_RELOADING
};
3707 /* According to LSB: 3, "program is not running" */
3708 return check_unit_generic(EXIT_PROGRAM_NOT_RUNNING
, states
, ELEMENTSOF(states
), strv_skip(argv
, 1));
3711 static int check_unit_failed(int argc
, char *argv
[], void *userdata
) {
3712 const UnitActiveState states
[] = { UNIT_FAILED
};
3713 return check_unit_generic(EXIT_PROGRAM_DEAD_AND_PID_EXISTS
, states
, ELEMENTSOF(states
), strv_skip(argv
, 1));
3716 static int kill_unit(int argc
, char *argv
[], void *userdata
) {
3717 _cleanup_strv_free_
char **names
= NULL
;
3718 char *kill_who
= NULL
, **name
;
3722 r
= acquire_bus(BUS_MANAGER
, &bus
);
3726 polkit_agent_open_maybe();
3729 arg_kill_who
= "all";
3731 /* --fail was specified */
3732 if (streq(arg_job_mode
, "fail"))
3733 kill_who
= strjoina(arg_kill_who
, "-fail");
3735 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
3737 return log_error_errno(r
, "Failed to expand names: %m");
3739 STRV_FOREACH(name
, names
) {
3740 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3742 q
= sd_bus_call_method(
3744 "org.freedesktop.systemd1",
3745 "/org/freedesktop/systemd1",
3746 "org.freedesktop.systemd1.Manager",
3750 "ssi", *name
, kill_who
? kill_who
: arg_kill_who
, arg_signal
);
3752 log_error_errno(q
, "Failed to kill unit %s: %s", *name
, bus_error_message(&error
, q
));
3761 typedef struct ExecStatusInfo
{
3769 usec_t start_timestamp
;
3770 usec_t exit_timestamp
;
3775 LIST_FIELDS(struct ExecStatusInfo
, exec
);
3778 static void exec_status_info_free(ExecStatusInfo
*i
) {
3787 static int exec_status_info_deserialize(sd_bus_message
*m
, ExecStatusInfo
*i
) {
3788 uint64_t start_timestamp
, exit_timestamp
, start_timestamp_monotonic
, exit_timestamp_monotonic
;
3791 int32_t code
, status
;
3797 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_STRUCT
, "sasbttttuii");
3799 return bus_log_parse_error(r
);
3803 r
= sd_bus_message_read(m
, "s", &path
);
3805 return bus_log_parse_error(r
);
3807 i
->path
= strdup(path
);
3811 r
= sd_bus_message_read_strv(m
, &i
->argv
);
3813 return bus_log_parse_error(r
);
3815 r
= sd_bus_message_read(m
,
3818 &start_timestamp
, &start_timestamp_monotonic
,
3819 &exit_timestamp
, &exit_timestamp_monotonic
,
3823 return bus_log_parse_error(r
);
3826 i
->start_timestamp
= (usec_t
) start_timestamp
;
3827 i
->exit_timestamp
= (usec_t
) exit_timestamp
;
3828 i
->pid
= (pid_t
) pid
;
3832 r
= sd_bus_message_exit_container(m
);
3834 return bus_log_parse_error(r
);
3839 typedef struct UnitCondition
{
3846 LIST_FIELDS(struct UnitCondition
, conditions
);
3849 static void unit_condition_free(UnitCondition
*c
) {
3858 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitCondition
*, unit_condition_free
);
3860 typedef struct UnitStatusInfo
{
3862 const char *load_state
;
3863 const char *active_state
;
3864 const char *sub_state
;
3865 const char *unit_file_state
;
3866 const char *unit_file_preset
;
3868 const char *description
;
3869 const char *following
;
3871 char **documentation
;
3873 const char *fragment_path
;
3874 const char *source_path
;
3875 const char *control_group
;
3877 char **dropin_paths
;
3879 const char *load_error
;
3882 usec_t inactive_exit_timestamp
;
3883 usec_t inactive_exit_timestamp_monotonic
;
3884 usec_t active_enter_timestamp
;
3885 usec_t active_exit_timestamp
;
3886 usec_t inactive_enter_timestamp
;
3888 bool need_daemon_reload
;
3894 const char *status_text
;
3895 const char *pid_file
;
3899 usec_t start_timestamp
;
3900 usec_t exit_timestamp
;
3902 int exit_code
, exit_status
;
3904 usec_t condition_timestamp
;
3905 bool condition_result
;
3906 LIST_HEAD(UnitCondition
, conditions
);
3908 usec_t assert_timestamp
;
3910 bool failed_assert_trigger
;
3911 bool failed_assert_negate
;
3912 const char *failed_assert
;
3913 const char *failed_assert_parameter
;
3914 usec_t next_elapse_real
;
3915 usec_t next_elapse_monotonic
;
3918 unsigned n_accepted
;
3919 unsigned n_connections
;
3922 /* Pairs of type, path */
3926 const char *sysfs_path
;
3928 /* Mount, Automount */
3935 uint64_t memory_current
;
3936 uint64_t memory_low
;
3937 uint64_t memory_high
;
3938 uint64_t memory_max
;
3939 uint64_t memory_swap_max
;
3940 uint64_t memory_limit
;
3941 uint64_t cpu_usage_nsec
;
3942 uint64_t tasks_current
;
3945 uint64_t ip_ingress_bytes
;
3946 uint64_t ip_egress_bytes
;
3948 LIST_HEAD(ExecStatusInfo
, exec
);
3951 static void unit_status_info_free(UnitStatusInfo
*info
) {
3955 strv_free(info
->documentation
);
3956 strv_free(info
->dropin_paths
);
3957 strv_free(info
->listen
);
3959 while ((c
= info
->conditions
)) {
3960 LIST_REMOVE(conditions
, info
->conditions
, c
);
3961 unit_condition_free(c
);
3964 while ((p
= info
->exec
)) {
3965 LIST_REMOVE(exec
, info
->exec
, p
);
3966 exec_status_info_free(p
);
3970 static void print_status_info(
3976 const char *active_on
, *active_off
, *on
, *off
, *ss
;
3978 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], *s1
;
3979 char since2
[FORMAT_TIMESTAMP_MAX
], *s2
;
3986 /* This shows pretty information about a unit. See
3987 * print_property() for a low-level property printer */
3989 if (streq_ptr(i
->active_state
, "failed")) {
3990 active_on
= ansi_highlight_red();
3991 active_off
= ansi_normal();
3992 } else if (STRPTR_IN_SET(i
->active_state
, "active", "reloading")) {
3993 active_on
= ansi_highlight_green();
3994 active_off
= ansi_normal();
3996 active_on
= active_off
= "";
3998 printf("%s%s%s %s", active_on
, special_glyph(BLACK_CIRCLE
), active_off
, strna(i
->id
));
4000 if (i
->description
&& !streq_ptr(i
->id
, i
->description
))
4001 printf(" - %s", i
->description
);
4006 printf(" Follow: unit currently follows state of %s\n", i
->following
);
4008 if (streq_ptr(i
->load_state
, "error")) {
4009 on
= ansi_highlight_red();
4010 off
= ansi_normal();
4014 path
= i
->source_path
? i
->source_path
: i
->fragment_path
;
4016 if (i
->load_error
!= 0)
4017 printf(" Loaded: %s%s%s (Reason: %s)\n",
4018 on
, strna(i
->load_state
), off
, i
->load_error
);
4019 else if (path
&& !isempty(i
->unit_file_state
) && !isempty(i
->unit_file_preset
) &&
4020 !STR_IN_SET(i
->unit_file_state
, "generated", "transient"))
4021 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
4022 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
, i
->unit_file_preset
);
4023 else if (path
&& !isempty(i
->unit_file_state
))
4024 printf(" Loaded: %s%s%s (%s; %s)\n",
4025 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
);
4027 printf(" Loaded: %s%s%s (%s)\n",
4028 on
, strna(i
->load_state
), off
, path
);
4030 printf(" Loaded: %s%s%s\n",
4031 on
, strna(i
->load_state
), off
);
4034 printf("Transient: yes\n");
4036 if (!strv_isempty(i
->dropin_paths
)) {
4037 _cleanup_free_
char *dir
= NULL
;
4041 STRV_FOREACH(dropin
, i
->dropin_paths
) {
4042 if (! dir
|| last
) {
4043 printf(dir
? " " : " Drop-In: ");
4047 dir
= dirname_malloc(*dropin
);
4053 printf("%s\n %s", dir
,
4054 special_glyph(TREE_RIGHT
));
4057 last
= ! (*(dropin
+ 1) && startswith(*(dropin
+ 1), dir
));
4059 printf("%s%s", basename(*dropin
), last
? "\n" : ", ");
4063 ss
= streq_ptr(i
->active_state
, i
->sub_state
) ? NULL
: i
->sub_state
;
4065 printf(" Active: %s%s (%s)%s",
4066 active_on
, strna(i
->active_state
), ss
, active_off
);
4068 printf(" Active: %s%s%s",
4069 active_on
, strna(i
->active_state
), active_off
);
4071 if (!isempty(i
->result
) && !streq(i
->result
, "success"))
4072 printf(" (Result: %s)", i
->result
);
4074 timestamp
= STRPTR_IN_SET(i
->active_state
, "active", "reloading") ? i
->active_enter_timestamp
:
4075 STRPTR_IN_SET(i
->active_state
, "inactive", "failed") ? i
->inactive_enter_timestamp
:
4076 STRPTR_IN_SET(i
->active_state
, "activating") ? i
->inactive_exit_timestamp
:
4077 i
->active_exit_timestamp
;
4079 s1
= format_timestamp_relative(since1
, sizeof(since1
), timestamp
);
4080 s2
= format_timestamp(since2
, sizeof(since2
), timestamp
);
4083 printf(" since %s; %s\n", s2
, s1
);
4085 printf(" since %s\n", s2
);
4089 if (endswith(i
->id
, ".timer")) {
4090 char tstamp1
[FORMAT_TIMESTAMP_RELATIVE_MAX
],
4091 tstamp2
[FORMAT_TIMESTAMP_MAX
];
4092 char *next_rel_time
, *next_time
;
4093 dual_timestamp nw
, next
= {i
->next_elapse_real
,
4094 i
->next_elapse_monotonic
};
4097 printf(" Trigger: ");
4099 dual_timestamp_get(&nw
);
4100 next_elapse
= calc_next_elapse(&nw
, &next
);
4101 next_rel_time
= format_timestamp_relative(tstamp1
,
4104 next_time
= format_timestamp(tstamp2
,
4108 if (next_time
&& next_rel_time
)
4109 printf("%s; %s\n", next_time
, next_rel_time
);
4114 if (!i
->condition_result
&& i
->condition_timestamp
> 0) {
4118 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->condition_timestamp
);
4119 s2
= format_timestamp(since2
, sizeof(since2
), i
->condition_timestamp
);
4121 printf("Condition: start %scondition failed%s at %s%s%s\n",
4122 ansi_highlight_yellow(), ansi_normal(),
4123 s2
, s1
? "; " : "", strempty(s1
));
4125 LIST_FOREACH(conditions
, c
, i
->conditions
)
4126 if (c
->tristate
< 0)
4129 LIST_FOREACH(conditions
, c
, i
->conditions
)
4130 if (c
->tristate
< 0)
4131 printf(" %s %s=%s%s%s was not met\n",
4132 --n
? special_glyph(TREE_BRANCH
) : special_glyph(TREE_RIGHT
),
4134 c
->trigger
? "|" : "",
4135 c
->negate
? "!" : "",
4139 if (!i
->assert_result
&& i
->assert_timestamp
> 0) {
4140 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->assert_timestamp
);
4141 s2
= format_timestamp(since2
, sizeof(since2
), i
->assert_timestamp
);
4143 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
4144 ansi_highlight_red(), ansi_normal(),
4145 s2
, s1
? "; " : "", strempty(s1
));
4146 if (i
->failed_assert_trigger
)
4147 printf(" none of the trigger assertions were met\n");
4148 else if (i
->failed_assert
)
4149 printf(" %s=%s%s was not met\n",
4151 i
->failed_assert_negate
? "!" : "",
4152 i
->failed_assert_parameter
);
4156 printf(" Device: %s\n", i
->sysfs_path
);
4158 printf(" Where: %s\n", i
->where
);
4160 printf(" What: %s\n", i
->what
);
4162 STRV_FOREACH(t
, i
->documentation
)
4163 printf(" %*s %s\n", 9, t
== i
->documentation
? "Docs:" : "", *t
);
4165 STRV_FOREACH_PAIR(t
, t2
, i
->listen
)
4166 printf(" %*s %s (%s)\n", 9, t
== i
->listen
? "Listen:" : "", *t2
, *t
);
4169 printf(" Accepted: %u; Connected: %u\n", i
->n_accepted
, i
->n_connections
);
4171 LIST_FOREACH(exec
, p
, i
->exec
) {
4172 _cleanup_free_
char *argv
= NULL
;
4175 /* Only show exited processes here */
4179 argv
= strv_join(p
->argv
, " ");
4180 printf(" Process: "PID_FMT
" %s=%s ", p
->pid
, p
->name
, strna(argv
));
4182 good
= is_clean_exit(p
->code
, p
->status
, EXIT_CLEAN_DAEMON
, NULL
);
4184 on
= ansi_highlight_red();
4185 off
= ansi_normal();
4189 printf("%s(code=%s, ", on
, sigchld_code_to_string(p
->code
));
4191 if (p
->code
== CLD_EXITED
) {
4194 printf("status=%i", p
->status
);
4196 c
= exit_status_to_string(p
->status
, EXIT_STATUS_SYSTEMD
);
4201 printf("signal=%s", signal_to_string(p
->status
));
4203 printf(")%s\n", off
);
4205 if (i
->main_pid
== p
->pid
&&
4206 i
->start_timestamp
== p
->start_timestamp
&&
4207 i
->exit_timestamp
== p
->start_timestamp
)
4208 /* Let's not show this twice */
4211 if (p
->pid
== i
->control_pid
)
4215 if (i
->main_pid
> 0 || i
->control_pid
> 0) {
4216 if (i
->main_pid
> 0) {
4217 printf(" Main PID: "PID_FMT
, i
->main_pid
);
4221 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
4222 _cleanup_free_
char *comm
= NULL
;
4224 (void) get_process_comm(i
->main_pid
, &comm
);
4226 printf(" (%s)", comm
);
4229 } else if (i
->exit_code
> 0) {
4230 printf(" (code=%s, ", sigchld_code_to_string(i
->exit_code
));
4232 if (i
->exit_code
== CLD_EXITED
) {
4235 printf("status=%i", i
->exit_status
);
4237 c
= exit_status_to_string(i
->exit_status
, EXIT_STATUS_SYSTEMD
);
4242 printf("signal=%s", signal_to_string(i
->exit_status
));
4247 if (i
->control_pid
> 0) {
4248 _cleanup_free_
char *c
= NULL
;
4250 if (i
->main_pid
> 0)
4251 fputs("; Control PID: ", stdout
);
4253 fputs("Cntrl PID: ", stdout
); /* if first in column, abbreviated so it fits alignment */
4255 printf(PID_FMT
, i
->control_pid
);
4257 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
4258 (void) get_process_comm(i
->control_pid
, &c
);
4268 printf(" Status: \"%s\"\n", i
->status_text
);
4269 if (i
->status_errno
> 0)
4270 printf(" Error: %i (%s)\n", i
->status_errno
, strerror(i
->status_errno
));
4272 if (i
->ip_ingress_bytes
!= (uint64_t) -1 && i
->ip_egress_bytes
!= (uint64_t) -1) {
4273 char buf_in
[FORMAT_BYTES_MAX
], buf_out
[FORMAT_BYTES_MAX
];
4275 printf(" IP: %s in, %s out\n",
4276 format_bytes(buf_in
, sizeof(buf_in
), i
->ip_ingress_bytes
),
4277 format_bytes(buf_out
, sizeof(buf_out
), i
->ip_egress_bytes
));
4280 if (i
->tasks_current
!= (uint64_t) -1) {
4281 printf(" Tasks: %" PRIu64
, i
->tasks_current
);
4283 if (i
->tasks_max
!= (uint64_t) -1)
4284 printf(" (limit: %" PRIu64
")\n", i
->tasks_max
);
4289 if (i
->memory_current
!= (uint64_t) -1) {
4290 char buf
[FORMAT_BYTES_MAX
];
4292 printf(" Memory: %s", format_bytes(buf
, sizeof(buf
), i
->memory_current
));
4294 if (i
->memory_low
> 0 || i
->memory_high
!= CGROUP_LIMIT_MAX
||
4295 i
->memory_max
!= CGROUP_LIMIT_MAX
|| i
->memory_swap_max
!= CGROUP_LIMIT_MAX
||
4296 i
->memory_limit
!= CGROUP_LIMIT_MAX
) {
4297 const char *prefix
= "";
4300 if (i
->memory_low
> 0) {
4301 printf("%slow: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_low
));
4304 if (i
->memory_high
!= CGROUP_LIMIT_MAX
) {
4305 printf("%shigh: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_high
));
4308 if (i
->memory_max
!= CGROUP_LIMIT_MAX
) {
4309 printf("%smax: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_max
));
4312 if (i
->memory_swap_max
!= CGROUP_LIMIT_MAX
) {
4313 printf("%sswap max: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_swap_max
));
4316 if (i
->memory_limit
!= CGROUP_LIMIT_MAX
) {
4317 printf("%slimit: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_limit
));
4325 if (i
->cpu_usage_nsec
!= (uint64_t) -1) {
4326 char buf
[FORMAT_TIMESPAN_MAX
];
4327 printf(" CPU: %s\n", format_timespan(buf
, sizeof(buf
), i
->cpu_usage_nsec
/ NSEC_PER_USEC
, USEC_PER_MSEC
));
4330 if (i
->control_group
) {
4331 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
4332 static const char prefix
[] = " ";
4335 printf(" CGroup: %s\n", i
->control_group
);
4338 if (c
> sizeof(prefix
) - 1)
4339 c
-= sizeof(prefix
) - 1;
4343 r
= unit_show_processes(bus
, i
->id
, i
->control_group
, prefix
, c
, get_output_flags(), &error
);
4348 /* Fallback for older systemd versions where the GetUnitProcesses() call is not yet available */
4350 if (i
->main_pid
> 0)
4351 extra
[k
++] = i
->main_pid
;
4353 if (i
->control_pid
> 0)
4354 extra
[k
++] = i
->control_pid
;
4356 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, prefix
, c
, extra
, k
, get_output_flags());
4358 log_warning_errno(r
, "Failed to dump process list, ignoring: %s", bus_error_message(&error
, r
));
4361 if (i
->id
&& arg_transport
== BUS_TRANSPORT_LOCAL
)
4362 show_journal_by_unit(
4367 i
->inactive_exit_timestamp_monotonic
,
4370 get_output_flags() | OUTPUT_BEGIN_NEWLINE
,
4371 SD_JOURNAL_LOCAL_ONLY
,
4372 arg_scope
== UNIT_FILE_SYSTEM
,
4375 if (i
->need_daemon_reload
)
4376 warn_unit_file_changed(i
->id
);
4379 static void show_unit_help(UnitStatusInfo
*i
) {
4384 if (!i
->documentation
) {
4385 log_info("Documentation for %s not known.", i
->id
);
4389 STRV_FOREACH(p
, i
->documentation
)
4390 if (startswith(*p
, "man:"))
4391 show_man_page(*p
+ 4, false);
4393 log_info("Can't show: %s", *p
);
4396 static int map_main_pid(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
4397 UnitStatusInfo
*i
= userdata
;
4401 r
= sd_bus_message_read(m
, "u", &u
);
4405 i
->main_pid
= (pid_t
) u
;
4411 static int map_load_error(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
4412 const char *n
, *message
;
4413 const char **p
= userdata
;
4416 r
= sd_bus_message_read(m
, "(ss)", &n
, &message
);
4420 if (!isempty(message
))
4426 static int map_listen(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
4427 const char *type
, *path
;
4428 char ***p
= userdata
;
4431 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4435 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0) {
4437 r
= strv_extend(p
, type
);
4441 r
= strv_extend(p
, path
);
4448 r
= sd_bus_message_exit_container(m
);
4455 static int map_conditions(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
4456 UnitStatusInfo
*i
= userdata
;
4457 const char *cond
, *param
;
4458 int trigger
, negate
;
4462 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
4466 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
4467 _cleanup_(unit_condition_freep
) UnitCondition
*c
= NULL
;
4469 c
= new0(UnitCondition
, 1);
4473 c
->name
= strdup(cond
);
4474 c
->param
= strdup(param
);
4475 if (!c
->name
|| !c
->param
)
4478 c
->trigger
= trigger
;
4480 c
->tristate
= state
;
4482 LIST_PREPEND(conditions
, i
->conditions
, c
);
4488 r
= sd_bus_message_exit_container(m
);
4495 static int map_asserts(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
4496 UnitStatusInfo
*i
= userdata
;
4497 const char *cond
, *param
;
4498 int trigger
, negate
;
4502 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
4506 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
4507 if (state
< 0 && (!trigger
|| !i
->failed_assert
)) {
4508 i
->failed_assert
= cond
;
4509 i
->failed_assert_trigger
= trigger
;
4510 i
->failed_assert_negate
= negate
;
4511 i
->failed_assert_parameter
= param
;
4517 r
= sd_bus_message_exit_container(m
);
4524 static int map_exec(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
4525 _cleanup_free_ ExecStatusInfo
*info
= NULL
;
4526 UnitStatusInfo
*i
= userdata
;
4529 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4533 info
= new0(ExecStatusInfo
, 1);
4537 while ((r
= exec_status_info_deserialize(m
, info
)) > 0) {
4539 info
->name
= strdup(member
);
4543 LIST_PREPEND(exec
, i
->exec
, info
);
4545 info
= new0(ExecStatusInfo
, 1);
4552 r
= sd_bus_message_exit_container(m
);
4559 #define print_prop(name, fmt, ...) \
4562 printf(fmt "\n", __VA_ARGS__); \
4564 printf("%s=" fmt "\n", name, __VA_ARGS__); \
4567 static int print_property(const char *name
, sd_bus_message
*m
, bool value
, bool all
) {
4569 const char *contents
;
4575 /* This is a low-level property printer, see
4576 * print_status_info() for the nicer output */
4578 r
= sd_bus_message_peek_type(m
, &bus_type
, &contents
);
4584 case SD_BUS_TYPE_STRUCT
:
4586 if (contents
[0] == SD_BUS_TYPE_UINT32
&& streq(name
, "Job")) {
4589 r
= sd_bus_message_read(m
, "(uo)", &u
, NULL
);
4591 return bus_log_parse_error(r
);
4594 print_prop(name
, "%"PRIu32
, u
);
4596 print_prop(name
, "%s", "");
4600 } else if (contents
[0] == SD_BUS_TYPE_STRING
&& streq(name
, "Unit")) {
4603 r
= sd_bus_message_read(m
, "(so)", &s
, NULL
);
4605 return bus_log_parse_error(r
);
4607 if (all
|| !isempty(s
))
4608 print_prop(name
, "%s", s
);
4612 } else if (contents
[0] == SD_BUS_TYPE_STRING
&& streq(name
, "LoadError")) {
4613 const char *a
= NULL
, *b
= NULL
;
4615 r
= sd_bus_message_read(m
, "(ss)", &a
, &b
);
4617 return bus_log_parse_error(r
);
4619 if (all
|| !isempty(a
) || !isempty(b
))
4620 print_prop(name
, "%s \"%s\"", strempty(a
), strempty(b
));
4623 } else if (streq_ptr(name
, "SystemCallFilter")) {
4624 _cleanup_strv_free_
char **l
= NULL
;
4627 r
= sd_bus_message_enter_container(m
, 'r', "bas");
4629 return bus_log_parse_error(r
);
4631 r
= sd_bus_message_read(m
, "b", &whitelist
);
4633 return bus_log_parse_error(r
);
4635 r
= sd_bus_message_read_strv(m
, &l
);
4637 return bus_log_parse_error(r
);
4639 r
= sd_bus_message_exit_container(m
);
4641 return bus_log_parse_error(r
);
4643 if (all
|| whitelist
|| !strv_isempty(l
)) {
4648 fputs(name
, stdout
);
4655 STRV_FOREACH(i
, l
) {
4663 fputc('\n', stdout
);
4671 case SD_BUS_TYPE_ARRAY
:
4673 if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "EnvironmentFiles")) {
4677 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sb)");
4679 return bus_log_parse_error(r
);
4681 while ((r
= sd_bus_message_read(m
, "(sb)", &path
, &ignore
)) > 0)
4682 print_prop(name
, "%s (ignore_errors=%s)", path
, yes_no(ignore
));
4685 return bus_log_parse_error(r
);
4687 r
= sd_bus_message_exit_container(m
);
4689 return bus_log_parse_error(r
);
4693 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Paths")) {
4694 const char *type
, *path
;
4696 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4698 return bus_log_parse_error(r
);
4700 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4701 print_prop(name
, "%s (%s)", path
, type
);
4703 return bus_log_parse_error(r
);
4705 r
= sd_bus_message_exit_container(m
);
4707 return bus_log_parse_error(r
);
4711 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
4712 const char *type
, *path
;
4714 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4716 return bus_log_parse_error(r
);
4718 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4719 print_prop(name
, "%s (%s)", path
, type
);
4721 return bus_log_parse_error(r
);
4723 r
= sd_bus_message_exit_container(m
);
4725 return bus_log_parse_error(r
);
4729 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "TimersMonotonic")) {
4731 uint64_t v
, next_elapse
;
4733 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(stt)");
4735 return bus_log_parse_error(r
);
4737 while ((r
= sd_bus_message_read(m
, "(stt)", &base
, &v
, &next_elapse
)) > 0) {
4738 char timespan1
[FORMAT_TIMESPAN_MAX
], timespan2
[FORMAT_TIMESPAN_MAX
];
4740 print_prop(name
, "{ %s=%s ; next_elapse=%s }", base
,
4741 format_timespan(timespan1
, sizeof(timespan1
), v
, 0),
4742 format_timespan(timespan2
, sizeof(timespan2
), next_elapse
, 0));
4745 return bus_log_parse_error(r
);
4747 r
= sd_bus_message_exit_container(m
);
4749 return bus_log_parse_error(r
);
4753 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "TimersCalendar")) {
4754 const char *base
, *spec
;
4755 uint64_t next_elapse
;
4757 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sst)");
4759 return bus_log_parse_error(r
);
4761 while ((r
= sd_bus_message_read(m
, "(sst)", &base
, &spec
, &next_elapse
)) > 0) {
4762 char timestamp
[FORMAT_TIMESTAMP_MAX
];
4764 print_prop(name
, "{ %s=%s ; next_elapse=%s }", base
, spec
,
4765 format_timestamp(timestamp
, sizeof(timestamp
), next_elapse
));
4768 return bus_log_parse_error(r
);
4770 r
= sd_bus_message_exit_container(m
);
4772 return bus_log_parse_error(r
);
4776 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
4777 ExecStatusInfo info
= {};
4779 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4781 return bus_log_parse_error(r
);
4783 while ((r
= exec_status_info_deserialize(m
, &info
)) > 0) {
4784 char timestamp1
[FORMAT_TIMESTAMP_MAX
], timestamp2
[FORMAT_TIMESTAMP_MAX
];
4785 _cleanup_free_
char *tt
;
4787 tt
= strv_join(info
.argv
, " ");
4790 "{ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT
" ; code=%s ; status=%i%s%s }",
4793 yes_no(info
.ignore
),
4794 strna(format_timestamp(timestamp1
, sizeof(timestamp1
), info
.start_timestamp
)),
4795 strna(format_timestamp(timestamp2
, sizeof(timestamp2
), info
.exit_timestamp
)),
4797 sigchld_code_to_string(info
.code
),
4799 info
.code
== CLD_EXITED
? "" : "/",
4800 strempty(info
.code
== CLD_EXITED
? NULL
: signal_to_string(info
.status
)));
4803 strv_free(info
.argv
);
4807 r
= sd_bus_message_exit_container(m
);
4809 return bus_log_parse_error(r
);
4813 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "DeviceAllow")) {
4814 const char *path
, *rwm
;
4816 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4818 return bus_log_parse_error(r
);
4820 while ((r
= sd_bus_message_read(m
, "(ss)", &path
, &rwm
)) > 0)
4821 print_prop(name
, "%s %s", strna(path
), strna(rwm
));
4823 return bus_log_parse_error(r
);
4825 r
= sd_bus_message_exit_container(m
);
4827 return bus_log_parse_error(r
);
4831 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&&
4832 STR_IN_SET(name
, "IODeviceWeight", "BlockIODeviceWeight")) {
4836 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4838 return bus_log_parse_error(r
);
4840 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &weight
)) > 0)
4841 print_prop(name
, "%s %"PRIu64
, strna(path
), weight
);
4843 return bus_log_parse_error(r
);
4845 r
= sd_bus_message_exit_container(m
);
4847 return bus_log_parse_error(r
);
4851 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&&
4852 (cgroup_io_limit_type_from_string(name
) >= 0 ||
4853 STR_IN_SET(name
, "BlockIOReadBandwidth", "BlockIOWriteBandwidth"))) {
4857 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4859 return bus_log_parse_error(r
);
4861 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &bandwidth
)) > 0)
4862 print_prop(name
, "%s %"PRIu64
, strna(path
), bandwidth
);
4864 return bus_log_parse_error(r
);
4866 r
= sd_bus_message_exit_container(m
);
4868 return bus_log_parse_error(r
);
4872 } else if (contents
[0] == SD_BUS_TYPE_BYTE
&& streq(name
, "StandardInputData")) {
4873 _cleanup_free_
char *h
= NULL
;
4878 r
= sd_bus_message_read_array(m
, 'y', &p
, &sz
);
4880 return bus_log_parse_error(r
);
4882 n
= base64mem(p
, sz
, &h
);
4886 print_prop(name
, "%s", h
);
4897 typedef enum SystemctlShowMode
{
4898 SYSTEMCTL_SHOW_PROPERTIES
,
4899 SYSTEMCTL_SHOW_STATUS
,
4900 SYSTEMCTL_SHOW_HELP
,
4901 _SYSTEMCTL_SHOW_MODE_MAX
,
4902 _SYSTEMCTL_SHOW_MODE_INVALID
= -1,
4903 } SystemctlShowMode
;
4905 static const char* const systemctl_show_mode_table
[] = {
4906 [SYSTEMCTL_SHOW_PROPERTIES
] = "show",
4907 [SYSTEMCTL_SHOW_STATUS
] = "status",
4908 [SYSTEMCTL_SHOW_HELP
] = "help",
4911 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(systemctl_show_mode
, SystemctlShowMode
);
4913 static int show_one(
4917 SystemctlShowMode show_mode
,
4921 static const struct bus_properties_map property_map
[] = {
4922 { "LoadState", "s", NULL
, offsetof(UnitStatusInfo
, load_state
) },
4923 { "ActiveState", "s", NULL
, offsetof(UnitStatusInfo
, active_state
) },
4924 { "Documentation", "as", NULL
, offsetof(UnitStatusInfo
, documentation
) },
4927 { "Id", "s", NULL
, offsetof(UnitStatusInfo
, id
) },
4928 { "LoadState", "s", NULL
, offsetof(UnitStatusInfo
, load_state
) },
4929 { "ActiveState", "s", NULL
, offsetof(UnitStatusInfo
, active_state
) },
4930 { "SubState", "s", NULL
, offsetof(UnitStatusInfo
, sub_state
) },
4931 { "UnitFileState", "s", NULL
, offsetof(UnitStatusInfo
, unit_file_state
) },
4932 { "UnitFilePreset", "s", NULL
, offsetof(UnitStatusInfo
, unit_file_preset
) },
4933 { "Description", "s", NULL
, offsetof(UnitStatusInfo
, description
) },
4934 { "Following", "s", NULL
, offsetof(UnitStatusInfo
, following
) },
4935 { "Documentation", "as", NULL
, offsetof(UnitStatusInfo
, documentation
) },
4936 { "FragmentPath", "s", NULL
, offsetof(UnitStatusInfo
, fragment_path
) },
4937 { "SourcePath", "s", NULL
, offsetof(UnitStatusInfo
, source_path
) },
4938 { "ControlGroup", "s", NULL
, offsetof(UnitStatusInfo
, control_group
) },
4939 { "DropInPaths", "as", NULL
, offsetof(UnitStatusInfo
, dropin_paths
) },
4940 { "LoadError", "(ss)", map_load_error
, offsetof(UnitStatusInfo
, load_error
) },
4941 { "Result", "s", NULL
, offsetof(UnitStatusInfo
, result
) },
4942 { "InactiveExitTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, inactive_exit_timestamp
) },
4943 { "InactiveExitTimestampMonotonic", "t", NULL
, offsetof(UnitStatusInfo
, inactive_exit_timestamp_monotonic
) },
4944 { "ActiveEnterTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, active_enter_timestamp
) },
4945 { "ActiveExitTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, active_exit_timestamp
) },
4946 { "InactiveEnterTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, inactive_enter_timestamp
) },
4947 { "NeedDaemonReload", "b", NULL
, offsetof(UnitStatusInfo
, need_daemon_reload
) },
4948 { "Transient", "b", NULL
, offsetof(UnitStatusInfo
, transient
) },
4949 { "ExecMainPID", "u", NULL
, offsetof(UnitStatusInfo
, main_pid
) },
4950 { "MainPID", "u", map_main_pid
, 0 },
4951 { "ControlPID", "u", NULL
, offsetof(UnitStatusInfo
, control_pid
) },
4952 { "StatusText", "s", NULL
, offsetof(UnitStatusInfo
, status_text
) },
4953 { "PIDFile", "s", NULL
, offsetof(UnitStatusInfo
, pid_file
) },
4954 { "StatusErrno", "i", NULL
, offsetof(UnitStatusInfo
, status_errno
) },
4955 { "ExecMainStartTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, start_timestamp
) },
4956 { "ExecMainExitTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, exit_timestamp
) },
4957 { "ExecMainCode", "i", NULL
, offsetof(UnitStatusInfo
, exit_code
) },
4958 { "ExecMainStatus", "i", NULL
, offsetof(UnitStatusInfo
, exit_status
) },
4959 { "ConditionTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, condition_timestamp
) },
4960 { "ConditionResult", "b", NULL
, offsetof(UnitStatusInfo
, condition_result
) },
4961 { "Conditions", "a(sbbsi)", map_conditions
, 0 },
4962 { "AssertTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, assert_timestamp
) },
4963 { "AssertResult", "b", NULL
, offsetof(UnitStatusInfo
, assert_result
) },
4964 { "Asserts", "a(sbbsi)", map_asserts
, 0 },
4965 { "NextElapseUSecRealtime", "t", NULL
, offsetof(UnitStatusInfo
, next_elapse_real
) },
4966 { "NextElapseUSecMonotonic", "t", NULL
, offsetof(UnitStatusInfo
, next_elapse_monotonic
) },
4967 { "NAccepted", "u", NULL
, offsetof(UnitStatusInfo
, n_accepted
) },
4968 { "NConnections", "u", NULL
, offsetof(UnitStatusInfo
, n_connections
) },
4969 { "Accept", "b", NULL
, offsetof(UnitStatusInfo
, accept
) },
4970 { "Listen", "a(ss)", map_listen
, offsetof(UnitStatusInfo
, listen
) },
4971 { "SysFSPath", "s", NULL
, offsetof(UnitStatusInfo
, sysfs_path
) },
4972 { "Where", "s", NULL
, offsetof(UnitStatusInfo
, where
) },
4973 { "What", "s", NULL
, offsetof(UnitStatusInfo
, what
) },
4974 { "MemoryCurrent", "t", NULL
, offsetof(UnitStatusInfo
, memory_current
) },
4975 { "MemoryLow", "t", NULL
, offsetof(UnitStatusInfo
, memory_low
) },
4976 { "MemoryHigh", "t", NULL
, offsetof(UnitStatusInfo
, memory_high
) },
4977 { "MemoryMax", "t", NULL
, offsetof(UnitStatusInfo
, memory_max
) },
4978 { "MemorySwapMax", "t", NULL
, offsetof(UnitStatusInfo
, memory_swap_max
) },
4979 { "MemoryLimit", "t", NULL
, offsetof(UnitStatusInfo
, memory_limit
) },
4980 { "CPUUsageNSec", "t", NULL
, offsetof(UnitStatusInfo
, cpu_usage_nsec
) },
4981 { "TasksCurrent", "t", NULL
, offsetof(UnitStatusInfo
, tasks_current
) },
4982 { "TasksMax", "t", NULL
, offsetof(UnitStatusInfo
, tasks_max
) },
4983 { "IPIngressBytes", "t", NULL
, offsetof(UnitStatusInfo
, ip_ingress_bytes
) },
4984 { "IPEgressBytes", "t", NULL
, offsetof(UnitStatusInfo
, ip_egress_bytes
) },
4985 { "ExecStartPre", "a(sasbttttuii)", map_exec
, 0 },
4986 { "ExecStart", "a(sasbttttuii)", map_exec
, 0 },
4987 { "ExecStartPost", "a(sasbttttuii)", map_exec
, 0 },
4988 { "ExecReload", "a(sasbttttuii)", map_exec
, 0 },
4989 { "ExecStopPre", "a(sasbttttuii)", map_exec
, 0 },
4990 { "ExecStop", "a(sasbttttuii)", map_exec
, 0 },
4991 { "ExecStopPost", "a(sasbttttuii)", map_exec
, 0 },
4995 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
4996 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
4997 _cleanup_set_free_ Set
*found_properties
= NULL
;
4998 _cleanup_(unit_status_info_free
) UnitStatusInfo info
= {
4999 .memory_current
= (uint64_t) -1,
5000 .memory_high
= CGROUP_LIMIT_MAX
,
5001 .memory_max
= CGROUP_LIMIT_MAX
,
5002 .memory_swap_max
= CGROUP_LIMIT_MAX
,
5003 .memory_limit
= (uint64_t) -1,
5004 .cpu_usage_nsec
= (uint64_t) -1,
5005 .tasks_current
= (uint64_t) -1,
5006 .tasks_max
= (uint64_t) -1,
5007 .ip_ingress_bytes
= (uint64_t) -1,
5008 .ip_egress_bytes
= (uint64_t) -1,
5016 log_debug("Showing one %s", path
);
5018 r
= bus_map_all_properties(
5020 "org.freedesktop.systemd1",
5022 show_mode
== SYSTEMCTL_SHOW_STATUS
? status_map
: property_map
,
5027 return log_error_errno(r
, "Failed to get properties: %s", bus_error_message(&error
, r
));
5029 if (unit
&& streq_ptr(info
.load_state
, "not-found") && streq_ptr(info
.active_state
, "inactive")) {
5030 log_full(show_mode
== SYSTEMCTL_SHOW_STATUS
? LOG_ERR
: LOG_DEBUG
,
5031 "Unit %s could not be found.", unit
);
5033 if (show_mode
== SYSTEMCTL_SHOW_STATUS
)
5034 return EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN
;
5035 else if (show_mode
== SYSTEMCTL_SHOW_HELP
)
5044 if (show_mode
== SYSTEMCTL_SHOW_STATUS
) {
5045 print_status_info(bus
, &info
, ellipsized
);
5047 if (info
.active_state
&& !STR_IN_SET(info
.active_state
, "active", "reloading"))
5048 return EXIT_PROGRAM_NOT_RUNNING
;
5050 return EXIT_PROGRAM_RUNNING_OR_SERVICE_OK
;
5052 } else if (show_mode
== SYSTEMCTL_SHOW_HELP
) {
5053 show_unit_help(&info
);
5057 r
= sd_bus_message_rewind(reply
, true);
5059 return log_error_errno(r
, "Failed to rewind: %s", bus_error_message(&error
, r
));
5061 r
= bus_message_print_all_properties(reply
, print_property
, arg_properties
, arg_value
, arg_all
, &found_properties
);
5063 return bus_log_parse_error(r
);
5065 STRV_FOREACH(pp
, arg_properties
)
5066 if (!set_contains(found_properties
, *pp
))
5067 log_debug("Property %s does not exist.", *pp
);
5072 static int get_unit_dbus_path_by_pid(
5077 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5078 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5082 r
= sd_bus_call_method(
5084 "org.freedesktop.systemd1",
5085 "/org/freedesktop/systemd1",
5086 "org.freedesktop.systemd1.Manager",
5092 return log_error_errno(r
, "Failed to get unit for PID %"PRIu32
": %s", pid
, bus_error_message(&error
, r
));
5094 r
= sd_bus_message_read(reply
, "o", &u
);
5096 return bus_log_parse_error(r
);
5106 static int show_all(
5111 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5112 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
5117 r
= get_unit_list(bus
, NULL
, NULL
, &unit_infos
, 0, &reply
);
5121 (void) pager_open(arg_no_pager
, false);
5125 qsort_safe(unit_infos
, c
, sizeof(UnitInfo
), compare_unit_info
);
5127 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
5128 _cleanup_free_
char *p
= NULL
;
5130 p
= unit_dbus_path_from_name(u
->id
);
5134 r
= show_one(bus
, p
, u
->id
, SYSTEMCTL_SHOW_STATUS
, new_line
, ellipsized
);
5137 else if (r
> 0 && ret
== 0)
5144 static int show_system_status(sd_bus
*bus
) {
5145 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], since2
[FORMAT_TIMESTAMP_MAX
];
5146 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5147 _cleanup_(machine_info_clear
) struct machine_info mi
= {};
5148 _cleanup_free_
char *hn
= NULL
;
5149 const char *on
, *off
;
5152 hn
= gethostname_malloc();
5156 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, &error
, NULL
, &mi
);
5158 return log_error_errno(r
, "Failed to read server status: %s", bus_error_message(&error
, r
));
5160 if (streq_ptr(mi
.state
, "degraded")) {
5161 on
= ansi_highlight_red();
5162 off
= ansi_normal();
5163 } else if (streq_ptr(mi
.state
, "running")) {
5164 on
= ansi_highlight_green();
5165 off
= ansi_normal();
5167 on
= ansi_highlight_yellow();
5168 off
= ansi_normal();
5171 printf("%s%s%s %s\n", on
, special_glyph(BLACK_CIRCLE
), off
, arg_host
? arg_host
: hn
);
5173 printf(" State: %s%s%s\n",
5174 on
, strna(mi
.state
), off
);
5176 printf(" Jobs: %" PRIu32
" queued\n", mi
.n_jobs
);
5177 printf(" Failed: %" PRIu32
" units\n", mi
.n_failed_units
);
5179 printf(" Since: %s; %s\n",
5180 format_timestamp(since2
, sizeof(since2
), mi
.timestamp
),
5181 format_timestamp_relative(since1
, sizeof(since1
), mi
.timestamp
));
5183 printf(" CGroup: %s\n", mi
.control_group
?: "/");
5184 if (IN_SET(arg_transport
,
5185 BUS_TRANSPORT_LOCAL
,
5186 BUS_TRANSPORT_MACHINE
)) {
5187 static const char prefix
[] = " ";
5191 if (c
> sizeof(prefix
) - 1)
5192 c
-= sizeof(prefix
) - 1;
5196 show_cgroup(SYSTEMD_CGROUP_CONTROLLER
, strempty(mi
.control_group
), prefix
, c
, get_output_flags());
5202 static int show(int argc
, char *argv
[], void *userdata
) {
5203 bool new_line
= false, ellipsized
= false;
5204 SystemctlShowMode show_mode
;
5210 show_mode
= systemctl_show_mode_from_string(argv
[0]);
5211 if (show_mode
< 0) {
5212 log_error("Invalid argument.");
5216 if (show_mode
== SYSTEMCTL_SHOW_HELP
&& argc
<= 1) {
5217 log_error("This command expects one or more unit names. Did you mean --help?");
5221 r
= acquire_bus(BUS_MANAGER
, &bus
);
5225 (void) pager_open(arg_no_pager
, false);
5227 if (show_mode
== SYSTEMCTL_SHOW_STATUS
)
5228 /* Increase max number of open files to 16K if we can, we
5229 * might needs this when browsing journal files, which might
5230 * be split up into many files. */
5231 setrlimit_closest(RLIMIT_NOFILE
, &RLIMIT_MAKE_CONST(16384));
5233 /* If no argument is specified inspect the manager itself */
5234 if (show_mode
== SYSTEMCTL_SHOW_PROPERTIES
&& argc
<= 1)
5235 return show_one(bus
, "/org/freedesktop/systemd1", NULL
, show_mode
, &new_line
, &ellipsized
);
5237 if (show_mode
== SYSTEMCTL_SHOW_STATUS
&& argc
<= 1) {
5239 show_system_status(bus
);
5243 ret
= show_all(bus
, &new_line
, &ellipsized
);
5245 _cleanup_free_
char **patterns
= NULL
;
5248 STRV_FOREACH(name
, strv_skip(argv
, 1)) {
5249 _cleanup_free_
char *path
= NULL
, *unit
= NULL
;
5252 if (safe_atou32(*name
, &id
) < 0) {
5253 if (strv_push(&patterns
, *name
) < 0)
5257 } else if (show_mode
== SYSTEMCTL_SHOW_PROPERTIES
) {
5258 /* Interpret as job id */
5259 if (asprintf(&path
, "/org/freedesktop/systemd1/job/%u", id
) < 0)
5263 /* Interpret as PID */
5264 r
= get_unit_dbus_path_by_pid(bus
, id
, &path
);
5270 r
= unit_name_from_dbus_path(path
, &unit
);
5275 r
= show_one(bus
, path
, unit
, show_mode
, &new_line
, &ellipsized
);
5278 else if (r
> 0 && ret
== 0)
5282 if (!strv_isempty(patterns
)) {
5283 _cleanup_strv_free_
char **names
= NULL
;
5285 r
= expand_names(bus
, patterns
, NULL
, &names
);
5287 return log_error_errno(r
, "Failed to expand names: %m");
5289 STRV_FOREACH(name
, names
) {
5290 _cleanup_free_
char *path
;
5292 path
= unit_dbus_path_from_name(*name
);
5296 r
= show_one(bus
, path
, *name
, show_mode
, &new_line
, &ellipsized
);
5299 if (r
> 0 && ret
== 0)
5305 if (ellipsized
&& !arg_quiet
)
5306 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
5311 static int cat_file(const char *filename
, bool newline
) {
5312 _cleanup_close_
int fd
;
5314 fd
= open(filename
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
5318 printf("%s%s# %s%s\n",
5319 newline
? "\n" : "",
5320 ansi_highlight_blue(),
5325 return copy_bytes(fd
, STDOUT_FILENO
, (uint64_t) -1, 0);
5328 static int cat(int argc
, char *argv
[], void *userdata
) {
5329 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
5330 _cleanup_strv_free_
char **names
= NULL
;
5336 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
5337 log_error("Cannot remotely cat units.");
5341 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
5343 return log_error_errno(r
, "Failed to determine unit paths: %m");
5345 r
= acquire_bus(BUS_MANAGER
, &bus
);
5349 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
5351 return log_error_errno(r
, "Failed to expand names: %m");
5353 (void) pager_open(arg_no_pager
, false);
5355 STRV_FOREACH(name
, names
) {
5356 _cleanup_free_
char *fragment_path
= NULL
;
5357 _cleanup_strv_free_
char **dropin_paths
= NULL
;
5360 r
= unit_find_paths(bus
, *name
, &lp
, &fragment_path
, &dropin_paths
);
5371 if (need_daemon_reload(bus
, *name
) > 0) /* ignore errors (<0), this is informational output */
5373 "%s# Warning: %s changed on disk, the version systemd has loaded is outdated.\n"
5374 "%s# This output shows the current version of the unit's original fragment and drop-in files.\n"
5375 "%s# If fragments or drop-ins were added or removed, they are not properly reflected in this output.\n"
5376 "%s# Run 'systemctl%s daemon-reload' to reload units.%s\n",
5377 ansi_highlight_red(),
5379 ansi_highlight_red(),
5380 ansi_highlight_red(),
5381 ansi_highlight_red(),
5382 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user",
5385 if (fragment_path
) {
5386 r
= cat_file(fragment_path
, false);
5388 return log_warning_errno(r
, "Failed to cat %s: %m", fragment_path
);
5391 STRV_FOREACH(path
, dropin_paths
) {
5392 r
= cat_file(*path
, path
== dropin_paths
);
5394 return log_warning_errno(r
, "Failed to cat %s: %m", *path
);
5401 static int set_property(int argc
, char *argv
[], void *userdata
) {
5402 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5403 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5404 _cleanup_free_
char *n
= NULL
;
5409 r
= acquire_bus(BUS_MANAGER
, &bus
);
5413 polkit_agent_open_maybe();
5415 r
= sd_bus_message_new_method_call(
5418 "org.freedesktop.systemd1",
5419 "/org/freedesktop/systemd1",
5420 "org.freedesktop.systemd1.Manager",
5421 "SetUnitProperties");
5423 return bus_log_create_error(r
);
5425 r
= unit_name_mangle(argv
[1], UNIT_NAME_NOGLOB
, &n
);
5427 return log_error_errno(r
, "Failed to mangle unit name: %m");
5429 t
= unit_name_to_type(n
);
5431 log_error("Invalid unit type: %s", n
);
5435 r
= sd_bus_message_append(m
, "sb", n
, arg_runtime
);
5437 return bus_log_create_error(r
);
5439 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, "(sv)");
5441 return bus_log_create_error(r
);
5443 r
= bus_append_unit_property_assignment_many(m
, t
, strv_skip(argv
, 2));
5447 r
= sd_bus_message_close_container(m
);
5449 return bus_log_create_error(r
);
5451 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5453 return log_error_errno(r
, "Failed to set unit properties on %s: %s", n
, bus_error_message(&error
, r
));
5458 static int daemon_reload(int argc
, char *argv
[], void *userdata
) {
5459 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5460 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5465 r
= acquire_bus(BUS_MANAGER
, &bus
);
5469 polkit_agent_open_maybe();
5471 switch (arg_action
) {
5478 method
= "Reexecute";
5481 case ACTION_SYSTEMCTL
:
5482 method
= streq(argv
[0], "daemon-reexec") ? "Reexecute" :
5483 /* "daemon-reload" */ "Reload";
5487 assert_not_reached("Unexpected action");
5490 r
= sd_bus_message_new_method_call(
5493 "org.freedesktop.systemd1",
5494 "/org/freedesktop/systemd1",
5495 "org.freedesktop.systemd1.Manager",
5498 return bus_log_create_error(r
);
5500 /* Note we use an extra-long timeout here. This is because a reload or reexec means generators are rerun which
5501 * are timed out after DEFAULT_TIMEOUT_USEC. Let's use twice that time here, so that the generators can have
5502 * their timeout, and for everything else there's the same time budget in place. */
5504 r
= sd_bus_call(bus
, m
, DEFAULT_TIMEOUT_USEC
* 2, &error
, NULL
);
5506 /* On reexecution, we expect a disconnect, not a reply */
5507 if (IN_SET(r
, -ETIMEDOUT
, -ECONNRESET
) && streq(method
, "Reexecute"))
5510 if (r
< 0 && arg_action
== ACTION_SYSTEMCTL
)
5511 return log_error_errno(r
, "Failed to reload daemon: %s", bus_error_message(&error
, r
));
5513 /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
5514 * old ways of doing things, hence don't log any error in that case here. */
5516 return r
< 0 ? r
: 0;
5519 static int trivial_method(int argc
, char *argv
[], void *userdata
) {
5520 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5528 r
= acquire_bus(BUS_MANAGER
, &bus
);
5532 polkit_agent_open_maybe();
5535 streq(argv
[0], "clear-jobs") ||
5536 streq(argv
[0], "cancel") ? "ClearJobs" :
5537 streq(argv
[0], "reset-failed") ? "ResetFailed" :
5538 streq(argv
[0], "halt") ? "Halt" :
5539 streq(argv
[0], "reboot") ? "Reboot" :
5540 streq(argv
[0], "kexec") ? "KExec" :
5541 streq(argv
[0], "exit") ? "Exit" :
5542 /* poweroff */ "PowerOff";
5544 r
= sd_bus_call_method(
5546 "org.freedesktop.systemd1",
5547 "/org/freedesktop/systemd1",
5548 "org.freedesktop.systemd1.Manager",
5553 if (r
< 0 && arg_action
== ACTION_SYSTEMCTL
)
5554 return log_error_errno(r
, "Failed to execute operation: %s", bus_error_message(&error
, r
));
5556 /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
5557 * old ways of doing things, hence don't log any error in that case here. */
5559 return r
< 0 ? r
: 0;
5562 static int reset_failed(int argc
, char *argv
[], void *userdata
) {
5563 _cleanup_strv_free_
char **names
= NULL
;
5569 return trivial_method(argc
, argv
, userdata
);
5571 r
= acquire_bus(BUS_MANAGER
, &bus
);
5575 polkit_agent_open_maybe();
5577 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
5579 return log_error_errno(r
, "Failed to expand names: %m");
5581 STRV_FOREACH(name
, names
) {
5582 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5584 q
= sd_bus_call_method(
5586 "org.freedesktop.systemd1",
5587 "/org/freedesktop/systemd1",
5588 "org.freedesktop.systemd1.Manager",
5594 log_error_errno(q
, "Failed to reset failed state of unit %s: %s", *name
, bus_error_message(&error
, q
));
5603 static int print_variable(const char *s
) {
5605 _cleanup_free_
char *esc
= NULL
;
5607 sep
= strchr(s
, '=');
5609 log_error("Invalid environment block");
5613 esc
= shell_maybe_quote(sep
+ 1, ESCAPE_POSIX
);
5617 printf("%.*s=%s\n", (int)(sep
-s
), s
, esc
);
5621 static int show_environment(int argc
, char *argv
[], void *userdata
) {
5622 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5623 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5628 r
= acquire_bus(BUS_MANAGER
, &bus
);
5632 (void) pager_open(arg_no_pager
, false);
5634 r
= sd_bus_get_property(
5636 "org.freedesktop.systemd1",
5637 "/org/freedesktop/systemd1",
5638 "org.freedesktop.systemd1.Manager",
5644 return log_error_errno(r
, "Failed to get environment: %s", bus_error_message(&error
, r
));
5646 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
5648 return bus_log_parse_error(r
);
5650 while ((r
= sd_bus_message_read_basic(reply
, SD_BUS_TYPE_STRING
, &text
)) > 0) {
5651 r
= print_variable(text
);
5656 return bus_log_parse_error(r
);
5658 r
= sd_bus_message_exit_container(reply
);
5660 return bus_log_parse_error(r
);
5665 static int switch_root(int argc
, char *argv
[], void *userdata
) {
5666 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5667 _cleanup_free_
char *cmdline_init
= NULL
;
5668 const char *root
, *init
;
5672 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
5673 log_error("Cannot switch root remotely.");
5677 if (argc
< 2 || argc
> 3) {
5678 log_error("Wrong number of arguments.");
5687 r
= parse_env_file("/proc/cmdline", WHITESPACE
,
5688 "init", &cmdline_init
,
5691 log_debug_errno(r
, "Failed to parse /proc/cmdline: %m");
5693 init
= cmdline_init
;
5696 init
= empty_to_null(init
);
5698 const char *root_systemd_path
= NULL
, *root_init_path
= NULL
;
5700 root_systemd_path
= strjoina(root
, "/" SYSTEMD_BINARY_PATH
);
5701 root_init_path
= strjoina(root
, "/", init
);
5703 /* If the passed init is actually the same as the
5704 * systemd binary, then let's suppress it. */
5705 if (files_same(root_init_path
, root_systemd_path
, 0) > 0)
5709 /* Instruct PID1 to exclude us from its killing spree applied during
5710 * the transition. Otherwise we would exit with a failure status even
5711 * though the switch to the new root has succeed. */
5712 argv_cmdline
[0] = '@';
5714 r
= acquire_bus(BUS_MANAGER
, &bus
);
5718 /* If we are slow to exit after the root switch, the new systemd instance
5719 * will send us a signal to terminate. Just ignore it and exit normally.
5720 * This way the unit does not end up as failed.
5722 r
= ignore_signals(SIGTERM
, -1);
5724 log_warning_errno(r
, "Failed to change disposition of SIGTERM to ignore: %m");
5726 log_debug("Switching root - root: %s; init: %s", root
, strna(init
));
5728 r
= sd_bus_call_method(
5730 "org.freedesktop.systemd1",
5731 "/org/freedesktop/systemd1",
5732 "org.freedesktop.systemd1.Manager",
5738 (void) default_signals(SIGTERM
, -1);
5740 return log_error_errno(r
, "Failed to switch root: %s", bus_error_message(&error
, r
));
5746 static int set_environment(int argc
, char *argv
[], void *userdata
) {
5747 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5748 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5756 r
= acquire_bus(BUS_MANAGER
, &bus
);
5760 polkit_agent_open_maybe();
5762 method
= streq(argv
[0], "set-environment")
5764 : "UnsetEnvironment";
5766 r
= sd_bus_message_new_method_call(
5769 "org.freedesktop.systemd1",
5770 "/org/freedesktop/systemd1",
5771 "org.freedesktop.systemd1.Manager",
5774 return bus_log_create_error(r
);
5776 r
= sd_bus_message_append_strv(m
, strv_skip(argv
, 1));
5778 return bus_log_create_error(r
);
5780 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5782 return log_error_errno(r
, "Failed to set environment: %s", bus_error_message(&error
, r
));
5787 static int import_environment(int argc
, char *argv
[], void *userdata
) {
5788 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5789 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5793 r
= acquire_bus(BUS_MANAGER
, &bus
);
5797 polkit_agent_open_maybe();
5799 r
= sd_bus_message_new_method_call(
5802 "org.freedesktop.systemd1",
5803 "/org/freedesktop/systemd1",
5804 "org.freedesktop.systemd1.Manager",
5807 return bus_log_create_error(r
);
5810 r
= sd_bus_message_append_strv(m
, environ
);
5814 r
= sd_bus_message_open_container(m
, 'a', "s");
5816 return bus_log_create_error(r
);
5818 STRV_FOREACH(a
, strv_skip(argv
, 1)) {
5820 if (!env_name_is_valid(*a
)) {
5821 log_error("Not a valid environment variable name: %s", *a
);
5825 STRV_FOREACH(b
, environ
) {
5828 eq
= startswith(*b
, *a
);
5829 if (eq
&& *eq
== '=') {
5831 r
= sd_bus_message_append(m
, "s", *b
);
5833 return bus_log_create_error(r
);
5840 r
= sd_bus_message_close_container(m
);
5843 return bus_log_create_error(r
);
5845 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5847 return log_error_errno(r
, "Failed to import environment: %s", bus_error_message(&error
, r
));
5852 static int enable_sysv_units(const char *verb
, char **args
) {
5855 #if HAVE_SYSV_COMPAT
5856 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
5859 /* Processes all SysV units, and reshuffles the array so that afterwards only the native units remain */
5861 if (arg_scope
!= UNIT_FILE_SYSTEM
)
5864 if (getenv_bool("SYSTEMCTL_SKIP_SYSV") > 0)
5867 if (!STR_IN_SET(verb
,
5873 r
= lookup_paths_init(&paths
, arg_scope
, LOOKUP_PATHS_EXCLUDE_GENERATED
, arg_root
);
5880 const char *argv
[] = {
5881 ROOTLIBEXECDIR
"/systemd-sysv-install",
5888 _cleanup_free_
char *p
= NULL
, *q
= NULL
, *l
= NULL
;
5889 bool found_native
= false, found_sysv
;
5897 if (!endswith(name
, ".service"))
5900 if (path_is_absolute(name
))
5903 j
= unit_file_exists(arg_scope
, &paths
, name
);
5904 if (j
< 0 && !IN_SET(j
, -ELOOP
, -ERFKILL
, -EADDRNOTAVAIL
))
5905 return log_error_errno(j
, "Failed to lookup unit file state: %m");
5906 found_native
= j
!= 0;
5908 /* If we have both a native unit and a SysV script, enable/disable them both (below); for is-enabled,
5909 * prefer the native unit */
5910 if (found_native
&& streq(verb
, "is-enabled"))
5913 p
= path_join(arg_root
, SYSTEM_SYSVINIT_PATH
, name
);
5917 p
[strlen(p
) - STRLEN(".service")] = 0;
5918 found_sysv
= access(p
, F_OK
) >= 0;
5924 log_info("Synchronizing state of %s with SysV service script with %s.", name
, argv
[0]);
5926 log_info("%s is not a native service, redirecting to systemd-sysv-install.", name
);
5929 if (!isempty(arg_root
))
5930 argv
[c
++] = q
= strappend("--root=", arg_root
);
5933 argv
[c
++] = basename(p
);
5936 l
= strv_join((char**)argv
, " ");
5941 log_info("Executing: %s", l
);
5943 j
= safe_fork("(sysv-install)", FORK_RESET_SIGNALS
|FORK_DEATHSIG
|FORK_LOG
, &pid
);
5948 execv(argv
[0], (char**) argv
);
5949 log_error_errno(errno
, "Failed to execute %s: %m", argv
[0]);
5950 _exit(EXIT_FAILURE
);
5953 j
= wait_for_terminate_and_check("sysv-install", pid
, WAIT_LOG_ABNORMAL
);
5956 if (streq(verb
, "is-enabled")) {
5957 if (j
== EXIT_SUCCESS
) {
5966 } else if (j
!= EXIT_SUCCESS
)
5967 return -EBADE
; /* We don't warn here, under the assumption the script already showed an explanation */
5972 /* Remove this entry, so that we don't try enabling it as native unit */
5975 assert(args
[f
] == name
);
5976 strv_remove(args
, name
);
5983 static int mangle_names(char **original_names
, char ***mangled_names
) {
5984 char **i
, **l
, **name
;
5987 l
= i
= new(char*, strv_length(original_names
) + 1);
5991 STRV_FOREACH(name
, original_names
) {
5993 /* When enabling units qualified path names are OK,
5994 * too, hence allow them explicitly. */
5996 if (is_path(*name
)) {
6003 r
= unit_name_mangle(*name
, UNIT_NAME_NOGLOB
, i
);
6007 return log_error_errno(r
, "Failed to mangle unit name: %m");
6020 static int normalize_filenames(char **names
) {
6024 STRV_FOREACH(u
, names
)
6025 if (!path_is_absolute(*u
)) {
6026 char* normalized_path
;
6028 if (!isempty(arg_root
)) {
6029 log_error("Non-absolute paths are not allowed when --root is used: %s", *u
);
6033 if (!strchr(*u
,'/')) {
6034 log_error("Link argument does contain at least one directory separator: %s", *u
);
6038 r
= path_make_absolute_cwd(*u
, &normalized_path
);
6042 free_and_replace(*u
, normalized_path
);
6048 static int normalize_names(char **names
, bool warn_if_path
) {
6050 bool was_path
= false;
6052 STRV_FOREACH(u
, names
) {
6058 r
= free_and_strdup(u
, basename(*u
));
6060 return log_error_errno(r
, "Failed to normalize unit file path: %m");
6065 if (warn_if_path
&& was_path
)
6066 log_warning("Warning: Can't execute disable on the unit file path. Proceeding with the unit name.");
6071 static int unit_exists(LookupPaths
*lp
, const char *unit
) {
6072 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6073 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
6074 _cleanup_free_
char *path
= NULL
;
6075 static const struct bus_properties_map property_map
[] = {
6076 { "LoadState", "s", NULL
, offsetof(UnitStatusInfo
, load_state
) },
6077 { "ActiveState", "s", NULL
, offsetof(UnitStatusInfo
, active_state
)},
6080 UnitStatusInfo info
= {};
6084 if (unit_name_is_valid(unit
, UNIT_NAME_TEMPLATE
))
6085 return unit_find_template_path(unit
, lp
, NULL
, NULL
);
6087 path
= unit_dbus_path_from_name(unit
);
6091 r
= acquire_bus(BUS_MANAGER
, &bus
);
6095 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", path
, property_map
, &error
, &m
, &info
);
6097 return log_error_errno(r
, "Failed to get properties: %s", bus_error_message(&error
, r
));
6099 return !streq_ptr(info
.load_state
, "not-found") || !streq_ptr(info
.active_state
, "inactive");
6102 static int enable_unit(int argc
, char *argv
[], void *userdata
) {
6103 _cleanup_strv_free_
char **names
= NULL
;
6104 const char *verb
= argv
[0];
6105 UnitFileChange
*changes
= NULL
;
6106 unsigned n_changes
= 0;
6107 int carries_install_info
= -1;
6108 bool ignore_carries_install_info
= arg_quiet
;
6114 r
= mangle_names(strv_skip(argv
, 1), &names
);
6118 r
= enable_sysv_units(verb
, names
);
6122 /* If the operation was fully executed by the SysV compat, let's finish early */
6123 if (strv_isempty(names
)) {
6124 if (arg_no_reload
|| install_client_side())
6126 return daemon_reload(argc
, argv
, userdata
);
6129 if (streq(verb
, "disable")) {
6130 r
= normalize_names(names
, true);
6135 if (streq(verb
, "link")) {
6136 r
= normalize_filenames(names
);
6141 if (install_client_side()) {
6142 UnitFileFlags flags
;
6144 flags
= args_to_flags();
6145 if (streq(verb
, "enable")) {
6146 r
= unit_file_enable(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6147 carries_install_info
= r
;
6148 } else if (streq(verb
, "disable"))
6149 r
= unit_file_disable(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6150 else if (streq(verb
, "reenable")) {
6151 r
= unit_file_reenable(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6152 carries_install_info
= r
;
6153 } else if (streq(verb
, "link"))
6154 r
= unit_file_link(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6155 else if (streq(verb
, "preset")) {
6156 r
= unit_file_preset(arg_scope
, flags
, arg_root
, names
, arg_preset_mode
, &changes
, &n_changes
);
6157 } else if (streq(verb
, "mask"))
6158 r
= unit_file_mask(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6159 else if (streq(verb
, "unmask"))
6160 r
= unit_file_unmask(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6161 else if (streq(verb
, "revert"))
6162 r
= unit_file_revert(arg_scope
, arg_root
, names
, &changes
, &n_changes
);
6164 assert_not_reached("Unknown verb");
6166 unit_file_dump_changes(r
, verb
, changes
, n_changes
, arg_quiet
);
6171 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
, *m
= NULL
;
6172 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6173 bool expect_carries_install_info
= false;
6174 bool send_runtime
= true, send_force
= true, send_preset_mode
= false;
6178 if (STR_IN_SET(verb
, "mask", "unmask")) {
6180 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
6182 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
6186 STRV_FOREACH(name
, names
) {
6187 r
= unit_exists(&lp
, *name
);
6191 log_notice("Unit %s does not exist, proceeding anyway.", *names
);
6195 r
= acquire_bus(BUS_MANAGER
, &bus
);
6199 polkit_agent_open_maybe();
6201 if (streq(verb
, "enable")) {
6202 method
= "EnableUnitFiles";
6203 expect_carries_install_info
= true;
6204 } else if (streq(verb
, "disable")) {
6205 method
= "DisableUnitFiles";
6207 } else if (streq(verb
, "reenable")) {
6208 method
= "ReenableUnitFiles";
6209 expect_carries_install_info
= true;
6210 } else if (streq(verb
, "link"))
6211 method
= "LinkUnitFiles";
6212 else if (streq(verb
, "preset")) {
6214 if (arg_preset_mode
!= UNIT_FILE_PRESET_FULL
) {
6215 method
= "PresetUnitFilesWithMode";
6216 send_preset_mode
= true;
6218 method
= "PresetUnitFiles";
6220 expect_carries_install_info
= true;
6221 ignore_carries_install_info
= true;
6222 } else if (streq(verb
, "mask"))
6223 method
= "MaskUnitFiles";
6224 else if (streq(verb
, "unmask")) {
6225 method
= "UnmaskUnitFiles";
6227 } else if (streq(verb
, "revert")) {
6228 method
= "RevertUnitFiles";
6229 send_runtime
= send_force
= false;
6231 assert_not_reached("Unknown verb");
6233 r
= sd_bus_message_new_method_call(
6236 "org.freedesktop.systemd1",
6237 "/org/freedesktop/systemd1",
6238 "org.freedesktop.systemd1.Manager",
6241 return bus_log_create_error(r
);
6243 r
= sd_bus_message_append_strv(m
, names
);
6245 return bus_log_create_error(r
);
6247 if (send_preset_mode
) {
6248 r
= sd_bus_message_append(m
, "s", unit_file_preset_mode_to_string(arg_preset_mode
));
6250 return bus_log_create_error(r
);
6254 r
= sd_bus_message_append(m
, "b", arg_runtime
);
6256 return bus_log_create_error(r
);
6260 r
= sd_bus_message_append(m
, "b", arg_force
);
6262 return bus_log_create_error(r
);
6265 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
6267 return log_error_errno(r
, "Failed to %s unit: %s", verb
, bus_error_message(&error
, r
));
6269 if (expect_carries_install_info
) {
6270 r
= sd_bus_message_read(reply
, "b", &carries_install_info
);
6272 return bus_log_parse_error(r
);
6275 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
6279 /* Try to reload if enabled */
6281 r
= daemon_reload(argc
, argv
, userdata
);
6286 if (carries_install_info
== 0 && !ignore_carries_install_info
)
6287 log_warning("The unit files have no installation config (WantedBy, RequiredBy, Also, Alias\n"
6288 "settings in the [Install] section, and DefaultInstance for template units).\n"
6289 "This means they are not meant to be enabled using systemctl.\n"
6290 "Possible reasons for having this kind of units are:\n"
6291 "1) A unit may be statically enabled by being symlinked from another unit's\n"
6292 " .wants/ or .requires/ directory.\n"
6293 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
6294 " a requirement dependency on it.\n"
6295 "3) A unit may be started when needed via activation (socket, path, timer,\n"
6296 " D-Bus, udev, scripted systemctl call, ...).\n"
6297 "4) In case of template units, the unit is meant to be enabled with some\n"
6298 " instance name specified.");
6300 if (arg_now
&& STR_IN_SET(argv
[0], "enable", "disable", "mask")) {
6304 r
= acquire_bus(BUS_MANAGER
, &bus
);
6308 len
= strv_length(names
);
6310 char *new_args
[len
+ 2];
6312 new_args
[0] = (char*) (streq(argv
[0], "enable") ? "start" : "stop");
6313 for (i
= 0; i
< len
; i
++)
6314 new_args
[i
+ 1] = basename(names
[i
]);
6315 new_args
[i
+ 1] = NULL
;
6317 r
= start_unit(len
+ 1, new_args
, userdata
);
6322 unit_file_changes_free(changes
, n_changes
);
6327 static int add_dependency(int argc
, char *argv
[], void *userdata
) {
6328 _cleanup_strv_free_
char **names
= NULL
;
6329 _cleanup_free_
char *target
= NULL
;
6330 const char *verb
= argv
[0];
6331 UnitFileChange
*changes
= NULL
;
6332 unsigned n_changes
= 0;
6339 r
= unit_name_mangle_with_suffix(argv
[1], UNIT_NAME_NOGLOB
, ".target", &target
);
6341 return log_error_errno(r
, "Failed to mangle unit name: %m");
6343 r
= mangle_names(strv_skip(argv
, 2), &names
);
6347 if (streq(verb
, "add-wants"))
6349 else if (streq(verb
, "add-requires"))
6350 dep
= UNIT_REQUIRES
;
6352 assert_not_reached("Unknown verb");
6354 if (install_client_side()) {
6355 r
= unit_file_add_dependency(arg_scope
, args_to_flags(), arg_root
, names
, target
, dep
, &changes
, &n_changes
);
6356 unit_file_dump_changes(r
, "add dependency on", changes
, n_changes
, arg_quiet
);
6361 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
, *m
= NULL
;
6362 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6365 r
= acquire_bus(BUS_MANAGER
, &bus
);
6369 polkit_agent_open_maybe();
6371 r
= sd_bus_message_new_method_call(
6374 "org.freedesktop.systemd1",
6375 "/org/freedesktop/systemd1",
6376 "org.freedesktop.systemd1.Manager",
6377 "AddDependencyUnitFiles");
6379 return bus_log_create_error(r
);
6381 r
= sd_bus_message_append_strv(m
, names
);
6383 return bus_log_create_error(r
);
6385 r
= sd_bus_message_append(m
, "ssbb", target
, unit_dependency_to_string(dep
), arg_runtime
, arg_force
);
6387 return bus_log_create_error(r
);
6389 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
6391 return log_error_errno(r
, "Failed to add dependency: %s", bus_error_message(&error
, r
));
6393 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
6397 if (arg_no_reload
) {
6402 r
= daemon_reload(argc
, argv
, userdata
);
6406 unit_file_changes_free(changes
, n_changes
);
6411 static int preset_all(int argc
, char *argv
[], void *userdata
) {
6412 UnitFileChange
*changes
= NULL
;
6413 unsigned n_changes
= 0;
6416 if (install_client_side()) {
6417 r
= unit_file_preset_all(arg_scope
, args_to_flags(), arg_root
, arg_preset_mode
, &changes
, &n_changes
);
6418 unit_file_dump_changes(r
, "preset", changes
, n_changes
, arg_quiet
);
6423 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6424 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6427 r
= acquire_bus(BUS_MANAGER
, &bus
);
6431 polkit_agent_open_maybe();
6433 r
= sd_bus_call_method(
6435 "org.freedesktop.systemd1",
6436 "/org/freedesktop/systemd1",
6437 "org.freedesktop.systemd1.Manager",
6438 "PresetAllUnitFiles",
6442 unit_file_preset_mode_to_string(arg_preset_mode
),
6446 return log_error_errno(r
, "Failed to preset all units: %s", bus_error_message(&error
, r
));
6448 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
6452 if (arg_no_reload
) {
6457 r
= daemon_reload(argc
, argv
, userdata
);
6461 unit_file_changes_free(changes
, n_changes
);
6466 static int show_installation_targets_client_side(const char *name
) {
6467 UnitFileChange
*changes
= NULL
;
6468 unsigned n_changes
= 0, i
;
6469 UnitFileFlags flags
;
6473 p
= STRV_MAKE(name
);
6474 flags
= UNIT_FILE_DRY_RUN
|
6475 (arg_runtime
? UNIT_FILE_RUNTIME
: 0);
6477 r
= unit_file_disable(UNIT_FILE_SYSTEM
, flags
, NULL
, p
, &changes
, &n_changes
);
6479 return log_error_errno(r
, "Failed to get file links for %s: %m", name
);
6481 for (i
= 0; i
< n_changes
; i
++)
6482 if (changes
[i
].type
== UNIT_FILE_UNLINK
)
6483 printf(" %s\n", changes
[i
].path
);
6488 static int show_installation_targets(sd_bus
*bus
, const char *name
) {
6489 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6490 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6494 r
= sd_bus_call_method(
6496 "org.freedesktop.systemd1",
6497 "/org/freedesktop/systemd1",
6498 "org.freedesktop.systemd1.Manager",
6502 "sb", name
, arg_runtime
);
6504 return log_error_errno(r
, "Failed to get unit file links for %s: %s", name
, bus_error_message(&error
, r
));
6506 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
6508 return bus_log_parse_error(r
);
6510 while ((r
= sd_bus_message_read(reply
, "s", &link
)) > 0)
6511 printf(" %s\n", link
);
6514 return bus_log_parse_error(r
);
6516 r
= sd_bus_message_exit_container(reply
);
6518 return bus_log_parse_error(r
);
6523 static int unit_is_enabled(int argc
, char *argv
[], void *userdata
) {
6525 _cleanup_strv_free_
char **names
= NULL
;
6530 r
= mangle_names(strv_skip(argv
, 1), &names
);
6534 r
= enable_sysv_units(argv
[0], names
);
6540 if (install_client_side()) {
6541 STRV_FOREACH(name
, names
) {
6542 UnitFileState state
;
6544 r
= unit_file_get_state(arg_scope
, arg_root
, *name
, &state
);
6546 return log_error_errno(r
, "Failed to get unit file state for %s: %m", *name
);
6550 UNIT_FILE_ENABLED_RUNTIME
,
6553 UNIT_FILE_GENERATED
))
6557 puts(unit_file_state_to_string(state
));
6559 r
= show_installation_targets_client_side(*name
);
6568 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6571 r
= acquire_bus(BUS_MANAGER
, &bus
);
6575 STRV_FOREACH(name
, names
) {
6576 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6579 r
= sd_bus_call_method(
6581 "org.freedesktop.systemd1",
6582 "/org/freedesktop/systemd1",
6583 "org.freedesktop.systemd1.Manager",
6589 return log_error_errno(r
, "Failed to get unit file state for %s: %s", *name
, bus_error_message(&error
, r
));
6591 r
= sd_bus_message_read(reply
, "s", &s
);
6593 return bus_log_parse_error(r
);
6595 if (STR_IN_SET(s
, "enabled", "enabled-runtime", "static", "indirect", "generated"))
6601 r
= show_installation_targets(bus
, *name
);
6609 return enabled
? EXIT_SUCCESS
: EXIT_FAILURE
;
6612 static int is_system_running(int argc
, char *argv
[], void *userdata
) {
6613 _cleanup_free_
char *state
= NULL
;
6617 if (running_in_chroot() > 0 || (arg_transport
== BUS_TRANSPORT_LOCAL
&& !sd_booted())) {
6620 return EXIT_FAILURE
;
6623 r
= acquire_bus(BUS_MANAGER
, &bus
);
6627 r
= sd_bus_get_property_string(
6629 "org.freedesktop.systemd1",
6630 "/org/freedesktop/systemd1",
6631 "org.freedesktop.systemd1.Manager",
6644 return streq(state
, "running") ? EXIT_SUCCESS
: EXIT_FAILURE
;
6647 static int create_edit_temp_file(const char *new_path
, const char *original_path
, char **ret_tmp_fn
) {
6648 _cleanup_free_
char *t
= NULL
;
6652 assert(original_path
);
6655 r
= tempfn_random(new_path
, NULL
, &t
);
6657 return log_error_errno(r
, "Failed to determine temporary filename for \"%s\": %m", new_path
);
6659 r
= mkdir_parents(new_path
, 0755);
6661 return log_error_errno(r
, "Failed to create directories for \"%s\": %m", new_path
);
6663 r
= copy_file(original_path
, t
, 0, 0644, 0, COPY_REFLINK
);
6668 return log_error_errno(r
, "Failed to create temporary file \"%s\": %m", t
);
6671 return log_error_errno(r
, "Failed to create temporary file for \"%s\": %m", new_path
);
6679 static int get_file_to_edit(
6680 const LookupPaths
*paths
,
6684 _cleanup_free_
char *path
= NULL
, *run
= NULL
;
6689 path
= strjoin(paths
->persistent_config
, "/", name
);
6694 run
= strjoin(paths
->runtime_config
, "/", name
);
6700 if (access(path
, F_OK
) >= 0) {
6701 log_error("Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.", run
, path
);
6715 static int unit_file_create_new(
6716 const LookupPaths
*paths
,
6717 const char *unit_name
,
6719 char **ret_new_path
,
6720 char **ret_tmp_path
) {
6722 char *tmp_new_path
, *tmp_tmp_path
, *ending
;
6726 assert(ret_new_path
);
6727 assert(ret_tmp_path
);
6729 ending
= strjoina(unit_name
, suffix
);
6730 r
= get_file_to_edit(paths
, ending
, &tmp_new_path
);
6734 r
= create_edit_temp_file(tmp_new_path
, tmp_new_path
, &tmp_tmp_path
);
6740 *ret_new_path
= tmp_new_path
;
6741 *ret_tmp_path
= tmp_tmp_path
;
6746 static int unit_file_create_copy(
6747 const LookupPaths
*paths
,
6748 const char *unit_name
,
6749 const char *fragment_path
,
6750 char **ret_new_path
,
6751 char **ret_tmp_path
) {
6753 char *tmp_new_path
, *tmp_tmp_path
;
6756 assert(fragment_path
);
6758 assert(ret_new_path
);
6759 assert(ret_tmp_path
);
6761 r
= get_file_to_edit(paths
, unit_name
, &tmp_new_path
);
6765 if (!path_equal(fragment_path
, tmp_new_path
) && access(tmp_new_path
, F_OK
) == 0) {
6768 r
= ask_char(&response
, "yn", "\"%s\" already exists. Overwrite with \"%s\"? [(y)es, (n)o] ", tmp_new_path
, fragment_path
);
6773 if (response
!= 'y') {
6774 log_warning("%s ignored", unit_name
);
6776 return -EKEYREJECTED
;
6780 r
= create_edit_temp_file(tmp_new_path
, fragment_path
, &tmp_tmp_path
);
6786 *ret_new_path
= tmp_new_path
;
6787 *ret_tmp_path
= tmp_tmp_path
;
6792 static int run_editor(char **paths
) {
6797 r
= safe_fork("(editor)", FORK_RESET_SIGNALS
|FORK_DEATHSIG
|FORK_LOG
|FORK_WAIT
, NULL
);
6802 char *editor
, **editor_args
= NULL
;
6803 char **tmp_path
, **original_path
, *p
;
6804 unsigned n_editor_args
= 0, i
= 1;
6807 argc
= strv_length(paths
)/2 + 1;
6809 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
6810 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
6811 * we try to execute well known editors
6813 editor
= getenv("SYSTEMD_EDITOR");
6815 editor
= getenv("EDITOR");
6817 editor
= getenv("VISUAL");
6819 if (!isempty(editor
)) {
6820 editor_args
= strv_split(editor
, WHITESPACE
);
6823 _exit(EXIT_FAILURE
);
6825 n_editor_args
= strv_length(editor_args
);
6826 argc
+= n_editor_args
- 1;
6828 args
= newa(const char*, argc
+ 1);
6830 if (n_editor_args
> 0) {
6831 args
[0] = editor_args
[0];
6832 for (; i
< n_editor_args
; i
++)
6833 args
[i
] = editor_args
[i
];
6836 STRV_FOREACH_PAIR(original_path
, tmp_path
, paths
) {
6837 args
[i
] = *tmp_path
;
6842 if (n_editor_args
> 0)
6843 execvp(args
[0], (char* const*) args
);
6845 FOREACH_STRING(p
, "editor", "nano", "vim", "vi") {
6847 execvp(p
, (char* const*) args
);
6848 /* We do not fail if the editor doesn't exist
6849 * because we want to try each one of them before
6852 if (errno
!= ENOENT
) {
6853 log_error_errno(errno
, "Failed to execute %s: %m", editor
);
6854 _exit(EXIT_FAILURE
);
6858 log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR, $EDITOR or $VISUAL.");
6859 _exit(EXIT_FAILURE
);
6865 static int find_paths_to_edit(sd_bus
*bus
, char **names
, char ***paths
) {
6866 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
6873 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
6877 STRV_FOREACH(name
, names
) {
6878 _cleanup_free_
char *path
= NULL
, *new_path
= NULL
, *tmp_path
= NULL
, *tmp_name
= NULL
;
6879 const char *unit_name
;
6881 r
= unit_find_paths(bus
, *name
, &lp
, &path
, NULL
);
6889 log_error("Run 'systemctl edit%s --force %s' to create a new unit.",
6890 arg_scope
== UNIT_FILE_GLOBAL
? " --global" :
6891 arg_scope
== UNIT_FILE_USER
? " --user" : "",
6896 /* Create a new unit from scratch */
6898 r
= unit_file_create_new(&lp
, unit_name
,
6899 arg_full
? NULL
: ".d/override.conf",
6900 &new_path
, &tmp_path
);
6904 unit_name
= basename(path
);
6905 /* We follow unit aliases, but we need to propagate the instance */
6906 if (unit_name_is_valid(*name
, UNIT_NAME_INSTANCE
) &&
6907 unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
6908 _cleanup_free_
char *instance
= NULL
;
6910 r
= unit_name_to_instance(*name
, &instance
);
6914 r
= unit_name_replace_instance(unit_name
, instance
, &tmp_name
);
6918 unit_name
= tmp_name
;
6922 r
= unit_file_create_copy(&lp
, unit_name
, path
, &new_path
, &tmp_path
);
6924 r
= unit_file_create_new(&lp
, unit_name
, ".d/override.conf", &new_path
, &tmp_path
);
6929 r
= strv_push_pair(paths
, new_path
, tmp_path
);
6932 new_path
= tmp_path
= NULL
;
6938 static int edit(int argc
, char *argv
[], void *userdata
) {
6939 _cleanup_strv_free_
char **names
= NULL
;
6940 _cleanup_strv_free_
char **paths
= NULL
;
6941 char **original
, **tmp
;
6946 log_error("Cannot edit units if not on a tty.");
6950 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
6951 log_error("Cannot edit units remotely.");
6955 r
= acquire_bus(BUS_MANAGER
, &bus
);
6959 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
6961 return log_error_errno(r
, "Failed to expand names: %m");
6963 r
= find_paths_to_edit(bus
, names
, &paths
);
6967 if (strv_isempty(paths
))
6970 r
= run_editor(paths
);
6974 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
6975 /* If the temporary file is empty we ignore it. It's
6976 * useful if the user wants to cancel its modification
6978 if (null_or_empty_path(*tmp
)) {
6979 log_warning("Editing \"%s\" canceled: temporary file is empty.", *original
);
6983 r
= rename(*tmp
, *original
);
6985 r
= log_error_errno(errno
, "Failed to rename \"%s\" to \"%s\": %m", *tmp
, *original
);
6992 if (!arg_no_reload
&& !install_client_side())
6993 r
= daemon_reload(argc
, argv
, userdata
);
6996 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
6997 (void) unlink(*tmp
);
6999 /* Removing empty dropin dirs */
7001 _cleanup_free_
char *dir
;
7003 dir
= dirname_malloc(*original
);
7007 /* no need to check if the dir is empty, rmdir
7008 * does nothing if it is not the case.
7017 static void systemctl_help(void) {
7019 (void) pager_open(arg_no_pager
, false);
7021 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
7022 "Query or send control commands to the systemd manager.\n\n"
7023 " -h --help Show this help\n"
7024 " --version Show package version\n"
7025 " --system Connect to system manager\n"
7026 " --user Connect to user service manager\n"
7027 " -H --host=[USER@]HOST\n"
7028 " Operate on remote host\n"
7029 " -M --machine=CONTAINER\n"
7030 " Operate on local container\n"
7031 " -t --type=TYPE List units of a particular type\n"
7032 " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n"
7033 " -p --property=NAME Show only properties by this name\n"
7034 " -a --all Show all properties/all units currently in memory,\n"
7035 " including dead/empty ones. To list all units installed on\n"
7036 " the system, use the 'list-unit-files' command instead.\n"
7037 " --failed Same as --state=failed\n"
7038 " -l --full Don't ellipsize unit names on output\n"
7039 " -r --recursive Show unit list of host and local containers\n"
7040 " --reverse Show reverse dependencies with 'list-dependencies'\n"
7041 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
7042 " queueing a new job\n"
7043 " --show-types When showing sockets, explicitly show their type\n"
7044 " --value When showing properties, only print the value\n"
7045 " -i --ignore-inhibitors\n"
7046 " When shutting down or sleeping, ignore inhibitors\n"
7047 " --kill-who=WHO Who to send signal to\n"
7048 " -s --signal=SIGNAL Which signal to send\n"
7049 " --now Start or stop unit in addition to enabling or disabling it\n"
7050 " --dry-run Only print what would be done\n"
7051 " -q --quiet Suppress output\n"
7052 " --wait For (re)start, wait until service stopped again\n"
7053 " --no-block Do not wait until operation finished\n"
7054 " --no-wall Don't send wall message before halt/power-off/reboot\n"
7055 " --no-reload Don't reload daemon after en-/dis-abling unit files\n"
7056 " --no-legend Do not print a legend (column headers and hints)\n"
7057 " --no-pager Do not pipe output into a pager\n"
7058 " --no-ask-password\n"
7059 " Do not ask for system passwords\n"
7060 " --global Enable/disable/mask unit files globally\n"
7061 " --runtime Enable/disable/mask unit files temporarily until next\n"
7063 " -f --force When enabling unit files, override existing symlinks\n"
7064 " When shutting down, execute action immediately\n"
7065 " --preset-mode= Apply only enable, only disable, or all presets\n"
7066 " --root=PATH Enable/disable/mask unit files in the specified root\n"
7068 " -n --lines=INTEGER Number of journal entries to show\n"
7069 " -o --output=STRING Change journal output mode (short, short-precise,\n"
7070 " short-iso, short-iso-precise, short-full,\n"
7071 " short-monotonic, short-unix,\n"
7072 " verbose, export, json, json-pretty, json-sse, cat)\n"
7073 " --firmware-setup Tell the firmware to show the setup menu on next boot\n"
7074 " --plain Print unit dependencies as a list instead of a tree\n\n"
7076 " list-units [PATTERN...] List units currently in memory\n"
7077 " list-sockets [PATTERN...] List socket units currently in memory,\n"
7078 " ordered by address\n"
7079 " list-timers [PATTERN...] List timer units currently in memory,\n"
7080 " ordered by next elapse\n"
7081 " start UNIT... Start (activate) one or more units\n"
7082 " stop UNIT... Stop (deactivate) one or more units\n"
7083 " reload UNIT... Reload one or more units\n"
7084 " restart UNIT... Start or restart one or more units\n"
7085 " try-restart UNIT... Restart one or more units if active\n"
7086 " reload-or-restart UNIT... Reload one or more units if possible,\n"
7087 " otherwise start or restart\n"
7088 " try-reload-or-restart UNIT... If active, reload one or more units,\n"
7089 " if supported, otherwise restart\n"
7090 " isolate UNIT Start one unit and stop all others\n"
7091 " kill UNIT... Send signal to processes of a unit\n"
7092 " is-active PATTERN... Check whether units are active\n"
7093 " is-failed PATTERN... Check whether units are failed\n"
7094 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
7095 " show [PATTERN...|JOB...] Show properties of one or more\n"
7096 " units/jobs or the manager\n"
7097 " cat PATTERN... Show files and drop-ins of specified units\n"
7098 " set-property UNIT PROPERTY=VALUE... Sets one or more properties of a unit\n"
7099 " help PATTERN...|PID... Show manual for one or more units\n"
7100 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
7102 " list-dependencies [UNIT] Recursively show units which are required\n"
7103 " or wanted by this unit or by which this\n"
7104 " unit is required or wanted\n\n"
7105 "Unit File Commands:\n"
7106 " list-unit-files [PATTERN...] List installed unit files\n"
7107 " enable [UNIT...|PATH...] Enable one or more unit files\n"
7108 " disable UNIT... Disable one or more unit files\n"
7109 " reenable UNIT... Reenable one or more unit files\n"
7110 " preset UNIT... Enable/disable one or more unit files\n"
7111 " based on preset configuration\n"
7112 " preset-all Enable/disable all unit files based on\n"
7113 " preset configuration\n"
7114 " is-enabled UNIT... Check whether unit files are enabled\n"
7115 " mask UNIT... Mask one or more units\n"
7116 " unmask UNIT... Unmask one or more units\n"
7117 " link PATH... Link one or more units files into\n"
7118 " the search path\n"
7119 " revert UNIT... Revert one or more unit files to vendor\n"
7121 " add-wants TARGET UNIT... Add 'Wants' dependency for the target\n"
7122 " on specified one or more units\n"
7123 " add-requires TARGET UNIT... Add 'Requires' dependency for the target\n"
7124 " on specified one or more units\n"
7125 " edit UNIT... Edit one or more unit files\n"
7126 " get-default Get the name of the default target\n"
7127 " set-default TARGET Set the default target\n\n"
7128 "Machine Commands:\n"
7129 " list-machines [PATTERN...] List local containers and host\n\n"
7131 " list-jobs [PATTERN...] List jobs\n"
7132 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
7133 "Environment Commands:\n"
7134 " show-environment Dump environment\n"
7135 " set-environment VARIABLE=VALUE... Set one or more environment variables\n"
7136 " unset-environment VARIABLE... Unset one or more environment variables\n"
7137 " import-environment [VARIABLE...] Import all or some environment variables\n\n"
7138 "Manager Lifecycle Commands:\n"
7139 " daemon-reload Reload systemd manager configuration\n"
7140 " daemon-reexec Reexecute systemd manager\n\n"
7141 "System Commands:\n"
7142 " is-system-running Check whether system is fully running\n"
7143 " default Enter system default mode\n"
7144 " rescue Enter system rescue mode\n"
7145 " emergency Enter system emergency mode\n"
7146 " halt Shut down and halt the system\n"
7147 " poweroff Shut down and power-off the system\n"
7148 " reboot [ARG] Shut down and reboot the system\n"
7149 " kexec Shut down and reboot the system with kexec\n"
7150 " exit [EXIT_CODE] Request user instance or container exit\n"
7151 " switch-root ROOT [INIT] Change to a different root file system\n"
7152 " suspend Suspend the system\n"
7153 " hibernate Hibernate the system\n"
7154 " hybrid-sleep Hibernate and suspend the system\n"
7155 " suspend-to-hibernate Suspend the system, wake after a period of\n"
7156 " time and put it into hibernate\n",
7157 program_invocation_short_name
);
7160 static void halt_help(void) {
7161 printf("%s [OPTIONS...]%s\n\n"
7162 "%s the system.\n\n"
7163 " --help Show this help\n"
7164 " --halt Halt the machine\n"
7165 " -p --poweroff Switch off the machine\n"
7166 " --reboot Reboot the machine\n"
7167 " -f --force Force immediate halt/power-off/reboot\n"
7168 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
7169 " -d --no-wtmp Don't write wtmp record\n"
7170 " --no-wall Don't send wall message before halt/power-off/reboot\n",
7171 program_invocation_short_name
,
7172 arg_action
== ACTION_REBOOT
? " [ARG]" : "",
7173 arg_action
== ACTION_REBOOT
? "Reboot" :
7174 arg_action
== ACTION_POWEROFF
? "Power off" :
7178 static void shutdown_help(void) {
7179 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
7180 "Shut down the system.\n\n"
7181 " --help Show this help\n"
7182 " -H --halt Halt the machine\n"
7183 " -P --poweroff Power-off the machine\n"
7184 " -r --reboot Reboot the machine\n"
7185 " -h Equivalent to --poweroff, overridden by --halt\n"
7186 " -k Don't halt/power-off/reboot, just send warnings\n"
7187 " --no-wall Don't send wall message before halt/power-off/reboot\n"
7188 " -c Cancel a pending shutdown\n",
7189 program_invocation_short_name
);
7192 static void telinit_help(void) {
7193 printf("%s [OPTIONS...] {COMMAND}\n\n"
7194 "Send control commands to the init daemon.\n\n"
7195 " --help Show this help\n"
7196 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
7198 " 0 Power-off the machine\n"
7199 " 6 Reboot the machine\n"
7200 " 2, 3, 4, 5 Start runlevelX.target unit\n"
7201 " 1, s, S Enter rescue mode\n"
7202 " q, Q Reload init daemon configuration\n"
7203 " u, U Reexecute init daemon\n",
7204 program_invocation_short_name
);
7207 static void runlevel_help(void) {
7208 printf("%s [OPTIONS...]\n\n"
7209 "Prints the previous and current runlevel of the init system.\n\n"
7210 " --help Show this help\n",
7211 program_invocation_short_name
);
7214 static void help_types(void) {
7218 puts("Available unit types:");
7219 for (i
= 0; i
< _UNIT_TYPE_MAX
; i
++)
7220 puts(unit_type_to_string(i
));
7223 static void help_states(void) {
7227 puts("Available unit load states:");
7228 for (i
= 0; i
< _UNIT_LOAD_STATE_MAX
; i
++)
7229 puts(unit_load_state_to_string(i
));
7232 puts("\nAvailable unit active states:");
7233 for (i
= 0; i
< _UNIT_ACTIVE_STATE_MAX
; i
++)
7234 puts(unit_active_state_to_string(i
));
7237 puts("\nAvailable automount unit substates:");
7238 for (i
= 0; i
< _AUTOMOUNT_STATE_MAX
; i
++)
7239 puts(automount_state_to_string(i
));
7242 puts("\nAvailable device unit substates:");
7243 for (i
= 0; i
< _DEVICE_STATE_MAX
; i
++)
7244 puts(device_state_to_string(i
));
7247 puts("\nAvailable mount unit substates:");
7248 for (i
= 0; i
< _MOUNT_STATE_MAX
; i
++)
7249 puts(mount_state_to_string(i
));
7252 puts("\nAvailable path unit substates:");
7253 for (i
= 0; i
< _PATH_STATE_MAX
; i
++)
7254 puts(path_state_to_string(i
));
7257 puts("\nAvailable scope unit substates:");
7258 for (i
= 0; i
< _SCOPE_STATE_MAX
; i
++)
7259 puts(scope_state_to_string(i
));
7262 puts("\nAvailable service unit substates:");
7263 for (i
= 0; i
< _SERVICE_STATE_MAX
; i
++)
7264 puts(service_state_to_string(i
));
7267 puts("\nAvailable slice unit substates:");
7268 for (i
= 0; i
< _SLICE_STATE_MAX
; i
++)
7269 puts(slice_state_to_string(i
));
7272 puts("\nAvailable socket unit substates:");
7273 for (i
= 0; i
< _SOCKET_STATE_MAX
; i
++)
7274 puts(socket_state_to_string(i
));
7277 puts("\nAvailable swap unit substates:");
7278 for (i
= 0; i
< _SWAP_STATE_MAX
; i
++)
7279 puts(swap_state_to_string(i
));
7282 puts("\nAvailable target unit substates:");
7283 for (i
= 0; i
< _TARGET_STATE_MAX
; i
++)
7284 puts(target_state_to_string(i
));
7287 puts("\nAvailable timer unit substates:");
7288 for (i
= 0; i
< _TIMER_STATE_MAX
; i
++)
7289 puts(timer_state_to_string(i
));
7292 static int systemctl_parse_argv(int argc
, char *argv
[]) {
7302 ARG_IGNORE_DEPENDENCIES
,
7315 ARG_NO_ASK_PASSWORD
,
7328 static const struct option options
[] = {
7329 { "help", no_argument
, NULL
, 'h' },
7330 { "version", no_argument
, NULL
, ARG_VERSION
},
7331 { "type", required_argument
, NULL
, 't' },
7332 { "property", required_argument
, NULL
, 'p' },
7333 { "all", no_argument
, NULL
, 'a' },
7334 { "reverse", no_argument
, NULL
, ARG_REVERSE
},
7335 { "after", no_argument
, NULL
, ARG_AFTER
},
7336 { "before", no_argument
, NULL
, ARG_BEFORE
},
7337 { "show-types", no_argument
, NULL
, ARG_SHOW_TYPES
},
7338 { "failed", no_argument
, NULL
, ARG_FAILED
}, /* compatibility only */
7339 { "full", no_argument
, NULL
, 'l' },
7340 { "job-mode", required_argument
, NULL
, ARG_JOB_MODE
},
7341 { "fail", no_argument
, NULL
, ARG_FAIL
}, /* compatibility only */
7342 { "irreversible", no_argument
, NULL
, ARG_IRREVERSIBLE
}, /* compatibility only */
7343 { "ignore-dependencies", no_argument
, NULL
, ARG_IGNORE_DEPENDENCIES
}, /* compatibility only */
7344 { "ignore-inhibitors", no_argument
, NULL
, 'i' },
7345 { "value", no_argument
, NULL
, ARG_VALUE
},
7346 { "user", no_argument
, NULL
, ARG_USER
},
7347 { "system", no_argument
, NULL
, ARG_SYSTEM
},
7348 { "global", no_argument
, NULL
, ARG_GLOBAL
},
7349 { "wait", no_argument
, NULL
, ARG_WAIT
},
7350 { "no-block", no_argument
, NULL
, ARG_NO_BLOCK
},
7351 { "no-legend", no_argument
, NULL
, ARG_NO_LEGEND
},
7352 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
7353 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7354 { "dry-run", no_argument
, NULL
, ARG_DRY_RUN
},
7355 { "quiet", no_argument
, NULL
, 'q' },
7356 { "root", required_argument
, NULL
, ARG_ROOT
},
7357 { "force", no_argument
, NULL
, 'f' },
7358 { "no-reload", no_argument
, NULL
, ARG_NO_RELOAD
},
7359 { "kill-who", required_argument
, NULL
, ARG_KILL_WHO
},
7360 { "signal", required_argument
, NULL
, 's' },
7361 { "no-ask-password", no_argument
, NULL
, ARG_NO_ASK_PASSWORD
},
7362 { "host", required_argument
, NULL
, 'H' },
7363 { "machine", required_argument
, NULL
, 'M' },
7364 { "runtime", no_argument
, NULL
, ARG_RUNTIME
},
7365 { "lines", required_argument
, NULL
, 'n' },
7366 { "output", required_argument
, NULL
, 'o' },
7367 { "plain", no_argument
, NULL
, ARG_PLAIN
},
7368 { "state", required_argument
, NULL
, ARG_STATE
},
7369 { "recursive", no_argument
, NULL
, 'r' },
7370 { "preset-mode", required_argument
, NULL
, ARG_PRESET_MODE
},
7371 { "firmware-setup", no_argument
, NULL
, ARG_FIRMWARE_SETUP
},
7372 { "now", no_argument
, NULL
, ARG_NOW
},
7373 { "message", required_argument
, NULL
, ARG_MESSAGE
},
7383 /* we default to allowing interactive authorization only in systemctl (not in the legacy commands) */
7384 arg_ask_password
= true;
7386 while ((c
= getopt_long(argc
, argv
, "ht:p:alqfs:H:M:n:o:ir", options
, NULL
)) >= 0)
7398 if (isempty(optarg
)) {
7399 log_error("--type= requires arguments.");
7403 for (p
= optarg
;;) {
7404 _cleanup_free_
char *type
= NULL
;
7406 r
= extract_first_word(&p
, &type
, ",", 0);
7408 return log_error_errno(r
, "Failed to parse type: %s", optarg
);
7412 if (streq(type
, "help")) {
7417 if (unit_type_from_string(type
) >= 0) {
7418 if (strv_push(&arg_types
, type
) < 0)
7424 /* It's much nicer to use --state= for
7425 * load states, but let's support this
7426 * in --types= too for compatibility
7427 * with old versions */
7428 if (unit_load_state_from_string(type
) >= 0) {
7429 if (strv_push(&arg_states
, type
) < 0)
7435 log_error("Unknown unit type or load state '%s'.", type
);
7436 log_info("Use -t help to see a list of allowed values.");
7444 /* Make sure that if the empty property list
7445 was specified, we won't show any properties. */
7446 if (isempty(optarg
) && !arg_properties
) {
7447 arg_properties
= new0(char*, 1);
7448 if (!arg_properties
)
7451 for (p
= optarg
;;) {
7452 _cleanup_free_
char *prop
= NULL
;
7454 r
= extract_first_word(&p
, &prop
, ",", 0);
7456 return log_error_errno(r
, "Failed to parse property: %s", optarg
);
7460 if (strv_push(&arg_properties
, prop
) < 0)
7466 /* If the user asked for a particular
7467 * property, show it to him, even if it is
7479 arg_dependency
= DEPENDENCY_REVERSE
;
7483 arg_dependency
= DEPENDENCY_AFTER
;
7484 arg_jobs_after
= true;
7488 arg_dependency
= DEPENDENCY_BEFORE
;
7489 arg_jobs_before
= true;
7492 case ARG_SHOW_TYPES
:
7493 arg_show_types
= true;
7501 arg_job_mode
= optarg
;
7505 arg_job_mode
= "fail";
7508 case ARG_IRREVERSIBLE
:
7509 arg_job_mode
= "replace-irreversibly";
7512 case ARG_IGNORE_DEPENDENCIES
:
7513 arg_job_mode
= "ignore-dependencies";
7517 arg_scope
= UNIT_FILE_USER
;
7521 arg_scope
= UNIT_FILE_SYSTEM
;
7525 arg_scope
= UNIT_FILE_GLOBAL
;
7533 arg_no_block
= true;
7537 arg_no_legend
= true;
7541 arg_no_pager
= true;
7549 r
= parse_path_argument_and_warn(optarg
, false, &arg_root
);
7559 if (strv_extend(&arg_states
, "failed") < 0)
7577 arg_no_reload
= true;
7581 arg_kill_who
= optarg
;
7585 arg_signal
= signal_from_string_try_harder(optarg
);
7586 if (arg_signal
< 0) {
7587 log_error("Failed to parse signal string %s.", optarg
);
7592 case ARG_NO_ASK_PASSWORD
:
7593 arg_ask_password
= false;
7597 arg_transport
= BUS_TRANSPORT_REMOTE
;
7602 arg_transport
= BUS_TRANSPORT_MACHINE
;
7611 if (safe_atou(optarg
, &arg_lines
) < 0) {
7612 log_error("Failed to parse lines '%s'", optarg
);
7618 arg_output
= output_mode_from_string(optarg
);
7619 if (arg_output
< 0) {
7620 log_error("Unknown output '%s'.", optarg
);
7626 arg_ignore_inhibitors
= true;
7633 case ARG_FIRMWARE_SETUP
:
7634 arg_firmware_setup
= true;
7638 if (isempty(optarg
)) {
7639 log_error("--state= requires arguments.");
7643 for (p
= optarg
;;) {
7644 _cleanup_free_
char *s
= NULL
;
7646 r
= extract_first_word(&p
, &s
, ",", 0);
7648 return log_error_errno(r
, "Failed to parse state: %s", optarg
);
7652 if (streq(s
, "help")) {
7657 if (strv_push(&arg_states
, s
) < 0)
7666 if (geteuid() != 0) {
7667 log_error("--recursive requires root privileges.");
7671 arg_recursive
= true;
7674 case ARG_PRESET_MODE
:
7676 arg_preset_mode
= unit_file_preset_mode_from_string(optarg
);
7677 if (arg_preset_mode
< 0) {
7678 log_error("Failed to parse preset mode: %s.", optarg
);
7689 if (strv_extend(&arg_wall
, optarg
) < 0)
7697 assert_not_reached("Unhandled option");
7700 if (arg_transport
!= BUS_TRANSPORT_LOCAL
&& arg_scope
!= UNIT_FILE_SYSTEM
) {
7701 log_error("Cannot access user instance remotely.");
7705 if (arg_wait
&& arg_no_block
) {
7706 log_error("--wait may not be combined with --no-block.");
7713 static int halt_parse_argv(int argc
, char *argv
[]) {
7722 static const struct option options
[] = {
7723 { "help", no_argument
, NULL
, ARG_HELP
},
7724 { "halt", no_argument
, NULL
, ARG_HALT
},
7725 { "poweroff", no_argument
, NULL
, 'p' },
7726 { "reboot", no_argument
, NULL
, ARG_REBOOT
},
7727 { "force", no_argument
, NULL
, 'f' },
7728 { "wtmp-only", no_argument
, NULL
, 'w' },
7729 { "no-wtmp", no_argument
, NULL
, 'd' },
7730 { "no-sync", no_argument
, NULL
, 'n' },
7731 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7740 if (utmp_get_runlevel(&runlevel
, NULL
) >= 0)
7741 if (IN_SET(runlevel
, '0', '6'))
7744 while ((c
= getopt_long(argc
, argv
, "pfwdnih", options
, NULL
)) >= 0)
7752 arg_action
= ACTION_HALT
;
7756 if (arg_action
!= ACTION_REBOOT
)
7757 arg_action
= ACTION_POWEROFF
;
7761 arg_action
= ACTION_REBOOT
;
7786 /* Compatibility nops */
7793 assert_not_reached("Unhandled option");
7796 if (arg_action
== ACTION_REBOOT
&& (argc
== optind
|| argc
== optind
+ 1)) {
7797 r
= update_reboot_parameter_and_warn(argc
== optind
+ 1 ? argv
[optind
] : NULL
);
7800 } else if (optind
< argc
) {
7801 log_error("Too many arguments.");
7808 static int parse_shutdown_time_spec(const char *t
, usec_t
*_u
) {
7812 if (streq(t
, "now"))
7814 else if (!strchr(t
, ':')) {
7817 if (safe_atou64(t
, &u
) < 0)
7820 *_u
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
* u
;
7829 hour
= strtol(t
, &e
, 10);
7830 if (errno
> 0 || *e
!= ':' || hour
< 0 || hour
> 23)
7833 minute
= strtol(e
+1, &e
, 10);
7834 if (errno
> 0 || *e
!= 0 || minute
< 0 || minute
> 59)
7837 n
= now(CLOCK_REALTIME
);
7838 s
= (time_t) (n
/ USEC_PER_SEC
);
7840 assert_se(localtime_r(&s
, &tm
));
7842 tm
.tm_hour
= (int) hour
;
7843 tm
.tm_min
= (int) minute
;
7846 assert_se(s
= mktime(&tm
));
7848 *_u
= (usec_t
) s
* USEC_PER_SEC
;
7851 *_u
+= USEC_PER_DAY
;
7857 static int shutdown_parse_argv(int argc
, char *argv
[]) {
7864 static const struct option options
[] = {
7865 { "help", no_argument
, NULL
, ARG_HELP
},
7866 { "halt", no_argument
, NULL
, 'H' },
7867 { "poweroff", no_argument
, NULL
, 'P' },
7868 { "reboot", no_argument
, NULL
, 'r' },
7869 { "kexec", no_argument
, NULL
, 'K' }, /* not documented extension */
7870 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7880 while ((c
= getopt_long(argc
, argv
, "HPrhkKat:fFc", options
, NULL
)) >= 0)
7888 arg_action
= ACTION_HALT
;
7892 arg_action
= ACTION_POWEROFF
;
7897 arg_action
= ACTION_KEXEC
;
7899 arg_action
= ACTION_REBOOT
;
7903 arg_action
= ACTION_KEXEC
;
7907 if (arg_action
!= ACTION_HALT
)
7908 arg_action
= ACTION_POWEROFF
;
7920 case 't': /* Note that we also ignore any passed argument to -t, not just the -t itself */
7923 /* Compatibility nops */
7927 arg_action
= ACTION_CANCEL_SHUTDOWN
;
7934 assert_not_reached("Unhandled option");
7937 if (argc
> optind
&& arg_action
!= ACTION_CANCEL_SHUTDOWN
) {
7938 r
= parse_shutdown_time_spec(argv
[optind
], &arg_when
);
7940 log_error("Failed to parse time specification: %s", argv
[optind
]);
7944 arg_when
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
;
7946 if (argc
> optind
&& arg_action
== ACTION_CANCEL_SHUTDOWN
)
7947 /* No time argument for shutdown cancel */
7948 wall
= argv
+ optind
;
7949 else if (argc
> optind
+ 1)
7950 /* We skip the time argument */
7951 wall
= argv
+ optind
+ 1;
7954 arg_wall
= strv_copy(wall
);
7964 static int telinit_parse_argv(int argc
, char *argv
[]) {
7971 static const struct option options
[] = {
7972 { "help", no_argument
, NULL
, ARG_HELP
},
7973 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7977 static const struct {
7981 { '0', ACTION_POWEROFF
},
7982 { '6', ACTION_REBOOT
},
7983 { '1', ACTION_RESCUE
},
7984 { '2', ACTION_RUNLEVEL2
},
7985 { '3', ACTION_RUNLEVEL3
},
7986 { '4', ACTION_RUNLEVEL4
},
7987 { '5', ACTION_RUNLEVEL5
},
7988 { 's', ACTION_RESCUE
},
7989 { 'S', ACTION_RESCUE
},
7990 { 'q', ACTION_RELOAD
},
7991 { 'Q', ACTION_RELOAD
},
7992 { 'u', ACTION_REEXEC
},
7993 { 'U', ACTION_REEXEC
}
8002 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
8017 assert_not_reached("Unhandled option");
8020 if (optind
>= argc
) {
8021 log_error("%s: required argument missing.", program_invocation_short_name
);
8025 if (optind
+ 1 < argc
) {
8026 log_error("Too many arguments.");
8030 if (strlen(argv
[optind
]) != 1) {
8031 log_error("Expected single character argument.");
8035 for (i
= 0; i
< ELEMENTSOF(table
); i
++)
8036 if (table
[i
].from
== argv
[optind
][0])
8039 if (i
>= ELEMENTSOF(table
)) {
8040 log_error("Unknown command '%s'.", argv
[optind
]);
8044 arg_action
= table
[i
].to
;
8051 static int runlevel_parse_argv(int argc
, char *argv
[]) {
8057 static const struct option options
[] = {
8058 { "help", no_argument
, NULL
, ARG_HELP
},
8067 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
8078 assert_not_reached("Unhandled option");
8081 if (optind
< argc
) {
8082 log_error("Too many arguments.");
8089 static int parse_argv(int argc
, char *argv
[]) {
8093 if (program_invocation_short_name
) {
8095 if (strstr(program_invocation_short_name
, "halt")) {
8096 arg_action
= ACTION_HALT
;
8097 return halt_parse_argv(argc
, argv
);
8099 } else if (strstr(program_invocation_short_name
, "poweroff")) {
8100 arg_action
= ACTION_POWEROFF
;
8101 return halt_parse_argv(argc
, argv
);
8103 } else if (strstr(program_invocation_short_name
, "reboot")) {
8105 arg_action
= ACTION_KEXEC
;
8107 arg_action
= ACTION_REBOOT
;
8108 return halt_parse_argv(argc
, argv
);
8110 } else if (strstr(program_invocation_short_name
, "shutdown")) {
8111 arg_action
= ACTION_POWEROFF
;
8112 return shutdown_parse_argv(argc
, argv
);
8114 } else if (strstr(program_invocation_short_name
, "init")) {
8116 /* Matches invocations as "init" as well as "telinit", which are synonymous when run as PID !=
8119 * On SysV "telinit" was the official command to communicate with PID 1, but "init" would
8120 * redirect itself to "telinit" if called with PID != 1. We follow the same logic here still,
8121 * though we add one level of indirection, as we implement "telinit" in "systemctl". Hence, for
8122 * us if you invoke "init" you get "systemd", but it will execve() "systemctl" immediately with
8123 * argv[] unmodified if PID is != 1. If you invoke "telinit" you directly get "systemctl". In
8124 * both cases we shall do the same thing, which is why we do strstr(p_i_s_n, "init") here, as a
8125 * quick way to match both.
8127 * Also see redirect_telinit() in src/core/main.c. */
8129 if (sd_booted() > 0) {
8130 arg_action
= _ACTION_INVALID
;
8131 return telinit_parse_argv(argc
, argv
);
8133 /* Hmm, so some other init system is running, we need to forward this request to
8134 * it. For now we simply guess that it is Upstart. */
8136 execv(TELINIT
, argv
);
8138 log_error("Couldn't find an alternative telinit implementation to spawn.");
8142 } else if (strstr(program_invocation_short_name
, "runlevel")) {
8143 arg_action
= ACTION_RUNLEVEL
;
8144 return runlevel_parse_argv(argc
, argv
);
8148 arg_action
= ACTION_SYSTEMCTL
;
8149 return systemctl_parse_argv(argc
, argv
);
8152 #if HAVE_SYSV_COMPAT
8153 _pure_
static int action_to_runlevel(void) {
8155 static const char table
[_ACTION_MAX
] = {
8156 [ACTION_HALT
] = '0',
8157 [ACTION_POWEROFF
] = '0',
8158 [ACTION_REBOOT
] = '6',
8159 [ACTION_RUNLEVEL2
] = '2',
8160 [ACTION_RUNLEVEL3
] = '3',
8161 [ACTION_RUNLEVEL4
] = '4',
8162 [ACTION_RUNLEVEL5
] = '5',
8163 [ACTION_RESCUE
] = '1'
8166 assert(arg_action
>= 0 && arg_action
< _ACTION_MAX
);
8168 return table
[arg_action
];
8172 static int talk_initctl(void) {
8173 #if HAVE_SYSV_COMPAT
8174 struct init_request request
= {
8175 .magic
= INIT_MAGIC
,
8177 .cmd
= INIT_CMD_RUNLVL
8180 _cleanup_close_
int fd
= -1;
8184 rl
= action_to_runlevel();
8188 request
.runlevel
= rl
;
8190 fd
= open(INIT_FIFO
, O_WRONLY
|O_NONBLOCK
|O_CLOEXEC
|O_NOCTTY
);
8192 if (errno
== ENOENT
)
8195 return log_error_errno(errno
, "Failed to open "INIT_FIFO
": %m");
8198 r
= loop_write(fd
, &request
, sizeof(request
), false);
8200 return log_error_errno(r
, "Failed to write to "INIT_FIFO
": %m");
8208 static int systemctl_main(int argc
, char *argv
[]) {
8210 static const Verb verbs
[] = {
8211 { "list-units", VERB_ANY
, VERB_ANY
, VERB_DEFAULT
|VERB_ONLINE_ONLY
, list_units
},
8212 { "list-unit-files", VERB_ANY
, VERB_ANY
, 0, list_unit_files
},
8213 { "list-sockets", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, list_sockets
},
8214 { "list-timers", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, list_timers
},
8215 { "list-jobs", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, list_jobs
},
8216 { "list-machines", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
|VERB_MUST_BE_ROOT
, list_machines
},
8217 { "clear-jobs", VERB_ANY
, 1, VERB_ONLINE_ONLY
, trivial_method
},
8218 { "cancel", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, cancel_job
},
8219 { "start", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8220 { "stop", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8221 { "condstop", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
}, /* For compatibility with ALTLinux */
8222 { "reload", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8223 { "restart", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8224 { "try-restart", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8225 { "reload-or-restart", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8226 { "reload-or-try-restart", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
}, /* For compatbility with old systemctl <= 228 */
8227 { "try-reload-or-restart", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
},
8228 { "force-reload", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
}, /* For compatibility with SysV */
8229 { "condreload", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
}, /* For compatibility with ALTLinux */
8230 { "condrestart", 2, VERB_ANY
, VERB_ONLINE_ONLY
, start_unit
}, /* For compatibility with RH */
8231 { "isolate", 2, 2, VERB_ONLINE_ONLY
, start_unit
},
8232 { "kill", 2, VERB_ANY
, VERB_ONLINE_ONLY
, kill_unit
},
8233 { "is-active", 2, VERB_ANY
, VERB_ONLINE_ONLY
, check_unit_active
},
8234 { "check", 2, VERB_ANY
, VERB_ONLINE_ONLY
, check_unit_active
}, /* deprecated alias of is-active */
8235 { "is-failed", 2, VERB_ANY
, VERB_ONLINE_ONLY
, check_unit_failed
},
8236 { "show", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, show
},
8237 { "cat", 2, VERB_ANY
, VERB_ONLINE_ONLY
, cat
},
8238 { "status", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, show
},
8239 { "help", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, show
},
8240 { "daemon-reload", VERB_ANY
, 1, VERB_ONLINE_ONLY
, daemon_reload
},
8241 { "daemon-reexec", VERB_ANY
, 1, VERB_ONLINE_ONLY
, daemon_reload
},
8242 { "show-environment", VERB_ANY
, 1, VERB_ONLINE_ONLY
, show_environment
},
8243 { "set-environment", 2, VERB_ANY
, VERB_ONLINE_ONLY
, set_environment
},
8244 { "unset-environment", 2, VERB_ANY
, VERB_ONLINE_ONLY
, set_environment
},
8245 { "import-environment", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, import_environment
},
8246 { "halt", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8247 { "poweroff", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8248 { "reboot", VERB_ANY
, 2, VERB_ONLINE_ONLY
, start_system_special
},
8249 { "kexec", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8250 { "suspend", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8251 { "hibernate", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8252 { "hybrid-sleep", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8253 { "suspend-to-hibernate", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8254 { "default", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_special
},
8255 { "rescue", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8256 { "emergency", VERB_ANY
, 1, VERB_ONLINE_ONLY
, start_system_special
},
8257 { "exit", VERB_ANY
, 2, VERB_ONLINE_ONLY
, start_special
},
8258 { "reset-failed", VERB_ANY
, VERB_ANY
, VERB_ONLINE_ONLY
, reset_failed
},
8259 { "enable", 2, VERB_ANY
, 0, enable_unit
},
8260 { "disable", 2, VERB_ANY
, 0, enable_unit
},
8261 { "is-enabled", 2, VERB_ANY
, 0, unit_is_enabled
},
8262 { "reenable", 2, VERB_ANY
, 0, enable_unit
},
8263 { "preset", 2, VERB_ANY
, 0, enable_unit
},
8264 { "preset-all", VERB_ANY
, 1, 0, preset_all
},
8265 { "mask", 2, VERB_ANY
, 0, enable_unit
},
8266 { "unmask", 2, VERB_ANY
, 0, enable_unit
},
8267 { "link", 2, VERB_ANY
, 0, enable_unit
},
8268 { "revert", 2, VERB_ANY
, 0, enable_unit
},
8269 { "switch-root", 2, VERB_ANY
, VERB_ONLINE_ONLY
, switch_root
},
8270 { "list-dependencies", VERB_ANY
, 2, VERB_ONLINE_ONLY
, list_dependencies
},
8271 { "set-default", 2, 2, 0, set_default
},
8272 { "get-default", VERB_ANY
, 1, 0, get_default
},
8273 { "set-property", 3, VERB_ANY
, VERB_ONLINE_ONLY
, set_property
},
8274 { "is-system-running", VERB_ANY
, 1, 0, is_system_running
},
8275 { "add-wants", 3, VERB_ANY
, 0, add_dependency
},
8276 { "add-requires", 3, VERB_ANY
, 0, add_dependency
},
8277 { "edit", 2, VERB_ANY
, VERB_ONLINE_ONLY
, edit
},
8281 return dispatch_verb(argc
, argv
, verbs
, NULL
);
8284 static int reload_with_fallback(void) {
8286 /* First, try systemd via D-Bus. */
8287 if (daemon_reload(0, NULL
, NULL
) >= 0)
8290 /* Nothing else worked, so let's try signals */
8291 assert(IN_SET(arg_action
, ACTION_RELOAD
, ACTION_REEXEC
));
8293 if (kill(1, arg_action
== ACTION_RELOAD
? SIGHUP
: SIGTERM
) < 0)
8294 return log_error_errno(errno
, "kill() failed: %m");
8299 static int start_with_fallback(void) {
8301 /* First, try systemd via D-Bus. */
8302 if (start_unit(0, NULL
, NULL
) >= 0)
8305 /* Nothing else worked, so let's try /dev/initctl */
8306 if (talk_initctl() > 0)
8309 log_error("Failed to talk to init daemon.");
8313 static int halt_now(enum action a
) {
8315 /* The kernel will automatically flush ATA disks and suchlike on reboot(), but the file systems need to be
8316 * synce'd explicitly in advance. */
8317 if (!arg_no_sync
&& !arg_dry_run
)
8320 /* Make sure C-A-D is handled by the kernel from this point on... */
8322 (void) reboot(RB_ENABLE_CAD
);
8328 log_info("Halting.");
8331 (void) reboot(RB_HALT_SYSTEM
);
8334 case ACTION_POWEROFF
:
8336 log_info("Powering off.");
8339 (void) reboot(RB_POWER_OFF
);
8344 return reboot_with_parameter(REBOOT_FALLBACK
|
8345 (arg_quiet
? 0 : REBOOT_LOG
) |
8346 (arg_dry_run
? REBOOT_DRY_RUN
: 0));
8349 assert_not_reached("Unknown action.");
8353 static int logind_schedule_shutdown(void) {
8356 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
8357 char date
[FORMAT_TIMESTAMP_MAX
];
8362 r
= acquire_bus(BUS_FULL
, &bus
);
8366 switch (arg_action
) {
8370 case ACTION_POWEROFF
:
8371 action
= "poweroff";
8386 action
= strjoina("dry-", action
);
8388 (void) logind_set_wall_message();
8390 r
= sd_bus_call_method(
8392 "org.freedesktop.login1",
8393 "/org/freedesktop/login1",
8394 "org.freedesktop.login1.Manager",
8402 return log_warning_errno(r
, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s", bus_error_message(&error
, r
));
8405 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.", format_timestamp(date
, sizeof(date
), arg_when
));
8408 log_error("Cannot schedule shutdown without logind support, proceeding with immediate shutdown.");
8413 static int halt_main(void) {
8416 r
= logind_check_inhibitors(arg_action
);
8421 return logind_schedule_shutdown();
8423 if (geteuid() != 0) {
8424 if (arg_dry_run
|| arg_force
> 0) {
8425 (void) must_be_root();
8429 /* Try logind if we are a normal user and no special
8430 * mode applies. Maybe PolicyKit allows us to shutdown
8432 if (IN_SET(arg_action
, ACTION_POWEROFF
, ACTION_REBOOT
, ACTION_HALT
)) {
8433 r
= logind_reboot(arg_action
);
8436 if (IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
8437 /* requested operation is not
8438 * supported on the local system or
8439 * already in progress */
8441 /* on all other errors, try low-level operation */
8445 if (!arg_dry_run
&& !arg_force
)
8446 return start_with_fallback();
8448 assert(geteuid() == 0);
8451 if (sd_booted() > 0)
8452 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
8454 r
= utmp_put_shutdown();
8456 log_warning_errno(r
, "Failed to write utmp record: %m");
8463 r
= halt_now(arg_action
);
8464 return log_error_errno(r
, "Failed to reboot: %m");
8467 static int runlevel_main(void) {
8468 int r
, runlevel
, previous
;
8470 r
= utmp_get_runlevel(&runlevel
, &previous
);
8477 previous
<= 0 ? 'N' : previous
,
8478 runlevel
<= 0 ? 'N' : runlevel
);
8483 static int logind_cancel_shutdown(void) {
8485 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
8489 r
= acquire_bus(BUS_FULL
, &bus
);
8493 (void) logind_set_wall_message();
8495 r
= sd_bus_call_method(
8497 "org.freedesktop.login1",
8498 "/org/freedesktop/login1",
8499 "org.freedesktop.login1.Manager",
8500 "CancelScheduledShutdown",
8504 return log_warning_errno(r
, "Failed to talk to logind, shutdown hasn't been cancelled: %s", bus_error_message(&error
, r
));
8508 log_error("Not compiled with logind support, cannot cancel scheduled shutdowns.");
8513 int main(int argc
, char*argv
[]) {
8516 argv_cmdline
= argv
[0];
8518 setlocale(LC_ALL
, "");
8519 log_parse_environment();
8523 /* Explicitly not on_tty() to avoid setting cached value.
8524 * This becomes relevant for piping output which might be
8526 original_stdout_is_tty
= isatty(STDOUT_FILENO
);
8528 r
= parse_argv(argc
, argv
);
8532 if (arg_action
!= ACTION_SYSTEMCTL
&& running_in_chroot() > 0) {
8535 log_info("Running in chroot, ignoring request.");
8540 /* systemctl_main() will print an error message for the bus
8541 * connection, but only if it needs to */
8543 switch (arg_action
) {
8545 case ACTION_SYSTEMCTL
:
8546 r
= systemctl_main(argc
, argv
);
8549 /* Legacy command aliases set arg_action. They provide some fallbacks,
8550 * e.g. to tell sysvinit to reboot after you have installed systemd
8554 case ACTION_POWEROFF
:
8560 case ACTION_RUNLEVEL2
:
8561 case ACTION_RUNLEVEL3
:
8562 case ACTION_RUNLEVEL4
:
8563 case ACTION_RUNLEVEL5
:
8565 r
= start_with_fallback();
8570 r
= reload_with_fallback();
8573 case ACTION_CANCEL_SHUTDOWN
:
8574 r
= logind_cancel_shutdown();
8577 case ACTION_RUNLEVEL
:
8578 r
= runlevel_main();
8582 case ACTION_SUSPEND
:
8583 case ACTION_HIBERNATE
:
8584 case ACTION_HYBRID_SLEEP
:
8585 case ACTION_SUSPEND_TO_HIBERNATE
:
8586 case ACTION_EMERGENCY
:
8587 case ACTION_DEFAULT
:
8588 /* systemctl verbs with no equivalent in the legacy commands.
8589 * These cannot appear in arg_action. Fall through. */
8591 case _ACTION_INVALID
:
8593 assert_not_reached("Unknown action");
8600 ask_password_agent_close();
8601 polkit_agent_close();
8603 strv_free(arg_types
);
8604 strv_free(arg_states
);
8605 strv_free(arg_properties
);
8607 strv_free(arg_wall
);
8611 /* Note that we return r here, not EXIT_SUCCESS, so that we can implement the LSB-like return codes */
8612 return r
< 0 ? EXIT_FAILURE
: r
;