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 "format-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_wait
= false;
122 static bool arg_no_block
= false;
123 static bool arg_no_legend
= false;
124 static bool arg_no_pager
= false;
125 static bool arg_no_wtmp
= false;
126 static bool arg_no_sync
= false;
127 static bool arg_no_wall
= false;
128 static bool arg_no_reload
= false;
129 static bool arg_value
= false;
130 static bool arg_show_types
= false;
131 static bool arg_ignore_inhibitors
= false;
132 static bool arg_dry
= false;
133 static bool arg_quiet
= false;
134 static bool arg_full
= false;
135 static bool arg_recursive
= false;
136 static int arg_force
= 0;
137 static bool arg_ask_password
= false;
138 static bool arg_runtime
= false;
139 static UnitFilePresetMode arg_preset_mode
= UNIT_FILE_PRESET_FULL
;
140 static char **arg_wall
= NULL
;
141 static const char *arg_kill_who
= NULL
;
142 static int arg_signal
= SIGTERM
;
143 static char *arg_root
= NULL
;
144 static usec_t arg_when
= 0;
145 static char *argv_cmdline
= NULL
;
167 ACTION_CANCEL_SHUTDOWN
,
169 } arg_action
= ACTION_SYSTEMCTL
;
170 static BusTransport arg_transport
= BUS_TRANSPORT_LOCAL
;
171 static const char *arg_host
= NULL
;
172 static unsigned arg_lines
= 10;
173 static OutputMode arg_output
= OUTPUT_SHORT
;
174 static bool arg_plain
= false;
175 static bool arg_firmware_setup
= false;
176 static bool arg_now
= false;
177 static bool arg_jobs_before
= false;
178 static bool arg_jobs_after
= false;
180 static int daemon_reload(int argc
, char *argv
[], void* userdata
);
181 static int trivial_method(int argc
, char *argv
[], void *userdata
);
182 static int halt_now(enum action a
);
183 static int get_state_one_unit(sd_bus
*bus
, const char *name
, UnitActiveState
*active_state
);
185 static bool original_stdout_is_tty
;
187 typedef enum BusFocus
{
188 BUS_FULL
, /* The full bus indicated via --system or --user */
189 BUS_MANAGER
, /* The manager itself, possibly directly, possibly via the bus */
193 static sd_bus
*busses
[_BUS_FOCUS_MAX
] = {};
195 static UnitFileFlags
args_to_flags(void) {
196 return (arg_runtime
? UNIT_FILE_RUNTIME
: 0) |
197 (arg_force
? UNIT_FILE_FORCE
: 0);
200 static int acquire_bus(BusFocus focus
, sd_bus
**ret
) {
203 assert(focus
< _BUS_FOCUS_MAX
);
206 /* We only go directly to the manager, if we are using a local transport */
207 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
210 if (getenv_bool("SYSTEMCTL_FORCE_BUS") > 0)
213 if (!busses
[focus
]) {
216 user
= arg_scope
!= UNIT_FILE_SYSTEM
;
218 if (focus
== BUS_MANAGER
)
219 r
= bus_connect_transport_systemd(arg_transport
, arg_host
, user
, &busses
[focus
]);
221 r
= bus_connect_transport(arg_transport
, arg_host
, user
, &busses
[focus
]);
223 return log_error_errno(r
, "Failed to connect to bus: %m");
225 (void) sd_bus_set_allow_interactive_authorization(busses
[focus
], arg_ask_password
);
228 *ret
= busses
[focus
];
232 static void release_busses(void) {
235 for (w
= 0; w
< _BUS_FOCUS_MAX
; w
++)
236 busses
[w
] = sd_bus_flush_close_unref(busses
[w
]);
239 static int map_string_no_copy(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
241 const char **p
= userdata
;
244 r
= sd_bus_message_read_basic(m
, SD_BUS_TYPE_STRING
, &s
);
254 static void ask_password_agent_open_if_enabled(void) {
256 /* Open the password agent as a child process if necessary */
258 if (!arg_ask_password
)
261 if (arg_scope
!= UNIT_FILE_SYSTEM
)
264 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
267 ask_password_agent_open();
270 static void polkit_agent_open_if_enabled(void) {
272 /* Open the polkit agent as a child process if necessary */
274 if (!arg_ask_password
)
277 if (arg_scope
!= UNIT_FILE_SYSTEM
)
280 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
286 static OutputFlags
get_output_flags(void) {
288 arg_all
* OUTPUT_SHOW_ALL
|
289 arg_full
* OUTPUT_FULL_WIDTH
|
290 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH
|
291 colors_enabled() * OUTPUT_COLOR
|
292 !arg_quiet
* OUTPUT_WARN_CUTOFF
;
295 static int translate_bus_error_to_exit_status(int r
, const sd_bus_error
*error
) {
298 if (!sd_bus_error_is_set(error
))
301 if (sd_bus_error_has_name(error
, SD_BUS_ERROR_ACCESS_DENIED
) ||
302 sd_bus_error_has_name(error
, BUS_ERROR_ONLY_BY_DEPENDENCY
) ||
303 sd_bus_error_has_name(error
, BUS_ERROR_NO_ISOLATION
) ||
304 sd_bus_error_has_name(error
, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE
))
305 return EXIT_NOPERMISSION
;
307 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
))
308 return EXIT_NOTINSTALLED
;
310 if (sd_bus_error_has_name(error
, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE
) ||
311 sd_bus_error_has_name(error
, SD_BUS_ERROR_NOT_SUPPORTED
))
312 return EXIT_NOTIMPLEMENTED
;
314 if (sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
))
315 return EXIT_NOTCONFIGURED
;
323 static bool install_client_side(void) {
325 /* Decides when to execute enable/disable/... operations
326 * client-side rather than server-side. */
328 if (running_in_chroot() > 0)
331 if (sd_booted() <= 0)
334 if (!isempty(arg_root
))
337 if (arg_scope
== UNIT_FILE_GLOBAL
)
340 /* Unsupported environment variable, mostly for debugging purposes */
341 if (getenv_bool("SYSTEMCTL_INSTALL_CLIENT_SIDE") > 0)
347 static int compare_unit_info(const void *a
, const void *b
) {
348 const UnitInfo
*u
= a
, *v
= b
;
352 /* First, order by machine */
353 if (!u
->machine
&& v
->machine
)
355 if (u
->machine
&& !v
->machine
)
357 if (u
->machine
&& v
->machine
) {
358 r
= strcasecmp(u
->machine
, v
->machine
);
363 /* Second, order by unit type */
364 d1
= strrchr(u
->id
, '.');
365 d2
= strrchr(v
->id
, '.');
367 r
= strcasecmp(d1
, d2
);
372 /* Third, order by name */
373 return strcasecmp(u
->id
, v
->id
);
376 static const char* unit_type_suffix(const char *name
) {
379 dot
= strrchr(name
, '.');
386 static bool output_show_unit(const UnitInfo
*u
, char **patterns
) {
389 if (!strv_fnmatch_or_empty(patterns
, u
->id
, FNM_NOESCAPE
))
392 if (arg_types
&& !strv_find(arg_types
, unit_type_suffix(u
->id
)))
398 /* Note that '--all' is not purely a state filter, but also a
399 * filter that hides units that "follow" other units (which is
400 * used for device units that appear under different names). */
401 if (!isempty(u
->following
))
404 if (!strv_isempty(arg_states
))
407 /* By default show all units except the ones in inactive
408 * state and with no pending job */
412 if (streq(u
->active_state
, "inactive"))
418 static int output_units_list(const UnitInfo
*unit_infos
, unsigned c
) {
419 unsigned circle_len
= 0, id_len
, max_id_len
, load_len
, active_len
, sub_len
, job_len
, desc_len
, max_desc_len
;
421 unsigned n_shown
= 0;
424 max_id_len
= strlen("UNIT");
425 load_len
= strlen("LOAD");
426 active_len
= strlen("ACTIVE");
427 sub_len
= strlen("SUB");
428 job_len
= strlen("JOB");
429 max_desc_len
= strlen("DESCRIPTION");
431 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
432 max_id_len
= MAX(max_id_len
, strlen(u
->id
) + (u
->machine
? strlen(u
->machine
)+1 : 0));
433 load_len
= MAX(load_len
, strlen(u
->load_state
));
434 active_len
= MAX(active_len
, strlen(u
->active_state
));
435 sub_len
= MAX(sub_len
, strlen(u
->sub_state
));
436 max_desc_len
= MAX(max_desc_len
, strlen(u
->description
));
438 if (u
->job_id
!= 0) {
439 job_len
= MAX(job_len
, strlen(u
->job_type
));
443 if (!arg_no_legend
&&
444 (streq(u
->active_state
, "failed") ||
445 STR_IN_SET(u
->load_state
, "error", "not-found", "masked")))
449 if (!arg_full
&& original_stdout_is_tty
) {
452 id_len
= MIN(max_id_len
, 25u); /* as much as it needs, but at most 25 for now */
453 basic_len
= circle_len
+ 5 + id_len
+ 5 + active_len
+ sub_len
;
456 basic_len
+= job_len
+ 1;
458 if (basic_len
< (unsigned) columns()) {
459 unsigned extra_len
, incr
;
460 extra_len
= columns() - basic_len
;
462 /* Either UNIT already got 25, or is fully satisfied.
463 * Grant up to 25 to DESC now. */
464 incr
= MIN(extra_len
, 25u);
468 /* Of the remainder give as much as the ID needs to the ID, and give the rest to the
469 * description but not more than it needs. */
471 incr
= MIN(max_id_len
- id_len
, extra_len
);
473 desc_len
+= MIN(extra_len
- incr
, max_desc_len
- desc_len
);
478 desc_len
= max_desc_len
;
481 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
482 _cleanup_free_
char *e
= NULL
, *j
= NULL
;
483 const char *on_underline
= "", *off_underline
= "";
484 const char *on_loaded
= "", *off_loaded
= "";
485 const char *on_active
= "", *off_active
= "";
486 const char *on_circle
= "", *off_circle
= "";
488 bool circle
= false, underline
= false;
490 if (!n_shown
&& !arg_no_legend
) {
495 printf("%s%-*s %-*s %-*s %-*s ",
499 active_len
, "ACTIVE",
503 printf("%-*s ", job_len
, "JOB");
507 !arg_full
&& arg_no_pager
? (int) desc_len
: -1,
514 if (u
+ 1 < unit_infos
+ c
&&
515 !streq(unit_type_suffix(u
->id
), unit_type_suffix((u
+ 1)->id
))) {
516 on_underline
= ansi_underline();
517 off_underline
= ansi_normal();
521 if (STR_IN_SET(u
->load_state
, "error", "not-found", "masked") && !arg_plain
) {
522 on_circle
= ansi_highlight_yellow();
523 off_circle
= ansi_normal();
525 on_loaded
= underline
? ansi_highlight_red_underline() : ansi_highlight_red();
526 off_loaded
= underline
? on_underline
: ansi_normal();
527 } else if (streq(u
->active_state
, "failed") && !arg_plain
) {
528 on_circle
= ansi_highlight_red();
529 off_circle
= ansi_normal();
531 on_active
= underline
? ansi_highlight_red_underline() : ansi_highlight_red();
532 off_active
= underline
? on_underline
: ansi_normal();
536 j
= strjoin(u
->machine
, ":", u
->id
);
545 e
= ellipsize(id
, id_len
, 33);
553 printf("%s%s%s ", on_circle
, circle
? special_glyph(BLACK_CIRCLE
) : " ", off_circle
);
555 printf("%s%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
557 on_active
, id_len
, id
, off_active
,
558 on_loaded
, load_len
, u
->load_state
, off_loaded
,
559 on_active
, active_len
, u
->active_state
,
560 sub_len
, u
->sub_state
, off_active
,
561 job_count
? job_len
+ 1 : 0, u
->job_id
? u
->job_type
: "");
565 !arg_full
&& arg_no_pager
? (int) desc_len
: -1,
570 if (!arg_no_legend
) {
571 const char *on
, *off
;
575 "LOAD = Reflects whether the unit definition was properly loaded.\n"
576 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
577 "SUB = The low-level unit activation state, values depend on unit type.");
578 puts(job_count
? "JOB = Pending job for the unit.\n" : "");
579 on
= ansi_highlight();
582 on
= ansi_highlight_red();
587 printf("%s%u loaded units listed.%s\n"
588 "To show all installed unit files use 'systemctl list-unit-files'.\n",
591 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
592 "To show all installed unit files use 'systemctl list-unit-files'.\n",
599 static int get_unit_list(
603 UnitInfo
**unit_infos
,
605 sd_bus_message
**_reply
) {
607 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
608 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
609 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
613 bool fallback
= false;
619 r
= sd_bus_message_new_method_call(
622 "org.freedesktop.systemd1",
623 "/org/freedesktop/systemd1",
624 "org.freedesktop.systemd1.Manager",
625 "ListUnitsByPatterns");
627 return bus_log_create_error(r
);
629 r
= sd_bus_message_append_strv(m
, arg_states
);
631 return bus_log_create_error(r
);
633 r
= sd_bus_message_append_strv(m
, patterns
);
635 return bus_log_create_error(r
);
637 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
638 if (r
< 0 && (sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_METHOD
) ||
639 sd_bus_error_has_name(&error
, SD_BUS_ERROR_ACCESS_DENIED
))) {
640 /* Fallback to legacy ListUnitsFiltered method */
642 log_debug_errno(r
, "Failed to list units: %s Falling back to ListUnitsFiltered method.", bus_error_message(&error
, r
));
643 m
= sd_bus_message_unref(m
);
644 sd_bus_error_free(&error
);
646 r
= sd_bus_message_new_method_call(
649 "org.freedesktop.systemd1",
650 "/org/freedesktop/systemd1",
651 "org.freedesktop.systemd1.Manager",
652 "ListUnitsFiltered");
654 return bus_log_create_error(r
);
656 r
= sd_bus_message_append_strv(m
, arg_states
);
658 return bus_log_create_error(r
);
660 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
663 return log_error_errno(r
, "Failed to list units: %s", bus_error_message(&error
, r
));
665 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssssouso)");
667 return bus_log_parse_error(r
);
669 while ((r
= bus_parse_unit_info(reply
, &u
)) > 0) {
672 if (!output_show_unit(&u
, fallback
? patterns
: NULL
))
675 if (!GREEDY_REALLOC(*unit_infos
, size
, c
+1))
678 (*unit_infos
)[c
++] = u
;
681 return bus_log_parse_error(r
);
683 r
= sd_bus_message_exit_container(reply
);
685 return bus_log_parse_error(r
);
693 static void message_set_freep(Set
**set
) {
696 while ((m
= set_steal_first(*set
)))
697 sd_bus_message_unref(m
);
702 static int get_unit_list_recursive(
705 UnitInfo
**_unit_infos
,
709 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
710 _cleanup_(message_set_freep
) Set
*replies
;
711 sd_bus_message
*reply
;
719 replies
= set_new(NULL
);
723 c
= get_unit_list(bus
, NULL
, patterns
, &unit_infos
, 0, &reply
);
727 r
= set_put(replies
, reply
);
729 sd_bus_message_unref(reply
);
734 _cleanup_strv_free_
char **machines
= NULL
;
737 r
= sd_get_machine_names(&machines
);
739 return log_error_errno(r
, "Failed to get machine names: %m");
741 STRV_FOREACH(i
, machines
) {
742 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*container
= NULL
;
745 r
= sd_bus_open_system_machine(&container
, *i
);
747 log_warning_errno(r
, "Failed to connect to container %s, ignoring: %m", *i
);
751 k
= get_unit_list(container
, *i
, patterns
, &unit_infos
, c
, &reply
);
757 r
= set_put(replies
, reply
);
759 sd_bus_message_unref(reply
);
764 *_machines
= machines
;
769 *_unit_infos
= unit_infos
;
778 static int list_units(int argc
, char *argv
[], void *userdata
) {
779 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
780 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
781 _cleanup_strv_free_
char **machines
= NULL
;
785 r
= acquire_bus(BUS_MANAGER
, &bus
);
789 pager_open(arg_no_pager
, false);
791 r
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
795 qsort_safe(unit_infos
, r
, sizeof(UnitInfo
), compare_unit_info
);
796 return output_units_list(unit_infos
, r
);
799 static int get_triggered_units(
804 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
811 r
= sd_bus_get_property_strv(
813 "org.freedesktop.systemd1",
815 "org.freedesktop.systemd1.Unit",
820 return log_error_errno(r
, "Failed to determine triggers: %s", bus_error_message(&error
, r
));
825 static int get_listening(
827 const char* unit_path
,
830 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
831 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
832 const char *type
, *path
;
835 r
= sd_bus_get_property(
837 "org.freedesktop.systemd1",
839 "org.freedesktop.systemd1.Socket",
845 return log_error_errno(r
, "Failed to get list of listening sockets: %s", bus_error_message(&error
, r
));
847 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
849 return bus_log_parse_error(r
);
851 while ((r
= sd_bus_message_read(reply
, "(ss)", &type
, &path
)) > 0) {
853 r
= strv_extend(listening
, type
);
857 r
= strv_extend(listening
, path
);
864 return bus_log_parse_error(r
);
866 r
= sd_bus_message_exit_container(reply
);
868 return bus_log_parse_error(r
);
880 /* Note: triggered is a list here, although it almost certainly
881 * will always be one unit. Nevertheless, dbus API allows for multiple
882 * values, so let's follow that. */
885 /* The strv above is shared. free is set only in the first one. */
889 static int socket_info_compare(const struct socket_info
*a
, const struct socket_info
*b
) {
895 if (!a
->machine
&& b
->machine
)
897 if (a
->machine
&& !b
->machine
)
899 if (a
->machine
&& b
->machine
) {
900 o
= strcasecmp(a
->machine
, b
->machine
);
905 o
= strcmp(a
->path
, b
->path
);
907 o
= strcmp(a
->type
, b
->type
);
912 static int output_sockets_list(struct socket_info
*socket_infos
, unsigned cs
) {
913 struct socket_info
*s
;
914 unsigned pathlen
= strlen("LISTEN"),
915 typelen
= strlen("TYPE") * arg_show_types
,
916 socklen
= strlen("UNIT"),
917 servlen
= strlen("ACTIVATES");
918 const char *on
, *off
;
920 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
924 socklen
= MAX(socklen
, strlen(s
->id
));
926 typelen
= MAX(typelen
, strlen(s
->type
));
927 pathlen
= MAX(pathlen
, strlen(s
->path
) + (s
->machine
? strlen(s
->machine
)+1 : 0));
929 STRV_FOREACH(a
, s
->triggered
)
930 tmp
+= strlen(*a
) + 2*(a
!= s
->triggered
);
931 servlen
= MAX(servlen
, tmp
);
936 printf("%-*s %-*.*s%-*s %s\n",
938 typelen
+ arg_show_types
, typelen
+ arg_show_types
, "TYPE ",
942 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
943 _cleanup_free_
char *j
= NULL
;
948 j
= strjoin(s
->machine
, ":", s
->path
);
956 printf("%-*s %-*s %-*s",
957 pathlen
, path
, typelen
, s
->type
, socklen
, s
->id
);
960 pathlen
, path
, socklen
, s
->id
);
961 STRV_FOREACH(a
, s
->triggered
)
963 a
== s
->triggered
? "" : ",", *a
);
967 on
= ansi_highlight();
972 on
= ansi_highlight_red();
976 if (!arg_no_legend
) {
977 printf("%s%u sockets listed.%s\n", on
, cs
, off
);
979 printf("Pass --all to see loaded but inactive sockets, too.\n");
985 static int list_sockets(int argc
, char *argv
[], void *userdata
) {
986 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
987 _cleanup_strv_free_
char **machines
= NULL
;
988 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
989 _cleanup_free_
struct socket_info
*socket_infos
= NULL
;
991 struct socket_info
*s
;
997 r
= acquire_bus(BUS_MANAGER
, &bus
);
1001 pager_open(arg_no_pager
, false);
1003 n
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
1007 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
1008 _cleanup_strv_free_
char **listening
= NULL
, **triggered
= NULL
;
1011 if (!endswith(u
->id
, ".socket"))
1014 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
1018 c
= get_listening(bus
, u
->unit_path
, &listening
);
1024 if (!GREEDY_REALLOC(socket_infos
, size
, cs
+ c
)) {
1029 for (i
= 0; i
< c
; i
++)
1030 socket_infos
[cs
+ i
] = (struct socket_info
) {
1031 .machine
= u
->machine
,
1033 .type
= listening
[i
*2],
1034 .path
= listening
[i
*2 + 1],
1035 .triggered
= triggered
,
1036 .own_triggered
= i
==0,
1039 /* from this point on we will cleanup those socket_infos */
1042 listening
= triggered
= NULL
; /* avoid cleanup */
1045 qsort_safe(socket_infos
, cs
, sizeof(struct socket_info
),
1046 (__compar_fn_t
) socket_info_compare
);
1048 output_sockets_list(socket_infos
, cs
);
1051 assert(cs
== 0 || socket_infos
);
1052 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
1055 if (s
->own_triggered
)
1056 strv_free(s
->triggered
);
1062 static int get_next_elapse(
1065 dual_timestamp
*next
) {
1067 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1075 r
= sd_bus_get_property_trivial(
1077 "org.freedesktop.systemd1",
1079 "org.freedesktop.systemd1.Timer",
1080 "NextElapseUSecMonotonic",
1085 return log_error_errno(r
, "Failed to get next elapsation time: %s", bus_error_message(&error
, r
));
1087 r
= sd_bus_get_property_trivial(
1089 "org.freedesktop.systemd1",
1091 "org.freedesktop.systemd1.Timer",
1092 "NextElapseUSecRealtime",
1097 return log_error_errno(r
, "Failed to get next elapsation time: %s", bus_error_message(&error
, r
));
1103 static int get_last_trigger(
1108 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1115 r
= sd_bus_get_property_trivial(
1117 "org.freedesktop.systemd1",
1119 "org.freedesktop.systemd1.Timer",
1125 return log_error_errno(r
, "Failed to get last trigger time: %s", bus_error_message(&error
, r
));
1131 const char* machine
;
1134 usec_t last_trigger
;
1138 static int timer_info_compare(const struct timer_info
*a
, const struct timer_info
*b
) {
1144 if (!a
->machine
&& b
->machine
)
1146 if (a
->machine
&& !b
->machine
)
1148 if (a
->machine
&& b
->machine
) {
1149 o
= strcasecmp(a
->machine
, b
->machine
);
1154 if (a
->next_elapse
< b
->next_elapse
)
1156 if (a
->next_elapse
> b
->next_elapse
)
1159 return strcmp(a
->id
, b
->id
);
1162 static int output_timers_list(struct timer_info
*timer_infos
, unsigned n
) {
1163 struct timer_info
*t
;
1165 nextlen
= strlen("NEXT"),
1166 leftlen
= strlen("LEFT"),
1167 lastlen
= strlen("LAST"),
1168 passedlen
= strlen("PASSED"),
1169 unitlen
= strlen("UNIT"),
1170 activatelen
= strlen("ACTIVATES");
1172 const char *on
, *off
;
1174 assert(timer_infos
|| n
== 0);
1176 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1180 if (t
->next_elapse
> 0) {
1181 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1183 format_timestamp(tstamp
, sizeof(tstamp
), t
->next_elapse
);
1184 nextlen
= MAX(nextlen
, strlen(tstamp
) + 1);
1186 format_timestamp_relative(trel
, sizeof(trel
), t
->next_elapse
);
1187 leftlen
= MAX(leftlen
, strlen(trel
));
1190 if (t
->last_trigger
> 0) {
1191 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1193 format_timestamp(tstamp
, sizeof(tstamp
), t
->last_trigger
);
1194 lastlen
= MAX(lastlen
, strlen(tstamp
) + 1);
1196 format_timestamp_relative(trel
, sizeof(trel
), t
->last_trigger
);
1197 passedlen
= MAX(passedlen
, strlen(trel
));
1200 unitlen
= MAX(unitlen
, strlen(t
->id
) + (t
->machine
? strlen(t
->machine
)+1 : 0));
1202 STRV_FOREACH(a
, t
->triggered
)
1203 ul
+= strlen(*a
) + 2*(a
!= t
->triggered
);
1205 activatelen
= MAX(activatelen
, ul
);
1210 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1214 passedlen
, "PASSED",
1218 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1219 _cleanup_free_
char *j
= NULL
;
1221 char tstamp1
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel1
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1222 char tstamp2
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel2
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1225 format_timestamp(tstamp1
, sizeof(tstamp1
), t
->next_elapse
);
1226 format_timestamp_relative(trel1
, sizeof(trel1
), t
->next_elapse
);
1228 format_timestamp(tstamp2
, sizeof(tstamp2
), t
->last_trigger
);
1229 format_timestamp_relative(trel2
, sizeof(trel2
), t
->last_trigger
);
1232 j
= strjoin(t
->machine
, ":", t
->id
);
1239 printf("%-*s %-*s %-*s %-*s %-*s",
1240 nextlen
, tstamp1
, leftlen
, trel1
, lastlen
, tstamp2
, passedlen
, trel2
, unitlen
, unit
);
1242 STRV_FOREACH(a
, t
->triggered
)
1244 a
== t
->triggered
? "" : ",", *a
);
1248 on
= ansi_highlight();
1249 off
= ansi_normal();
1253 on
= ansi_highlight_red();
1254 off
= ansi_normal();
1257 if (!arg_no_legend
) {
1258 printf("%s%u timers listed.%s\n", on
, n
, off
);
1260 printf("Pass --all to see loaded but inactive timers, too.\n");
1266 static usec_t
calc_next_elapse(dual_timestamp
*nw
, dual_timestamp
*next
) {
1272 if (next
->monotonic
!= USEC_INFINITY
&& next
->monotonic
> 0) {
1275 if (next
->monotonic
> nw
->monotonic
)
1276 converted
= nw
->realtime
+ (next
->monotonic
- nw
->monotonic
);
1278 converted
= nw
->realtime
- (nw
->monotonic
- next
->monotonic
);
1280 if (next
->realtime
!= USEC_INFINITY
&& next
->realtime
> 0)
1281 next_elapse
= MIN(converted
, next
->realtime
);
1283 next_elapse
= converted
;
1286 next_elapse
= next
->realtime
;
1291 static int list_timers(int argc
, char *argv
[], void *userdata
) {
1292 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
1293 _cleanup_strv_free_
char **machines
= NULL
;
1294 _cleanup_free_
struct timer_info
*timer_infos
= NULL
;
1295 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
1296 struct timer_info
*t
;
1304 r
= acquire_bus(BUS_MANAGER
, &bus
);
1308 pager_open(arg_no_pager
, false);
1310 n
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
1314 dual_timestamp_get(&nw
);
1316 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
1317 _cleanup_strv_free_
char **triggered
= NULL
;
1318 dual_timestamp next
= DUAL_TIMESTAMP_NULL
;
1321 if (!endswith(u
->id
, ".timer"))
1324 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
1328 r
= get_next_elapse(bus
, u
->unit_path
, &next
);
1332 get_last_trigger(bus
, u
->unit_path
, &last
);
1334 if (!GREEDY_REALLOC(timer_infos
, size
, c
+1)) {
1339 m
= calc_next_elapse(&nw
, &next
);
1341 timer_infos
[c
++] = (struct timer_info
) {
1342 .machine
= u
->machine
,
1345 .last_trigger
= last
,
1346 .triggered
= triggered
,
1349 triggered
= NULL
; /* avoid cleanup */
1352 qsort_safe(timer_infos
, c
, sizeof(struct timer_info
),
1353 (__compar_fn_t
) timer_info_compare
);
1355 output_timers_list(timer_infos
, c
);
1358 for (t
= timer_infos
; t
< timer_infos
+ c
; t
++)
1359 strv_free(t
->triggered
);
1364 static int compare_unit_file_list(const void *a
, const void *b
) {
1365 const char *d1
, *d2
;
1366 const UnitFileList
*u
= a
, *v
= b
;
1368 d1
= strrchr(u
->path
, '.');
1369 d2
= strrchr(v
->path
, '.');
1374 r
= strcasecmp(d1
, d2
);
1379 return strcasecmp(basename(u
->path
), basename(v
->path
));
1382 static bool output_show_unit_file(const UnitFileList
*u
, char **states
, char **patterns
) {
1385 if (!strv_fnmatch_or_empty(patterns
, basename(u
->path
), FNM_NOESCAPE
))
1388 if (!strv_isempty(arg_types
)) {
1391 dot
= strrchr(u
->path
, '.');
1395 if (!strv_find(arg_types
, dot
+1))
1399 if (!strv_isempty(states
) &&
1400 !strv_find(states
, unit_file_state_to_string(u
->state
)))
1406 static void output_unit_file_list(const UnitFileList
*units
, unsigned c
) {
1407 unsigned max_id_len
, id_cols
, state_cols
;
1408 const UnitFileList
*u
;
1410 max_id_len
= strlen("UNIT FILE");
1411 state_cols
= strlen("STATE");
1413 for (u
= units
; u
< units
+ c
; u
++) {
1414 max_id_len
= MAX(max_id_len
, strlen(basename(u
->path
)));
1415 state_cols
= MAX(state_cols
, strlen(unit_file_state_to_string(u
->state
)));
1419 unsigned basic_cols
;
1421 id_cols
= MIN(max_id_len
, 25u);
1422 basic_cols
= 1 + id_cols
+ state_cols
;
1423 if (basic_cols
< (unsigned) columns())
1424 id_cols
+= MIN(columns() - basic_cols
, max_id_len
- id_cols
);
1426 id_cols
= max_id_len
;
1428 if (!arg_no_legend
&& c
> 0)
1429 printf("%s%-*s %-*s%s\n",
1431 id_cols
, "UNIT FILE",
1432 state_cols
, "STATE",
1435 for (u
= units
; u
< units
+ c
; u
++) {
1436 _cleanup_free_
char *e
= NULL
;
1437 const char *on
, *off
, *on_underline
= "", *off_underline
= "";
1439 bool underline
= false;
1441 if (u
+ 1 < units
+ c
&&
1442 !streq(unit_type_suffix(u
->path
), unit_type_suffix((u
+ 1)->path
))) {
1443 on_underline
= ansi_underline();
1444 off_underline
= ansi_normal();
1448 if (IN_SET(u
->state
,
1450 UNIT_FILE_MASKED_RUNTIME
,
1453 on
= underline
? ansi_highlight_red_underline() : ansi_highlight_red();
1454 else if (u
->state
== UNIT_FILE_ENABLED
)
1455 on
= underline
? ansi_highlight_green_underline() : ansi_highlight_green();
1458 off
= off_underline
;
1460 id
= basename(u
->path
);
1462 e
= arg_full
? NULL
: ellipsize(id
, id_cols
, 33);
1464 printf("%s%-*s %s%-*s%s%s\n",
1466 id_cols
, e
? e
: id
,
1467 on
, state_cols
, unit_file_state_to_string(u
->state
), off
,
1472 printf("\n%u unit files listed.\n", c
);
1475 static int list_unit_files(int argc
, char *argv
[], void *userdata
) {
1476 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1477 _cleanup_free_ UnitFileList
*units
= NULL
;
1484 bool fallback
= false;
1486 if (install_client_side()) {
1492 h
= hashmap_new(&string_hash_ops
);
1496 r
= unit_file_get_list(arg_scope
, arg_root
, h
, arg_states
, strv_skip(argv
, 1));
1498 unit_file_list_free(h
);
1499 return log_error_errno(r
, "Failed to get unit file list: %m");
1502 n_units
= hashmap_size(h
);
1504 units
= new(UnitFileList
, n_units
?: 1); /* avoid malloc(0) */
1506 unit_file_list_free(h
);
1510 HASHMAP_FOREACH(u
, h
, i
) {
1511 if (!output_show_unit_file(u
, NULL
, NULL
))
1518 assert(c
<= n_units
);
1523 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
1524 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1527 r
= acquire_bus(BUS_MANAGER
, &bus
);
1531 r
= sd_bus_message_new_method_call(
1534 "org.freedesktop.systemd1",
1535 "/org/freedesktop/systemd1",
1536 "org.freedesktop.systemd1.Manager",
1537 "ListUnitFilesByPatterns");
1539 return bus_log_create_error(r
);
1541 r
= sd_bus_message_append_strv(m
, arg_states
);
1543 return bus_log_create_error(r
);
1545 r
= sd_bus_message_append_strv(m
, strv_skip(argv
, 1));
1547 return bus_log_create_error(r
);
1549 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
1550 if (r
< 0 && sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_METHOD
)) {
1551 /* Fallback to legacy ListUnitFiles method */
1553 log_debug_errno(r
, "Failed to list unit files: %s Falling back to ListUnitsFiles method.", bus_error_message(&error
, r
));
1554 m
= sd_bus_message_unref(m
);
1555 sd_bus_error_free(&error
);
1557 r
= sd_bus_message_new_method_call(
1560 "org.freedesktop.systemd1",
1561 "/org/freedesktop/systemd1",
1562 "org.freedesktop.systemd1.Manager",
1565 return bus_log_create_error(r
);
1567 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
1570 return log_error_errno(r
, "Failed to list unit files: %s", bus_error_message(&error
, r
));
1572 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
1574 return bus_log_parse_error(r
);
1576 while ((r
= sd_bus_message_read(reply
, "(ss)", &path
, &state
)) > 0) {
1578 if (!GREEDY_REALLOC(units
, size
, c
+ 1))
1581 units
[c
] = (struct UnitFileList
) {
1583 unit_file_state_from_string(state
)
1586 if (output_show_unit_file(&units
[c
],
1587 fallback
? arg_states
: NULL
,
1588 fallback
? strv_skip(argv
, 1) : NULL
))
1593 return bus_log_parse_error(r
);
1595 r
= sd_bus_message_exit_container(reply
);
1597 return bus_log_parse_error(r
);
1600 pager_open(arg_no_pager
, false);
1602 qsort_safe(units
, c
, sizeof(UnitFileList
), compare_unit_file_list
);
1603 output_unit_file_list(units
, c
);
1605 if (install_client_side())
1606 for (unit
= units
; unit
< units
+ c
; unit
++)
1612 static int list_dependencies_print(const char *name
, int level
, unsigned int branches
, bool last
) {
1613 _cleanup_free_
char *n
= NULL
;
1614 size_t max_len
= MAX(columns(),20u);
1620 for (i
= level
- 1; i
>= 0; i
--) {
1622 if (len
> max_len
- 3 && !arg_full
) {
1623 printf("%s...\n",max_len
% 2 ? "" : " ");
1626 printf("%s", special_glyph(branches
& (1 << i
) ? TREE_VERTICAL
: TREE_SPACE
));
1630 if (len
> max_len
- 3 && !arg_full
) {
1631 printf("%s...\n",max_len
% 2 ? "" : " ");
1635 printf("%s", special_glyph(last
? TREE_RIGHT
: TREE_BRANCH
));
1639 printf("%s\n", name
);
1643 n
= ellipsize(name
, max_len
-len
, 100);
1651 static int list_dependencies_get_dependencies(sd_bus
*bus
, const char *name
, char ***deps
) {
1653 static const char *dependencies
[_DEPENDENCY_MAX
] = {
1654 [DEPENDENCY_FORWARD
] = "Requires\0"
1659 [DEPENDENCY_REVERSE
] = "RequiredBy\0"
1664 [DEPENDENCY_AFTER
] = "After\0",
1665 [DEPENDENCY_BEFORE
] = "Before\0",
1668 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1669 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1670 _cleanup_strv_free_
char **ret
= NULL
;
1671 _cleanup_free_
char *path
= NULL
;
1677 assert_cc(ELEMENTSOF(dependencies
) == _DEPENDENCY_MAX
);
1679 path
= unit_dbus_path_from_name(name
);
1683 r
= sd_bus_call_method(
1685 "org.freedesktop.systemd1",
1687 "org.freedesktop.DBus.Properties",
1691 "s", "org.freedesktop.systemd1.Unit");
1693 return log_error_errno(r
, "Failed to get properties of %s: %s", name
, bus_error_message(&error
, r
));
1695 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
1697 return bus_log_parse_error(r
);
1699 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
1702 r
= sd_bus_message_read(reply
, "s", &prop
);
1704 return bus_log_parse_error(r
);
1706 if (!nulstr_contains(dependencies
[arg_dependency
], prop
)) {
1707 r
= sd_bus_message_skip(reply
, "v");
1709 return bus_log_parse_error(r
);
1712 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, "as");
1714 return bus_log_parse_error(r
);
1716 r
= bus_message_read_strv_extend(reply
, &ret
);
1718 return bus_log_parse_error(r
);
1720 r
= sd_bus_message_exit_container(reply
);
1722 return bus_log_parse_error(r
);
1725 r
= sd_bus_message_exit_container(reply
);
1727 return bus_log_parse_error(r
);
1731 return bus_log_parse_error(r
);
1733 r
= sd_bus_message_exit_container(reply
);
1735 return bus_log_parse_error(r
);
1743 static int list_dependencies_compare(const void *_a
, const void *_b
) {
1744 const char **a
= (const char**) _a
, **b
= (const char**) _b
;
1746 if (unit_name_to_type(*a
) == UNIT_TARGET
&& unit_name_to_type(*b
) != UNIT_TARGET
)
1748 if (unit_name_to_type(*a
) != UNIT_TARGET
&& unit_name_to_type(*b
) == UNIT_TARGET
)
1751 return strcasecmp(*a
, *b
);
1754 static int list_dependencies_one(
1759 unsigned int branches
) {
1761 _cleanup_strv_free_
char **deps
= NULL
;
1769 r
= strv_extend(units
, name
);
1773 r
= list_dependencies_get_dependencies(bus
, name
, &deps
);
1777 qsort_safe(deps
, strv_length(deps
), sizeof (char*), list_dependencies_compare
);
1779 STRV_FOREACH(c
, deps
) {
1780 if (strv_contains(*units
, *c
)) {
1782 r
= list_dependencies_print("...", level
+ 1, (branches
<< 1) | (c
[1] == NULL
? 0 : 1), 1);
1792 UnitActiveState active_state
= _UNIT_ACTIVE_STATE_INVALID
;
1795 (void) get_state_one_unit(bus
, *c
, &active_state
);
1797 switch (active_state
) {
1799 case UNIT_RELOADING
:
1800 case UNIT_ACTIVATING
:
1801 on
= ansi_highlight_green();
1805 case UNIT_DEACTIVATING
:
1810 on
= ansi_highlight_red();
1814 printf("%s%s%s ", on
, special_glyph(BLACK_CIRCLE
), ansi_normal());
1817 r
= list_dependencies_print(*c
, level
, branches
, c
[1] == NULL
);
1821 if (arg_all
|| unit_name_to_type(*c
) == UNIT_TARGET
) {
1822 r
= list_dependencies_one(bus
, *c
, level
+ 1, units
, (branches
<< 1) | (c
[1] == NULL
? 0 : 1));
1829 strv_remove(*units
, name
);
1834 static int list_dependencies(int argc
, char *argv
[], void *userdata
) {
1835 _cleanup_strv_free_
char **units
= NULL
;
1836 _cleanup_free_
char *unit
= NULL
;
1842 r
= unit_name_mangle(argv
[1], UNIT_NAME_NOGLOB
, &unit
);
1844 return log_error_errno(r
, "Failed to mangle unit name: %m");
1848 u
= SPECIAL_DEFAULT_TARGET
;
1850 r
= acquire_bus(BUS_MANAGER
, &bus
);
1854 pager_open(arg_no_pager
, false);
1858 return list_dependencies_one(bus
, u
, 0, &units
, 0);
1861 struct machine_info
{
1865 char *control_group
;
1866 uint32_t n_failed_units
;
1871 static const struct bus_properties_map machine_info_property_map
[] = {
1872 { "SystemState", "s", NULL
, offsetof(struct machine_info
, state
) },
1873 { "NJobs", "u", NULL
, offsetof(struct machine_info
, n_jobs
) },
1874 { "NFailedUnits", "u", NULL
, offsetof(struct machine_info
, n_failed_units
) },
1875 { "ControlGroup", "s", NULL
, offsetof(struct machine_info
, control_group
) },
1876 { "UserspaceTimestamp", "t", NULL
, offsetof(struct machine_info
, timestamp
) },
1880 static void machine_info_clear(struct machine_info
*info
) {
1885 free(info
->control_group
);
1889 static void free_machines_list(struct machine_info
*machine_infos
, int n
) {
1895 for (i
= 0; i
< n
; i
++)
1896 machine_info_clear(&machine_infos
[i
]);
1898 free(machine_infos
);
1901 static int compare_machine_info(const void *a
, const void *b
) {
1902 const struct machine_info
*u
= a
, *v
= b
;
1904 if (u
->is_host
!= v
->is_host
)
1905 return u
->is_host
> v
->is_host
? -1 : 1;
1907 return strcasecmp(u
->name
, v
->name
);
1910 static int get_machine_properties(sd_bus
*bus
, struct machine_info
*mi
) {
1911 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*container
= NULL
;
1917 r
= sd_bus_open_system_machine(&container
, mi
->name
);
1924 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, mi
);
1931 static bool output_show_machine(const char *name
, char **patterns
) {
1932 return strv_fnmatch_or_empty(patterns
, name
, FNM_NOESCAPE
);
1935 static int get_machine_list(
1937 struct machine_info
**_machine_infos
,
1940 struct machine_info
*machine_infos
= NULL
;
1941 _cleanup_strv_free_
char **m
= NULL
;
1942 _cleanup_free_
char *hn
= NULL
;
1947 hn
= gethostname_malloc();
1951 if (output_show_machine(hn
, patterns
)) {
1952 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1))
1955 machine_infos
[c
].is_host
= true;
1956 machine_infos
[c
].name
= hn
;
1959 get_machine_properties(bus
, &machine_infos
[c
]);
1963 r
= sd_get_machine_names(&m
);
1965 return log_error_errno(r
, "Failed to get machine list: %m");
1967 STRV_FOREACH(i
, m
) {
1968 _cleanup_free_
char *class = NULL
;
1970 if (!output_show_machine(*i
, patterns
))
1973 sd_machine_get_class(*i
, &class);
1974 if (!streq_ptr(class, "container"))
1977 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1)) {
1978 free_machines_list(machine_infos
, c
);
1982 machine_infos
[c
].is_host
= false;
1983 machine_infos
[c
].name
= strdup(*i
);
1984 if (!machine_infos
[c
].name
) {
1985 free_machines_list(machine_infos
, c
);
1989 get_machine_properties(NULL
, &machine_infos
[c
]);
1993 *_machine_infos
= machine_infos
;
1997 static void output_machines_list(struct machine_info
*machine_infos
, unsigned n
) {
1998 struct machine_info
*m
;
2001 namelen
= sizeof("NAME") - 1,
2002 statelen
= sizeof("STATE") - 1,
2003 failedlen
= sizeof("FAILED") - 1,
2004 jobslen
= sizeof("JOBS") - 1;
2006 assert(machine_infos
|| n
== 0);
2008 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
2009 namelen
= MAX(namelen
, strlen(m
->name
) + (m
->is_host
? sizeof(" (host)") - 1 : 0));
2010 statelen
= MAX(statelen
, m
->state
? strlen(m
->state
) : 0);
2011 failedlen
= MAX(failedlen
, DECIMAL_STR_WIDTH(m
->n_failed_units
));
2012 jobslen
= MAX(jobslen
, DECIMAL_STR_WIDTH(m
->n_jobs
));
2014 if (!arg_plain
&& !streq_ptr(m
->state
, "running"))
2018 if (!arg_no_legend
) {
2022 printf("%-*s %-*s %-*s %-*s\n",
2025 failedlen
, "FAILED",
2029 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
2030 const char *on_state
= "", *off_state
= "";
2031 const char *on_failed
= "", *off_failed
= "";
2032 bool circle
= false;
2034 if (streq_ptr(m
->state
, "degraded")) {
2035 on_state
= ansi_highlight_red();
2036 off_state
= ansi_normal();
2038 } else if (!streq_ptr(m
->state
, "running")) {
2039 on_state
= ansi_highlight_yellow();
2040 off_state
= ansi_normal();
2044 if (m
->n_failed_units
> 0) {
2045 on_failed
= ansi_highlight_red();
2046 off_failed
= ansi_normal();
2048 on_failed
= off_failed
= "";
2051 printf("%s%s%s ", on_state
, circle
? special_glyph(BLACK_CIRCLE
) : " ", off_state
);
2054 printf("%-*s (host) %s%-*s%s %s%*" PRIu32
"%s %*" PRIu32
"\n",
2055 (int) (namelen
- (sizeof(" (host)")-1)), strna(m
->name
),
2056 on_state
, statelen
, strna(m
->state
), off_state
,
2057 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
2058 jobslen
, m
->n_jobs
);
2060 printf("%-*s %s%-*s%s %s%*" PRIu32
"%s %*" PRIu32
"\n",
2061 namelen
, strna(m
->name
),
2062 on_state
, statelen
, strna(m
->state
), off_state
,
2063 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
2064 jobslen
, m
->n_jobs
);
2068 printf("\n%u machines listed.\n", n
);
2071 static int list_machines(int argc
, char *argv
[], void *userdata
) {
2072 struct machine_info
*machine_infos
= NULL
;
2076 if (geteuid() != 0) {
2077 log_error("Must be root.");
2081 r
= acquire_bus(BUS_MANAGER
, &bus
);
2085 r
= get_machine_list(bus
, &machine_infos
, strv_skip(argv
, 1));
2089 pager_open(arg_no_pager
, false);
2091 qsort_safe(machine_infos
, r
, sizeof(struct machine_info
), compare_machine_info
);
2092 output_machines_list(machine_infos
, r
);
2093 free_machines_list(machine_infos
, r
);
2098 static int get_default(int argc
, char *argv
[], void *userdata
) {
2099 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2100 _cleanup_free_
char *_path
= NULL
;
2104 if (install_client_side()) {
2105 r
= unit_file_get_default(arg_scope
, arg_root
, &_path
);
2107 return log_error_errno(r
, "Failed to get default target: %m");
2112 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2115 r
= acquire_bus(BUS_MANAGER
, &bus
);
2119 r
= sd_bus_call_method(
2121 "org.freedesktop.systemd1",
2122 "/org/freedesktop/systemd1",
2123 "org.freedesktop.systemd1.Manager",
2129 return log_error_errno(r
, "Failed to get default target: %s", bus_error_message(&error
, r
));
2131 r
= sd_bus_message_read(reply
, "s", &path
);
2133 return bus_log_parse_error(r
);
2137 printf("%s\n", path
);
2142 static int set_default(int argc
, char *argv
[], void *userdata
) {
2143 _cleanup_free_
char *unit
= NULL
;
2144 UnitFileChange
*changes
= NULL
;
2145 unsigned n_changes
= 0;
2151 r
= unit_name_mangle_with_suffix(argv
[1], UNIT_NAME_NOGLOB
, ".target", &unit
);
2153 return log_error_errno(r
, "Failed to mangle unit name: %m");
2155 if (install_client_side()) {
2156 r
= unit_file_set_default(arg_scope
, UNIT_FILE_FORCE
, arg_root
, unit
, &changes
, &n_changes
);
2157 unit_file_dump_changes(r
, "set default", changes
, n_changes
, arg_quiet
);
2162 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2163 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2166 polkit_agent_open_if_enabled();
2168 r
= acquire_bus(BUS_MANAGER
, &bus
);
2172 r
= sd_bus_call_method(
2174 "org.freedesktop.systemd1",
2175 "/org/freedesktop/systemd1",
2176 "org.freedesktop.systemd1.Manager",
2182 return log_error_errno(r
, "Failed to set default target: %s", bus_error_message(&error
, r
));
2184 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
2188 /* Try to reload if enabled */
2190 r
= daemon_reload(argc
, argv
, userdata
);
2196 unit_file_changes_free(changes
, n_changes
);
2201 static int output_waiting_jobs(sd_bus
*bus
, uint32_t id
, const char *method
, const char *prefix
) {
2202 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2203 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2204 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2210 r
= sd_bus_call_method(
2212 "org.freedesktop.systemd1",
2213 "/org/freedesktop/systemd1",
2214 "org.freedesktop.systemd1.Manager",
2220 return log_debug_errno(r
, "Failed to get waiting jobs for job %" PRIu32
, id
);
2222 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2224 return bus_log_parse_error(r
);
2226 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &other_id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0)
2227 printf("%s %u (%s/%s)\n", prefix
, other_id
, name
, type
);
2229 return bus_log_parse_error(r
);
2231 r
= sd_bus_message_exit_container(reply
);
2233 return bus_log_parse_error(r
);
2240 const char *name
, *type
, *state
;
2243 static void output_jobs_list(sd_bus
*bus
, const struct job_info
* jobs
, unsigned n
, bool skipped
) {
2244 unsigned id_len
, unit_len
, type_len
, state_len
;
2245 const struct job_info
*j
;
2246 const char *on
, *off
;
2247 bool shorten
= false;
2249 assert(n
== 0 || jobs
);
2252 if (!arg_no_legend
) {
2253 on
= ansi_highlight_green();
2254 off
= ansi_normal();
2256 printf("%sNo jobs %s.%s\n", on
, skipped
? "listed" : "running", off
);
2261 pager_open(arg_no_pager
, false);
2263 id_len
= strlen("JOB");
2264 unit_len
= strlen("UNIT");
2265 type_len
= strlen("TYPE");
2266 state_len
= strlen("STATE");
2268 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2269 uint32_t id
= j
->id
;
2270 assert(j
->name
&& j
->type
&& j
->state
);
2272 id_len
= MAX(id_len
, DECIMAL_STR_WIDTH(id
));
2273 unit_len
= MAX(unit_len
, strlen(j
->name
));
2274 type_len
= MAX(type_len
, strlen(j
->type
));
2275 state_len
= MAX(state_len
, strlen(j
->state
));
2278 if (!arg_full
&& id_len
+ 1 + unit_len
+ type_len
+ 1 + state_len
> columns()) {
2279 unit_len
= MAX(33u, columns() - id_len
- type_len
- state_len
- 3);
2284 printf("%*s %-*s %-*s %-*s\n",
2288 state_len
, "STATE");
2290 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2291 _cleanup_free_
char *e
= NULL
;
2293 if (streq(j
->state
, "running")) {
2294 on
= ansi_highlight();
2295 off
= ansi_normal();
2299 e
= shorten
? ellipsize(j
->name
, unit_len
, 33) : NULL
;
2300 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2302 on
, unit_len
, e
? e
: j
->name
, off
,
2304 on
, state_len
, j
->state
, off
);
2307 output_waiting_jobs(bus
, j
->id
, "GetJobAfter", "\twaiting for job");
2308 if (arg_jobs_before
)
2309 output_waiting_jobs(bus
, j
->id
, "GetJobBefore", "\tblocking job");
2312 if (!arg_no_legend
) {
2313 on
= ansi_highlight();
2314 off
= ansi_normal();
2316 printf("\n%s%u jobs listed%s.\n", on
, n
, off
);
2320 static bool output_show_job(struct job_info
*job
, char **patterns
) {
2321 return strv_fnmatch_or_empty(patterns
, job
->name
, FNM_NOESCAPE
);
2324 static int list_jobs(int argc
, char *argv
[], void *userdata
) {
2325 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2326 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2327 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2328 _cleanup_free_
struct job_info
*jobs
= NULL
;
2334 bool skipped
= false;
2336 r
= acquire_bus(BUS_MANAGER
, &bus
);
2340 r
= sd_bus_call_method(
2342 "org.freedesktop.systemd1",
2343 "/org/freedesktop/systemd1",
2344 "org.freedesktop.systemd1.Manager",
2350 return log_error_errno(r
, "Failed to list jobs: %s", bus_error_message(&error
, r
));
2352 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2354 return bus_log_parse_error(r
);
2356 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0) {
2357 struct job_info job
= { id
, name
, type
, state
};
2359 if (!output_show_job(&job
, strv_skip(argv
, 1))) {
2364 if (!GREEDY_REALLOC(jobs
, size
, c
+ 1))
2370 return bus_log_parse_error(r
);
2372 r
= sd_bus_message_exit_container(reply
);
2374 return bus_log_parse_error(r
);
2376 pager_open(arg_no_pager
, false);
2378 output_jobs_list(bus
, jobs
, c
, skipped
);
2382 static int cancel_job(int argc
, char *argv
[], void *userdata
) {
2388 return trivial_method(argc
, argv
, userdata
);
2390 r
= acquire_bus(BUS_MANAGER
, &bus
);
2394 polkit_agent_open_if_enabled();
2396 STRV_FOREACH(name
, strv_skip(argv
, 1)) {
2397 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2401 q
= safe_atou32(*name
, &id
);
2403 return log_error_errno(q
, "Failed to parse job id \"%s\": %m", *name
);
2405 q
= sd_bus_call_method(
2407 "org.freedesktop.systemd1",
2408 "/org/freedesktop/systemd1",
2409 "org.freedesktop.systemd1.Manager",
2415 log_error_errno(q
, "Failed to cancel job %"PRIu32
": %s", id
, bus_error_message(&error
, q
));
2424 static int need_daemon_reload(sd_bus
*bus
, const char *unit
) {
2425 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2429 /* We ignore all errors here, since this is used to show a
2432 /* We don't use unit_dbus_path_from_name() directly since we
2433 * don't want to load the unit if it isn't loaded. */
2435 r
= sd_bus_call_method(
2437 "org.freedesktop.systemd1",
2438 "/org/freedesktop/systemd1",
2439 "org.freedesktop.systemd1.Manager",
2447 r
= sd_bus_message_read(reply
, "o", &path
);
2451 r
= sd_bus_get_property_trivial(
2453 "org.freedesktop.systemd1",
2455 "org.freedesktop.systemd1.Unit",
2465 static void warn_unit_file_changed(const char *name
) {
2468 log_warning("%sWarning:%s %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
2469 ansi_highlight_red(),
2472 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user");
2475 static int unit_file_find_path(LookupPaths
*lp
, const char *unit_name
, char **unit_path
) {
2482 STRV_FOREACH(p
, lp
->search_path
) {
2483 _cleanup_free_
char *path
= NULL
, *lpath
= NULL
;
2486 path
= path_join(arg_root
, *p
, unit_name
);
2490 r
= chase_symlinks(path
, arg_root
, &lpath
);
2496 return log_error_errno(r
, "Failed to access path '%s': %m", path
);
2506 static int unit_find_paths(
2508 const char *unit_name
,
2510 char **fragment_path
,
2511 char ***dropin_paths
) {
2513 _cleanup_free_
char *path
= NULL
;
2514 _cleanup_strv_free_
char **dropins
= NULL
;
2518 * Finds where the unit is defined on disk. Returns 0 if the unit
2519 * is not found. Returns 1 if it is found, and sets
2520 * - the path to the unit in *path, if it exists on disk,
2521 * - and a strv of existing drop-ins in *dropins,
2522 * if the arg is not NULL and any dropins were found.
2526 assert(fragment_path
);
2529 if (!install_client_side() && !unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
2530 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2531 _cleanup_free_
char *unit
= NULL
;
2533 unit
= unit_dbus_path_from_name(unit_name
);
2537 r
= sd_bus_get_property_string(
2539 "org.freedesktop.systemd1",
2541 "org.freedesktop.systemd1.Unit",
2546 return log_error_errno(r
, "Failed to get FragmentPath: %s", bus_error_message(&error
, r
));
2549 r
= sd_bus_get_property_strv(
2551 "org.freedesktop.systemd1",
2553 "org.freedesktop.systemd1.Unit",
2558 return log_error_errno(r
, "Failed to get DropInPaths: %s", bus_error_message(&error
, r
));
2561 _cleanup_set_free_ Set
*names
;
2563 names
= set_new(NULL
);
2567 r
= unit_file_find_path(lp
, unit_name
, &path
);
2572 _cleanup_free_
char *template = NULL
;
2574 r
= unit_name_template(unit_name
, &template);
2575 if (r
< 0 && r
!= -EINVAL
)
2576 return log_error_errno(r
, "Failed to determine template name: %m");
2578 r
= unit_file_find_path(lp
, template, &path
);
2584 r
= set_put(names
, basename(path
));
2586 return log_error_errno(r
, "Failed to add unit name: %m");
2589 r
= unit_file_find_dropin_paths(lp
->search_path
, NULL
, names
, &dropins
);
2597 if (!isempty(path
)) {
2598 *fragment_path
= path
;
2603 if (dropin_paths
&& !strv_isempty(dropins
)) {
2604 *dropin_paths
= dropins
;
2609 if (r
== 0 && !arg_force
)
2610 log_error("No files found for %s.", unit_name
);
2615 static int get_state_one_unit(sd_bus
*bus
, const char *name
, UnitActiveState
*active_state
) {
2616 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2617 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2618 _cleanup_free_
char *buf
= NULL
;
2619 UnitActiveState state
;
2624 assert(active_state
);
2626 /* We don't use unit_dbus_path_from_name() directly since we don't want to load the unit unnecessarily, if it
2628 r
= sd_bus_call_method(
2630 "org.freedesktop.systemd1",
2631 "/org/freedesktop/systemd1",
2632 "org.freedesktop.systemd1.Manager",
2638 if (!sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_UNIT
))
2639 return log_error_errno(r
, "Failed to retrieve unit: %s", bus_error_message(&error
, r
));
2641 /* The unit is currently not loaded, hence say it's "inactive", since all units that aren't loaded are
2642 * considered inactive. */
2643 state
= UNIT_INACTIVE
;
2646 r
= sd_bus_message_read(reply
, "o", &path
);
2648 return bus_log_parse_error(r
);
2650 r
= sd_bus_get_property_string(
2652 "org.freedesktop.systemd1",
2654 "org.freedesktop.systemd1.Unit",
2659 return log_error_errno(r
, "Failed to retrieve unit state: %s", bus_error_message(&error
, r
));
2661 state
= unit_active_state_from_string(buf
);
2662 if (state
== _UNIT_ACTIVE_STATE_INVALID
) {
2663 log_error("Invalid unit state '%s' for: %s", buf
, name
);
2668 *active_state
= state
;
2672 static int check_triggering_units(
2676 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2677 _cleanup_free_
char *path
= NULL
, *n
= NULL
, *load_state
= NULL
;
2678 _cleanup_strv_free_
char **triggered_by
= NULL
;
2679 bool print_warning_label
= true;
2680 UnitActiveState active_state
;
2684 r
= unit_name_mangle(name
, UNIT_NAME_NOGLOB
, &n
);
2686 return log_error_errno(r
, "Failed to mangle unit name: %m");
2688 path
= unit_dbus_path_from_name(n
);
2692 r
= sd_bus_get_property_string(
2694 "org.freedesktop.systemd1",
2696 "org.freedesktop.systemd1.Unit",
2701 return log_error_errno(r
, "Failed to get load state of %s: %s", n
, bus_error_message(&error
, r
));
2703 if (streq(load_state
, "masked"))
2706 r
= sd_bus_get_property_strv(
2708 "org.freedesktop.systemd1",
2710 "org.freedesktop.systemd1.Unit",
2715 return log_error_errno(r
, "Failed to get triggered by array of %s: %s", n
, bus_error_message(&error
, r
));
2717 STRV_FOREACH(i
, triggered_by
) {
2718 r
= get_state_one_unit(bus
, *i
, &active_state
);
2722 if (!IN_SET(active_state
, UNIT_ACTIVE
, UNIT_RELOADING
))
2725 if (print_warning_label
) {
2726 log_warning("Warning: Stopping %s, but it can still be activated by:", n
);
2727 print_warning_label
= false;
2730 log_warning(" %s", *i
);
2736 static const struct {
2739 } unit_actions
[] = {
2740 { "start", "StartUnit" },
2741 { "stop", "StopUnit" },
2742 { "condstop", "StopUnit" },
2743 { "reload", "ReloadUnit" },
2744 { "restart", "RestartUnit" },
2745 { "try-restart", "TryRestartUnit" },
2746 { "condrestart", "TryRestartUnit" },
2747 { "reload-or-restart", "ReloadOrRestartUnit" },
2748 { "try-reload-or-restart", "ReloadOrTryRestartUnit" },
2749 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2750 { "condreload", "ReloadOrTryRestartUnit" },
2751 { "force-reload", "ReloadOrTryRestartUnit" }
2754 static const char *verb_to_method(const char *verb
) {
2757 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2758 if (streq_ptr(unit_actions
[i
].verb
, verb
))
2759 return unit_actions
[i
].method
;
2764 static const char *method_to_verb(const char *method
) {
2767 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2768 if (streq_ptr(unit_actions
[i
].method
, method
))
2769 return unit_actions
[i
].verb
;
2781 static void wait_context_free(WaitContext
*c
) {
2782 c
->match
= sd_bus_slot_unref(c
->match
);
2783 c
->event
= sd_event_unref(c
->event
);
2784 c
->unit_paths
= set_free_free(c
->unit_paths
);
2787 static int on_properties_changed(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
2788 WaitContext
*c
= userdata
;
2792 path
= sd_bus_message_get_path(m
);
2793 if (!set_contains(c
->unit_paths
, path
))
2796 /* Check if ActiveState changed to inactive/failed */
2797 /* (s interface, a{sv} changed_properties, as invalidated_properties) */
2798 r
= sd_bus_message_skip(m
, "s");
2800 return bus_log_parse_error(r
);
2802 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "{sv}");
2804 return bus_log_parse_error(r
);
2806 while ((r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
2809 r
= sd_bus_message_read(m
, "s", &s
);
2811 return bus_log_parse_error(r
);
2813 if (streq(s
, "ActiveState")) {
2816 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, "s");
2818 return bus_log_parse_error(r
);
2820 r
= sd_bus_message_read(m
, "s", &s
);
2822 return bus_log_parse_error(r
);
2824 is_failed
= streq(s
, "failed");
2825 if (streq(s
, "inactive") || is_failed
) {
2826 log_debug("%s became %s, dropping from --wait tracking", path
, s
);
2827 free(set_remove(c
->unit_paths
, path
));
2828 c
->any_failed
= c
->any_failed
|| is_failed
;
2830 log_debug("ActiveState on %s changed to %s", path
, s
);
2832 break; /* no need to dissect the rest of the message */
2834 /* other property */
2835 r
= sd_bus_message_skip(m
, "v");
2837 return bus_log_parse_error(r
);
2839 r
= sd_bus_message_exit_container(m
);
2841 return bus_log_parse_error(r
);
2844 return bus_log_parse_error(r
);
2846 if (set_isempty(c
->unit_paths
))
2847 sd_event_exit(c
->event
, EXIT_SUCCESS
);
2852 static int start_unit_one(
2857 sd_bus_error
*error
,
2859 WaitContext
*wait_context
) {
2861 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2871 _cleanup_free_
char *unit_path
= NULL
;
2874 log_debug("Watching for property changes of %s", name
);
2875 r
= sd_bus_call_method(
2877 "org.freedesktop.systemd1",
2878 "/org/freedesktop/systemd1",
2879 "org.freedesktop.systemd1.Manager",
2885 return log_error_errno(r
, "Failed to RefUnit %s: %s", name
, bus_error_message(error
, r
));
2887 unit_path
= unit_dbus_path_from_name(name
);
2891 r
= set_put_strdup(wait_context
->unit_paths
, unit_path
);
2893 return log_error_errno(r
, "Failed to add unit path %s to set: %m", unit_path
);
2895 mt
= strjoina("type='signal',"
2896 "interface='org.freedesktop.DBus.Properties',"
2897 "path='", unit_path
, "',"
2898 "member='PropertiesChanged'");
2899 r
= sd_bus_add_match(bus
, &wait_context
->match
, mt
, on_properties_changed
, wait_context
);
2901 return log_error_errno(r
, "Failed to add match for PropertiesChanged signal: %m");
2904 log_debug("Calling manager for %s on %s, %s", method
, name
, mode
);
2906 r
= sd_bus_call_method(
2908 "org.freedesktop.systemd1",
2909 "/org/freedesktop/systemd1",
2910 "org.freedesktop.systemd1.Manager",
2918 /* There's always a fallback possible for legacy actions. */
2919 if (arg_action
!= ACTION_SYSTEMCTL
)
2922 verb
= method_to_verb(method
);
2924 log_error("Failed to %s %s: %s", verb
, name
, bus_error_message(error
, r
));
2926 if (!sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) &&
2927 !sd_bus_error_has_name(error
, BUS_ERROR_UNIT_MASKED
))
2928 log_error("See %s logs and 'systemctl%s status%s %s' for details.",
2929 arg_scope
== UNIT_FILE_SYSTEM
? "system" : "user",
2930 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user",
2931 name
[0] == '-' ? " --" : "",
2937 r
= sd_bus_message_read(reply
, "o", &path
);
2939 return bus_log_parse_error(r
);
2941 if (need_daemon_reload(bus
, name
) > 0)
2942 warn_unit_file_changed(name
);
2945 log_debug("Adding %s to the set", path
);
2946 r
= bus_wait_for_jobs_add(w
, path
);
2954 static int expand_names(sd_bus
*bus
, char **names
, const char* suffix
, char ***ret
) {
2955 _cleanup_strv_free_
char **mangled
= NULL
, **globs
= NULL
;
2962 STRV_FOREACH(name
, names
) {
2966 r
= unit_name_mangle_with_suffix(*name
, UNIT_NAME_GLOB
, suffix
, &t
);
2968 r
= unit_name_mangle(*name
, UNIT_NAME_GLOB
, &t
);
2970 return log_error_errno(r
, "Failed to mangle name: %m");
2972 if (string_is_glob(t
))
2973 r
= strv_consume(&globs
, t
);
2975 r
= strv_consume(&mangled
, t
);
2980 /* Query the manager only if any of the names are a glob, since
2981 * this is fairly expensive */
2982 if (!strv_isempty(globs
)) {
2983 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2984 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
2985 size_t allocated
, n
;
2987 r
= get_unit_list(bus
, NULL
, globs
, &unit_infos
, 0, &reply
);
2991 n
= strv_length(mangled
);
2994 for (i
= 0; i
< r
; i
++) {
2995 if (!GREEDY_REALLOC(mangled
, allocated
, n
+2))
2998 mangled
[n
] = strdup(unit_infos
[i
].id
);
3002 mangled
[++n
] = NULL
;
3007 mangled
= NULL
; /* do not free */
3012 static const struct {
3016 } action_table
[_ACTION_MAX
] = {
3017 [ACTION_HALT
] = { SPECIAL_HALT_TARGET
, "halt", "replace-irreversibly" },
3018 [ACTION_POWEROFF
] = { SPECIAL_POWEROFF_TARGET
, "poweroff", "replace-irreversibly" },
3019 [ACTION_REBOOT
] = { SPECIAL_REBOOT_TARGET
, "reboot", "replace-irreversibly" },
3020 [ACTION_KEXEC
] = { SPECIAL_KEXEC_TARGET
, "kexec", "replace-irreversibly" },
3021 [ACTION_RUNLEVEL2
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
3022 [ACTION_RUNLEVEL3
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
3023 [ACTION_RUNLEVEL4
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
3024 [ACTION_RUNLEVEL5
] = { SPECIAL_GRAPHICAL_TARGET
, NULL
, "isolate" },
3025 [ACTION_RESCUE
] = { SPECIAL_RESCUE_TARGET
, "rescue", "isolate" },
3026 [ACTION_EMERGENCY
] = { SPECIAL_EMERGENCY_TARGET
, "emergency", "isolate" },
3027 [ACTION_DEFAULT
] = { SPECIAL_DEFAULT_TARGET
, "default", "isolate" },
3028 [ACTION_EXIT
] = { SPECIAL_EXIT_TARGET
, "exit", "replace-irreversibly" },
3029 [ACTION_SUSPEND
] = { SPECIAL_SUSPEND_TARGET
, "suspend", "replace-irreversibly" },
3030 [ACTION_HIBERNATE
] = { SPECIAL_HIBERNATE_TARGET
, "hibernate", "replace-irreversibly" },
3031 [ACTION_HYBRID_SLEEP
] = { SPECIAL_HYBRID_SLEEP_TARGET
, "hybrid-sleep", "replace-irreversibly" },
3034 static enum action
verb_to_action(const char *verb
) {
3037 for (i
= _ACTION_INVALID
; i
< _ACTION_MAX
; i
++)
3038 if (streq_ptr(action_table
[i
].verb
, verb
))
3041 return _ACTION_INVALID
;
3044 static int start_unit(int argc
, char *argv
[], void *userdata
) {
3045 _cleanup_(bus_wait_for_jobs_freep
) BusWaitForJobs
*w
= NULL
;
3046 const char *method
, *mode
, *one_name
, *suffix
= NULL
;
3047 _cleanup_strv_free_
char **names
= NULL
;
3049 _cleanup_(wait_context_free
) WaitContext wait_context
= {};
3053 if (arg_wait
&& !strstr(argv
[0], "start")) {
3054 log_error("--wait may only be used with a command that starts units.");
3058 /* we cannot do sender tracking on the private bus, so we need the full
3059 * one for RefUnit to implement --wait */
3060 r
= acquire_bus(arg_wait
? BUS_FULL
: BUS_MANAGER
, &bus
);
3064 ask_password_agent_open_if_enabled();
3065 polkit_agent_open_if_enabled();
3067 if (arg_action
== ACTION_SYSTEMCTL
) {
3070 method
= verb_to_method(argv
[0]);
3071 action
= verb_to_action(argv
[0]);
3073 if (streq(argv
[0], "isolate")) {
3077 mode
= action_table
[action
].mode
?: arg_job_mode
;
3079 one_name
= action_table
[action
].target
;
3081 assert(arg_action
< ELEMENTSOF(action_table
));
3082 assert(action_table
[arg_action
].target
);
3084 method
= "StartUnit";
3086 mode
= action_table
[arg_action
].mode
;
3087 one_name
= action_table
[arg_action
].target
;
3091 names
= strv_new(one_name
, NULL
);
3093 r
= expand_names(bus
, strv_skip(argv
, 1), suffix
, &names
);
3095 return log_error_errno(r
, "Failed to expand names: %m");
3098 if (!arg_no_block
) {
3099 r
= bus_wait_for_jobs_new(bus
, &w
);
3101 return log_error_errno(r
, "Could not watch jobs: %m");
3105 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3107 wait_context
.unit_paths
= set_new(&string_hash_ops
);
3108 if (!wait_context
.unit_paths
)
3111 r
= sd_bus_call_method(
3113 "org.freedesktop.systemd1",
3114 "/org/freedesktop/systemd1",
3115 "org.freedesktop.systemd1.Manager",
3120 return log_error_errno(r
, "Failed to enable subscription: %s", bus_error_message(&error
, r
));
3121 r
= sd_event_default(&wait_context
.event
);
3123 return log_error_errno(r
, "Failed to allocate event loop: %m");
3124 r
= sd_bus_attach_event(bus
, wait_context
.event
, 0);
3126 return log_error_errno(r
, "Failed to attach bus to event loop: %m");
3129 STRV_FOREACH(name
, names
) {
3130 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3133 q
= start_unit_one(bus
, method
, *name
, mode
, &error
, w
, arg_wait
? &wait_context
: NULL
);
3134 if (r
>= 0 && q
< 0)
3135 r
= translate_bus_error_to_exit_status(q
, &error
);
3138 if (!arg_no_block
) {
3139 int q
, arg_count
= 0;
3140 const char* extra_args
[4] = {};
3142 if (arg_scope
!= UNIT_FILE_SYSTEM
)
3143 extra_args
[arg_count
++] = "--user";
3145 assert(IN_SET(arg_transport
, BUS_TRANSPORT_LOCAL
, BUS_TRANSPORT_REMOTE
, BUS_TRANSPORT_MACHINE
));
3146 if (arg_transport
== BUS_TRANSPORT_REMOTE
) {
3147 extra_args
[arg_count
++] = "-H";
3148 extra_args
[arg_count
++] = arg_host
;
3149 } else if (arg_transport
== BUS_TRANSPORT_MACHINE
) {
3150 extra_args
[arg_count
++] = "-M";
3151 extra_args
[arg_count
++] = arg_host
;
3154 q
= bus_wait_for_jobs(w
, arg_quiet
, extra_args
);
3158 /* When stopping units, warn if they can still be triggered by
3159 * another active unit (socket, path, timer) */
3160 if (!arg_quiet
&& streq(method
, "StopUnit"))
3161 STRV_FOREACH(name
, names
)
3162 check_triggering_units(bus
, *name
);
3165 if (r
>= 0 && arg_wait
) {
3167 q
= sd_event_loop(wait_context
.event
);
3169 return log_error_errno(q
, "Failed to run event loop: %m");
3170 if (wait_context
.any_failed
)
3177 static int logind_set_wall_message(void) {
3179 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3181 _cleanup_free_
char *m
= NULL
;
3184 r
= acquire_bus(BUS_FULL
, &bus
);
3188 m
= strv_join(arg_wall
, " ");
3192 r
= sd_bus_call_method(
3194 "org.freedesktop.login1",
3195 "/org/freedesktop/login1",
3196 "org.freedesktop.login1.Manager",
3205 return log_warning_errno(r
, "Failed to set wall message, ignoring: %s", bus_error_message(&error
, r
));
3211 /* Ask systemd-logind, which might grant access to unprivileged users
3212 * through PolicyKit */
3213 static int logind_reboot(enum action a
) {
3215 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3216 const char *method
, *description
;
3220 r
= acquire_bus(BUS_FULL
, &bus
);
3228 description
= "reboot system";
3231 case ACTION_POWEROFF
:
3232 method
= "PowerOff";
3233 description
= "power off system";
3236 case ACTION_SUSPEND
:
3238 description
= "suspend system";
3241 case ACTION_HIBERNATE
:
3242 method
= "Hibernate";
3243 description
= "hibernate system";
3246 case ACTION_HYBRID_SLEEP
:
3247 method
= "HybridSleep";
3248 description
= "put system into hybrid sleep";
3255 polkit_agent_open_if_enabled();
3256 (void) logind_set_wall_message();
3258 r
= sd_bus_call_method(
3260 "org.freedesktop.login1",
3261 "/org/freedesktop/login1",
3262 "org.freedesktop.login1.Manager",
3266 "b", arg_ask_password
);
3268 return log_error_errno(r
, "Failed to %s via logind: %s", description
, bus_error_message(&error
, r
));
3276 static int logind_check_inhibitors(enum action a
) {
3278 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
3279 _cleanup_strv_free_
char **sessions
= NULL
;
3280 const char *what
, *who
, *why
, *mode
;
3287 if (arg_ignore_inhibitors
|| arg_force
> 0)
3299 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
3302 r
= acquire_bus(BUS_FULL
, &bus
);
3306 r
= sd_bus_call_method(
3308 "org.freedesktop.login1",
3309 "/org/freedesktop/login1",
3310 "org.freedesktop.login1.Manager",
3316 /* If logind is not around, then there are no inhibitors... */
3319 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssuu)");
3321 return bus_log_parse_error(r
);
3323 while ((r
= sd_bus_message_read(reply
, "(ssssuu)", &what
, &who
, &why
, &mode
, &uid
, &pid
)) > 0) {
3324 _cleanup_free_
char *comm
= NULL
, *user
= NULL
;
3325 _cleanup_strv_free_
char **sv
= NULL
;
3327 if (!streq(mode
, "block"))
3330 sv
= strv_split(what
, ":");
3334 if ((pid_t
) pid
< 0)
3335 return log_error_errno(ERANGE
, "Bad PID %"PRIu32
": %m", pid
);
3337 if (!strv_contains(sv
,
3342 ACTION_KEXEC
) ? "shutdown" : "sleep"))
3345 get_process_comm(pid
, &comm
);
3346 user
= uid_to_name(uid
);
3348 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT
" \"%s\", user %s), reason is \"%s\".",
3349 who
, (pid_t
) pid
, strna(comm
), strna(user
), why
);
3354 return bus_log_parse_error(r
);
3356 r
= sd_bus_message_exit_container(reply
);
3358 return bus_log_parse_error(r
);
3360 /* Check for current sessions */
3361 sd_get_sessions(&sessions
);
3362 STRV_FOREACH(s
, sessions
) {
3363 _cleanup_free_
char *type
= NULL
, *tty
= NULL
, *seat
= NULL
, *user
= NULL
, *service
= NULL
, *class = NULL
;
3365 if (sd_session_get_uid(*s
, &uid
) < 0 || uid
== getuid())
3368 if (sd_session_get_class(*s
, &class) < 0 || !streq(class, "user"))
3371 if (sd_session_get_type(*s
, &type
) < 0 || !STR_IN_SET(type
, "x11", "tty"))
3374 sd_session_get_tty(*s
, &tty
);
3375 sd_session_get_seat(*s
, &seat
);
3376 sd_session_get_service(*s
, &service
);
3377 user
= uid_to_name(uid
);
3379 log_warning("User %s is logged in on %s.", strna(user
), isempty(tty
) ? (isempty(seat
) ? strna(service
) : seat
) : tty
);
3386 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
3387 action_table
[a
].verb
);
3395 static int logind_prepare_firmware_setup(void) {
3397 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3401 r
= acquire_bus(BUS_FULL
, &bus
);
3405 r
= sd_bus_call_method(
3407 "org.freedesktop.login1",
3408 "/org/freedesktop/login1",
3409 "org.freedesktop.login1.Manager",
3410 "SetRebootToFirmwareSetup",
3415 return log_error_errno(r
, "Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error
, r
));
3419 log_error("Cannot remotely indicate to EFI to boot into setup mode.");
3424 static int prepare_firmware_setup(void) {
3427 if (!arg_firmware_setup
)
3430 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
3432 r
= efi_set_reboot_to_firmware(true);
3434 log_debug_errno(r
, "Cannot indicate to EFI to boot into setup mode, will retry via logind: %m");
3439 return logind_prepare_firmware_setup();
3442 static int set_exit_code(uint8_t code
) {
3443 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3447 r
= acquire_bus(BUS_MANAGER
, &bus
);
3451 r
= sd_bus_call_method(
3453 "org.freedesktop.systemd1",
3454 "/org/freedesktop/systemd1",
3455 "org.freedesktop.systemd1.Manager",
3461 return log_error_errno(r
, "Failed to set exit code: %s", bus_error_message(&error
, r
));
3466 static int start_special(int argc
, char *argv
[], void *userdata
) {
3472 a
= verb_to_action(argv
[0]);
3474 r
= logind_check_inhibitors(a
);
3478 if (arg_force
>= 2 && geteuid() != 0) {
3479 log_error("Must be root.");
3483 r
= prepare_firmware_setup();
3487 if (a
== ACTION_REBOOT
&& argc
> 1) {
3488 r
= update_reboot_parameter_and_warn(argv
[1]);
3492 } else if (a
== ACTION_EXIT
&& argc
> 1) {
3495 /* If the exit code is not given on the command line,
3496 * don't reset it to zero: just keep it as it might
3497 * have been set previously. */
3499 r
= safe_atou8(argv
[1], &code
);
3501 return log_error_errno(r
, "Invalid exit code.");
3503 r
= set_exit_code(code
);
3508 if (arg_force
>= 2 &&
3515 if (arg_force
>= 1 &&
3522 return trivial_method(argc
, argv
, userdata
);
3524 /* First try logind, to allow authentication with polkit */
3530 ACTION_HYBRID_SLEEP
)) {
3531 r
= logind_reboot(a
);
3534 if (IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
3535 /* requested operation is not supported or already in progress */
3538 /* On all other errors, try low-level operation */
3541 return start_unit(argc
, argv
, userdata
);
3544 static int start_system_special(int argc
, char *argv
[], void *userdata
) {
3545 /* Like start_special above, but raises an error when running in user mode */
3547 if (arg_scope
!= UNIT_FILE_SYSTEM
) {
3548 log_error("Bad action for %s mode.",
3549 arg_scope
== UNIT_FILE_GLOBAL
? "--global" : "--user");
3553 return start_special(argc
, argv
, userdata
);
3556 static int check_unit_generic(int code
, const UnitActiveState good_states
[], int nb_states
, char **args
) {
3557 _cleanup_strv_free_
char **names
= NULL
;
3558 UnitActiveState active_state
;
3564 r
= acquire_bus(BUS_MANAGER
, &bus
);
3568 r
= expand_names(bus
, args
, NULL
, &names
);
3570 return log_error_errno(r
, "Failed to expand names: %m");
3572 STRV_FOREACH(name
, names
) {
3573 r
= get_state_one_unit(bus
, *name
, &active_state
);
3578 puts(unit_active_state_to_string(active_state
));
3580 for (i
= 0; i
< nb_states
; ++i
)
3581 if (good_states
[i
] == active_state
)
3585 /* use the given return code for the case that we won't find
3586 * any unit which matches the list */
3587 return found
? 0 : code
;
3590 static int check_unit_active(int argc
, char *argv
[], void *userdata
) {
3591 const UnitActiveState states
[] = { UNIT_ACTIVE
, UNIT_RELOADING
};
3592 /* According to LSB: 3, "program is not running" */
3593 return check_unit_generic(EXIT_PROGRAM_NOT_RUNNING
, states
, ELEMENTSOF(states
), strv_skip(argv
, 1));
3596 static int check_unit_failed(int argc
, char *argv
[], void *userdata
) {
3597 const UnitActiveState states
[] = { UNIT_FAILED
};
3598 return check_unit_generic(EXIT_PROGRAM_DEAD_AND_PID_EXISTS
, states
, ELEMENTSOF(states
), strv_skip(argv
, 1));
3601 static int kill_unit(int argc
, char *argv
[], void *userdata
) {
3602 _cleanup_strv_free_
char **names
= NULL
;
3603 char *kill_who
= NULL
, **name
;
3607 r
= acquire_bus(BUS_MANAGER
, &bus
);
3611 polkit_agent_open_if_enabled();
3614 arg_kill_who
= "all";
3616 /* --fail was specified */
3617 if (streq(arg_job_mode
, "fail"))
3618 kill_who
= strjoina(arg_kill_who
, "-fail");
3620 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
3622 return log_error_errno(r
, "Failed to expand names: %m");
3624 STRV_FOREACH(name
, names
) {
3625 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3627 q
= sd_bus_call_method(
3629 "org.freedesktop.systemd1",
3630 "/org/freedesktop/systemd1",
3631 "org.freedesktop.systemd1.Manager",
3635 "ssi", *name
, kill_who
? kill_who
: arg_kill_who
, arg_signal
);
3637 log_error_errno(q
, "Failed to kill unit %s: %s", *name
, bus_error_message(&error
, q
));
3646 typedef struct ExecStatusInfo
{
3654 usec_t start_timestamp
;
3655 usec_t exit_timestamp
;
3660 LIST_FIELDS(struct ExecStatusInfo
, exec
);
3663 static void exec_status_info_free(ExecStatusInfo
*i
) {
3672 static int exec_status_info_deserialize(sd_bus_message
*m
, ExecStatusInfo
*i
) {
3673 uint64_t start_timestamp
, exit_timestamp
, start_timestamp_monotonic
, exit_timestamp_monotonic
;
3676 int32_t code
, status
;
3682 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_STRUCT
, "sasbttttuii");
3684 return bus_log_parse_error(r
);
3688 r
= sd_bus_message_read(m
, "s", &path
);
3690 return bus_log_parse_error(r
);
3692 i
->path
= strdup(path
);
3696 r
= sd_bus_message_read_strv(m
, &i
->argv
);
3698 return bus_log_parse_error(r
);
3700 r
= sd_bus_message_read(m
,
3703 &start_timestamp
, &start_timestamp_monotonic
,
3704 &exit_timestamp
, &exit_timestamp_monotonic
,
3708 return bus_log_parse_error(r
);
3711 i
->start_timestamp
= (usec_t
) start_timestamp
;
3712 i
->exit_timestamp
= (usec_t
) exit_timestamp
;
3713 i
->pid
= (pid_t
) pid
;
3717 r
= sd_bus_message_exit_container(m
);
3719 return bus_log_parse_error(r
);
3724 typedef struct UnitCondition
{
3731 LIST_FIELDS(struct UnitCondition
, conditions
);
3734 static void unit_condition_free(UnitCondition
*c
) {
3743 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitCondition
*, unit_condition_free
);
3745 typedef struct UnitStatusInfo
{
3747 const char *load_state
;
3748 const char *active_state
;
3749 const char *sub_state
;
3750 const char *unit_file_state
;
3751 const char *unit_file_preset
;
3753 const char *description
;
3754 const char *following
;
3756 char **documentation
;
3758 const char *fragment_path
;
3759 const char *source_path
;
3760 const char *control_group
;
3762 char **dropin_paths
;
3764 const char *load_error
;
3767 usec_t inactive_exit_timestamp
;
3768 usec_t inactive_exit_timestamp_monotonic
;
3769 usec_t active_enter_timestamp
;
3770 usec_t active_exit_timestamp
;
3771 usec_t inactive_enter_timestamp
;
3773 bool need_daemon_reload
;
3779 const char *status_text
;
3780 const char *pid_file
;
3784 usec_t start_timestamp
;
3785 usec_t exit_timestamp
;
3787 int exit_code
, exit_status
;
3789 usec_t condition_timestamp
;
3790 bool condition_result
;
3791 LIST_HEAD(UnitCondition
, conditions
);
3793 usec_t assert_timestamp
;
3795 bool failed_assert_trigger
;
3796 bool failed_assert_negate
;
3797 const char *failed_assert
;
3798 const char *failed_assert_parameter
;
3801 unsigned n_accepted
;
3802 unsigned n_connections
;
3805 /* Pairs of type, path */
3809 const char *sysfs_path
;
3811 /* Mount, Automount */
3818 uint64_t memory_current
;
3819 uint64_t memory_low
;
3820 uint64_t memory_high
;
3821 uint64_t memory_max
;
3822 uint64_t memory_swap_max
;
3823 uint64_t memory_limit
;
3824 uint64_t cpu_usage_nsec
;
3825 uint64_t tasks_current
;
3828 LIST_HEAD(ExecStatusInfo
, exec
);
3831 static void unit_status_info_free(UnitStatusInfo
*info
) {
3835 strv_free(info
->documentation
);
3836 strv_free(info
->dropin_paths
);
3837 strv_free(info
->listen
);
3839 while ((c
= info
->conditions
)) {
3840 LIST_REMOVE(conditions
, info
->conditions
, c
);
3841 unit_condition_free(c
);
3844 while ((p
= info
->exec
)) {
3845 LIST_REMOVE(exec
, info
->exec
, p
);
3846 exec_status_info_free(p
);
3850 static void print_status_info(
3856 const char *active_on
, *active_off
, *on
, *off
, *ss
;
3858 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], *s1
;
3859 char since2
[FORMAT_TIMESTAMP_MAX
], *s2
;
3866 /* This shows pretty information about a unit. See
3867 * print_property() for a low-level property printer */
3869 if (streq_ptr(i
->active_state
, "failed")) {
3870 active_on
= ansi_highlight_red();
3871 active_off
= ansi_normal();
3872 } else if (STRPTR_IN_SET(i
->active_state
, "active", "reloading")) {
3873 active_on
= ansi_highlight_green();
3874 active_off
= ansi_normal();
3876 active_on
= active_off
= "";
3878 printf("%s%s%s %s", active_on
, special_glyph(BLACK_CIRCLE
), active_off
, strna(i
->id
));
3880 if (i
->description
&& !streq_ptr(i
->id
, i
->description
))
3881 printf(" - %s", i
->description
);
3886 printf(" Follow: unit currently follows state of %s\n", i
->following
);
3888 if (streq_ptr(i
->load_state
, "error")) {
3889 on
= ansi_highlight_red();
3890 off
= ansi_normal();
3894 path
= i
->source_path
? i
->source_path
: i
->fragment_path
;
3896 if (i
->load_error
!= 0)
3897 printf(" Loaded: %s%s%s (Reason: %s)\n",
3898 on
, strna(i
->load_state
), off
, i
->load_error
);
3899 else if (path
&& !isempty(i
->unit_file_state
) && !isempty(i
->unit_file_preset
))
3900 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
3901 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
, i
->unit_file_preset
);
3902 else if (path
&& !isempty(i
->unit_file_state
))
3903 printf(" Loaded: %s%s%s (%s; %s)\n",
3904 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
);
3906 printf(" Loaded: %s%s%s (%s)\n",
3907 on
, strna(i
->load_state
), off
, path
);
3909 printf(" Loaded: %s%s%s\n",
3910 on
, strna(i
->load_state
), off
);
3913 printf("Transient: yes\n");
3915 if (!strv_isempty(i
->dropin_paths
)) {
3916 _cleanup_free_
char *dir
= NULL
;
3920 STRV_FOREACH(dropin
, i
->dropin_paths
) {
3921 if (! dir
|| last
) {
3922 printf(dir
? " " : " Drop-In: ");
3926 dir
= dirname_malloc(*dropin
);
3932 printf("%s\n %s", dir
,
3933 special_glyph(TREE_RIGHT
));
3936 last
= ! (*(dropin
+ 1) && startswith(*(dropin
+ 1), dir
));
3938 printf("%s%s", basename(*dropin
), last
? "\n" : ", ");
3942 ss
= streq_ptr(i
->active_state
, i
->sub_state
) ? NULL
: i
->sub_state
;
3944 printf(" Active: %s%s (%s)%s",
3945 active_on
, strna(i
->active_state
), ss
, active_off
);
3947 printf(" Active: %s%s%s",
3948 active_on
, strna(i
->active_state
), active_off
);
3950 if (!isempty(i
->result
) && !streq(i
->result
, "success"))
3951 printf(" (Result: %s)", i
->result
);
3953 timestamp
= STRPTR_IN_SET(i
->active_state
, "active", "reloading") ? i
->active_enter_timestamp
:
3954 STRPTR_IN_SET(i
->active_state
, "inactive", "failed") ? i
->inactive_enter_timestamp
:
3955 STRPTR_IN_SET(i
->active_state
, "activating") ? i
->inactive_exit_timestamp
:
3956 i
->active_exit_timestamp
;
3958 s1
= format_timestamp_relative(since1
, sizeof(since1
), timestamp
);
3959 s2
= format_timestamp(since2
, sizeof(since2
), timestamp
);
3962 printf(" since %s; %s\n", s2
, s1
);
3964 printf(" since %s\n", s2
);
3968 if (!i
->condition_result
&& i
->condition_timestamp
> 0) {
3972 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->condition_timestamp
);
3973 s2
= format_timestamp(since2
, sizeof(since2
), i
->condition_timestamp
);
3975 printf("Condition: start %scondition failed%s at %s%s%s\n",
3976 ansi_highlight_yellow(), ansi_normal(),
3977 s2
, s1
? "; " : "", strempty(s1
));
3979 LIST_FOREACH(conditions
, c
, i
->conditions
)
3980 if (c
->tristate
< 0)
3983 LIST_FOREACH(conditions
, c
, i
->conditions
)
3984 if (c
->tristate
< 0)
3985 printf(" %s %s=%s%s%s was not met\n",
3986 --n
? special_glyph(TREE_BRANCH
) : special_glyph(TREE_RIGHT
),
3988 c
->trigger
? "|" : "",
3989 c
->negate
? "!" : "",
3993 if (!i
->assert_result
&& i
->assert_timestamp
> 0) {
3994 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->assert_timestamp
);
3995 s2
= format_timestamp(since2
, sizeof(since2
), i
->assert_timestamp
);
3997 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
3998 ansi_highlight_red(), ansi_normal(),
3999 s2
, s1
? "; " : "", strempty(s1
));
4000 if (i
->failed_assert_trigger
)
4001 printf(" none of the trigger assertions were met\n");
4002 else if (i
->failed_assert
)
4003 printf(" %s=%s%s was not met\n",
4005 i
->failed_assert_negate
? "!" : "",
4006 i
->failed_assert_parameter
);
4010 printf(" Device: %s\n", i
->sysfs_path
);
4012 printf(" Where: %s\n", i
->where
);
4014 printf(" What: %s\n", i
->what
);
4016 STRV_FOREACH(t
, i
->documentation
)
4017 printf(" %*s %s\n", 9, t
== i
->documentation
? "Docs:" : "", *t
);
4019 STRV_FOREACH_PAIR(t
, t2
, i
->listen
)
4020 printf(" %*s %s (%s)\n", 9, t
== i
->listen
? "Listen:" : "", *t2
, *t
);
4023 printf(" Accepted: %u; Connected: %u\n", i
->n_accepted
, i
->n_connections
);
4025 LIST_FOREACH(exec
, p
, i
->exec
) {
4026 _cleanup_free_
char *argv
= NULL
;
4029 /* Only show exited processes here */
4033 argv
= strv_join(p
->argv
, " ");
4034 printf(" Process: "PID_FMT
" %s=%s ", p
->pid
, p
->name
, strna(argv
));
4036 good
= is_clean_exit(p
->code
, p
->status
, EXIT_CLEAN_DAEMON
, NULL
);
4038 on
= ansi_highlight_red();
4039 off
= ansi_normal();
4043 printf("%s(code=%s, ", on
, sigchld_code_to_string(p
->code
));
4045 if (p
->code
== CLD_EXITED
) {
4048 printf("status=%i", p
->status
);
4050 c
= exit_status_to_string(p
->status
, EXIT_STATUS_SYSTEMD
);
4055 printf("signal=%s", signal_to_string(p
->status
));
4057 printf(")%s\n", off
);
4059 if (i
->main_pid
== p
->pid
&&
4060 i
->start_timestamp
== p
->start_timestamp
&&
4061 i
->exit_timestamp
== p
->start_timestamp
)
4062 /* Let's not show this twice */
4065 if (p
->pid
== i
->control_pid
)
4069 if (i
->main_pid
> 0 || i
->control_pid
> 0) {
4070 if (i
->main_pid
> 0) {
4071 printf(" Main PID: "PID_FMT
, i
->main_pid
);
4074 _cleanup_free_
char *comm
= NULL
;
4075 (void) get_process_comm(i
->main_pid
, &comm
);
4077 printf(" (%s)", comm
);
4078 } else if (i
->exit_code
> 0) {
4079 printf(" (code=%s, ", sigchld_code_to_string(i
->exit_code
));
4081 if (i
->exit_code
== CLD_EXITED
) {
4084 printf("status=%i", i
->exit_status
);
4086 c
= exit_status_to_string(i
->exit_status
, EXIT_STATUS_SYSTEMD
);
4091 printf("signal=%s", signal_to_string(i
->exit_status
));
4096 if (i
->control_pid
> 0) {
4097 _cleanup_free_
char *c
= NULL
;
4099 if (i
->main_pid
> 0)
4100 fputs("; Control PID: ", stdout
);
4102 fputs("Cntrl PID: ", stdout
); /* if first in column, abbreviated so it fits alignment */
4104 printf(PID_FMT
, i
->control_pid
);
4106 (void) get_process_comm(i
->control_pid
, &c
);
4115 printf(" Status: \"%s\"\n", i
->status_text
);
4116 if (i
->status_errno
> 0)
4117 printf(" Error: %i (%s)\n", i
->status_errno
, strerror(i
->status_errno
));
4119 if (i
->tasks_current
!= (uint64_t) -1) {
4120 printf(" Tasks: %" PRIu64
, i
->tasks_current
);
4122 if (i
->tasks_max
!= (uint64_t) -1)
4123 printf(" (limit: %" PRIu64
")\n", i
->tasks_max
);
4128 if (i
->memory_current
!= (uint64_t) -1) {
4129 char buf
[FORMAT_BYTES_MAX
];
4131 printf(" Memory: %s", format_bytes(buf
, sizeof(buf
), i
->memory_current
));
4133 if (i
->memory_low
> 0 || i
->memory_high
!= CGROUP_LIMIT_MAX
||
4134 i
->memory_max
!= CGROUP_LIMIT_MAX
|| i
->memory_swap_max
!= CGROUP_LIMIT_MAX
||
4135 i
->memory_limit
!= CGROUP_LIMIT_MAX
) {
4136 const char *prefix
= "";
4139 if (i
->memory_low
> 0) {
4140 printf("%slow: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_low
));
4143 if (i
->memory_high
!= CGROUP_LIMIT_MAX
) {
4144 printf("%shigh: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_high
));
4147 if (i
->memory_max
!= CGROUP_LIMIT_MAX
) {
4148 printf("%smax: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_max
));
4151 if (i
->memory_swap_max
!= CGROUP_LIMIT_MAX
) {
4152 printf("%sswap max: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_swap_max
));
4155 if (i
->memory_limit
!= CGROUP_LIMIT_MAX
) {
4156 printf("%slimit: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_limit
));
4164 if (i
->cpu_usage_nsec
!= (uint64_t) -1) {
4165 char buf
[FORMAT_TIMESPAN_MAX
];
4166 printf(" CPU: %s\n", format_timespan(buf
, sizeof(buf
), i
->cpu_usage_nsec
/ NSEC_PER_USEC
, USEC_PER_MSEC
));
4169 if (i
->control_group
) {
4170 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
4171 static const char prefix
[] = " ";
4174 printf(" CGroup: %s\n", i
->control_group
);
4177 if (c
> sizeof(prefix
) - 1)
4178 c
-= sizeof(prefix
) - 1;
4182 r
= unit_show_processes(bus
, i
->id
, i
->control_group
, prefix
, c
, get_output_flags(), &error
);
4187 /* Fallback for older systemd versions where the GetUnitProcesses() call is not yet available */
4189 if (i
->main_pid
> 0)
4190 extra
[k
++] = i
->main_pid
;
4192 if (i
->control_pid
> 0)
4193 extra
[k
++] = i
->control_pid
;
4195 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, prefix
, c
, extra
, k
, get_output_flags());
4197 log_warning_errno(r
, "Failed to dump process list, ignoring: %s", bus_error_message(&error
, r
));
4200 if (i
->id
&& arg_transport
== BUS_TRANSPORT_LOCAL
)
4201 show_journal_by_unit(
4206 i
->inactive_exit_timestamp_monotonic
,
4209 get_output_flags() | OUTPUT_BEGIN_NEWLINE
,
4210 SD_JOURNAL_LOCAL_ONLY
,
4211 arg_scope
== UNIT_FILE_SYSTEM
,
4214 if (i
->need_daemon_reload
)
4215 warn_unit_file_changed(i
->id
);
4218 static void show_unit_help(UnitStatusInfo
*i
) {
4223 if (!i
->documentation
) {
4224 log_info("Documentation for %s not known.", i
->id
);
4228 STRV_FOREACH(p
, i
->documentation
)
4229 if (startswith(*p
, "man:"))
4230 show_man_page(*p
+ 4, false);
4232 log_info("Can't show: %s", *p
);
4235 static int status_property(const char *name
, sd_bus_message
*m
, UnitStatusInfo
*i
, const char *contents
) {
4242 switch (contents
[0]) {
4244 case SD_BUS_TYPE_STRING
: {
4247 r
= sd_bus_message_read(m
, "s", &s
);
4249 return bus_log_parse_error(r
);
4252 if (streq(name
, "Id"))
4254 else if (streq(name
, "LoadState"))
4256 else if (streq(name
, "ActiveState"))
4257 i
->active_state
= s
;
4258 else if (streq(name
, "SubState"))
4260 else if (streq(name
, "Description"))
4262 else if (streq(name
, "FragmentPath"))
4263 i
->fragment_path
= s
;
4264 else if (streq(name
, "SourcePath"))
4267 else if (streq(name
, "DefaultControlGroup")) {
4269 e
= startswith(s
, SYSTEMD_CGROUP_CONTROLLER
":");
4271 i
->control_group
= e
;
4274 else if (streq(name
, "ControlGroup"))
4275 i
->control_group
= s
;
4276 else if (streq(name
, "StatusText"))
4278 else if (streq(name
, "PIDFile"))
4280 else if (streq(name
, "SysFSPath"))
4282 else if (streq(name
, "Where"))
4284 else if (streq(name
, "What"))
4286 else if (streq(name
, "Following"))
4288 else if (streq(name
, "UnitFileState"))
4289 i
->unit_file_state
= s
;
4290 else if (streq(name
, "UnitFilePreset"))
4291 i
->unit_file_preset
= s
;
4292 else if (streq(name
, "Result"))
4299 case SD_BUS_TYPE_BOOLEAN
: {
4302 r
= sd_bus_message_read(m
, "b", &b
);
4304 return bus_log_parse_error(r
);
4306 if (streq(name
, "Accept"))
4308 else if (streq(name
, "NeedDaemonReload"))
4309 i
->need_daemon_reload
= b
;
4310 else if (streq(name
, "ConditionResult"))
4311 i
->condition_result
= b
;
4312 else if (streq(name
, "AssertResult"))
4313 i
->assert_result
= b
;
4314 else if (streq(name
, "Transient"))
4320 case SD_BUS_TYPE_UINT32
: {
4323 r
= sd_bus_message_read(m
, "u", &u
);
4325 return bus_log_parse_error(r
);
4327 if (streq(name
, "MainPID")) {
4329 i
->main_pid
= (pid_t
) u
;
4332 } else if (streq(name
, "ControlPID"))
4333 i
->control_pid
= (pid_t
) u
;
4334 else if (streq(name
, "ExecMainPID")) {
4336 i
->main_pid
= (pid_t
) u
;
4337 } else if (streq(name
, "NAccepted"))
4339 else if (streq(name
, "NConnections"))
4340 i
->n_connections
= u
;
4345 case SD_BUS_TYPE_INT32
: {
4348 r
= sd_bus_message_read(m
, "i", &j
);
4350 return bus_log_parse_error(r
);
4352 if (streq(name
, "ExecMainCode"))
4353 i
->exit_code
= (int) j
;
4354 else if (streq(name
, "ExecMainStatus"))
4355 i
->exit_status
= (int) j
;
4356 else if (streq(name
, "StatusErrno"))
4357 i
->status_errno
= (int) j
;
4362 case SD_BUS_TYPE_UINT64
: {
4365 r
= sd_bus_message_read(m
, "t", &u
);
4367 return bus_log_parse_error(r
);
4369 if (streq(name
, "ExecMainStartTimestamp"))
4370 i
->start_timestamp
= (usec_t
) u
;
4371 else if (streq(name
, "ExecMainExitTimestamp"))
4372 i
->exit_timestamp
= (usec_t
) u
;
4373 else if (streq(name
, "ActiveEnterTimestamp"))
4374 i
->active_enter_timestamp
= (usec_t
) u
;
4375 else if (streq(name
, "InactiveEnterTimestamp"))
4376 i
->inactive_enter_timestamp
= (usec_t
) u
;
4377 else if (streq(name
, "InactiveExitTimestamp"))
4378 i
->inactive_exit_timestamp
= (usec_t
) u
;
4379 else if (streq(name
, "InactiveExitTimestampMonotonic"))
4380 i
->inactive_exit_timestamp_monotonic
= (usec_t
) u
;
4381 else if (streq(name
, "ActiveExitTimestamp"))
4382 i
->active_exit_timestamp
= (usec_t
) u
;
4383 else if (streq(name
, "ConditionTimestamp"))
4384 i
->condition_timestamp
= (usec_t
) u
;
4385 else if (streq(name
, "AssertTimestamp"))
4386 i
->assert_timestamp
= (usec_t
) u
;
4387 else if (streq(name
, "MemoryCurrent"))
4388 i
->memory_current
= u
;
4389 else if (streq(name
, "MemoryLow"))
4391 else if (streq(name
, "MemoryHigh"))
4393 else if (streq(name
, "MemoryMax"))
4395 else if (streq(name
, "MemorySwapMax"))
4396 i
->memory_swap_max
= u
;
4397 else if (streq(name
, "MemoryLimit"))
4398 i
->memory_limit
= u
;
4399 else if (streq(name
, "TasksCurrent"))
4400 i
->tasks_current
= u
;
4401 else if (streq(name
, "TasksMax"))
4403 else if (streq(name
, "CPUUsageNSec"))
4404 i
->cpu_usage_nsec
= u
;
4409 case SD_BUS_TYPE_ARRAY
:
4411 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
4412 _cleanup_free_ ExecStatusInfo
*info
= NULL
;
4414 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4416 return bus_log_parse_error(r
);
4418 info
= new0(ExecStatusInfo
, 1);
4422 while ((r
= exec_status_info_deserialize(m
, info
)) > 0) {
4424 info
->name
= strdup(name
);
4428 LIST_PREPEND(exec
, i
->exec
, info
);
4430 info
= new0(ExecStatusInfo
, 1);
4436 return bus_log_parse_error(r
);
4438 r
= sd_bus_message_exit_container(m
);
4440 return bus_log_parse_error(r
);
4444 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
4445 const char *type
, *path
;
4447 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4449 return bus_log_parse_error(r
);
4451 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0) {
4453 r
= strv_extend(&i
->listen
, type
);
4457 r
= strv_extend(&i
->listen
, path
);
4462 return bus_log_parse_error(r
);
4464 r
= sd_bus_message_exit_container(m
);
4466 return bus_log_parse_error(r
);
4470 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "DropInPaths")) {
4472 r
= sd_bus_message_read_strv(m
, &i
->dropin_paths
);
4474 return bus_log_parse_error(r
);
4476 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Documentation")) {
4478 r
= sd_bus_message_read_strv(m
, &i
->documentation
);
4480 return bus_log_parse_error(r
);
4482 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Conditions")) {
4483 const char *cond
, *param
;
4484 int trigger
, negate
;
4487 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
4489 return bus_log_parse_error(r
);
4491 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
4492 _cleanup_(unit_condition_freep
) UnitCondition
*c
= NULL
;
4494 log_debug("%s trigger=%d negate=%d %s →%d", cond
, trigger
, negate
, param
, state
);
4496 c
= new0(UnitCondition
, 1);
4500 c
->name
= strdup(cond
);
4501 c
->param
= strdup(param
);
4502 if (!c
->name
|| !c
->param
)
4505 c
->trigger
= trigger
;
4507 c
->tristate
= state
;
4509 LIST_PREPEND(conditions
, i
->conditions
, c
);
4513 return bus_log_parse_error(r
);
4515 r
= sd_bus_message_exit_container(m
);
4517 return bus_log_parse_error(r
);
4519 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Asserts")) {
4520 const char *cond
, *param
;
4521 int trigger
, negate
;
4524 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
4526 return bus_log_parse_error(r
);
4528 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
4529 log_debug("%s %d %d %s %d", cond
, trigger
, negate
, param
, state
);
4530 if (state
< 0 && (!trigger
|| !i
->failed_assert
)) {
4531 i
->failed_assert
= cond
;
4532 i
->failed_assert_trigger
= trigger
;
4533 i
->failed_assert_negate
= negate
;
4534 i
->failed_assert_parameter
= param
;
4538 return bus_log_parse_error(r
);
4540 r
= sd_bus_message_exit_container(m
);
4542 return bus_log_parse_error(r
);
4549 case SD_BUS_TYPE_STRUCT_BEGIN
:
4551 if (streq(name
, "LoadError")) {
4552 const char *n
, *message
;
4554 r
= sd_bus_message_read(m
, "(ss)", &n
, &message
);
4556 return bus_log_parse_error(r
);
4558 if (!isempty(message
))
4559 i
->load_error
= message
;
4572 r
= sd_bus_message_skip(m
, contents
);
4574 return bus_log_parse_error(r
);
4579 #define print_prop(name, fmt, ...) \
4582 printf(fmt "\n", __VA_ARGS__); \
4584 printf("%s=" fmt "\n", name, __VA_ARGS__); \
4587 static int print_property(const char *name
, sd_bus_message
*m
, const char *contents
) {
4593 /* This is a low-level property printer, see
4594 * print_status_info() for the nicer output */
4596 if (arg_properties
&& !strv_find(arg_properties
, name
)) {
4597 /* skip what we didn't read */
4598 r
= sd_bus_message_skip(m
, contents
);
4602 switch (contents
[0]) {
4604 case SD_BUS_TYPE_STRUCT_BEGIN
:
4606 if (contents
[1] == SD_BUS_TYPE_UINT32
&& streq(name
, "Job")) {
4609 r
= sd_bus_message_read(m
, "(uo)", &u
, NULL
);
4611 return bus_log_parse_error(r
);
4614 print_prop(name
, "%"PRIu32
, u
);
4616 print_prop(name
, "%s", "");
4620 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Unit")) {
4623 r
= sd_bus_message_read(m
, "(so)", &s
, NULL
);
4625 return bus_log_parse_error(r
);
4627 if (arg_all
|| !isempty(s
))
4628 print_prop(name
, "%s", s
);
4632 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "LoadError")) {
4633 const char *a
= NULL
, *b
= NULL
;
4635 r
= sd_bus_message_read(m
, "(ss)", &a
, &b
);
4637 return bus_log_parse_error(r
);
4639 if (arg_all
|| !isempty(a
) || !isempty(b
))
4640 print_prop(name
, "%s \"%s\"", strempty(a
), strempty(b
));
4643 } else if (streq_ptr(name
, "SystemCallFilter")) {
4644 _cleanup_strv_free_
char **l
= NULL
;
4647 r
= sd_bus_message_enter_container(m
, 'r', "bas");
4649 return bus_log_parse_error(r
);
4651 r
= sd_bus_message_read(m
, "b", &whitelist
);
4653 return bus_log_parse_error(r
);
4655 r
= sd_bus_message_read_strv(m
, &l
);
4657 return bus_log_parse_error(r
);
4659 r
= sd_bus_message_exit_container(m
);
4661 return bus_log_parse_error(r
);
4663 if (arg_all
|| whitelist
|| !strv_isempty(l
)) {
4668 fputs(name
, stdout
);
4675 STRV_FOREACH(i
, l
) {
4683 fputc('\n', stdout
);
4691 case SD_BUS_TYPE_ARRAY
:
4693 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "EnvironmentFiles")) {
4697 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sb)");
4699 return bus_log_parse_error(r
);
4701 while ((r
= sd_bus_message_read(m
, "(sb)", &path
, &ignore
)) > 0)
4702 print_prop("EnvironmentFile", "%s (ignore_errors=%s)", path
, yes_no(ignore
));
4705 return bus_log_parse_error(r
);
4707 r
= sd_bus_message_exit_container(m
);
4709 return bus_log_parse_error(r
);
4713 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Paths")) {
4714 const char *type
, *path
;
4716 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4718 return bus_log_parse_error(r
);
4720 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4721 print_prop(type
, "%s", path
);
4723 return bus_log_parse_error(r
);
4725 r
= sd_bus_message_exit_container(m
);
4727 return bus_log_parse_error(r
);
4731 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
4732 const char *type
, *path
;
4734 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4736 return bus_log_parse_error(r
);
4738 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4742 printf("Listen%s=%s\n", type
, path
);
4744 return bus_log_parse_error(r
);
4746 r
= sd_bus_message_exit_container(m
);
4748 return bus_log_parse_error(r
);
4752 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Timers")) {
4754 uint64_t value
, next_elapse
;
4756 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(stt)");
4758 return bus_log_parse_error(r
);
4760 while ((r
= sd_bus_message_read(m
, "(stt)", &base
, &value
, &next_elapse
)) > 0) {
4761 char timespan1
[FORMAT_TIMESPAN_MAX
], timespan2
[FORMAT_TIMESPAN_MAX
];
4763 print_prop(base
, "{ value=%s ; next_elapse=%s }",
4764 format_timespan(timespan1
, sizeof(timespan1
), value
, 0),
4765 format_timespan(timespan2
, sizeof(timespan2
), next_elapse
, 0));
4768 return bus_log_parse_error(r
);
4770 r
= sd_bus_message_exit_container(m
);
4772 return bus_log_parse_error(r
);
4776 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
4777 ExecStatusInfo info
= {};
4779 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4781 return bus_log_parse_error(r
);
4783 while ((r
= exec_status_info_deserialize(m
, &info
)) > 0) {
4784 char timestamp1
[FORMAT_TIMESTAMP_MAX
], timestamp2
[FORMAT_TIMESTAMP_MAX
];
4785 _cleanup_free_
char *tt
;
4787 tt
= strv_join(info
.argv
, " ");
4790 "{ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT
" ; code=%s ; status=%i%s%s }",
4793 yes_no(info
.ignore
),
4794 strna(format_timestamp(timestamp1
, sizeof(timestamp1
), info
.start_timestamp
)),
4795 strna(format_timestamp(timestamp2
, sizeof(timestamp2
), info
.exit_timestamp
)),
4797 sigchld_code_to_string(info
.code
),
4799 info
.code
== CLD_EXITED
? "" : "/",
4800 strempty(info
.code
== CLD_EXITED
? NULL
: signal_to_string(info
.status
)));
4803 strv_free(info
.argv
);
4807 r
= sd_bus_message_exit_container(m
);
4809 return bus_log_parse_error(r
);
4813 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "DeviceAllow")) {
4814 const char *path
, *rwm
;
4816 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4818 return bus_log_parse_error(r
);
4820 while ((r
= sd_bus_message_read(m
, "(ss)", &path
, &rwm
)) > 0)
4821 print_prop(name
, "%s %s", strna(path
), strna(rwm
));
4823 return bus_log_parse_error(r
);
4825 r
= sd_bus_message_exit_container(m
);
4827 return bus_log_parse_error(r
);
4831 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&&
4832 STR_IN_SET(name
, "IODeviceWeight", "BlockIODeviceWeight")) {
4836 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4838 return bus_log_parse_error(r
);
4840 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &weight
)) > 0)
4841 print_prop(name
, "%s %"PRIu64
, strna(path
), weight
);
4843 return bus_log_parse_error(r
);
4845 r
= sd_bus_message_exit_container(m
);
4847 return bus_log_parse_error(r
);
4851 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&&
4852 (cgroup_io_limit_type_from_string(name
) >= 0 ||
4853 STR_IN_SET(name
, "BlockIOReadBandwidth", "BlockIOWriteBandwidth"))) {
4857 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4859 return bus_log_parse_error(r
);
4861 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &bandwidth
)) > 0)
4862 print_prop(name
, "%s %"PRIu64
, strna(path
), bandwidth
);
4864 return bus_log_parse_error(r
);
4866 r
= sd_bus_message_exit_container(m
);
4868 return bus_log_parse_error(r
);
4876 r
= bus_print_property(name
, m
, arg_value
, arg_all
);
4878 return bus_log_parse_error(r
);
4881 r
= sd_bus_message_skip(m
, contents
);
4883 return bus_log_parse_error(r
);
4886 printf("%s=[unprintable]\n", name
);
4892 static int show_one(
4897 bool show_properties
,
4901 static const struct bus_properties_map property_map
[] = {
4902 { "LoadState", "s", map_string_no_copy
, offsetof(UnitStatusInfo
, load_state
) },
4903 { "ActiveState", "s", map_string_no_copy
, offsetof(UnitStatusInfo
, active_state
) },
4907 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
4908 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
4909 _cleanup_set_free_ Set
*found_properties
= NULL
;
4910 _cleanup_(unit_status_info_free
) UnitStatusInfo info
= {
4911 .memory_current
= (uint64_t) -1,
4912 .memory_high
= CGROUP_LIMIT_MAX
,
4913 .memory_max
= CGROUP_LIMIT_MAX
,
4914 .memory_swap_max
= CGROUP_LIMIT_MAX
,
4915 .memory_limit
= (uint64_t) -1,
4916 .cpu_usage_nsec
= (uint64_t) -1,
4917 .tasks_current
= (uint64_t) -1,
4918 .tasks_max
= (uint64_t) -1,
4925 log_debug("Showing one %s", path
);
4927 r
= sd_bus_call_method(
4929 "org.freedesktop.systemd1",
4931 "org.freedesktop.DBus.Properties",
4937 return log_error_errno(r
, "Failed to get properties: %s", bus_error_message(&error
, r
));
4940 r
= bus_message_map_all_properties(reply
, property_map
, &info
);
4942 return log_error_errno(r
, "Failed to map properties: %s", bus_error_message(&error
, r
));
4944 if (streq_ptr(info
.load_state
, "not-found") && streq_ptr(info
.active_state
, "inactive")) {
4945 log_full(streq(verb
, "status") ? LOG_ERR
: LOG_DEBUG
,
4946 "Unit %s could not be found.", unit
);
4948 if (streq(verb
, "status"))
4949 return EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN
;
4951 if (!streq(verb
, "show"))
4955 r
= sd_bus_message_rewind(reply
, true);
4957 return log_error_errno(r
, "Failed to rewind: %s", bus_error_message(&error
, r
));
4960 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
4962 return bus_log_parse_error(r
);
4969 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
4970 const char *name
, *contents
;
4972 r
= sd_bus_message_read(reply
, "s", &name
);
4974 return bus_log_parse_error(r
);
4976 r
= sd_bus_message_peek_type(reply
, NULL
, &contents
);
4978 return bus_log_parse_error(r
);
4980 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, contents
);
4982 return bus_log_parse_error(r
);
4984 if (show_properties
) {
4985 r
= set_ensure_allocated(&found_properties
, &string_hash_ops
);
4989 r
= set_put(found_properties
, name
);
4990 if (r
< 0 && r
!= EEXIST
)
4993 r
= print_property(name
, reply
, contents
);
4995 r
= status_property(name
, reply
, &info
, contents
);
4999 r
= sd_bus_message_exit_container(reply
);
5001 return bus_log_parse_error(r
);
5003 r
= sd_bus_message_exit_container(reply
);
5005 return bus_log_parse_error(r
);
5008 return bus_log_parse_error(r
);
5010 r
= sd_bus_message_exit_container(reply
);
5012 return bus_log_parse_error(r
);
5015 if (show_properties
) {
5017 int not_found_level
= streq(verb
, "show") ? LOG_DEBUG
: LOG_WARNING
;
5019 STRV_FOREACH(pp
, arg_properties
)
5020 if (!set_contains(found_properties
, *pp
)) {
5021 log_full(not_found_level
, "Property %s does not exist.", *pp
);
5025 } else if (streq(verb
, "help"))
5026 show_unit_help(&info
);
5027 else if (streq(verb
, "status")) {
5028 print_status_info(bus
, &info
, ellipsized
);
5030 if (info
.active_state
&& !STR_IN_SET(info
.active_state
, "active", "reloading"))
5031 r
= EXIT_PROGRAM_NOT_RUNNING
;
5033 r
= EXIT_PROGRAM_RUNNING_OR_SERVICE_OK
;
5039 static int get_unit_dbus_path_by_pid(
5044 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5045 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5049 r
= sd_bus_call_method(
5051 "org.freedesktop.systemd1",
5052 "/org/freedesktop/systemd1",
5053 "org.freedesktop.systemd1.Manager",
5059 return log_error_errno(r
, "Failed to get unit for PID %"PRIu32
": %s", pid
, bus_error_message(&error
, r
));
5061 r
= sd_bus_message_read(reply
, "o", &u
);
5063 return bus_log_parse_error(r
);
5073 static int show_all(
5076 bool show_properties
,
5080 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5081 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
5086 r
= get_unit_list(bus
, NULL
, NULL
, &unit_infos
, 0, &reply
);
5090 pager_open(arg_no_pager
, false);
5094 qsort_safe(unit_infos
, c
, sizeof(UnitInfo
), compare_unit_info
);
5096 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
5097 _cleanup_free_
char *p
= NULL
;
5099 p
= unit_dbus_path_from_name(u
->id
);
5103 r
= show_one(verb
, bus
, p
, u
->id
, show_properties
, new_line
, ellipsized
);
5106 else if (r
> 0 && ret
== 0)
5113 static int show_system_status(sd_bus
*bus
) {
5114 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], since2
[FORMAT_TIMESTAMP_MAX
];
5115 _cleanup_free_
char *hn
= NULL
;
5116 _cleanup_(machine_info_clear
) struct machine_info mi
= {};
5117 const char *on
, *off
;
5120 hn
= gethostname_malloc();
5124 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, &mi
);
5126 return log_error_errno(r
, "Failed to read server status: %m");
5128 if (streq_ptr(mi
.state
, "degraded")) {
5129 on
= ansi_highlight_red();
5130 off
= ansi_normal();
5131 } else if (!streq_ptr(mi
.state
, "running")) {
5132 on
= ansi_highlight_yellow();
5133 off
= ansi_normal();
5137 printf("%s%s%s %s\n", on
, special_glyph(BLACK_CIRCLE
), off
, arg_host
? arg_host
: hn
);
5139 printf(" State: %s%s%s\n",
5140 on
, strna(mi
.state
), off
);
5142 printf(" Jobs: %" PRIu32
" queued\n", mi
.n_jobs
);
5143 printf(" Failed: %" PRIu32
" units\n", mi
.n_failed_units
);
5145 printf(" Since: %s; %s\n",
5146 format_timestamp(since2
, sizeof(since2
), mi
.timestamp
),
5147 format_timestamp_relative(since1
, sizeof(since1
), mi
.timestamp
));
5149 printf(" CGroup: %s\n", mi
.control_group
?: "/");
5150 if (IN_SET(arg_transport
,
5151 BUS_TRANSPORT_LOCAL
,
5152 BUS_TRANSPORT_MACHINE
)) {
5153 static const char prefix
[] = " ";
5157 if (c
> sizeof(prefix
) - 1)
5158 c
-= sizeof(prefix
) - 1;
5162 show_cgroup(SYSTEMD_CGROUP_CONTROLLER
, strempty(mi
.control_group
), prefix
, c
, get_output_flags());
5168 static int show(int argc
, char *argv
[], void *userdata
) {
5169 bool show_properties
, show_status
, show_help
, new_line
= false;
5170 bool ellipsized
= false;
5176 show_properties
= streq(argv
[0], "show");
5177 show_status
= streq(argv
[0], "status");
5178 show_help
= streq(argv
[0], "help");
5180 if (show_help
&& argc
<= 1) {
5181 log_error("This command expects one or more unit names. Did you mean --help?");
5185 r
= acquire_bus(BUS_MANAGER
, &bus
);
5189 pager_open(arg_no_pager
, false);
5192 /* Increase max number of open files to 16K if we can, we
5193 * might needs this when browsing journal files, which might
5194 * be split up into many files. */
5195 setrlimit_closest(RLIMIT_NOFILE
, &RLIMIT_MAKE_CONST(16384));
5197 /* If no argument is specified inspect the manager itself */
5198 if (show_properties
&& argc
<= 1)
5199 return show_one(argv
[0], bus
, "/org/freedesktop/systemd1", NULL
, show_properties
, &new_line
, &ellipsized
);
5201 if (show_status
&& argc
<= 1) {
5203 show_system_status(bus
);
5207 ret
= show_all(argv
[0], bus
, false, &new_line
, &ellipsized
);
5209 _cleanup_free_
char **patterns
= NULL
;
5212 STRV_FOREACH(name
, strv_skip(argv
, 1)) {
5213 _cleanup_free_
char *path
= NULL
, *unit
= NULL
;
5216 if (safe_atou32(*name
, &id
) < 0) {
5217 if (strv_push(&patterns
, *name
) < 0)
5221 } else if (show_properties
) {
5222 /* Interpret as job id */
5223 if (asprintf(&path
, "/org/freedesktop/systemd1/job/%u", id
) < 0)
5227 /* Interpret as PID */
5228 r
= get_unit_dbus_path_by_pid(bus
, id
, &path
);
5234 r
= unit_name_from_dbus_path(path
, &unit
);
5239 r
= show_one(argv
[0], bus
, path
, unit
, show_properties
, &new_line
, &ellipsized
);
5242 else if (r
> 0 && ret
== 0)
5246 if (!strv_isempty(patterns
)) {
5247 _cleanup_strv_free_
char **names
= NULL
;
5249 r
= expand_names(bus
, patterns
, NULL
, &names
);
5251 return log_error_errno(r
, "Failed to expand names: %m");
5253 STRV_FOREACH(name
, names
) {
5254 _cleanup_free_
char *path
;
5256 path
= unit_dbus_path_from_name(*name
);
5260 r
= show_one(argv
[0], bus
, path
, *name
, show_properties
, &new_line
, &ellipsized
);
5263 if (r
> 0 && ret
== 0)
5269 if (ellipsized
&& !arg_quiet
)
5270 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
5275 static int cat_file(const char *filename
, bool newline
) {
5276 _cleanup_close_
int fd
;
5278 fd
= open(filename
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
5282 printf("%s%s# %s%s\n",
5283 newline
? "\n" : "",
5284 ansi_highlight_blue(),
5289 return copy_bytes(fd
, STDOUT_FILENO
, (uint64_t) -1, false);
5292 static int cat(int argc
, char *argv
[], void *userdata
) {
5293 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
5294 _cleanup_strv_free_
char **names
= NULL
;
5300 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
5301 log_error("Cannot remotely cat units.");
5305 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
5307 return log_error_errno(r
, "Failed to determine unit paths: %m");
5309 r
= acquire_bus(BUS_MANAGER
, &bus
);
5313 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
5315 return log_error_errno(r
, "Failed to expand names: %m");
5317 pager_open(arg_no_pager
, false);
5319 STRV_FOREACH(name
, names
) {
5320 _cleanup_free_
char *fragment_path
= NULL
;
5321 _cleanup_strv_free_
char **dropin_paths
= NULL
;
5324 r
= unit_find_paths(bus
, *name
, &lp
, &fragment_path
, &dropin_paths
);
5335 if (need_daemon_reload(bus
, *name
) > 0) /* ignore errors (<0), this is informational output */
5337 "%s# Warning: %s changed on disk, the version systemd has loaded is outdated.\n"
5338 "%s# This output shows the current version of the unit's original fragment and drop-in files.\n"
5339 "%s# If fragments or drop-ins were added or removed, they are not properly reflected in this output.\n"
5340 "%s# Run 'systemctl%s daemon-reload' to reload units.%s\n",
5341 ansi_highlight_red(),
5343 ansi_highlight_red(),
5344 ansi_highlight_red(),
5345 ansi_highlight_red(),
5346 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user",
5349 if (fragment_path
) {
5350 r
= cat_file(fragment_path
, false);
5352 return log_warning_errno(r
, "Failed to cat %s: %m", fragment_path
);
5355 STRV_FOREACH(path
, dropin_paths
) {
5356 r
= cat_file(*path
, path
== dropin_paths
);
5358 return log_warning_errno(r
, "Failed to cat %s: %m", *path
);
5365 static int set_property(int argc
, char *argv
[], void *userdata
) {
5366 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5367 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5368 _cleanup_free_
char *n
= NULL
;
5372 r
= acquire_bus(BUS_MANAGER
, &bus
);
5376 polkit_agent_open_if_enabled();
5378 r
= sd_bus_message_new_method_call(
5381 "org.freedesktop.systemd1",
5382 "/org/freedesktop/systemd1",
5383 "org.freedesktop.systemd1.Manager",
5384 "SetUnitProperties");
5386 return bus_log_create_error(r
);
5388 r
= unit_name_mangle(argv
[1], UNIT_NAME_NOGLOB
, &n
);
5390 return log_error_errno(r
, "Failed to mangle unit name: %m");
5392 r
= sd_bus_message_append(m
, "sb", n
, arg_runtime
);
5394 return bus_log_create_error(r
);
5396 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, "(sv)");
5398 return bus_log_create_error(r
);
5400 r
= bus_append_unit_property_assignment_many(m
, strv_skip(argv
, 2));
5404 r
= sd_bus_message_close_container(m
);
5406 return bus_log_create_error(r
);
5408 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5410 return log_error_errno(r
, "Failed to set unit properties on %s: %s", n
, bus_error_message(&error
, r
));
5415 static int daemon_reload(int argc
, char *argv
[], void *userdata
) {
5416 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5417 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5422 r
= acquire_bus(BUS_MANAGER
, &bus
);
5426 polkit_agent_open_if_enabled();
5428 switch (arg_action
) {
5435 method
= "Reexecute";
5438 case ACTION_SYSTEMCTL
:
5439 method
= streq(argv
[0], "daemon-reexec") ? "Reexecute" :
5440 /* "daemon-reload" */ "Reload";
5444 assert_not_reached("Unexpected action");
5447 r
= sd_bus_message_new_method_call(
5450 "org.freedesktop.systemd1",
5451 "/org/freedesktop/systemd1",
5452 "org.freedesktop.systemd1.Manager",
5455 return bus_log_create_error(r
);
5457 /* Note we use an extra-long timeout here. This is because a reload or reexec means generators are rerun which
5458 * are timed out after DEFAULT_TIMEOUT_USEC. Let's use twice that time here, so that the generators can have
5459 * their timeout, and for everything else there's the same time budget in place. */
5461 r
= sd_bus_call(bus
, m
, DEFAULT_TIMEOUT_USEC
* 2, &error
, NULL
);
5463 /* On reexecution, we expect a disconnect, not a reply */
5464 if (IN_SET(r
, -ETIMEDOUT
, -ECONNRESET
) && streq(method
, "Reexecute"))
5467 if (r
< 0 && arg_action
== ACTION_SYSTEMCTL
)
5468 return log_error_errno(r
, "Failed to reload daemon: %s", bus_error_message(&error
, r
));
5470 /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
5471 * old ways of doing things, hence don't log any error in that case here. */
5473 return r
< 0 ? r
: 0;
5476 static int trivial_method(int argc
, char *argv
[], void *userdata
) {
5477 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5482 r
= acquire_bus(BUS_MANAGER
, &bus
);
5486 polkit_agent_open_if_enabled();
5489 streq(argv
[0], "clear-jobs") ||
5490 streq(argv
[0], "cancel") ? "ClearJobs" :
5491 streq(argv
[0], "reset-failed") ? "ResetFailed" :
5492 streq(argv
[0], "halt") ? "Halt" :
5493 streq(argv
[0], "reboot") ? "Reboot" :
5494 streq(argv
[0], "kexec") ? "KExec" :
5495 streq(argv
[0], "exit") ? "Exit" :
5496 /* poweroff */ "PowerOff";
5498 r
= sd_bus_call_method(
5500 "org.freedesktop.systemd1",
5501 "/org/freedesktop/systemd1",
5502 "org.freedesktop.systemd1.Manager",
5507 if (r
< 0 && arg_action
== ACTION_SYSTEMCTL
)
5508 return log_error_errno(r
, "Failed to execute operation: %s", bus_error_message(&error
, r
));
5510 /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
5511 * old ways of doing things, hence don't log any error in that case here. */
5513 return r
< 0 ? r
: 0;
5516 static int reset_failed(int argc
, char *argv
[], void *userdata
) {
5517 _cleanup_strv_free_
char **names
= NULL
;
5523 return trivial_method(argc
, argv
, userdata
);
5525 r
= acquire_bus(BUS_MANAGER
, &bus
);
5529 polkit_agent_open_if_enabled();
5531 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
5533 return log_error_errno(r
, "Failed to expand names: %m");
5535 STRV_FOREACH(name
, names
) {
5536 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5538 q
= sd_bus_call_method(
5540 "org.freedesktop.systemd1",
5541 "/org/freedesktop/systemd1",
5542 "org.freedesktop.systemd1.Manager",
5548 log_error_errno(q
, "Failed to reset failed state of unit %s: %s", *name
, bus_error_message(&error
, q
));
5557 static int show_environment(int argc
, char *argv
[], void *userdata
) {
5558 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5559 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5564 r
= acquire_bus(BUS_MANAGER
, &bus
);
5568 pager_open(arg_no_pager
, false);
5570 r
= sd_bus_get_property(
5572 "org.freedesktop.systemd1",
5573 "/org/freedesktop/systemd1",
5574 "org.freedesktop.systemd1.Manager",
5580 return log_error_errno(r
, "Failed to get environment: %s", bus_error_message(&error
, r
));
5582 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
5584 return bus_log_parse_error(r
);
5586 while ((r
= sd_bus_message_read_basic(reply
, SD_BUS_TYPE_STRING
, &text
)) > 0)
5589 return bus_log_parse_error(r
);
5591 r
= sd_bus_message_exit_container(reply
);
5593 return bus_log_parse_error(r
);
5598 static int switch_root(int argc
, char *argv
[], void *userdata
) {
5599 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5600 _cleanup_free_
char *cmdline_init
= NULL
;
5601 const char *root
, *init
;
5605 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
5606 log_error("Cannot switch root remotely.");
5610 if (argc
< 2 || argc
> 3) {
5611 log_error("Wrong number of arguments.");
5620 r
= parse_env_file("/proc/cmdline", WHITESPACE
,
5621 "init", &cmdline_init
,
5624 log_debug_errno(r
, "Failed to parse /proc/cmdline: %m");
5626 init
= cmdline_init
;
5629 init
= empty_to_null(init
);
5631 const char *root_systemd_path
= NULL
, *root_init_path
= NULL
;
5633 root_systemd_path
= strjoina(root
, "/" SYSTEMD_BINARY_PATH
);
5634 root_init_path
= strjoina(root
, "/", init
);
5636 /* If the passed init is actually the same as the
5637 * systemd binary, then let's suppress it. */
5638 if (files_same(root_init_path
, root_systemd_path
) > 0)
5642 /* Instruct PID1 to exclude us from its killing spree applied during
5643 * the transition from the initrd to the main system otherwise we would
5644 * exit with a failure status even though the switch to the new root
5647 argv_cmdline
[0] = '@';
5649 r
= acquire_bus(BUS_MANAGER
, &bus
);
5653 log_debug("Switching root - root: %s; init: %s", root
, strna(init
));
5655 r
= sd_bus_call_method(
5657 "org.freedesktop.systemd1",
5658 "/org/freedesktop/systemd1",
5659 "org.freedesktop.systemd1.Manager",
5665 return log_error_errno(r
, "Failed to switch root: %s", bus_error_message(&error
, r
));
5670 static int set_environment(int argc
, char *argv
[], void *userdata
) {
5671 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5672 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5680 r
= acquire_bus(BUS_MANAGER
, &bus
);
5684 polkit_agent_open_if_enabled();
5686 method
= streq(argv
[0], "set-environment")
5688 : "UnsetEnvironment";
5690 r
= sd_bus_message_new_method_call(
5693 "org.freedesktop.systemd1",
5694 "/org/freedesktop/systemd1",
5695 "org.freedesktop.systemd1.Manager",
5698 return bus_log_create_error(r
);
5700 r
= sd_bus_message_append_strv(m
, strv_skip(argv
, 1));
5702 return bus_log_create_error(r
);
5704 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5706 return log_error_errno(r
, "Failed to set environment: %s", bus_error_message(&error
, r
));
5711 static int import_environment(int argc
, char *argv
[], void *userdata
) {
5712 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5713 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5717 r
= acquire_bus(BUS_MANAGER
, &bus
);
5721 polkit_agent_open_if_enabled();
5723 r
= sd_bus_message_new_method_call(
5726 "org.freedesktop.systemd1",
5727 "/org/freedesktop/systemd1",
5728 "org.freedesktop.systemd1.Manager",
5731 return bus_log_create_error(r
);
5734 r
= sd_bus_message_append_strv(m
, environ
);
5738 r
= sd_bus_message_open_container(m
, 'a', "s");
5740 return bus_log_create_error(r
);
5742 STRV_FOREACH(a
, strv_skip(argv
, 1)) {
5744 if (!env_name_is_valid(*a
)) {
5745 log_error("Not a valid environment variable name: %s", *a
);
5749 STRV_FOREACH(b
, environ
) {
5752 eq
= startswith(*b
, *a
);
5753 if (eq
&& *eq
== '=') {
5755 r
= sd_bus_message_append(m
, "s", *b
);
5757 return bus_log_create_error(r
);
5764 r
= sd_bus_message_close_container(m
);
5767 return bus_log_create_error(r
);
5769 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5771 return log_error_errno(r
, "Failed to import environment: %s", bus_error_message(&error
, r
));
5776 static int enable_sysv_units(const char *verb
, char **args
) {
5779 #if defined(HAVE_SYSV_COMPAT)
5780 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
5783 /* Processes all SysV units, and reshuffles the array so that afterwards only the native units remain */
5785 if (arg_scope
!= UNIT_FILE_SYSTEM
)
5788 if (getenv_bool("SYSTEMCTL_SKIP_SYSV") > 0)
5791 if (!STR_IN_SET(verb
,
5797 r
= lookup_paths_init(&paths
, arg_scope
, LOOKUP_PATHS_EXCLUDE_GENERATED
, arg_root
);
5804 const char *argv
[] = {
5805 ROOTLIBEXECDIR
"/systemd-sysv-install",
5812 _cleanup_free_
char *p
= NULL
, *q
= NULL
, *l
= NULL
;
5813 bool found_native
= false, found_sysv
;
5822 if (!endswith(name
, ".service"))
5825 if (path_is_absolute(name
))
5828 j
= unit_file_exists(arg_scope
, &paths
, name
);
5829 if (j
< 0 && !IN_SET(j
, -ELOOP
, -ERFKILL
, -EADDRNOTAVAIL
))
5830 return log_error_errno(j
, "Failed to lookup unit file state: %m");
5831 found_native
= j
!= 0;
5833 /* If we have both a native unit and a SysV script, enable/disable them both (below); for is-enabled,
5834 * prefer the native unit */
5835 if (found_native
&& streq(verb
, "is-enabled"))
5838 p
= path_join(arg_root
, SYSTEM_SYSVINIT_PATH
, name
);
5842 p
[strlen(p
) - strlen(".service")] = 0;
5843 found_sysv
= access(p
, F_OK
) >= 0;
5849 log_info("Synchronizing state of %s with SysV service script with %s.", name
, argv
[0]);
5851 log_info("%s is not a native service, redirecting to systemd-sysv-install.", name
);
5854 if (!isempty(arg_root
))
5855 argv
[c
++] = q
= strappend("--root=", arg_root
);
5858 argv
[c
++] = basename(p
);
5861 l
= strv_join((char**)argv
, " ");
5865 log_info("Executing: %s", l
);
5869 return log_error_errno(errno
, "Failed to fork: %m");
5870 else if (pid
== 0) {
5873 (void) reset_all_signal_handlers();
5874 (void) reset_signal_mask();
5876 execv(argv
[0], (char**) argv
);
5877 log_error_errno(errno
, "Failed to execute %s: %m", argv
[0]);
5878 _exit(EXIT_FAILURE
);
5881 j
= wait_for_terminate(pid
, &status
);
5883 return log_error_errno(j
, "Failed to wait for child: %m");
5885 if (status
.si_code
== CLD_EXITED
) {
5886 if (streq(verb
, "is-enabled")) {
5887 if (status
.si_status
== 0) {
5896 } else if (status
.si_status
!= 0)
5897 return -EBADE
; /* We don't warn here, under the assumption the script already showed an explanation */
5899 log_error("Unexpected waitid() result.");
5906 /* Remove this entry, so that we don't try enabling it as native unit */
5909 assert(args
[f
] == name
);
5910 strv_remove(args
, name
);
5917 static int mangle_names(char **original_names
, char ***mangled_names
) {
5918 char **i
, **l
, **name
;
5921 l
= i
= new(char*, strv_length(original_names
) + 1);
5925 STRV_FOREACH(name
, original_names
) {
5927 /* When enabling units qualified path names are OK,
5928 * too, hence allow them explicitly. */
5930 if (is_path(*name
)) {
5937 r
= unit_name_mangle(*name
, UNIT_NAME_NOGLOB
, i
);
5940 return log_error_errno(r
, "Failed to mangle unit name: %m");
5953 static int normalize_names(char **names
, bool warn_if_path
) {
5955 bool was_path
= false;
5957 STRV_FOREACH(u
, names
) {
5963 r
= free_and_strdup(u
, basename(*u
));
5965 return log_error_errno(r
, "Failed to normalize unit file path: %m");
5970 if (warn_if_path
&& was_path
)
5971 log_warning("Warning: Can't execute disable on the unit file path. Proceeding with the unit name.");
5976 static int unit_exists(const char *unit
) {
5977 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5978 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5979 _cleanup_free_
char *path
= NULL
;
5980 static const struct bus_properties_map property_map
[] = {
5981 { "LoadState", "s", map_string_no_copy
, offsetof(UnitStatusInfo
, load_state
) },
5982 { "ActiveState", "s", map_string_no_copy
, offsetof(UnitStatusInfo
, active_state
)},
5985 UnitStatusInfo info
= {};
5989 path
= unit_dbus_path_from_name(unit
);
5993 r
= acquire_bus(BUS_MANAGER
, &bus
);
5997 r
= sd_bus_call_method(
5999 "org.freedesktop.systemd1",
6001 "org.freedesktop.DBus.Properties",
6007 return log_error_errno(r
, "Failed to get properties: %s", bus_error_message(&error
, r
));
6009 r
= bus_message_map_all_properties(reply
, property_map
, &info
);
6011 return log_error_errno(r
, "Failed to map properties: %s", bus_error_message(&error
, r
));
6013 return !streq_ptr(info
.load_state
, "not-found") || !streq_ptr(info
.active_state
, "inactive");
6016 static int enable_unit(int argc
, char *argv
[], void *userdata
) {
6017 _cleanup_strv_free_
char **names
= NULL
;
6018 const char *verb
= argv
[0];
6019 UnitFileChange
*changes
= NULL
;
6020 unsigned n_changes
= 0;
6021 int carries_install_info
= -1;
6022 bool ignore_carries_install_info
= arg_quiet
;
6028 r
= mangle_names(strv_skip(argv
, 1), &names
);
6032 r
= enable_sysv_units(verb
, names
);
6036 /* If the operation was fully executed by the SysV compat, let's finish early */
6037 if (strv_isempty(names
)) {
6038 if (arg_no_reload
|| install_client_side())
6040 return daemon_reload(argc
, argv
, userdata
);
6043 if (streq(verb
, "disable")) {
6044 r
= normalize_names(names
, true);
6049 if (install_client_side()) {
6050 UnitFileFlags flags
;
6052 flags
= args_to_flags();
6053 if (streq(verb
, "enable")) {
6054 r
= unit_file_enable(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6055 carries_install_info
= r
;
6056 } else if (streq(verb
, "disable"))
6057 r
= unit_file_disable(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6058 else if (streq(verb
, "reenable")) {
6059 r
= unit_file_reenable(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6060 carries_install_info
= r
;
6061 } else if (streq(verb
, "link"))
6062 r
= unit_file_link(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6063 else if (streq(verb
, "preset")) {
6064 r
= unit_file_preset(arg_scope
, flags
, arg_root
, names
, arg_preset_mode
, &changes
, &n_changes
);
6065 } else if (streq(verb
, "mask"))
6066 r
= unit_file_mask(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6067 else if (streq(verb
, "unmask"))
6068 r
= unit_file_unmask(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6069 else if (streq(verb
, "revert"))
6070 r
= unit_file_revert(arg_scope
, arg_root
, names
, &changes
, &n_changes
);
6072 assert_not_reached("Unknown verb");
6074 unit_file_dump_changes(r
, verb
, changes
, n_changes
, arg_quiet
);
6079 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
, *m
= NULL
;
6080 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6081 bool expect_carries_install_info
= false;
6082 bool send_runtime
= true, send_force
= true, send_preset_mode
= false;
6086 if (STR_IN_SET(verb
, "mask", "unmask")) {
6087 r
= unit_exists(*names
);
6091 log_notice("Unit %s does not exist, proceeding anyway.", *names
);
6094 r
= acquire_bus(BUS_MANAGER
, &bus
);
6098 polkit_agent_open_if_enabled();
6100 if (streq(verb
, "enable")) {
6101 method
= "EnableUnitFiles";
6102 expect_carries_install_info
= true;
6103 } else if (streq(verb
, "disable")) {
6104 method
= "DisableUnitFiles";
6106 } else if (streq(verb
, "reenable")) {
6107 method
= "ReenableUnitFiles";
6108 expect_carries_install_info
= true;
6109 } else if (streq(verb
, "link"))
6110 method
= "LinkUnitFiles";
6111 else if (streq(verb
, "preset")) {
6113 if (arg_preset_mode
!= UNIT_FILE_PRESET_FULL
) {
6114 method
= "PresetUnitFilesWithMode";
6115 send_preset_mode
= true;
6117 method
= "PresetUnitFiles";
6119 expect_carries_install_info
= true;
6120 ignore_carries_install_info
= true;
6121 } else if (streq(verb
, "mask"))
6122 method
= "MaskUnitFiles";
6123 else if (streq(verb
, "unmask")) {
6124 method
= "UnmaskUnitFiles";
6126 } else if (streq(verb
, "revert")) {
6127 method
= "RevertUnitFiles";
6128 send_runtime
= send_force
= false;
6130 assert_not_reached("Unknown verb");
6132 r
= sd_bus_message_new_method_call(
6135 "org.freedesktop.systemd1",
6136 "/org/freedesktop/systemd1",
6137 "org.freedesktop.systemd1.Manager",
6140 return bus_log_create_error(r
);
6142 r
= sd_bus_message_append_strv(m
, names
);
6144 return bus_log_create_error(r
);
6146 if (send_preset_mode
) {
6147 r
= sd_bus_message_append(m
, "s", unit_file_preset_mode_to_string(arg_preset_mode
));
6149 return bus_log_create_error(r
);
6153 r
= sd_bus_message_append(m
, "b", arg_runtime
);
6155 return bus_log_create_error(r
);
6159 r
= sd_bus_message_append(m
, "b", arg_force
);
6161 return bus_log_create_error(r
);
6164 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
6166 return log_error_errno(r
, "Failed to %s unit: %s", verb
, bus_error_message(&error
, r
));
6168 if (expect_carries_install_info
) {
6169 r
= sd_bus_message_read(reply
, "b", &carries_install_info
);
6171 return bus_log_parse_error(r
);
6174 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
6178 /* Try to reload if enabled */
6180 r
= daemon_reload(argc
, argv
, userdata
);
6185 if (carries_install_info
== 0 && !ignore_carries_install_info
)
6186 log_warning("The unit files have no installation config (WantedBy, RequiredBy, Also, Alias\n"
6187 "settings in the [Install] section, and DefaultInstance for template units).\n"
6188 "This means they are not meant to be enabled using systemctl.\n"
6189 "Possible reasons for having this kind of units are:\n"
6190 "1) A unit may be statically enabled by being symlinked from another unit's\n"
6191 " .wants/ or .requires/ directory.\n"
6192 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
6193 " a requirement dependency on it.\n"
6194 "3) A unit may be started when needed via activation (socket, path, timer,\n"
6195 " D-Bus, udev, scripted systemctl call, ...).\n"
6196 "4) In case of template units, the unit is meant to be enabled with some\n"
6197 " instance name specified.");
6199 if (arg_now
&& n_changes
> 0 && STR_IN_SET(argv
[0], "enable", "disable", "mask")) {
6200 char *new_args
[n_changes
+ 2];
6204 r
= acquire_bus(BUS_MANAGER
, &bus
);
6208 new_args
[0] = (char*) (streq(argv
[0], "enable") ? "start" : "stop");
6209 for (i
= 0; i
< n_changes
; i
++)
6210 new_args
[i
+ 1] = basename(changes
[i
].path
);
6211 new_args
[i
+ 1] = NULL
;
6213 r
= start_unit(strv_length(new_args
), new_args
, userdata
);
6217 unit_file_changes_free(changes
, n_changes
);
6222 static int add_dependency(int argc
, char *argv
[], void *userdata
) {
6223 _cleanup_strv_free_
char **names
= NULL
;
6224 _cleanup_free_
char *target
= NULL
;
6225 const char *verb
= argv
[0];
6226 UnitFileChange
*changes
= NULL
;
6227 unsigned n_changes
= 0;
6234 r
= unit_name_mangle_with_suffix(argv
[1], UNIT_NAME_NOGLOB
, ".target", &target
);
6236 return log_error_errno(r
, "Failed to mangle unit name: %m");
6238 r
= mangle_names(strv_skip(argv
, 2), &names
);
6242 if (streq(verb
, "add-wants"))
6244 else if (streq(verb
, "add-requires"))
6245 dep
= UNIT_REQUIRES
;
6247 assert_not_reached("Unknown verb");
6249 if (install_client_side()) {
6250 r
= unit_file_add_dependency(arg_scope
, args_to_flags(), arg_root
, names
, target
, dep
, &changes
, &n_changes
);
6251 unit_file_dump_changes(r
, "add dependency on", changes
, n_changes
, arg_quiet
);
6256 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
, *m
= NULL
;
6257 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6260 r
= acquire_bus(BUS_MANAGER
, &bus
);
6264 polkit_agent_open_if_enabled();
6266 r
= sd_bus_message_new_method_call(
6269 "org.freedesktop.systemd1",
6270 "/org/freedesktop/systemd1",
6271 "org.freedesktop.systemd1.Manager",
6272 "AddDependencyUnitFiles");
6274 return bus_log_create_error(r
);
6276 r
= sd_bus_message_append_strv(m
, names
);
6278 return bus_log_create_error(r
);
6280 r
= sd_bus_message_append(m
, "ssbb", target
, unit_dependency_to_string(dep
), arg_runtime
, arg_force
);
6282 return bus_log_create_error(r
);
6284 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
6286 return log_error_errno(r
, "Failed to add dependency: %s", bus_error_message(&error
, r
));
6288 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
6292 if (arg_no_reload
) {
6297 r
= daemon_reload(argc
, argv
, userdata
);
6301 unit_file_changes_free(changes
, n_changes
);
6306 static int preset_all(int argc
, char *argv
[], void *userdata
) {
6307 UnitFileChange
*changes
= NULL
;
6308 unsigned n_changes
= 0;
6311 if (install_client_side()) {
6312 r
= unit_file_preset_all(arg_scope
, args_to_flags(), arg_root
, arg_preset_mode
, &changes
, &n_changes
);
6313 unit_file_dump_changes(r
, "preset", changes
, n_changes
, arg_quiet
);
6318 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6319 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6322 r
= acquire_bus(BUS_MANAGER
, &bus
);
6326 polkit_agent_open_if_enabled();
6328 r
= sd_bus_call_method(
6330 "org.freedesktop.systemd1",
6331 "/org/freedesktop/systemd1",
6332 "org.freedesktop.systemd1.Manager",
6333 "PresetAllUnitFiles",
6337 unit_file_preset_mode_to_string(arg_preset_mode
),
6341 return log_error_errno(r
, "Failed to preset all units: %s", bus_error_message(&error
, r
));
6343 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
6347 if (arg_no_reload
) {
6352 r
= daemon_reload(argc
, argv
, userdata
);
6356 unit_file_changes_free(changes
, n_changes
);
6361 static int show_installation_targets_client_side(const char *name
) {
6362 UnitFileChange
*changes
= NULL
;
6363 unsigned n_changes
= 0, i
;
6364 UnitFileFlags flags
;
6368 p
= STRV_MAKE(name
);
6369 flags
= UNIT_FILE_DRY_RUN
|
6370 (arg_runtime
? UNIT_FILE_RUNTIME
: 0);
6372 r
= unit_file_disable(UNIT_FILE_SYSTEM
, flags
, NULL
, p
, &changes
, &n_changes
);
6374 return log_error_errno(r
, "Failed to get file links for %s: %m", name
);
6376 for (i
= 0; i
< n_changes
; i
++)
6377 if (changes
[i
].type
== UNIT_FILE_UNLINK
)
6378 printf(" %s\n", changes
[i
].path
);
6383 static int show_installation_targets(sd_bus
*bus
, const char *name
) {
6384 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6385 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6389 r
= sd_bus_call_method(
6391 "org.freedesktop.systemd1",
6392 "/org/freedesktop/systemd1",
6393 "org.freedesktop.systemd1.Manager",
6397 "sb", name
, arg_runtime
);
6399 return log_error_errno(r
, "Failed to get unit file links for %s: %s", name
, bus_error_message(&error
, r
));
6401 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
6403 return bus_log_parse_error(r
);
6405 while ((r
= sd_bus_message_read(reply
, "s", &link
)) > 0)
6406 printf(" %s\n", link
);
6409 return bus_log_parse_error(r
);
6411 r
= sd_bus_message_exit_container(reply
);
6413 return bus_log_parse_error(r
);
6418 static int unit_is_enabled(int argc
, char *argv
[], void *userdata
) {
6420 _cleanup_strv_free_
char **names
= NULL
;
6425 r
= mangle_names(strv_skip(argv
, 1), &names
);
6429 r
= enable_sysv_units(argv
[0], names
);
6435 if (install_client_side()) {
6436 STRV_FOREACH(name
, names
) {
6437 UnitFileState state
;
6439 r
= unit_file_get_state(arg_scope
, arg_root
, *name
, &state
);
6441 return log_error_errno(r
, "Failed to get unit file state for %s: %m", *name
);
6445 UNIT_FILE_ENABLED_RUNTIME
,
6448 UNIT_FILE_GENERATED
))
6452 puts(unit_file_state_to_string(state
));
6454 r
= show_installation_targets_client_side(*name
);
6463 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6466 r
= acquire_bus(BUS_MANAGER
, &bus
);
6470 STRV_FOREACH(name
, names
) {
6471 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6474 r
= sd_bus_call_method(
6476 "org.freedesktop.systemd1",
6477 "/org/freedesktop/systemd1",
6478 "org.freedesktop.systemd1.Manager",
6484 return log_error_errno(r
, "Failed to get unit file state for %s: %s", *name
, bus_error_message(&error
, r
));
6486 r
= sd_bus_message_read(reply
, "s", &s
);
6488 return bus_log_parse_error(r
);
6490 if (STR_IN_SET(s
, "enabled", "enabled-runtime", "static", "indirect", "generated"))
6496 r
= show_installation_targets(bus
, *name
);
6504 return enabled
? EXIT_SUCCESS
: EXIT_FAILURE
;
6507 static int is_system_running(int argc
, char *argv
[], void *userdata
) {
6508 _cleanup_free_
char *state
= NULL
;
6512 if (running_in_chroot() > 0 || (arg_transport
== BUS_TRANSPORT_LOCAL
&& !sd_booted())) {
6515 return EXIT_FAILURE
;
6518 r
= acquire_bus(BUS_MANAGER
, &bus
);
6522 r
= sd_bus_get_property_string(
6524 "org.freedesktop.systemd1",
6525 "/org/freedesktop/systemd1",
6526 "org.freedesktop.systemd1.Manager",
6539 return streq(state
, "running") ? EXIT_SUCCESS
: EXIT_FAILURE
;
6542 static int create_edit_temp_file(const char *new_path
, const char *original_path
, char **ret_tmp_fn
) {
6543 _cleanup_free_
char *t
= NULL
;
6547 assert(original_path
);
6550 r
= tempfn_random(new_path
, NULL
, &t
);
6552 return log_error_errno(r
, "Failed to determine temporary filename for \"%s\": %m", new_path
);
6554 r
= mkdir_parents(new_path
, 0755);
6556 return log_error_errno(r
, "Failed to create directories for \"%s\": %m", new_path
);
6558 r
= copy_file(original_path
, t
, 0, 0644, 0);
6563 return log_error_errno(r
, "Failed to create temporary file \"%s\": %m", t
);
6566 return log_error_errno(r
, "Failed to create temporary file for \"%s\": %m", new_path
);
6574 static int get_file_to_edit(
6575 const LookupPaths
*paths
,
6579 _cleanup_free_
char *path
= NULL
, *run
= NULL
;
6584 path
= strjoin(paths
->persistent_config
, "/", name
);
6589 run
= strjoin(paths
->runtime_config
, "/", name
);
6595 if (access(path
, F_OK
) >= 0) {
6596 log_error("Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.", run
, path
);
6610 static int unit_file_create_new(
6611 const LookupPaths
*paths
,
6612 const char *unit_name
,
6614 char **ret_new_path
,
6615 char **ret_tmp_path
) {
6617 char *tmp_new_path
, *tmp_tmp_path
, *ending
;
6621 assert(ret_new_path
);
6622 assert(ret_tmp_path
);
6624 ending
= strjoina(unit_name
, suffix
);
6625 r
= get_file_to_edit(paths
, ending
, &tmp_new_path
);
6629 r
= create_edit_temp_file(tmp_new_path
, tmp_new_path
, &tmp_tmp_path
);
6635 *ret_new_path
= tmp_new_path
;
6636 *ret_tmp_path
= tmp_tmp_path
;
6641 static int unit_file_create_copy(
6642 const LookupPaths
*paths
,
6643 const char *unit_name
,
6644 const char *fragment_path
,
6645 char **ret_new_path
,
6646 char **ret_tmp_path
) {
6648 char *tmp_new_path
, *tmp_tmp_path
;
6651 assert(fragment_path
);
6653 assert(ret_new_path
);
6654 assert(ret_tmp_path
);
6656 r
= get_file_to_edit(paths
, unit_name
, &tmp_new_path
);
6660 if (!path_equal(fragment_path
, tmp_new_path
) && access(tmp_new_path
, F_OK
) == 0) {
6663 r
= ask_char(&response
, "yn", "\"%s\" already exists. Overwrite with \"%s\"? [(y)es, (n)o] ", tmp_new_path
, fragment_path
);
6668 if (response
!= 'y') {
6669 log_warning("%s ignored", unit_name
);
6671 return -EKEYREJECTED
;
6675 r
= create_edit_temp_file(tmp_new_path
, fragment_path
, &tmp_tmp_path
);
6681 *ret_new_path
= tmp_new_path
;
6682 *ret_tmp_path
= tmp_tmp_path
;
6687 static int run_editor(char **paths
) {
6695 return log_error_errno(errno
, "Failed to fork: %m");
6699 char *editor
, **editor_args
= NULL
;
6700 char **tmp_path
, **original_path
, *p
;
6701 unsigned n_editor_args
= 0, i
= 1;
6704 (void) reset_all_signal_handlers();
6705 (void) reset_signal_mask();
6707 argc
= strv_length(paths
)/2 + 1;
6709 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
6710 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
6711 * we try to execute well known editors
6713 editor
= getenv("SYSTEMD_EDITOR");
6715 editor
= getenv("EDITOR");
6717 editor
= getenv("VISUAL");
6719 if (!isempty(editor
)) {
6720 editor_args
= strv_split(editor
, WHITESPACE
);
6723 _exit(EXIT_FAILURE
);
6725 n_editor_args
= strv_length(editor_args
);
6726 argc
+= n_editor_args
- 1;
6728 args
= newa(const char*, argc
+ 1);
6730 if (n_editor_args
> 0) {
6731 args
[0] = editor_args
[0];
6732 for (; i
< n_editor_args
; i
++)
6733 args
[i
] = editor_args
[i
];
6736 STRV_FOREACH_PAIR(original_path
, tmp_path
, paths
) {
6737 args
[i
] = *tmp_path
;
6742 if (n_editor_args
> 0)
6743 execvp(args
[0], (char* const*) args
);
6745 FOREACH_STRING(p
, "editor", "nano", "vim", "vi") {
6747 execvp(p
, (char* const*) args
);
6748 /* We do not fail if the editor doesn't exist
6749 * because we want to try each one of them before
6752 if (errno
!= ENOENT
) {
6753 log_error_errno(errno
, "Failed to execute %s: %m", editor
);
6754 _exit(EXIT_FAILURE
);
6758 log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR, $EDITOR or $VISUAL.");
6759 _exit(EXIT_FAILURE
);
6762 r
= wait_for_terminate_and_warn("editor", pid
, true);
6764 return log_error_errno(r
, "Failed to wait for child: %m");
6769 static int find_paths_to_edit(sd_bus
*bus
, char **names
, char ***paths
) {
6770 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
6777 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
6781 STRV_FOREACH(name
, names
) {
6782 _cleanup_free_
char *path
= NULL
, *new_path
= NULL
, *tmp_path
= NULL
;
6784 r
= unit_find_paths(bus
, *name
, &lp
, &path
, NULL
);
6787 else if (!arg_force
) {
6789 log_error("Run 'systemctl edit --force %s' to create a new unit.", *name
);
6792 // FIXME: support units with path==NULL (no FragmentPath)
6793 log_error("No fragment exists for %s.", *name
);
6800 r
= unit_file_create_copy(&lp
, basename(path
), path
, &new_path
, &tmp_path
);
6802 r
= unit_file_create_new(&lp
, basename(path
), ".d/override.conf", &new_path
, &tmp_path
);
6804 r
= unit_file_create_new(&lp
, *name
, NULL
, &new_path
, &tmp_path
);
6808 r
= strv_push_pair(paths
, new_path
, tmp_path
);
6811 new_path
= tmp_path
= NULL
;
6817 static int edit(int argc
, char *argv
[], void *userdata
) {
6818 _cleanup_strv_free_
char **names
= NULL
;
6819 _cleanup_strv_free_
char **paths
= NULL
;
6820 char **original
, **tmp
;
6825 log_error("Cannot edit units if not on a tty.");
6829 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
6830 log_error("Cannot edit units remotely.");
6834 r
= acquire_bus(BUS_MANAGER
, &bus
);
6838 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
6840 return log_error_errno(r
, "Failed to expand names: %m");
6842 r
= find_paths_to_edit(bus
, names
, &paths
);
6846 if (strv_isempty(paths
))
6849 r
= run_editor(paths
);
6853 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
6854 /* If the temporary file is empty we ignore it. It's
6855 * useful if the user wants to cancel its modification
6857 if (null_or_empty_path(*tmp
)) {
6858 log_warning("Editing \"%s\" canceled: temporary file is empty.", *original
);
6862 r
= rename(*tmp
, *original
);
6864 r
= log_error_errno(errno
, "Failed to rename \"%s\" to \"%s\": %m", *tmp
, *original
);
6871 if (!arg_no_reload
&& !install_client_side())
6872 r
= daemon_reload(argc
, argv
, userdata
);
6875 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
6876 (void) unlink(*tmp
);
6878 /* Removing empty dropin dirs */
6880 _cleanup_free_
char *dir
;
6882 dir
= dirname_malloc(*original
);
6886 /* no need to check if the dir is empty, rmdir
6887 * does nothing if it is not the case.
6896 static void systemctl_help(void) {
6898 pager_open(arg_no_pager
, false);
6900 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
6901 "Query or send control commands to the systemd manager.\n\n"
6902 " -h --help Show this help\n"
6903 " --version Show package version\n"
6904 " --system Connect to system manager\n"
6905 " --user Connect to user service manager\n"
6906 " -H --host=[USER@]HOST\n"
6907 " Operate on remote host\n"
6908 " -M --machine=CONTAINER\n"
6909 " Operate on local container\n"
6910 " -t --type=TYPE List units of a particular type\n"
6911 " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n"
6912 " -p --property=NAME Show only properties by this name\n"
6913 " -a --all Show all properties/all units currently in memory,\n"
6914 " including dead/empty ones. To list all units installed on\n"
6915 " the system, use the 'list-unit-files' command instead.\n"
6916 " -l --full Don't ellipsize unit names on output\n"
6917 " -r --recursive Show unit list of host and local containers\n"
6918 " --reverse Show reverse dependencies with 'list-dependencies'\n"
6919 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
6920 " queueing a new job\n"
6921 " --show-types When showing sockets, explicitly show their type\n"
6922 " --value When showing properties, only print the value\n"
6923 " -i --ignore-inhibitors\n"
6924 " When shutting down or sleeping, ignore inhibitors\n"
6925 " --kill-who=WHO Who to send signal to\n"
6926 " -s --signal=SIGNAL Which signal to send\n"
6927 " --now Start or stop unit in addition to enabling or disabling it\n"
6928 " -q --quiet Suppress output\n"
6929 " --wait For (re)start, wait until service stopped again\n"
6930 " --no-block Do not wait until operation finished\n"
6931 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6932 " --no-reload Don't reload daemon after en-/dis-abling unit files\n"
6933 " --no-legend Do not print a legend (column headers and hints)\n"
6934 " --no-pager Do not pipe output into a pager\n"
6935 " --no-ask-password\n"
6936 " Do not ask for system passwords\n"
6937 " --global Enable/disable unit files globally\n"
6938 " --runtime Enable unit files only temporarily until next reboot\n"
6939 " -f --force When enabling unit files, override existing symlinks\n"
6940 " When shutting down, execute action immediately\n"
6941 " --preset-mode= Apply only enable, only disable, or all presets\n"
6942 " --root=PATH Enable unit files in the specified root directory\n"
6943 " -n --lines=INTEGER Number of journal entries to show\n"
6944 " -o --output=STRING Change journal output mode (short, short-precise,\n"
6945 " short-iso, short-full, short-monotonic, short-unix,\n"
6946 " verbose, export, json, json-pretty, json-sse, cat)\n"
6947 " --firmware-setup Tell the firmware to show the setup menu on next boot\n"
6948 " --plain Print unit dependencies as a list instead of a tree\n\n"
6950 " list-units [PATTERN...] List units currently in memory\n"
6951 " list-sockets [PATTERN...] List socket units currently in memory, ordered\n"
6953 " list-timers [PATTERN...] List timer units currently in memory, ordered\n"
6955 " start NAME... Start (activate) one or more units\n"
6956 " stop NAME... Stop (deactivate) one or more units\n"
6957 " reload NAME... Reload one or more units\n"
6958 " restart NAME... Start or restart one or more units\n"
6959 " try-restart NAME... Restart one or more units if active\n"
6960 " reload-or-restart NAME... Reload one or more units if possible,\n"
6961 " otherwise start or restart\n"
6962 " try-reload-or-restart NAME... If active, reload one or more units,\n"
6963 " if supported, otherwise restart\n"
6964 " isolate NAME Start one unit and stop all others\n"
6965 " kill NAME... Send signal to processes of a unit\n"
6966 " is-active PATTERN... Check whether units are active\n"
6967 " is-failed PATTERN... Check whether units are failed\n"
6968 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
6969 " show [PATTERN...|JOB...] Show properties of one or more\n"
6970 " units/jobs or the manager\n"
6971 " cat PATTERN... Show files and drop-ins of one or more units\n"
6972 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
6973 " help PATTERN...|PID... Show manual for one or more units\n"
6974 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
6976 " list-dependencies [NAME] Recursively show units which are required\n"
6977 " or wanted by this unit or by which this\n"
6978 " unit is required or wanted\n\n"
6979 "Unit File Commands:\n"
6980 " list-unit-files [PATTERN...] List installed unit files\n"
6981 " enable [NAME...|PATH...] Enable one or more unit files\n"
6982 " disable NAME... Disable one or more unit files\n"
6983 " reenable NAME... Reenable one or more unit files\n"
6984 " preset NAME... Enable/disable one or more unit files\n"
6985 " based on preset configuration\n"
6986 " preset-all Enable/disable all unit files based on\n"
6987 " preset configuration\n"
6988 " is-enabled NAME... Check whether unit files are enabled\n"
6989 " mask NAME... Mask one or more units\n"
6990 " unmask NAME... Unmask one or more units\n"
6991 " link PATH... Link one or more units files into\n"
6992 " the search path\n"
6993 " revert NAME... Revert one or more unit files to vendor\n"
6995 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
6996 " on specified one or more units\n"
6997 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
6998 " on specified one or more units\n"
6999 " edit NAME... Edit one or more unit files\n"
7000 " get-default Get the name of the default target\n"
7001 " set-default NAME Set the default target\n\n"
7002 "Machine Commands:\n"
7003 " list-machines [PATTERN...] List local containers and host\n\n"
7005 " list-jobs [PATTERN...] List jobs\n"
7006 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
7007 "Environment Commands:\n"
7008 " show-environment Dump environment\n"
7009 " set-environment NAME=VALUE... Set one or more environment variables\n"
7010 " unset-environment NAME... Unset one or more environment variables\n"
7011 " import-environment [NAME...] Import all or some environment variables\n\n"
7012 "Manager Lifecycle Commands:\n"
7013 " daemon-reload Reload systemd manager configuration\n"
7014 " daemon-reexec Reexecute systemd manager\n\n"
7015 "System Commands:\n"
7016 " is-system-running Check whether system is fully running\n"
7017 " default Enter system default mode\n"
7018 " rescue Enter system rescue mode\n"
7019 " emergency Enter system emergency mode\n"
7020 " halt Shut down and halt the system\n"
7021 " poweroff Shut down and power-off the system\n"
7022 " reboot [ARG] Shut down and reboot the system\n"
7023 " kexec Shut down and reboot the system with kexec\n"
7024 " exit [EXIT_CODE] Request user instance or container exit\n"
7025 " switch-root ROOT [INIT] Change to a different root file system\n"
7026 " suspend Suspend the system\n"
7027 " hibernate Hibernate the system\n"
7028 " hybrid-sleep Hibernate and suspend the system\n",
7029 program_invocation_short_name
);
7032 static void halt_help(void) {
7033 printf("%s [OPTIONS...]%s\n\n"
7034 "%s the system.\n\n"
7035 " --help Show this help\n"
7036 " --halt Halt the machine\n"
7037 " -p --poweroff Switch off the machine\n"
7038 " --reboot Reboot the machine\n"
7039 " -f --force Force immediate halt/power-off/reboot\n"
7040 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
7041 " -d --no-wtmp Don't write wtmp record\n"
7042 " --no-wall Don't send wall message before halt/power-off/reboot\n",
7043 program_invocation_short_name
,
7044 arg_action
== ACTION_REBOOT
? " [ARG]" : "",
7045 arg_action
== ACTION_REBOOT
? "Reboot" :
7046 arg_action
== ACTION_POWEROFF
? "Power off" :
7050 static void shutdown_help(void) {
7051 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
7052 "Shut down the system.\n\n"
7053 " --help Show this help\n"
7054 " -H --halt Halt the machine\n"
7055 " -P --poweroff Power-off the machine\n"
7056 " -r --reboot Reboot the machine\n"
7057 " -h Equivalent to --poweroff, overridden by --halt\n"
7058 " -k Don't halt/power-off/reboot, just send warnings\n"
7059 " --no-wall Don't send wall message before halt/power-off/reboot\n"
7060 " -c Cancel a pending shutdown\n",
7061 program_invocation_short_name
);
7064 static void telinit_help(void) {
7065 printf("%s [OPTIONS...] {COMMAND}\n\n"
7066 "Send control commands to the init daemon.\n\n"
7067 " --help Show this help\n"
7068 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
7070 " 0 Power-off the machine\n"
7071 " 6 Reboot the machine\n"
7072 " 2, 3, 4, 5 Start runlevelX.target unit\n"
7073 " 1, s, S Enter rescue mode\n"
7074 " q, Q Reload init daemon configuration\n"
7075 " u, U Reexecute init daemon\n",
7076 program_invocation_short_name
);
7079 static void runlevel_help(void) {
7080 printf("%s [OPTIONS...]\n\n"
7081 "Prints the previous and current runlevel of the init system.\n\n"
7082 " --help Show this help\n",
7083 program_invocation_short_name
);
7086 static void help_types(void) {
7090 puts("Available unit types:");
7091 for (i
= 0; i
< _UNIT_TYPE_MAX
; i
++)
7092 puts(unit_type_to_string(i
));
7095 static void help_states(void) {
7099 puts("Available unit load states:");
7100 for (i
= 0; i
< _UNIT_LOAD_STATE_MAX
; i
++)
7101 puts(unit_load_state_to_string(i
));
7104 puts("\nAvailable unit active states:");
7105 for (i
= 0; i
< _UNIT_ACTIVE_STATE_MAX
; i
++)
7106 puts(unit_active_state_to_string(i
));
7109 puts("\nAvailable automount unit substates:");
7110 for (i
= 0; i
< _AUTOMOUNT_STATE_MAX
; i
++)
7111 puts(automount_state_to_string(i
));
7114 puts("\nAvailable busname unit substates:");
7115 for (i
= 0; i
< _BUSNAME_STATE_MAX
; i
++)
7116 puts(busname_state_to_string(i
));
7119 puts("\nAvailable device unit substates:");
7120 for (i
= 0; i
< _DEVICE_STATE_MAX
; i
++)
7121 puts(device_state_to_string(i
));
7124 puts("\nAvailable mount unit substates:");
7125 for (i
= 0; i
< _MOUNT_STATE_MAX
; i
++)
7126 puts(mount_state_to_string(i
));
7129 puts("\nAvailable path unit substates:");
7130 for (i
= 0; i
< _PATH_STATE_MAX
; i
++)
7131 puts(path_state_to_string(i
));
7134 puts("\nAvailable scope unit substates:");
7135 for (i
= 0; i
< _SCOPE_STATE_MAX
; i
++)
7136 puts(scope_state_to_string(i
));
7139 puts("\nAvailable service unit substates:");
7140 for (i
= 0; i
< _SERVICE_STATE_MAX
; i
++)
7141 puts(service_state_to_string(i
));
7144 puts("\nAvailable slice unit substates:");
7145 for (i
= 0; i
< _SLICE_STATE_MAX
; i
++)
7146 puts(slice_state_to_string(i
));
7149 puts("\nAvailable socket unit substates:");
7150 for (i
= 0; i
< _SOCKET_STATE_MAX
; i
++)
7151 puts(socket_state_to_string(i
));
7154 puts("\nAvailable swap unit substates:");
7155 for (i
= 0; i
< _SWAP_STATE_MAX
; i
++)
7156 puts(swap_state_to_string(i
));
7159 puts("\nAvailable target unit substates:");
7160 for (i
= 0; i
< _TARGET_STATE_MAX
; i
++)
7161 puts(target_state_to_string(i
));
7164 puts("\nAvailable timer unit substates:");
7165 for (i
= 0; i
< _TIMER_STATE_MAX
; i
++)
7166 puts(timer_state_to_string(i
));
7169 static int systemctl_parse_argv(int argc
, char *argv
[]) {
7178 ARG_IGNORE_DEPENDENCIES
,
7191 ARG_NO_ASK_PASSWORD
,
7205 static const struct option options
[] = {
7206 { "help", no_argument
, NULL
, 'h' },
7207 { "version", no_argument
, NULL
, ARG_VERSION
},
7208 { "type", required_argument
, NULL
, 't' },
7209 { "property", required_argument
, NULL
, 'p' },
7210 { "all", no_argument
, NULL
, 'a' },
7211 { "reverse", no_argument
, NULL
, ARG_REVERSE
},
7212 { "after", no_argument
, NULL
, ARG_AFTER
},
7213 { "before", no_argument
, NULL
, ARG_BEFORE
},
7214 { "show-types", no_argument
, NULL
, ARG_SHOW_TYPES
},
7215 { "failed", no_argument
, NULL
, ARG_FAILED
}, /* compatibility only */
7216 { "full", no_argument
, NULL
, 'l' },
7217 { "job-mode", required_argument
, NULL
, ARG_JOB_MODE
},
7218 { "fail", no_argument
, NULL
, ARG_FAIL
}, /* compatibility only */
7219 { "irreversible", no_argument
, NULL
, ARG_IRREVERSIBLE
}, /* compatibility only */
7220 { "ignore-dependencies", no_argument
, NULL
, ARG_IGNORE_DEPENDENCIES
}, /* compatibility only */
7221 { "ignore-inhibitors", no_argument
, NULL
, 'i' },
7222 { "value", no_argument
, NULL
, ARG_VALUE
},
7223 { "user", no_argument
, NULL
, ARG_USER
},
7224 { "system", no_argument
, NULL
, ARG_SYSTEM
},
7225 { "global", no_argument
, NULL
, ARG_GLOBAL
},
7226 { "wait", no_argument
, NULL
, ARG_WAIT
},
7227 { "no-block", no_argument
, NULL
, ARG_NO_BLOCK
},
7228 { "no-legend", no_argument
, NULL
, ARG_NO_LEGEND
},
7229 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
7230 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7231 { "quiet", no_argument
, NULL
, 'q' },
7232 { "root", required_argument
, NULL
, ARG_ROOT
},
7233 { "force", no_argument
, NULL
, ARG_FORCE
},
7234 { "no-reload", no_argument
, NULL
, ARG_NO_RELOAD
},
7235 { "kill-who", required_argument
, NULL
, ARG_KILL_WHO
},
7236 { "signal", required_argument
, NULL
, 's' },
7237 { "no-ask-password", no_argument
, NULL
, ARG_NO_ASK_PASSWORD
},
7238 { "host", required_argument
, NULL
, 'H' },
7239 { "machine", required_argument
, NULL
, 'M' },
7240 { "runtime", no_argument
, NULL
, ARG_RUNTIME
},
7241 { "lines", required_argument
, NULL
, 'n' },
7242 { "output", required_argument
, NULL
, 'o' },
7243 { "plain", no_argument
, NULL
, ARG_PLAIN
},
7244 { "state", required_argument
, NULL
, ARG_STATE
},
7245 { "recursive", no_argument
, NULL
, 'r' },
7246 { "preset-mode", required_argument
, NULL
, ARG_PRESET_MODE
},
7247 { "firmware-setup", no_argument
, NULL
, ARG_FIRMWARE_SETUP
},
7248 { "now", no_argument
, NULL
, ARG_NOW
},
7249 { "message", required_argument
, NULL
, ARG_MESSAGE
},
7259 /* we default to allowing interactive authorization only in systemctl (not in the legacy commands) */
7260 arg_ask_password
= true;
7262 while ((c
= getopt_long(argc
, argv
, "ht:p:alqfs:H:M:n:o:ir", options
, NULL
)) >= 0)
7274 if (isempty(optarg
)) {
7275 log_error("--type requires arguments.");
7279 for (p
= optarg
;;) {
7280 _cleanup_free_
char *type
= NULL
;
7282 r
= extract_first_word(&p
, &type
, ",", 0);
7284 return log_error_errno(r
, "Failed to parse type: %s", optarg
);
7288 if (streq(type
, "help")) {
7293 if (unit_type_from_string(type
) >= 0) {
7294 if (strv_push(&arg_types
, type
) < 0)
7300 /* It's much nicer to use --state= for
7301 * load states, but let's support this
7302 * in --types= too for compatibility
7303 * with old versions */
7304 if (unit_load_state_from_string(type
) >= 0) {
7305 if (strv_push(&arg_states
, type
) < 0)
7311 log_error("Unknown unit type or load state '%s'.", type
);
7312 log_info("Use -t help to see a list of allowed values.");
7320 /* Make sure that if the empty property list
7321 was specified, we won't show any properties. */
7322 if (isempty(optarg
) && !arg_properties
) {
7323 arg_properties
= new0(char*, 1);
7324 if (!arg_properties
)
7327 for (p
= optarg
;;) {
7328 _cleanup_free_
char *prop
= NULL
;
7330 r
= extract_first_word(&p
, &prop
, ",", 0);
7332 return log_error_errno(r
, "Failed to parse property: %s", optarg
);
7336 if (strv_push(&arg_properties
, prop
) < 0)
7342 /* If the user asked for a particular
7343 * property, show it to him, even if it is
7355 arg_dependency
= DEPENDENCY_REVERSE
;
7359 arg_dependency
= DEPENDENCY_AFTER
;
7360 arg_jobs_after
= true;
7364 arg_dependency
= DEPENDENCY_BEFORE
;
7365 arg_jobs_before
= true;
7368 case ARG_SHOW_TYPES
:
7369 arg_show_types
= true;
7377 arg_job_mode
= optarg
;
7381 arg_job_mode
= "fail";
7384 case ARG_IRREVERSIBLE
:
7385 arg_job_mode
= "replace-irreversibly";
7388 case ARG_IGNORE_DEPENDENCIES
:
7389 arg_job_mode
= "ignore-dependencies";
7393 arg_scope
= UNIT_FILE_USER
;
7397 arg_scope
= UNIT_FILE_SYSTEM
;
7401 arg_scope
= UNIT_FILE_GLOBAL
;
7409 arg_no_block
= true;
7413 arg_no_legend
= true;
7417 arg_no_pager
= true;
7425 r
= parse_path_argument_and_warn(optarg
, false, &arg_root
);
7435 if (strv_extend(&arg_states
, "failed") < 0)
7453 arg_no_reload
= true;
7457 arg_kill_who
= optarg
;
7461 arg_signal
= signal_from_string_try_harder(optarg
);
7462 if (arg_signal
< 0) {
7463 log_error("Failed to parse signal string %s.", optarg
);
7468 case ARG_NO_ASK_PASSWORD
:
7469 arg_ask_password
= false;
7473 arg_transport
= BUS_TRANSPORT_REMOTE
;
7478 arg_transport
= BUS_TRANSPORT_MACHINE
;
7487 if (safe_atou(optarg
, &arg_lines
) < 0) {
7488 log_error("Failed to parse lines '%s'", optarg
);
7494 arg_output
= output_mode_from_string(optarg
);
7495 if (arg_output
< 0) {
7496 log_error("Unknown output '%s'.", optarg
);
7502 arg_ignore_inhibitors
= true;
7509 case ARG_FIRMWARE_SETUP
:
7510 arg_firmware_setup
= true;
7514 if (isempty(optarg
)) {
7515 log_error("--signal requires arguments.");
7519 for (p
= optarg
;;) {
7520 _cleanup_free_
char *s
= NULL
;
7522 r
= extract_first_word(&p
, &s
, ",", 0);
7524 return log_error_errno(r
, "Failed to parse signal: %s", optarg
);
7528 if (streq(s
, "help")) {
7533 if (strv_push(&arg_states
, s
) < 0)
7542 if (geteuid() != 0) {
7543 log_error("--recursive requires root privileges.");
7547 arg_recursive
= true;
7550 case ARG_PRESET_MODE
:
7552 arg_preset_mode
= unit_file_preset_mode_from_string(optarg
);
7553 if (arg_preset_mode
< 0) {
7554 log_error("Failed to parse preset mode: %s.", optarg
);
7565 if (strv_extend(&arg_wall
, optarg
) < 0)
7573 assert_not_reached("Unhandled option");
7576 if (arg_transport
!= BUS_TRANSPORT_LOCAL
&& arg_scope
!= UNIT_FILE_SYSTEM
) {
7577 log_error("Cannot access user instance remotely.");
7581 if (arg_wait
&& arg_no_block
) {
7582 log_error("--wait may not be combined with --no-block.");
7589 static int halt_parse_argv(int argc
, char *argv
[]) {
7598 static const struct option options
[] = {
7599 { "help", no_argument
, NULL
, ARG_HELP
},
7600 { "halt", no_argument
, NULL
, ARG_HALT
},
7601 { "poweroff", no_argument
, NULL
, 'p' },
7602 { "reboot", no_argument
, NULL
, ARG_REBOOT
},
7603 { "force", no_argument
, NULL
, 'f' },
7604 { "wtmp-only", no_argument
, NULL
, 'w' },
7605 { "no-wtmp", no_argument
, NULL
, 'd' },
7606 { "no-sync", no_argument
, NULL
, 'n' },
7607 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7616 if (utmp_get_runlevel(&runlevel
, NULL
) >= 0)
7617 if (runlevel
== '0' || runlevel
== '6')
7620 while ((c
= getopt_long(argc
, argv
, "pfwdnih", options
, NULL
)) >= 0)
7628 arg_action
= ACTION_HALT
;
7632 if (arg_action
!= ACTION_REBOOT
)
7633 arg_action
= ACTION_POWEROFF
;
7637 arg_action
= ACTION_REBOOT
;
7662 /* Compatibility nops */
7669 assert_not_reached("Unhandled option");
7672 if (arg_action
== ACTION_REBOOT
&& (argc
== optind
|| argc
== optind
+ 1)) {
7673 r
= update_reboot_parameter_and_warn(argc
== optind
+ 1 ? argv
[optind
] : NULL
);
7676 } else if (optind
< argc
) {
7677 log_error("Too many arguments.");
7684 static int parse_shutdown_time_spec(const char *t
, usec_t
*_u
) {
7688 if (streq(t
, "now"))
7690 else if (!strchr(t
, ':')) {
7693 if (safe_atou64(t
, &u
) < 0)
7696 *_u
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
* u
;
7705 hour
= strtol(t
, &e
, 10);
7706 if (errno
> 0 || *e
!= ':' || hour
< 0 || hour
> 23)
7709 minute
= strtol(e
+1, &e
, 10);
7710 if (errno
> 0 || *e
!= 0 || minute
< 0 || minute
> 59)
7713 n
= now(CLOCK_REALTIME
);
7714 s
= (time_t) (n
/ USEC_PER_SEC
);
7716 assert_se(localtime_r(&s
, &tm
));
7718 tm
.tm_hour
= (int) hour
;
7719 tm
.tm_min
= (int) minute
;
7722 assert_se(s
= mktime(&tm
));
7724 *_u
= (usec_t
) s
* USEC_PER_SEC
;
7727 *_u
+= USEC_PER_DAY
;
7733 static int shutdown_parse_argv(int argc
, char *argv
[]) {
7740 static const struct option options
[] = {
7741 { "help", no_argument
, NULL
, ARG_HELP
},
7742 { "halt", no_argument
, NULL
, 'H' },
7743 { "poweroff", no_argument
, NULL
, 'P' },
7744 { "reboot", no_argument
, NULL
, 'r' },
7745 { "kexec", no_argument
, NULL
, 'K' }, /* not documented extension */
7746 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7756 while ((c
= getopt_long(argc
, argv
, "HPrhkKtafFc", options
, NULL
)) >= 0)
7764 arg_action
= ACTION_HALT
;
7768 arg_action
= ACTION_POWEROFF
;
7773 arg_action
= ACTION_KEXEC
;
7775 arg_action
= ACTION_REBOOT
;
7779 arg_action
= ACTION_KEXEC
;
7783 if (arg_action
!= ACTION_HALT
)
7784 arg_action
= ACTION_POWEROFF
;
7799 /* Compatibility nops */
7803 arg_action
= ACTION_CANCEL_SHUTDOWN
;
7810 assert_not_reached("Unhandled option");
7813 if (argc
> optind
&& arg_action
!= ACTION_CANCEL_SHUTDOWN
) {
7814 r
= parse_shutdown_time_spec(argv
[optind
], &arg_when
);
7816 log_error("Failed to parse time specification: %s", argv
[optind
]);
7820 arg_when
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
;
7822 if (argc
> optind
&& arg_action
== ACTION_CANCEL_SHUTDOWN
)
7823 /* No time argument for shutdown cancel */
7824 wall
= argv
+ optind
;
7825 else if (argc
> optind
+ 1)
7826 /* We skip the time argument */
7827 wall
= argv
+ optind
+ 1;
7830 arg_wall
= strv_copy(wall
);
7840 static int telinit_parse_argv(int argc
, char *argv
[]) {
7847 static const struct option options
[] = {
7848 { "help", no_argument
, NULL
, ARG_HELP
},
7849 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7853 static const struct {
7857 { '0', ACTION_POWEROFF
},
7858 { '6', ACTION_REBOOT
},
7859 { '1', ACTION_RESCUE
},
7860 { '2', ACTION_RUNLEVEL2
},
7861 { '3', ACTION_RUNLEVEL3
},
7862 { '4', ACTION_RUNLEVEL4
},
7863 { '5', ACTION_RUNLEVEL5
},
7864 { 's', ACTION_RESCUE
},
7865 { 'S', ACTION_RESCUE
},
7866 { 'q', ACTION_RELOAD
},
7867 { 'Q', ACTION_RELOAD
},
7868 { 'u', ACTION_REEXEC
},
7869 { 'U', ACTION_REEXEC
}
7878 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
7893 assert_not_reached("Unhandled option");
7896 if (optind
>= argc
) {
7897 log_error("%s: required argument missing.", program_invocation_short_name
);
7901 if (optind
+ 1 < argc
) {
7902 log_error("Too many arguments.");
7906 if (strlen(argv
[optind
]) != 1) {
7907 log_error("Expected single character argument.");
7911 for (i
= 0; i
< ELEMENTSOF(table
); i
++)
7912 if (table
[i
].from
== argv
[optind
][0])
7915 if (i
>= ELEMENTSOF(table
)) {
7916 log_error("Unknown command '%s'.", argv
[optind
]);
7920 arg_action
= table
[i
].to
;
7927 static int runlevel_parse_argv(int argc
, char *argv
[]) {
7933 static const struct option options
[] = {
7934 { "help", no_argument
, NULL
, ARG_HELP
},
7943 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
7954 assert_not_reached("Unhandled option");
7957 if (optind
< argc
) {
7958 log_error("Too many arguments.");
7965 static int parse_argv(int argc
, char *argv
[]) {
7969 if (program_invocation_short_name
) {
7971 if (strstr(program_invocation_short_name
, "halt")) {
7972 arg_action
= ACTION_HALT
;
7973 return halt_parse_argv(argc
, argv
);
7974 } else if (strstr(program_invocation_short_name
, "poweroff")) {
7975 arg_action
= ACTION_POWEROFF
;
7976 return halt_parse_argv(argc
, argv
);
7977 } else if (strstr(program_invocation_short_name
, "reboot")) {
7979 arg_action
= ACTION_KEXEC
;
7981 arg_action
= ACTION_REBOOT
;
7982 return halt_parse_argv(argc
, argv
);
7983 } else if (strstr(program_invocation_short_name
, "shutdown")) {
7984 arg_action
= ACTION_POWEROFF
;
7985 return shutdown_parse_argv(argc
, argv
);
7986 } else if (strstr(program_invocation_short_name
, "init")) {
7988 if (sd_booted() > 0) {
7989 arg_action
= _ACTION_INVALID
;
7990 return telinit_parse_argv(argc
, argv
);
7992 /* Hmm, so some other init system is
7993 * running, we need to forward this
7994 * request to it. For now we simply
7995 * guess that it is Upstart. */
7997 execv(TELINIT
, argv
);
7999 log_error("Couldn't find an alternative telinit implementation to spawn.");
8003 } else if (strstr(program_invocation_short_name
, "runlevel")) {
8004 arg_action
= ACTION_RUNLEVEL
;
8005 return runlevel_parse_argv(argc
, argv
);
8009 arg_action
= ACTION_SYSTEMCTL
;
8010 return systemctl_parse_argv(argc
, argv
);
8013 #ifdef HAVE_SYSV_COMPAT
8014 _pure_
static int action_to_runlevel(void) {
8016 static const char table
[_ACTION_MAX
] = {
8017 [ACTION_HALT
] = '0',
8018 [ACTION_POWEROFF
] = '0',
8019 [ACTION_REBOOT
] = '6',
8020 [ACTION_RUNLEVEL2
] = '2',
8021 [ACTION_RUNLEVEL3
] = '3',
8022 [ACTION_RUNLEVEL4
] = '4',
8023 [ACTION_RUNLEVEL5
] = '5',
8024 [ACTION_RESCUE
] = '1'
8027 assert(arg_action
< _ACTION_MAX
);
8029 return table
[arg_action
];
8033 static int talk_initctl(void) {
8034 #ifdef HAVE_SYSV_COMPAT
8035 struct init_request request
= {
8036 .magic
= INIT_MAGIC
,
8038 .cmd
= INIT_CMD_RUNLVL
8041 _cleanup_close_
int fd
= -1;
8045 rl
= action_to_runlevel();
8049 request
.runlevel
= rl
;
8051 fd
= open(INIT_FIFO
, O_WRONLY
|O_NDELAY
|O_CLOEXEC
|O_NOCTTY
);
8053 if (errno
== ENOENT
)
8056 return log_error_errno(errno
, "Failed to open "INIT_FIFO
": %m");
8059 r
= loop_write(fd
, &request
, sizeof(request
), false);
8061 return log_error_errno(r
, "Failed to write to "INIT_FIFO
": %m");
8069 static int systemctl_main(int argc
, char *argv
[]) {
8071 static const Verb verbs
[] = {
8072 { "list-units", VERB_ANY
, VERB_ANY
, VERB_DEFAULT
|VERB_NOCHROOT
, list_units
},
8073 { "list-unit-files", VERB_ANY
, VERB_ANY
, 0, list_unit_files
},
8074 { "list-sockets", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_sockets
},
8075 { "list-timers", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_timers
},
8076 { "list-jobs", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_jobs
},
8077 { "list-machines", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_machines
},
8078 { "clear-jobs", VERB_ANY
, 1, VERB_NOCHROOT
, trivial_method
},
8079 { "cancel", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, cancel_job
},
8080 { "start", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8081 { "stop", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8082 { "condstop", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with ALTLinux */
8083 { "reload", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8084 { "restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8085 { "try-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8086 { "reload-or-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8087 { "reload-or-try-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatbility with old systemctl <= 228 */
8088 { "try-reload-or-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8089 { "force-reload", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with SysV */
8090 { "condreload", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with ALTLinux */
8091 { "condrestart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with RH */
8092 { "isolate", 2, 2, VERB_NOCHROOT
, start_unit
},
8093 { "kill", 2, VERB_ANY
, VERB_NOCHROOT
, kill_unit
},
8094 { "is-active", 2, VERB_ANY
, VERB_NOCHROOT
, check_unit_active
},
8095 { "check", 2, VERB_ANY
, VERB_NOCHROOT
, check_unit_active
},
8096 { "is-failed", 2, VERB_ANY
, VERB_NOCHROOT
, check_unit_failed
},
8097 { "show", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, show
},
8098 { "cat", 2, VERB_ANY
, VERB_NOCHROOT
, cat
},
8099 { "status", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, show
},
8100 { "help", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, show
},
8101 { "daemon-reload", VERB_ANY
, 1, VERB_NOCHROOT
, daemon_reload
},
8102 { "daemon-reexec", VERB_ANY
, 1, VERB_NOCHROOT
, daemon_reload
},
8103 { "show-environment", VERB_ANY
, 1, VERB_NOCHROOT
, show_environment
},
8104 { "set-environment", 2, VERB_ANY
, VERB_NOCHROOT
, set_environment
},
8105 { "unset-environment", 2, VERB_ANY
, VERB_NOCHROOT
, set_environment
},
8106 { "import-environment", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, import_environment
},
8107 { "halt", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8108 { "poweroff", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8109 { "reboot", VERB_ANY
, 2, VERB_NOCHROOT
, start_system_special
},
8110 { "kexec", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8111 { "suspend", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8112 { "hibernate", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8113 { "hybrid-sleep", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8114 { "default", VERB_ANY
, 1, VERB_NOCHROOT
, start_special
},
8115 { "rescue", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8116 { "emergency", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8117 { "exit", VERB_ANY
, 2, VERB_NOCHROOT
, start_special
},
8118 { "reset-failed", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, reset_failed
},
8119 { "enable", 2, VERB_ANY
, 0, enable_unit
},
8120 { "disable", 2, VERB_ANY
, 0, enable_unit
},
8121 { "is-enabled", 2, VERB_ANY
, 0, unit_is_enabled
},
8122 { "reenable", 2, VERB_ANY
, 0, enable_unit
},
8123 { "preset", 2, VERB_ANY
, 0, enable_unit
},
8124 { "preset-all", VERB_ANY
, 1, 0, preset_all
},
8125 { "mask", 2, VERB_ANY
, 0, enable_unit
},
8126 { "unmask", 2, VERB_ANY
, 0, enable_unit
},
8127 { "link", 2, VERB_ANY
, 0, enable_unit
},
8128 { "revert", 2, VERB_ANY
, 0, enable_unit
},
8129 { "switch-root", 2, VERB_ANY
, VERB_NOCHROOT
, switch_root
},
8130 { "list-dependencies", VERB_ANY
, 2, VERB_NOCHROOT
, list_dependencies
},
8131 { "set-default", 2, 2, 0, set_default
},
8132 { "get-default", VERB_ANY
, 1, 0, get_default
},
8133 { "set-property", 3, VERB_ANY
, VERB_NOCHROOT
, set_property
},
8134 { "is-system-running", VERB_ANY
, 1, 0, is_system_running
},
8135 { "add-wants", 3, VERB_ANY
, 0, add_dependency
},
8136 { "add-requires", 3, VERB_ANY
, 0, add_dependency
},
8137 { "edit", 2, VERB_ANY
, VERB_NOCHROOT
, edit
},
8141 return dispatch_verb(argc
, argv
, verbs
, NULL
);
8144 static int reload_with_fallback(void) {
8146 /* First, try systemd via D-Bus. */
8147 if (daemon_reload(0, NULL
, NULL
) >= 0)
8150 /* Nothing else worked, so let's try signals */
8151 assert(IN_SET(arg_action
, ACTION_RELOAD
, ACTION_REEXEC
));
8153 if (kill(1, arg_action
== ACTION_RELOAD
? SIGHUP
: SIGTERM
) < 0)
8154 return log_error_errno(errno
, "kill() failed: %m");
8159 static int start_with_fallback(void) {
8161 /* First, try systemd via D-Bus. */
8162 if (start_unit(0, NULL
, NULL
) >= 0)
8165 /* Nothing else worked, so let's try /dev/initctl */
8166 if (talk_initctl() > 0)
8169 log_error("Failed to talk to init daemon.");
8173 static int halt_now(enum action a
) {
8176 /* The kernel will automaticall flush ATA disks and suchlike
8177 * on reboot(), but the file systems need to be synce'd
8178 * explicitly in advance. */
8182 /* Make sure C-A-D is handled by the kernel from this point
8184 (void) reboot(RB_ENABLE_CAD
);
8189 log_info("Halting.");
8190 (void) reboot(RB_HALT_SYSTEM
);
8193 case ACTION_POWEROFF
:
8194 log_info("Powering off.");
8195 (void) reboot(RB_POWER_OFF
);
8199 case ACTION_REBOOT
: {
8200 _cleanup_free_
char *param
= NULL
;
8202 r
= read_one_line_file("/run/systemd/reboot-param", ¶m
);
8204 log_warning_errno(r
, "Failed to read reboot parameter file: %m");
8206 if (!isempty(param
)) {
8207 log_info("Rebooting with argument '%s'.", param
);
8208 (void) syscall(SYS_reboot
, LINUX_REBOOT_MAGIC1
, LINUX_REBOOT_MAGIC2
, LINUX_REBOOT_CMD_RESTART2
, param
);
8209 log_warning_errno(errno
, "Failed to reboot with parameter, retrying without: %m");
8212 log_info("Rebooting.");
8213 (void) reboot(RB_AUTOBOOT
);
8218 assert_not_reached("Unknown action.");
8222 static int logind_schedule_shutdown(void) {
8225 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
8226 char date
[FORMAT_TIMESTAMP_MAX
];
8231 r
= acquire_bus(BUS_FULL
, &bus
);
8235 switch (arg_action
) {
8239 case ACTION_POWEROFF
:
8240 action
= "poweroff";
8255 action
= strjoina("dry-", action
);
8257 (void) logind_set_wall_message();
8259 r
= sd_bus_call_method(
8261 "org.freedesktop.login1",
8262 "/org/freedesktop/login1",
8263 "org.freedesktop.login1.Manager",
8271 return log_warning_errno(r
, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s", bus_error_message(&error
, r
));
8273 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.", format_timestamp(date
, sizeof(date
), arg_when
));
8276 log_error("Cannot schedule shutdown without logind support, proceeding with immediate shutdown.");
8281 static int halt_main(void) {
8284 r
= logind_check_inhibitors(arg_action
);
8289 return logind_schedule_shutdown();
8291 if (geteuid() != 0) {
8292 if (arg_dry
|| arg_force
> 0) {
8293 log_error("Must be root.");
8297 /* Try logind if we are a normal user and no special
8298 * mode applies. Maybe PolicyKit allows us to shutdown
8300 if (IN_SET(arg_action
, ACTION_POWEROFF
, ACTION_REBOOT
)) {
8301 r
= logind_reboot(arg_action
);
8304 if (IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
8305 /* requested operation is not
8306 * supported on the local system or
8307 * already in progress */
8309 /* on all other errors, try low-level operation */
8313 if (!arg_dry
&& !arg_force
)
8314 return start_with_fallback();
8316 assert(geteuid() == 0);
8319 if (sd_booted() > 0)
8320 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
8322 r
= utmp_put_shutdown();
8324 log_warning_errno(r
, "Failed to write utmp record: %m");
8331 r
= halt_now(arg_action
);
8332 return log_error_errno(r
, "Failed to reboot: %m");
8335 static int runlevel_main(void) {
8336 int r
, runlevel
, previous
;
8338 r
= utmp_get_runlevel(&runlevel
, &previous
);
8345 previous
<= 0 ? 'N' : previous
,
8346 runlevel
<= 0 ? 'N' : runlevel
);
8351 static int logind_cancel_shutdown(void) {
8353 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
8357 r
= acquire_bus(BUS_FULL
, &bus
);
8361 (void) logind_set_wall_message();
8363 r
= sd_bus_call_method(
8365 "org.freedesktop.login1",
8366 "/org/freedesktop/login1",
8367 "org.freedesktop.login1.Manager",
8368 "CancelScheduledShutdown",
8372 return log_warning_errno(r
, "Failed to talk to logind, shutdown hasn't been cancelled: %s", bus_error_message(&error
, r
));
8376 log_error("Not compiled with logind support, cannot cancel scheduled shutdowns.");
8381 int main(int argc
, char*argv
[]) {
8384 argv_cmdline
= argv
[0];
8386 setlocale(LC_ALL
, "");
8387 log_parse_environment();
8391 /* Explicitly not on_tty() to avoid setting cached value.
8392 * This becomes relevant for piping output which might be
8394 original_stdout_is_tty
= isatty(STDOUT_FILENO
);
8396 r
= parse_argv(argc
, argv
);
8400 if (arg_action
!= ACTION_SYSTEMCTL
&& running_in_chroot() > 0) {
8401 log_info("Running in chroot, ignoring request.");
8406 /* systemctl_main() will print an error message for the bus
8407 * connection, but only if it needs to */
8409 switch (arg_action
) {
8411 case ACTION_SYSTEMCTL
:
8412 r
= systemctl_main(argc
, argv
);
8416 case ACTION_POWEROFF
:
8422 case ACTION_RUNLEVEL2
:
8423 case ACTION_RUNLEVEL3
:
8424 case ACTION_RUNLEVEL4
:
8425 case ACTION_RUNLEVEL5
:
8427 case ACTION_EMERGENCY
:
8428 case ACTION_DEFAULT
:
8429 r
= start_with_fallback();
8434 r
= reload_with_fallback();
8437 case ACTION_CANCEL_SHUTDOWN
:
8438 r
= logind_cancel_shutdown();
8441 case ACTION_RUNLEVEL
:
8442 r
= runlevel_main();
8445 case _ACTION_INVALID
:
8447 assert_not_reached("Unknown action");
8454 ask_password_agent_close();
8455 polkit_agent_close();
8457 strv_free(arg_types
);
8458 strv_free(arg_states
);
8459 strv_free(arg_properties
);
8461 strv_free(arg_wall
);
8464 /* Note that we return r here, not EXIT_SUCCESS, so that we can implement the LSB-like return codes */
8465 return r
< 0 ? EXIT_FAILURE
: r
;