2 This file is part of systemd.
4 Copyright 2010 Lennart Poettering
5 Copyright 2013 Marc-Antoine Perennou
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #include <linux/reboot.h>
30 #include <sys/reboot.h>
31 #include <sys/socket.h>
35 #include "sd-daemon.h"
38 #include "alloc-util.h"
39 #include "bus-common-errors.h"
40 #include "bus-error.h"
41 #include "bus-message.h"
42 #include "bus-unit-util.h"
44 #include "cgroup-show.h"
45 #include "cgroup-util.h"
50 #include "exit-status.h"
53 #include "formats-util.h"
55 #include "glob-util.h"
56 #include "hostname-util.h"
61 #include "locale-util.h"
63 #include "logs-show.h"
67 #include "parse-util.h"
68 #include "path-lookup.h"
69 #include "path-util.h"
70 #include "process-util.h"
71 #include "rlimit-util.h"
74 #include "signal-util.h"
75 #include "socket-util.h"
76 #include "spawn-ask-password-agent.h"
77 #include "spawn-polkit-agent.h"
79 #include "stat-util.h"
81 #include "terminal-util.h"
82 #include "unit-name.h"
83 #include "user-util.h"
85 #include "utmp-wtmp.h"
89 /* The init script exit status codes
90 0 program is running or service is OK
91 1 program is dead and /var/run pid file exists
92 2 program is dead and /var/lock lock file exists
93 3 program is not running
94 4 program or service status is unknown
95 5-99 reserved for future LSB use
96 100-149 reserved for distribution use
97 150-199 reserved for application use
101 EXIT_PROGRAM_RUNNING_OR_SERVICE_OK
= 0,
102 EXIT_PROGRAM_DEAD_AND_PID_EXISTS
= 1,
103 EXIT_PROGRAM_DEAD_AND_LOCK_FILE_EXISTS
= 2,
104 EXIT_PROGRAM_NOT_RUNNING
= 3,
105 EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN
= 4,
108 static char **arg_types
= NULL
;
109 static char **arg_states
= NULL
;
110 static char **arg_properties
= NULL
;
111 static bool arg_all
= false;
112 static enum dependency
{
118 } arg_dependency
= DEPENDENCY_FORWARD
;
119 static const char *arg_job_mode
= "replace";
120 static UnitFileScope arg_scope
= UNIT_FILE_SYSTEM
;
121 static bool arg_no_block
= false;
122 static bool arg_no_legend
= false;
123 static bool arg_no_pager
= false;
124 static bool arg_no_wtmp
= false;
125 static bool arg_no_sync
= false;
126 static bool arg_no_wall
= false;
127 static bool arg_no_reload
= false;
128 static bool arg_value
= false;
129 static bool arg_show_types
= false;
130 static bool arg_ignore_inhibitors
= false;
131 static bool arg_dry
= false;
132 static bool arg_quiet
= false;
133 static bool arg_full
= false;
134 static bool arg_recursive
= false;
135 static int arg_force
= 0;
136 static bool arg_ask_password
= false;
137 static bool arg_runtime
= false;
138 static UnitFilePresetMode arg_preset_mode
= UNIT_FILE_PRESET_FULL
;
139 static char **arg_wall
= NULL
;
140 static const char *arg_kill_who
= NULL
;
141 static int arg_signal
= SIGTERM
;
142 static char *arg_root
= NULL
;
143 static usec_t arg_when
= 0;
165 ACTION_CANCEL_SHUTDOWN
,
167 } arg_action
= ACTION_SYSTEMCTL
;
168 static BusTransport arg_transport
= BUS_TRANSPORT_LOCAL
;
169 static const char *arg_host
= NULL
;
170 static unsigned arg_lines
= 10;
171 static OutputMode arg_output
= OUTPUT_SHORT
;
172 static bool arg_plain
= false;
173 static bool arg_firmware_setup
= false;
174 static bool arg_now
= false;
176 static int daemon_reload(int argc
, char *argv
[], void* userdata
);
177 static int halt_now(enum action a
);
178 static int get_state_one_unit(sd_bus
*bus
, const char *name
, UnitActiveState
*active_state
);
180 static bool original_stdout_is_tty
;
182 typedef enum BusFocus
{
183 BUS_FULL
, /* The full bus indicated via --system or --user */
184 BUS_MANAGER
, /* The manager itself, possibly directly, possibly via the bus */
188 static sd_bus
*busses
[_BUS_FOCUS_MAX
] = {};
190 static int acquire_bus(BusFocus focus
, sd_bus
**ret
) {
193 assert(focus
< _BUS_FOCUS_MAX
);
196 /* We only go directly to the manager, if we are using a local transport */
197 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
200 if (!busses
[focus
]) {
203 user
= arg_scope
!= UNIT_FILE_SYSTEM
;
205 if (focus
== BUS_MANAGER
)
206 r
= bus_connect_transport_systemd(arg_transport
, arg_host
, user
, &busses
[focus
]);
208 r
= bus_connect_transport(arg_transport
, arg_host
, user
, &busses
[focus
]);
210 return log_error_errno(r
, "Failed to connect to bus: %m");
212 (void) sd_bus_set_allow_interactive_authorization(busses
[focus
], arg_ask_password
);
215 *ret
= busses
[focus
];
219 static void release_busses(void) {
222 for (w
= 0; w
< _BUS_FOCUS_MAX
; w
++)
223 busses
[w
] = sd_bus_flush_close_unref(busses
[w
]);
226 static void ask_password_agent_open_if_enabled(void) {
228 /* Open the password agent as a child process if necessary */
230 if (!arg_ask_password
)
233 if (arg_scope
!= UNIT_FILE_SYSTEM
)
236 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
239 ask_password_agent_open();
242 static void polkit_agent_open_if_enabled(void) {
244 /* Open the polkit agent as a child process if necessary */
246 if (!arg_ask_password
)
249 if (arg_scope
!= UNIT_FILE_SYSTEM
)
252 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
258 static OutputFlags
get_output_flags(void) {
260 arg_all
* OUTPUT_SHOW_ALL
|
261 arg_full
* OUTPUT_FULL_WIDTH
|
262 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH
|
263 colors_enabled() * OUTPUT_COLOR
|
264 !arg_quiet
* OUTPUT_WARN_CUTOFF
;
267 static int translate_bus_error_to_exit_status(int r
, const sd_bus_error
*error
) {
270 if (!sd_bus_error_is_set(error
))
273 if (sd_bus_error_has_name(error
, SD_BUS_ERROR_ACCESS_DENIED
) ||
274 sd_bus_error_has_name(error
, BUS_ERROR_ONLY_BY_DEPENDENCY
) ||
275 sd_bus_error_has_name(error
, BUS_ERROR_NO_ISOLATION
) ||
276 sd_bus_error_has_name(error
, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE
))
277 return EXIT_NOPERMISSION
;
279 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
))
280 return EXIT_NOTINSTALLED
;
282 if (sd_bus_error_has_name(error
, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE
) ||
283 sd_bus_error_has_name(error
, SD_BUS_ERROR_NOT_SUPPORTED
))
284 return EXIT_NOTIMPLEMENTED
;
286 if (sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
))
287 return EXIT_NOTCONFIGURED
;
295 static bool install_client_side(void) {
297 /* Decides when to execute enable/disable/... operations
298 * client-side rather than server-side. */
300 if (running_in_chroot() > 0)
303 if (sd_booted() <= 0)
306 if (!isempty(arg_root
))
309 if (arg_scope
== UNIT_FILE_GLOBAL
)
312 /* Unsupported environment variable, mostly for debugging purposes */
313 if (getenv_bool("SYSTEMCTL_INSTALL_CLIENT_SIDE") > 0)
319 static int compare_unit_info(const void *a
, const void *b
) {
320 const UnitInfo
*u
= a
, *v
= b
;
324 /* First, order by machine */
325 if (!u
->machine
&& v
->machine
)
327 if (u
->machine
&& !v
->machine
)
329 if (u
->machine
&& v
->machine
) {
330 r
= strcasecmp(u
->machine
, v
->machine
);
335 /* Second, order by unit type */
336 d1
= strrchr(u
->id
, '.');
337 d2
= strrchr(v
->id
, '.');
339 r
= strcasecmp(d1
, d2
);
344 /* Third, order by name */
345 return strcasecmp(u
->id
, v
->id
);
348 static bool output_show_unit(const UnitInfo
*u
, char **patterns
) {
351 if (!strv_fnmatch_or_empty(patterns
, u
->id
, FNM_NOESCAPE
))
357 dot
= strrchr(u
->id
, '.');
361 if (!strv_find(arg_types
, dot
+1))
368 /* Note that '--all' is not purely a state filter, but also a
369 * filter that hides units that "follow" other units (which is
370 * used for device units that appear under different names). */
371 if (!isempty(u
->following
))
374 if (!strv_isempty(arg_states
))
377 /* By default show all units except the ones in inactive
378 * state and with no pending job */
382 if (streq(u
->active_state
, "inactive"))
388 static int output_units_list(const UnitInfo
*unit_infos
, unsigned c
) {
389 unsigned circle_len
= 0, id_len
, max_id_len
, load_len
, active_len
, sub_len
, job_len
, desc_len
;
391 unsigned n_shown
= 0;
394 max_id_len
= strlen("UNIT");
395 load_len
= strlen("LOAD");
396 active_len
= strlen("ACTIVE");
397 sub_len
= strlen("SUB");
398 job_len
= strlen("JOB");
401 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
402 max_id_len
= MAX(max_id_len
, strlen(u
->id
) + (u
->machine
? strlen(u
->machine
)+1 : 0));
403 load_len
= MAX(load_len
, strlen(u
->load_state
));
404 active_len
= MAX(active_len
, strlen(u
->active_state
));
405 sub_len
= MAX(sub_len
, strlen(u
->sub_state
));
407 if (u
->job_id
!= 0) {
408 job_len
= MAX(job_len
, strlen(u
->job_type
));
412 if (!arg_no_legend
&&
413 (streq(u
->active_state
, "failed") ||
414 STR_IN_SET(u
->load_state
, "error", "not-found", "masked")))
418 if (!arg_full
&& original_stdout_is_tty
) {
421 id_len
= MIN(max_id_len
, 25u);
422 basic_len
= circle_len
+ 5 + id_len
+ 5 + active_len
+ sub_len
;
425 basic_len
+= job_len
+ 1;
427 if (basic_len
< (unsigned) columns()) {
428 unsigned extra_len
, incr
;
429 extra_len
= columns() - basic_len
;
431 /* Either UNIT already got 25, or is fully satisfied.
432 * Grant up to 25 to DESC now. */
433 incr
= MIN(extra_len
, 25u);
437 /* split the remaining space between UNIT and DESC,
438 * but do not give UNIT more than it needs. */
440 incr
= MIN(extra_len
/ 2, max_id_len
- id_len
);
442 desc_len
+= extra_len
- incr
;
448 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
449 _cleanup_free_
char *e
= NULL
, *j
= NULL
;
450 const char *on_loaded
= "", *off_loaded
= "";
451 const char *on_active
= "", *off_active
= "";
452 const char *on_circle
= "", *off_circle
= "";
456 if (!n_shown
&& !arg_no_legend
) {
461 printf("%-*s %-*s %-*s %-*s ",
464 active_len
, "ACTIVE",
468 printf("%-*s ", job_len
, "JOB");
470 if (!arg_full
&& arg_no_pager
)
471 printf("%.*s\n", desc_len
, "DESCRIPTION");
473 printf("%s\n", "DESCRIPTION");
478 if (STR_IN_SET(u
->load_state
, "error", "not-found", "masked") && !arg_plain
) {
479 on_loaded
= ansi_highlight_red();
480 on_circle
= ansi_highlight_yellow();
481 off_loaded
= off_circle
= ansi_normal();
483 } else if (streq(u
->active_state
, "failed") && !arg_plain
) {
484 on_circle
= on_active
= ansi_highlight_red();
485 off_circle
= off_active
= ansi_normal();
490 j
= strjoin(u
->machine
, ":", u
->id
, NULL
);
499 e
= ellipsize(id
, id_len
, 33);
507 printf("%s%s%s ", on_circle
, circle
? special_glyph(BLACK_CIRCLE
) : " ", off_circle
);
509 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
510 on_active
, id_len
, id
, off_active
,
511 on_loaded
, load_len
, u
->load_state
, off_loaded
,
512 on_active
, active_len
, u
->active_state
,
513 sub_len
, u
->sub_state
, off_active
,
514 job_count
? job_len
+ 1 : 0, u
->job_id
? u
->job_type
: "");
517 printf("%.*s\n", desc_len
, u
->description
);
519 printf("%s\n", u
->description
);
522 if (!arg_no_legend
) {
523 const char *on
, *off
;
527 "LOAD = Reflects whether the unit definition was properly loaded.\n"
528 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
529 "SUB = The low-level unit activation state, values depend on unit type.");
530 puts(job_count
? "JOB = Pending job for the unit.\n" : "");
531 on
= ansi_highlight();
534 on
= ansi_highlight_red();
539 printf("%s%u loaded units listed.%s\n"
540 "To show all installed unit files use 'systemctl list-unit-files'.\n",
543 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
544 "To show all installed unit files use 'systemctl list-unit-files'.\n",
551 static int get_unit_list(
555 UnitInfo
**unit_infos
,
557 sd_bus_message
**_reply
) {
559 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
560 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
561 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
565 bool fallback
= false;
571 r
= sd_bus_message_new_method_call(
574 "org.freedesktop.systemd1",
575 "/org/freedesktop/systemd1",
576 "org.freedesktop.systemd1.Manager",
577 "ListUnitsByPatterns");
579 return bus_log_create_error(r
);
581 r
= sd_bus_message_append_strv(m
, arg_states
);
583 return bus_log_create_error(r
);
585 r
= sd_bus_message_append_strv(m
, patterns
);
587 return bus_log_create_error(r
);
589 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
590 if (r
< 0 && sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_METHOD
)) {
591 /* Fallback to legacy ListUnitsFiltered method */
593 log_debug_errno(r
, "Failed to list units: %s Falling back to ListUnitsFiltered method.", bus_error_message(&error
, r
));
594 m
= sd_bus_message_unref(m
);
595 sd_bus_error_free(&error
);
597 r
= sd_bus_message_new_method_call(
600 "org.freedesktop.systemd1",
601 "/org/freedesktop/systemd1",
602 "org.freedesktop.systemd1.Manager",
603 "ListUnitsFiltered");
605 return bus_log_create_error(r
);
607 r
= sd_bus_message_append_strv(m
, arg_states
);
609 return bus_log_create_error(r
);
611 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
614 return log_error_errno(r
, "Failed to list units: %s", bus_error_message(&error
, r
));
616 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssssouso)");
618 return bus_log_parse_error(r
);
620 while ((r
= bus_parse_unit_info(reply
, &u
)) > 0) {
623 if (!output_show_unit(&u
, fallback
? patterns
: NULL
))
626 if (!GREEDY_REALLOC(*unit_infos
, size
, c
+1))
629 (*unit_infos
)[c
++] = u
;
632 return bus_log_parse_error(r
);
634 r
= sd_bus_message_exit_container(reply
);
636 return bus_log_parse_error(r
);
644 static void message_set_freep(Set
**set
) {
647 while ((m
= set_steal_first(*set
)))
648 sd_bus_message_unref(m
);
653 static int get_unit_list_recursive(
656 UnitInfo
**_unit_infos
,
660 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
661 _cleanup_(message_set_freep
) Set
*replies
;
662 sd_bus_message
*reply
;
670 replies
= set_new(NULL
);
674 c
= get_unit_list(bus
, NULL
, patterns
, &unit_infos
, 0, &reply
);
678 r
= set_put(replies
, reply
);
680 sd_bus_message_unref(reply
);
685 _cleanup_strv_free_
char **machines
= NULL
;
688 r
= sd_get_machine_names(&machines
);
690 return log_error_errno(r
, "Failed to get machine names: %m");
692 STRV_FOREACH(i
, machines
) {
693 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*container
= NULL
;
696 r
= sd_bus_open_system_machine(&container
, *i
);
698 log_warning_errno(r
, "Failed to connect to container %s, ignoring: %m", *i
);
702 k
= get_unit_list(container
, *i
, patterns
, &unit_infos
, c
, &reply
);
708 r
= set_put(replies
, reply
);
710 sd_bus_message_unref(reply
);
715 *_machines
= machines
;
720 *_unit_infos
= unit_infos
;
729 static int list_units(int argc
, char *argv
[], void *userdata
) {
730 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
731 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
732 _cleanup_strv_free_
char **machines
= NULL
;
736 pager_open(arg_no_pager
, false);
738 r
= acquire_bus(BUS_MANAGER
, &bus
);
742 r
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
746 qsort_safe(unit_infos
, r
, sizeof(UnitInfo
), compare_unit_info
);
747 return output_units_list(unit_infos
, r
);
750 static int get_triggered_units(
755 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
762 r
= sd_bus_get_property_strv(
764 "org.freedesktop.systemd1",
766 "org.freedesktop.systemd1.Unit",
771 return log_error_errno(r
, "Failed to determine triggers: %s", bus_error_message(&error
, r
));
776 static int get_listening(
778 const char* unit_path
,
781 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
782 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
783 const char *type
, *path
;
786 r
= sd_bus_get_property(
788 "org.freedesktop.systemd1",
790 "org.freedesktop.systemd1.Socket",
796 return log_error_errno(r
, "Failed to get list of listening sockets: %s", bus_error_message(&error
, r
));
798 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
800 return bus_log_parse_error(r
);
802 while ((r
= sd_bus_message_read(reply
, "(ss)", &type
, &path
)) > 0) {
804 r
= strv_extend(listening
, type
);
808 r
= strv_extend(listening
, path
);
815 return bus_log_parse_error(r
);
817 r
= sd_bus_message_exit_container(reply
);
819 return bus_log_parse_error(r
);
831 /* Note: triggered is a list here, although it almost certainly
832 * will always be one unit. Nevertheless, dbus API allows for multiple
833 * values, so let's follow that. */
836 /* The strv above is shared. free is set only in the first one. */
840 static int socket_info_compare(const struct socket_info
*a
, const struct socket_info
*b
) {
846 if (!a
->machine
&& b
->machine
)
848 if (a
->machine
&& !b
->machine
)
850 if (a
->machine
&& b
->machine
) {
851 o
= strcasecmp(a
->machine
, b
->machine
);
856 o
= strcmp(a
->path
, b
->path
);
858 o
= strcmp(a
->type
, b
->type
);
863 static int output_sockets_list(struct socket_info
*socket_infos
, unsigned cs
) {
864 struct socket_info
*s
;
865 unsigned pathlen
= strlen("LISTEN"),
866 typelen
= strlen("TYPE") * arg_show_types
,
867 socklen
= strlen("UNIT"),
868 servlen
= strlen("ACTIVATES");
869 const char *on
, *off
;
871 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
875 socklen
= MAX(socklen
, strlen(s
->id
));
877 typelen
= MAX(typelen
, strlen(s
->type
));
878 pathlen
= MAX(pathlen
, strlen(s
->path
) + (s
->machine
? strlen(s
->machine
)+1 : 0));
880 STRV_FOREACH(a
, s
->triggered
)
881 tmp
+= strlen(*a
) + 2*(a
!= s
->triggered
);
882 servlen
= MAX(servlen
, tmp
);
887 printf("%-*s %-*.*s%-*s %s\n",
889 typelen
+ arg_show_types
, typelen
+ arg_show_types
, "TYPE ",
893 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
894 _cleanup_free_
char *j
= NULL
;
899 j
= strjoin(s
->machine
, ":", s
->path
, NULL
);
907 printf("%-*s %-*s %-*s",
908 pathlen
, path
, typelen
, s
->type
, socklen
, s
->id
);
911 pathlen
, path
, socklen
, s
->id
);
912 STRV_FOREACH(a
, s
->triggered
)
914 a
== s
->triggered
? "" : ",", *a
);
918 on
= ansi_highlight();
923 on
= ansi_highlight_red();
927 if (!arg_no_legend
) {
928 printf("%s%u sockets listed.%s\n", on
, cs
, off
);
930 printf("Pass --all to see loaded but inactive sockets, too.\n");
936 static int list_sockets(int argc
, char *argv
[], void *userdata
) {
937 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
938 _cleanup_strv_free_
char **machines
= NULL
;
939 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
940 _cleanup_free_
struct socket_info
*socket_infos
= NULL
;
942 struct socket_info
*s
;
948 pager_open(arg_no_pager
, false);
950 r
= acquire_bus(BUS_MANAGER
, &bus
);
954 n
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
958 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
959 _cleanup_strv_free_
char **listening
= NULL
, **triggered
= NULL
;
962 if (!endswith(u
->id
, ".socket"))
965 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
969 c
= get_listening(bus
, u
->unit_path
, &listening
);
975 if (!GREEDY_REALLOC(socket_infos
, size
, cs
+ c
)) {
980 for (i
= 0; i
< c
; i
++)
981 socket_infos
[cs
+ i
] = (struct socket_info
) {
982 .machine
= u
->machine
,
984 .type
= listening
[i
*2],
985 .path
= listening
[i
*2 + 1],
986 .triggered
= triggered
,
987 .own_triggered
= i
==0,
990 /* from this point on we will cleanup those socket_infos */
993 listening
= triggered
= NULL
; /* avoid cleanup */
996 qsort_safe(socket_infos
, cs
, sizeof(struct socket_info
),
997 (__compar_fn_t
) socket_info_compare
);
999 output_sockets_list(socket_infos
, cs
);
1002 assert(cs
== 0 || socket_infos
);
1003 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
1006 if (s
->own_triggered
)
1007 strv_free(s
->triggered
);
1013 static int get_next_elapse(
1016 dual_timestamp
*next
) {
1018 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1026 r
= sd_bus_get_property_trivial(
1028 "org.freedesktop.systemd1",
1030 "org.freedesktop.systemd1.Timer",
1031 "NextElapseUSecMonotonic",
1036 return log_error_errno(r
, "Failed to get next elapsation time: %s", bus_error_message(&error
, r
));
1038 r
= sd_bus_get_property_trivial(
1040 "org.freedesktop.systemd1",
1042 "org.freedesktop.systemd1.Timer",
1043 "NextElapseUSecRealtime",
1048 return log_error_errno(r
, "Failed to get next elapsation time: %s", bus_error_message(&error
, r
));
1054 static int get_last_trigger(
1059 _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",
1076 return log_error_errno(r
, "Failed to get last trigger time: %s", bus_error_message(&error
, r
));
1082 const char* machine
;
1085 usec_t last_trigger
;
1089 static int timer_info_compare(const struct timer_info
*a
, const struct timer_info
*b
) {
1095 if (!a
->machine
&& b
->machine
)
1097 if (a
->machine
&& !b
->machine
)
1099 if (a
->machine
&& b
->machine
) {
1100 o
= strcasecmp(a
->machine
, b
->machine
);
1105 if (a
->next_elapse
< b
->next_elapse
)
1107 if (a
->next_elapse
> b
->next_elapse
)
1110 return strcmp(a
->id
, b
->id
);
1113 static int output_timers_list(struct timer_info
*timer_infos
, unsigned n
) {
1114 struct timer_info
*t
;
1116 nextlen
= strlen("NEXT"),
1117 leftlen
= strlen("LEFT"),
1118 lastlen
= strlen("LAST"),
1119 passedlen
= strlen("PASSED"),
1120 unitlen
= strlen("UNIT"),
1121 activatelen
= strlen("ACTIVATES");
1123 const char *on
, *off
;
1125 assert(timer_infos
|| n
== 0);
1127 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1131 if (t
->next_elapse
> 0) {
1132 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1134 format_timestamp(tstamp
, sizeof(tstamp
), t
->next_elapse
);
1135 nextlen
= MAX(nextlen
, strlen(tstamp
) + 1);
1137 format_timestamp_relative(trel
, sizeof(trel
), t
->next_elapse
);
1138 leftlen
= MAX(leftlen
, strlen(trel
));
1141 if (t
->last_trigger
> 0) {
1142 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1144 format_timestamp(tstamp
, sizeof(tstamp
), t
->last_trigger
);
1145 lastlen
= MAX(lastlen
, strlen(tstamp
) + 1);
1147 format_timestamp_relative(trel
, sizeof(trel
), t
->last_trigger
);
1148 passedlen
= MAX(passedlen
, strlen(trel
));
1151 unitlen
= MAX(unitlen
, strlen(t
->id
) + (t
->machine
? strlen(t
->machine
)+1 : 0));
1153 STRV_FOREACH(a
, t
->triggered
)
1154 ul
+= strlen(*a
) + 2*(a
!= t
->triggered
);
1156 activatelen
= MAX(activatelen
, ul
);
1161 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1165 passedlen
, "PASSED",
1169 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1170 _cleanup_free_
char *j
= NULL
;
1172 char tstamp1
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel1
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1173 char tstamp2
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel2
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1176 format_timestamp(tstamp1
, sizeof(tstamp1
), t
->next_elapse
);
1177 format_timestamp_relative(trel1
, sizeof(trel1
), t
->next_elapse
);
1179 format_timestamp(tstamp2
, sizeof(tstamp2
), t
->last_trigger
);
1180 format_timestamp_relative(trel2
, sizeof(trel2
), t
->last_trigger
);
1183 j
= strjoin(t
->machine
, ":", t
->id
, NULL
);
1190 printf("%-*s %-*s %-*s %-*s %-*s",
1191 nextlen
, tstamp1
, leftlen
, trel1
, lastlen
, tstamp2
, passedlen
, trel2
, unitlen
, unit
);
1193 STRV_FOREACH(a
, t
->triggered
)
1195 a
== t
->triggered
? "" : ",", *a
);
1199 on
= ansi_highlight();
1200 off
= ansi_normal();
1204 on
= ansi_highlight_red();
1205 off
= ansi_normal();
1208 if (!arg_no_legend
) {
1209 printf("%s%u timers listed.%s\n", on
, n
, off
);
1211 printf("Pass --all to see loaded but inactive timers, too.\n");
1217 static usec_t
calc_next_elapse(dual_timestamp
*nw
, dual_timestamp
*next
) {
1223 if (next
->monotonic
!= USEC_INFINITY
&& next
->monotonic
> 0) {
1226 if (next
->monotonic
> nw
->monotonic
)
1227 converted
= nw
->realtime
+ (next
->monotonic
- nw
->monotonic
);
1229 converted
= nw
->realtime
- (nw
->monotonic
- next
->monotonic
);
1231 if (next
->realtime
!= USEC_INFINITY
&& next
->realtime
> 0)
1232 next_elapse
= MIN(converted
, next
->realtime
);
1234 next_elapse
= converted
;
1237 next_elapse
= next
->realtime
;
1242 static int list_timers(int argc
, char *argv
[], void *userdata
) {
1243 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
1244 _cleanup_strv_free_
char **machines
= NULL
;
1245 _cleanup_free_
struct timer_info
*timer_infos
= NULL
;
1246 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
1247 struct timer_info
*t
;
1255 pager_open(arg_no_pager
, false);
1257 r
= acquire_bus(BUS_MANAGER
, &bus
);
1261 n
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
1265 dual_timestamp_get(&nw
);
1267 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
1268 _cleanup_strv_free_
char **triggered
= NULL
;
1269 dual_timestamp next
= DUAL_TIMESTAMP_NULL
;
1272 if (!endswith(u
->id
, ".timer"))
1275 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
1279 r
= get_next_elapse(bus
, u
->unit_path
, &next
);
1283 get_last_trigger(bus
, u
->unit_path
, &last
);
1285 if (!GREEDY_REALLOC(timer_infos
, size
, c
+1)) {
1290 m
= calc_next_elapse(&nw
, &next
);
1292 timer_infos
[c
++] = (struct timer_info
) {
1293 .machine
= u
->machine
,
1296 .last_trigger
= last
,
1297 .triggered
= triggered
,
1300 triggered
= NULL
; /* avoid cleanup */
1303 qsort_safe(timer_infos
, c
, sizeof(struct timer_info
),
1304 (__compar_fn_t
) timer_info_compare
);
1306 output_timers_list(timer_infos
, c
);
1309 for (t
= timer_infos
; t
< timer_infos
+ c
; t
++)
1310 strv_free(t
->triggered
);
1315 static int compare_unit_file_list(const void *a
, const void *b
) {
1316 const char *d1
, *d2
;
1317 const UnitFileList
*u
= a
, *v
= b
;
1319 d1
= strrchr(u
->path
, '.');
1320 d2
= strrchr(v
->path
, '.');
1325 r
= strcasecmp(d1
, d2
);
1330 return strcasecmp(basename(u
->path
), basename(v
->path
));
1333 static bool output_show_unit_file(const UnitFileList
*u
, char **states
, char **patterns
) {
1336 if (!strv_fnmatch_or_empty(patterns
, basename(u
->path
), FNM_NOESCAPE
))
1339 if (!strv_isempty(arg_types
)) {
1342 dot
= strrchr(u
->path
, '.');
1346 if (!strv_find(arg_types
, dot
+1))
1350 if (!strv_isempty(states
) &&
1351 !strv_find(states
, unit_file_state_to_string(u
->state
)))
1357 static void output_unit_file_list(const UnitFileList
*units
, unsigned c
) {
1358 unsigned max_id_len
, id_cols
, state_cols
;
1359 const UnitFileList
*u
;
1361 max_id_len
= strlen("UNIT FILE");
1362 state_cols
= strlen("STATE");
1364 for (u
= units
; u
< units
+ c
; u
++) {
1365 max_id_len
= MAX(max_id_len
, strlen(basename(u
->path
)));
1366 state_cols
= MAX(state_cols
, strlen(unit_file_state_to_string(u
->state
)));
1370 unsigned basic_cols
;
1372 id_cols
= MIN(max_id_len
, 25u);
1373 basic_cols
= 1 + id_cols
+ state_cols
;
1374 if (basic_cols
< (unsigned) columns())
1375 id_cols
+= MIN(columns() - basic_cols
, max_id_len
- id_cols
);
1377 id_cols
= max_id_len
;
1379 if (!arg_no_legend
&& c
> 0)
1380 printf("%-*s %-*s\n",
1381 id_cols
, "UNIT FILE",
1382 state_cols
, "STATE");
1384 for (u
= units
; u
< units
+ c
; u
++) {
1385 _cleanup_free_
char *e
= NULL
;
1386 const char *on
, *off
;
1389 if (IN_SET(u
->state
,
1391 UNIT_FILE_MASKED_RUNTIME
,
1394 on
= ansi_highlight_red();
1395 off
= ansi_normal();
1396 } else if (u
->state
== UNIT_FILE_ENABLED
) {
1397 on
= ansi_highlight_green();
1398 off
= ansi_normal();
1402 id
= basename(u
->path
);
1404 e
= arg_full
? NULL
: ellipsize(id
, id_cols
, 33);
1406 printf("%-*s %s%-*s%s\n",
1407 id_cols
, e
? e
: id
,
1408 on
, state_cols
, unit_file_state_to_string(u
->state
), off
);
1412 printf("\n%u unit files listed.\n", c
);
1415 static int list_unit_files(int argc
, char *argv
[], void *userdata
) {
1416 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1417 _cleanup_free_ UnitFileList
*units
= NULL
;
1424 bool fallback
= false;
1426 pager_open(arg_no_pager
, false);
1428 if (install_client_side()) {
1434 h
= hashmap_new(&string_hash_ops
);
1438 r
= unit_file_get_list(arg_scope
, arg_root
, h
, arg_states
, strv_skip(argv
, 1));
1440 unit_file_list_free(h
);
1441 return log_error_errno(r
, "Failed to get unit file list: %m");
1444 n_units
= hashmap_size(h
);
1446 units
= new(UnitFileList
, n_units
?: 1); /* avoid malloc(0) */
1448 unit_file_list_free(h
);
1452 HASHMAP_FOREACH(u
, h
, i
) {
1453 if (!output_show_unit_file(u
, NULL
, NULL
))
1460 assert(c
<= n_units
);
1465 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
1466 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1469 r
= acquire_bus(BUS_MANAGER
, &bus
);
1473 r
= sd_bus_message_new_method_call(
1476 "org.freedesktop.systemd1",
1477 "/org/freedesktop/systemd1",
1478 "org.freedesktop.systemd1.Manager",
1479 "ListUnitFilesByPatterns");
1481 return bus_log_create_error(r
);
1483 r
= sd_bus_message_append_strv(m
, arg_states
);
1485 return bus_log_create_error(r
);
1487 r
= sd_bus_message_append_strv(m
, strv_skip(argv
, 1));
1489 return bus_log_create_error(r
);
1491 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
1492 if (r
< 0 && sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_METHOD
)) {
1493 /* Fallback to legacy ListUnitFiles method */
1495 log_debug_errno(r
, "Failed to list unit files: %s Falling back to ListUnitsFiles method.", bus_error_message(&error
, r
));
1496 m
= sd_bus_message_unref(m
);
1497 sd_bus_error_free(&error
);
1499 r
= sd_bus_message_new_method_call(
1502 "org.freedesktop.systemd1",
1503 "/org/freedesktop/systemd1",
1504 "org.freedesktop.systemd1.Manager",
1507 return bus_log_create_error(r
);
1509 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
1512 return log_error_errno(r
, "Failed to list unit files: %s", bus_error_message(&error
, r
));
1514 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
1516 return bus_log_parse_error(r
);
1518 while ((r
= sd_bus_message_read(reply
, "(ss)", &path
, &state
)) > 0) {
1520 if (!GREEDY_REALLOC(units
, size
, c
+ 1))
1523 units
[c
] = (struct UnitFileList
) {
1525 unit_file_state_from_string(state
)
1528 if (output_show_unit_file(&units
[c
],
1529 fallback
? arg_states
: NULL
,
1530 fallback
? strv_skip(argv
, 1) : NULL
))
1535 return bus_log_parse_error(r
);
1537 r
= sd_bus_message_exit_container(reply
);
1539 return bus_log_parse_error(r
);
1542 qsort_safe(units
, c
, sizeof(UnitFileList
), compare_unit_file_list
);
1543 output_unit_file_list(units
, c
);
1545 if (install_client_side())
1546 for (unit
= units
; unit
< units
+ c
; unit
++)
1552 static int list_dependencies_print(const char *name
, int level
, unsigned int branches
, bool last
) {
1553 _cleanup_free_
char *n
= NULL
;
1554 size_t max_len
= MAX(columns(),20u);
1560 for (i
= level
- 1; i
>= 0; i
--) {
1562 if (len
> max_len
- 3 && !arg_full
) {
1563 printf("%s...\n",max_len
% 2 ? "" : " ");
1566 printf("%s", special_glyph(branches
& (1 << i
) ? TREE_VERTICAL
: TREE_SPACE
));
1570 if (len
> max_len
- 3 && !arg_full
) {
1571 printf("%s...\n",max_len
% 2 ? "" : " ");
1575 printf("%s", special_glyph(last
? TREE_RIGHT
: TREE_BRANCH
));
1579 printf("%s\n", name
);
1583 n
= ellipsize(name
, max_len
-len
, 100);
1591 static int list_dependencies_get_dependencies(sd_bus
*bus
, const char *name
, char ***deps
) {
1593 static const char *dependencies
[_DEPENDENCY_MAX
] = {
1594 [DEPENDENCY_FORWARD
] = "Requires\0"
1599 [DEPENDENCY_REVERSE
] = "RequiredBy\0"
1604 [DEPENDENCY_AFTER
] = "After\0",
1605 [DEPENDENCY_BEFORE
] = "Before\0",
1608 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1609 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1610 _cleanup_strv_free_
char **ret
= NULL
;
1611 _cleanup_free_
char *path
= NULL
;
1617 assert_cc(ELEMENTSOF(dependencies
) == _DEPENDENCY_MAX
);
1619 path
= unit_dbus_path_from_name(name
);
1623 r
= sd_bus_call_method(
1625 "org.freedesktop.systemd1",
1627 "org.freedesktop.DBus.Properties",
1631 "s", "org.freedesktop.systemd1.Unit");
1633 return log_error_errno(r
, "Failed to get properties of %s: %s", name
, bus_error_message(&error
, r
));
1635 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
1637 return bus_log_parse_error(r
);
1639 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
1642 r
= sd_bus_message_read(reply
, "s", &prop
);
1644 return bus_log_parse_error(r
);
1646 if (!nulstr_contains(dependencies
[arg_dependency
], prop
)) {
1647 r
= sd_bus_message_skip(reply
, "v");
1649 return bus_log_parse_error(r
);
1652 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, "as");
1654 return bus_log_parse_error(r
);
1656 r
= bus_message_read_strv_extend(reply
, &ret
);
1658 return bus_log_parse_error(r
);
1660 r
= sd_bus_message_exit_container(reply
);
1662 return bus_log_parse_error(r
);
1665 r
= sd_bus_message_exit_container(reply
);
1667 return bus_log_parse_error(r
);
1671 return bus_log_parse_error(r
);
1673 r
= sd_bus_message_exit_container(reply
);
1675 return bus_log_parse_error(r
);
1683 static int list_dependencies_compare(const void *_a
, const void *_b
) {
1684 const char **a
= (const char**) _a
, **b
= (const char**) _b
;
1686 if (unit_name_to_type(*a
) == UNIT_TARGET
&& unit_name_to_type(*b
) != UNIT_TARGET
)
1688 if (unit_name_to_type(*a
) != UNIT_TARGET
&& unit_name_to_type(*b
) == UNIT_TARGET
)
1691 return strcasecmp(*a
, *b
);
1694 static int list_dependencies_one(
1699 unsigned int branches
) {
1701 _cleanup_strv_free_
char **deps
= NULL
;
1709 r
= strv_extend(units
, name
);
1713 r
= list_dependencies_get_dependencies(bus
, name
, &deps
);
1717 qsort_safe(deps
, strv_length(deps
), sizeof (char*), list_dependencies_compare
);
1719 STRV_FOREACH(c
, deps
) {
1720 if (strv_contains(*units
, *c
)) {
1722 r
= list_dependencies_print("...", level
+ 1, (branches
<< 1) | (c
[1] == NULL
? 0 : 1), 1);
1732 UnitActiveState active_state
= _UNIT_ACTIVE_STATE_INVALID
;
1735 (void) get_state_one_unit(bus
, *c
, &active_state
);
1737 switch (active_state
) {
1739 case UNIT_RELOADING
:
1740 case UNIT_ACTIVATING
:
1741 on
= ansi_highlight_green();
1745 case UNIT_DEACTIVATING
:
1750 on
= ansi_highlight_red();
1754 printf("%s%s%s ", on
, special_glyph(BLACK_CIRCLE
), ansi_normal());
1757 r
= list_dependencies_print(*c
, level
, branches
, c
[1] == NULL
);
1761 if (arg_all
|| unit_name_to_type(*c
) == UNIT_TARGET
) {
1762 r
= list_dependencies_one(bus
, *c
, level
+ 1, units
, (branches
<< 1) | (c
[1] == NULL
? 0 : 1));
1769 strv_remove(*units
, name
);
1774 static int list_dependencies(int argc
, char *argv
[], void *userdata
) {
1775 _cleanup_strv_free_
char **units
= NULL
;
1776 _cleanup_free_
char *unit
= NULL
;
1782 r
= unit_name_mangle(argv
[1], UNIT_NAME_NOGLOB
, &unit
);
1784 return log_error_errno(r
, "Failed to mangle unit name: %m");
1788 u
= SPECIAL_DEFAULT_TARGET
;
1790 pager_open(arg_no_pager
, false);
1792 r
= acquire_bus(BUS_MANAGER
, &bus
);
1798 return list_dependencies_one(bus
, u
, 0, &units
, 0);
1801 struct machine_info
{
1805 char *control_group
;
1806 uint32_t n_failed_units
;
1811 static const struct bus_properties_map machine_info_property_map
[] = {
1812 { "SystemState", "s", NULL
, offsetof(struct machine_info
, state
) },
1813 { "NJobs", "u", NULL
, offsetof(struct machine_info
, n_jobs
) },
1814 { "NFailedUnits", "u", NULL
, offsetof(struct machine_info
, n_failed_units
) },
1815 { "ControlGroup", "s", NULL
, offsetof(struct machine_info
, control_group
) },
1816 { "UserspaceTimestamp", "t", NULL
, offsetof(struct machine_info
, timestamp
) },
1820 static void machine_info_clear(struct machine_info
*info
) {
1824 free(info
->control_group
);
1829 static void free_machines_list(struct machine_info
*machine_infos
, int n
) {
1835 for (i
= 0; i
< n
; i
++)
1836 machine_info_clear(&machine_infos
[i
]);
1838 free(machine_infos
);
1841 static int compare_machine_info(const void *a
, const void *b
) {
1842 const struct machine_info
*u
= a
, *v
= b
;
1844 if (u
->is_host
!= v
->is_host
)
1845 return u
->is_host
> v
->is_host
? -1 : 1;
1847 return strcasecmp(u
->name
, v
->name
);
1850 static int get_machine_properties(sd_bus
*bus
, struct machine_info
*mi
) {
1851 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*container
= NULL
;
1857 r
= sd_bus_open_system_machine(&container
, mi
->name
);
1864 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, mi
);
1871 static bool output_show_machine(const char *name
, char **patterns
) {
1872 return strv_fnmatch_or_empty(patterns
, name
, FNM_NOESCAPE
);
1875 static int get_machine_list(
1877 struct machine_info
**_machine_infos
,
1880 struct machine_info
*machine_infos
= NULL
;
1881 _cleanup_strv_free_
char **m
= NULL
;
1882 _cleanup_free_
char *hn
= NULL
;
1887 hn
= gethostname_malloc();
1891 if (output_show_machine(hn
, patterns
)) {
1892 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1))
1895 machine_infos
[c
].is_host
= true;
1896 machine_infos
[c
].name
= hn
;
1899 get_machine_properties(bus
, &machine_infos
[c
]);
1903 r
= sd_get_machine_names(&m
);
1905 return log_error_errno(r
, "Failed to get machine list: %m");
1907 STRV_FOREACH(i
, m
) {
1908 _cleanup_free_
char *class = NULL
;
1910 if (!output_show_machine(*i
, patterns
))
1913 sd_machine_get_class(*i
, &class);
1914 if (!streq_ptr(class, "container"))
1917 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1)) {
1918 free_machines_list(machine_infos
, c
);
1922 machine_infos
[c
].is_host
= false;
1923 machine_infos
[c
].name
= strdup(*i
);
1924 if (!machine_infos
[c
].name
) {
1925 free_machines_list(machine_infos
, c
);
1929 get_machine_properties(NULL
, &machine_infos
[c
]);
1933 *_machine_infos
= machine_infos
;
1937 static void output_machines_list(struct machine_info
*machine_infos
, unsigned n
) {
1938 struct machine_info
*m
;
1941 namelen
= sizeof("NAME") - 1,
1942 statelen
= sizeof("STATE") - 1,
1943 failedlen
= sizeof("FAILED") - 1,
1944 jobslen
= sizeof("JOBS") - 1;
1946 assert(machine_infos
|| n
== 0);
1948 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
1949 namelen
= MAX(namelen
, strlen(m
->name
) + (m
->is_host
? sizeof(" (host)") - 1 : 0));
1950 statelen
= MAX(statelen
, m
->state
? strlen(m
->state
) : 0);
1951 failedlen
= MAX(failedlen
, DECIMAL_STR_WIDTH(m
->n_failed_units
));
1952 jobslen
= MAX(jobslen
, DECIMAL_STR_WIDTH(m
->n_jobs
));
1954 if (!arg_plain
&& !streq_ptr(m
->state
, "running"))
1958 if (!arg_no_legend
) {
1962 printf("%-*s %-*s %-*s %-*s\n",
1965 failedlen
, "FAILED",
1969 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
1970 const char *on_state
= "", *off_state
= "";
1971 const char *on_failed
= "", *off_failed
= "";
1972 bool circle
= false;
1974 if (streq_ptr(m
->state
, "degraded")) {
1975 on_state
= ansi_highlight_red();
1976 off_state
= ansi_normal();
1978 } else if (!streq_ptr(m
->state
, "running")) {
1979 on_state
= ansi_highlight_yellow();
1980 off_state
= ansi_normal();
1984 if (m
->n_failed_units
> 0) {
1985 on_failed
= ansi_highlight_red();
1986 off_failed
= ansi_normal();
1988 on_failed
= off_failed
= "";
1991 printf("%s%s%s ", on_state
, circle
? special_glyph(BLACK_CIRCLE
) : " ", off_state
);
1994 printf("%-*s (host) %s%-*s%s %s%*" PRIu32
"%s %*" PRIu32
"\n",
1995 (int) (namelen
- (sizeof(" (host)")-1)), strna(m
->name
),
1996 on_state
, statelen
, strna(m
->state
), off_state
,
1997 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
1998 jobslen
, m
->n_jobs
);
2000 printf("%-*s %s%-*s%s %s%*" PRIu32
"%s %*" PRIu32
"\n",
2001 namelen
, strna(m
->name
),
2002 on_state
, statelen
, strna(m
->state
), off_state
,
2003 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
2004 jobslen
, m
->n_jobs
);
2008 printf("\n%u machines listed.\n", n
);
2011 static int list_machines(int argc
, char *argv
[], void *userdata
) {
2012 struct machine_info
*machine_infos
= NULL
;
2016 if (geteuid() != 0) {
2017 log_error("Must be root.");
2021 pager_open(arg_no_pager
, false);
2023 r
= acquire_bus(BUS_MANAGER
, &bus
);
2027 r
= get_machine_list(bus
, &machine_infos
, strv_skip(argv
, 1));
2031 qsort_safe(machine_infos
, r
, sizeof(struct machine_info
), compare_machine_info
);
2032 output_machines_list(machine_infos
, r
);
2033 free_machines_list(machine_infos
, r
);
2038 static int get_default(int argc
, char *argv
[], void *userdata
) {
2039 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2040 _cleanup_free_
char *_path
= NULL
;
2044 if (install_client_side()) {
2045 r
= unit_file_get_default(arg_scope
, arg_root
, &_path
);
2047 return log_error_errno(r
, "Failed to get default target: %m");
2052 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2055 r
= acquire_bus(BUS_MANAGER
, &bus
);
2059 r
= sd_bus_call_method(
2061 "org.freedesktop.systemd1",
2062 "/org/freedesktop/systemd1",
2063 "org.freedesktop.systemd1.Manager",
2069 return log_error_errno(r
, "Failed to get default target: %s", bus_error_message(&error
, r
));
2071 r
= sd_bus_message_read(reply
, "s", &path
);
2073 return bus_log_parse_error(r
);
2077 printf("%s\n", path
);
2082 static int set_default(int argc
, char *argv
[], void *userdata
) {
2083 _cleanup_free_
char *unit
= NULL
;
2084 UnitFileChange
*changes
= NULL
;
2085 unsigned n_changes
= 0;
2091 r
= unit_name_mangle_with_suffix(argv
[1], UNIT_NAME_NOGLOB
, ".target", &unit
);
2093 return log_error_errno(r
, "Failed to mangle unit name: %m");
2095 if (install_client_side()) {
2096 r
= unit_file_set_default(arg_scope
, arg_root
, unit
, true, &changes
, &n_changes
);
2097 unit_file_dump_changes(r
, "set default", changes
, n_changes
, arg_quiet
);
2102 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2103 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2106 polkit_agent_open_if_enabled();
2108 r
= acquire_bus(BUS_MANAGER
, &bus
);
2112 r
= sd_bus_call_method(
2114 "org.freedesktop.systemd1",
2115 "/org/freedesktop/systemd1",
2116 "org.freedesktop.systemd1.Manager",
2122 return log_error_errno(r
, "Failed to set default target: %s", bus_error_message(&error
, r
));
2124 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
2128 /* Try to reload if enabled */
2130 r
= daemon_reload(argc
, argv
, userdata
);
2136 unit_file_changes_free(changes
, n_changes
);
2143 const char *name
, *type
, *state
;
2146 static void output_jobs_list(const struct job_info
* jobs
, unsigned n
, bool skipped
) {
2147 unsigned id_len
, unit_len
, type_len
, state_len
;
2148 const struct job_info
*j
;
2149 const char *on
, *off
;
2150 bool shorten
= false;
2152 assert(n
== 0 || jobs
);
2155 if (!arg_no_legend
) {
2156 on
= ansi_highlight_green();
2157 off
= ansi_normal();
2159 printf("%sNo jobs %s.%s\n", on
, skipped
? "listed" : "running", off
);
2164 pager_open(arg_no_pager
, false);
2166 id_len
= strlen("JOB");
2167 unit_len
= strlen("UNIT");
2168 type_len
= strlen("TYPE");
2169 state_len
= strlen("STATE");
2171 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2172 uint32_t id
= j
->id
;
2173 assert(j
->name
&& j
->type
&& j
->state
);
2175 id_len
= MAX(id_len
, DECIMAL_STR_WIDTH(id
));
2176 unit_len
= MAX(unit_len
, strlen(j
->name
));
2177 type_len
= MAX(type_len
, strlen(j
->type
));
2178 state_len
= MAX(state_len
, strlen(j
->state
));
2181 if (!arg_full
&& id_len
+ 1 + unit_len
+ type_len
+ 1 + state_len
> columns()) {
2182 unit_len
= MAX(33u, columns() - id_len
- type_len
- state_len
- 3);
2187 printf("%*s %-*s %-*s %-*s\n",
2191 state_len
, "STATE");
2193 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2194 _cleanup_free_
char *e
= NULL
;
2196 if (streq(j
->state
, "running")) {
2197 on
= ansi_highlight();
2198 off
= ansi_normal();
2202 e
= shorten
? ellipsize(j
->name
, unit_len
, 33) : NULL
;
2203 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2205 on
, unit_len
, e
? e
: j
->name
, off
,
2207 on
, state_len
, j
->state
, off
);
2210 if (!arg_no_legend
) {
2211 on
= ansi_highlight();
2212 off
= ansi_normal();
2214 printf("\n%s%u jobs listed%s.\n", on
, n
, off
);
2218 static bool output_show_job(struct job_info
*job
, char **patterns
) {
2219 return strv_fnmatch_or_empty(patterns
, job
->name
, FNM_NOESCAPE
);
2222 static int list_jobs(int argc
, char *argv
[], void *userdata
) {
2223 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2224 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2225 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2226 _cleanup_free_
struct job_info
*jobs
= NULL
;
2232 bool skipped
= false;
2234 pager_open(arg_no_pager
, false);
2236 r
= acquire_bus(BUS_MANAGER
, &bus
);
2240 r
= sd_bus_call_method(
2242 "org.freedesktop.systemd1",
2243 "/org/freedesktop/systemd1",
2244 "org.freedesktop.systemd1.Manager",
2250 return log_error_errno(r
, "Failed to list jobs: %s", bus_error_message(&error
, r
));
2252 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2254 return bus_log_parse_error(r
);
2256 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0) {
2257 struct job_info job
= { id
, name
, type
, state
};
2259 if (!output_show_job(&job
, strv_skip(argv
, 1))) {
2264 if (!GREEDY_REALLOC(jobs
, size
, c
+ 1))
2270 return bus_log_parse_error(r
);
2272 r
= sd_bus_message_exit_container(reply
);
2274 return bus_log_parse_error(r
);
2276 output_jobs_list(jobs
, c
, skipped
);
2280 static int cancel_job(int argc
, char *argv
[], void *userdata
) {
2286 return daemon_reload(argc
, argv
, userdata
);
2288 polkit_agent_open_if_enabled();
2290 r
= acquire_bus(BUS_MANAGER
, &bus
);
2294 STRV_FOREACH(name
, strv_skip(argv
, 1)) {
2295 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2299 q
= safe_atou32(*name
, &id
);
2301 return log_error_errno(q
, "Failed to parse job id \"%s\": %m", *name
);
2303 q
= sd_bus_call_method(
2305 "org.freedesktop.systemd1",
2306 "/org/freedesktop/systemd1",
2307 "org.freedesktop.systemd1.Manager",
2313 log_error_errno(q
, "Failed to cancel job %"PRIu32
": %s", id
, bus_error_message(&error
, q
));
2322 static int need_daemon_reload(sd_bus
*bus
, const char *unit
) {
2323 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2327 /* We ignore all errors here, since this is used to show a
2330 /* We don't use unit_dbus_path_from_name() directly since we
2331 * don't want to load the unit if it isn't loaded. */
2333 r
= sd_bus_call_method(
2335 "org.freedesktop.systemd1",
2336 "/org/freedesktop/systemd1",
2337 "org.freedesktop.systemd1.Manager",
2345 r
= sd_bus_message_read(reply
, "o", &path
);
2349 r
= sd_bus_get_property_trivial(
2351 "org.freedesktop.systemd1",
2353 "org.freedesktop.systemd1.Unit",
2363 static void warn_unit_file_changed(const char *name
) {
2366 log_warning("%sWarning:%s %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
2367 ansi_highlight_red(),
2370 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user");
2373 static int unit_file_find_path(LookupPaths
*lp
, const char *unit_name
, char **unit_path
) {
2380 STRV_FOREACH(p
, lp
->search_path
) {
2381 _cleanup_free_
char *path
;
2383 path
= path_join(arg_root
, *p
, unit_name
);
2387 if (access(path
, F_OK
) == 0) {
2397 static int unit_find_paths(
2399 const char *unit_name
,
2401 char **fragment_path
,
2402 char ***dropin_paths
) {
2404 _cleanup_free_
char *path
= NULL
;
2405 _cleanup_strv_free_
char **dropins
= NULL
;
2409 * Finds where the unit is defined on disk. Returns 0 if the unit
2410 * is not found. Returns 1 if it is found, and sets
2411 * - the path to the unit in *path, if it exists on disk,
2412 * - and a strv of existing drop-ins in *dropins,
2413 * if the arg is not NULL and any dropins were found.
2417 assert(fragment_path
);
2420 if (!install_client_side() && !unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
2421 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2422 _cleanup_free_
char *unit
= NULL
;
2424 unit
= unit_dbus_path_from_name(unit_name
);
2428 r
= sd_bus_get_property_string(
2430 "org.freedesktop.systemd1",
2432 "org.freedesktop.systemd1.Unit",
2437 return log_error_errno(r
, "Failed to get FragmentPath: %s", bus_error_message(&error
, r
));
2440 r
= sd_bus_get_property_strv(
2442 "org.freedesktop.systemd1",
2444 "org.freedesktop.systemd1.Unit",
2449 return log_error_errno(r
, "Failed to get DropInPaths: %s", bus_error_message(&error
, r
));
2452 _cleanup_set_free_ Set
*names
;
2454 names
= set_new(NULL
);
2458 r
= set_put(names
, unit_name
);
2460 return log_error_errno(r
, "Failed to add unit name: %m");
2462 r
= unit_file_find_path(lp
, unit_name
, &path
);
2467 _cleanup_free_
char *template = NULL
;
2469 r
= unit_name_template(unit_name
, &template);
2470 if (r
< 0 && r
!= -EINVAL
)
2471 return log_error_errno(r
, "Failed to determine template name: %m");
2473 r
= unit_file_find_path(lp
, template, &path
);
2480 r
= unit_file_find_dropin_paths(lp
->search_path
, NULL
, names
, &dropins
);
2488 if (!isempty(path
)) {
2489 *fragment_path
= path
;
2494 if (dropin_paths
&& !strv_isempty(dropins
)) {
2495 *dropin_paths
= dropins
;
2501 log_error("No files found for %s.", unit_name
);
2506 static int get_state_one_unit(sd_bus
*bus
, const char *name
, UnitActiveState
*active_state
) {
2507 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2508 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2509 _cleanup_free_
char *buf
= NULL
;
2510 UnitActiveState state
;
2515 assert(active_state
);
2517 /* We don't use unit_dbus_path_from_name() directly since we don't want to load the unit unnecessarily, if it
2519 r
= sd_bus_call_method(
2521 "org.freedesktop.systemd1",
2522 "/org/freedesktop/systemd1",
2523 "org.freedesktop.systemd1.Manager",
2529 if (!sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_UNIT
))
2530 return log_error_errno(r
, "Failed to retrieve unit: %s", bus_error_message(&error
, r
));
2532 /* The unit is currently not loaded, hence say it's "inactive", since all units that aren't loaded are
2533 * considered inactive. */
2534 state
= UNIT_INACTIVE
;
2537 r
= sd_bus_message_read(reply
, "o", &path
);
2539 return bus_log_parse_error(r
);
2541 r
= sd_bus_get_property_string(
2543 "org.freedesktop.systemd1",
2545 "org.freedesktop.systemd1.Unit",
2550 return log_error_errno(r
, "Failed to retrieve unit state: %s", bus_error_message(&error
, r
));
2552 state
= unit_active_state_from_string(buf
);
2553 if (state
== _UNIT_ACTIVE_STATE_INVALID
) {
2554 log_error("Invalid unit state '%s' for: %s", buf
, name
);
2559 *active_state
= state
;
2563 static int check_triggering_units(
2567 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2568 _cleanup_free_
char *path
= NULL
, *n
= NULL
, *load_state
= NULL
;
2569 _cleanup_strv_free_
char **triggered_by
= NULL
;
2570 bool print_warning_label
= true;
2571 UnitActiveState active_state
;
2575 r
= unit_name_mangle(name
, UNIT_NAME_NOGLOB
, &n
);
2577 return log_error_errno(r
, "Failed to mangle unit name: %m");
2579 path
= unit_dbus_path_from_name(n
);
2583 r
= sd_bus_get_property_string(
2585 "org.freedesktop.systemd1",
2587 "org.freedesktop.systemd1.Unit",
2592 return log_error_errno(r
, "Failed to get load state of %s: %s", n
, bus_error_message(&error
, r
));
2594 if (streq(load_state
, "masked"))
2597 r
= sd_bus_get_property_strv(
2599 "org.freedesktop.systemd1",
2601 "org.freedesktop.systemd1.Unit",
2606 return log_error_errno(r
, "Failed to get triggered by array of %s: %s", n
, bus_error_message(&error
, r
));
2608 STRV_FOREACH(i
, triggered_by
) {
2609 r
= get_state_one_unit(bus
, *i
, &active_state
);
2613 if (!IN_SET(active_state
, UNIT_ACTIVE
, UNIT_RELOADING
))
2616 if (print_warning_label
) {
2617 log_warning("Warning: Stopping %s, but it can still be activated by:", n
);
2618 print_warning_label
= false;
2621 log_warning(" %s", *i
);
2627 static const struct {
2630 } unit_actions
[] = {
2631 { "start", "StartUnit" },
2632 { "stop", "StopUnit" },
2633 { "condstop", "StopUnit" },
2634 { "reload", "ReloadUnit" },
2635 { "restart", "RestartUnit" },
2636 { "try-restart", "TryRestartUnit" },
2637 { "condrestart", "TryRestartUnit" },
2638 { "reload-or-restart", "ReloadOrRestartUnit" },
2639 { "try-reload-or-restart", "ReloadOrTryRestartUnit" },
2640 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2641 { "condreload", "ReloadOrTryRestartUnit" },
2642 { "force-reload", "ReloadOrTryRestartUnit" }
2645 static const char *verb_to_method(const char *verb
) {
2648 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2649 if (streq_ptr(unit_actions
[i
].verb
, verb
))
2650 return unit_actions
[i
].method
;
2655 static const char *method_to_verb(const char *method
) {
2658 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2659 if (streq_ptr(unit_actions
[i
].method
, method
))
2660 return unit_actions
[i
].verb
;
2665 static int start_unit_one(
2670 sd_bus_error
*error
,
2671 BusWaitForJobs
*w
) {
2673 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2682 log_debug("Calling manager for %s on %s, %s", method
, name
, mode
);
2684 r
= sd_bus_call_method(
2686 "org.freedesktop.systemd1",
2687 "/org/freedesktop/systemd1",
2688 "org.freedesktop.systemd1.Manager",
2696 if (r
== -ENOENT
&& arg_action
!= ACTION_SYSTEMCTL
)
2697 /* There's always a fallback possible for
2698 * legacy actions. */
2699 return -EADDRNOTAVAIL
;
2701 verb
= method_to_verb(method
);
2703 log_error("Failed to %s %s: %s", verb
, name
, bus_error_message(error
, r
));
2705 if (!sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) &&
2706 !sd_bus_error_has_name(error
, BUS_ERROR_UNIT_MASKED
))
2707 log_error("See %s logs and 'systemctl%s status %s' for details.",
2708 arg_scope
== UNIT_FILE_SYSTEM
? "system" : "user",
2709 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user",
2715 r
= sd_bus_message_read(reply
, "o", &path
);
2717 return bus_log_parse_error(r
);
2719 if (need_daemon_reload(bus
, name
) > 0)
2720 warn_unit_file_changed(name
);
2723 log_debug("Adding %s to the set", path
);
2724 r
= bus_wait_for_jobs_add(w
, path
);
2732 static int expand_names(sd_bus
*bus
, char **names
, const char* suffix
, char ***ret
) {
2733 _cleanup_strv_free_
char **mangled
= NULL
, **globs
= NULL
;
2740 STRV_FOREACH(name
, names
) {
2744 r
= unit_name_mangle_with_suffix(*name
, UNIT_NAME_GLOB
, suffix
, &t
);
2746 r
= unit_name_mangle(*name
, UNIT_NAME_GLOB
, &t
);
2748 return log_error_errno(r
, "Failed to mangle name: %m");
2750 if (string_is_glob(t
))
2751 r
= strv_consume(&globs
, t
);
2753 r
= strv_consume(&mangled
, t
);
2758 /* Query the manager only if any of the names are a glob, since
2759 * this is fairly expensive */
2760 if (!strv_isempty(globs
)) {
2761 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2762 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
2763 size_t allocated
, n
;
2765 r
= get_unit_list(bus
, NULL
, globs
, &unit_infos
, 0, &reply
);
2769 n
= strv_length(mangled
);
2772 for (i
= 0; i
< r
; i
++) {
2773 if (!GREEDY_REALLOC(mangled
, allocated
, n
+2))
2776 mangled
[n
] = strdup(unit_infos
[i
].id
);
2780 mangled
[++n
] = NULL
;
2785 mangled
= NULL
; /* do not free */
2790 static const struct {
2794 } action_table
[_ACTION_MAX
] = {
2795 [ACTION_HALT
] = { SPECIAL_HALT_TARGET
, "halt", "replace-irreversibly" },
2796 [ACTION_POWEROFF
] = { SPECIAL_POWEROFF_TARGET
, "poweroff", "replace-irreversibly" },
2797 [ACTION_REBOOT
] = { SPECIAL_REBOOT_TARGET
, "reboot", "replace-irreversibly" },
2798 [ACTION_KEXEC
] = { SPECIAL_KEXEC_TARGET
, "kexec", "replace-irreversibly" },
2799 [ACTION_RUNLEVEL2
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2800 [ACTION_RUNLEVEL3
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2801 [ACTION_RUNLEVEL4
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2802 [ACTION_RUNLEVEL5
] = { SPECIAL_GRAPHICAL_TARGET
, NULL
, "isolate" },
2803 [ACTION_RESCUE
] = { SPECIAL_RESCUE_TARGET
, "rescue", "isolate" },
2804 [ACTION_EMERGENCY
] = { SPECIAL_EMERGENCY_TARGET
, "emergency", "isolate" },
2805 [ACTION_DEFAULT
] = { SPECIAL_DEFAULT_TARGET
, "default", "isolate" },
2806 [ACTION_EXIT
] = { SPECIAL_EXIT_TARGET
, "exit", "replace-irreversibly" },
2807 [ACTION_SUSPEND
] = { SPECIAL_SUSPEND_TARGET
, "suspend", "replace-irreversibly" },
2808 [ACTION_HIBERNATE
] = { SPECIAL_HIBERNATE_TARGET
, "hibernate", "replace-irreversibly" },
2809 [ACTION_HYBRID_SLEEP
] = { SPECIAL_HYBRID_SLEEP_TARGET
, "hybrid-sleep", "replace-irreversibly" },
2812 static enum action
verb_to_action(const char *verb
) {
2815 for (i
= _ACTION_INVALID
; i
< _ACTION_MAX
; i
++)
2816 if (streq_ptr(action_table
[i
].verb
, verb
))
2819 return _ACTION_INVALID
;
2822 static int start_unit(int argc
, char *argv
[], void *userdata
) {
2823 _cleanup_(bus_wait_for_jobs_freep
) BusWaitForJobs
*w
= NULL
;
2824 const char *method
, *mode
, *one_name
, *suffix
= NULL
;
2825 _cleanup_strv_free_
char **names
= NULL
;
2830 ask_password_agent_open_if_enabled();
2831 polkit_agent_open_if_enabled();
2833 r
= acquire_bus(BUS_MANAGER
, &bus
);
2837 if (arg_action
== ACTION_SYSTEMCTL
) {
2840 method
= verb_to_method(argv
[0]);
2841 action
= verb_to_action(argv
[0]);
2843 if (streq(argv
[0], "isolate")) {
2847 mode
= action_table
[action
].mode
?: arg_job_mode
;
2849 one_name
= action_table
[action
].target
;
2851 assert(arg_action
< ELEMENTSOF(action_table
));
2852 assert(action_table
[arg_action
].target
);
2854 method
= "StartUnit";
2856 mode
= action_table
[arg_action
].mode
;
2857 one_name
= action_table
[arg_action
].target
;
2861 names
= strv_new(one_name
, NULL
);
2863 r
= expand_names(bus
, strv_skip(argv
, 1), suffix
, &names
);
2865 return log_error_errno(r
, "Failed to expand names: %m");
2868 if (!arg_no_block
) {
2869 r
= bus_wait_for_jobs_new(bus
, &w
);
2871 return log_error_errno(r
, "Could not watch jobs: %m");
2874 STRV_FOREACH(name
, names
) {
2875 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2878 q
= start_unit_one(bus
, method
, *name
, mode
, &error
, w
);
2879 if (r
>= 0 && q
< 0)
2880 r
= translate_bus_error_to_exit_status(q
, &error
);
2883 if (!arg_no_block
) {
2884 int q
, arg_count
= 0;
2885 const char* extra_args
[4] = {};
2887 if (arg_scope
!= UNIT_FILE_SYSTEM
)
2888 extra_args
[arg_count
++] = "--user";
2890 assert(IN_SET(arg_transport
, BUS_TRANSPORT_LOCAL
, BUS_TRANSPORT_REMOTE
, BUS_TRANSPORT_MACHINE
));
2891 if (arg_transport
== BUS_TRANSPORT_REMOTE
) {
2892 extra_args
[arg_count
++] = "-H";
2893 extra_args
[arg_count
++] = arg_host
;
2894 } else if (arg_transport
== BUS_TRANSPORT_MACHINE
) {
2895 extra_args
[arg_count
++] = "-M";
2896 extra_args
[arg_count
++] = arg_host
;
2899 q
= bus_wait_for_jobs(w
, arg_quiet
, extra_args
);
2903 /* When stopping units, warn if they can still be triggered by
2904 * another active unit (socket, path, timer) */
2905 if (!arg_quiet
&& streq(method
, "StopUnit"))
2906 STRV_FOREACH(name
, names
)
2907 check_triggering_units(bus
, *name
);
2913 static int logind_set_wall_message(void) {
2915 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2917 _cleanup_free_
char *m
= NULL
;
2920 r
= acquire_bus(BUS_FULL
, &bus
);
2924 m
= strv_join(arg_wall
, " ");
2928 r
= sd_bus_call_method(
2930 "org.freedesktop.login1",
2931 "/org/freedesktop/login1",
2932 "org.freedesktop.login1.Manager",
2941 return log_warning_errno(r
, "Failed to set wall message, ignoring: %s", bus_error_message(&error
, r
));
2947 /* Ask systemd-logind, which might grant access to unprivileged users
2948 * through PolicyKit */
2949 static int logind_reboot(enum action a
) {
2951 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2952 const char *method
, *description
;
2956 polkit_agent_open_if_enabled();
2957 (void) logind_set_wall_message();
2959 r
= acquire_bus(BUS_FULL
, &bus
);
2967 description
= "reboot system";
2970 case ACTION_POWEROFF
:
2971 method
= "PowerOff";
2972 description
= "power off system";
2975 case ACTION_SUSPEND
:
2977 description
= "suspend system";
2980 case ACTION_HIBERNATE
:
2981 method
= "Hibernate";
2982 description
= "hibernate system";
2985 case ACTION_HYBRID_SLEEP
:
2986 method
= "HybridSleep";
2987 description
= "put system into hybrid sleep";
2994 r
= sd_bus_call_method(
2996 "org.freedesktop.login1",
2997 "/org/freedesktop/login1",
2998 "org.freedesktop.login1.Manager",
3002 "b", arg_ask_password
);
3004 return log_error_errno(r
, "Failed to %s via logind: %s", description
, bus_error_message(&error
, r
));
3012 static int logind_check_inhibitors(enum action a
) {
3014 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
3015 _cleanup_strv_free_
char **sessions
= NULL
;
3016 const char *what
, *who
, *why
, *mode
;
3023 if (arg_ignore_inhibitors
|| arg_force
> 0)
3035 r
= acquire_bus(BUS_FULL
, &bus
);
3039 r
= sd_bus_call_method(
3041 "org.freedesktop.login1",
3042 "/org/freedesktop/login1",
3043 "org.freedesktop.login1.Manager",
3049 /* If logind is not around, then there are no inhibitors... */
3052 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssuu)");
3054 return bus_log_parse_error(r
);
3056 while ((r
= sd_bus_message_read(reply
, "(ssssuu)", &what
, &who
, &why
, &mode
, &uid
, &pid
)) > 0) {
3057 _cleanup_free_
char *comm
= NULL
, *user
= NULL
;
3058 _cleanup_strv_free_
char **sv
= NULL
;
3060 if (!streq(mode
, "block"))
3063 sv
= strv_split(what
, ":");
3067 if ((pid_t
) pid
< 0)
3068 return log_error_errno(ERANGE
, "Bad PID %"PRIu32
": %m", pid
);
3070 if (!strv_contains(sv
,
3075 ACTION_KEXEC
) ? "shutdown" : "sleep"))
3078 get_process_comm(pid
, &comm
);
3079 user
= uid_to_name(uid
);
3081 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT
" \"%s\", user %s), reason is \"%s\".",
3082 who
, (pid_t
) pid
, strna(comm
), strna(user
), why
);
3087 return bus_log_parse_error(r
);
3089 r
= sd_bus_message_exit_container(reply
);
3091 return bus_log_parse_error(r
);
3093 /* Check for current sessions */
3094 sd_get_sessions(&sessions
);
3095 STRV_FOREACH(s
, sessions
) {
3096 _cleanup_free_
char *type
= NULL
, *tty
= NULL
, *seat
= NULL
, *user
= NULL
, *service
= NULL
, *class = NULL
;
3098 if (sd_session_get_uid(*s
, &uid
) < 0 || uid
== getuid())
3101 if (sd_session_get_class(*s
, &class) < 0 || !streq(class, "user"))
3104 if (sd_session_get_type(*s
, &type
) < 0 || (!streq(type
, "x11") && !streq(type
, "tty")))
3107 sd_session_get_tty(*s
, &tty
);
3108 sd_session_get_seat(*s
, &seat
);
3109 sd_session_get_service(*s
, &service
);
3110 user
= uid_to_name(uid
);
3112 log_warning("User %s is logged in on %s.", strna(user
), isempty(tty
) ? (isempty(seat
) ? strna(service
) : seat
) : tty
);
3119 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
3120 action_table
[a
].verb
);
3128 static int logind_prepare_firmware_setup(void) {
3130 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3134 r
= acquire_bus(BUS_FULL
, &bus
);
3138 r
= sd_bus_call_method(
3140 "org.freedesktop.login1",
3141 "/org/freedesktop/login1",
3142 "org.freedesktop.login1.Manager",
3143 "SetRebootToFirmwareSetup",
3148 return log_error_errno(r
, "Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error
, r
));
3152 log_error("Cannot remotely indicate to EFI to boot into setup mode.");
3157 static int prepare_firmware_setup(void) {
3160 if (!arg_firmware_setup
)
3163 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
3165 r
= efi_set_reboot_to_firmware(true);
3167 log_debug_errno(r
, "Cannot indicate to EFI to boot into setup mode, will retry via logind: %m");
3172 return logind_prepare_firmware_setup();
3175 static int set_exit_code(uint8_t code
) {
3176 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3180 r
= acquire_bus(BUS_MANAGER
, &bus
);
3184 r
= sd_bus_call_method(
3186 "org.freedesktop.systemd1",
3187 "/org/freedesktop/systemd1",
3188 "org.freedesktop.systemd1.Manager",
3194 return log_error_errno(r
, "Failed to set exit code: %s", bus_error_message(&error
, r
));
3199 static int start_special(int argc
, char *argv
[], void *userdata
) {
3205 a
= verb_to_action(argv
[0]);
3207 r
= logind_check_inhibitors(a
);
3211 if (arg_force
>= 2 && geteuid() != 0) {
3212 log_error("Must be root.");
3216 r
= prepare_firmware_setup();
3220 if (a
== ACTION_REBOOT
&& argc
> 1) {
3221 r
= update_reboot_parameter_and_warn(argv
[1]);
3225 } else if (a
== ACTION_EXIT
&& argc
> 1) {
3228 /* If the exit code is not given on the command line,
3229 * don't reset it to zero: just keep it as it might
3230 * have been set previously. */
3232 r
= safe_atou8(argv
[1], &code
);
3234 return log_error_errno(r
, "Invalid exit code.");
3236 r
= set_exit_code(code
);
3241 if (arg_force
>= 2 &&
3248 if (arg_force
>= 1 &&
3255 return daemon_reload(argc
, argv
, userdata
);
3257 /* First try logind, to allow authentication with polkit */
3263 ACTION_HYBRID_SLEEP
)) {
3264 r
= logind_reboot(a
);
3267 if (IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
3268 /* requested operation is not supported or already in progress */
3271 /* On all other errors, try low-level operation */
3274 return start_unit(argc
, argv
, userdata
);
3277 static int check_unit_generic(int code
, const UnitActiveState good_states
[], int nb_states
, char **args
) {
3278 _cleanup_strv_free_
char **names
= NULL
;
3279 UnitActiveState active_state
;
3285 r
= acquire_bus(BUS_MANAGER
, &bus
);
3289 r
= expand_names(bus
, args
, NULL
, &names
);
3291 return log_error_errno(r
, "Failed to expand names: %m");
3293 STRV_FOREACH(name
, names
) {
3294 r
= get_state_one_unit(bus
, *name
, &active_state
);
3299 puts(unit_active_state_to_string(active_state
));
3301 for (i
= 0; i
< nb_states
; ++i
)
3302 if (good_states
[i
] == active_state
)
3306 /* use the given return code for the case that we won't find
3307 * any unit which matches the list */
3308 return found
? 0 : code
;
3311 static int check_unit_active(int argc
, char *argv
[], void *userdata
) {
3312 const UnitActiveState states
[] = { UNIT_ACTIVE
, UNIT_RELOADING
};
3313 /* According to LSB: 3, "program is not running" */
3314 return check_unit_generic(EXIT_PROGRAM_NOT_RUNNING
, states
, ELEMENTSOF(states
), strv_skip(argv
, 1));
3317 static int check_unit_failed(int argc
, char *argv
[], void *userdata
) {
3318 const UnitActiveState states
[] = { UNIT_FAILED
};
3319 return check_unit_generic(EXIT_PROGRAM_DEAD_AND_PID_EXISTS
, states
, ELEMENTSOF(states
), strv_skip(argv
, 1));
3322 static int kill_unit(int argc
, char *argv
[], void *userdata
) {
3323 _cleanup_strv_free_
char **names
= NULL
;
3324 char *kill_who
= NULL
, **name
;
3328 polkit_agent_open_if_enabled();
3330 r
= acquire_bus(BUS_MANAGER
, &bus
);
3335 arg_kill_who
= "all";
3337 /* --fail was specified */
3338 if (streq(arg_job_mode
, "fail"))
3339 kill_who
= strjoina(arg_kill_who
, "-fail");
3341 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
3343 return log_error_errno(r
, "Failed to expand names: %m");
3345 STRV_FOREACH(name
, names
) {
3346 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3348 q
= sd_bus_call_method(
3350 "org.freedesktop.systemd1",
3351 "/org/freedesktop/systemd1",
3352 "org.freedesktop.systemd1.Manager",
3356 "ssi", *names
, kill_who
? kill_who
: arg_kill_who
, arg_signal
);
3358 log_error_errno(q
, "Failed to kill unit %s: %s", *names
, bus_error_message(&error
, q
));
3367 typedef struct ExecStatusInfo
{
3375 usec_t start_timestamp
;
3376 usec_t exit_timestamp
;
3381 LIST_FIELDS(struct ExecStatusInfo
, exec
);
3384 static void exec_status_info_free(ExecStatusInfo
*i
) {
3393 static int exec_status_info_deserialize(sd_bus_message
*m
, ExecStatusInfo
*i
) {
3394 uint64_t start_timestamp
, exit_timestamp
, start_timestamp_monotonic
, exit_timestamp_monotonic
;
3397 int32_t code
, status
;
3403 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_STRUCT
, "sasbttttuii");
3405 return bus_log_parse_error(r
);
3409 r
= sd_bus_message_read(m
, "s", &path
);
3411 return bus_log_parse_error(r
);
3413 i
->path
= strdup(path
);
3417 r
= sd_bus_message_read_strv(m
, &i
->argv
);
3419 return bus_log_parse_error(r
);
3421 r
= sd_bus_message_read(m
,
3424 &start_timestamp
, &start_timestamp_monotonic
,
3425 &exit_timestamp
, &exit_timestamp_monotonic
,
3429 return bus_log_parse_error(r
);
3432 i
->start_timestamp
= (usec_t
) start_timestamp
;
3433 i
->exit_timestamp
= (usec_t
) exit_timestamp
;
3434 i
->pid
= (pid_t
) pid
;
3438 r
= sd_bus_message_exit_container(m
);
3440 return bus_log_parse_error(r
);
3445 typedef struct UnitStatusInfo
{
3447 const char *load_state
;
3448 const char *active_state
;
3449 const char *sub_state
;
3450 const char *unit_file_state
;
3451 const char *unit_file_preset
;
3453 const char *description
;
3454 const char *following
;
3456 char **documentation
;
3458 const char *fragment_path
;
3459 const char *source_path
;
3460 const char *control_group
;
3462 char **dropin_paths
;
3464 const char *load_error
;
3467 usec_t inactive_exit_timestamp
;
3468 usec_t inactive_exit_timestamp_monotonic
;
3469 usec_t active_enter_timestamp
;
3470 usec_t active_exit_timestamp
;
3471 usec_t inactive_enter_timestamp
;
3473 bool need_daemon_reload
;
3479 const char *status_text
;
3480 const char *pid_file
;
3484 usec_t start_timestamp
;
3485 usec_t exit_timestamp
;
3487 int exit_code
, exit_status
;
3489 usec_t condition_timestamp
;
3490 bool condition_result
;
3491 bool failed_condition_trigger
;
3492 bool failed_condition_negate
;
3493 const char *failed_condition
;
3494 const char *failed_condition_parameter
;
3496 usec_t assert_timestamp
;
3498 bool failed_assert_trigger
;
3499 bool failed_assert_negate
;
3500 const char *failed_assert
;
3501 const char *failed_assert_parameter
;
3504 unsigned n_accepted
;
3505 unsigned n_connections
;
3508 /* Pairs of type, path */
3512 const char *sysfs_path
;
3514 /* Mount, Automount */
3521 uint64_t memory_current
;
3522 uint64_t memory_low
;
3523 uint64_t memory_high
;
3524 uint64_t memory_max
;
3525 uint64_t memory_limit
;
3526 uint64_t cpu_usage_nsec
;
3527 uint64_t tasks_current
;
3530 LIST_HEAD(ExecStatusInfo
, exec
);
3533 static void print_status_info(
3539 const char *active_on
, *active_off
, *on
, *off
, *ss
;
3541 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], *s1
;
3542 char since2
[FORMAT_TIMESTAMP_MAX
], *s2
;
3549 /* This shows pretty information about a unit. See
3550 * print_property() for a low-level property printer */
3552 if (streq_ptr(i
->active_state
, "failed")) {
3553 active_on
= ansi_highlight_red();
3554 active_off
= ansi_normal();
3555 } else if (streq_ptr(i
->active_state
, "active") || streq_ptr(i
->active_state
, "reloading")) {
3556 active_on
= ansi_highlight_green();
3557 active_off
= ansi_normal();
3559 active_on
= active_off
= "";
3561 printf("%s%s%s %s", active_on
, special_glyph(BLACK_CIRCLE
), active_off
, strna(i
->id
));
3563 if (i
->description
&& !streq_ptr(i
->id
, i
->description
))
3564 printf(" - %s", i
->description
);
3569 printf(" Follow: unit currently follows state of %s\n", i
->following
);
3571 if (streq_ptr(i
->load_state
, "error")) {
3572 on
= ansi_highlight_red();
3573 off
= ansi_normal();
3577 path
= i
->source_path
? i
->source_path
: i
->fragment_path
;
3579 if (i
->load_error
!= 0)
3580 printf(" Loaded: %s%s%s (Reason: %s)\n",
3581 on
, strna(i
->load_state
), off
, i
->load_error
);
3582 else if (path
&& !isempty(i
->unit_file_state
) && !isempty(i
->unit_file_preset
))
3583 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
3584 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
, i
->unit_file_preset
);
3585 else if (path
&& !isempty(i
->unit_file_state
))
3586 printf(" Loaded: %s%s%s (%s; %s)\n",
3587 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
);
3589 printf(" Loaded: %s%s%s (%s)\n",
3590 on
, strna(i
->load_state
), off
, path
);
3592 printf(" Loaded: %s%s%s\n",
3593 on
, strna(i
->load_state
), off
);
3596 printf("Transient: yes\n");
3598 if (!strv_isempty(i
->dropin_paths
)) {
3599 _cleanup_free_
char *dir
= NULL
;
3603 STRV_FOREACH(dropin
, i
->dropin_paths
) {
3604 if (! dir
|| last
) {
3605 printf(dir
? " " : " Drop-In: ");
3609 dir
= dirname_malloc(*dropin
);
3615 printf("%s\n %s", dir
,
3616 special_glyph(TREE_RIGHT
));
3619 last
= ! (*(dropin
+ 1) && startswith(*(dropin
+ 1), dir
));
3621 printf("%s%s", basename(*dropin
), last
? "\n" : ", ");
3625 ss
= streq_ptr(i
->active_state
, i
->sub_state
) ? NULL
: i
->sub_state
;
3627 printf(" Active: %s%s (%s)%s",
3628 active_on
, strna(i
->active_state
), ss
, active_off
);
3630 printf(" Active: %s%s%s",
3631 active_on
, strna(i
->active_state
), active_off
);
3633 if (!isempty(i
->result
) && !streq(i
->result
, "success"))
3634 printf(" (Result: %s)", i
->result
);
3636 timestamp
= (streq_ptr(i
->active_state
, "active") ||
3637 streq_ptr(i
->active_state
, "reloading")) ? i
->active_enter_timestamp
:
3638 (streq_ptr(i
->active_state
, "inactive") ||
3639 streq_ptr(i
->active_state
, "failed")) ? i
->inactive_enter_timestamp
:
3640 streq_ptr(i
->active_state
, "activating") ? i
->inactive_exit_timestamp
:
3641 i
->active_exit_timestamp
;
3643 s1
= format_timestamp_relative(since1
, sizeof(since1
), timestamp
);
3644 s2
= format_timestamp(since2
, sizeof(since2
), timestamp
);
3647 printf(" since %s; %s\n", s2
, s1
);
3649 printf(" since %s\n", s2
);
3653 if (!i
->condition_result
&& i
->condition_timestamp
> 0) {
3654 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->condition_timestamp
);
3655 s2
= format_timestamp(since2
, sizeof(since2
), i
->condition_timestamp
);
3657 printf("Condition: start %scondition failed%s at %s%s%s\n",
3658 ansi_highlight_yellow(), ansi_normal(),
3659 s2
, s1
? "; " : "", strempty(s1
));
3660 if (i
->failed_condition_trigger
)
3661 printf(" none of the trigger conditions were met\n");
3662 else if (i
->failed_condition
)
3663 printf(" %s=%s%s was not met\n",
3664 i
->failed_condition
,
3665 i
->failed_condition_negate
? "!" : "",
3666 i
->failed_condition_parameter
);
3669 if (!i
->assert_result
&& i
->assert_timestamp
> 0) {
3670 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->assert_timestamp
);
3671 s2
= format_timestamp(since2
, sizeof(since2
), i
->assert_timestamp
);
3673 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
3674 ansi_highlight_red(), ansi_normal(),
3675 s2
, s1
? "; " : "", strempty(s1
));
3676 if (i
->failed_assert_trigger
)
3677 printf(" none of the trigger assertions were met\n");
3678 else if (i
->failed_assert
)
3679 printf(" %s=%s%s was not met\n",
3681 i
->failed_assert_negate
? "!" : "",
3682 i
->failed_assert_parameter
);
3686 printf(" Device: %s\n", i
->sysfs_path
);
3688 printf(" Where: %s\n", i
->where
);
3690 printf(" What: %s\n", i
->what
);
3692 STRV_FOREACH(t
, i
->documentation
)
3693 printf(" %*s %s\n", 9, t
== i
->documentation
? "Docs:" : "", *t
);
3695 STRV_FOREACH_PAIR(t
, t2
, i
->listen
)
3696 printf(" %*s %s (%s)\n", 9, t
== i
->listen
? "Listen:" : "", *t2
, *t
);
3699 printf(" Accepted: %u; Connected: %u\n", i
->n_accepted
, i
->n_connections
);
3701 LIST_FOREACH(exec
, p
, i
->exec
) {
3702 _cleanup_free_
char *argv
= NULL
;
3705 /* Only show exited processes here */
3709 argv
= strv_join(p
->argv
, " ");
3710 printf(" Process: "PID_FMT
" %s=%s ", p
->pid
, p
->name
, strna(argv
));
3712 good
= is_clean_exit_lsb(p
->code
, p
->status
, NULL
);
3714 on
= ansi_highlight_red();
3715 off
= ansi_normal();
3719 printf("%s(code=%s, ", on
, sigchld_code_to_string(p
->code
));
3721 if (p
->code
== CLD_EXITED
) {
3724 printf("status=%i", p
->status
);
3726 c
= exit_status_to_string(p
->status
, EXIT_STATUS_SYSTEMD
);
3731 printf("signal=%s", signal_to_string(p
->status
));
3733 printf(")%s\n", off
);
3735 if (i
->main_pid
== p
->pid
&&
3736 i
->start_timestamp
== p
->start_timestamp
&&
3737 i
->exit_timestamp
== p
->start_timestamp
)
3738 /* Let's not show this twice */
3741 if (p
->pid
== i
->control_pid
)
3745 if (i
->main_pid
> 0 || i
->control_pid
> 0) {
3746 if (i
->main_pid
> 0) {
3747 printf(" Main PID: "PID_FMT
, i
->main_pid
);
3750 _cleanup_free_
char *comm
= NULL
;
3751 get_process_comm(i
->main_pid
, &comm
);
3753 printf(" (%s)", comm
);
3754 } else if (i
->exit_code
> 0) {
3755 printf(" (code=%s, ", sigchld_code_to_string(i
->exit_code
));
3757 if (i
->exit_code
== CLD_EXITED
) {
3760 printf("status=%i", i
->exit_status
);
3762 c
= exit_status_to_string(i
->exit_status
, EXIT_STATUS_SYSTEMD
);
3767 printf("signal=%s", signal_to_string(i
->exit_status
));
3771 if (i
->control_pid
> 0)
3775 if (i
->control_pid
> 0) {
3776 _cleanup_free_
char *c
= NULL
;
3778 printf(" %8s: "PID_FMT
, i
->main_pid
? "" : " Control", i
->control_pid
);
3780 get_process_comm(i
->control_pid
, &c
);
3789 printf(" Status: \"%s\"\n", i
->status_text
);
3790 if (i
->status_errno
> 0)
3791 printf(" Error: %i (%s)\n", i
->status_errno
, strerror(i
->status_errno
));
3793 if (i
->tasks_current
!= (uint64_t) -1) {
3794 printf(" Tasks: %" PRIu64
, i
->tasks_current
);
3796 if (i
->tasks_max
!= (uint64_t) -1)
3797 printf(" (limit: %" PRIi64
")\n", i
->tasks_max
);
3802 if (i
->memory_current
!= (uint64_t) -1) {
3803 char buf
[FORMAT_BYTES_MAX
];
3805 printf(" Memory: %s", format_bytes(buf
, sizeof(buf
), i
->memory_current
));
3807 if (i
->memory_low
> 0 || i
->memory_high
!= CGROUP_LIMIT_MAX
|| i
->memory_max
!= CGROUP_LIMIT_MAX
||
3808 i
->memory_limit
!= CGROUP_LIMIT_MAX
) {
3809 const char *prefix
= "";
3812 if (i
->memory_low
> 0) {
3813 printf("%slow: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_low
));
3816 if (i
->memory_high
!= CGROUP_LIMIT_MAX
) {
3817 printf("%shigh: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_high
));
3820 if (i
->memory_max
!= CGROUP_LIMIT_MAX
) {
3821 printf("%smax: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_max
));
3824 if (i
->memory_limit
!= CGROUP_LIMIT_MAX
) {
3825 printf("%slimit: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_limit
));
3833 if (i
->cpu_usage_nsec
!= (uint64_t) -1) {
3834 char buf
[FORMAT_TIMESPAN_MAX
];
3835 printf(" CPU: %s\n", format_timespan(buf
, sizeof(buf
), i
->cpu_usage_nsec
/ NSEC_PER_USEC
, USEC_PER_MSEC
));
3838 if (i
->control_group
)
3839 printf(" CGroup: %s\n", i
->control_group
);
3842 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3843 static const char prefix
[] = " ";
3847 if (c
> sizeof(prefix
) - 1)
3848 c
-= sizeof(prefix
) - 1;
3852 r
= unit_show_processes(bus
, i
->id
, i
->control_group
, prefix
, c
, get_output_flags(), &error
);
3857 /* Fallback for older systemd versions where the GetUnitProcesses() call is not yet available */
3859 if (i
->main_pid
> 0)
3860 extra
[k
++] = i
->main_pid
;
3862 if (i
->control_pid
> 0)
3863 extra
[k
++] = i
->control_pid
;
3865 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, prefix
, c
, extra
, k
, get_output_flags());
3867 log_warning_errno(r
, "Failed to dump process list, ignoring: %s", bus_error_message(&error
, r
));
3870 if (i
->id
&& arg_transport
== BUS_TRANSPORT_LOCAL
)
3871 show_journal_by_unit(
3876 i
->inactive_exit_timestamp_monotonic
,
3879 get_output_flags() | OUTPUT_BEGIN_NEWLINE
,
3880 SD_JOURNAL_LOCAL_ONLY
,
3881 arg_scope
== UNIT_FILE_SYSTEM
,
3884 if (i
->need_daemon_reload
)
3885 warn_unit_file_changed(i
->id
);
3888 static void show_unit_help(UnitStatusInfo
*i
) {
3893 if (!i
->documentation
) {
3894 log_info("Documentation for %s not known.", i
->id
);
3898 STRV_FOREACH(p
, i
->documentation
)
3899 if (startswith(*p
, "man:"))
3900 show_man_page(*p
+ 4, false);
3902 log_info("Can't show: %s", *p
);
3905 static int status_property(const char *name
, sd_bus_message
*m
, UnitStatusInfo
*i
, const char *contents
) {
3912 switch (contents
[0]) {
3914 case SD_BUS_TYPE_STRING
: {
3917 r
= sd_bus_message_read(m
, "s", &s
);
3919 return bus_log_parse_error(r
);
3922 if (streq(name
, "Id"))
3924 else if (streq(name
, "LoadState"))
3926 else if (streq(name
, "ActiveState"))
3927 i
->active_state
= s
;
3928 else if (streq(name
, "SubState"))
3930 else if (streq(name
, "Description"))
3932 else if (streq(name
, "FragmentPath"))
3933 i
->fragment_path
= s
;
3934 else if (streq(name
, "SourcePath"))
3937 else if (streq(name
, "DefaultControlGroup")) {
3939 e
= startswith(s
, SYSTEMD_CGROUP_CONTROLLER
":");
3941 i
->control_group
= e
;
3944 else if (streq(name
, "ControlGroup"))
3945 i
->control_group
= s
;
3946 else if (streq(name
, "StatusText"))
3948 else if (streq(name
, "PIDFile"))
3950 else if (streq(name
, "SysFSPath"))
3952 else if (streq(name
, "Where"))
3954 else if (streq(name
, "What"))
3956 else if (streq(name
, "Following"))
3958 else if (streq(name
, "UnitFileState"))
3959 i
->unit_file_state
= s
;
3960 else if (streq(name
, "UnitFilePreset"))
3961 i
->unit_file_preset
= s
;
3962 else if (streq(name
, "Result"))
3969 case SD_BUS_TYPE_BOOLEAN
: {
3972 r
= sd_bus_message_read(m
, "b", &b
);
3974 return bus_log_parse_error(r
);
3976 if (streq(name
, "Accept"))
3978 else if (streq(name
, "NeedDaemonReload"))
3979 i
->need_daemon_reload
= b
;
3980 else if (streq(name
, "ConditionResult"))
3981 i
->condition_result
= b
;
3982 else if (streq(name
, "AssertResult"))
3983 i
->assert_result
= b
;
3984 else if (streq(name
, "Transient"))
3990 case SD_BUS_TYPE_UINT32
: {
3993 r
= sd_bus_message_read(m
, "u", &u
);
3995 return bus_log_parse_error(r
);
3997 if (streq(name
, "MainPID")) {
3999 i
->main_pid
= (pid_t
) u
;
4002 } else if (streq(name
, "ControlPID"))
4003 i
->control_pid
= (pid_t
) u
;
4004 else if (streq(name
, "ExecMainPID")) {
4006 i
->main_pid
= (pid_t
) u
;
4007 } else if (streq(name
, "NAccepted"))
4009 else if (streq(name
, "NConnections"))
4010 i
->n_connections
= u
;
4015 case SD_BUS_TYPE_INT32
: {
4018 r
= sd_bus_message_read(m
, "i", &j
);
4020 return bus_log_parse_error(r
);
4022 if (streq(name
, "ExecMainCode"))
4023 i
->exit_code
= (int) j
;
4024 else if (streq(name
, "ExecMainStatus"))
4025 i
->exit_status
= (int) j
;
4026 else if (streq(name
, "StatusErrno"))
4027 i
->status_errno
= (int) j
;
4032 case SD_BUS_TYPE_UINT64
: {
4035 r
= sd_bus_message_read(m
, "t", &u
);
4037 return bus_log_parse_error(r
);
4039 if (streq(name
, "ExecMainStartTimestamp"))
4040 i
->start_timestamp
= (usec_t
) u
;
4041 else if (streq(name
, "ExecMainExitTimestamp"))
4042 i
->exit_timestamp
= (usec_t
) u
;
4043 else if (streq(name
, "ActiveEnterTimestamp"))
4044 i
->active_enter_timestamp
= (usec_t
) u
;
4045 else if (streq(name
, "InactiveEnterTimestamp"))
4046 i
->inactive_enter_timestamp
= (usec_t
) u
;
4047 else if (streq(name
, "InactiveExitTimestamp"))
4048 i
->inactive_exit_timestamp
= (usec_t
) u
;
4049 else if (streq(name
, "InactiveExitTimestampMonotonic"))
4050 i
->inactive_exit_timestamp_monotonic
= (usec_t
) u
;
4051 else if (streq(name
, "ActiveExitTimestamp"))
4052 i
->active_exit_timestamp
= (usec_t
) u
;
4053 else if (streq(name
, "ConditionTimestamp"))
4054 i
->condition_timestamp
= (usec_t
) u
;
4055 else if (streq(name
, "AssertTimestamp"))
4056 i
->assert_timestamp
= (usec_t
) u
;
4057 else if (streq(name
, "MemoryCurrent"))
4058 i
->memory_current
= u
;
4059 else if (streq(name
, "MemoryLow"))
4061 else if (streq(name
, "MemoryHigh"))
4063 else if (streq(name
, "MemoryMax"))
4065 else if (streq(name
, "MemoryLimit"))
4066 i
->memory_limit
= u
;
4067 else if (streq(name
, "TasksCurrent"))
4068 i
->tasks_current
= u
;
4069 else if (streq(name
, "TasksMax"))
4071 else if (streq(name
, "CPUUsageNSec"))
4072 i
->cpu_usage_nsec
= u
;
4077 case SD_BUS_TYPE_ARRAY
:
4079 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
4080 _cleanup_free_ ExecStatusInfo
*info
= NULL
;
4082 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4084 return bus_log_parse_error(r
);
4086 info
= new0(ExecStatusInfo
, 1);
4090 while ((r
= exec_status_info_deserialize(m
, info
)) > 0) {
4092 info
->name
= strdup(name
);
4096 LIST_PREPEND(exec
, i
->exec
, info
);
4098 info
= new0(ExecStatusInfo
, 1);
4104 return bus_log_parse_error(r
);
4106 r
= sd_bus_message_exit_container(m
);
4108 return bus_log_parse_error(r
);
4112 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
4113 const char *type
, *path
;
4115 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4117 return bus_log_parse_error(r
);
4119 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0) {
4121 r
= strv_extend(&i
->listen
, type
);
4125 r
= strv_extend(&i
->listen
, path
);
4130 return bus_log_parse_error(r
);
4132 r
= sd_bus_message_exit_container(m
);
4134 return bus_log_parse_error(r
);
4138 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "DropInPaths")) {
4140 r
= sd_bus_message_read_strv(m
, &i
->dropin_paths
);
4142 return bus_log_parse_error(r
);
4144 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Documentation")) {
4146 r
= sd_bus_message_read_strv(m
, &i
->documentation
);
4148 return bus_log_parse_error(r
);
4150 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Conditions")) {
4151 const char *cond
, *param
;
4152 int trigger
, negate
;
4155 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
4157 return bus_log_parse_error(r
);
4159 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
4160 log_debug("%s %d %d %s %d", cond
, trigger
, negate
, param
, state
);
4161 if (state
< 0 && (!trigger
|| !i
->failed_condition
)) {
4162 i
->failed_condition
= cond
;
4163 i
->failed_condition_trigger
= trigger
;
4164 i
->failed_condition_negate
= negate
;
4165 i
->failed_condition_parameter
= param
;
4169 return bus_log_parse_error(r
);
4171 r
= sd_bus_message_exit_container(m
);
4173 return bus_log_parse_error(r
);
4175 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Asserts")) {
4176 const char *cond
, *param
;
4177 int trigger
, negate
;
4180 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
4182 return bus_log_parse_error(r
);
4184 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
4185 log_debug("%s %d %d %s %d", cond
, trigger
, negate
, param
, state
);
4186 if (state
< 0 && (!trigger
|| !i
->failed_assert
)) {
4187 i
->failed_assert
= cond
;
4188 i
->failed_assert_trigger
= trigger
;
4189 i
->failed_assert_negate
= negate
;
4190 i
->failed_assert_parameter
= param
;
4194 return bus_log_parse_error(r
);
4196 r
= sd_bus_message_exit_container(m
);
4198 return bus_log_parse_error(r
);
4205 case SD_BUS_TYPE_STRUCT_BEGIN
:
4207 if (streq(name
, "LoadError")) {
4208 const char *n
, *message
;
4210 r
= sd_bus_message_read(m
, "(ss)", &n
, &message
);
4212 return bus_log_parse_error(r
);
4214 if (!isempty(message
))
4215 i
->load_error
= message
;
4228 r
= sd_bus_message_skip(m
, contents
);
4230 return bus_log_parse_error(r
);
4235 #define print_prop(name, fmt, ...) \
4238 printf(fmt "\n", __VA_ARGS__); \
4240 printf("%s=" fmt "\n", name, __VA_ARGS__); \
4243 static int print_property(const char *name
, sd_bus_message
*m
, const char *contents
) {
4249 /* This is a low-level property printer, see
4250 * print_status_info() for the nicer output */
4252 if (arg_properties
&& !strv_find(arg_properties
, name
)) {
4253 /* skip what we didn't read */
4254 r
= sd_bus_message_skip(m
, contents
);
4258 switch (contents
[0]) {
4260 case SD_BUS_TYPE_STRUCT_BEGIN
:
4262 if (contents
[1] == SD_BUS_TYPE_UINT32
&& streq(name
, "Job")) {
4265 r
= sd_bus_message_read(m
, "(uo)", &u
, NULL
);
4267 return bus_log_parse_error(r
);
4270 print_prop(name
, "%"PRIu32
, u
);
4272 print_prop(name
, "%s", "");
4276 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Unit")) {
4279 r
= sd_bus_message_read(m
, "(so)", &s
, NULL
);
4281 return bus_log_parse_error(r
);
4283 if (arg_all
|| !isempty(s
))
4284 print_prop(name
, "%s", s
);
4288 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "LoadError")) {
4289 const char *a
= NULL
, *b
= NULL
;
4291 r
= sd_bus_message_read(m
, "(ss)", &a
, &b
);
4293 return bus_log_parse_error(r
);
4295 if (arg_all
|| !isempty(a
) || !isempty(b
))
4296 print_prop(name
, "%s \"%s\"", strempty(a
), strempty(b
));
4299 } else if (streq_ptr(name
, "SystemCallFilter")) {
4300 _cleanup_strv_free_
char **l
= NULL
;
4303 r
= sd_bus_message_enter_container(m
, 'r', "bas");
4305 return bus_log_parse_error(r
);
4307 r
= sd_bus_message_read(m
, "b", &whitelist
);
4309 return bus_log_parse_error(r
);
4311 r
= sd_bus_message_read_strv(m
, &l
);
4313 return bus_log_parse_error(r
);
4315 r
= sd_bus_message_exit_container(m
);
4317 return bus_log_parse_error(r
);
4319 if (arg_all
|| whitelist
|| !strv_isempty(l
)) {
4324 fputs(name
, stdout
);
4331 STRV_FOREACH(i
, l
) {
4339 fputc('\n', stdout
);
4347 case SD_BUS_TYPE_ARRAY
:
4349 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "EnvironmentFiles")) {
4353 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sb)");
4355 return bus_log_parse_error(r
);
4357 while ((r
= sd_bus_message_read(m
, "(sb)", &path
, &ignore
)) > 0)
4358 print_prop("EnvironmentFile", "%s (ignore_errors=%s)\n", path
, yes_no(ignore
));
4361 return bus_log_parse_error(r
);
4363 r
= sd_bus_message_exit_container(m
);
4365 return bus_log_parse_error(r
);
4369 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Paths")) {
4370 const char *type
, *path
;
4372 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4374 return bus_log_parse_error(r
);
4376 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4377 print_prop(type
, "%s", path
);
4379 return bus_log_parse_error(r
);
4381 r
= sd_bus_message_exit_container(m
);
4383 return bus_log_parse_error(r
);
4387 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
4388 const char *type
, *path
;
4390 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4392 return bus_log_parse_error(r
);
4394 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4398 printf("Listen%s=%s\n", type
, path
);
4400 return bus_log_parse_error(r
);
4402 r
= sd_bus_message_exit_container(m
);
4404 return bus_log_parse_error(r
);
4408 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Timers")) {
4410 uint64_t value
, next_elapse
;
4412 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(stt)");
4414 return bus_log_parse_error(r
);
4416 while ((r
= sd_bus_message_read(m
, "(stt)", &base
, &value
, &next_elapse
)) > 0) {
4417 char timespan1
[FORMAT_TIMESPAN_MAX
], timespan2
[FORMAT_TIMESPAN_MAX
];
4419 print_prop(base
, "{ value=%s ; next_elapse=%s }",
4420 format_timespan(timespan1
, sizeof(timespan1
), value
, 0),
4421 format_timespan(timespan2
, sizeof(timespan2
), next_elapse
, 0));
4424 return bus_log_parse_error(r
);
4426 r
= sd_bus_message_exit_container(m
);
4428 return bus_log_parse_error(r
);
4432 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
4433 ExecStatusInfo info
= {};
4435 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4437 return bus_log_parse_error(r
);
4439 while ((r
= exec_status_info_deserialize(m
, &info
)) > 0) {
4440 char timestamp1
[FORMAT_TIMESTAMP_MAX
], timestamp2
[FORMAT_TIMESTAMP_MAX
];
4441 _cleanup_free_
char *tt
;
4443 tt
= strv_join(info
.argv
, " ");
4446 "{ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT
" ; code=%s ; status=%i%s%s }",
4449 yes_no(info
.ignore
),
4450 strna(format_timestamp(timestamp1
, sizeof(timestamp1
), info
.start_timestamp
)),
4451 strna(format_timestamp(timestamp2
, sizeof(timestamp2
), info
.exit_timestamp
)),
4453 sigchld_code_to_string(info
.code
),
4455 info
.code
== CLD_EXITED
? "" : "/",
4456 strempty(info
.code
== CLD_EXITED
? NULL
: signal_to_string(info
.status
)));
4459 strv_free(info
.argv
);
4463 r
= sd_bus_message_exit_container(m
);
4465 return bus_log_parse_error(r
);
4469 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "DeviceAllow")) {
4470 const char *path
, *rwm
;
4472 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4474 return bus_log_parse_error(r
);
4476 while ((r
= sd_bus_message_read(m
, "(ss)", &path
, &rwm
)) > 0)
4477 print_prop(name
, "%s %s", strna(path
), strna(rwm
));
4479 return bus_log_parse_error(r
);
4481 r
= sd_bus_message_exit_container(m
);
4483 return bus_log_parse_error(r
);
4487 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& (streq(name
, "IODeviceWeight") || streq(name
, "BlockIODeviceWeight"))) {
4491 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4493 return bus_log_parse_error(r
);
4495 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &weight
)) > 0)
4496 print_prop(name
, "%s %"PRIu64
, strna(path
), weight
);
4498 return bus_log_parse_error(r
);
4500 r
= sd_bus_message_exit_container(m
);
4502 return bus_log_parse_error(r
);
4506 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& (cgroup_io_limit_type_from_string(name
) >= 0 ||
4507 streq(name
, "BlockIOReadBandwidth") || streq(name
, "BlockIOWriteBandwidth"))) {
4511 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4513 return bus_log_parse_error(r
);
4515 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &bandwidth
)) > 0)
4516 print_prop(name
, "%s %"PRIu64
, strna(path
), bandwidth
);
4518 return bus_log_parse_error(r
);
4520 r
= sd_bus_message_exit_container(m
);
4522 return bus_log_parse_error(r
);
4530 r
= bus_print_property(name
, m
, arg_value
, arg_all
);
4532 return bus_log_parse_error(r
);
4535 r
= sd_bus_message_skip(m
, contents
);
4537 return bus_log_parse_error(r
);
4540 printf("%s=[unprintable]\n", name
);
4546 static int show_one(
4550 bool show_properties
,
4554 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
4555 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
4556 UnitStatusInfo info
= {
4557 .memory_current
= (uint64_t) -1,
4558 .memory_high
= CGROUP_LIMIT_MAX
,
4559 .memory_max
= CGROUP_LIMIT_MAX
,
4560 .memory_limit
= (uint64_t) -1,
4561 .cpu_usage_nsec
= (uint64_t) -1,
4562 .tasks_current
= (uint64_t) -1,
4563 .tasks_max
= (uint64_t) -1,
4565 struct property_info
{
4566 const char *load_state
, *active_state
;
4567 } property_info
= {};
4568 static const struct bus_properties_map property_map
[] = {
4569 { "LoadState", "s", NULL
, offsetof(struct property_info
, load_state
) },
4570 { "ActiveState", "s", NULL
, offsetof(struct property_info
, active_state
) },
4579 log_debug("Showing one %s", path
);
4581 r
= sd_bus_call_method(
4583 "org.freedesktop.systemd1",
4585 "org.freedesktop.DBus.Properties",
4591 return log_error_errno(r
, "Failed to get properties: %s", bus_error_message(&error
, r
));
4593 r
= bus_message_map_all_properties(reply
, property_map
, &property_info
);
4595 return log_error_errno(r
, "Failed to map properties: %s", bus_error_message(&error
, r
));
4597 if (streq_ptr(property_info
.load_state
, "not-found") && streq_ptr(property_info
.active_state
, "inactive"))
4598 return EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN
;
4600 r
= sd_bus_message_rewind(reply
, true);
4602 return log_error_errno(r
, "Failed to rewind: %s", bus_error_message(&error
, r
));
4604 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
4606 return bus_log_parse_error(r
);
4613 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
4614 const char *name
, *contents
;
4616 r
= sd_bus_message_read(reply
, "s", &name
);
4618 return bus_log_parse_error(r
);
4620 r
= sd_bus_message_peek_type(reply
, NULL
, &contents
);
4622 return bus_log_parse_error(r
);
4624 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, contents
);
4626 return bus_log_parse_error(r
);
4628 if (show_properties
)
4629 r
= print_property(name
, reply
, contents
);
4631 r
= status_property(name
, reply
, &info
, contents
);
4635 r
= sd_bus_message_exit_container(reply
);
4637 return bus_log_parse_error(r
);
4639 r
= sd_bus_message_exit_container(reply
);
4641 return bus_log_parse_error(r
);
4644 return bus_log_parse_error(r
);
4646 r
= sd_bus_message_exit_container(reply
);
4648 return bus_log_parse_error(r
);
4652 if (!show_properties
) {
4653 if (streq(verb
, "help"))
4654 show_unit_help(&info
);
4656 print_status_info(bus
, &info
, ellipsized
);
4659 strv_free(info
.documentation
);
4660 strv_free(info
.dropin_paths
);
4661 strv_free(info
.listen
);
4663 if (!streq_ptr(info
.active_state
, "active") &&
4664 !streq_ptr(info
.active_state
, "reloading") &&
4665 streq(verb
, "status")) {
4666 /* According to LSB: "program not running" */
4667 /* 0: program is running or service is OK
4668 * 1: program is dead and /run PID file exists
4669 * 2: program is dead and /run/lock lock file exists
4670 * 3: program is not running
4671 * 4: program or service status is unknown
4673 if (info
.pid_file
&& access(info
.pid_file
, F_OK
) == 0)
4674 r
= EXIT_PROGRAM_DEAD_AND_PID_EXISTS
;
4675 else if (streq_ptr(info
.load_state
, "not-found") && streq_ptr(info
.active_state
, "inactive"))
4676 r
= EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN
;
4678 r
= EXIT_PROGRAM_NOT_RUNNING
;
4681 while ((p
= info
.exec
)) {
4682 LIST_REMOVE(exec
, info
.exec
, p
);
4683 exec_status_info_free(p
);
4689 static int get_unit_dbus_path_by_pid(
4694 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
4695 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
4699 r
= sd_bus_call_method(
4701 "org.freedesktop.systemd1",
4702 "/org/freedesktop/systemd1",
4703 "org.freedesktop.systemd1.Manager",
4709 return log_error_errno(r
, "Failed to get unit for PID %"PRIu32
": %s", pid
, bus_error_message(&error
, r
));
4711 r
= sd_bus_message_read(reply
, "o", &u
);
4713 return bus_log_parse_error(r
);
4723 static int show_all(
4726 bool show_properties
,
4730 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
4731 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
4736 r
= get_unit_list(bus
, NULL
, NULL
, &unit_infos
, 0, &reply
);
4740 pager_open(arg_no_pager
, false);
4744 qsort_safe(unit_infos
, c
, sizeof(UnitInfo
), compare_unit_info
);
4746 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
4747 _cleanup_free_
char *p
= NULL
;
4749 p
= unit_dbus_path_from_name(u
->id
);
4753 r
= show_one(verb
, bus
, p
, show_properties
, new_line
, ellipsized
);
4756 else if (r
> 0 && ret
== 0)
4763 static int show_system_status(sd_bus
*bus
) {
4764 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], since2
[FORMAT_TIMESTAMP_MAX
];
4765 _cleanup_free_
char *hn
= NULL
;
4766 _cleanup_(machine_info_clear
) struct machine_info mi
= {};
4767 const char *on
, *off
;
4770 hn
= gethostname_malloc();
4774 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, &mi
);
4776 return log_error_errno(r
, "Failed to read server status: %m");
4778 if (streq_ptr(mi
.state
, "degraded")) {
4779 on
= ansi_highlight_red();
4780 off
= ansi_normal();
4781 } else if (!streq_ptr(mi
.state
, "running")) {
4782 on
= ansi_highlight_yellow();
4783 off
= ansi_normal();
4787 printf("%s%s%s %s\n", on
, special_glyph(BLACK_CIRCLE
), off
, arg_host
? arg_host
: hn
);
4789 printf(" State: %s%s%s\n",
4790 on
, strna(mi
.state
), off
);
4792 printf(" Jobs: %" PRIu32
" queued\n", mi
.n_jobs
);
4793 printf(" Failed: %" PRIu32
" units\n", mi
.n_failed_units
);
4795 printf(" Since: %s; %s\n",
4796 format_timestamp(since2
, sizeof(since2
), mi
.timestamp
),
4797 format_timestamp_relative(since1
, sizeof(since1
), mi
.timestamp
));
4799 printf(" CGroup: %s\n", mi
.control_group
?: "/");
4800 if (IN_SET(arg_transport
,
4801 BUS_TRANSPORT_LOCAL
,
4802 BUS_TRANSPORT_MACHINE
)) {
4803 static const char prefix
[] = " ";
4807 if (c
> sizeof(prefix
) - 1)
4808 c
-= sizeof(prefix
) - 1;
4812 show_cgroup(SYSTEMD_CGROUP_CONTROLLER
, strempty(mi
.control_group
), prefix
, c
, get_output_flags());
4818 static int show(int argc
, char *argv
[], void *userdata
) {
4819 bool show_properties
, show_status
, show_help
, new_line
= false;
4820 bool ellipsized
= false;
4826 show_properties
= streq(argv
[0], "show");
4827 show_status
= streq(argv
[0], "status");
4828 show_help
= streq(argv
[0], "help");
4830 if (show_help
&& argc
<= 1) {
4831 log_error("This command expects one or more unit names. Did you mean --help?");
4835 pager_open(arg_no_pager
, false);
4838 /* Increase max number of open files to 16K if we can, we
4839 * might needs this when browsing journal files, which might
4840 * be split up into many files. */
4841 setrlimit_closest(RLIMIT_NOFILE
, &RLIMIT_MAKE_CONST(16384));
4843 r
= acquire_bus(BUS_MANAGER
, &bus
);
4847 /* If no argument is specified inspect the manager itself */
4848 if (show_properties
&& argc
<= 1)
4849 return show_one(argv
[0], bus
, "/org/freedesktop/systemd1", show_properties
, &new_line
, &ellipsized
);
4851 if (show_status
&& argc
<= 1) {
4853 pager_open(arg_no_pager
, false);
4854 show_system_status(bus
);
4858 ret
= show_all(argv
[0], bus
, false, &new_line
, &ellipsized
);
4860 _cleanup_free_
char **patterns
= NULL
;
4863 STRV_FOREACH(name
, strv_skip(argv
, 1)) {
4864 _cleanup_free_
char *unit
= NULL
;
4867 if (safe_atou32(*name
, &id
) < 0) {
4868 if (strv_push(&patterns
, *name
) < 0)
4872 } else if (show_properties
) {
4873 /* Interpret as job id */
4874 if (asprintf(&unit
, "/org/freedesktop/systemd1/job/%u", id
) < 0)
4878 /* Interpret as PID */
4879 r
= get_unit_dbus_path_by_pid(bus
, id
, &unit
);
4886 r
= show_one(argv
[0], bus
, unit
, show_properties
, &new_line
, &ellipsized
);
4889 else if (r
> 0 && ret
== 0)
4893 if (!strv_isempty(patterns
)) {
4894 _cleanup_strv_free_
char **names
= NULL
;
4896 r
= expand_names(bus
, patterns
, NULL
, &names
);
4898 return log_error_errno(r
, "Failed to expand names: %m");
4900 STRV_FOREACH(name
, names
) {
4901 _cleanup_free_
char *unit
;
4903 unit
= unit_dbus_path_from_name(*name
);
4907 r
= show_one(argv
[0], bus
, unit
, show_properties
, &new_line
, &ellipsized
);
4910 else if (r
> 0 && ret
== 0)
4913 if (r
== EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN
)
4914 log_error("Can't display property %s. Unit %s does not exist.", *patterns
, *name
);
4919 if (ellipsized
&& !arg_quiet
)
4920 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4925 static int cat_file(const char *filename
, bool newline
) {
4926 _cleanup_close_
int fd
;
4928 fd
= open(filename
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
4932 printf("%s%s# %s%s\n",
4933 newline
? "\n" : "",
4934 ansi_highlight_blue(),
4939 return copy_bytes(fd
, STDOUT_FILENO
, (uint64_t) -1, false);
4942 static int cat(int argc
, char *argv
[], void *userdata
) {
4943 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
4944 _cleanup_strv_free_
char **names
= NULL
;
4950 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
4951 log_error("Cannot remotely cat units.");
4955 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
4957 return log_error_errno(r
, "Failed to determine unit paths: %m");
4959 r
= acquire_bus(BUS_MANAGER
, &bus
);
4963 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
4965 return log_error_errno(r
, "Failed to expand names: %m");
4967 pager_open(arg_no_pager
, false);
4969 STRV_FOREACH(name
, names
) {
4970 _cleanup_free_
char *fragment_path
= NULL
;
4971 _cleanup_strv_free_
char **dropin_paths
= NULL
;
4974 r
= unit_find_paths(bus
, *name
, &lp
, &fragment_path
, &dropin_paths
);
4985 if (fragment_path
) {
4986 r
= cat_file(fragment_path
, false);
4988 return log_warning_errno(r
, "Failed to cat %s: %m", fragment_path
);
4991 STRV_FOREACH(path
, dropin_paths
) {
4992 r
= cat_file(*path
, path
== dropin_paths
);
4994 return log_warning_errno(r
, "Failed to cat %s: %m", *path
);
5001 static int set_property(int argc
, char *argv
[], void *userdata
) {
5002 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5003 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5004 _cleanup_free_
char *n
= NULL
;
5009 polkit_agent_open_if_enabled();
5011 r
= acquire_bus(BUS_MANAGER
, &bus
);
5015 r
= sd_bus_message_new_method_call(
5018 "org.freedesktop.systemd1",
5019 "/org/freedesktop/systemd1",
5020 "org.freedesktop.systemd1.Manager",
5021 "SetUnitProperties");
5023 return bus_log_create_error(r
);
5025 r
= unit_name_mangle(argv
[1], UNIT_NAME_NOGLOB
, &n
);
5027 return log_error_errno(r
, "Failed to mangle unit name: %m");
5029 r
= sd_bus_message_append(m
, "sb", n
, arg_runtime
);
5031 return bus_log_create_error(r
);
5033 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, "(sv)");
5035 return bus_log_create_error(r
);
5037 STRV_FOREACH(i
, strv_skip(argv
, 2)) {
5038 r
= bus_append_unit_property_assignment(m
, *i
);
5043 r
= sd_bus_message_close_container(m
);
5045 return bus_log_create_error(r
);
5047 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5049 return log_error_errno(r
, "Failed to set unit properties on %s: %s", n
, bus_error_message(&error
, r
));
5054 static int daemon_reload(int argc
, char *argv
[], void *userdata
) {
5055 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5060 polkit_agent_open_if_enabled();
5062 r
= acquire_bus(BUS_MANAGER
, &bus
);
5066 if (arg_action
== ACTION_RELOAD
)
5068 else if (arg_action
== ACTION_REEXEC
)
5069 method
= "Reexecute";
5071 assert(arg_action
== ACTION_SYSTEMCTL
);
5074 streq(argv
[0], "clear-jobs") ||
5075 streq(argv
[0], "cancel") ? "ClearJobs" :
5076 streq(argv
[0], "daemon-reexec") ? "Reexecute" :
5077 streq(argv
[0], "reset-failed") ? "ResetFailed" :
5078 streq(argv
[0], "halt") ? "Halt" :
5079 streq(argv
[0], "poweroff") ? "PowerOff" :
5080 streq(argv
[0], "reboot") ? "Reboot" :
5081 streq(argv
[0], "kexec") ? "KExec" :
5082 streq(argv
[0], "exit") ? "Exit" :
5083 /* "daemon-reload" */ "Reload";
5086 r
= sd_bus_call_method(
5088 "org.freedesktop.systemd1",
5089 "/org/freedesktop/systemd1",
5090 "org.freedesktop.systemd1.Manager",
5095 if (r
== -ENOENT
&& arg_action
!= ACTION_SYSTEMCTL
)
5096 /* There's always a fallback possible for
5097 * legacy actions. */
5099 else if ((r
== -ETIMEDOUT
|| r
== -ECONNRESET
) && streq(method
, "Reexecute"))
5100 /* On reexecution, we expect a disconnect, not a
5104 return log_error_errno(r
, "Failed to reload daemon: %s", bus_error_message(&error
, r
));
5106 return r
< 0 ? r
: 0;
5109 static int reset_failed(int argc
, char *argv
[], void *userdata
) {
5110 _cleanup_strv_free_
char **names
= NULL
;
5116 return daemon_reload(argc
, argv
, userdata
);
5118 polkit_agent_open_if_enabled();
5120 r
= acquire_bus(BUS_MANAGER
, &bus
);
5124 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
5126 return log_error_errno(r
, "Failed to expand names: %m");
5128 STRV_FOREACH(name
, names
) {
5129 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5131 q
= sd_bus_call_method(
5133 "org.freedesktop.systemd1",
5134 "/org/freedesktop/systemd1",
5135 "org.freedesktop.systemd1.Manager",
5141 log_error_errno(q
, "Failed to reset failed state of unit %s: %s", *name
, bus_error_message(&error
, q
));
5150 static int show_environment(int argc
, char *argv
[], void *userdata
) {
5151 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5152 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5157 pager_open(arg_no_pager
, false);
5159 r
= acquire_bus(BUS_MANAGER
, &bus
);
5163 r
= sd_bus_get_property(
5165 "org.freedesktop.systemd1",
5166 "/org/freedesktop/systemd1",
5167 "org.freedesktop.systemd1.Manager",
5173 return log_error_errno(r
, "Failed to get environment: %s", bus_error_message(&error
, r
));
5175 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
5177 return bus_log_parse_error(r
);
5179 while ((r
= sd_bus_message_read_basic(reply
, SD_BUS_TYPE_STRING
, &text
)) > 0)
5182 return bus_log_parse_error(r
);
5184 r
= sd_bus_message_exit_container(reply
);
5186 return bus_log_parse_error(r
);
5191 static int switch_root(int argc
, char *argv
[], void *userdata
) {
5192 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5193 _cleanup_free_
char *cmdline_init
= NULL
;
5194 const char *root
, *init
;
5198 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
5199 log_error("Cannot switch root remotely.");
5203 if (argc
< 2 || argc
> 3) {
5204 log_error("Wrong number of arguments.");
5213 r
= parse_env_file("/proc/cmdline", WHITESPACE
,
5214 "init", &cmdline_init
,
5217 log_debug_errno(r
, "Failed to parse /proc/cmdline: %m");
5219 init
= cmdline_init
;
5222 init
= empty_to_null(init
);
5224 const char *root_systemd_path
= NULL
, *root_init_path
= NULL
;
5226 root_systemd_path
= strjoina(root
, "/" SYSTEMD_BINARY_PATH
);
5227 root_init_path
= strjoina(root
, "/", init
);
5229 /* If the passed init is actually the same as the
5230 * systemd binary, then let's suppress it. */
5231 if (files_same(root_init_path
, root_systemd_path
) > 0)
5235 r
= acquire_bus(BUS_MANAGER
, &bus
);
5239 log_debug("Switching root - root: %s; init: %s", root
, strna(init
));
5241 r
= sd_bus_call_method(
5243 "org.freedesktop.systemd1",
5244 "/org/freedesktop/systemd1",
5245 "org.freedesktop.systemd1.Manager",
5251 return log_error_errno(r
, "Failed to switch root: %s", bus_error_message(&error
, r
));
5256 static int set_environment(int argc
, char *argv
[], void *userdata
) {
5257 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5258 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5266 polkit_agent_open_if_enabled();
5268 r
= acquire_bus(BUS_MANAGER
, &bus
);
5272 method
= streq(argv
[0], "set-environment")
5274 : "UnsetEnvironment";
5276 r
= sd_bus_message_new_method_call(
5279 "org.freedesktop.systemd1",
5280 "/org/freedesktop/systemd1",
5281 "org.freedesktop.systemd1.Manager",
5284 return bus_log_create_error(r
);
5286 r
= sd_bus_message_append_strv(m
, strv_skip(argv
, 1));
5288 return bus_log_create_error(r
);
5290 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5292 return log_error_errno(r
, "Failed to set environment: %s", bus_error_message(&error
, r
));
5297 static int import_environment(int argc
, char *argv
[], void *userdata
) {
5298 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5299 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5303 polkit_agent_open_if_enabled();
5305 r
= acquire_bus(BUS_MANAGER
, &bus
);
5309 r
= sd_bus_message_new_method_call(
5312 "org.freedesktop.systemd1",
5313 "/org/freedesktop/systemd1",
5314 "org.freedesktop.systemd1.Manager",
5317 return bus_log_create_error(r
);
5320 r
= sd_bus_message_append_strv(m
, environ
);
5324 r
= sd_bus_message_open_container(m
, 'a', "s");
5326 return bus_log_create_error(r
);
5328 STRV_FOREACH(a
, strv_skip(argv
, 1)) {
5330 if (!env_name_is_valid(*a
)) {
5331 log_error("Not a valid environment variable name: %s", *a
);
5335 STRV_FOREACH(b
, environ
) {
5338 eq
= startswith(*b
, *a
);
5339 if (eq
&& *eq
== '=') {
5341 r
= sd_bus_message_append(m
, "s", *b
);
5343 return bus_log_create_error(r
);
5350 r
= sd_bus_message_close_container(m
);
5353 return bus_log_create_error(r
);
5355 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5357 return log_error_errno(r
, "Failed to import environment: %s", bus_error_message(&error
, r
));
5362 static int enable_sysv_units(const char *verb
, char **args
) {
5365 #if defined(HAVE_SYSV_COMPAT)
5366 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
5369 /* Processes all SysV units, and reshuffles the array so that afterwards only the native units remain */
5371 if (arg_scope
!= UNIT_FILE_SYSTEM
)
5374 if (getenv_bool("SYSTEMCTL_SKIP_SYSV") > 0)
5377 if (!STR_IN_SET(verb
,
5383 r
= lookup_paths_init(&paths
, arg_scope
, LOOKUP_PATHS_EXCLUDE_GENERATED
, arg_root
);
5390 const char *argv
[] = {
5391 ROOTLIBEXECDIR
"/systemd-sysv-install",
5398 _cleanup_free_
char *p
= NULL
, *q
= NULL
, *l
= NULL
;
5399 bool found_native
= false, found_sysv
;
5408 if (!endswith(name
, ".service"))
5411 if (path_is_absolute(name
))
5414 j
= unit_file_exists(arg_scope
, &paths
, name
);
5415 if (j
< 0 && !IN_SET(j
, -ELOOP
, -ERFKILL
, -EADDRNOTAVAIL
))
5416 return log_error_errno(j
, "Failed to lookup unit file state: %m");
5417 found_native
= j
!= 0;
5419 /* If we have both a native unit and a SysV script, enable/disable them both (below); for is-enabled,
5420 * prefer the native unit */
5421 if (found_native
&& streq(verb
, "is-enabled"))
5424 p
= path_join(arg_root
, SYSTEM_SYSVINIT_PATH
, name
);
5428 p
[strlen(p
) - strlen(".service")] = 0;
5429 found_sysv
= access(p
, F_OK
) >= 0;
5434 log_info("Synchronizing state of %s with SysV service script with %s.", name
, argv
[0]);
5436 log_info("%s is not a native service, redirecting to systemd-sysv-install.", name
);
5438 if (!isempty(arg_root
))
5439 argv
[c
++] = q
= strappend("--root=", arg_root
);
5442 argv
[c
++] = basename(p
);
5445 l
= strv_join((char**)argv
, " ");
5449 log_info("Executing: %s", l
);
5453 return log_error_errno(errno
, "Failed to fork: %m");
5454 else if (pid
== 0) {
5457 (void) reset_all_signal_handlers();
5458 (void) reset_signal_mask();
5460 execv(argv
[0], (char**) argv
);
5461 log_error_errno(errno
, "Failed to execute %s: %m", argv
[0]);
5462 _exit(EXIT_FAILURE
);
5465 j
= wait_for_terminate(pid
, &status
);
5467 log_error_errno(j
, "Failed to wait for child: %m");
5471 if (status
.si_code
== CLD_EXITED
) {
5472 if (streq(verb
, "is-enabled")) {
5473 if (status
.si_status
== 0) {
5482 } else if (status
.si_status
!= 0)
5483 return -EBADE
; /* We don't warn here, under the assumption the script already showed an explanation */
5485 log_error("Unexpected waitid() result.");
5492 /* Remove this entry, so that we don't try enabling it as native unit */
5495 assert(args
[f
] == name
);
5496 strv_remove(args
, name
);
5503 static int mangle_names(char **original_names
, char ***mangled_names
) {
5504 char **i
, **l
, **name
;
5507 l
= i
= new(char*, strv_length(original_names
) + 1);
5511 STRV_FOREACH(name
, original_names
) {
5513 /* When enabling units qualified path names are OK,
5514 * too, hence allow them explicitly. */
5516 if (is_path(*name
)) {
5523 r
= unit_name_mangle(*name
, UNIT_NAME_NOGLOB
, i
);
5526 return log_error_errno(r
, "Failed to mangle unit name: %m");
5539 static int enable_unit(int argc
, char *argv
[], void *userdata
) {
5540 _cleanup_strv_free_
char **names
= NULL
;
5541 const char *verb
= argv
[0];
5542 UnitFileChange
*changes
= NULL
;
5543 unsigned n_changes
= 0;
5544 int carries_install_info
= -1;
5545 bool ignore_carries_install_info
= arg_quiet
;
5551 r
= mangle_names(strv_skip(argv
, 1), &names
);
5555 r
= enable_sysv_units(verb
, names
);
5559 /* If the operation was fully executed by the SysV compat, let's finish early */
5560 if (strv_isempty(names
)) {
5561 if (arg_no_reload
|| install_client_side())
5563 return daemon_reload(argc
, argv
, userdata
);
5566 if (install_client_side()) {
5567 if (streq(verb
, "enable")) {
5568 r
= unit_file_enable(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5569 carries_install_info
= r
;
5570 } else if (streq(verb
, "disable"))
5571 r
= unit_file_disable(arg_scope
, arg_runtime
, arg_root
, names
, &changes
, &n_changes
);
5572 else if (streq(verb
, "reenable")) {
5573 r
= unit_file_reenable(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5574 carries_install_info
= r
;
5575 } else if (streq(verb
, "link"))
5576 r
= unit_file_link(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5577 else if (streq(verb
, "preset")) {
5578 r
= unit_file_preset(arg_scope
, arg_runtime
, arg_root
, names
, arg_preset_mode
, arg_force
, &changes
, &n_changes
);
5579 } else if (streq(verb
, "mask"))
5580 r
= unit_file_mask(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5581 else if (streq(verb
, "unmask"))
5582 r
= unit_file_unmask(arg_scope
, arg_runtime
, arg_root
, names
, &changes
, &n_changes
);
5583 else if (streq(verb
, "revert"))
5584 r
= unit_file_revert(arg_scope
, arg_root
, names
, &changes
, &n_changes
);
5586 assert_not_reached("Unknown verb");
5588 unit_file_dump_changes(r
, verb
, changes
, n_changes
, arg_quiet
);
5593 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
, *m
= NULL
;
5594 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5595 bool expect_carries_install_info
= false;
5596 bool send_runtime
= true, send_force
= true, send_preset_mode
= false;
5600 polkit_agent_open_if_enabled();
5602 r
= acquire_bus(BUS_MANAGER
, &bus
);
5606 if (streq(verb
, "enable")) {
5607 method
= "EnableUnitFiles";
5608 expect_carries_install_info
= true;
5609 } else if (streq(verb
, "disable")) {
5610 method
= "DisableUnitFiles";
5612 } else if (streq(verb
, "reenable")) {
5613 method
= "ReenableUnitFiles";
5614 expect_carries_install_info
= true;
5615 } else if (streq(verb
, "link"))
5616 method
= "LinkUnitFiles";
5617 else if (streq(verb
, "preset")) {
5619 if (arg_preset_mode
!= UNIT_FILE_PRESET_FULL
) {
5620 method
= "PresetUnitFilesWithMode";
5621 send_preset_mode
= true;
5623 method
= "PresetUnitFiles";
5625 expect_carries_install_info
= true;
5626 ignore_carries_install_info
= true;
5627 } else if (streq(verb
, "mask"))
5628 method
= "MaskUnitFiles";
5629 else if (streq(verb
, "unmask")) {
5630 method
= "UnmaskUnitFiles";
5632 } else if (streq(verb
, "revert")) {
5633 method
= "RevertUnitFiles";
5634 send_runtime
= send_force
= false;
5636 assert_not_reached("Unknown verb");
5638 r
= sd_bus_message_new_method_call(
5641 "org.freedesktop.systemd1",
5642 "/org/freedesktop/systemd1",
5643 "org.freedesktop.systemd1.Manager",
5646 return bus_log_create_error(r
);
5648 r
= sd_bus_message_append_strv(m
, names
);
5650 return bus_log_create_error(r
);
5652 if (send_preset_mode
) {
5653 r
= sd_bus_message_append(m
, "s", unit_file_preset_mode_to_string(arg_preset_mode
));
5655 return bus_log_create_error(r
);
5659 r
= sd_bus_message_append(m
, "b", arg_runtime
);
5661 return bus_log_create_error(r
);
5665 r
= sd_bus_message_append(m
, "b", arg_force
);
5667 return bus_log_create_error(r
);
5670 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
5672 return log_error_errno(r
, "Failed to %s unit: %s", verb
, bus_error_message(&error
, r
));
5674 if (expect_carries_install_info
) {
5675 r
= sd_bus_message_read(reply
, "b", &carries_install_info
);
5677 return bus_log_parse_error(r
);
5680 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
5684 /* Try to reload if enabled */
5686 r
= daemon_reload(argc
, argv
, userdata
);
5691 if (carries_install_info
== 0 && !ignore_carries_install_info
)
5692 log_warning("The unit files have no installation config (WantedBy, RequiredBy, Also, Alias\n"
5693 "settings in the [Install] section, and DefaultInstance for template units).\n"
5694 "This means they are not meant to be enabled using systemctl.\n"
5695 "Possible reasons for having this kind of units are:\n"
5696 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5697 " .wants/ or .requires/ directory.\n"
5698 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5699 " a requirement dependency on it.\n"
5700 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5701 " D-Bus, udev, scripted systemctl call, ...).\n"
5702 "4) In case of template units, the unit is meant to be enabled with some\n"
5703 " instance name specified.");
5705 if (arg_now
&& n_changes
> 0 && STR_IN_SET(argv
[0], "enable", "disable", "mask")) {
5706 char *new_args
[n_changes
+ 2];
5710 r
= acquire_bus(BUS_MANAGER
, &bus
);
5714 new_args
[0] = (char*) (streq(argv
[0], "enable") ? "start" : "stop");
5715 for (i
= 0; i
< n_changes
; i
++)
5716 new_args
[i
+ 1] = basename(changes
[i
].path
);
5717 new_args
[i
+ 1] = NULL
;
5719 r
= start_unit(strv_length(new_args
), new_args
, userdata
);
5723 unit_file_changes_free(changes
, n_changes
);
5728 static int add_dependency(int argc
, char *argv
[], void *userdata
) {
5729 _cleanup_strv_free_
char **names
= NULL
;
5730 _cleanup_free_
char *target
= NULL
;
5731 const char *verb
= argv
[0];
5732 UnitFileChange
*changes
= NULL
;
5733 unsigned n_changes
= 0;
5740 r
= unit_name_mangle_with_suffix(argv
[1], UNIT_NAME_NOGLOB
, ".target", &target
);
5742 return log_error_errno(r
, "Failed to mangle unit name: %m");
5744 r
= mangle_names(strv_skip(argv
, 2), &names
);
5748 if (streq(verb
, "add-wants"))
5750 else if (streq(verb
, "add-requires"))
5751 dep
= UNIT_REQUIRES
;
5753 assert_not_reached("Unknown verb");
5755 if (install_client_side()) {
5756 r
= unit_file_add_dependency(arg_scope
, arg_runtime
, arg_root
, names
, target
, dep
, arg_force
, &changes
, &n_changes
);
5757 unit_file_dump_changes(r
, "add dependency on", changes
, n_changes
, arg_quiet
);
5762 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
, *m
= NULL
;
5763 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5766 polkit_agent_open_if_enabled();
5768 r
= acquire_bus(BUS_MANAGER
, &bus
);
5772 r
= sd_bus_message_new_method_call(
5775 "org.freedesktop.systemd1",
5776 "/org/freedesktop/systemd1",
5777 "org.freedesktop.systemd1.Manager",
5778 "AddDependencyUnitFiles");
5780 return bus_log_create_error(r
);
5782 r
= sd_bus_message_append_strv(m
, names
);
5784 return bus_log_create_error(r
);
5786 r
= sd_bus_message_append(m
, "ssbb", target
, unit_dependency_to_string(dep
), arg_runtime
, arg_force
);
5788 return bus_log_create_error(r
);
5790 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
5792 return log_error_errno(r
, "Failed to add dependency: %s", bus_error_message(&error
, r
));
5794 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
5798 if (arg_no_reload
) {
5803 r
= daemon_reload(argc
, argv
, userdata
);
5807 unit_file_changes_free(changes
, n_changes
);
5812 static int preset_all(int argc
, char *argv
[], void *userdata
) {
5813 UnitFileChange
*changes
= NULL
;
5814 unsigned n_changes
= 0;
5817 if (install_client_side()) {
5818 r
= unit_file_preset_all(arg_scope
, arg_runtime
, arg_root
, arg_preset_mode
, arg_force
, &changes
, &n_changes
);
5819 unit_file_dump_changes(r
, "preset", changes
, n_changes
, arg_quiet
);
5824 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5825 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5828 polkit_agent_open_if_enabled();
5830 r
= acquire_bus(BUS_MANAGER
, &bus
);
5834 r
= sd_bus_call_method(
5836 "org.freedesktop.systemd1",
5837 "/org/freedesktop/systemd1",
5838 "org.freedesktop.systemd1.Manager",
5839 "PresetAllUnitFiles",
5843 unit_file_preset_mode_to_string(arg_preset_mode
),
5847 return log_error_errno(r
, "Failed to preset all units: %s", bus_error_message(&error
, r
));
5849 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
5853 if (arg_no_reload
) {
5858 r
= daemon_reload(argc
, argv
, userdata
);
5862 unit_file_changes_free(changes
, n_changes
);
5867 static int unit_is_enabled(int argc
, char *argv
[], void *userdata
) {
5869 _cleanup_strv_free_
char **names
= NULL
;
5874 r
= mangle_names(strv_skip(argv
, 1), &names
);
5878 r
= enable_sysv_units(argv
[0], names
);
5884 if (install_client_side()) {
5886 STRV_FOREACH(name
, names
) {
5887 UnitFileState state
;
5889 r
= unit_file_get_state(arg_scope
, arg_root
, *name
, &state
);
5891 return log_error_errno(state
, "Failed to get unit file state for %s: %m", *name
);
5895 UNIT_FILE_ENABLED_RUNTIME
,
5898 UNIT_FILE_GENERATED
))
5902 puts(unit_file_state_to_string(state
));
5907 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5910 r
= acquire_bus(BUS_MANAGER
, &bus
);
5914 STRV_FOREACH(name
, names
) {
5915 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5918 r
= sd_bus_call_method(
5920 "org.freedesktop.systemd1",
5921 "/org/freedesktop/systemd1",
5922 "org.freedesktop.systemd1.Manager",
5928 return log_error_errno(r
, "Failed to get unit file state for %s: %s", *name
, bus_error_message(&error
, r
));
5930 r
= sd_bus_message_read(reply
, "s", &s
);
5932 return bus_log_parse_error(r
);
5934 if (STR_IN_SET(s
, "enabled", "enabled-runtime", "static", "indirect", "generated"))
5942 return enabled
? EXIT_SUCCESS
: EXIT_FAILURE
;
5945 static int is_system_running(int argc
, char *argv
[], void *userdata
) {
5946 _cleanup_free_
char *state
= NULL
;
5950 if (running_in_chroot() > 0 || (arg_transport
== BUS_TRANSPORT_LOCAL
&& !sd_booted())) {
5953 return EXIT_FAILURE
;
5956 r
= acquire_bus(BUS_MANAGER
, &bus
);
5960 r
= sd_bus_get_property_string(
5962 "org.freedesktop.systemd1",
5963 "/org/freedesktop/systemd1",
5964 "org.freedesktop.systemd1.Manager",
5977 return streq(state
, "running") ? EXIT_SUCCESS
: EXIT_FAILURE
;
5980 static int create_edit_temp_file(const char *new_path
, const char *original_path
, char **ret_tmp_fn
) {
5981 _cleanup_free_
char *t
= NULL
;
5985 assert(original_path
);
5988 r
= tempfn_random(new_path
, NULL
, &t
);
5990 return log_error_errno(r
, "Failed to determine temporary filename for \"%s\": %m", new_path
);
5992 r
= mkdir_parents(new_path
, 0755);
5994 return log_error_errno(r
, "Failed to create directories for \"%s\": %m", new_path
);
5996 r
= copy_file(original_path
, t
, 0, 0644, 0);
6001 return log_error_errno(r
, "Failed to create temporary file \"%s\": %m", t
);
6004 return log_error_errno(r
, "Failed to copy \"%s\" to \"%s\": %m", original_path
, t
);
6012 static int get_file_to_edit(
6013 const LookupPaths
*paths
,
6017 _cleanup_free_
char *path
= NULL
, *run
= NULL
;
6022 path
= strjoin(paths
->persistent_config
, "/", name
, NULL
);
6027 run
= strjoin(paths
->runtime_config
, name
, NULL
);
6033 if (access(path
, F_OK
) >= 0) {
6034 log_error("Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.", run
, path
);
6048 static int unit_file_create_dropin(
6049 const LookupPaths
*paths
,
6050 const char *unit_name
,
6051 char **ret_new_path
,
6052 char **ret_tmp_path
) {
6054 char *tmp_new_path
, *tmp_tmp_path
, *ending
;
6058 assert(ret_new_path
);
6059 assert(ret_tmp_path
);
6061 ending
= strjoina(unit_name
, ".d/override.conf");
6062 r
= get_file_to_edit(paths
, ending
, &tmp_new_path
);
6066 r
= create_edit_temp_file(tmp_new_path
, tmp_new_path
, &tmp_tmp_path
);
6072 *ret_new_path
= tmp_new_path
;
6073 *ret_tmp_path
= tmp_tmp_path
;
6078 static int unit_file_create_copy(
6079 const LookupPaths
*paths
,
6080 const char *unit_name
,
6081 const char *fragment_path
,
6082 char **ret_new_path
,
6083 char **ret_tmp_path
) {
6085 char *tmp_new_path
, *tmp_tmp_path
;
6088 assert(fragment_path
);
6090 assert(ret_new_path
);
6091 assert(ret_tmp_path
);
6093 r
= get_file_to_edit(paths
, unit_name
, &tmp_new_path
);
6097 if (!path_equal(fragment_path
, tmp_new_path
) && access(tmp_new_path
, F_OK
) == 0) {
6100 r
= ask_char(&response
, "yn", "\"%s\" already exists. Overwrite with \"%s\"? [(y)es, (n)o] ", tmp_new_path
, fragment_path
);
6105 if (response
!= 'y') {
6106 log_warning("%s ignored", unit_name
);
6112 r
= create_edit_temp_file(tmp_new_path
, fragment_path
, &tmp_tmp_path
);
6114 log_error_errno(r
, "Failed to create temporary file for \"%s\": %m", tmp_new_path
);
6119 *ret_new_path
= tmp_new_path
;
6120 *ret_tmp_path
= tmp_tmp_path
;
6125 static int run_editor(char **paths
) {
6133 return log_error_errno(errno
, "Failed to fork: %m");
6137 char *editor
, **editor_args
= NULL
;
6138 char **tmp_path
, **original_path
, *p
;
6139 unsigned n_editor_args
= 0, i
= 1;
6142 (void) reset_all_signal_handlers();
6143 (void) reset_signal_mask();
6145 argc
= strv_length(paths
)/2 + 1;
6147 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
6148 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
6149 * we try to execute well known editors
6151 editor
= getenv("SYSTEMD_EDITOR");
6153 editor
= getenv("EDITOR");
6155 editor
= getenv("VISUAL");
6157 if (!isempty(editor
)) {
6158 editor_args
= strv_split(editor
, WHITESPACE
);
6161 _exit(EXIT_FAILURE
);
6163 n_editor_args
= strv_length(editor_args
);
6164 argc
+= n_editor_args
- 1;
6166 args
= newa(const char*, argc
+ 1);
6168 if (n_editor_args
> 0) {
6169 args
[0] = editor_args
[0];
6170 for (; i
< n_editor_args
; i
++)
6171 args
[i
] = editor_args
[i
];
6174 STRV_FOREACH_PAIR(original_path
, tmp_path
, paths
) {
6175 args
[i
] = *tmp_path
;
6180 if (n_editor_args
> 0)
6181 execvp(args
[0], (char* const*) args
);
6183 FOREACH_STRING(p
, "editor", "nano", "vim", "vi") {
6185 execvp(p
, (char* const*) args
);
6186 /* We do not fail if the editor doesn't exist
6187 * because we want to try each one of them before
6190 if (errno
!= ENOENT
) {
6191 log_error_errno(errno
, "Failed to execute %s: %m", editor
);
6192 _exit(EXIT_FAILURE
);
6196 log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR, $EDITOR or $VISUAL.");
6197 _exit(EXIT_FAILURE
);
6200 r
= wait_for_terminate_and_warn("editor", pid
, true);
6202 return log_error_errno(r
, "Failed to wait for child: %m");
6207 static int find_paths_to_edit(sd_bus
*bus
, char **names
, char ***paths
) {
6208 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
6215 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
6219 STRV_FOREACH(name
, names
) {
6220 _cleanup_free_
char *path
= NULL
, *new_path
= NULL
, *tmp_path
= NULL
;
6222 r
= unit_find_paths(bus
, *name
, &lp
, &path
, NULL
);
6228 // FIXME: support units with path==NULL (no FragmentPath)
6229 log_error("No fragment exists for %s.", *name
);
6234 r
= unit_file_create_copy(&lp
, *name
, path
, &new_path
, &tmp_path
);
6236 r
= unit_file_create_dropin(&lp
, *name
, &new_path
, &tmp_path
);
6240 r
= strv_push_pair(paths
, new_path
, tmp_path
);
6243 new_path
= tmp_path
= NULL
;
6249 static int edit(int argc
, char *argv
[], void *userdata
) {
6250 _cleanup_strv_free_
char **names
= NULL
;
6251 _cleanup_strv_free_
char **paths
= NULL
;
6252 char **original
, **tmp
;
6257 log_error("Cannot edit units if not on a tty.");
6261 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
6262 log_error("Cannot edit units remotely.");
6266 r
= acquire_bus(BUS_MANAGER
, &bus
);
6270 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
6272 return log_error_errno(r
, "Failed to expand names: %m");
6274 r
= find_paths_to_edit(bus
, names
, &paths
);
6278 if (strv_isempty(paths
))
6281 r
= run_editor(paths
);
6285 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
6286 /* If the temporary file is empty we ignore it. It's
6287 * useful if the user wants to cancel its modification
6289 if (null_or_empty_path(*tmp
)) {
6290 log_warning("Editing \"%s\" canceled: temporary file is empty.", *original
);
6294 r
= rename(*tmp
, *original
);
6296 r
= log_error_errno(errno
, "Failed to rename \"%s\" to \"%s\": %m", *tmp
, *original
);
6303 if (!arg_no_reload
&& !install_client_side())
6304 r
= daemon_reload(argc
, argv
, userdata
);
6307 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
6308 (void) unlink(*tmp
);
6310 /* Removing empty dropin dirs */
6312 _cleanup_free_
char *dir
;
6314 dir
= dirname_malloc(*original
);
6318 /* no need to check if the dir is empty, rmdir
6319 * does nothing if it is not the case.
6328 static void systemctl_help(void) {
6330 pager_open(arg_no_pager
, false);
6332 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
6333 "Query or send control commands to the systemd manager.\n\n"
6334 " -h --help Show this help\n"
6335 " --version Show package version\n"
6336 " --system Connect to system manager\n"
6337 " --user Connect to user service manager\n"
6338 " -H --host=[USER@]HOST\n"
6339 " Operate on remote host\n"
6340 " -M --machine=CONTAINER\n"
6341 " Operate on local container\n"
6342 " -t --type=TYPE List units of a particular type\n"
6343 " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n"
6344 " -p --property=NAME Show only properties by this name\n"
6345 " -a --all Show all loaded units/properties, including dead/empty\n"
6346 " ones. To list all units installed on the system, use\n"
6347 " the 'list-unit-files' command instead.\n"
6348 " -l --full Don't ellipsize unit names on output\n"
6349 " -r --recursive Show unit list of host and local containers\n"
6350 " --reverse Show reverse dependencies with 'list-dependencies'\n"
6351 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
6352 " queueing a new job\n"
6353 " --show-types When showing sockets, explicitly show their type\n"
6354 " --value When showing properties, only print the value\n"
6355 " -i --ignore-inhibitors\n"
6356 " When shutting down or sleeping, ignore inhibitors\n"
6357 " --kill-who=WHO Who to send signal to\n"
6358 " -s --signal=SIGNAL Which signal to send\n"
6359 " --now Start or stop unit in addition to enabling or disabling it\n"
6360 " -q --quiet Suppress output\n"
6361 " --no-block Do not wait until operation finished\n"
6362 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6363 " --no-reload Don't reload daemon after en-/dis-abling unit files\n"
6364 " --no-legend Do not print a legend (column headers and hints)\n"
6365 " --no-pager Do not pipe output into a pager\n"
6366 " --no-ask-password\n"
6367 " Do not ask for system passwords\n"
6368 " --global Enable/disable unit files globally\n"
6369 " --runtime Enable unit files only temporarily until next reboot\n"
6370 " -f --force When enabling unit files, override existing symlinks\n"
6371 " When shutting down, execute action immediately\n"
6372 " --preset-mode= Apply only enable, only disable, or all presets\n"
6373 " --root=PATH Enable unit files in the specified root directory\n"
6374 " -n --lines=INTEGER Number of journal entries to show\n"
6375 " -o --output=STRING Change journal output mode (short, short-iso,\n"
6376 " short-precise, short-monotonic, verbose,\n"
6377 " export, json, json-pretty, json-sse, cat)\n"
6378 " --firmware-setup Tell the firmware to show the setup menu on next boot\n"
6379 " --plain Print unit dependencies as a list instead of a tree\n\n"
6381 " list-units [PATTERN...] List loaded units\n"
6382 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
6383 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
6384 " start NAME... Start (activate) one or more units\n"
6385 " stop NAME... Stop (deactivate) one or more units\n"
6386 " reload NAME... Reload one or more units\n"
6387 " restart NAME... Start or restart one or more units\n"
6388 " try-restart NAME... Restart one or more units if active\n"
6389 " reload-or-restart NAME... Reload one or more units if possible,\n"
6390 " otherwise start or restart\n"
6391 " try-reload-or-restart NAME... If active, reload one or more units,\n"
6392 " if supported, otherwise restart\n"
6393 " isolate NAME Start one unit and stop all others\n"
6394 " kill NAME... Send signal to processes of a unit\n"
6395 " is-active PATTERN... Check whether units are active\n"
6396 " is-failed PATTERN... Check whether units are failed\n"
6397 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
6398 " show [PATTERN...|JOB...] Show properties of one or more\n"
6399 " units/jobs or the manager\n"
6400 " cat PATTERN... Show files and drop-ins of one or more units\n"
6401 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
6402 " help PATTERN...|PID... Show manual for one or more units\n"
6403 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
6405 " list-dependencies [NAME] Recursively show units which are required\n"
6406 " or wanted by this unit or by which this\n"
6407 " unit is required or wanted\n\n"
6408 "Unit File Commands:\n"
6409 " list-unit-files [PATTERN...] List installed unit files\n"
6410 " enable NAME... Enable one or more unit files\n"
6411 " disable NAME... Disable one or more unit files\n"
6412 " reenable NAME... Reenable one or more unit files\n"
6413 " preset NAME... Enable/disable one or more unit files\n"
6414 " based on preset configuration\n"
6415 " preset-all Enable/disable all unit files based on\n"
6416 " preset configuration\n"
6417 " is-enabled NAME... Check whether unit files are enabled\n"
6418 " mask NAME... Mask one or more units\n"
6419 " unmask NAME... Unmask one or more units\n"
6420 " link PATH... Link one or more units files into\n"
6421 " the search path\n"
6422 " revert NAME... Revert one or more unit files to vendor\n"
6424 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
6425 " on specified one or more units\n"
6426 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
6427 " on specified one or more units\n"
6428 " edit NAME... Edit one or more unit files\n"
6429 " get-default Get the name of the default target\n"
6430 " set-default NAME Set the default target\n\n"
6431 "Machine Commands:\n"
6432 " list-machines [PATTERN...] List local containers and host\n\n"
6434 " list-jobs [PATTERN...] List jobs\n"
6435 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
6436 "Environment Commands:\n"
6437 " show-environment Dump environment\n"
6438 " set-environment NAME=VALUE... Set one or more environment variables\n"
6439 " unset-environment NAME... Unset one or more environment variables\n"
6440 " import-environment [NAME...] Import all or some environment variables\n\n"
6441 "Manager Lifecycle Commands:\n"
6442 " daemon-reload Reload systemd manager configuration\n"
6443 " daemon-reexec Reexecute systemd manager\n\n"
6444 "System Commands:\n"
6445 " is-system-running Check whether system is fully running\n"
6446 " default Enter system default mode\n"
6447 " rescue Enter system rescue mode\n"
6448 " emergency Enter system emergency mode\n"
6449 " halt Shut down and halt the system\n"
6450 " poweroff Shut down and power-off the system\n"
6451 " reboot [ARG] Shut down and reboot the system\n"
6452 " kexec Shut down and reboot the system with kexec\n"
6453 " exit [EXIT_CODE] Request user instance or container exit\n"
6454 " switch-root ROOT [INIT] Change to a different root file system\n"
6455 " suspend Suspend the system\n"
6456 " hibernate Hibernate the system\n"
6457 " hybrid-sleep Hibernate and suspend the system\n",
6458 program_invocation_short_name
);
6461 static void halt_help(void) {
6462 printf("%s [OPTIONS...]%s\n\n"
6463 "%s the system.\n\n"
6464 " --help Show this help\n"
6465 " --halt Halt the machine\n"
6466 " -p --poweroff Switch off the machine\n"
6467 " --reboot Reboot the machine\n"
6468 " -f --force Force immediate halt/power-off/reboot\n"
6469 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
6470 " -d --no-wtmp Don't write wtmp record\n"
6471 " --no-wall Don't send wall message before halt/power-off/reboot\n",
6472 program_invocation_short_name
,
6473 arg_action
== ACTION_REBOOT
? " [ARG]" : "",
6474 arg_action
== ACTION_REBOOT
? "Reboot" :
6475 arg_action
== ACTION_POWEROFF
? "Power off" :
6479 static void shutdown_help(void) {
6480 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
6481 "Shut down the system.\n\n"
6482 " --help Show this help\n"
6483 " -H --halt Halt the machine\n"
6484 " -P --poweroff Power-off the machine\n"
6485 " -r --reboot Reboot the machine\n"
6486 " -h Equivalent to --poweroff, overridden by --halt\n"
6487 " -k Don't halt/power-off/reboot, just send warnings\n"
6488 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6489 " -c Cancel a pending shutdown\n",
6490 program_invocation_short_name
);
6493 static void telinit_help(void) {
6494 printf("%s [OPTIONS...] {COMMAND}\n\n"
6495 "Send control commands to the init daemon.\n\n"
6496 " --help Show this help\n"
6497 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
6499 " 0 Power-off the machine\n"
6500 " 6 Reboot the machine\n"
6501 " 2, 3, 4, 5 Start runlevelX.target unit\n"
6502 " 1, s, S Enter rescue mode\n"
6503 " q, Q Reload init daemon configuration\n"
6504 " u, U Reexecute init daemon\n",
6505 program_invocation_short_name
);
6508 static void runlevel_help(void) {
6509 printf("%s [OPTIONS...]\n\n"
6510 "Prints the previous and current runlevel of the init system.\n\n"
6511 " --help Show this help\n",
6512 program_invocation_short_name
);
6515 static void help_types(void) {
6519 puts("Available unit types:");
6520 for (i
= 0; i
< _UNIT_TYPE_MAX
; i
++)
6521 puts(unit_type_to_string(i
));
6524 static void help_states(void) {
6528 puts("Available unit load states:");
6529 for (i
= 0; i
< _UNIT_LOAD_STATE_MAX
; i
++)
6530 puts(unit_load_state_to_string(i
));
6533 puts("\nAvailable unit active states:");
6534 for (i
= 0; i
< _UNIT_ACTIVE_STATE_MAX
; i
++)
6535 puts(unit_active_state_to_string(i
));
6538 puts("\nAvailable automount unit substates:");
6539 for (i
= 0; i
< _AUTOMOUNT_STATE_MAX
; i
++)
6540 puts(automount_state_to_string(i
));
6543 puts("\nAvailable busname unit substates:");
6544 for (i
= 0; i
< _BUSNAME_STATE_MAX
; i
++)
6545 puts(busname_state_to_string(i
));
6548 puts("\nAvailable device unit substates:");
6549 for (i
= 0; i
< _DEVICE_STATE_MAX
; i
++)
6550 puts(device_state_to_string(i
));
6553 puts("\nAvailable mount unit substates:");
6554 for (i
= 0; i
< _MOUNT_STATE_MAX
; i
++)
6555 puts(mount_state_to_string(i
));
6558 puts("\nAvailable path unit substates:");
6559 for (i
= 0; i
< _PATH_STATE_MAX
; i
++)
6560 puts(path_state_to_string(i
));
6563 puts("\nAvailable scope unit substates:");
6564 for (i
= 0; i
< _SCOPE_STATE_MAX
; i
++)
6565 puts(scope_state_to_string(i
));
6568 puts("\nAvailable service unit substates:");
6569 for (i
= 0; i
< _SERVICE_STATE_MAX
; i
++)
6570 puts(service_state_to_string(i
));
6573 puts("\nAvailable slice unit substates:");
6574 for (i
= 0; i
< _SLICE_STATE_MAX
; i
++)
6575 puts(slice_state_to_string(i
));
6578 puts("\nAvailable socket unit substates:");
6579 for (i
= 0; i
< _SOCKET_STATE_MAX
; i
++)
6580 puts(socket_state_to_string(i
));
6583 puts("\nAvailable swap unit substates:");
6584 for (i
= 0; i
< _SWAP_STATE_MAX
; i
++)
6585 puts(swap_state_to_string(i
));
6588 puts("\nAvailable target unit substates:");
6589 for (i
= 0; i
< _TARGET_STATE_MAX
; i
++)
6590 puts(target_state_to_string(i
));
6593 puts("\nAvailable timer unit substates:");
6594 for (i
= 0; i
< _TIMER_STATE_MAX
; i
++)
6595 puts(timer_state_to_string(i
));
6598 static int systemctl_parse_argv(int argc
, char *argv
[]) {
6607 ARG_IGNORE_DEPENDENCIES
,
6620 ARG_NO_ASK_PASSWORD
,
6633 static const struct option options
[] = {
6634 { "help", no_argument
, NULL
, 'h' },
6635 { "version", no_argument
, NULL
, ARG_VERSION
},
6636 { "type", required_argument
, NULL
, 't' },
6637 { "property", required_argument
, NULL
, 'p' },
6638 { "all", no_argument
, NULL
, 'a' },
6639 { "reverse", no_argument
, NULL
, ARG_REVERSE
},
6640 { "after", no_argument
, NULL
, ARG_AFTER
},
6641 { "before", no_argument
, NULL
, ARG_BEFORE
},
6642 { "show-types", no_argument
, NULL
, ARG_SHOW_TYPES
},
6643 { "failed", no_argument
, NULL
, ARG_FAILED
}, /* compatibility only */
6644 { "full", no_argument
, NULL
, 'l' },
6645 { "job-mode", required_argument
, NULL
, ARG_JOB_MODE
},
6646 { "fail", no_argument
, NULL
, ARG_FAIL
}, /* compatibility only */
6647 { "irreversible", no_argument
, NULL
, ARG_IRREVERSIBLE
}, /* compatibility only */
6648 { "ignore-dependencies", no_argument
, NULL
, ARG_IGNORE_DEPENDENCIES
}, /* compatibility only */
6649 { "ignore-inhibitors", no_argument
, NULL
, 'i' },
6650 { "value", no_argument
, NULL
, ARG_VALUE
},
6651 { "user", no_argument
, NULL
, ARG_USER
},
6652 { "system", no_argument
, NULL
, ARG_SYSTEM
},
6653 { "global", no_argument
, NULL
, ARG_GLOBAL
},
6654 { "no-block", no_argument
, NULL
, ARG_NO_BLOCK
},
6655 { "no-legend", no_argument
, NULL
, ARG_NO_LEGEND
},
6656 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
6657 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6658 { "quiet", no_argument
, NULL
, 'q' },
6659 { "root", required_argument
, NULL
, ARG_ROOT
},
6660 { "force", no_argument
, NULL
, ARG_FORCE
},
6661 { "no-reload", no_argument
, NULL
, ARG_NO_RELOAD
},
6662 { "kill-who", required_argument
, NULL
, ARG_KILL_WHO
},
6663 { "signal", required_argument
, NULL
, 's' },
6664 { "no-ask-password", no_argument
, NULL
, ARG_NO_ASK_PASSWORD
},
6665 { "host", required_argument
, NULL
, 'H' },
6666 { "machine", required_argument
, NULL
, 'M' },
6667 { "runtime", no_argument
, NULL
, ARG_RUNTIME
},
6668 { "lines", required_argument
, NULL
, 'n' },
6669 { "output", required_argument
, NULL
, 'o' },
6670 { "plain", no_argument
, NULL
, ARG_PLAIN
},
6671 { "state", required_argument
, NULL
, ARG_STATE
},
6672 { "recursive", no_argument
, NULL
, 'r' },
6673 { "preset-mode", required_argument
, NULL
, ARG_PRESET_MODE
},
6674 { "firmware-setup", no_argument
, NULL
, ARG_FIRMWARE_SETUP
},
6675 { "now", no_argument
, NULL
, ARG_NOW
},
6676 { "message", required_argument
, NULL
, ARG_MESSAGE
},
6686 /* we default to allowing interactive authorization only in systemctl (not in the legacy commands) */
6687 arg_ask_password
= true;
6689 while ((c
= getopt_long(argc
, argv
, "ht:p:alqfs:H:M:n:o:ir", options
, NULL
)) >= 0)
6701 if (isempty(optarg
)) {
6702 log_error("--type requires arguments.");
6708 _cleanup_free_
char *type
= NULL
;
6710 r
= extract_first_word(&p
, &type
, ",", 0);
6712 return log_error_errno(r
, "Failed to parse type: %s", optarg
);
6717 if (streq(type
, "help")) {
6722 if (unit_type_from_string(type
) >= 0) {
6723 if (strv_push(&arg_types
, type
) < 0)
6729 /* It's much nicer to use --state= for
6730 * load states, but let's support this
6731 * in --types= too for compatibility
6732 * with old versions */
6733 if (unit_load_state_from_string(type
) >= 0) {
6734 if (strv_push(&arg_states
, type
) < 0)
6740 log_error("Unknown unit type or load state '%s'.", type
);
6741 log_info("Use -t help to see a list of allowed values.");
6749 /* Make sure that if the empty property list
6750 was specified, we won't show any properties. */
6751 if (isempty(optarg
) && !arg_properties
) {
6752 arg_properties
= new0(char*, 1);
6753 if (!arg_properties
)
6758 _cleanup_free_
char *prop
= NULL
;
6760 r
= extract_first_word(&p
, &prop
, ",", 0);
6762 return log_error_errno(r
, "Failed to parse property: %s", optarg
);
6767 if (strv_push(&arg_properties
, prop
) < 0)
6774 /* If the user asked for a particular
6775 * property, show it to him, even if it is
6787 arg_dependency
= DEPENDENCY_REVERSE
;
6791 arg_dependency
= DEPENDENCY_AFTER
;
6795 arg_dependency
= DEPENDENCY_BEFORE
;
6798 case ARG_SHOW_TYPES
:
6799 arg_show_types
= true;
6807 arg_job_mode
= optarg
;
6811 arg_job_mode
= "fail";
6814 case ARG_IRREVERSIBLE
:
6815 arg_job_mode
= "replace-irreversibly";
6818 case ARG_IGNORE_DEPENDENCIES
:
6819 arg_job_mode
= "ignore-dependencies";
6823 arg_scope
= UNIT_FILE_USER
;
6827 arg_scope
= UNIT_FILE_SYSTEM
;
6831 arg_scope
= UNIT_FILE_GLOBAL
;
6835 arg_no_block
= true;
6839 arg_no_legend
= true;
6843 arg_no_pager
= true;
6851 r
= parse_path_argument_and_warn(optarg
, false, &arg_root
);
6861 if (strv_extend(&arg_states
, "failed") < 0)
6879 arg_no_reload
= true;
6883 arg_kill_who
= optarg
;
6887 arg_signal
= signal_from_string_try_harder(optarg
);
6888 if (arg_signal
< 0) {
6889 log_error("Failed to parse signal string %s.", optarg
);
6894 case ARG_NO_ASK_PASSWORD
:
6895 arg_ask_password
= false;
6899 arg_transport
= BUS_TRANSPORT_REMOTE
;
6904 arg_transport
= BUS_TRANSPORT_MACHINE
;
6913 if (safe_atou(optarg
, &arg_lines
) < 0) {
6914 log_error("Failed to parse lines '%s'", optarg
);
6920 arg_output
= output_mode_from_string(optarg
);
6921 if (arg_output
< 0) {
6922 log_error("Unknown output '%s'.", optarg
);
6928 arg_ignore_inhibitors
= true;
6935 case ARG_FIRMWARE_SETUP
:
6936 arg_firmware_setup
= true;
6940 if (isempty(optarg
)) {
6941 log_error("--signal requires arguments.");
6947 _cleanup_free_
char *s
= NULL
;
6949 r
= extract_first_word(&p
, &s
, ",", 0);
6951 return log_error_errno(r
, "Failed to parse signal: %s", optarg
);
6956 if (streq(s
, "help")) {
6961 if (strv_push(&arg_states
, s
) < 0)
6970 if (geteuid() != 0) {
6971 log_error("--recursive requires root privileges.");
6975 arg_recursive
= true;
6978 case ARG_PRESET_MODE
:
6980 arg_preset_mode
= unit_file_preset_mode_from_string(optarg
);
6981 if (arg_preset_mode
< 0) {
6982 log_error("Failed to parse preset mode: %s.", optarg
);
6993 if (strv_extend(&arg_wall
, optarg
) < 0)
7001 assert_not_reached("Unhandled option");
7004 if (arg_transport
!= BUS_TRANSPORT_LOCAL
&& arg_scope
!= UNIT_FILE_SYSTEM
) {
7005 log_error("Cannot access user instance remotely.");
7012 static int halt_parse_argv(int argc
, char *argv
[]) {
7021 static const struct option options
[] = {
7022 { "help", no_argument
, NULL
, ARG_HELP
},
7023 { "halt", no_argument
, NULL
, ARG_HALT
},
7024 { "poweroff", no_argument
, NULL
, 'p' },
7025 { "reboot", no_argument
, NULL
, ARG_REBOOT
},
7026 { "force", no_argument
, NULL
, 'f' },
7027 { "wtmp-only", no_argument
, NULL
, 'w' },
7028 { "no-wtmp", no_argument
, NULL
, 'd' },
7029 { "no-sync", no_argument
, NULL
, 'n' },
7030 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7039 if (utmp_get_runlevel(&runlevel
, NULL
) >= 0)
7040 if (runlevel
== '0' || runlevel
== '6')
7043 while ((c
= getopt_long(argc
, argv
, "pfwdnih", options
, NULL
)) >= 0)
7051 arg_action
= ACTION_HALT
;
7055 if (arg_action
!= ACTION_REBOOT
)
7056 arg_action
= ACTION_POWEROFF
;
7060 arg_action
= ACTION_REBOOT
;
7085 /* Compatibility nops */
7092 assert_not_reached("Unhandled option");
7095 if (arg_action
== ACTION_REBOOT
&& (argc
== optind
|| argc
== optind
+ 1)) {
7096 r
= update_reboot_parameter_and_warn(argc
== optind
+ 1 ? argv
[optind
] : NULL
);
7099 } else if (optind
< argc
) {
7100 log_error("Too many arguments.");
7107 static int parse_shutdown_time_spec(const char *t
, usec_t
*_u
) {
7111 if (streq(t
, "now"))
7113 else if (!strchr(t
, ':')) {
7116 if (safe_atou64(t
, &u
) < 0)
7119 *_u
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
* u
;
7128 hour
= strtol(t
, &e
, 10);
7129 if (errno
> 0 || *e
!= ':' || hour
< 0 || hour
> 23)
7132 minute
= strtol(e
+1, &e
, 10);
7133 if (errno
> 0 || *e
!= 0 || minute
< 0 || minute
> 59)
7136 n
= now(CLOCK_REALTIME
);
7137 s
= (time_t) (n
/ USEC_PER_SEC
);
7139 assert_se(localtime_r(&s
, &tm
));
7141 tm
.tm_hour
= (int) hour
;
7142 tm
.tm_min
= (int) minute
;
7145 assert_se(s
= mktime(&tm
));
7147 *_u
= (usec_t
) s
* USEC_PER_SEC
;
7150 *_u
+= USEC_PER_DAY
;
7156 static int shutdown_parse_argv(int argc
, char *argv
[]) {
7163 static const struct option options
[] = {
7164 { "help", no_argument
, NULL
, ARG_HELP
},
7165 { "halt", no_argument
, NULL
, 'H' },
7166 { "poweroff", no_argument
, NULL
, 'P' },
7167 { "reboot", no_argument
, NULL
, 'r' },
7168 { "kexec", no_argument
, NULL
, 'K' }, /* not documented extension */
7169 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7179 while ((c
= getopt_long(argc
, argv
, "HPrhkKtafFc", options
, NULL
)) >= 0)
7187 arg_action
= ACTION_HALT
;
7191 arg_action
= ACTION_POWEROFF
;
7196 arg_action
= ACTION_KEXEC
;
7198 arg_action
= ACTION_REBOOT
;
7202 arg_action
= ACTION_KEXEC
;
7206 if (arg_action
!= ACTION_HALT
)
7207 arg_action
= ACTION_POWEROFF
;
7222 /* Compatibility nops */
7226 arg_action
= ACTION_CANCEL_SHUTDOWN
;
7233 assert_not_reached("Unhandled option");
7236 if (argc
> optind
&& arg_action
!= ACTION_CANCEL_SHUTDOWN
) {
7237 r
= parse_shutdown_time_spec(argv
[optind
], &arg_when
);
7239 log_error("Failed to parse time specification: %s", argv
[optind
]);
7243 arg_when
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
;
7245 if (argc
> optind
&& arg_action
== ACTION_CANCEL_SHUTDOWN
)
7246 /* No time argument for shutdown cancel */
7247 wall
= argv
+ optind
;
7248 else if (argc
> optind
+ 1)
7249 /* We skip the time argument */
7250 wall
= argv
+ optind
+ 1;
7253 arg_wall
= strv_copy(wall
);
7263 static int telinit_parse_argv(int argc
, char *argv
[]) {
7270 static const struct option options
[] = {
7271 { "help", no_argument
, NULL
, ARG_HELP
},
7272 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7276 static const struct {
7280 { '0', ACTION_POWEROFF
},
7281 { '6', ACTION_REBOOT
},
7282 { '1', ACTION_RESCUE
},
7283 { '2', ACTION_RUNLEVEL2
},
7284 { '3', ACTION_RUNLEVEL3
},
7285 { '4', ACTION_RUNLEVEL4
},
7286 { '5', ACTION_RUNLEVEL5
},
7287 { 's', ACTION_RESCUE
},
7288 { 'S', ACTION_RESCUE
},
7289 { 'q', ACTION_RELOAD
},
7290 { 'Q', ACTION_RELOAD
},
7291 { 'u', ACTION_REEXEC
},
7292 { 'U', ACTION_REEXEC
}
7301 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
7316 assert_not_reached("Unhandled option");
7319 if (optind
>= argc
) {
7320 log_error("%s: required argument missing.", program_invocation_short_name
);
7324 if (optind
+ 1 < argc
) {
7325 log_error("Too many arguments.");
7329 if (strlen(argv
[optind
]) != 1) {
7330 log_error("Expected single character argument.");
7334 for (i
= 0; i
< ELEMENTSOF(table
); i
++)
7335 if (table
[i
].from
== argv
[optind
][0])
7338 if (i
>= ELEMENTSOF(table
)) {
7339 log_error("Unknown command '%s'.", argv
[optind
]);
7343 arg_action
= table
[i
].to
;
7350 static int runlevel_parse_argv(int argc
, char *argv
[]) {
7356 static const struct option options
[] = {
7357 { "help", no_argument
, NULL
, ARG_HELP
},
7366 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
7377 assert_not_reached("Unhandled option");
7380 if (optind
< argc
) {
7381 log_error("Too many arguments.");
7388 static int parse_argv(int argc
, char *argv
[]) {
7392 if (program_invocation_short_name
) {
7394 if (strstr(program_invocation_short_name
, "halt")) {
7395 arg_action
= ACTION_HALT
;
7396 return halt_parse_argv(argc
, argv
);
7397 } else if (strstr(program_invocation_short_name
, "poweroff")) {
7398 arg_action
= ACTION_POWEROFF
;
7399 return halt_parse_argv(argc
, argv
);
7400 } else if (strstr(program_invocation_short_name
, "reboot")) {
7402 arg_action
= ACTION_KEXEC
;
7404 arg_action
= ACTION_REBOOT
;
7405 return halt_parse_argv(argc
, argv
);
7406 } else if (strstr(program_invocation_short_name
, "shutdown")) {
7407 arg_action
= ACTION_POWEROFF
;
7408 return shutdown_parse_argv(argc
, argv
);
7409 } else if (strstr(program_invocation_short_name
, "init")) {
7411 if (sd_booted() > 0) {
7412 arg_action
= _ACTION_INVALID
;
7413 return telinit_parse_argv(argc
, argv
);
7415 /* Hmm, so some other init system is
7416 * running, we need to forward this
7417 * request to it. For now we simply
7418 * guess that it is Upstart. */
7420 execv(TELINIT
, argv
);
7422 log_error("Couldn't find an alternative telinit implementation to spawn.");
7426 } else if (strstr(program_invocation_short_name
, "runlevel")) {
7427 arg_action
= ACTION_RUNLEVEL
;
7428 return runlevel_parse_argv(argc
, argv
);
7432 arg_action
= ACTION_SYSTEMCTL
;
7433 return systemctl_parse_argv(argc
, argv
);
7436 #ifdef HAVE_SYSV_COMPAT
7437 _pure_
static int action_to_runlevel(void) {
7439 static const char table
[_ACTION_MAX
] = {
7440 [ACTION_HALT
] = '0',
7441 [ACTION_POWEROFF
] = '0',
7442 [ACTION_REBOOT
] = '6',
7443 [ACTION_RUNLEVEL2
] = '2',
7444 [ACTION_RUNLEVEL3
] = '3',
7445 [ACTION_RUNLEVEL4
] = '4',
7446 [ACTION_RUNLEVEL5
] = '5',
7447 [ACTION_RESCUE
] = '1'
7450 assert(arg_action
< _ACTION_MAX
);
7452 return table
[arg_action
];
7456 static int talk_initctl(void) {
7457 #ifdef HAVE_SYSV_COMPAT
7458 struct init_request request
= {
7459 .magic
= INIT_MAGIC
,
7461 .cmd
= INIT_CMD_RUNLVL
7464 _cleanup_close_
int fd
= -1;
7468 rl
= action_to_runlevel();
7472 request
.runlevel
= rl
;
7474 fd
= open(INIT_FIFO
, O_WRONLY
|O_NDELAY
|O_CLOEXEC
|O_NOCTTY
);
7476 if (errno
== ENOENT
)
7479 return log_error_errno(errno
, "Failed to open "INIT_FIFO
": %m");
7482 r
= loop_write(fd
, &request
, sizeof(request
), false);
7484 return log_error_errno(r
, "Failed to write to "INIT_FIFO
": %m");
7492 static int systemctl_main(int argc
, char *argv
[]) {
7494 static const Verb verbs
[] = {
7495 { "list-units", VERB_ANY
, VERB_ANY
, VERB_DEFAULT
|VERB_NOCHROOT
, list_units
},
7496 { "list-unit-files", VERB_ANY
, VERB_ANY
, 0, list_unit_files
},
7497 { "list-sockets", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_sockets
},
7498 { "list-timers", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_timers
},
7499 { "list-jobs", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_jobs
},
7500 { "list-machines", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_machines
},
7501 { "clear-jobs", VERB_ANY
, 1, VERB_NOCHROOT
, daemon_reload
},
7502 { "cancel", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, cancel_job
},
7503 { "start", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
7504 { "stop", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
7505 { "condstop", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with ALTLinux */
7506 { "reload", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
7507 { "restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
7508 { "try-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
7509 { "reload-or-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
7510 { "reload-or-try-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatbility with old systemctl <= 228 */
7511 { "try-reload-or-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
7512 { "force-reload", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with SysV */
7513 { "condreload", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with ALTLinux */
7514 { "condrestart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with RH */
7515 { "isolate", 2, 2, VERB_NOCHROOT
, start_unit
},
7516 { "kill", 2, VERB_ANY
, VERB_NOCHROOT
, kill_unit
},
7517 { "is-active", 2, VERB_ANY
, VERB_NOCHROOT
, check_unit_active
},
7518 { "check", 2, VERB_ANY
, VERB_NOCHROOT
, check_unit_active
},
7519 { "is-failed", 2, VERB_ANY
, VERB_NOCHROOT
, check_unit_failed
},
7520 { "show", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, show
},
7521 { "cat", 2, VERB_ANY
, VERB_NOCHROOT
, cat
},
7522 { "status", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, show
},
7523 { "help", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, show
},
7524 { "daemon-reload", VERB_ANY
, 1, VERB_NOCHROOT
, daemon_reload
},
7525 { "daemon-reexec", VERB_ANY
, 1, VERB_NOCHROOT
, daemon_reload
},
7526 { "show-environment", VERB_ANY
, 1, VERB_NOCHROOT
, show_environment
},
7527 { "set-environment", 2, VERB_ANY
, VERB_NOCHROOT
, set_environment
},
7528 { "unset-environment", 2, VERB_ANY
, VERB_NOCHROOT
, set_environment
},
7529 { "import-environment", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, import_environment
},
7530 { "halt", VERB_ANY
, 1, VERB_NOCHROOT
, start_special
},
7531 { "poweroff", VERB_ANY
, 1, VERB_NOCHROOT
, start_special
},
7532 { "reboot", VERB_ANY
, 2, VERB_NOCHROOT
, start_special
},
7533 { "kexec", VERB_ANY
, 1, VERB_NOCHROOT
, start_special
},
7534 { "suspend", VERB_ANY
, 1, VERB_NOCHROOT
, start_special
},
7535 { "hibernate", VERB_ANY
, 1, VERB_NOCHROOT
, start_special
},
7536 { "hybrid-sleep", VERB_ANY
, 1, VERB_NOCHROOT
, start_special
},
7537 { "default", VERB_ANY
, 1, VERB_NOCHROOT
, start_special
},
7538 { "rescue", VERB_ANY
, 1, VERB_NOCHROOT
, start_special
},
7539 { "emergency", VERB_ANY
, 1, VERB_NOCHROOT
, start_special
},
7540 { "exit", VERB_ANY
, 2, VERB_NOCHROOT
, start_special
},
7541 { "reset-failed", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, reset_failed
},
7542 { "enable", 2, VERB_ANY
, 0, enable_unit
},
7543 { "disable", 2, VERB_ANY
, 0, enable_unit
},
7544 { "is-enabled", 2, VERB_ANY
, 0, unit_is_enabled
},
7545 { "reenable", 2, VERB_ANY
, 0, enable_unit
},
7546 { "preset", 2, VERB_ANY
, 0, enable_unit
},
7547 { "preset-all", VERB_ANY
, 1, 0, preset_all
},
7548 { "mask", 2, VERB_ANY
, 0, enable_unit
},
7549 { "unmask", 2, VERB_ANY
, 0, enable_unit
},
7550 { "link", 2, VERB_ANY
, 0, enable_unit
},
7551 { "revert", 2, VERB_ANY
, 0, enable_unit
},
7552 { "switch-root", 2, VERB_ANY
, VERB_NOCHROOT
, switch_root
},
7553 { "list-dependencies", VERB_ANY
, 2, VERB_NOCHROOT
, list_dependencies
},
7554 { "set-default", 2, 2, 0, set_default
},
7555 { "get-default", VERB_ANY
, 1, 0, get_default
},
7556 { "set-property", 3, VERB_ANY
, VERB_NOCHROOT
, set_property
},
7557 { "is-system-running", VERB_ANY
, 1, 0, is_system_running
},
7558 { "add-wants", 3, VERB_ANY
, 0, add_dependency
},
7559 { "add-requires", 3, VERB_ANY
, 0, add_dependency
},
7560 { "edit", 2, VERB_ANY
, VERB_NOCHROOT
, edit
},
7564 return dispatch_verb(argc
, argv
, verbs
, NULL
);
7567 static int reload_with_fallback(void) {
7569 /* First, try systemd via D-Bus. */
7570 if (daemon_reload(0, NULL
, NULL
) >= 0)
7573 /* Nothing else worked, so let's try signals */
7574 assert(arg_action
== ACTION_RELOAD
|| arg_action
== ACTION_REEXEC
);
7576 if (kill(1, arg_action
== ACTION_RELOAD
? SIGHUP
: SIGTERM
) < 0)
7577 return log_error_errno(errno
, "kill() failed: %m");
7582 static int start_with_fallback(void) {
7584 /* First, try systemd via D-Bus. */
7585 if (start_unit(0, NULL
, NULL
) >= 0)
7588 /* Nothing else worked, so let's try
7590 if (talk_initctl() > 0)
7593 log_error("Failed to talk to init daemon.");
7597 static int halt_now(enum action a
) {
7600 /* The kernel will automaticall flush ATA disks and suchlike
7601 * on reboot(), but the file systems need to be synce'd
7602 * explicitly in advance. */
7606 /* Make sure C-A-D is handled by the kernel from this point
7608 (void) reboot(RB_ENABLE_CAD
);
7613 log_info("Halting.");
7614 (void) reboot(RB_HALT_SYSTEM
);
7617 case ACTION_POWEROFF
:
7618 log_info("Powering off.");
7619 (void) reboot(RB_POWER_OFF
);
7623 case ACTION_REBOOT
: {
7624 _cleanup_free_
char *param
= NULL
;
7626 r
= read_one_line_file("/run/systemd/reboot-param", ¶m
);
7628 log_warning_errno(r
, "Failed to read reboot parameter file: %m");
7630 if (!isempty(param
)) {
7631 log_info("Rebooting with argument '%s'.", param
);
7632 (void) syscall(SYS_reboot
, LINUX_REBOOT_MAGIC1
, LINUX_REBOOT_MAGIC2
, LINUX_REBOOT_CMD_RESTART2
, param
);
7633 log_warning_errno(errno
, "Failed to reboot with parameter, retrying without: %m");
7636 log_info("Rebooting.");
7637 (void) reboot(RB_AUTOBOOT
);
7642 assert_not_reached("Unknown action.");
7646 static int logind_schedule_shutdown(void) {
7649 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
7650 char date
[FORMAT_TIMESTAMP_MAX
];
7655 (void) logind_set_wall_message();
7657 r
= acquire_bus(BUS_FULL
, &bus
);
7661 switch (arg_action
) {
7665 case ACTION_POWEROFF
:
7666 action
= "poweroff";
7681 action
= strjoina("dry-", action
);
7683 r
= sd_bus_call_method(
7685 "org.freedesktop.login1",
7686 "/org/freedesktop/login1",
7687 "org.freedesktop.login1.Manager",
7695 return log_warning_errno(r
, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s", bus_error_message(&error
, r
));
7697 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.", format_timestamp(date
, sizeof(date
), arg_when
));
7700 log_error("Cannot schedule shutdown without logind support, proceeding with immediate shutdown.");
7705 static int halt_main(void) {
7708 r
= logind_check_inhibitors(arg_action
);
7713 return logind_schedule_shutdown();
7715 if (geteuid() != 0) {
7716 if (arg_dry
|| arg_force
> 0) {
7717 log_error("Must be root.");
7721 /* Try logind if we are a normal user and no special
7722 * mode applies. Maybe PolicyKit allows us to shutdown
7724 if (IN_SET(arg_action
, ACTION_POWEROFF
, ACTION_REBOOT
)) {
7725 r
= logind_reboot(arg_action
);
7728 if (IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
7729 /* requested operation is not
7730 * supported on the local system or
7731 * already in progress */
7733 /* on all other errors, try low-level operation */
7737 if (!arg_dry
&& !arg_force
)
7738 return start_with_fallback();
7740 assert(geteuid() == 0);
7743 if (sd_booted() > 0)
7744 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
7746 r
= utmp_put_shutdown();
7748 log_warning_errno(r
, "Failed to write utmp record: %m");
7755 r
= halt_now(arg_action
);
7756 return log_error_errno(r
, "Failed to reboot: %m");
7759 static int runlevel_main(void) {
7760 int r
, runlevel
, previous
;
7762 r
= utmp_get_runlevel(&runlevel
, &previous
);
7769 previous
<= 0 ? 'N' : previous
,
7770 runlevel
<= 0 ? 'N' : runlevel
);
7775 static int logind_cancel_shutdown(void) {
7777 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
7781 r
= acquire_bus(BUS_FULL
, &bus
);
7785 (void) logind_set_wall_message();
7787 r
= sd_bus_call_method(
7789 "org.freedesktop.login1",
7790 "/org/freedesktop/login1",
7791 "org.freedesktop.login1.Manager",
7792 "CancelScheduledShutdown",
7796 return log_warning_errno(r
, "Failed to talk to logind, shutdown hasn't been cancelled: %s", bus_error_message(&error
, r
));
7800 log_error("Not compiled with logind support, cannot cancel scheduled shutdowns.");
7805 int main(int argc
, char*argv
[]) {
7808 setlocale(LC_ALL
, "");
7809 log_parse_environment();
7813 /* Explicitly not on_tty() to avoid setting cached value.
7814 * This becomes relevant for piping output which might be
7816 original_stdout_is_tty
= isatty(STDOUT_FILENO
);
7818 r
= parse_argv(argc
, argv
);
7822 if (arg_action
!= ACTION_SYSTEMCTL
&& running_in_chroot() > 0) {
7823 log_info("Running in chroot, ignoring request.");
7828 /* systemctl_main() will print an error message for the bus
7829 * connection, but only if it needs to */
7831 switch (arg_action
) {
7833 case ACTION_SYSTEMCTL
:
7834 r
= systemctl_main(argc
, argv
);
7838 case ACTION_POWEROFF
:
7844 case ACTION_RUNLEVEL2
:
7845 case ACTION_RUNLEVEL3
:
7846 case ACTION_RUNLEVEL4
:
7847 case ACTION_RUNLEVEL5
:
7849 case ACTION_EMERGENCY
:
7850 case ACTION_DEFAULT
:
7851 r
= start_with_fallback();
7856 r
= reload_with_fallback();
7859 case ACTION_CANCEL_SHUTDOWN
:
7860 r
= logind_cancel_shutdown();
7863 case ACTION_RUNLEVEL
:
7864 r
= runlevel_main();
7867 case _ACTION_INVALID
:
7869 assert_not_reached("Unknown action");
7874 ask_password_agent_close();
7875 polkit_agent_close();
7877 strv_free(arg_types
);
7878 strv_free(arg_states
);
7879 strv_free(arg_properties
);
7881 strv_free(arg_wall
);
7886 /* Note that we return r here, not EXIT_SUCCESS, so that we can implement the LSB-like return codes */
7887 return r
< 0 ? EXIT_FAILURE
: r
;