2 This file is part of systemd.
4 Copyright 2010 Lennart Poettering
5 Copyright 2013 Marc-Antoine Perennou
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #include <linux/reboot.h>
30 #include <sys/reboot.h>
31 #include <sys/socket.h>
35 #include "sd-daemon.h"
38 #include "alloc-util.h"
39 #include "bus-common-errors.h"
40 #include "bus-error.h"
41 #include "bus-message.h"
42 #include "bus-unit-util.h"
44 #include "cgroup-show.h"
45 #include "cgroup-util.h"
50 #include "exit-status.h"
53 #include "formats-util.h"
55 #include "glob-util.h"
56 #include "hostname-util.h"
61 #include "locale-util.h"
63 #include "logs-show.h"
67 #include "parse-util.h"
68 #include "path-lookup.h"
69 #include "path-util.h"
70 #include "process-util.h"
71 #include "rlimit-util.h"
74 #include "signal-util.h"
75 #include "socket-util.h"
76 #include "spawn-ask-password-agent.h"
77 #include "spawn-polkit-agent.h"
79 #include "stat-util.h"
81 #include "terminal-util.h"
82 #include "unit-name.h"
83 #include "user-util.h"
85 #include "utmp-wtmp.h"
89 /* The init script exit status codes
90 0 program is running or service is OK
91 1 program is dead and /var/run pid file exists
92 2 program is dead and /var/lock lock file exists
93 3 program is not running
94 4 program or service status is unknown
95 5-99 reserved for future LSB use
96 100-149 reserved for distribution use
97 150-199 reserved for application use
101 EXIT_PROGRAM_RUNNING_OR_SERVICE_OK
= 0,
102 EXIT_PROGRAM_DEAD_AND_PID_EXISTS
= 1,
103 EXIT_PROGRAM_DEAD_AND_LOCK_FILE_EXISTS
= 2,
104 EXIT_PROGRAM_NOT_RUNNING
= 3,
105 EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN
= 4,
108 static char **arg_types
= NULL
;
109 static char **arg_states
= NULL
;
110 static char **arg_properties
= NULL
;
111 static bool arg_all
= false;
112 static enum dependency
{
118 } arg_dependency
= DEPENDENCY_FORWARD
;
119 static const char *arg_job_mode
= "replace";
120 static UnitFileScope arg_scope
= UNIT_FILE_SYSTEM
;
121 static bool arg_no_block
= false;
122 static bool arg_no_legend
= false;
123 static bool arg_no_pager
= false;
124 static bool arg_no_wtmp
= false;
125 static bool arg_no_sync
= false;
126 static bool arg_no_wall
= false;
127 static bool arg_no_reload
= false;
128 static bool arg_value
= false;
129 static bool arg_show_types
= false;
130 static bool arg_ignore_inhibitors
= false;
131 static bool arg_dry
= false;
132 static bool arg_quiet
= false;
133 static bool arg_full
= false;
134 static bool arg_recursive
= false;
135 static int arg_force
= 0;
136 static bool arg_ask_password
= false;
137 static bool arg_runtime
= false;
138 static UnitFilePresetMode arg_preset_mode
= UNIT_FILE_PRESET_FULL
;
139 static char **arg_wall
= NULL
;
140 static const char *arg_kill_who
= NULL
;
141 static int arg_signal
= SIGTERM
;
142 static char *arg_root
= NULL
;
143 static usec_t arg_when
= 0;
165 ACTION_CANCEL_SHUTDOWN
,
167 } arg_action
= ACTION_SYSTEMCTL
;
168 static BusTransport arg_transport
= BUS_TRANSPORT_LOCAL
;
169 static const char *arg_host
= NULL
;
170 static unsigned arg_lines
= 10;
171 static OutputMode arg_output
= OUTPUT_SHORT
;
172 static bool arg_plain
= false;
173 static bool arg_firmware_setup
= false;
174 static bool arg_now
= false;
176 static int daemon_reload(int argc
, char *argv
[], void* userdata
);
177 static int trivial_method(int argc
, char *argv
[], void *userdata
);
178 static int halt_now(enum action a
);
179 static int get_state_one_unit(sd_bus
*bus
, const char *name
, UnitActiveState
*active_state
);
181 static bool original_stdout_is_tty
;
183 typedef enum BusFocus
{
184 BUS_FULL
, /* The full bus indicated via --system or --user */
185 BUS_MANAGER
, /* The manager itself, possibly directly, possibly via the bus */
189 static sd_bus
*busses
[_BUS_FOCUS_MAX
] = {};
191 static int acquire_bus(BusFocus focus
, sd_bus
**ret
) {
194 assert(focus
< _BUS_FOCUS_MAX
);
197 /* We only go directly to the manager, if we are using a local transport */
198 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
201 if (!busses
[focus
]) {
204 user
= arg_scope
!= UNIT_FILE_SYSTEM
;
206 if (focus
== BUS_MANAGER
)
207 r
= bus_connect_transport_systemd(arg_transport
, arg_host
, user
, &busses
[focus
]);
209 r
= bus_connect_transport(arg_transport
, arg_host
, user
, &busses
[focus
]);
211 return log_error_errno(r
, "Failed to connect to bus: %m");
213 (void) sd_bus_set_allow_interactive_authorization(busses
[focus
], arg_ask_password
);
216 *ret
= busses
[focus
];
220 static void release_busses(void) {
223 for (w
= 0; w
< _BUS_FOCUS_MAX
; w
++)
224 busses
[w
] = sd_bus_flush_close_unref(busses
[w
]);
227 static int map_string_no_copy(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
229 const char **p
= userdata
;
232 r
= sd_bus_message_read_basic(m
, SD_BUS_TYPE_STRING
, &s
);
242 static void ask_password_agent_open_if_enabled(void) {
244 /* Open the password agent as a child process if necessary */
246 if (!arg_ask_password
)
249 if (arg_scope
!= UNIT_FILE_SYSTEM
)
252 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
255 ask_password_agent_open();
258 static void polkit_agent_open_if_enabled(void) {
260 /* Open the polkit agent as a child process if necessary */
262 if (!arg_ask_password
)
265 if (arg_scope
!= UNIT_FILE_SYSTEM
)
268 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
274 static OutputFlags
get_output_flags(void) {
276 arg_all
* OUTPUT_SHOW_ALL
|
277 arg_full
* OUTPUT_FULL_WIDTH
|
278 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH
|
279 colors_enabled() * OUTPUT_COLOR
|
280 !arg_quiet
* OUTPUT_WARN_CUTOFF
;
283 static int translate_bus_error_to_exit_status(int r
, const sd_bus_error
*error
) {
286 if (!sd_bus_error_is_set(error
))
289 if (sd_bus_error_has_name(error
, SD_BUS_ERROR_ACCESS_DENIED
) ||
290 sd_bus_error_has_name(error
, BUS_ERROR_ONLY_BY_DEPENDENCY
) ||
291 sd_bus_error_has_name(error
, BUS_ERROR_NO_ISOLATION
) ||
292 sd_bus_error_has_name(error
, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE
))
293 return EXIT_NOPERMISSION
;
295 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
))
296 return EXIT_NOTINSTALLED
;
298 if (sd_bus_error_has_name(error
, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE
) ||
299 sd_bus_error_has_name(error
, SD_BUS_ERROR_NOT_SUPPORTED
))
300 return EXIT_NOTIMPLEMENTED
;
302 if (sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
))
303 return EXIT_NOTCONFIGURED
;
311 static bool install_client_side(void) {
313 /* Decides when to execute enable/disable/... operations
314 * client-side rather than server-side. */
316 if (running_in_chroot() > 0)
319 if (sd_booted() <= 0)
322 if (!isempty(arg_root
))
325 if (arg_scope
== UNIT_FILE_GLOBAL
)
328 /* Unsupported environment variable, mostly for debugging purposes */
329 if (getenv_bool("SYSTEMCTL_INSTALL_CLIENT_SIDE") > 0)
335 static int compare_unit_info(const void *a
, const void *b
) {
336 const UnitInfo
*u
= a
, *v
= b
;
340 /* First, order by machine */
341 if (!u
->machine
&& v
->machine
)
343 if (u
->machine
&& !v
->machine
)
345 if (u
->machine
&& v
->machine
) {
346 r
= strcasecmp(u
->machine
, v
->machine
);
351 /* Second, order by unit type */
352 d1
= strrchr(u
->id
, '.');
353 d2
= strrchr(v
->id
, '.');
355 r
= strcasecmp(d1
, d2
);
360 /* Third, order by name */
361 return strcasecmp(u
->id
, v
->id
);
364 static bool output_show_unit(const UnitInfo
*u
, char **patterns
) {
367 if (!strv_fnmatch_or_empty(patterns
, u
->id
, FNM_NOESCAPE
))
373 dot
= strrchr(u
->id
, '.');
377 if (!strv_find(arg_types
, dot
+1))
384 /* Note that '--all' is not purely a state filter, but also a
385 * filter that hides units that "follow" other units (which is
386 * used for device units that appear under different names). */
387 if (!isempty(u
->following
))
390 if (!strv_isempty(arg_states
))
393 /* By default show all units except the ones in inactive
394 * state and with no pending job */
398 if (streq(u
->active_state
, "inactive"))
404 static int output_units_list(const UnitInfo
*unit_infos
, unsigned c
) {
405 unsigned circle_len
= 0, id_len
, max_id_len
, load_len
, active_len
, sub_len
, job_len
, desc_len
;
407 unsigned n_shown
= 0;
410 max_id_len
= strlen("UNIT");
411 load_len
= strlen("LOAD");
412 active_len
= strlen("ACTIVE");
413 sub_len
= strlen("SUB");
414 job_len
= strlen("JOB");
417 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
418 max_id_len
= MAX(max_id_len
, strlen(u
->id
) + (u
->machine
? strlen(u
->machine
)+1 : 0));
419 load_len
= MAX(load_len
, strlen(u
->load_state
));
420 active_len
= MAX(active_len
, strlen(u
->active_state
));
421 sub_len
= MAX(sub_len
, strlen(u
->sub_state
));
423 if (u
->job_id
!= 0) {
424 job_len
= MAX(job_len
, strlen(u
->job_type
));
428 if (!arg_no_legend
&&
429 (streq(u
->active_state
, "failed") ||
430 STR_IN_SET(u
->load_state
, "error", "not-found", "masked")))
434 if (!arg_full
&& original_stdout_is_tty
) {
437 id_len
= MIN(max_id_len
, 25u);
438 basic_len
= circle_len
+ 5 + id_len
+ 5 + active_len
+ sub_len
;
441 basic_len
+= job_len
+ 1;
443 if (basic_len
< (unsigned) columns()) {
444 unsigned extra_len
, incr
;
445 extra_len
= columns() - basic_len
;
447 /* Either UNIT already got 25, or is fully satisfied.
448 * Grant up to 25 to DESC now. */
449 incr
= MIN(extra_len
, 25u);
453 /* split the remaining space between UNIT and DESC,
454 * but do not give UNIT more than it needs. */
456 incr
= MIN(extra_len
/ 2, max_id_len
- id_len
);
458 desc_len
+= extra_len
- incr
;
464 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
465 _cleanup_free_
char *e
= NULL
, *j
= NULL
;
466 const char *on_loaded
= "", *off_loaded
= "";
467 const char *on_active
= "", *off_active
= "";
468 const char *on_circle
= "", *off_circle
= "";
472 if (!n_shown
&& !arg_no_legend
) {
477 printf("%-*s %-*s %-*s %-*s ",
480 active_len
, "ACTIVE",
484 printf("%-*s ", job_len
, "JOB");
486 if (!arg_full
&& arg_no_pager
)
487 printf("%.*s\n", desc_len
, "DESCRIPTION");
489 printf("%s\n", "DESCRIPTION");
494 if (STR_IN_SET(u
->load_state
, "error", "not-found", "masked") && !arg_plain
) {
495 on_loaded
= ansi_highlight_red();
496 on_circle
= ansi_highlight_yellow();
497 off_loaded
= off_circle
= ansi_normal();
499 } else if (streq(u
->active_state
, "failed") && !arg_plain
) {
500 on_circle
= on_active
= ansi_highlight_red();
501 off_circle
= off_active
= ansi_normal();
506 j
= strjoin(u
->machine
, ":", u
->id
, NULL
);
515 e
= ellipsize(id
, id_len
, 33);
523 printf("%s%s%s ", on_circle
, circle
? special_glyph(BLACK_CIRCLE
) : " ", off_circle
);
525 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
526 on_active
, id_len
, id
, off_active
,
527 on_loaded
, load_len
, u
->load_state
, off_loaded
,
528 on_active
, active_len
, u
->active_state
,
529 sub_len
, u
->sub_state
, off_active
,
530 job_count
? job_len
+ 1 : 0, u
->job_id
? u
->job_type
: "");
533 printf("%.*s\n", desc_len
, u
->description
);
535 printf("%s\n", u
->description
);
538 if (!arg_no_legend
) {
539 const char *on
, *off
;
543 "LOAD = Reflects whether the unit definition was properly loaded.\n"
544 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
545 "SUB = The low-level unit activation state, values depend on unit type.");
546 puts(job_count
? "JOB = Pending job for the unit.\n" : "");
547 on
= ansi_highlight();
550 on
= ansi_highlight_red();
555 printf("%s%u loaded units listed.%s\n"
556 "To show all installed unit files use 'systemctl list-unit-files'.\n",
559 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
560 "To show all installed unit files use 'systemctl list-unit-files'.\n",
567 static int get_unit_list(
571 UnitInfo
**unit_infos
,
573 sd_bus_message
**_reply
) {
575 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
576 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
577 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
581 bool fallback
= false;
587 r
= sd_bus_message_new_method_call(
590 "org.freedesktop.systemd1",
591 "/org/freedesktop/systemd1",
592 "org.freedesktop.systemd1.Manager",
593 "ListUnitsByPatterns");
595 return bus_log_create_error(r
);
597 r
= sd_bus_message_append_strv(m
, arg_states
);
599 return bus_log_create_error(r
);
601 r
= sd_bus_message_append_strv(m
, patterns
);
603 return bus_log_create_error(r
);
605 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
606 if (r
< 0 && (sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_METHOD
) ||
607 sd_bus_error_has_name(&error
, SD_BUS_ERROR_ACCESS_DENIED
))) {
608 /* Fallback to legacy ListUnitsFiltered method */
610 log_debug_errno(r
, "Failed to list units: %s Falling back to ListUnitsFiltered method.", bus_error_message(&error
, r
));
611 m
= sd_bus_message_unref(m
);
612 sd_bus_error_free(&error
);
614 r
= sd_bus_message_new_method_call(
617 "org.freedesktop.systemd1",
618 "/org/freedesktop/systemd1",
619 "org.freedesktop.systemd1.Manager",
620 "ListUnitsFiltered");
622 return bus_log_create_error(r
);
624 r
= sd_bus_message_append_strv(m
, arg_states
);
626 return bus_log_create_error(r
);
628 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
631 return log_error_errno(r
, "Failed to list units: %s", bus_error_message(&error
, r
));
633 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssssouso)");
635 return bus_log_parse_error(r
);
637 while ((r
= bus_parse_unit_info(reply
, &u
)) > 0) {
640 if (!output_show_unit(&u
, fallback
? patterns
: NULL
))
643 if (!GREEDY_REALLOC(*unit_infos
, size
, c
+1))
646 (*unit_infos
)[c
++] = u
;
649 return bus_log_parse_error(r
);
651 r
= sd_bus_message_exit_container(reply
);
653 return bus_log_parse_error(r
);
661 static void message_set_freep(Set
**set
) {
664 while ((m
= set_steal_first(*set
)))
665 sd_bus_message_unref(m
);
670 static int get_unit_list_recursive(
673 UnitInfo
**_unit_infos
,
677 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
678 _cleanup_(message_set_freep
) Set
*replies
;
679 sd_bus_message
*reply
;
687 replies
= set_new(NULL
);
691 c
= get_unit_list(bus
, NULL
, patterns
, &unit_infos
, 0, &reply
);
695 r
= set_put(replies
, reply
);
697 sd_bus_message_unref(reply
);
702 _cleanup_strv_free_
char **machines
= NULL
;
705 r
= sd_get_machine_names(&machines
);
707 return log_error_errno(r
, "Failed to get machine names: %m");
709 STRV_FOREACH(i
, machines
) {
710 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*container
= NULL
;
713 r
= sd_bus_open_system_machine(&container
, *i
);
715 log_warning_errno(r
, "Failed to connect to container %s, ignoring: %m", *i
);
719 k
= get_unit_list(container
, *i
, patterns
, &unit_infos
, c
, &reply
);
725 r
= set_put(replies
, reply
);
727 sd_bus_message_unref(reply
);
732 *_machines
= machines
;
737 *_unit_infos
= unit_infos
;
746 static int list_units(int argc
, char *argv
[], void *userdata
) {
747 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
748 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
749 _cleanup_strv_free_
char **machines
= NULL
;
753 r
= acquire_bus(BUS_MANAGER
, &bus
);
757 pager_open(arg_no_pager
, false);
759 r
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
763 qsort_safe(unit_infos
, r
, sizeof(UnitInfo
), compare_unit_info
);
764 return output_units_list(unit_infos
, r
);
767 static int get_triggered_units(
772 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
779 r
= sd_bus_get_property_strv(
781 "org.freedesktop.systemd1",
783 "org.freedesktop.systemd1.Unit",
788 return log_error_errno(r
, "Failed to determine triggers: %s", bus_error_message(&error
, r
));
793 static int get_listening(
795 const char* unit_path
,
798 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
799 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
800 const char *type
, *path
;
803 r
= sd_bus_get_property(
805 "org.freedesktop.systemd1",
807 "org.freedesktop.systemd1.Socket",
813 return log_error_errno(r
, "Failed to get list of listening sockets: %s", bus_error_message(&error
, r
));
815 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
817 return bus_log_parse_error(r
);
819 while ((r
= sd_bus_message_read(reply
, "(ss)", &type
, &path
)) > 0) {
821 r
= strv_extend(listening
, type
);
825 r
= strv_extend(listening
, path
);
832 return bus_log_parse_error(r
);
834 r
= sd_bus_message_exit_container(reply
);
836 return bus_log_parse_error(r
);
848 /* Note: triggered is a list here, although it almost certainly
849 * will always be one unit. Nevertheless, dbus API allows for multiple
850 * values, so let's follow that. */
853 /* The strv above is shared. free is set only in the first one. */
857 static int socket_info_compare(const struct socket_info
*a
, const struct socket_info
*b
) {
863 if (!a
->machine
&& b
->machine
)
865 if (a
->machine
&& !b
->machine
)
867 if (a
->machine
&& b
->machine
) {
868 o
= strcasecmp(a
->machine
, b
->machine
);
873 o
= strcmp(a
->path
, b
->path
);
875 o
= strcmp(a
->type
, b
->type
);
880 static int output_sockets_list(struct socket_info
*socket_infos
, unsigned cs
) {
881 struct socket_info
*s
;
882 unsigned pathlen
= strlen("LISTEN"),
883 typelen
= strlen("TYPE") * arg_show_types
,
884 socklen
= strlen("UNIT"),
885 servlen
= strlen("ACTIVATES");
886 const char *on
, *off
;
888 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
892 socklen
= MAX(socklen
, strlen(s
->id
));
894 typelen
= MAX(typelen
, strlen(s
->type
));
895 pathlen
= MAX(pathlen
, strlen(s
->path
) + (s
->machine
? strlen(s
->machine
)+1 : 0));
897 STRV_FOREACH(a
, s
->triggered
)
898 tmp
+= strlen(*a
) + 2*(a
!= s
->triggered
);
899 servlen
= MAX(servlen
, tmp
);
904 printf("%-*s %-*.*s%-*s %s\n",
906 typelen
+ arg_show_types
, typelen
+ arg_show_types
, "TYPE ",
910 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
911 _cleanup_free_
char *j
= NULL
;
916 j
= strjoin(s
->machine
, ":", s
->path
, NULL
);
924 printf("%-*s %-*s %-*s",
925 pathlen
, path
, typelen
, s
->type
, socklen
, s
->id
);
928 pathlen
, path
, socklen
, s
->id
);
929 STRV_FOREACH(a
, s
->triggered
)
931 a
== s
->triggered
? "" : ",", *a
);
935 on
= ansi_highlight();
940 on
= ansi_highlight_red();
944 if (!arg_no_legend
) {
945 printf("%s%u sockets listed.%s\n", on
, cs
, off
);
947 printf("Pass --all to see loaded but inactive sockets, too.\n");
953 static int list_sockets(int argc
, char *argv
[], void *userdata
) {
954 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
955 _cleanup_strv_free_
char **machines
= NULL
;
956 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
957 _cleanup_free_
struct socket_info
*socket_infos
= NULL
;
959 struct socket_info
*s
;
965 r
= acquire_bus(BUS_MANAGER
, &bus
);
969 pager_open(arg_no_pager
, false);
971 n
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
975 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
976 _cleanup_strv_free_
char **listening
= NULL
, **triggered
= NULL
;
979 if (!endswith(u
->id
, ".socket"))
982 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
986 c
= get_listening(bus
, u
->unit_path
, &listening
);
992 if (!GREEDY_REALLOC(socket_infos
, size
, cs
+ c
)) {
997 for (i
= 0; i
< c
; i
++)
998 socket_infos
[cs
+ i
] = (struct socket_info
) {
999 .machine
= u
->machine
,
1001 .type
= listening
[i
*2],
1002 .path
= listening
[i
*2 + 1],
1003 .triggered
= triggered
,
1004 .own_triggered
= i
==0,
1007 /* from this point on we will cleanup those socket_infos */
1010 listening
= triggered
= NULL
; /* avoid cleanup */
1013 qsort_safe(socket_infos
, cs
, sizeof(struct socket_info
),
1014 (__compar_fn_t
) socket_info_compare
);
1016 output_sockets_list(socket_infos
, cs
);
1019 assert(cs
== 0 || socket_infos
);
1020 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
1023 if (s
->own_triggered
)
1024 strv_free(s
->triggered
);
1030 static int get_next_elapse(
1033 dual_timestamp
*next
) {
1035 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1043 r
= sd_bus_get_property_trivial(
1045 "org.freedesktop.systemd1",
1047 "org.freedesktop.systemd1.Timer",
1048 "NextElapseUSecMonotonic",
1053 return log_error_errno(r
, "Failed to get next elapsation time: %s", bus_error_message(&error
, r
));
1055 r
= sd_bus_get_property_trivial(
1057 "org.freedesktop.systemd1",
1059 "org.freedesktop.systemd1.Timer",
1060 "NextElapseUSecRealtime",
1065 return log_error_errno(r
, "Failed to get next elapsation time: %s", bus_error_message(&error
, r
));
1071 static int get_last_trigger(
1076 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1083 r
= sd_bus_get_property_trivial(
1085 "org.freedesktop.systemd1",
1087 "org.freedesktop.systemd1.Timer",
1093 return log_error_errno(r
, "Failed to get last trigger time: %s", bus_error_message(&error
, r
));
1099 const char* machine
;
1102 usec_t last_trigger
;
1106 static int timer_info_compare(const struct timer_info
*a
, const struct timer_info
*b
) {
1112 if (!a
->machine
&& b
->machine
)
1114 if (a
->machine
&& !b
->machine
)
1116 if (a
->machine
&& b
->machine
) {
1117 o
= strcasecmp(a
->machine
, b
->machine
);
1122 if (a
->next_elapse
< b
->next_elapse
)
1124 if (a
->next_elapse
> b
->next_elapse
)
1127 return strcmp(a
->id
, b
->id
);
1130 static int output_timers_list(struct timer_info
*timer_infos
, unsigned n
) {
1131 struct timer_info
*t
;
1133 nextlen
= strlen("NEXT"),
1134 leftlen
= strlen("LEFT"),
1135 lastlen
= strlen("LAST"),
1136 passedlen
= strlen("PASSED"),
1137 unitlen
= strlen("UNIT"),
1138 activatelen
= strlen("ACTIVATES");
1140 const char *on
, *off
;
1142 assert(timer_infos
|| n
== 0);
1144 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1148 if (t
->next_elapse
> 0) {
1149 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1151 format_timestamp(tstamp
, sizeof(tstamp
), t
->next_elapse
);
1152 nextlen
= MAX(nextlen
, strlen(tstamp
) + 1);
1154 format_timestamp_relative(trel
, sizeof(trel
), t
->next_elapse
);
1155 leftlen
= MAX(leftlen
, strlen(trel
));
1158 if (t
->last_trigger
> 0) {
1159 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1161 format_timestamp(tstamp
, sizeof(tstamp
), t
->last_trigger
);
1162 lastlen
= MAX(lastlen
, strlen(tstamp
) + 1);
1164 format_timestamp_relative(trel
, sizeof(trel
), t
->last_trigger
);
1165 passedlen
= MAX(passedlen
, strlen(trel
));
1168 unitlen
= MAX(unitlen
, strlen(t
->id
) + (t
->machine
? strlen(t
->machine
)+1 : 0));
1170 STRV_FOREACH(a
, t
->triggered
)
1171 ul
+= strlen(*a
) + 2*(a
!= t
->triggered
);
1173 activatelen
= MAX(activatelen
, ul
);
1178 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1182 passedlen
, "PASSED",
1186 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1187 _cleanup_free_
char *j
= NULL
;
1189 char tstamp1
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel1
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1190 char tstamp2
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel2
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1193 format_timestamp(tstamp1
, sizeof(tstamp1
), t
->next_elapse
);
1194 format_timestamp_relative(trel1
, sizeof(trel1
), t
->next_elapse
);
1196 format_timestamp(tstamp2
, sizeof(tstamp2
), t
->last_trigger
);
1197 format_timestamp_relative(trel2
, sizeof(trel2
), t
->last_trigger
);
1200 j
= strjoin(t
->machine
, ":", t
->id
, NULL
);
1207 printf("%-*s %-*s %-*s %-*s %-*s",
1208 nextlen
, tstamp1
, leftlen
, trel1
, lastlen
, tstamp2
, passedlen
, trel2
, unitlen
, unit
);
1210 STRV_FOREACH(a
, t
->triggered
)
1212 a
== t
->triggered
? "" : ",", *a
);
1216 on
= ansi_highlight();
1217 off
= ansi_normal();
1221 on
= ansi_highlight_red();
1222 off
= ansi_normal();
1225 if (!arg_no_legend
) {
1226 printf("%s%u timers listed.%s\n", on
, n
, off
);
1228 printf("Pass --all to see loaded but inactive timers, too.\n");
1234 static usec_t
calc_next_elapse(dual_timestamp
*nw
, dual_timestamp
*next
) {
1240 if (next
->monotonic
!= USEC_INFINITY
&& next
->monotonic
> 0) {
1243 if (next
->monotonic
> nw
->monotonic
)
1244 converted
= nw
->realtime
+ (next
->monotonic
- nw
->monotonic
);
1246 converted
= nw
->realtime
- (nw
->monotonic
- next
->monotonic
);
1248 if (next
->realtime
!= USEC_INFINITY
&& next
->realtime
> 0)
1249 next_elapse
= MIN(converted
, next
->realtime
);
1251 next_elapse
= converted
;
1254 next_elapse
= next
->realtime
;
1259 static int list_timers(int argc
, char *argv
[], void *userdata
) {
1260 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
1261 _cleanup_strv_free_
char **machines
= NULL
;
1262 _cleanup_free_
struct timer_info
*timer_infos
= NULL
;
1263 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
1264 struct timer_info
*t
;
1272 r
= acquire_bus(BUS_MANAGER
, &bus
);
1276 pager_open(arg_no_pager
, false);
1278 n
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
1282 dual_timestamp_get(&nw
);
1284 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
1285 _cleanup_strv_free_
char **triggered
= NULL
;
1286 dual_timestamp next
= DUAL_TIMESTAMP_NULL
;
1289 if (!endswith(u
->id
, ".timer"))
1292 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
1296 r
= get_next_elapse(bus
, u
->unit_path
, &next
);
1300 get_last_trigger(bus
, u
->unit_path
, &last
);
1302 if (!GREEDY_REALLOC(timer_infos
, size
, c
+1)) {
1307 m
= calc_next_elapse(&nw
, &next
);
1309 timer_infos
[c
++] = (struct timer_info
) {
1310 .machine
= u
->machine
,
1313 .last_trigger
= last
,
1314 .triggered
= triggered
,
1317 triggered
= NULL
; /* avoid cleanup */
1320 qsort_safe(timer_infos
, c
, sizeof(struct timer_info
),
1321 (__compar_fn_t
) timer_info_compare
);
1323 output_timers_list(timer_infos
, c
);
1326 for (t
= timer_infos
; t
< timer_infos
+ c
; t
++)
1327 strv_free(t
->triggered
);
1332 static int compare_unit_file_list(const void *a
, const void *b
) {
1333 const char *d1
, *d2
;
1334 const UnitFileList
*u
= a
, *v
= b
;
1336 d1
= strrchr(u
->path
, '.');
1337 d2
= strrchr(v
->path
, '.');
1342 r
= strcasecmp(d1
, d2
);
1347 return strcasecmp(basename(u
->path
), basename(v
->path
));
1350 static bool output_show_unit_file(const UnitFileList
*u
, char **states
, char **patterns
) {
1353 if (!strv_fnmatch_or_empty(patterns
, basename(u
->path
), FNM_NOESCAPE
))
1356 if (!strv_isempty(arg_types
)) {
1359 dot
= strrchr(u
->path
, '.');
1363 if (!strv_find(arg_types
, dot
+1))
1367 if (!strv_isempty(states
) &&
1368 !strv_find(states
, unit_file_state_to_string(u
->state
)))
1374 static void output_unit_file_list(const UnitFileList
*units
, unsigned c
) {
1375 unsigned max_id_len
, id_cols
, state_cols
;
1376 const UnitFileList
*u
;
1378 max_id_len
= strlen("UNIT FILE");
1379 state_cols
= strlen("STATE");
1381 for (u
= units
; u
< units
+ c
; u
++) {
1382 max_id_len
= MAX(max_id_len
, strlen(basename(u
->path
)));
1383 state_cols
= MAX(state_cols
, strlen(unit_file_state_to_string(u
->state
)));
1387 unsigned basic_cols
;
1389 id_cols
= MIN(max_id_len
, 25u);
1390 basic_cols
= 1 + id_cols
+ state_cols
;
1391 if (basic_cols
< (unsigned) columns())
1392 id_cols
+= MIN(columns() - basic_cols
, max_id_len
- id_cols
);
1394 id_cols
= max_id_len
;
1396 if (!arg_no_legend
&& c
> 0)
1397 printf("%-*s %-*s\n",
1398 id_cols
, "UNIT FILE",
1399 state_cols
, "STATE");
1401 for (u
= units
; u
< units
+ c
; u
++) {
1402 _cleanup_free_
char *e
= NULL
;
1403 const char *on
, *off
;
1406 if (IN_SET(u
->state
,
1408 UNIT_FILE_MASKED_RUNTIME
,
1411 on
= ansi_highlight_red();
1412 off
= ansi_normal();
1413 } else if (u
->state
== UNIT_FILE_ENABLED
) {
1414 on
= ansi_highlight_green();
1415 off
= ansi_normal();
1419 id
= basename(u
->path
);
1421 e
= arg_full
? NULL
: ellipsize(id
, id_cols
, 33);
1423 printf("%-*s %s%-*s%s\n",
1424 id_cols
, e
? e
: id
,
1425 on
, state_cols
, unit_file_state_to_string(u
->state
), off
);
1429 printf("\n%u unit files listed.\n", c
);
1432 static int list_unit_files(int argc
, char *argv
[], void *userdata
) {
1433 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1434 _cleanup_free_ UnitFileList
*units
= NULL
;
1441 bool fallback
= false;
1443 if (install_client_side()) {
1449 h
= hashmap_new(&string_hash_ops
);
1453 r
= unit_file_get_list(arg_scope
, arg_root
, h
, arg_states
, strv_skip(argv
, 1));
1455 unit_file_list_free(h
);
1456 return log_error_errno(r
, "Failed to get unit file list: %m");
1459 n_units
= hashmap_size(h
);
1461 units
= new(UnitFileList
, n_units
?: 1); /* avoid malloc(0) */
1463 unit_file_list_free(h
);
1467 HASHMAP_FOREACH(u
, h
, i
) {
1468 if (!output_show_unit_file(u
, NULL
, NULL
))
1475 assert(c
<= n_units
);
1480 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
1481 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1484 r
= acquire_bus(BUS_MANAGER
, &bus
);
1488 r
= sd_bus_message_new_method_call(
1491 "org.freedesktop.systemd1",
1492 "/org/freedesktop/systemd1",
1493 "org.freedesktop.systemd1.Manager",
1494 "ListUnitFilesByPatterns");
1496 return bus_log_create_error(r
);
1498 r
= sd_bus_message_append_strv(m
, arg_states
);
1500 return bus_log_create_error(r
);
1502 r
= sd_bus_message_append_strv(m
, strv_skip(argv
, 1));
1504 return bus_log_create_error(r
);
1506 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
1507 if (r
< 0 && sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_METHOD
)) {
1508 /* Fallback to legacy ListUnitFiles method */
1510 log_debug_errno(r
, "Failed to list unit files: %s Falling back to ListUnitsFiles method.", bus_error_message(&error
, r
));
1511 m
= sd_bus_message_unref(m
);
1512 sd_bus_error_free(&error
);
1514 r
= sd_bus_message_new_method_call(
1517 "org.freedesktop.systemd1",
1518 "/org/freedesktop/systemd1",
1519 "org.freedesktop.systemd1.Manager",
1522 return bus_log_create_error(r
);
1524 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
1527 return log_error_errno(r
, "Failed to list unit files: %s", bus_error_message(&error
, r
));
1529 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
1531 return bus_log_parse_error(r
);
1533 while ((r
= sd_bus_message_read(reply
, "(ss)", &path
, &state
)) > 0) {
1535 if (!GREEDY_REALLOC(units
, size
, c
+ 1))
1538 units
[c
] = (struct UnitFileList
) {
1540 unit_file_state_from_string(state
)
1543 if (output_show_unit_file(&units
[c
],
1544 fallback
? arg_states
: NULL
,
1545 fallback
? strv_skip(argv
, 1) : NULL
))
1550 return bus_log_parse_error(r
);
1552 r
= sd_bus_message_exit_container(reply
);
1554 return bus_log_parse_error(r
);
1557 pager_open(arg_no_pager
, false);
1559 qsort_safe(units
, c
, sizeof(UnitFileList
), compare_unit_file_list
);
1560 output_unit_file_list(units
, c
);
1562 if (install_client_side())
1563 for (unit
= units
; unit
< units
+ c
; unit
++)
1569 static int list_dependencies_print(const char *name
, int level
, unsigned int branches
, bool last
) {
1570 _cleanup_free_
char *n
= NULL
;
1571 size_t max_len
= MAX(columns(),20u);
1577 for (i
= level
- 1; i
>= 0; i
--) {
1579 if (len
> max_len
- 3 && !arg_full
) {
1580 printf("%s...\n",max_len
% 2 ? "" : " ");
1583 printf("%s", special_glyph(branches
& (1 << i
) ? TREE_VERTICAL
: TREE_SPACE
));
1587 if (len
> max_len
- 3 && !arg_full
) {
1588 printf("%s...\n",max_len
% 2 ? "" : " ");
1592 printf("%s", special_glyph(last
? TREE_RIGHT
: TREE_BRANCH
));
1596 printf("%s\n", name
);
1600 n
= ellipsize(name
, max_len
-len
, 100);
1608 static int list_dependencies_get_dependencies(sd_bus
*bus
, const char *name
, char ***deps
) {
1610 static const char *dependencies
[_DEPENDENCY_MAX
] = {
1611 [DEPENDENCY_FORWARD
] = "Requires\0"
1616 [DEPENDENCY_REVERSE
] = "RequiredBy\0"
1621 [DEPENDENCY_AFTER
] = "After\0",
1622 [DEPENDENCY_BEFORE
] = "Before\0",
1625 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1626 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1627 _cleanup_strv_free_
char **ret
= NULL
;
1628 _cleanup_free_
char *path
= NULL
;
1634 assert_cc(ELEMENTSOF(dependencies
) == _DEPENDENCY_MAX
);
1636 path
= unit_dbus_path_from_name(name
);
1640 r
= sd_bus_call_method(
1642 "org.freedesktop.systemd1",
1644 "org.freedesktop.DBus.Properties",
1648 "s", "org.freedesktop.systemd1.Unit");
1650 return log_error_errno(r
, "Failed to get properties of %s: %s", name
, bus_error_message(&error
, r
));
1652 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
1654 return bus_log_parse_error(r
);
1656 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
1659 r
= sd_bus_message_read(reply
, "s", &prop
);
1661 return bus_log_parse_error(r
);
1663 if (!nulstr_contains(dependencies
[arg_dependency
], prop
)) {
1664 r
= sd_bus_message_skip(reply
, "v");
1666 return bus_log_parse_error(r
);
1669 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, "as");
1671 return bus_log_parse_error(r
);
1673 r
= bus_message_read_strv_extend(reply
, &ret
);
1675 return bus_log_parse_error(r
);
1677 r
= sd_bus_message_exit_container(reply
);
1679 return bus_log_parse_error(r
);
1682 r
= sd_bus_message_exit_container(reply
);
1684 return bus_log_parse_error(r
);
1688 return bus_log_parse_error(r
);
1690 r
= sd_bus_message_exit_container(reply
);
1692 return bus_log_parse_error(r
);
1700 static int list_dependencies_compare(const void *_a
, const void *_b
) {
1701 const char **a
= (const char**) _a
, **b
= (const char**) _b
;
1703 if (unit_name_to_type(*a
) == UNIT_TARGET
&& unit_name_to_type(*b
) != UNIT_TARGET
)
1705 if (unit_name_to_type(*a
) != UNIT_TARGET
&& unit_name_to_type(*b
) == UNIT_TARGET
)
1708 return strcasecmp(*a
, *b
);
1711 static int list_dependencies_one(
1716 unsigned int branches
) {
1718 _cleanup_strv_free_
char **deps
= NULL
;
1726 r
= strv_extend(units
, name
);
1730 r
= list_dependencies_get_dependencies(bus
, name
, &deps
);
1734 qsort_safe(deps
, strv_length(deps
), sizeof (char*), list_dependencies_compare
);
1736 STRV_FOREACH(c
, deps
) {
1737 if (strv_contains(*units
, *c
)) {
1739 r
= list_dependencies_print("...", level
+ 1, (branches
<< 1) | (c
[1] == NULL
? 0 : 1), 1);
1749 UnitActiveState active_state
= _UNIT_ACTIVE_STATE_INVALID
;
1752 (void) get_state_one_unit(bus
, *c
, &active_state
);
1754 switch (active_state
) {
1756 case UNIT_RELOADING
:
1757 case UNIT_ACTIVATING
:
1758 on
= ansi_highlight_green();
1762 case UNIT_DEACTIVATING
:
1767 on
= ansi_highlight_red();
1771 printf("%s%s%s ", on
, special_glyph(BLACK_CIRCLE
), ansi_normal());
1774 r
= list_dependencies_print(*c
, level
, branches
, c
[1] == NULL
);
1778 if (arg_all
|| unit_name_to_type(*c
) == UNIT_TARGET
) {
1779 r
= list_dependencies_one(bus
, *c
, level
+ 1, units
, (branches
<< 1) | (c
[1] == NULL
? 0 : 1));
1786 strv_remove(*units
, name
);
1791 static int list_dependencies(int argc
, char *argv
[], void *userdata
) {
1792 _cleanup_strv_free_
char **units
= NULL
;
1793 _cleanup_free_
char *unit
= NULL
;
1799 r
= unit_name_mangle(argv
[1], UNIT_NAME_NOGLOB
, &unit
);
1801 return log_error_errno(r
, "Failed to mangle unit name: %m");
1805 u
= SPECIAL_DEFAULT_TARGET
;
1807 r
= acquire_bus(BUS_MANAGER
, &bus
);
1811 pager_open(arg_no_pager
, false);
1815 return list_dependencies_one(bus
, u
, 0, &units
, 0);
1818 struct machine_info
{
1822 char *control_group
;
1823 uint32_t n_failed_units
;
1828 static const struct bus_properties_map machine_info_property_map
[] = {
1829 { "SystemState", "s", NULL
, offsetof(struct machine_info
, state
) },
1830 { "NJobs", "u", NULL
, offsetof(struct machine_info
, n_jobs
) },
1831 { "NFailedUnits", "u", NULL
, offsetof(struct machine_info
, n_failed_units
) },
1832 { "ControlGroup", "s", NULL
, offsetof(struct machine_info
, control_group
) },
1833 { "UserspaceTimestamp", "t", NULL
, offsetof(struct machine_info
, timestamp
) },
1837 static void machine_info_clear(struct machine_info
*info
) {
1842 free(info
->control_group
);
1846 static void free_machines_list(struct machine_info
*machine_infos
, int n
) {
1852 for (i
= 0; i
< n
; i
++)
1853 machine_info_clear(&machine_infos
[i
]);
1855 free(machine_infos
);
1858 static int compare_machine_info(const void *a
, const void *b
) {
1859 const struct machine_info
*u
= a
, *v
= b
;
1861 if (u
->is_host
!= v
->is_host
)
1862 return u
->is_host
> v
->is_host
? -1 : 1;
1864 return strcasecmp(u
->name
, v
->name
);
1867 static int get_machine_properties(sd_bus
*bus
, struct machine_info
*mi
) {
1868 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*container
= NULL
;
1874 r
= sd_bus_open_system_machine(&container
, mi
->name
);
1881 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, mi
);
1888 static bool output_show_machine(const char *name
, char **patterns
) {
1889 return strv_fnmatch_or_empty(patterns
, name
, FNM_NOESCAPE
);
1892 static int get_machine_list(
1894 struct machine_info
**_machine_infos
,
1897 struct machine_info
*machine_infos
= NULL
;
1898 _cleanup_strv_free_
char **m
= NULL
;
1899 _cleanup_free_
char *hn
= NULL
;
1904 hn
= gethostname_malloc();
1908 if (output_show_machine(hn
, patterns
)) {
1909 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1))
1912 machine_infos
[c
].is_host
= true;
1913 machine_infos
[c
].name
= hn
;
1916 get_machine_properties(bus
, &machine_infos
[c
]);
1920 r
= sd_get_machine_names(&m
);
1922 return log_error_errno(r
, "Failed to get machine list: %m");
1924 STRV_FOREACH(i
, m
) {
1925 _cleanup_free_
char *class = NULL
;
1927 if (!output_show_machine(*i
, patterns
))
1930 sd_machine_get_class(*i
, &class);
1931 if (!streq_ptr(class, "container"))
1934 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1)) {
1935 free_machines_list(machine_infos
, c
);
1939 machine_infos
[c
].is_host
= false;
1940 machine_infos
[c
].name
= strdup(*i
);
1941 if (!machine_infos
[c
].name
) {
1942 free_machines_list(machine_infos
, c
);
1946 get_machine_properties(NULL
, &machine_infos
[c
]);
1950 *_machine_infos
= machine_infos
;
1954 static void output_machines_list(struct machine_info
*machine_infos
, unsigned n
) {
1955 struct machine_info
*m
;
1958 namelen
= sizeof("NAME") - 1,
1959 statelen
= sizeof("STATE") - 1,
1960 failedlen
= sizeof("FAILED") - 1,
1961 jobslen
= sizeof("JOBS") - 1;
1963 assert(machine_infos
|| n
== 0);
1965 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
1966 namelen
= MAX(namelen
, strlen(m
->name
) + (m
->is_host
? sizeof(" (host)") - 1 : 0));
1967 statelen
= MAX(statelen
, m
->state
? strlen(m
->state
) : 0);
1968 failedlen
= MAX(failedlen
, DECIMAL_STR_WIDTH(m
->n_failed_units
));
1969 jobslen
= MAX(jobslen
, DECIMAL_STR_WIDTH(m
->n_jobs
));
1971 if (!arg_plain
&& !streq_ptr(m
->state
, "running"))
1975 if (!arg_no_legend
) {
1979 printf("%-*s %-*s %-*s %-*s\n",
1982 failedlen
, "FAILED",
1986 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
1987 const char *on_state
= "", *off_state
= "";
1988 const char *on_failed
= "", *off_failed
= "";
1989 bool circle
= false;
1991 if (streq_ptr(m
->state
, "degraded")) {
1992 on_state
= ansi_highlight_red();
1993 off_state
= ansi_normal();
1995 } else if (!streq_ptr(m
->state
, "running")) {
1996 on_state
= ansi_highlight_yellow();
1997 off_state
= ansi_normal();
2001 if (m
->n_failed_units
> 0) {
2002 on_failed
= ansi_highlight_red();
2003 off_failed
= ansi_normal();
2005 on_failed
= off_failed
= "";
2008 printf("%s%s%s ", on_state
, circle
? special_glyph(BLACK_CIRCLE
) : " ", off_state
);
2011 printf("%-*s (host) %s%-*s%s %s%*" PRIu32
"%s %*" PRIu32
"\n",
2012 (int) (namelen
- (sizeof(" (host)")-1)), strna(m
->name
),
2013 on_state
, statelen
, strna(m
->state
), off_state
,
2014 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
2015 jobslen
, m
->n_jobs
);
2017 printf("%-*s %s%-*s%s %s%*" PRIu32
"%s %*" PRIu32
"\n",
2018 namelen
, strna(m
->name
),
2019 on_state
, statelen
, strna(m
->state
), off_state
,
2020 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
2021 jobslen
, m
->n_jobs
);
2025 printf("\n%u machines listed.\n", n
);
2028 static int list_machines(int argc
, char *argv
[], void *userdata
) {
2029 struct machine_info
*machine_infos
= NULL
;
2033 if (geteuid() != 0) {
2034 log_error("Must be root.");
2038 r
= acquire_bus(BUS_MANAGER
, &bus
);
2042 r
= get_machine_list(bus
, &machine_infos
, strv_skip(argv
, 1));
2046 pager_open(arg_no_pager
, false);
2048 qsort_safe(machine_infos
, r
, sizeof(struct machine_info
), compare_machine_info
);
2049 output_machines_list(machine_infos
, r
);
2050 free_machines_list(machine_infos
, r
);
2055 static int get_default(int argc
, char *argv
[], void *userdata
) {
2056 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2057 _cleanup_free_
char *_path
= NULL
;
2061 if (install_client_side()) {
2062 r
= unit_file_get_default(arg_scope
, arg_root
, &_path
);
2064 return log_error_errno(r
, "Failed to get default target: %m");
2069 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2072 r
= acquire_bus(BUS_MANAGER
, &bus
);
2076 r
= sd_bus_call_method(
2078 "org.freedesktop.systemd1",
2079 "/org/freedesktop/systemd1",
2080 "org.freedesktop.systemd1.Manager",
2086 return log_error_errno(r
, "Failed to get default target: %s", bus_error_message(&error
, r
));
2088 r
= sd_bus_message_read(reply
, "s", &path
);
2090 return bus_log_parse_error(r
);
2094 printf("%s\n", path
);
2099 static int set_default(int argc
, char *argv
[], void *userdata
) {
2100 _cleanup_free_
char *unit
= NULL
;
2101 UnitFileChange
*changes
= NULL
;
2102 unsigned n_changes
= 0;
2108 r
= unit_name_mangle_with_suffix(argv
[1], UNIT_NAME_NOGLOB
, ".target", &unit
);
2110 return log_error_errno(r
, "Failed to mangle unit name: %m");
2112 if (install_client_side()) {
2113 r
= unit_file_set_default(arg_scope
, arg_root
, unit
, true, &changes
, &n_changes
);
2114 unit_file_dump_changes(r
, "set default", changes
, n_changes
, arg_quiet
);
2119 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2120 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2123 polkit_agent_open_if_enabled();
2125 r
= acquire_bus(BUS_MANAGER
, &bus
);
2129 r
= sd_bus_call_method(
2131 "org.freedesktop.systemd1",
2132 "/org/freedesktop/systemd1",
2133 "org.freedesktop.systemd1.Manager",
2139 return log_error_errno(r
, "Failed to set default target: %s", bus_error_message(&error
, r
));
2141 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
2145 /* Try to reload if enabled */
2147 r
= daemon_reload(argc
, argv
, userdata
);
2153 unit_file_changes_free(changes
, n_changes
);
2160 const char *name
, *type
, *state
;
2163 static void output_jobs_list(const struct job_info
* jobs
, unsigned n
, bool skipped
) {
2164 unsigned id_len
, unit_len
, type_len
, state_len
;
2165 const struct job_info
*j
;
2166 const char *on
, *off
;
2167 bool shorten
= false;
2169 assert(n
== 0 || jobs
);
2172 if (!arg_no_legend
) {
2173 on
= ansi_highlight_green();
2174 off
= ansi_normal();
2176 printf("%sNo jobs %s.%s\n", on
, skipped
? "listed" : "running", off
);
2181 pager_open(arg_no_pager
, false);
2183 id_len
= strlen("JOB");
2184 unit_len
= strlen("UNIT");
2185 type_len
= strlen("TYPE");
2186 state_len
= strlen("STATE");
2188 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2189 uint32_t id
= j
->id
;
2190 assert(j
->name
&& j
->type
&& j
->state
);
2192 id_len
= MAX(id_len
, DECIMAL_STR_WIDTH(id
));
2193 unit_len
= MAX(unit_len
, strlen(j
->name
));
2194 type_len
= MAX(type_len
, strlen(j
->type
));
2195 state_len
= MAX(state_len
, strlen(j
->state
));
2198 if (!arg_full
&& id_len
+ 1 + unit_len
+ type_len
+ 1 + state_len
> columns()) {
2199 unit_len
= MAX(33u, columns() - id_len
- type_len
- state_len
- 3);
2204 printf("%*s %-*s %-*s %-*s\n",
2208 state_len
, "STATE");
2210 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2211 _cleanup_free_
char *e
= NULL
;
2213 if (streq(j
->state
, "running")) {
2214 on
= ansi_highlight();
2215 off
= ansi_normal();
2219 e
= shorten
? ellipsize(j
->name
, unit_len
, 33) : NULL
;
2220 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2222 on
, unit_len
, e
? e
: j
->name
, off
,
2224 on
, state_len
, j
->state
, off
);
2227 if (!arg_no_legend
) {
2228 on
= ansi_highlight();
2229 off
= ansi_normal();
2231 printf("\n%s%u jobs listed%s.\n", on
, n
, off
);
2235 static bool output_show_job(struct job_info
*job
, char **patterns
) {
2236 return strv_fnmatch_or_empty(patterns
, job
->name
, FNM_NOESCAPE
);
2239 static int list_jobs(int argc
, char *argv
[], void *userdata
) {
2240 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2241 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2242 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2243 _cleanup_free_
struct job_info
*jobs
= NULL
;
2249 bool skipped
= false;
2251 r
= acquire_bus(BUS_MANAGER
, &bus
);
2255 r
= sd_bus_call_method(
2257 "org.freedesktop.systemd1",
2258 "/org/freedesktop/systemd1",
2259 "org.freedesktop.systemd1.Manager",
2265 return log_error_errno(r
, "Failed to list jobs: %s", bus_error_message(&error
, r
));
2267 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2269 return bus_log_parse_error(r
);
2271 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0) {
2272 struct job_info job
= { id
, name
, type
, state
};
2274 if (!output_show_job(&job
, strv_skip(argv
, 1))) {
2279 if (!GREEDY_REALLOC(jobs
, size
, c
+ 1))
2285 return bus_log_parse_error(r
);
2287 r
= sd_bus_message_exit_container(reply
);
2289 return bus_log_parse_error(r
);
2291 pager_open(arg_no_pager
, false);
2293 output_jobs_list(jobs
, c
, skipped
);
2297 static int cancel_job(int argc
, char *argv
[], void *userdata
) {
2303 return trivial_method(argc
, argv
, userdata
);
2305 r
= acquire_bus(BUS_MANAGER
, &bus
);
2309 polkit_agent_open_if_enabled();
2311 STRV_FOREACH(name
, strv_skip(argv
, 1)) {
2312 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2316 q
= safe_atou32(*name
, &id
);
2318 return log_error_errno(q
, "Failed to parse job id \"%s\": %m", *name
);
2320 q
= sd_bus_call_method(
2322 "org.freedesktop.systemd1",
2323 "/org/freedesktop/systemd1",
2324 "org.freedesktop.systemd1.Manager",
2330 log_error_errno(q
, "Failed to cancel job %"PRIu32
": %s", id
, bus_error_message(&error
, q
));
2339 static int need_daemon_reload(sd_bus
*bus
, const char *unit
) {
2340 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2344 /* We ignore all errors here, since this is used to show a
2347 /* We don't use unit_dbus_path_from_name() directly since we
2348 * don't want to load the unit if it isn't loaded. */
2350 r
= sd_bus_call_method(
2352 "org.freedesktop.systemd1",
2353 "/org/freedesktop/systemd1",
2354 "org.freedesktop.systemd1.Manager",
2362 r
= sd_bus_message_read(reply
, "o", &path
);
2366 r
= sd_bus_get_property_trivial(
2368 "org.freedesktop.systemd1",
2370 "org.freedesktop.systemd1.Unit",
2380 static void warn_unit_file_changed(const char *name
) {
2383 log_warning("%sWarning:%s %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
2384 ansi_highlight_red(),
2387 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user");
2390 static int unit_file_find_path(LookupPaths
*lp
, const char *unit_name
, char **unit_path
) {
2397 STRV_FOREACH(p
, lp
->search_path
) {
2398 _cleanup_free_
char *path
;
2400 path
= path_join(arg_root
, *p
, unit_name
);
2404 if (access(path
, F_OK
) == 0) {
2414 static int unit_find_paths(
2416 const char *unit_name
,
2418 char **fragment_path
,
2419 char ***dropin_paths
) {
2421 _cleanup_free_
char *path
= NULL
;
2422 _cleanup_strv_free_
char **dropins
= NULL
;
2426 * Finds where the unit is defined on disk. Returns 0 if the unit
2427 * is not found. Returns 1 if it is found, and sets
2428 * - the path to the unit in *path, if it exists on disk,
2429 * - and a strv of existing drop-ins in *dropins,
2430 * if the arg is not NULL and any dropins were found.
2434 assert(fragment_path
);
2437 if (!install_client_side() && !unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
2438 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2439 _cleanup_free_
char *unit
= NULL
;
2441 unit
= unit_dbus_path_from_name(unit_name
);
2445 r
= sd_bus_get_property_string(
2447 "org.freedesktop.systemd1",
2449 "org.freedesktop.systemd1.Unit",
2454 return log_error_errno(r
, "Failed to get FragmentPath: %s", bus_error_message(&error
, r
));
2457 r
= sd_bus_get_property_strv(
2459 "org.freedesktop.systemd1",
2461 "org.freedesktop.systemd1.Unit",
2466 return log_error_errno(r
, "Failed to get DropInPaths: %s", bus_error_message(&error
, r
));
2469 _cleanup_set_free_ Set
*names
;
2471 names
= set_new(NULL
);
2475 r
= set_put(names
, unit_name
);
2477 return log_error_errno(r
, "Failed to add unit name: %m");
2479 r
= unit_file_find_path(lp
, unit_name
, &path
);
2484 _cleanup_free_
char *template = NULL
;
2486 r
= unit_name_template(unit_name
, &template);
2487 if (r
< 0 && r
!= -EINVAL
)
2488 return log_error_errno(r
, "Failed to determine template name: %m");
2490 r
= unit_file_find_path(lp
, template, &path
);
2497 r
= unit_file_find_dropin_paths(lp
->search_path
, NULL
, names
, &dropins
);
2505 if (!isempty(path
)) {
2506 *fragment_path
= path
;
2511 if (dropin_paths
&& !strv_isempty(dropins
)) {
2512 *dropin_paths
= dropins
;
2517 if (r
== 0 && !arg_force
)
2518 log_error("No files found for %s.", unit_name
);
2523 static int get_state_one_unit(sd_bus
*bus
, const char *name
, UnitActiveState
*active_state
) {
2524 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2525 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2526 _cleanup_free_
char *buf
= NULL
;
2527 UnitActiveState state
;
2532 assert(active_state
);
2534 /* We don't use unit_dbus_path_from_name() directly since we don't want to load the unit unnecessarily, if it
2536 r
= sd_bus_call_method(
2538 "org.freedesktop.systemd1",
2539 "/org/freedesktop/systemd1",
2540 "org.freedesktop.systemd1.Manager",
2546 if (!sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_UNIT
))
2547 return log_error_errno(r
, "Failed to retrieve unit: %s", bus_error_message(&error
, r
));
2549 /* The unit is currently not loaded, hence say it's "inactive", since all units that aren't loaded are
2550 * considered inactive. */
2551 state
= UNIT_INACTIVE
;
2554 r
= sd_bus_message_read(reply
, "o", &path
);
2556 return bus_log_parse_error(r
);
2558 r
= sd_bus_get_property_string(
2560 "org.freedesktop.systemd1",
2562 "org.freedesktop.systemd1.Unit",
2567 return log_error_errno(r
, "Failed to retrieve unit state: %s", bus_error_message(&error
, r
));
2569 state
= unit_active_state_from_string(buf
);
2570 if (state
== _UNIT_ACTIVE_STATE_INVALID
) {
2571 log_error("Invalid unit state '%s' for: %s", buf
, name
);
2576 *active_state
= state
;
2580 static int check_triggering_units(
2584 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2585 _cleanup_free_
char *path
= NULL
, *n
= NULL
, *load_state
= NULL
;
2586 _cleanup_strv_free_
char **triggered_by
= NULL
;
2587 bool print_warning_label
= true;
2588 UnitActiveState active_state
;
2592 r
= unit_name_mangle(name
, UNIT_NAME_NOGLOB
, &n
);
2594 return log_error_errno(r
, "Failed to mangle unit name: %m");
2596 path
= unit_dbus_path_from_name(n
);
2600 r
= sd_bus_get_property_string(
2602 "org.freedesktop.systemd1",
2604 "org.freedesktop.systemd1.Unit",
2609 return log_error_errno(r
, "Failed to get load state of %s: %s", n
, bus_error_message(&error
, r
));
2611 if (streq(load_state
, "masked"))
2614 r
= sd_bus_get_property_strv(
2616 "org.freedesktop.systemd1",
2618 "org.freedesktop.systemd1.Unit",
2623 return log_error_errno(r
, "Failed to get triggered by array of %s: %s", n
, bus_error_message(&error
, r
));
2625 STRV_FOREACH(i
, triggered_by
) {
2626 r
= get_state_one_unit(bus
, *i
, &active_state
);
2630 if (!IN_SET(active_state
, UNIT_ACTIVE
, UNIT_RELOADING
))
2633 if (print_warning_label
) {
2634 log_warning("Warning: Stopping %s, but it can still be activated by:", n
);
2635 print_warning_label
= false;
2638 log_warning(" %s", *i
);
2644 static const struct {
2647 } unit_actions
[] = {
2648 { "start", "StartUnit" },
2649 { "stop", "StopUnit" },
2650 { "condstop", "StopUnit" },
2651 { "reload", "ReloadUnit" },
2652 { "restart", "RestartUnit" },
2653 { "try-restart", "TryRestartUnit" },
2654 { "condrestart", "TryRestartUnit" },
2655 { "reload-or-restart", "ReloadOrRestartUnit" },
2656 { "try-reload-or-restart", "ReloadOrTryRestartUnit" },
2657 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2658 { "condreload", "ReloadOrTryRestartUnit" },
2659 { "force-reload", "ReloadOrTryRestartUnit" }
2662 static const char *verb_to_method(const char *verb
) {
2665 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2666 if (streq_ptr(unit_actions
[i
].verb
, verb
))
2667 return unit_actions
[i
].method
;
2672 static const char *method_to_verb(const char *method
) {
2675 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2676 if (streq_ptr(unit_actions
[i
].method
, method
))
2677 return unit_actions
[i
].verb
;
2682 static int start_unit_one(
2687 sd_bus_error
*error
,
2688 BusWaitForJobs
*w
) {
2690 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2699 log_debug("Calling manager for %s on %s, %s", method
, name
, mode
);
2701 r
= sd_bus_call_method(
2703 "org.freedesktop.systemd1",
2704 "/org/freedesktop/systemd1",
2705 "org.freedesktop.systemd1.Manager",
2713 /* There's always a fallback possible for legacy actions. */
2714 if (arg_action
!= ACTION_SYSTEMCTL
)
2717 verb
= method_to_verb(method
);
2719 log_error("Failed to %s %s: %s", verb
, name
, bus_error_message(error
, r
));
2721 if (!sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) &&
2722 !sd_bus_error_has_name(error
, BUS_ERROR_UNIT_MASKED
))
2723 log_error("See %s logs and 'systemctl%s status %s' for details.",
2724 arg_scope
== UNIT_FILE_SYSTEM
? "system" : "user",
2725 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user",
2731 r
= sd_bus_message_read(reply
, "o", &path
);
2733 return bus_log_parse_error(r
);
2735 if (need_daemon_reload(bus
, name
) > 0)
2736 warn_unit_file_changed(name
);
2739 log_debug("Adding %s to the set", path
);
2740 r
= bus_wait_for_jobs_add(w
, path
);
2748 static int expand_names(sd_bus
*bus
, char **names
, const char* suffix
, char ***ret
) {
2749 _cleanup_strv_free_
char **mangled
= NULL
, **globs
= NULL
;
2756 STRV_FOREACH(name
, names
) {
2760 r
= unit_name_mangle_with_suffix(*name
, UNIT_NAME_GLOB
, suffix
, &t
);
2762 r
= unit_name_mangle(*name
, UNIT_NAME_GLOB
, &t
);
2764 return log_error_errno(r
, "Failed to mangle name: %m");
2766 if (string_is_glob(t
))
2767 r
= strv_consume(&globs
, t
);
2769 r
= strv_consume(&mangled
, t
);
2774 /* Query the manager only if any of the names are a glob, since
2775 * this is fairly expensive */
2776 if (!strv_isempty(globs
)) {
2777 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2778 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
2779 size_t allocated
, n
;
2781 r
= get_unit_list(bus
, NULL
, globs
, &unit_infos
, 0, &reply
);
2785 n
= strv_length(mangled
);
2788 for (i
= 0; i
< r
; i
++) {
2789 if (!GREEDY_REALLOC(mangled
, allocated
, n
+2))
2792 mangled
[n
] = strdup(unit_infos
[i
].id
);
2796 mangled
[++n
] = NULL
;
2801 mangled
= NULL
; /* do not free */
2806 static const struct {
2810 } action_table
[_ACTION_MAX
] = {
2811 [ACTION_HALT
] = { SPECIAL_HALT_TARGET
, "halt", "replace-irreversibly" },
2812 [ACTION_POWEROFF
] = { SPECIAL_POWEROFF_TARGET
, "poweroff", "replace-irreversibly" },
2813 [ACTION_REBOOT
] = { SPECIAL_REBOOT_TARGET
, "reboot", "replace-irreversibly" },
2814 [ACTION_KEXEC
] = { SPECIAL_KEXEC_TARGET
, "kexec", "replace-irreversibly" },
2815 [ACTION_RUNLEVEL2
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2816 [ACTION_RUNLEVEL3
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2817 [ACTION_RUNLEVEL4
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2818 [ACTION_RUNLEVEL5
] = { SPECIAL_GRAPHICAL_TARGET
, NULL
, "isolate" },
2819 [ACTION_RESCUE
] = { SPECIAL_RESCUE_TARGET
, "rescue", "isolate" },
2820 [ACTION_EMERGENCY
] = { SPECIAL_EMERGENCY_TARGET
, "emergency", "isolate" },
2821 [ACTION_DEFAULT
] = { SPECIAL_DEFAULT_TARGET
, "default", "isolate" },
2822 [ACTION_EXIT
] = { SPECIAL_EXIT_TARGET
, "exit", "replace-irreversibly" },
2823 [ACTION_SUSPEND
] = { SPECIAL_SUSPEND_TARGET
, "suspend", "replace-irreversibly" },
2824 [ACTION_HIBERNATE
] = { SPECIAL_HIBERNATE_TARGET
, "hibernate", "replace-irreversibly" },
2825 [ACTION_HYBRID_SLEEP
] = { SPECIAL_HYBRID_SLEEP_TARGET
, "hybrid-sleep", "replace-irreversibly" },
2828 static enum action
verb_to_action(const char *verb
) {
2831 for (i
= _ACTION_INVALID
; i
< _ACTION_MAX
; i
++)
2832 if (streq_ptr(action_table
[i
].verb
, verb
))
2835 return _ACTION_INVALID
;
2838 static int start_unit(int argc
, char *argv
[], void *userdata
) {
2839 _cleanup_(bus_wait_for_jobs_freep
) BusWaitForJobs
*w
= NULL
;
2840 const char *method
, *mode
, *one_name
, *suffix
= NULL
;
2841 _cleanup_strv_free_
char **names
= NULL
;
2846 r
= acquire_bus(BUS_MANAGER
, &bus
);
2850 ask_password_agent_open_if_enabled();
2851 polkit_agent_open_if_enabled();
2853 if (arg_action
== ACTION_SYSTEMCTL
) {
2856 method
= verb_to_method(argv
[0]);
2857 action
= verb_to_action(argv
[0]);
2859 if (streq(argv
[0], "isolate")) {
2863 mode
= action_table
[action
].mode
?: arg_job_mode
;
2865 one_name
= action_table
[action
].target
;
2867 assert(arg_action
< ELEMENTSOF(action_table
));
2868 assert(action_table
[arg_action
].target
);
2870 method
= "StartUnit";
2872 mode
= action_table
[arg_action
].mode
;
2873 one_name
= action_table
[arg_action
].target
;
2877 names
= strv_new(one_name
, NULL
);
2879 r
= expand_names(bus
, strv_skip(argv
, 1), suffix
, &names
);
2881 return log_error_errno(r
, "Failed to expand names: %m");
2884 if (!arg_no_block
) {
2885 r
= bus_wait_for_jobs_new(bus
, &w
);
2887 return log_error_errno(r
, "Could not watch jobs: %m");
2890 STRV_FOREACH(name
, names
) {
2891 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2894 q
= start_unit_one(bus
, method
, *name
, mode
, &error
, w
);
2895 if (r
>= 0 && q
< 0)
2896 r
= translate_bus_error_to_exit_status(q
, &error
);
2899 if (!arg_no_block
) {
2900 int q
, arg_count
= 0;
2901 const char* extra_args
[4] = {};
2903 if (arg_scope
!= UNIT_FILE_SYSTEM
)
2904 extra_args
[arg_count
++] = "--user";
2906 assert(IN_SET(arg_transport
, BUS_TRANSPORT_LOCAL
, BUS_TRANSPORT_REMOTE
, BUS_TRANSPORT_MACHINE
));
2907 if (arg_transport
== BUS_TRANSPORT_REMOTE
) {
2908 extra_args
[arg_count
++] = "-H";
2909 extra_args
[arg_count
++] = arg_host
;
2910 } else if (arg_transport
== BUS_TRANSPORT_MACHINE
) {
2911 extra_args
[arg_count
++] = "-M";
2912 extra_args
[arg_count
++] = arg_host
;
2915 q
= bus_wait_for_jobs(w
, arg_quiet
, extra_args
);
2919 /* When stopping units, warn if they can still be triggered by
2920 * another active unit (socket, path, timer) */
2921 if (!arg_quiet
&& streq(method
, "StopUnit"))
2922 STRV_FOREACH(name
, names
)
2923 check_triggering_units(bus
, *name
);
2929 static int logind_set_wall_message(void) {
2931 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2933 _cleanup_free_
char *m
= NULL
;
2936 r
= acquire_bus(BUS_FULL
, &bus
);
2940 m
= strv_join(arg_wall
, " ");
2944 r
= sd_bus_call_method(
2946 "org.freedesktop.login1",
2947 "/org/freedesktop/login1",
2948 "org.freedesktop.login1.Manager",
2957 return log_warning_errno(r
, "Failed to set wall message, ignoring: %s", bus_error_message(&error
, r
));
2963 /* Ask systemd-logind, which might grant access to unprivileged users
2964 * through PolicyKit */
2965 static int logind_reboot(enum action a
) {
2967 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2968 const char *method
, *description
;
2972 r
= acquire_bus(BUS_FULL
, &bus
);
2980 description
= "reboot system";
2983 case ACTION_POWEROFF
:
2984 method
= "PowerOff";
2985 description
= "power off system";
2988 case ACTION_SUSPEND
:
2990 description
= "suspend system";
2993 case ACTION_HIBERNATE
:
2994 method
= "Hibernate";
2995 description
= "hibernate system";
2998 case ACTION_HYBRID_SLEEP
:
2999 method
= "HybridSleep";
3000 description
= "put system into hybrid sleep";
3007 polkit_agent_open_if_enabled();
3008 (void) logind_set_wall_message();
3010 r
= sd_bus_call_method(
3012 "org.freedesktop.login1",
3013 "/org/freedesktop/login1",
3014 "org.freedesktop.login1.Manager",
3018 "b", arg_ask_password
);
3020 return log_error_errno(r
, "Failed to %s via logind: %s", description
, bus_error_message(&error
, r
));
3028 static int logind_check_inhibitors(enum action a
) {
3030 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
3031 _cleanup_strv_free_
char **sessions
= NULL
;
3032 const char *what
, *who
, *why
, *mode
;
3039 if (arg_ignore_inhibitors
|| arg_force
> 0)
3051 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
3054 r
= acquire_bus(BUS_FULL
, &bus
);
3058 r
= sd_bus_call_method(
3060 "org.freedesktop.login1",
3061 "/org/freedesktop/login1",
3062 "org.freedesktop.login1.Manager",
3068 /* If logind is not around, then there are no inhibitors... */
3071 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssuu)");
3073 return bus_log_parse_error(r
);
3075 while ((r
= sd_bus_message_read(reply
, "(ssssuu)", &what
, &who
, &why
, &mode
, &uid
, &pid
)) > 0) {
3076 _cleanup_free_
char *comm
= NULL
, *user
= NULL
;
3077 _cleanup_strv_free_
char **sv
= NULL
;
3079 if (!streq(mode
, "block"))
3082 sv
= strv_split(what
, ":");
3086 if ((pid_t
) pid
< 0)
3087 return log_error_errno(ERANGE
, "Bad PID %"PRIu32
": %m", pid
);
3089 if (!strv_contains(sv
,
3094 ACTION_KEXEC
) ? "shutdown" : "sleep"))
3097 get_process_comm(pid
, &comm
);
3098 user
= uid_to_name(uid
);
3100 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT
" \"%s\", user %s), reason is \"%s\".",
3101 who
, (pid_t
) pid
, strna(comm
), strna(user
), why
);
3106 return bus_log_parse_error(r
);
3108 r
= sd_bus_message_exit_container(reply
);
3110 return bus_log_parse_error(r
);
3112 /* Check for current sessions */
3113 sd_get_sessions(&sessions
);
3114 STRV_FOREACH(s
, sessions
) {
3115 _cleanup_free_
char *type
= NULL
, *tty
= NULL
, *seat
= NULL
, *user
= NULL
, *service
= NULL
, *class = NULL
;
3117 if (sd_session_get_uid(*s
, &uid
) < 0 || uid
== getuid())
3120 if (sd_session_get_class(*s
, &class) < 0 || !streq(class, "user"))
3123 if (sd_session_get_type(*s
, &type
) < 0 || (!streq(type
, "x11") && !streq(type
, "tty")))
3126 sd_session_get_tty(*s
, &tty
);
3127 sd_session_get_seat(*s
, &seat
);
3128 sd_session_get_service(*s
, &service
);
3129 user
= uid_to_name(uid
);
3131 log_warning("User %s is logged in on %s.", strna(user
), isempty(tty
) ? (isempty(seat
) ? strna(service
) : seat
) : tty
);
3138 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
3139 action_table
[a
].verb
);
3147 static int logind_prepare_firmware_setup(void) {
3149 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3153 r
= acquire_bus(BUS_FULL
, &bus
);
3157 r
= sd_bus_call_method(
3159 "org.freedesktop.login1",
3160 "/org/freedesktop/login1",
3161 "org.freedesktop.login1.Manager",
3162 "SetRebootToFirmwareSetup",
3167 return log_error_errno(r
, "Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error
, r
));
3171 log_error("Cannot remotely indicate to EFI to boot into setup mode.");
3176 static int prepare_firmware_setup(void) {
3179 if (!arg_firmware_setup
)
3182 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
3184 r
= efi_set_reboot_to_firmware(true);
3186 log_debug_errno(r
, "Cannot indicate to EFI to boot into setup mode, will retry via logind: %m");
3191 return logind_prepare_firmware_setup();
3194 static int set_exit_code(uint8_t code
) {
3195 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3199 r
= acquire_bus(BUS_MANAGER
, &bus
);
3203 r
= sd_bus_call_method(
3205 "org.freedesktop.systemd1",
3206 "/org/freedesktop/systemd1",
3207 "org.freedesktop.systemd1.Manager",
3213 return log_error_errno(r
, "Failed to set exit code: %s", bus_error_message(&error
, r
));
3218 static int start_special(int argc
, char *argv
[], void *userdata
) {
3224 a
= verb_to_action(argv
[0]);
3226 r
= logind_check_inhibitors(a
);
3230 if (arg_force
>= 2 && geteuid() != 0) {
3231 log_error("Must be root.");
3235 r
= prepare_firmware_setup();
3239 if (a
== ACTION_REBOOT
&& argc
> 1) {
3240 r
= update_reboot_parameter_and_warn(argv
[1]);
3244 } else if (a
== ACTION_EXIT
&& argc
> 1) {
3247 /* If the exit code is not given on the command line,
3248 * don't reset it to zero: just keep it as it might
3249 * have been set previously. */
3251 r
= safe_atou8(argv
[1], &code
);
3253 return log_error_errno(r
, "Invalid exit code.");
3255 r
= set_exit_code(code
);
3260 if (arg_force
>= 2 &&
3267 if (arg_force
>= 1 &&
3274 return trivial_method(argc
, argv
, userdata
);
3276 /* First try logind, to allow authentication with polkit */
3282 ACTION_HYBRID_SLEEP
)) {
3283 r
= logind_reboot(a
);
3286 if (IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
3287 /* requested operation is not supported or already in progress */
3290 /* On all other errors, try low-level operation */
3293 return start_unit(argc
, argv
, userdata
);
3296 static int start_system_special(int argc
, char *argv
[], void *userdata
) {
3297 /* Like start_special above, but raises an error when running in user mode */
3299 if (arg_scope
!= UNIT_FILE_SYSTEM
) {
3300 log_error("Bad action for %s mode.",
3301 arg_scope
== UNIT_FILE_GLOBAL
? "--global" : "--user");
3305 return start_special(argc
, argv
, userdata
);
3308 static int check_unit_generic(int code
, const UnitActiveState good_states
[], int nb_states
, char **args
) {
3309 _cleanup_strv_free_
char **names
= NULL
;
3310 UnitActiveState active_state
;
3316 r
= acquire_bus(BUS_MANAGER
, &bus
);
3320 r
= expand_names(bus
, args
, NULL
, &names
);
3322 return log_error_errno(r
, "Failed to expand names: %m");
3324 STRV_FOREACH(name
, names
) {
3325 r
= get_state_one_unit(bus
, *name
, &active_state
);
3330 puts(unit_active_state_to_string(active_state
));
3332 for (i
= 0; i
< nb_states
; ++i
)
3333 if (good_states
[i
] == active_state
)
3337 /* use the given return code for the case that we won't find
3338 * any unit which matches the list */
3339 return found
? 0 : code
;
3342 static int check_unit_active(int argc
, char *argv
[], void *userdata
) {
3343 const UnitActiveState states
[] = { UNIT_ACTIVE
, UNIT_RELOADING
};
3344 /* According to LSB: 3, "program is not running" */
3345 return check_unit_generic(EXIT_PROGRAM_NOT_RUNNING
, states
, ELEMENTSOF(states
), strv_skip(argv
, 1));
3348 static int check_unit_failed(int argc
, char *argv
[], void *userdata
) {
3349 const UnitActiveState states
[] = { UNIT_FAILED
};
3350 return check_unit_generic(EXIT_PROGRAM_DEAD_AND_PID_EXISTS
, states
, ELEMENTSOF(states
), strv_skip(argv
, 1));
3353 static int kill_unit(int argc
, char *argv
[], void *userdata
) {
3354 _cleanup_strv_free_
char **names
= NULL
;
3355 char *kill_who
= NULL
, **name
;
3359 r
= acquire_bus(BUS_MANAGER
, &bus
);
3363 polkit_agent_open_if_enabled();
3366 arg_kill_who
= "all";
3368 /* --fail was specified */
3369 if (streq(arg_job_mode
, "fail"))
3370 kill_who
= strjoina(arg_kill_who
, "-fail");
3372 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
3374 return log_error_errno(r
, "Failed to expand names: %m");
3376 STRV_FOREACH(name
, names
) {
3377 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3379 q
= sd_bus_call_method(
3381 "org.freedesktop.systemd1",
3382 "/org/freedesktop/systemd1",
3383 "org.freedesktop.systemd1.Manager",
3387 "ssi", *names
, kill_who
? kill_who
: arg_kill_who
, arg_signal
);
3389 log_error_errno(q
, "Failed to kill unit %s: %s", *names
, bus_error_message(&error
, q
));
3398 typedef struct ExecStatusInfo
{
3406 usec_t start_timestamp
;
3407 usec_t exit_timestamp
;
3412 LIST_FIELDS(struct ExecStatusInfo
, exec
);
3415 static void exec_status_info_free(ExecStatusInfo
*i
) {
3424 static int exec_status_info_deserialize(sd_bus_message
*m
, ExecStatusInfo
*i
) {
3425 uint64_t start_timestamp
, exit_timestamp
, start_timestamp_monotonic
, exit_timestamp_monotonic
;
3428 int32_t code
, status
;
3434 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_STRUCT
, "sasbttttuii");
3436 return bus_log_parse_error(r
);
3440 r
= sd_bus_message_read(m
, "s", &path
);
3442 return bus_log_parse_error(r
);
3444 i
->path
= strdup(path
);
3448 r
= sd_bus_message_read_strv(m
, &i
->argv
);
3450 return bus_log_parse_error(r
);
3452 r
= sd_bus_message_read(m
,
3455 &start_timestamp
, &start_timestamp_monotonic
,
3456 &exit_timestamp
, &exit_timestamp_monotonic
,
3460 return bus_log_parse_error(r
);
3463 i
->start_timestamp
= (usec_t
) start_timestamp
;
3464 i
->exit_timestamp
= (usec_t
) exit_timestamp
;
3465 i
->pid
= (pid_t
) pid
;
3469 r
= sd_bus_message_exit_container(m
);
3471 return bus_log_parse_error(r
);
3476 typedef struct UnitCondition
{
3483 LIST_FIELDS(struct UnitCondition
, conditions
);
3486 static void unit_condition_free(UnitCondition
*c
) {
3495 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitCondition
*, unit_condition_free
);
3497 typedef struct UnitStatusInfo
{
3499 const char *load_state
;
3500 const char *active_state
;
3501 const char *sub_state
;
3502 const char *unit_file_state
;
3503 const char *unit_file_preset
;
3505 const char *description
;
3506 const char *following
;
3508 char **documentation
;
3510 const char *fragment_path
;
3511 const char *source_path
;
3512 const char *control_group
;
3514 char **dropin_paths
;
3516 const char *load_error
;
3519 usec_t inactive_exit_timestamp
;
3520 usec_t inactive_exit_timestamp_monotonic
;
3521 usec_t active_enter_timestamp
;
3522 usec_t active_exit_timestamp
;
3523 usec_t inactive_enter_timestamp
;
3525 bool need_daemon_reload
;
3531 const char *status_text
;
3532 const char *pid_file
;
3536 usec_t start_timestamp
;
3537 usec_t exit_timestamp
;
3539 int exit_code
, exit_status
;
3541 usec_t condition_timestamp
;
3542 bool condition_result
;
3543 LIST_HEAD(UnitCondition
, conditions
);
3545 usec_t assert_timestamp
;
3547 bool failed_assert_trigger
;
3548 bool failed_assert_negate
;
3549 const char *failed_assert
;
3550 const char *failed_assert_parameter
;
3553 unsigned n_accepted
;
3554 unsigned n_connections
;
3557 /* Pairs of type, path */
3561 const char *sysfs_path
;
3563 /* Mount, Automount */
3570 uint64_t memory_current
;
3571 uint64_t memory_low
;
3572 uint64_t memory_high
;
3573 uint64_t memory_max
;
3574 uint64_t memory_limit
;
3575 uint64_t cpu_usage_nsec
;
3576 uint64_t tasks_current
;
3579 LIST_HEAD(ExecStatusInfo
, exec
);
3582 static void unit_status_info_free(UnitStatusInfo
*info
) {
3586 strv_free(info
->documentation
);
3587 strv_free(info
->dropin_paths
);
3588 strv_free(info
->listen
);
3590 while ((c
= info
->conditions
)) {
3591 LIST_REMOVE(conditions
, info
->conditions
, c
);
3592 unit_condition_free(c
);
3595 while ((p
= info
->exec
)) {
3596 LIST_REMOVE(exec
, info
->exec
, p
);
3597 exec_status_info_free(p
);
3601 static void print_status_info(
3607 const char *active_on
, *active_off
, *on
, *off
, *ss
;
3609 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], *s1
;
3610 char since2
[FORMAT_TIMESTAMP_MAX
], *s2
;
3617 /* This shows pretty information about a unit. See
3618 * print_property() for a low-level property printer */
3620 if (streq_ptr(i
->active_state
, "failed")) {
3621 active_on
= ansi_highlight_red();
3622 active_off
= ansi_normal();
3623 } else if (streq_ptr(i
->active_state
, "active") || streq_ptr(i
->active_state
, "reloading")) {
3624 active_on
= ansi_highlight_green();
3625 active_off
= ansi_normal();
3627 active_on
= active_off
= "";
3629 printf("%s%s%s %s", active_on
, special_glyph(BLACK_CIRCLE
), active_off
, strna(i
->id
));
3631 if (i
->description
&& !streq_ptr(i
->id
, i
->description
))
3632 printf(" - %s", i
->description
);
3637 printf(" Follow: unit currently follows state of %s\n", i
->following
);
3639 if (streq_ptr(i
->load_state
, "error")) {
3640 on
= ansi_highlight_red();
3641 off
= ansi_normal();
3645 path
= i
->source_path
? i
->source_path
: i
->fragment_path
;
3647 if (i
->load_error
!= 0)
3648 printf(" Loaded: %s%s%s (Reason: %s)\n",
3649 on
, strna(i
->load_state
), off
, i
->load_error
);
3650 else if (path
&& !isempty(i
->unit_file_state
) && !isempty(i
->unit_file_preset
))
3651 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
3652 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
, i
->unit_file_preset
);
3653 else if (path
&& !isempty(i
->unit_file_state
))
3654 printf(" Loaded: %s%s%s (%s; %s)\n",
3655 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
);
3657 printf(" Loaded: %s%s%s (%s)\n",
3658 on
, strna(i
->load_state
), off
, path
);
3660 printf(" Loaded: %s%s%s\n",
3661 on
, strna(i
->load_state
), off
);
3664 printf("Transient: yes\n");
3666 if (!strv_isempty(i
->dropin_paths
)) {
3667 _cleanup_free_
char *dir
= NULL
;
3671 STRV_FOREACH(dropin
, i
->dropin_paths
) {
3672 if (! dir
|| last
) {
3673 printf(dir
? " " : " Drop-In: ");
3677 dir
= dirname_malloc(*dropin
);
3683 printf("%s\n %s", dir
,
3684 special_glyph(TREE_RIGHT
));
3687 last
= ! (*(dropin
+ 1) && startswith(*(dropin
+ 1), dir
));
3689 printf("%s%s", basename(*dropin
), last
? "\n" : ", ");
3693 ss
= streq_ptr(i
->active_state
, i
->sub_state
) ? NULL
: i
->sub_state
;
3695 printf(" Active: %s%s (%s)%s",
3696 active_on
, strna(i
->active_state
), ss
, active_off
);
3698 printf(" Active: %s%s%s",
3699 active_on
, strna(i
->active_state
), active_off
);
3701 if (!isempty(i
->result
) && !streq(i
->result
, "success"))
3702 printf(" (Result: %s)", i
->result
);
3704 timestamp
= (streq_ptr(i
->active_state
, "active") ||
3705 streq_ptr(i
->active_state
, "reloading")) ? i
->active_enter_timestamp
:
3706 (streq_ptr(i
->active_state
, "inactive") ||
3707 streq_ptr(i
->active_state
, "failed")) ? i
->inactive_enter_timestamp
:
3708 streq_ptr(i
->active_state
, "activating") ? i
->inactive_exit_timestamp
:
3709 i
->active_exit_timestamp
;
3711 s1
= format_timestamp_relative(since1
, sizeof(since1
), timestamp
);
3712 s2
= format_timestamp(since2
, sizeof(since2
), timestamp
);
3715 printf(" since %s; %s\n", s2
, s1
);
3717 printf(" since %s\n", s2
);
3721 if (!i
->condition_result
&& i
->condition_timestamp
> 0) {
3725 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->condition_timestamp
);
3726 s2
= format_timestamp(since2
, sizeof(since2
), i
->condition_timestamp
);
3728 printf("Condition: start %scondition failed%s at %s%s%s\n",
3729 ansi_highlight_yellow(), ansi_normal(),
3730 s2
, s1
? "; " : "", strempty(s1
));
3732 LIST_FOREACH(conditions
, c
, i
->conditions
)
3733 if (c
->tristate
< 0)
3736 LIST_FOREACH(conditions
, c
, i
->conditions
)
3737 if (c
->tristate
< 0)
3738 printf(" %s %s=%s%s%s was not met\n",
3739 --n
? special_glyph(TREE_BRANCH
) : special_glyph(TREE_RIGHT
),
3741 c
->trigger
? "|" : "",
3742 c
->negate
? "!" : "",
3746 if (!i
->assert_result
&& i
->assert_timestamp
> 0) {
3747 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->assert_timestamp
);
3748 s2
= format_timestamp(since2
, sizeof(since2
), i
->assert_timestamp
);
3750 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
3751 ansi_highlight_red(), ansi_normal(),
3752 s2
, s1
? "; " : "", strempty(s1
));
3753 if (i
->failed_assert_trigger
)
3754 printf(" none of the trigger assertions were met\n");
3755 else if (i
->failed_assert
)
3756 printf(" %s=%s%s was not met\n",
3758 i
->failed_assert_negate
? "!" : "",
3759 i
->failed_assert_parameter
);
3763 printf(" Device: %s\n", i
->sysfs_path
);
3765 printf(" Where: %s\n", i
->where
);
3767 printf(" What: %s\n", i
->what
);
3769 STRV_FOREACH(t
, i
->documentation
)
3770 printf(" %*s %s\n", 9, t
== i
->documentation
? "Docs:" : "", *t
);
3772 STRV_FOREACH_PAIR(t
, t2
, i
->listen
)
3773 printf(" %*s %s (%s)\n", 9, t
== i
->listen
? "Listen:" : "", *t2
, *t
);
3776 printf(" Accepted: %u; Connected: %u\n", i
->n_accepted
, i
->n_connections
);
3778 LIST_FOREACH(exec
, p
, i
->exec
) {
3779 _cleanup_free_
char *argv
= NULL
;
3782 /* Only show exited processes here */
3786 argv
= strv_join(p
->argv
, " ");
3787 printf(" Process: "PID_FMT
" %s=%s ", p
->pid
, p
->name
, strna(argv
));
3789 good
= is_clean_exit_lsb(p
->code
, p
->status
, NULL
);
3791 on
= ansi_highlight_red();
3792 off
= ansi_normal();
3796 printf("%s(code=%s, ", on
, sigchld_code_to_string(p
->code
));
3798 if (p
->code
== CLD_EXITED
) {
3801 printf("status=%i", p
->status
);
3803 c
= exit_status_to_string(p
->status
, EXIT_STATUS_SYSTEMD
);
3808 printf("signal=%s", signal_to_string(p
->status
));
3810 printf(")%s\n", off
);
3812 if (i
->main_pid
== p
->pid
&&
3813 i
->start_timestamp
== p
->start_timestamp
&&
3814 i
->exit_timestamp
== p
->start_timestamp
)
3815 /* Let's not show this twice */
3818 if (p
->pid
== i
->control_pid
)
3822 if (i
->main_pid
> 0 || i
->control_pid
> 0) {
3823 if (i
->main_pid
> 0) {
3824 printf(" Main PID: "PID_FMT
, i
->main_pid
);
3827 _cleanup_free_
char *comm
= NULL
;
3828 (void) get_process_comm(i
->main_pid
, &comm
);
3830 printf(" (%s)", comm
);
3831 } else if (i
->exit_code
> 0) {
3832 printf(" (code=%s, ", sigchld_code_to_string(i
->exit_code
));
3834 if (i
->exit_code
== CLD_EXITED
) {
3837 printf("status=%i", i
->exit_status
);
3839 c
= exit_status_to_string(i
->exit_status
, EXIT_STATUS_SYSTEMD
);
3844 printf("signal=%s", signal_to_string(i
->exit_status
));
3849 if (i
->control_pid
> 0) {
3850 _cleanup_free_
char *c
= NULL
;
3852 if (i
->main_pid
> 0)
3853 fputs("; Control PID: ", stdout
);
3855 fputs("Cntrl PID: ", stdout
); /* if first in column, abbreviated so it fits alignment */
3857 printf(PID_FMT
, i
->control_pid
);
3859 (void) get_process_comm(i
->control_pid
, &c
);
3868 printf(" Status: \"%s\"\n", i
->status_text
);
3869 if (i
->status_errno
> 0)
3870 printf(" Error: %i (%s)\n", i
->status_errno
, strerror(i
->status_errno
));
3872 if (i
->tasks_current
!= (uint64_t) -1) {
3873 printf(" Tasks: %" PRIu64
, i
->tasks_current
);
3875 if (i
->tasks_max
!= (uint64_t) -1)
3876 printf(" (limit: %" PRIu64
")\n", i
->tasks_max
);
3881 if (i
->memory_current
!= (uint64_t) -1) {
3882 char buf
[FORMAT_BYTES_MAX
];
3884 printf(" Memory: %s", format_bytes(buf
, sizeof(buf
), i
->memory_current
));
3886 if (i
->memory_low
> 0 || i
->memory_high
!= CGROUP_LIMIT_MAX
|| i
->memory_max
!= CGROUP_LIMIT_MAX
||
3887 i
->memory_limit
!= CGROUP_LIMIT_MAX
) {
3888 const char *prefix
= "";
3891 if (i
->memory_low
> 0) {
3892 printf("%slow: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_low
));
3895 if (i
->memory_high
!= CGROUP_LIMIT_MAX
) {
3896 printf("%shigh: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_high
));
3899 if (i
->memory_max
!= CGROUP_LIMIT_MAX
) {
3900 printf("%smax: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_max
));
3903 if (i
->memory_limit
!= CGROUP_LIMIT_MAX
) {
3904 printf("%slimit: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_limit
));
3912 if (i
->cpu_usage_nsec
!= (uint64_t) -1) {
3913 char buf
[FORMAT_TIMESPAN_MAX
];
3914 printf(" CPU: %s\n", format_timespan(buf
, sizeof(buf
), i
->cpu_usage_nsec
/ NSEC_PER_USEC
, USEC_PER_MSEC
));
3917 if (i
->control_group
) {
3918 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3919 static const char prefix
[] = " ";
3922 printf(" CGroup: %s\n", i
->control_group
);
3925 if (c
> sizeof(prefix
) - 1)
3926 c
-= sizeof(prefix
) - 1;
3930 r
= unit_show_processes(bus
, i
->id
, i
->control_group
, prefix
, c
, get_output_flags(), &error
);
3935 /* Fallback for older systemd versions where the GetUnitProcesses() call is not yet available */
3937 if (i
->main_pid
> 0)
3938 extra
[k
++] = i
->main_pid
;
3940 if (i
->control_pid
> 0)
3941 extra
[k
++] = i
->control_pid
;
3943 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, prefix
, c
, extra
, k
, get_output_flags());
3945 log_warning_errno(r
, "Failed to dump process list, ignoring: %s", bus_error_message(&error
, r
));
3948 if (i
->id
&& arg_transport
== BUS_TRANSPORT_LOCAL
)
3949 show_journal_by_unit(
3954 i
->inactive_exit_timestamp_monotonic
,
3957 get_output_flags() | OUTPUT_BEGIN_NEWLINE
,
3958 SD_JOURNAL_LOCAL_ONLY
,
3959 arg_scope
== UNIT_FILE_SYSTEM
,
3962 if (i
->need_daemon_reload
)
3963 warn_unit_file_changed(i
->id
);
3966 static void show_unit_help(UnitStatusInfo
*i
) {
3971 if (!i
->documentation
) {
3972 log_info("Documentation for %s not known.", i
->id
);
3976 STRV_FOREACH(p
, i
->documentation
)
3977 if (startswith(*p
, "man:"))
3978 show_man_page(*p
+ 4, false);
3980 log_info("Can't show: %s", *p
);
3983 static int status_property(const char *name
, sd_bus_message
*m
, UnitStatusInfo
*i
, const char *contents
) {
3990 switch (contents
[0]) {
3992 case SD_BUS_TYPE_STRING
: {
3995 r
= sd_bus_message_read(m
, "s", &s
);
3997 return bus_log_parse_error(r
);
4000 if (streq(name
, "Id"))
4002 else if (streq(name
, "LoadState"))
4004 else if (streq(name
, "ActiveState"))
4005 i
->active_state
= s
;
4006 else if (streq(name
, "SubState"))
4008 else if (streq(name
, "Description"))
4010 else if (streq(name
, "FragmentPath"))
4011 i
->fragment_path
= s
;
4012 else if (streq(name
, "SourcePath"))
4015 else if (streq(name
, "DefaultControlGroup")) {
4017 e
= startswith(s
, SYSTEMD_CGROUP_CONTROLLER
":");
4019 i
->control_group
= e
;
4022 else if (streq(name
, "ControlGroup"))
4023 i
->control_group
= s
;
4024 else if (streq(name
, "StatusText"))
4026 else if (streq(name
, "PIDFile"))
4028 else if (streq(name
, "SysFSPath"))
4030 else if (streq(name
, "Where"))
4032 else if (streq(name
, "What"))
4034 else if (streq(name
, "Following"))
4036 else if (streq(name
, "UnitFileState"))
4037 i
->unit_file_state
= s
;
4038 else if (streq(name
, "UnitFilePreset"))
4039 i
->unit_file_preset
= s
;
4040 else if (streq(name
, "Result"))
4047 case SD_BUS_TYPE_BOOLEAN
: {
4050 r
= sd_bus_message_read(m
, "b", &b
);
4052 return bus_log_parse_error(r
);
4054 if (streq(name
, "Accept"))
4056 else if (streq(name
, "NeedDaemonReload"))
4057 i
->need_daemon_reload
= b
;
4058 else if (streq(name
, "ConditionResult"))
4059 i
->condition_result
= b
;
4060 else if (streq(name
, "AssertResult"))
4061 i
->assert_result
= b
;
4062 else if (streq(name
, "Transient"))
4068 case SD_BUS_TYPE_UINT32
: {
4071 r
= sd_bus_message_read(m
, "u", &u
);
4073 return bus_log_parse_error(r
);
4075 if (streq(name
, "MainPID")) {
4077 i
->main_pid
= (pid_t
) u
;
4080 } else if (streq(name
, "ControlPID"))
4081 i
->control_pid
= (pid_t
) u
;
4082 else if (streq(name
, "ExecMainPID")) {
4084 i
->main_pid
= (pid_t
) u
;
4085 } else if (streq(name
, "NAccepted"))
4087 else if (streq(name
, "NConnections"))
4088 i
->n_connections
= u
;
4093 case SD_BUS_TYPE_INT32
: {
4096 r
= sd_bus_message_read(m
, "i", &j
);
4098 return bus_log_parse_error(r
);
4100 if (streq(name
, "ExecMainCode"))
4101 i
->exit_code
= (int) j
;
4102 else if (streq(name
, "ExecMainStatus"))
4103 i
->exit_status
= (int) j
;
4104 else if (streq(name
, "StatusErrno"))
4105 i
->status_errno
= (int) j
;
4110 case SD_BUS_TYPE_UINT64
: {
4113 r
= sd_bus_message_read(m
, "t", &u
);
4115 return bus_log_parse_error(r
);
4117 if (streq(name
, "ExecMainStartTimestamp"))
4118 i
->start_timestamp
= (usec_t
) u
;
4119 else if (streq(name
, "ExecMainExitTimestamp"))
4120 i
->exit_timestamp
= (usec_t
) u
;
4121 else if (streq(name
, "ActiveEnterTimestamp"))
4122 i
->active_enter_timestamp
= (usec_t
) u
;
4123 else if (streq(name
, "InactiveEnterTimestamp"))
4124 i
->inactive_enter_timestamp
= (usec_t
) u
;
4125 else if (streq(name
, "InactiveExitTimestamp"))
4126 i
->inactive_exit_timestamp
= (usec_t
) u
;
4127 else if (streq(name
, "InactiveExitTimestampMonotonic"))
4128 i
->inactive_exit_timestamp_monotonic
= (usec_t
) u
;
4129 else if (streq(name
, "ActiveExitTimestamp"))
4130 i
->active_exit_timestamp
= (usec_t
) u
;
4131 else if (streq(name
, "ConditionTimestamp"))
4132 i
->condition_timestamp
= (usec_t
) u
;
4133 else if (streq(name
, "AssertTimestamp"))
4134 i
->assert_timestamp
= (usec_t
) u
;
4135 else if (streq(name
, "MemoryCurrent"))
4136 i
->memory_current
= u
;
4137 else if (streq(name
, "MemoryLow"))
4139 else if (streq(name
, "MemoryHigh"))
4141 else if (streq(name
, "MemoryMax"))
4143 else if (streq(name
, "MemoryLimit"))
4144 i
->memory_limit
= u
;
4145 else if (streq(name
, "TasksCurrent"))
4146 i
->tasks_current
= u
;
4147 else if (streq(name
, "TasksMax"))
4149 else if (streq(name
, "CPUUsageNSec"))
4150 i
->cpu_usage_nsec
= u
;
4155 case SD_BUS_TYPE_ARRAY
:
4157 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
4158 _cleanup_free_ ExecStatusInfo
*info
= NULL
;
4160 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4162 return bus_log_parse_error(r
);
4164 info
= new0(ExecStatusInfo
, 1);
4168 while ((r
= exec_status_info_deserialize(m
, info
)) > 0) {
4170 info
->name
= strdup(name
);
4174 LIST_PREPEND(exec
, i
->exec
, info
);
4176 info
= new0(ExecStatusInfo
, 1);
4182 return bus_log_parse_error(r
);
4184 r
= sd_bus_message_exit_container(m
);
4186 return bus_log_parse_error(r
);
4190 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
4191 const char *type
, *path
;
4193 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4195 return bus_log_parse_error(r
);
4197 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0) {
4199 r
= strv_extend(&i
->listen
, type
);
4203 r
= strv_extend(&i
->listen
, path
);
4208 return bus_log_parse_error(r
);
4210 r
= sd_bus_message_exit_container(m
);
4212 return bus_log_parse_error(r
);
4216 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "DropInPaths")) {
4218 r
= sd_bus_message_read_strv(m
, &i
->dropin_paths
);
4220 return bus_log_parse_error(r
);
4222 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Documentation")) {
4224 r
= sd_bus_message_read_strv(m
, &i
->documentation
);
4226 return bus_log_parse_error(r
);
4228 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Conditions")) {
4229 const char *cond
, *param
;
4230 int trigger
, negate
;
4233 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
4235 return bus_log_parse_error(r
);
4237 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
4238 _cleanup_(unit_condition_freep
) UnitCondition
*c
= NULL
;
4240 log_debug("%s trigger=%d negate=%d %s →%d", cond
, trigger
, negate
, param
, state
);
4242 c
= new0(UnitCondition
, 1);
4246 c
->name
= strdup(cond
);
4247 c
->param
= strdup(param
);
4248 if (!c
->name
|| !c
->param
)
4251 c
->trigger
= trigger
;
4253 c
->tristate
= state
;
4255 LIST_PREPEND(conditions
, i
->conditions
, c
);
4259 return bus_log_parse_error(r
);
4261 r
= sd_bus_message_exit_container(m
);
4263 return bus_log_parse_error(r
);
4265 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Asserts")) {
4266 const char *cond
, *param
;
4267 int trigger
, negate
;
4270 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
4272 return bus_log_parse_error(r
);
4274 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
4275 log_debug("%s %d %d %s %d", cond
, trigger
, negate
, param
, state
);
4276 if (state
< 0 && (!trigger
|| !i
->failed_assert
)) {
4277 i
->failed_assert
= cond
;
4278 i
->failed_assert_trigger
= trigger
;
4279 i
->failed_assert_negate
= negate
;
4280 i
->failed_assert_parameter
= param
;
4284 return bus_log_parse_error(r
);
4286 r
= sd_bus_message_exit_container(m
);
4288 return bus_log_parse_error(r
);
4295 case SD_BUS_TYPE_STRUCT_BEGIN
:
4297 if (streq(name
, "LoadError")) {
4298 const char *n
, *message
;
4300 r
= sd_bus_message_read(m
, "(ss)", &n
, &message
);
4302 return bus_log_parse_error(r
);
4304 if (!isempty(message
))
4305 i
->load_error
= message
;
4318 r
= sd_bus_message_skip(m
, contents
);
4320 return bus_log_parse_error(r
);
4325 #define print_prop(name, fmt, ...) \
4328 printf(fmt "\n", __VA_ARGS__); \
4330 printf("%s=" fmt "\n", name, __VA_ARGS__); \
4333 static int print_property(const char *name
, sd_bus_message
*m
, const char *contents
) {
4339 /* This is a low-level property printer, see
4340 * print_status_info() for the nicer output */
4342 if (arg_properties
&& !strv_find(arg_properties
, name
)) {
4343 /* skip what we didn't read */
4344 r
= sd_bus_message_skip(m
, contents
);
4348 switch (contents
[0]) {
4350 case SD_BUS_TYPE_STRUCT_BEGIN
:
4352 if (contents
[1] == SD_BUS_TYPE_UINT32
&& streq(name
, "Job")) {
4355 r
= sd_bus_message_read(m
, "(uo)", &u
, NULL
);
4357 return bus_log_parse_error(r
);
4360 print_prop(name
, "%"PRIu32
, u
);
4362 print_prop(name
, "%s", "");
4366 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Unit")) {
4369 r
= sd_bus_message_read(m
, "(so)", &s
, NULL
);
4371 return bus_log_parse_error(r
);
4373 if (arg_all
|| !isempty(s
))
4374 print_prop(name
, "%s", s
);
4378 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "LoadError")) {
4379 const char *a
= NULL
, *b
= NULL
;
4381 r
= sd_bus_message_read(m
, "(ss)", &a
, &b
);
4383 return bus_log_parse_error(r
);
4385 if (arg_all
|| !isempty(a
) || !isempty(b
))
4386 print_prop(name
, "%s \"%s\"", strempty(a
), strempty(b
));
4389 } else if (streq_ptr(name
, "SystemCallFilter")) {
4390 _cleanup_strv_free_
char **l
= NULL
;
4393 r
= sd_bus_message_enter_container(m
, 'r', "bas");
4395 return bus_log_parse_error(r
);
4397 r
= sd_bus_message_read(m
, "b", &whitelist
);
4399 return bus_log_parse_error(r
);
4401 r
= sd_bus_message_read_strv(m
, &l
);
4403 return bus_log_parse_error(r
);
4405 r
= sd_bus_message_exit_container(m
);
4407 return bus_log_parse_error(r
);
4409 if (arg_all
|| whitelist
|| !strv_isempty(l
)) {
4414 fputs(name
, stdout
);
4421 STRV_FOREACH(i
, l
) {
4429 fputc('\n', stdout
);
4437 case SD_BUS_TYPE_ARRAY
:
4439 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "EnvironmentFiles")) {
4443 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sb)");
4445 return bus_log_parse_error(r
);
4447 while ((r
= sd_bus_message_read(m
, "(sb)", &path
, &ignore
)) > 0)
4448 print_prop("EnvironmentFile", "%s (ignore_errors=%s)", path
, yes_no(ignore
));
4451 return bus_log_parse_error(r
);
4453 r
= sd_bus_message_exit_container(m
);
4455 return bus_log_parse_error(r
);
4459 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Paths")) {
4460 const char *type
, *path
;
4462 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4464 return bus_log_parse_error(r
);
4466 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4467 print_prop(type
, "%s", path
);
4469 return bus_log_parse_error(r
);
4471 r
= sd_bus_message_exit_container(m
);
4473 return bus_log_parse_error(r
);
4477 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
4478 const char *type
, *path
;
4480 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4482 return bus_log_parse_error(r
);
4484 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4488 printf("Listen%s=%s\n", type
, path
);
4490 return bus_log_parse_error(r
);
4492 r
= sd_bus_message_exit_container(m
);
4494 return bus_log_parse_error(r
);
4498 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Timers")) {
4500 uint64_t value
, next_elapse
;
4502 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(stt)");
4504 return bus_log_parse_error(r
);
4506 while ((r
= sd_bus_message_read(m
, "(stt)", &base
, &value
, &next_elapse
)) > 0) {
4507 char timespan1
[FORMAT_TIMESPAN_MAX
], timespan2
[FORMAT_TIMESPAN_MAX
];
4509 print_prop(base
, "{ value=%s ; next_elapse=%s }",
4510 format_timespan(timespan1
, sizeof(timespan1
), value
, 0),
4511 format_timespan(timespan2
, sizeof(timespan2
), next_elapse
, 0));
4514 return bus_log_parse_error(r
);
4516 r
= sd_bus_message_exit_container(m
);
4518 return bus_log_parse_error(r
);
4522 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
4523 ExecStatusInfo info
= {};
4525 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4527 return bus_log_parse_error(r
);
4529 while ((r
= exec_status_info_deserialize(m
, &info
)) > 0) {
4530 char timestamp1
[FORMAT_TIMESTAMP_MAX
], timestamp2
[FORMAT_TIMESTAMP_MAX
];
4531 _cleanup_free_
char *tt
;
4533 tt
= strv_join(info
.argv
, " ");
4536 "{ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT
" ; code=%s ; status=%i%s%s }",
4539 yes_no(info
.ignore
),
4540 strna(format_timestamp(timestamp1
, sizeof(timestamp1
), info
.start_timestamp
)),
4541 strna(format_timestamp(timestamp2
, sizeof(timestamp2
), info
.exit_timestamp
)),
4543 sigchld_code_to_string(info
.code
),
4545 info
.code
== CLD_EXITED
? "" : "/",
4546 strempty(info
.code
== CLD_EXITED
? NULL
: signal_to_string(info
.status
)));
4549 strv_free(info
.argv
);
4553 r
= sd_bus_message_exit_container(m
);
4555 return bus_log_parse_error(r
);
4559 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "DeviceAllow")) {
4560 const char *path
, *rwm
;
4562 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4564 return bus_log_parse_error(r
);
4566 while ((r
= sd_bus_message_read(m
, "(ss)", &path
, &rwm
)) > 0)
4567 print_prop(name
, "%s %s", strna(path
), strna(rwm
));
4569 return bus_log_parse_error(r
);
4571 r
= sd_bus_message_exit_container(m
);
4573 return bus_log_parse_error(r
);
4577 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& (streq(name
, "IODeviceWeight") || streq(name
, "BlockIODeviceWeight"))) {
4581 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4583 return bus_log_parse_error(r
);
4585 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &weight
)) > 0)
4586 print_prop(name
, "%s %"PRIu64
, strna(path
), weight
);
4588 return bus_log_parse_error(r
);
4590 r
= sd_bus_message_exit_container(m
);
4592 return bus_log_parse_error(r
);
4596 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& (cgroup_io_limit_type_from_string(name
) >= 0 ||
4597 streq(name
, "BlockIOReadBandwidth") || streq(name
, "BlockIOWriteBandwidth"))) {
4601 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4603 return bus_log_parse_error(r
);
4605 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &bandwidth
)) > 0)
4606 print_prop(name
, "%s %"PRIu64
, strna(path
), bandwidth
);
4608 return bus_log_parse_error(r
);
4610 r
= sd_bus_message_exit_container(m
);
4612 return bus_log_parse_error(r
);
4620 r
= bus_print_property(name
, m
, arg_value
, arg_all
);
4622 return bus_log_parse_error(r
);
4625 r
= sd_bus_message_skip(m
, contents
);
4627 return bus_log_parse_error(r
);
4630 printf("%s=[unprintable]\n", name
);
4636 static int show_one(
4641 bool show_properties
,
4645 static const struct bus_properties_map property_map
[] = {
4646 { "LoadState", "s", map_string_no_copy
, offsetof(UnitStatusInfo
, load_state
) },
4647 { "ActiveState", "s", map_string_no_copy
, offsetof(UnitStatusInfo
, active_state
) },
4651 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
4652 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
4653 _cleanup_set_free_ Set
*found_properties
= NULL
;
4654 _cleanup_(unit_status_info_free
) UnitStatusInfo info
= {
4655 .memory_current
= (uint64_t) -1,
4656 .memory_high
= CGROUP_LIMIT_MAX
,
4657 .memory_max
= CGROUP_LIMIT_MAX
,
4658 .memory_limit
= (uint64_t) -1,
4659 .cpu_usage_nsec
= (uint64_t) -1,
4660 .tasks_current
= (uint64_t) -1,
4661 .tasks_max
= (uint64_t) -1,
4668 log_debug("Showing one %s", path
);
4670 r
= sd_bus_call_method(
4672 "org.freedesktop.systemd1",
4674 "org.freedesktop.DBus.Properties",
4680 return log_error_errno(r
, "Failed to get properties: %s", bus_error_message(&error
, r
));
4683 r
= bus_message_map_all_properties(reply
, property_map
, &info
);
4685 return log_error_errno(r
, "Failed to map properties: %s", bus_error_message(&error
, r
));
4687 if (streq_ptr(info
.load_state
, "not-found") && streq_ptr(info
.active_state
, "inactive")) {
4688 log_error("Unit %s could not be found.", unit
);
4690 if (streq(verb
, "status"))
4691 return EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN
;
4696 r
= sd_bus_message_rewind(reply
, true);
4698 return log_error_errno(r
, "Failed to rewind: %s", bus_error_message(&error
, r
));
4701 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
4703 return bus_log_parse_error(r
);
4710 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
4711 const char *name
, *contents
;
4713 r
= sd_bus_message_read(reply
, "s", &name
);
4715 return bus_log_parse_error(r
);
4717 r
= sd_bus_message_peek_type(reply
, NULL
, &contents
);
4719 return bus_log_parse_error(r
);
4721 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, contents
);
4723 return bus_log_parse_error(r
);
4725 if (show_properties
) {
4726 r
= set_ensure_allocated(&found_properties
, &string_hash_ops
);
4730 r
= set_put(found_properties
, name
);
4731 if (r
< 0 && r
!= EEXIST
)
4734 r
= print_property(name
, reply
, contents
);
4736 r
= status_property(name
, reply
, &info
, contents
);
4740 r
= sd_bus_message_exit_container(reply
);
4742 return bus_log_parse_error(r
);
4744 r
= sd_bus_message_exit_container(reply
);
4746 return bus_log_parse_error(r
);
4749 return bus_log_parse_error(r
);
4751 r
= sd_bus_message_exit_container(reply
);
4753 return bus_log_parse_error(r
);
4756 if (show_properties
) {
4759 STRV_FOREACH(pp
, arg_properties
)
4760 if (!set_contains(found_properties
, *pp
)) {
4761 log_warning("Property %s does not exist.", *pp
);
4765 } else if (streq(verb
, "help"))
4766 show_unit_help(&info
);
4767 else if (streq(verb
, "status")) {
4768 print_status_info(bus
, &info
, ellipsized
);
4770 if (info
.active_state
&& STR_IN_SET(info
.active_state
, "inactive", "failed"))
4771 r
= EXIT_PROGRAM_NOT_RUNNING
;
4773 r
= EXIT_PROGRAM_RUNNING_OR_SERVICE_OK
;
4779 static int get_unit_dbus_path_by_pid(
4784 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
4785 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
4789 r
= sd_bus_call_method(
4791 "org.freedesktop.systemd1",
4792 "/org/freedesktop/systemd1",
4793 "org.freedesktop.systemd1.Manager",
4799 return log_error_errno(r
, "Failed to get unit for PID %"PRIu32
": %s", pid
, bus_error_message(&error
, r
));
4801 r
= sd_bus_message_read(reply
, "o", &u
);
4803 return bus_log_parse_error(r
);
4813 static int show_all(
4816 bool show_properties
,
4820 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
4821 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
4826 r
= get_unit_list(bus
, NULL
, NULL
, &unit_infos
, 0, &reply
);
4830 pager_open(arg_no_pager
, false);
4834 qsort_safe(unit_infos
, c
, sizeof(UnitInfo
), compare_unit_info
);
4836 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
4837 _cleanup_free_
char *p
= NULL
;
4839 p
= unit_dbus_path_from_name(u
->id
);
4843 r
= show_one(verb
, bus
, p
, u
->id
, show_properties
, new_line
, ellipsized
);
4846 else if (r
> 0 && ret
== 0)
4853 static int show_system_status(sd_bus
*bus
) {
4854 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], since2
[FORMAT_TIMESTAMP_MAX
];
4855 _cleanup_free_
char *hn
= NULL
;
4856 _cleanup_(machine_info_clear
) struct machine_info mi
= {};
4857 const char *on
, *off
;
4860 hn
= gethostname_malloc();
4864 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, &mi
);
4866 return log_error_errno(r
, "Failed to read server status: %m");
4868 if (streq_ptr(mi
.state
, "degraded")) {
4869 on
= ansi_highlight_red();
4870 off
= ansi_normal();
4871 } else if (!streq_ptr(mi
.state
, "running")) {
4872 on
= ansi_highlight_yellow();
4873 off
= ansi_normal();
4877 printf("%s%s%s %s\n", on
, special_glyph(BLACK_CIRCLE
), off
, arg_host
? arg_host
: hn
);
4879 printf(" State: %s%s%s\n",
4880 on
, strna(mi
.state
), off
);
4882 printf(" Jobs: %" PRIu32
" queued\n", mi
.n_jobs
);
4883 printf(" Failed: %" PRIu32
" units\n", mi
.n_failed_units
);
4885 printf(" Since: %s; %s\n",
4886 format_timestamp(since2
, sizeof(since2
), mi
.timestamp
),
4887 format_timestamp_relative(since1
, sizeof(since1
), mi
.timestamp
));
4889 printf(" CGroup: %s\n", mi
.control_group
?: "/");
4890 if (IN_SET(arg_transport
,
4891 BUS_TRANSPORT_LOCAL
,
4892 BUS_TRANSPORT_MACHINE
)) {
4893 static const char prefix
[] = " ";
4897 if (c
> sizeof(prefix
) - 1)
4898 c
-= sizeof(prefix
) - 1;
4902 show_cgroup(SYSTEMD_CGROUP_CONTROLLER
, strempty(mi
.control_group
), prefix
, c
, get_output_flags());
4908 static int show(int argc
, char *argv
[], void *userdata
) {
4909 bool show_properties
, show_status
, show_help
, new_line
= false;
4910 bool ellipsized
= false;
4916 show_properties
= streq(argv
[0], "show");
4917 show_status
= streq(argv
[0], "status");
4918 show_help
= streq(argv
[0], "help");
4920 if (show_help
&& argc
<= 1) {
4921 log_error("This command expects one or more unit names. Did you mean --help?");
4925 r
= acquire_bus(BUS_MANAGER
, &bus
);
4929 pager_open(arg_no_pager
, false);
4932 /* Increase max number of open files to 16K if we can, we
4933 * might needs this when browsing journal files, which might
4934 * be split up into many files. */
4935 setrlimit_closest(RLIMIT_NOFILE
, &RLIMIT_MAKE_CONST(16384));
4937 /* If no argument is specified inspect the manager itself */
4938 if (show_properties
&& argc
<= 1)
4939 return show_one(argv
[0], bus
, "/org/freedesktop/systemd1", NULL
, show_properties
, &new_line
, &ellipsized
);
4941 if (show_status
&& argc
<= 1) {
4943 show_system_status(bus
);
4947 ret
= show_all(argv
[0], bus
, false, &new_line
, &ellipsized
);
4949 _cleanup_free_
char **patterns
= NULL
;
4952 STRV_FOREACH(name
, strv_skip(argv
, 1)) {
4953 _cleanup_free_
char *path
= NULL
, *unit
= NULL
;
4956 if (safe_atou32(*name
, &id
) < 0) {
4957 if (strv_push(&patterns
, *name
) < 0)
4961 } else if (show_properties
) {
4962 /* Interpret as job id */
4963 if (asprintf(&path
, "/org/freedesktop/systemd1/job/%u", id
) < 0)
4967 /* Interpret as PID */
4968 r
= get_unit_dbus_path_by_pid(bus
, id
, &path
);
4974 r
= unit_name_from_dbus_path(path
, &unit
);
4979 r
= show_one(argv
[0], bus
, path
, unit
, show_properties
, &new_line
, &ellipsized
);
4982 else if (r
> 0 && ret
== 0)
4986 if (!strv_isempty(patterns
)) {
4987 _cleanup_strv_free_
char **names
= NULL
;
4989 r
= expand_names(bus
, patterns
, NULL
, &names
);
4991 return log_error_errno(r
, "Failed to expand names: %m");
4993 STRV_FOREACH(name
, names
) {
4994 _cleanup_free_
char *path
;
4996 path
= unit_dbus_path_from_name(*name
);
5000 r
= show_one(argv
[0], bus
, path
, *name
, show_properties
, &new_line
, &ellipsized
);
5003 if (r
> 0 && ret
== 0)
5009 if (ellipsized
&& !arg_quiet
)
5010 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
5015 static int cat_file(const char *filename
, bool newline
) {
5016 _cleanup_close_
int fd
;
5018 fd
= open(filename
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
5022 printf("%s%s# %s%s\n",
5023 newline
? "\n" : "",
5024 ansi_highlight_blue(),
5029 return copy_bytes(fd
, STDOUT_FILENO
, (uint64_t) -1, false);
5032 static int cat(int argc
, char *argv
[], void *userdata
) {
5033 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
5034 _cleanup_strv_free_
char **names
= NULL
;
5040 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
5041 log_error("Cannot remotely cat units.");
5045 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
5047 return log_error_errno(r
, "Failed to determine unit paths: %m");
5049 r
= acquire_bus(BUS_MANAGER
, &bus
);
5053 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
5055 return log_error_errno(r
, "Failed to expand names: %m");
5057 pager_open(arg_no_pager
, false);
5059 STRV_FOREACH(name
, names
) {
5060 _cleanup_free_
char *fragment_path
= NULL
;
5061 _cleanup_strv_free_
char **dropin_paths
= NULL
;
5064 r
= unit_find_paths(bus
, *name
, &lp
, &fragment_path
, &dropin_paths
);
5075 if (fragment_path
) {
5076 r
= cat_file(fragment_path
, false);
5078 return log_warning_errno(r
, "Failed to cat %s: %m", fragment_path
);
5081 STRV_FOREACH(path
, dropin_paths
) {
5082 r
= cat_file(*path
, path
== dropin_paths
);
5084 return log_warning_errno(r
, "Failed to cat %s: %m", *path
);
5091 static int set_property(int argc
, char *argv
[], void *userdata
) {
5092 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5093 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5094 _cleanup_free_
char *n
= NULL
;
5099 r
= acquire_bus(BUS_MANAGER
, &bus
);
5103 polkit_agent_open_if_enabled();
5105 r
= sd_bus_message_new_method_call(
5108 "org.freedesktop.systemd1",
5109 "/org/freedesktop/systemd1",
5110 "org.freedesktop.systemd1.Manager",
5111 "SetUnitProperties");
5113 return bus_log_create_error(r
);
5115 r
= unit_name_mangle(argv
[1], UNIT_NAME_NOGLOB
, &n
);
5117 return log_error_errno(r
, "Failed to mangle unit name: %m");
5119 r
= sd_bus_message_append(m
, "sb", n
, arg_runtime
);
5121 return bus_log_create_error(r
);
5123 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, "(sv)");
5125 return bus_log_create_error(r
);
5127 STRV_FOREACH(i
, strv_skip(argv
, 2)) {
5128 r
= bus_append_unit_property_assignment(m
, *i
);
5133 r
= sd_bus_message_close_container(m
);
5135 return bus_log_create_error(r
);
5137 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5139 return log_error_errno(r
, "Failed to set unit properties on %s: %s", n
, bus_error_message(&error
, r
));
5144 static int daemon_reload(int argc
, char *argv
[], void *userdata
) {
5145 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5146 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5151 r
= acquire_bus(BUS_MANAGER
, &bus
);
5155 polkit_agent_open_if_enabled();
5157 switch (arg_action
) {
5164 method
= "Reexecute";
5167 case ACTION_SYSTEMCTL
:
5168 method
= streq(argv
[0], "daemon-reexec") ? "Reexecute" :
5169 /* "daemon-reload" */ "Reload";
5173 assert_not_reached("Unexpected action");
5176 r
= sd_bus_message_new_method_call(
5179 "org.freedesktop.systemd1",
5180 "/org/freedesktop/systemd1",
5181 "org.freedesktop.systemd1.Manager",
5184 return bus_log_create_error(r
);
5186 /* Note we use an extra-long timeout here. This is because a reload or reexec means generators are rerun which
5187 * are timed out after DEFAULT_TIMEOUT_USEC. Let's use twice that time here, so that the generators can have
5188 * their timeout, and for everything else there's the same time budget in place. */
5190 r
= sd_bus_call(bus
, m
, DEFAULT_TIMEOUT_USEC
* 2, &error
, NULL
);
5192 /* On reexecution, we expect a disconnect, not a reply */
5193 if (IN_SET(r
, -ETIMEDOUT
, -ECONNRESET
) && streq(method
, "Reexecute"))
5196 if (r
< 0 && arg_action
== ACTION_SYSTEMCTL
)
5197 return log_error_errno(r
, "Failed to reload daemon: %s", bus_error_message(&error
, r
));
5199 /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
5200 * old ways of doing things, hence don't log any error in that case here. */
5202 return r
< 0 ? r
: 0;
5205 static int trivial_method(int argc
, char *argv
[], void *userdata
) {
5206 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5211 r
= acquire_bus(BUS_MANAGER
, &bus
);
5215 polkit_agent_open_if_enabled();
5218 streq(argv
[0], "clear-jobs") ||
5219 streq(argv
[0], "cancel") ? "ClearJobs" :
5220 streq(argv
[0], "reset-failed") ? "ResetFailed" :
5221 streq(argv
[0], "halt") ? "Halt" :
5222 streq(argv
[0], "reboot") ? "Reboot" :
5223 streq(argv
[0], "kexec") ? "KExec" :
5224 streq(argv
[0], "exit") ? "Exit" :
5225 /* poweroff */ "PowerOff";
5227 r
= sd_bus_call_method(
5229 "org.freedesktop.systemd1",
5230 "/org/freedesktop/systemd1",
5231 "org.freedesktop.systemd1.Manager",
5236 if (r
< 0 && arg_action
== ACTION_SYSTEMCTL
)
5237 return log_error_errno(r
, "Failed to execute operation: %s", bus_error_message(&error
, r
));
5239 /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
5240 * old ways of doing things, hence don't log any error in that case here. */
5242 return r
< 0 ? r
: 0;
5245 static int reset_failed(int argc
, char *argv
[], void *userdata
) {
5246 _cleanup_strv_free_
char **names
= NULL
;
5252 return trivial_method(argc
, argv
, userdata
);
5254 r
= acquire_bus(BUS_MANAGER
, &bus
);
5258 polkit_agent_open_if_enabled();
5260 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
5262 return log_error_errno(r
, "Failed to expand names: %m");
5264 STRV_FOREACH(name
, names
) {
5265 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5267 q
= sd_bus_call_method(
5269 "org.freedesktop.systemd1",
5270 "/org/freedesktop/systemd1",
5271 "org.freedesktop.systemd1.Manager",
5277 log_error_errno(q
, "Failed to reset failed state of unit %s: %s", *name
, bus_error_message(&error
, q
));
5286 static int show_environment(int argc
, char *argv
[], void *userdata
) {
5287 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5288 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5293 r
= acquire_bus(BUS_MANAGER
, &bus
);
5297 pager_open(arg_no_pager
, false);
5299 r
= sd_bus_get_property(
5301 "org.freedesktop.systemd1",
5302 "/org/freedesktop/systemd1",
5303 "org.freedesktop.systemd1.Manager",
5309 return log_error_errno(r
, "Failed to get environment: %s", bus_error_message(&error
, r
));
5311 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
5313 return bus_log_parse_error(r
);
5315 while ((r
= sd_bus_message_read_basic(reply
, SD_BUS_TYPE_STRING
, &text
)) > 0)
5318 return bus_log_parse_error(r
);
5320 r
= sd_bus_message_exit_container(reply
);
5322 return bus_log_parse_error(r
);
5327 static int switch_root(int argc
, char *argv
[], void *userdata
) {
5328 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5329 _cleanup_free_
char *cmdline_init
= NULL
;
5330 const char *root
, *init
;
5334 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
5335 log_error("Cannot switch root remotely.");
5339 if (argc
< 2 || argc
> 3) {
5340 log_error("Wrong number of arguments.");
5349 r
= parse_env_file("/proc/cmdline", WHITESPACE
,
5350 "init", &cmdline_init
,
5353 log_debug_errno(r
, "Failed to parse /proc/cmdline: %m");
5355 init
= cmdline_init
;
5358 init
= empty_to_null(init
);
5360 const char *root_systemd_path
= NULL
, *root_init_path
= NULL
;
5362 root_systemd_path
= strjoina(root
, "/" SYSTEMD_BINARY_PATH
);
5363 root_init_path
= strjoina(root
, "/", init
);
5365 /* If the passed init is actually the same as the
5366 * systemd binary, then let's suppress it. */
5367 if (files_same(root_init_path
, root_systemd_path
) > 0)
5371 r
= acquire_bus(BUS_MANAGER
, &bus
);
5375 log_debug("Switching root - root: %s; init: %s", root
, strna(init
));
5377 r
= sd_bus_call_method(
5379 "org.freedesktop.systemd1",
5380 "/org/freedesktop/systemd1",
5381 "org.freedesktop.systemd1.Manager",
5387 return log_error_errno(r
, "Failed to switch root: %s", bus_error_message(&error
, r
));
5392 static int set_environment(int argc
, char *argv
[], void *userdata
) {
5393 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5394 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5402 r
= acquire_bus(BUS_MANAGER
, &bus
);
5406 polkit_agent_open_if_enabled();
5408 method
= streq(argv
[0], "set-environment")
5410 : "UnsetEnvironment";
5412 r
= sd_bus_message_new_method_call(
5415 "org.freedesktop.systemd1",
5416 "/org/freedesktop/systemd1",
5417 "org.freedesktop.systemd1.Manager",
5420 return bus_log_create_error(r
);
5422 r
= sd_bus_message_append_strv(m
, strv_skip(argv
, 1));
5424 return bus_log_create_error(r
);
5426 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5428 return log_error_errno(r
, "Failed to set environment: %s", bus_error_message(&error
, r
));
5433 static int import_environment(int argc
, char *argv
[], void *userdata
) {
5434 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5435 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5439 r
= acquire_bus(BUS_MANAGER
, &bus
);
5443 polkit_agent_open_if_enabled();
5445 r
= sd_bus_message_new_method_call(
5448 "org.freedesktop.systemd1",
5449 "/org/freedesktop/systemd1",
5450 "org.freedesktop.systemd1.Manager",
5453 return bus_log_create_error(r
);
5456 r
= sd_bus_message_append_strv(m
, environ
);
5460 r
= sd_bus_message_open_container(m
, 'a', "s");
5462 return bus_log_create_error(r
);
5464 STRV_FOREACH(a
, strv_skip(argv
, 1)) {
5466 if (!env_name_is_valid(*a
)) {
5467 log_error("Not a valid environment variable name: %s", *a
);
5471 STRV_FOREACH(b
, environ
) {
5474 eq
= startswith(*b
, *a
);
5475 if (eq
&& *eq
== '=') {
5477 r
= sd_bus_message_append(m
, "s", *b
);
5479 return bus_log_create_error(r
);
5486 r
= sd_bus_message_close_container(m
);
5489 return bus_log_create_error(r
);
5491 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5493 return log_error_errno(r
, "Failed to import environment: %s", bus_error_message(&error
, r
));
5498 static int enable_sysv_units(const char *verb
, char **args
) {
5501 #if defined(HAVE_SYSV_COMPAT)
5502 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
5505 /* Processes all SysV units, and reshuffles the array so that afterwards only the native units remain */
5507 if (arg_scope
!= UNIT_FILE_SYSTEM
)
5510 if (getenv_bool("SYSTEMCTL_SKIP_SYSV") > 0)
5513 if (!STR_IN_SET(verb
,
5519 r
= lookup_paths_init(&paths
, arg_scope
, LOOKUP_PATHS_EXCLUDE_GENERATED
, arg_root
);
5526 const char *argv
[] = {
5527 ROOTLIBEXECDIR
"/systemd-sysv-install",
5534 _cleanup_free_
char *p
= NULL
, *q
= NULL
, *l
= NULL
;
5535 bool found_native
= false, found_sysv
;
5544 if (!endswith(name
, ".service"))
5547 if (path_is_absolute(name
))
5550 j
= unit_file_exists(arg_scope
, &paths
, name
);
5551 if (j
< 0 && !IN_SET(j
, -ELOOP
, -ERFKILL
, -EADDRNOTAVAIL
))
5552 return log_error_errno(j
, "Failed to lookup unit file state: %m");
5553 found_native
= j
!= 0;
5555 /* If we have both a native unit and a SysV script, enable/disable them both (below); for is-enabled,
5556 * prefer the native unit */
5557 if (found_native
&& streq(verb
, "is-enabled"))
5560 p
= path_join(arg_root
, SYSTEM_SYSVINIT_PATH
, name
);
5564 p
[strlen(p
) - strlen(".service")] = 0;
5565 found_sysv
= access(p
, F_OK
) >= 0;
5570 log_info("Synchronizing state of %s with SysV service script with %s.", name
, argv
[0]);
5572 log_info("%s is not a native service, redirecting to systemd-sysv-install.", name
);
5574 if (!isempty(arg_root
))
5575 argv
[c
++] = q
= strappend("--root=", arg_root
);
5578 argv
[c
++] = basename(p
);
5581 l
= strv_join((char**)argv
, " ");
5585 log_info("Executing: %s", l
);
5589 return log_error_errno(errno
, "Failed to fork: %m");
5590 else if (pid
== 0) {
5593 (void) reset_all_signal_handlers();
5594 (void) reset_signal_mask();
5596 execv(argv
[0], (char**) argv
);
5597 log_error_errno(errno
, "Failed to execute %s: %m", argv
[0]);
5598 _exit(EXIT_FAILURE
);
5601 j
= wait_for_terminate(pid
, &status
);
5603 return log_error_errno(j
, "Failed to wait for child: %m");
5605 if (status
.si_code
== CLD_EXITED
) {
5606 if (streq(verb
, "is-enabled")) {
5607 if (status
.si_status
== 0) {
5616 } else if (status
.si_status
!= 0)
5617 return -EBADE
; /* We don't warn here, under the assumption the script already showed an explanation */
5619 log_error("Unexpected waitid() result.");
5626 /* Remove this entry, so that we don't try enabling it as native unit */
5629 assert(args
[f
] == name
);
5630 strv_remove(args
, name
);
5637 static int mangle_names(char **original_names
, char ***mangled_names
) {
5638 char **i
, **l
, **name
;
5641 l
= i
= new(char*, strv_length(original_names
) + 1);
5645 STRV_FOREACH(name
, original_names
) {
5647 /* When enabling units qualified path names are OK,
5648 * too, hence allow them explicitly. */
5650 if (is_path(*name
)) {
5657 r
= unit_name_mangle(*name
, UNIT_NAME_NOGLOB
, i
);
5660 return log_error_errno(r
, "Failed to mangle unit name: %m");
5673 static int unit_exists(const char *unit
) {
5674 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5675 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5676 _cleanup_free_
char *path
= NULL
;
5677 static const struct bus_properties_map property_map
[] = {
5678 { "LoadState", "s", map_string_no_copy
, offsetof(UnitStatusInfo
, load_state
) },
5679 { "ActiveState", "s", map_string_no_copy
, offsetof(UnitStatusInfo
, active_state
)},
5682 UnitStatusInfo info
= {};
5686 path
= unit_dbus_path_from_name(unit
);
5690 r
= acquire_bus(BUS_MANAGER
, &bus
);
5694 r
= sd_bus_call_method(
5696 "org.freedesktop.systemd1",
5698 "org.freedesktop.DBus.Properties",
5704 return log_error_errno(r
, "Failed to get properties: %s", bus_error_message(&error
, r
));
5706 r
= bus_message_map_all_properties(reply
, property_map
, &info
);
5708 return log_error_errno(r
, "Failed to map properties: %s", bus_error_message(&error
, r
));
5710 return !streq_ptr(info
.load_state
, "not-found") || !streq_ptr(info
.active_state
, "inactive");
5713 static int enable_unit(int argc
, char *argv
[], void *userdata
) {
5714 _cleanup_strv_free_
char **names
= NULL
;
5715 const char *verb
= argv
[0];
5716 UnitFileChange
*changes
= NULL
;
5717 unsigned n_changes
= 0;
5718 int carries_install_info
= -1;
5719 bool ignore_carries_install_info
= arg_quiet
;
5725 r
= mangle_names(strv_skip(argv
, 1), &names
);
5729 r
= enable_sysv_units(verb
, names
);
5733 /* If the operation was fully executed by the SysV compat, let's finish early */
5734 if (strv_isempty(names
)) {
5735 if (arg_no_reload
|| install_client_side())
5737 return daemon_reload(argc
, argv
, userdata
);
5740 if (install_client_side()) {
5741 if (streq(verb
, "enable")) {
5742 r
= unit_file_enable(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5743 carries_install_info
= r
;
5744 } else if (streq(verb
, "disable"))
5745 r
= unit_file_disable(arg_scope
, arg_runtime
, arg_root
, names
, &changes
, &n_changes
);
5746 else if (streq(verb
, "reenable")) {
5747 r
= unit_file_reenable(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5748 carries_install_info
= r
;
5749 } else if (streq(verb
, "link"))
5750 r
= unit_file_link(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5751 else if (streq(verb
, "preset")) {
5752 r
= unit_file_preset(arg_scope
, arg_runtime
, arg_root
, names
, arg_preset_mode
, arg_force
, &changes
, &n_changes
);
5753 } else if (streq(verb
, "mask"))
5754 r
= unit_file_mask(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5755 else if (streq(verb
, "unmask"))
5756 r
= unit_file_unmask(arg_scope
, arg_runtime
, arg_root
, names
, &changes
, &n_changes
);
5757 else if (streq(verb
, "revert"))
5758 r
= unit_file_revert(arg_scope
, arg_root
, names
, &changes
, &n_changes
);
5760 assert_not_reached("Unknown verb");
5762 unit_file_dump_changes(r
, verb
, changes
, n_changes
, arg_quiet
);
5767 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
, *m
= NULL
;
5768 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5769 bool expect_carries_install_info
= false;
5770 bool send_runtime
= true, send_force
= true, send_preset_mode
= false;
5774 if (STR_IN_SET(verb
, "mask", "unmask")) {
5775 r
= unit_exists(*names
);
5779 log_notice("Unit %s does not exist, proceeding anyway.", *names
);
5782 r
= acquire_bus(BUS_MANAGER
, &bus
);
5786 polkit_agent_open_if_enabled();
5788 if (streq(verb
, "enable")) {
5789 method
= "EnableUnitFiles";
5790 expect_carries_install_info
= true;
5791 } else if (streq(verb
, "disable")) {
5792 method
= "DisableUnitFiles";
5794 } else if (streq(verb
, "reenable")) {
5795 method
= "ReenableUnitFiles";
5796 expect_carries_install_info
= true;
5797 } else if (streq(verb
, "link"))
5798 method
= "LinkUnitFiles";
5799 else if (streq(verb
, "preset")) {
5801 if (arg_preset_mode
!= UNIT_FILE_PRESET_FULL
) {
5802 method
= "PresetUnitFilesWithMode";
5803 send_preset_mode
= true;
5805 method
= "PresetUnitFiles";
5807 expect_carries_install_info
= true;
5808 ignore_carries_install_info
= true;
5809 } else if (streq(verb
, "mask"))
5810 method
= "MaskUnitFiles";
5811 else if (streq(verb
, "unmask")) {
5812 method
= "UnmaskUnitFiles";
5814 } else if (streq(verb
, "revert")) {
5815 method
= "RevertUnitFiles";
5816 send_runtime
= send_force
= false;
5818 assert_not_reached("Unknown verb");
5820 r
= sd_bus_message_new_method_call(
5823 "org.freedesktop.systemd1",
5824 "/org/freedesktop/systemd1",
5825 "org.freedesktop.systemd1.Manager",
5828 return bus_log_create_error(r
);
5830 r
= sd_bus_message_append_strv(m
, names
);
5832 return bus_log_create_error(r
);
5834 if (send_preset_mode
) {
5835 r
= sd_bus_message_append(m
, "s", unit_file_preset_mode_to_string(arg_preset_mode
));
5837 return bus_log_create_error(r
);
5841 r
= sd_bus_message_append(m
, "b", arg_runtime
);
5843 return bus_log_create_error(r
);
5847 r
= sd_bus_message_append(m
, "b", arg_force
);
5849 return bus_log_create_error(r
);
5852 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
5854 return log_error_errno(r
, "Failed to %s unit: %s", verb
, bus_error_message(&error
, r
));
5856 if (expect_carries_install_info
) {
5857 r
= sd_bus_message_read(reply
, "b", &carries_install_info
);
5859 return bus_log_parse_error(r
);
5862 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
5866 /* Try to reload if enabled */
5868 r
= daemon_reload(argc
, argv
, userdata
);
5873 if (carries_install_info
== 0 && !ignore_carries_install_info
)
5874 log_warning("The unit files have no installation config (WantedBy, RequiredBy, Also, Alias\n"
5875 "settings in the [Install] section, and DefaultInstance for template units).\n"
5876 "This means they are not meant to be enabled using systemctl.\n"
5877 "Possible reasons for having this kind of units are:\n"
5878 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5879 " .wants/ or .requires/ directory.\n"
5880 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5881 " a requirement dependency on it.\n"
5882 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5883 " D-Bus, udev, scripted systemctl call, ...).\n"
5884 "4) In case of template units, the unit is meant to be enabled with some\n"
5885 " instance name specified.");
5887 if (arg_now
&& n_changes
> 0 && STR_IN_SET(argv
[0], "enable", "disable", "mask")) {
5888 char *new_args
[n_changes
+ 2];
5892 r
= acquire_bus(BUS_MANAGER
, &bus
);
5896 new_args
[0] = (char*) (streq(argv
[0], "enable") ? "start" : "stop");
5897 for (i
= 0; i
< n_changes
; i
++)
5898 new_args
[i
+ 1] = basename(changes
[i
].path
);
5899 new_args
[i
+ 1] = NULL
;
5901 r
= start_unit(strv_length(new_args
), new_args
, userdata
);
5905 unit_file_changes_free(changes
, n_changes
);
5910 static int add_dependency(int argc
, char *argv
[], void *userdata
) {
5911 _cleanup_strv_free_
char **names
= NULL
;
5912 _cleanup_free_
char *target
= NULL
;
5913 const char *verb
= argv
[0];
5914 UnitFileChange
*changes
= NULL
;
5915 unsigned n_changes
= 0;
5922 r
= unit_name_mangle_with_suffix(argv
[1], UNIT_NAME_NOGLOB
, ".target", &target
);
5924 return log_error_errno(r
, "Failed to mangle unit name: %m");
5926 r
= mangle_names(strv_skip(argv
, 2), &names
);
5930 if (streq(verb
, "add-wants"))
5932 else if (streq(verb
, "add-requires"))
5933 dep
= UNIT_REQUIRES
;
5935 assert_not_reached("Unknown verb");
5937 if (install_client_side()) {
5938 r
= unit_file_add_dependency(arg_scope
, arg_runtime
, arg_root
, names
, target
, dep
, arg_force
, &changes
, &n_changes
);
5939 unit_file_dump_changes(r
, "add dependency on", changes
, n_changes
, arg_quiet
);
5944 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
, *m
= NULL
;
5945 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5948 r
= acquire_bus(BUS_MANAGER
, &bus
);
5952 polkit_agent_open_if_enabled();
5954 r
= sd_bus_message_new_method_call(
5957 "org.freedesktop.systemd1",
5958 "/org/freedesktop/systemd1",
5959 "org.freedesktop.systemd1.Manager",
5960 "AddDependencyUnitFiles");
5962 return bus_log_create_error(r
);
5964 r
= sd_bus_message_append_strv(m
, names
);
5966 return bus_log_create_error(r
);
5968 r
= sd_bus_message_append(m
, "ssbb", target
, unit_dependency_to_string(dep
), arg_runtime
, arg_force
);
5970 return bus_log_create_error(r
);
5972 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
5974 return log_error_errno(r
, "Failed to add dependency: %s", bus_error_message(&error
, r
));
5976 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
5980 if (arg_no_reload
) {
5985 r
= daemon_reload(argc
, argv
, userdata
);
5989 unit_file_changes_free(changes
, n_changes
);
5994 static int preset_all(int argc
, char *argv
[], void *userdata
) {
5995 UnitFileChange
*changes
= NULL
;
5996 unsigned n_changes
= 0;
5999 if (install_client_side()) {
6000 r
= unit_file_preset_all(arg_scope
, arg_runtime
, arg_root
, arg_preset_mode
, arg_force
, &changes
, &n_changes
);
6001 unit_file_dump_changes(r
, "preset", changes
, n_changes
, arg_quiet
);
6006 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6007 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6010 r
= acquire_bus(BUS_MANAGER
, &bus
);
6014 polkit_agent_open_if_enabled();
6016 r
= sd_bus_call_method(
6018 "org.freedesktop.systemd1",
6019 "/org/freedesktop/systemd1",
6020 "org.freedesktop.systemd1.Manager",
6021 "PresetAllUnitFiles",
6025 unit_file_preset_mode_to_string(arg_preset_mode
),
6029 return log_error_errno(r
, "Failed to preset all units: %s", bus_error_message(&error
, r
));
6031 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
6035 if (arg_no_reload
) {
6040 r
= daemon_reload(argc
, argv
, userdata
);
6044 unit_file_changes_free(changes
, n_changes
);
6049 static int unit_is_enabled(int argc
, char *argv
[], void *userdata
) {
6051 _cleanup_strv_free_
char **names
= NULL
;
6056 r
= mangle_names(strv_skip(argv
, 1), &names
);
6060 r
= enable_sysv_units(argv
[0], names
);
6066 if (install_client_side()) {
6068 STRV_FOREACH(name
, names
) {
6069 UnitFileState state
;
6071 r
= unit_file_get_state(arg_scope
, arg_root
, *name
, &state
);
6073 return log_error_errno(state
, "Failed to get unit file state for %s: %m", *name
);
6077 UNIT_FILE_ENABLED_RUNTIME
,
6080 UNIT_FILE_GENERATED
))
6084 puts(unit_file_state_to_string(state
));
6089 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6092 r
= acquire_bus(BUS_MANAGER
, &bus
);
6096 STRV_FOREACH(name
, names
) {
6097 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6100 r
= sd_bus_call_method(
6102 "org.freedesktop.systemd1",
6103 "/org/freedesktop/systemd1",
6104 "org.freedesktop.systemd1.Manager",
6110 return log_error_errno(r
, "Failed to get unit file state for %s: %s", *name
, bus_error_message(&error
, r
));
6112 r
= sd_bus_message_read(reply
, "s", &s
);
6114 return bus_log_parse_error(r
);
6116 if (STR_IN_SET(s
, "enabled", "enabled-runtime", "static", "indirect", "generated"))
6124 return enabled
? EXIT_SUCCESS
: EXIT_FAILURE
;
6127 static int is_system_running(int argc
, char *argv
[], void *userdata
) {
6128 _cleanup_free_
char *state
= NULL
;
6132 if (running_in_chroot() > 0 || (arg_transport
== BUS_TRANSPORT_LOCAL
&& !sd_booted())) {
6135 return EXIT_FAILURE
;
6138 r
= acquire_bus(BUS_MANAGER
, &bus
);
6142 r
= sd_bus_get_property_string(
6144 "org.freedesktop.systemd1",
6145 "/org/freedesktop/systemd1",
6146 "org.freedesktop.systemd1.Manager",
6159 return streq(state
, "running") ? EXIT_SUCCESS
: EXIT_FAILURE
;
6162 static int create_edit_temp_file(const char *new_path
, const char *original_path
, char **ret_tmp_fn
) {
6163 _cleanup_free_
char *t
= NULL
;
6167 assert(original_path
);
6170 r
= tempfn_random(new_path
, NULL
, &t
);
6172 return log_error_errno(r
, "Failed to determine temporary filename for \"%s\": %m", new_path
);
6174 r
= mkdir_parents(new_path
, 0755);
6176 return log_error_errno(r
, "Failed to create directories for \"%s\": %m", new_path
);
6178 r
= copy_file(original_path
, t
, 0, 0644, 0);
6183 return log_error_errno(r
, "Failed to create temporary file \"%s\": %m", t
);
6186 return log_error_errno(r
, "Failed to create temporary file for \"%s\": %m", new_path
);
6194 static int get_file_to_edit(
6195 const LookupPaths
*paths
,
6199 _cleanup_free_
char *path
= NULL
, *run
= NULL
;
6204 path
= strjoin(paths
->persistent_config
, "/", name
, NULL
);
6209 run
= strjoin(paths
->runtime_config
, "/", name
, NULL
);
6215 if (access(path
, F_OK
) >= 0) {
6216 log_error("Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.", run
, path
);
6230 static int unit_file_create_new(
6231 const LookupPaths
*paths
,
6232 const char *unit_name
,
6234 char **ret_new_path
,
6235 char **ret_tmp_path
) {
6237 char *tmp_new_path
, *tmp_tmp_path
, *ending
;
6241 assert(ret_new_path
);
6242 assert(ret_tmp_path
);
6244 ending
= strjoina(unit_name
, suffix
);
6245 r
= get_file_to_edit(paths
, ending
, &tmp_new_path
);
6249 r
= create_edit_temp_file(tmp_new_path
, tmp_new_path
, &tmp_tmp_path
);
6255 *ret_new_path
= tmp_new_path
;
6256 *ret_tmp_path
= tmp_tmp_path
;
6261 static int unit_file_create_copy(
6262 const LookupPaths
*paths
,
6263 const char *unit_name
,
6264 const char *fragment_path
,
6265 char **ret_new_path
,
6266 char **ret_tmp_path
) {
6268 char *tmp_new_path
, *tmp_tmp_path
;
6271 assert(fragment_path
);
6273 assert(ret_new_path
);
6274 assert(ret_tmp_path
);
6276 r
= get_file_to_edit(paths
, unit_name
, &tmp_new_path
);
6280 if (!path_equal(fragment_path
, tmp_new_path
) && access(tmp_new_path
, F_OK
) == 0) {
6283 r
= ask_char(&response
, "yn", "\"%s\" already exists. Overwrite with \"%s\"? [(y)es, (n)o] ", tmp_new_path
, fragment_path
);
6288 if (response
!= 'y') {
6289 log_warning("%s ignored", unit_name
);
6291 return -EKEYREJECTED
;
6295 r
= create_edit_temp_file(tmp_new_path
, fragment_path
, &tmp_tmp_path
);
6301 *ret_new_path
= tmp_new_path
;
6302 *ret_tmp_path
= tmp_tmp_path
;
6307 static int run_editor(char **paths
) {
6315 return log_error_errno(errno
, "Failed to fork: %m");
6319 char *editor
, **editor_args
= NULL
;
6320 char **tmp_path
, **original_path
, *p
;
6321 unsigned n_editor_args
= 0, i
= 1;
6324 (void) reset_all_signal_handlers();
6325 (void) reset_signal_mask();
6327 argc
= strv_length(paths
)/2 + 1;
6329 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
6330 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
6331 * we try to execute well known editors
6333 editor
= getenv("SYSTEMD_EDITOR");
6335 editor
= getenv("EDITOR");
6337 editor
= getenv("VISUAL");
6339 if (!isempty(editor
)) {
6340 editor_args
= strv_split(editor
, WHITESPACE
);
6343 _exit(EXIT_FAILURE
);
6345 n_editor_args
= strv_length(editor_args
);
6346 argc
+= n_editor_args
- 1;
6348 args
= newa(const char*, argc
+ 1);
6350 if (n_editor_args
> 0) {
6351 args
[0] = editor_args
[0];
6352 for (; i
< n_editor_args
; i
++)
6353 args
[i
] = editor_args
[i
];
6356 STRV_FOREACH_PAIR(original_path
, tmp_path
, paths
) {
6357 args
[i
] = *tmp_path
;
6362 if (n_editor_args
> 0)
6363 execvp(args
[0], (char* const*) args
);
6365 FOREACH_STRING(p
, "editor", "nano", "vim", "vi") {
6367 execvp(p
, (char* const*) args
);
6368 /* We do not fail if the editor doesn't exist
6369 * because we want to try each one of them before
6372 if (errno
!= ENOENT
) {
6373 log_error_errno(errno
, "Failed to execute %s: %m", editor
);
6374 _exit(EXIT_FAILURE
);
6378 log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR, $EDITOR or $VISUAL.");
6379 _exit(EXIT_FAILURE
);
6382 r
= wait_for_terminate_and_warn("editor", pid
, true);
6384 return log_error_errno(r
, "Failed to wait for child: %m");
6389 static int find_paths_to_edit(sd_bus
*bus
, char **names
, char ***paths
) {
6390 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
6397 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
6401 STRV_FOREACH(name
, names
) {
6402 _cleanup_free_
char *path
= NULL
, *new_path
= NULL
, *tmp_path
= NULL
;
6404 r
= unit_find_paths(bus
, *name
, &lp
, &path
, NULL
);
6407 else if (!arg_force
) {
6409 log_error("Run 'systemctl edit --force %s' to create a new unit.", *name
);
6412 // FIXME: support units with path==NULL (no FragmentPath)
6413 log_error("No fragment exists for %s.", *name
);
6420 r
= unit_file_create_copy(&lp
, *name
, path
, &new_path
, &tmp_path
);
6422 r
= unit_file_create_new(&lp
, *name
, ".d/override.conf", &new_path
, &tmp_path
);
6424 r
= unit_file_create_new(&lp
, *name
, NULL
, &new_path
, &tmp_path
);
6428 r
= strv_push_pair(paths
, new_path
, tmp_path
);
6431 new_path
= tmp_path
= NULL
;
6437 static int edit(int argc
, char *argv
[], void *userdata
) {
6438 _cleanup_strv_free_
char **names
= NULL
;
6439 _cleanup_strv_free_
char **paths
= NULL
;
6440 char **original
, **tmp
;
6445 log_error("Cannot edit units if not on a tty.");
6449 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
6450 log_error("Cannot edit units remotely.");
6454 r
= acquire_bus(BUS_MANAGER
, &bus
);
6458 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
6460 return log_error_errno(r
, "Failed to expand names: %m");
6462 r
= find_paths_to_edit(bus
, names
, &paths
);
6466 if (strv_isempty(paths
))
6469 r
= run_editor(paths
);
6473 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
6474 /* If the temporary file is empty we ignore it. It's
6475 * useful if the user wants to cancel its modification
6477 if (null_or_empty_path(*tmp
)) {
6478 log_warning("Editing \"%s\" canceled: temporary file is empty.", *original
);
6482 r
= rename(*tmp
, *original
);
6484 r
= log_error_errno(errno
, "Failed to rename \"%s\" to \"%s\": %m", *tmp
, *original
);
6491 if (!arg_no_reload
&& !install_client_side())
6492 r
= daemon_reload(argc
, argv
, userdata
);
6495 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
6496 (void) unlink(*tmp
);
6498 /* Removing empty dropin dirs */
6500 _cleanup_free_
char *dir
;
6502 dir
= dirname_malloc(*original
);
6506 /* no need to check if the dir is empty, rmdir
6507 * does nothing if it is not the case.
6516 static void systemctl_help(void) {
6518 pager_open(arg_no_pager
, false);
6520 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
6521 "Query or send control commands to the systemd manager.\n\n"
6522 " -h --help Show this help\n"
6523 " --version Show package version\n"
6524 " --system Connect to system manager\n"
6525 " --user Connect to user service manager\n"
6526 " -H --host=[USER@]HOST\n"
6527 " Operate on remote host\n"
6528 " -M --machine=CONTAINER\n"
6529 " Operate on local container\n"
6530 " -t --type=TYPE List units of a particular type\n"
6531 " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n"
6532 " -p --property=NAME Show only properties by this name\n"
6533 " -a --all Show all loaded units/properties, including dead/empty\n"
6534 " ones. To list all units installed on the system, use\n"
6535 " the 'list-unit-files' command instead.\n"
6536 " -l --full Don't ellipsize unit names on output\n"
6537 " -r --recursive Show unit list of host and local containers\n"
6538 " --reverse Show reverse dependencies with 'list-dependencies'\n"
6539 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
6540 " queueing a new job\n"
6541 " --show-types When showing sockets, explicitly show their type\n"
6542 " --value When showing properties, only print the value\n"
6543 " -i --ignore-inhibitors\n"
6544 " When shutting down or sleeping, ignore inhibitors\n"
6545 " --kill-who=WHO Who to send signal to\n"
6546 " -s --signal=SIGNAL Which signal to send\n"
6547 " --now Start or stop unit in addition to enabling or disabling it\n"
6548 " -q --quiet Suppress output\n"
6549 " --no-block Do not wait until operation finished\n"
6550 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6551 " --no-reload Don't reload daemon after en-/dis-abling unit files\n"
6552 " --no-legend Do not print a legend (column headers and hints)\n"
6553 " --no-pager Do not pipe output into a pager\n"
6554 " --no-ask-password\n"
6555 " Do not ask for system passwords\n"
6556 " --global Enable/disable unit files globally\n"
6557 " --runtime Enable unit files only temporarily until next reboot\n"
6558 " -f --force When enabling unit files, override existing symlinks\n"
6559 " When shutting down, execute action immediately\n"
6560 " --preset-mode= Apply only enable, only disable, or all presets\n"
6561 " --root=PATH Enable unit files in the specified root directory\n"
6562 " -n --lines=INTEGER Number of journal entries to show\n"
6563 " -o --output=STRING Change journal output mode (short, short-iso,\n"
6564 " short-precise, short-monotonic, verbose,\n"
6565 " export, json, json-pretty, json-sse, cat)\n"
6566 " --firmware-setup Tell the firmware to show the setup menu on next boot\n"
6567 " --plain Print unit dependencies as a list instead of a tree\n\n"
6569 " list-units [PATTERN...] List loaded units\n"
6570 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
6571 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
6572 " start NAME... Start (activate) one or more units\n"
6573 " stop NAME... Stop (deactivate) one or more units\n"
6574 " reload NAME... Reload one or more units\n"
6575 " restart NAME... Start or restart one or more units\n"
6576 " try-restart NAME... Restart one or more units if active\n"
6577 " reload-or-restart NAME... Reload one or more units if possible,\n"
6578 " otherwise start or restart\n"
6579 " try-reload-or-restart NAME... If active, reload one or more units,\n"
6580 " if supported, otherwise restart\n"
6581 " isolate NAME Start one unit and stop all others\n"
6582 " kill NAME... Send signal to processes of a unit\n"
6583 " is-active PATTERN... Check whether units are active\n"
6584 " is-failed PATTERN... Check whether units are failed\n"
6585 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
6586 " show [PATTERN...|JOB...] Show properties of one or more\n"
6587 " units/jobs or the manager\n"
6588 " cat PATTERN... Show files and drop-ins of one or more units\n"
6589 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
6590 " help PATTERN...|PID... Show manual for one or more units\n"
6591 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
6593 " list-dependencies [NAME] Recursively show units which are required\n"
6594 " or wanted by this unit or by which this\n"
6595 " unit is required or wanted\n\n"
6596 "Unit File Commands:\n"
6597 " list-unit-files [PATTERN...] List installed unit files\n"
6598 " enable [NAME...|PATH...] Enable one or more unit files\n"
6599 " disable NAME... Disable one or more unit files\n"
6600 " reenable NAME... Reenable one or more unit files\n"
6601 " preset NAME... Enable/disable one or more unit files\n"
6602 " based on preset configuration\n"
6603 " preset-all Enable/disable all unit files based on\n"
6604 " preset configuration\n"
6605 " is-enabled NAME... Check whether unit files are enabled\n"
6606 " mask NAME... Mask one or more units\n"
6607 " unmask NAME... Unmask one or more units\n"
6608 " link PATH... Link one or more units files into\n"
6609 " the search path\n"
6610 " revert NAME... Revert one or more unit files to vendor\n"
6612 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
6613 " on specified one or more units\n"
6614 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
6615 " on specified one or more units\n"
6616 " edit NAME... Edit one or more unit files\n"
6617 " get-default Get the name of the default target\n"
6618 " set-default NAME Set the default target\n\n"
6619 "Machine Commands:\n"
6620 " list-machines [PATTERN...] List local containers and host\n\n"
6622 " list-jobs [PATTERN...] List jobs\n"
6623 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
6624 "Environment Commands:\n"
6625 " show-environment Dump environment\n"
6626 " set-environment NAME=VALUE... Set one or more environment variables\n"
6627 " unset-environment NAME... Unset one or more environment variables\n"
6628 " import-environment [NAME...] Import all or some environment variables\n\n"
6629 "Manager Lifecycle Commands:\n"
6630 " daemon-reload Reload systemd manager configuration\n"
6631 " daemon-reexec Reexecute systemd manager\n\n"
6632 "System Commands:\n"
6633 " is-system-running Check whether system is fully running\n"
6634 " default Enter system default mode\n"
6635 " rescue Enter system rescue mode\n"
6636 " emergency Enter system emergency mode\n"
6637 " halt Shut down and halt the system\n"
6638 " poweroff Shut down and power-off the system\n"
6639 " reboot [ARG] Shut down and reboot the system\n"
6640 " kexec Shut down and reboot the system with kexec\n"
6641 " exit [EXIT_CODE] Request user instance or container exit\n"
6642 " switch-root ROOT [INIT] Change to a different root file system\n"
6643 " suspend Suspend the system\n"
6644 " hibernate Hibernate the system\n"
6645 " hybrid-sleep Hibernate and suspend the system\n",
6646 program_invocation_short_name
);
6649 static void halt_help(void) {
6650 printf("%s [OPTIONS...]%s\n\n"
6651 "%s the system.\n\n"
6652 " --help Show this help\n"
6653 " --halt Halt the machine\n"
6654 " -p --poweroff Switch off the machine\n"
6655 " --reboot Reboot the machine\n"
6656 " -f --force Force immediate halt/power-off/reboot\n"
6657 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
6658 " -d --no-wtmp Don't write wtmp record\n"
6659 " --no-wall Don't send wall message before halt/power-off/reboot\n",
6660 program_invocation_short_name
,
6661 arg_action
== ACTION_REBOOT
? " [ARG]" : "",
6662 arg_action
== ACTION_REBOOT
? "Reboot" :
6663 arg_action
== ACTION_POWEROFF
? "Power off" :
6667 static void shutdown_help(void) {
6668 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
6669 "Shut down the system.\n\n"
6670 " --help Show this help\n"
6671 " -H --halt Halt the machine\n"
6672 " -P --poweroff Power-off the machine\n"
6673 " -r --reboot Reboot the machine\n"
6674 " -h Equivalent to --poweroff, overridden by --halt\n"
6675 " -k Don't halt/power-off/reboot, just send warnings\n"
6676 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6677 " -c Cancel a pending shutdown\n",
6678 program_invocation_short_name
);
6681 static void telinit_help(void) {
6682 printf("%s [OPTIONS...] {COMMAND}\n\n"
6683 "Send control commands to the init daemon.\n\n"
6684 " --help Show this help\n"
6685 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
6687 " 0 Power-off the machine\n"
6688 " 6 Reboot the machine\n"
6689 " 2, 3, 4, 5 Start runlevelX.target unit\n"
6690 " 1, s, S Enter rescue mode\n"
6691 " q, Q Reload init daemon configuration\n"
6692 " u, U Reexecute init daemon\n",
6693 program_invocation_short_name
);
6696 static void runlevel_help(void) {
6697 printf("%s [OPTIONS...]\n\n"
6698 "Prints the previous and current runlevel of the init system.\n\n"
6699 " --help Show this help\n",
6700 program_invocation_short_name
);
6703 static void help_types(void) {
6707 puts("Available unit types:");
6708 for (i
= 0; i
< _UNIT_TYPE_MAX
; i
++)
6709 puts(unit_type_to_string(i
));
6712 static void help_states(void) {
6716 puts("Available unit load states:");
6717 for (i
= 0; i
< _UNIT_LOAD_STATE_MAX
; i
++)
6718 puts(unit_load_state_to_string(i
));
6721 puts("\nAvailable unit active states:");
6722 for (i
= 0; i
< _UNIT_ACTIVE_STATE_MAX
; i
++)
6723 puts(unit_active_state_to_string(i
));
6726 puts("\nAvailable automount unit substates:");
6727 for (i
= 0; i
< _AUTOMOUNT_STATE_MAX
; i
++)
6728 puts(automount_state_to_string(i
));
6731 puts("\nAvailable busname unit substates:");
6732 for (i
= 0; i
< _BUSNAME_STATE_MAX
; i
++)
6733 puts(busname_state_to_string(i
));
6736 puts("\nAvailable device unit substates:");
6737 for (i
= 0; i
< _DEVICE_STATE_MAX
; i
++)
6738 puts(device_state_to_string(i
));
6741 puts("\nAvailable mount unit substates:");
6742 for (i
= 0; i
< _MOUNT_STATE_MAX
; i
++)
6743 puts(mount_state_to_string(i
));
6746 puts("\nAvailable path unit substates:");
6747 for (i
= 0; i
< _PATH_STATE_MAX
; i
++)
6748 puts(path_state_to_string(i
));
6751 puts("\nAvailable scope unit substates:");
6752 for (i
= 0; i
< _SCOPE_STATE_MAX
; i
++)
6753 puts(scope_state_to_string(i
));
6756 puts("\nAvailable service unit substates:");
6757 for (i
= 0; i
< _SERVICE_STATE_MAX
; i
++)
6758 puts(service_state_to_string(i
));
6761 puts("\nAvailable slice unit substates:");
6762 for (i
= 0; i
< _SLICE_STATE_MAX
; i
++)
6763 puts(slice_state_to_string(i
));
6766 puts("\nAvailable socket unit substates:");
6767 for (i
= 0; i
< _SOCKET_STATE_MAX
; i
++)
6768 puts(socket_state_to_string(i
));
6771 puts("\nAvailable swap unit substates:");
6772 for (i
= 0; i
< _SWAP_STATE_MAX
; i
++)
6773 puts(swap_state_to_string(i
));
6776 puts("\nAvailable target unit substates:");
6777 for (i
= 0; i
< _TARGET_STATE_MAX
; i
++)
6778 puts(target_state_to_string(i
));
6781 puts("\nAvailable timer unit substates:");
6782 for (i
= 0; i
< _TIMER_STATE_MAX
; i
++)
6783 puts(timer_state_to_string(i
));
6786 static int systemctl_parse_argv(int argc
, char *argv
[]) {
6795 ARG_IGNORE_DEPENDENCIES
,
6808 ARG_NO_ASK_PASSWORD
,
6821 static const struct option options
[] = {
6822 { "help", no_argument
, NULL
, 'h' },
6823 { "version", no_argument
, NULL
, ARG_VERSION
},
6824 { "type", required_argument
, NULL
, 't' },
6825 { "property", required_argument
, NULL
, 'p' },
6826 { "all", no_argument
, NULL
, 'a' },
6827 { "reverse", no_argument
, NULL
, ARG_REVERSE
},
6828 { "after", no_argument
, NULL
, ARG_AFTER
},
6829 { "before", no_argument
, NULL
, ARG_BEFORE
},
6830 { "show-types", no_argument
, NULL
, ARG_SHOW_TYPES
},
6831 { "failed", no_argument
, NULL
, ARG_FAILED
}, /* compatibility only */
6832 { "full", no_argument
, NULL
, 'l' },
6833 { "job-mode", required_argument
, NULL
, ARG_JOB_MODE
},
6834 { "fail", no_argument
, NULL
, ARG_FAIL
}, /* compatibility only */
6835 { "irreversible", no_argument
, NULL
, ARG_IRREVERSIBLE
}, /* compatibility only */
6836 { "ignore-dependencies", no_argument
, NULL
, ARG_IGNORE_DEPENDENCIES
}, /* compatibility only */
6837 { "ignore-inhibitors", no_argument
, NULL
, 'i' },
6838 { "value", no_argument
, NULL
, ARG_VALUE
},
6839 { "user", no_argument
, NULL
, ARG_USER
},
6840 { "system", no_argument
, NULL
, ARG_SYSTEM
},
6841 { "global", no_argument
, NULL
, ARG_GLOBAL
},
6842 { "no-block", no_argument
, NULL
, ARG_NO_BLOCK
},
6843 { "no-legend", no_argument
, NULL
, ARG_NO_LEGEND
},
6844 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
6845 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6846 { "quiet", no_argument
, NULL
, 'q' },
6847 { "root", required_argument
, NULL
, ARG_ROOT
},
6848 { "force", no_argument
, NULL
, ARG_FORCE
},
6849 { "no-reload", no_argument
, NULL
, ARG_NO_RELOAD
},
6850 { "kill-who", required_argument
, NULL
, ARG_KILL_WHO
},
6851 { "signal", required_argument
, NULL
, 's' },
6852 { "no-ask-password", no_argument
, NULL
, ARG_NO_ASK_PASSWORD
},
6853 { "host", required_argument
, NULL
, 'H' },
6854 { "machine", required_argument
, NULL
, 'M' },
6855 { "runtime", no_argument
, NULL
, ARG_RUNTIME
},
6856 { "lines", required_argument
, NULL
, 'n' },
6857 { "output", required_argument
, NULL
, 'o' },
6858 { "plain", no_argument
, NULL
, ARG_PLAIN
},
6859 { "state", required_argument
, NULL
, ARG_STATE
},
6860 { "recursive", no_argument
, NULL
, 'r' },
6861 { "preset-mode", required_argument
, NULL
, ARG_PRESET_MODE
},
6862 { "firmware-setup", no_argument
, NULL
, ARG_FIRMWARE_SETUP
},
6863 { "now", no_argument
, NULL
, ARG_NOW
},
6864 { "message", required_argument
, NULL
, ARG_MESSAGE
},
6874 /* we default to allowing interactive authorization only in systemctl (not in the legacy commands) */
6875 arg_ask_password
= true;
6877 while ((c
= getopt_long(argc
, argv
, "ht:p:alqfs:H:M:n:o:ir", options
, NULL
)) >= 0)
6889 if (isempty(optarg
)) {
6890 log_error("--type requires arguments.");
6896 _cleanup_free_
char *type
= NULL
;
6898 r
= extract_first_word(&p
, &type
, ",", 0);
6900 return log_error_errno(r
, "Failed to parse type: %s", optarg
);
6905 if (streq(type
, "help")) {
6910 if (unit_type_from_string(type
) >= 0) {
6911 if (strv_push(&arg_types
, type
) < 0)
6917 /* It's much nicer to use --state= for
6918 * load states, but let's support this
6919 * in --types= too for compatibility
6920 * with old versions */
6921 if (unit_load_state_from_string(type
) >= 0) {
6922 if (strv_push(&arg_states
, type
) < 0)
6928 log_error("Unknown unit type or load state '%s'.", type
);
6929 log_info("Use -t help to see a list of allowed values.");
6937 /* Make sure that if the empty property list
6938 was specified, we won't show any properties. */
6939 if (isempty(optarg
) && !arg_properties
) {
6940 arg_properties
= new0(char*, 1);
6941 if (!arg_properties
)
6946 _cleanup_free_
char *prop
= NULL
;
6948 r
= extract_first_word(&p
, &prop
, ",", 0);
6950 return log_error_errno(r
, "Failed to parse property: %s", optarg
);
6955 if (strv_push(&arg_properties
, prop
) < 0)
6962 /* If the user asked for a particular
6963 * property, show it to him, even if it is
6975 arg_dependency
= DEPENDENCY_REVERSE
;
6979 arg_dependency
= DEPENDENCY_AFTER
;
6983 arg_dependency
= DEPENDENCY_BEFORE
;
6986 case ARG_SHOW_TYPES
:
6987 arg_show_types
= true;
6995 arg_job_mode
= optarg
;
6999 arg_job_mode
= "fail";
7002 case ARG_IRREVERSIBLE
:
7003 arg_job_mode
= "replace-irreversibly";
7006 case ARG_IGNORE_DEPENDENCIES
:
7007 arg_job_mode
= "ignore-dependencies";
7011 arg_scope
= UNIT_FILE_USER
;
7015 arg_scope
= UNIT_FILE_SYSTEM
;
7019 arg_scope
= UNIT_FILE_GLOBAL
;
7023 arg_no_block
= true;
7027 arg_no_legend
= true;
7031 arg_no_pager
= true;
7039 r
= parse_path_argument_and_warn(optarg
, false, &arg_root
);
7049 if (strv_extend(&arg_states
, "failed") < 0)
7067 arg_no_reload
= true;
7071 arg_kill_who
= optarg
;
7075 arg_signal
= signal_from_string_try_harder(optarg
);
7076 if (arg_signal
< 0) {
7077 log_error("Failed to parse signal string %s.", optarg
);
7082 case ARG_NO_ASK_PASSWORD
:
7083 arg_ask_password
= false;
7087 arg_transport
= BUS_TRANSPORT_REMOTE
;
7092 arg_transport
= BUS_TRANSPORT_MACHINE
;
7101 if (safe_atou(optarg
, &arg_lines
) < 0) {
7102 log_error("Failed to parse lines '%s'", optarg
);
7108 arg_output
= output_mode_from_string(optarg
);
7109 if (arg_output
< 0) {
7110 log_error("Unknown output '%s'.", optarg
);
7116 arg_ignore_inhibitors
= true;
7123 case ARG_FIRMWARE_SETUP
:
7124 arg_firmware_setup
= true;
7128 if (isempty(optarg
)) {
7129 log_error("--signal requires arguments.");
7135 _cleanup_free_
char *s
= NULL
;
7137 r
= extract_first_word(&p
, &s
, ",", 0);
7139 return log_error_errno(r
, "Failed to parse signal: %s", optarg
);
7144 if (streq(s
, "help")) {
7149 if (strv_push(&arg_states
, s
) < 0)
7158 if (geteuid() != 0) {
7159 log_error("--recursive requires root privileges.");
7163 arg_recursive
= true;
7166 case ARG_PRESET_MODE
:
7168 arg_preset_mode
= unit_file_preset_mode_from_string(optarg
);
7169 if (arg_preset_mode
< 0) {
7170 log_error("Failed to parse preset mode: %s.", optarg
);
7181 if (strv_extend(&arg_wall
, optarg
) < 0)
7189 assert_not_reached("Unhandled option");
7192 if (arg_transport
!= BUS_TRANSPORT_LOCAL
&& arg_scope
!= UNIT_FILE_SYSTEM
) {
7193 log_error("Cannot access user instance remotely.");
7200 static int halt_parse_argv(int argc
, char *argv
[]) {
7209 static const struct option options
[] = {
7210 { "help", no_argument
, NULL
, ARG_HELP
},
7211 { "halt", no_argument
, NULL
, ARG_HALT
},
7212 { "poweroff", no_argument
, NULL
, 'p' },
7213 { "reboot", no_argument
, NULL
, ARG_REBOOT
},
7214 { "force", no_argument
, NULL
, 'f' },
7215 { "wtmp-only", no_argument
, NULL
, 'w' },
7216 { "no-wtmp", no_argument
, NULL
, 'd' },
7217 { "no-sync", no_argument
, NULL
, 'n' },
7218 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7227 if (utmp_get_runlevel(&runlevel
, NULL
) >= 0)
7228 if (runlevel
== '0' || runlevel
== '6')
7231 while ((c
= getopt_long(argc
, argv
, "pfwdnih", options
, NULL
)) >= 0)
7239 arg_action
= ACTION_HALT
;
7243 if (arg_action
!= ACTION_REBOOT
)
7244 arg_action
= ACTION_POWEROFF
;
7248 arg_action
= ACTION_REBOOT
;
7273 /* Compatibility nops */
7280 assert_not_reached("Unhandled option");
7283 if (arg_action
== ACTION_REBOOT
&& (argc
== optind
|| argc
== optind
+ 1)) {
7284 r
= update_reboot_parameter_and_warn(argc
== optind
+ 1 ? argv
[optind
] : NULL
);
7287 } else if (optind
< argc
) {
7288 log_error("Too many arguments.");
7295 static int parse_shutdown_time_spec(const char *t
, usec_t
*_u
) {
7299 if (streq(t
, "now"))
7301 else if (!strchr(t
, ':')) {
7304 if (safe_atou64(t
, &u
) < 0)
7307 *_u
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
* u
;
7316 hour
= strtol(t
, &e
, 10);
7317 if (errno
> 0 || *e
!= ':' || hour
< 0 || hour
> 23)
7320 minute
= strtol(e
+1, &e
, 10);
7321 if (errno
> 0 || *e
!= 0 || minute
< 0 || minute
> 59)
7324 n
= now(CLOCK_REALTIME
);
7325 s
= (time_t) (n
/ USEC_PER_SEC
);
7327 assert_se(localtime_r(&s
, &tm
));
7329 tm
.tm_hour
= (int) hour
;
7330 tm
.tm_min
= (int) minute
;
7333 assert_se(s
= mktime(&tm
));
7335 *_u
= (usec_t
) s
* USEC_PER_SEC
;
7338 *_u
+= USEC_PER_DAY
;
7344 static int shutdown_parse_argv(int argc
, char *argv
[]) {
7351 static const struct option options
[] = {
7352 { "help", no_argument
, NULL
, ARG_HELP
},
7353 { "halt", no_argument
, NULL
, 'H' },
7354 { "poweroff", no_argument
, NULL
, 'P' },
7355 { "reboot", no_argument
, NULL
, 'r' },
7356 { "kexec", no_argument
, NULL
, 'K' }, /* not documented extension */
7357 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7367 while ((c
= getopt_long(argc
, argv
, "HPrhkKtafFc", options
, NULL
)) >= 0)
7375 arg_action
= ACTION_HALT
;
7379 arg_action
= ACTION_POWEROFF
;
7384 arg_action
= ACTION_KEXEC
;
7386 arg_action
= ACTION_REBOOT
;
7390 arg_action
= ACTION_KEXEC
;
7394 if (arg_action
!= ACTION_HALT
)
7395 arg_action
= ACTION_POWEROFF
;
7410 /* Compatibility nops */
7414 arg_action
= ACTION_CANCEL_SHUTDOWN
;
7421 assert_not_reached("Unhandled option");
7424 if (argc
> optind
&& arg_action
!= ACTION_CANCEL_SHUTDOWN
) {
7425 r
= parse_shutdown_time_spec(argv
[optind
], &arg_when
);
7427 log_error("Failed to parse time specification: %s", argv
[optind
]);
7431 arg_when
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
;
7433 if (argc
> optind
&& arg_action
== ACTION_CANCEL_SHUTDOWN
)
7434 /* No time argument for shutdown cancel */
7435 wall
= argv
+ optind
;
7436 else if (argc
> optind
+ 1)
7437 /* We skip the time argument */
7438 wall
= argv
+ optind
+ 1;
7441 arg_wall
= strv_copy(wall
);
7451 static int telinit_parse_argv(int argc
, char *argv
[]) {
7458 static const struct option options
[] = {
7459 { "help", no_argument
, NULL
, ARG_HELP
},
7460 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7464 static const struct {
7468 { '0', ACTION_POWEROFF
},
7469 { '6', ACTION_REBOOT
},
7470 { '1', ACTION_RESCUE
},
7471 { '2', ACTION_RUNLEVEL2
},
7472 { '3', ACTION_RUNLEVEL3
},
7473 { '4', ACTION_RUNLEVEL4
},
7474 { '5', ACTION_RUNLEVEL5
},
7475 { 's', ACTION_RESCUE
},
7476 { 'S', ACTION_RESCUE
},
7477 { 'q', ACTION_RELOAD
},
7478 { 'Q', ACTION_RELOAD
},
7479 { 'u', ACTION_REEXEC
},
7480 { 'U', ACTION_REEXEC
}
7489 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
7504 assert_not_reached("Unhandled option");
7507 if (optind
>= argc
) {
7508 log_error("%s: required argument missing.", program_invocation_short_name
);
7512 if (optind
+ 1 < argc
) {
7513 log_error("Too many arguments.");
7517 if (strlen(argv
[optind
]) != 1) {
7518 log_error("Expected single character argument.");
7522 for (i
= 0; i
< ELEMENTSOF(table
); i
++)
7523 if (table
[i
].from
== argv
[optind
][0])
7526 if (i
>= ELEMENTSOF(table
)) {
7527 log_error("Unknown command '%s'.", argv
[optind
]);
7531 arg_action
= table
[i
].to
;
7538 static int runlevel_parse_argv(int argc
, char *argv
[]) {
7544 static const struct option options
[] = {
7545 { "help", no_argument
, NULL
, ARG_HELP
},
7554 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
7565 assert_not_reached("Unhandled option");
7568 if (optind
< argc
) {
7569 log_error("Too many arguments.");
7576 static int parse_argv(int argc
, char *argv
[]) {
7580 if (program_invocation_short_name
) {
7582 if (strstr(program_invocation_short_name
, "halt")) {
7583 arg_action
= ACTION_HALT
;
7584 return halt_parse_argv(argc
, argv
);
7585 } else if (strstr(program_invocation_short_name
, "poweroff")) {
7586 arg_action
= ACTION_POWEROFF
;
7587 return halt_parse_argv(argc
, argv
);
7588 } else if (strstr(program_invocation_short_name
, "reboot")) {
7590 arg_action
= ACTION_KEXEC
;
7592 arg_action
= ACTION_REBOOT
;
7593 return halt_parse_argv(argc
, argv
);
7594 } else if (strstr(program_invocation_short_name
, "shutdown")) {
7595 arg_action
= ACTION_POWEROFF
;
7596 return shutdown_parse_argv(argc
, argv
);
7597 } else if (strstr(program_invocation_short_name
, "init")) {
7599 if (sd_booted() > 0) {
7600 arg_action
= _ACTION_INVALID
;
7601 return telinit_parse_argv(argc
, argv
);
7603 /* Hmm, so some other init system is
7604 * running, we need to forward this
7605 * request to it. For now we simply
7606 * guess that it is Upstart. */
7608 execv(TELINIT
, argv
);
7610 log_error("Couldn't find an alternative telinit implementation to spawn.");
7614 } else if (strstr(program_invocation_short_name
, "runlevel")) {
7615 arg_action
= ACTION_RUNLEVEL
;
7616 return runlevel_parse_argv(argc
, argv
);
7620 arg_action
= ACTION_SYSTEMCTL
;
7621 return systemctl_parse_argv(argc
, argv
);
7624 #ifdef HAVE_SYSV_COMPAT
7625 _pure_
static int action_to_runlevel(void) {
7627 static const char table
[_ACTION_MAX
] = {
7628 [ACTION_HALT
] = '0',
7629 [ACTION_POWEROFF
] = '0',
7630 [ACTION_REBOOT
] = '6',
7631 [ACTION_RUNLEVEL2
] = '2',
7632 [ACTION_RUNLEVEL3
] = '3',
7633 [ACTION_RUNLEVEL4
] = '4',
7634 [ACTION_RUNLEVEL5
] = '5',
7635 [ACTION_RESCUE
] = '1'
7638 assert(arg_action
< _ACTION_MAX
);
7640 return table
[arg_action
];
7644 static int talk_initctl(void) {
7645 #ifdef HAVE_SYSV_COMPAT
7646 struct init_request request
= {
7647 .magic
= INIT_MAGIC
,
7649 .cmd
= INIT_CMD_RUNLVL
7652 _cleanup_close_
int fd
= -1;
7656 rl
= action_to_runlevel();
7660 request
.runlevel
= rl
;
7662 fd
= open(INIT_FIFO
, O_WRONLY
|O_NDELAY
|O_CLOEXEC
|O_NOCTTY
);
7664 if (errno
== ENOENT
)
7667 return log_error_errno(errno
, "Failed to open "INIT_FIFO
": %m");
7670 r
= loop_write(fd
, &request
, sizeof(request
), false);
7672 return log_error_errno(r
, "Failed to write to "INIT_FIFO
": %m");
7680 static int systemctl_main(int argc
, char *argv
[]) {
7682 static const Verb verbs
[] = {
7683 { "list-units", VERB_ANY
, VERB_ANY
, VERB_DEFAULT
|VERB_NOCHROOT
, list_units
},
7684 { "list-unit-files", VERB_ANY
, VERB_ANY
, 0, list_unit_files
},
7685 { "list-sockets", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_sockets
},
7686 { "list-timers", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_timers
},
7687 { "list-jobs", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_jobs
},
7688 { "list-machines", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_machines
},
7689 { "clear-jobs", VERB_ANY
, 1, VERB_NOCHROOT
, trivial_method
},
7690 { "cancel", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, cancel_job
},
7691 { "start", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
7692 { "stop", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
7693 { "condstop", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with ALTLinux */
7694 { "reload", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
7695 { "restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
7696 { "try-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
7697 { "reload-or-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
7698 { "reload-or-try-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatbility with old systemctl <= 228 */
7699 { "try-reload-or-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
7700 { "force-reload", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with SysV */
7701 { "condreload", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with ALTLinux */
7702 { "condrestart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with RH */
7703 { "isolate", 2, 2, VERB_NOCHROOT
, start_unit
},
7704 { "kill", 2, VERB_ANY
, VERB_NOCHROOT
, kill_unit
},
7705 { "is-active", 2, VERB_ANY
, VERB_NOCHROOT
, check_unit_active
},
7706 { "check", 2, VERB_ANY
, VERB_NOCHROOT
, check_unit_active
},
7707 { "is-failed", 2, VERB_ANY
, VERB_NOCHROOT
, check_unit_failed
},
7708 { "show", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, show
},
7709 { "cat", 2, VERB_ANY
, VERB_NOCHROOT
, cat
},
7710 { "status", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, show
},
7711 { "help", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, show
},
7712 { "daemon-reload", VERB_ANY
, 1, VERB_NOCHROOT
, daemon_reload
},
7713 { "daemon-reexec", VERB_ANY
, 1, VERB_NOCHROOT
, daemon_reload
},
7714 { "show-environment", VERB_ANY
, 1, VERB_NOCHROOT
, show_environment
},
7715 { "set-environment", 2, VERB_ANY
, VERB_NOCHROOT
, set_environment
},
7716 { "unset-environment", 2, VERB_ANY
, VERB_NOCHROOT
, set_environment
},
7717 { "import-environment", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, import_environment
},
7718 { "halt", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
7719 { "poweroff", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
7720 { "reboot", VERB_ANY
, 2, VERB_NOCHROOT
, start_system_special
},
7721 { "kexec", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
7722 { "suspend", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
7723 { "hibernate", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
7724 { "hybrid-sleep", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
7725 { "default", VERB_ANY
, 1, VERB_NOCHROOT
, start_special
},
7726 { "rescue", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
7727 { "emergency", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
7728 { "exit", VERB_ANY
, 2, VERB_NOCHROOT
, start_special
},
7729 { "reset-failed", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, reset_failed
},
7730 { "enable", 2, VERB_ANY
, 0, enable_unit
},
7731 { "disable", 2, VERB_ANY
, 0, enable_unit
},
7732 { "is-enabled", 2, VERB_ANY
, 0, unit_is_enabled
},
7733 { "reenable", 2, VERB_ANY
, 0, enable_unit
},
7734 { "preset", 2, VERB_ANY
, 0, enable_unit
},
7735 { "preset-all", VERB_ANY
, 1, 0, preset_all
},
7736 { "mask", 2, VERB_ANY
, 0, enable_unit
},
7737 { "unmask", 2, VERB_ANY
, 0, enable_unit
},
7738 { "link", 2, VERB_ANY
, 0, enable_unit
},
7739 { "revert", 2, VERB_ANY
, 0, enable_unit
},
7740 { "switch-root", 2, VERB_ANY
, VERB_NOCHROOT
, switch_root
},
7741 { "list-dependencies", VERB_ANY
, 2, VERB_NOCHROOT
, list_dependencies
},
7742 { "set-default", 2, 2, 0, set_default
},
7743 { "get-default", VERB_ANY
, 1, 0, get_default
},
7744 { "set-property", 3, VERB_ANY
, VERB_NOCHROOT
, set_property
},
7745 { "is-system-running", VERB_ANY
, 1, 0, is_system_running
},
7746 { "add-wants", 3, VERB_ANY
, 0, add_dependency
},
7747 { "add-requires", 3, VERB_ANY
, 0, add_dependency
},
7748 { "edit", 2, VERB_ANY
, VERB_NOCHROOT
, edit
},
7752 return dispatch_verb(argc
, argv
, verbs
, NULL
);
7755 static int reload_with_fallback(void) {
7757 /* First, try systemd via D-Bus. */
7758 if (daemon_reload(0, NULL
, NULL
) >= 0)
7761 /* Nothing else worked, so let's try signals */
7762 assert(IN_SET(arg_action
, ACTION_RELOAD
, ACTION_REEXEC
));
7764 if (kill(1, arg_action
== ACTION_RELOAD
? SIGHUP
: SIGTERM
) < 0)
7765 return log_error_errno(errno
, "kill() failed: %m");
7770 static int start_with_fallback(void) {
7772 /* First, try systemd via D-Bus. */
7773 if (start_unit(0, NULL
, NULL
) >= 0)
7776 /* Nothing else worked, so let's try /dev/initctl */
7777 if (talk_initctl() > 0)
7780 log_error("Failed to talk to init daemon.");
7784 static int halt_now(enum action a
) {
7787 /* The kernel will automaticall flush ATA disks and suchlike
7788 * on reboot(), but the file systems need to be synce'd
7789 * explicitly in advance. */
7793 /* Make sure C-A-D is handled by the kernel from this point
7795 (void) reboot(RB_ENABLE_CAD
);
7800 log_info("Halting.");
7801 (void) reboot(RB_HALT_SYSTEM
);
7804 case ACTION_POWEROFF
:
7805 log_info("Powering off.");
7806 (void) reboot(RB_POWER_OFF
);
7810 case ACTION_REBOOT
: {
7811 _cleanup_free_
char *param
= NULL
;
7813 r
= read_one_line_file("/run/systemd/reboot-param", ¶m
);
7815 log_warning_errno(r
, "Failed to read reboot parameter file: %m");
7817 if (!isempty(param
)) {
7818 log_info("Rebooting with argument '%s'.", param
);
7819 (void) syscall(SYS_reboot
, LINUX_REBOOT_MAGIC1
, LINUX_REBOOT_MAGIC2
, LINUX_REBOOT_CMD_RESTART2
, param
);
7820 log_warning_errno(errno
, "Failed to reboot with parameter, retrying without: %m");
7823 log_info("Rebooting.");
7824 (void) reboot(RB_AUTOBOOT
);
7829 assert_not_reached("Unknown action.");
7833 static int logind_schedule_shutdown(void) {
7836 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
7837 char date
[FORMAT_TIMESTAMP_MAX
];
7842 r
= acquire_bus(BUS_FULL
, &bus
);
7846 switch (arg_action
) {
7850 case ACTION_POWEROFF
:
7851 action
= "poweroff";
7866 action
= strjoina("dry-", action
);
7868 (void) logind_set_wall_message();
7870 r
= sd_bus_call_method(
7872 "org.freedesktop.login1",
7873 "/org/freedesktop/login1",
7874 "org.freedesktop.login1.Manager",
7882 return log_warning_errno(r
, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s", bus_error_message(&error
, r
));
7884 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.", format_timestamp(date
, sizeof(date
), arg_when
));
7887 log_error("Cannot schedule shutdown without logind support, proceeding with immediate shutdown.");
7892 static int halt_main(void) {
7895 r
= logind_check_inhibitors(arg_action
);
7900 return logind_schedule_shutdown();
7902 if (geteuid() != 0) {
7903 if (arg_dry
|| arg_force
> 0) {
7904 log_error("Must be root.");
7908 /* Try logind if we are a normal user and no special
7909 * mode applies. Maybe PolicyKit allows us to shutdown
7911 if (IN_SET(arg_action
, ACTION_POWEROFF
, ACTION_REBOOT
)) {
7912 r
= logind_reboot(arg_action
);
7915 if (IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
7916 /* requested operation is not
7917 * supported on the local system or
7918 * already in progress */
7920 /* on all other errors, try low-level operation */
7924 if (!arg_dry
&& !arg_force
)
7925 return start_with_fallback();
7927 assert(geteuid() == 0);
7930 if (sd_booted() > 0)
7931 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
7933 r
= utmp_put_shutdown();
7935 log_warning_errno(r
, "Failed to write utmp record: %m");
7942 r
= halt_now(arg_action
);
7943 return log_error_errno(r
, "Failed to reboot: %m");
7946 static int runlevel_main(void) {
7947 int r
, runlevel
, previous
;
7949 r
= utmp_get_runlevel(&runlevel
, &previous
);
7956 previous
<= 0 ? 'N' : previous
,
7957 runlevel
<= 0 ? 'N' : runlevel
);
7962 static int logind_cancel_shutdown(void) {
7964 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
7968 r
= acquire_bus(BUS_FULL
, &bus
);
7972 (void) logind_set_wall_message();
7974 r
= sd_bus_call_method(
7976 "org.freedesktop.login1",
7977 "/org/freedesktop/login1",
7978 "org.freedesktop.login1.Manager",
7979 "CancelScheduledShutdown",
7983 return log_warning_errno(r
, "Failed to talk to logind, shutdown hasn't been cancelled: %s", bus_error_message(&error
, r
));
7987 log_error("Not compiled with logind support, cannot cancel scheduled shutdowns.");
7992 int main(int argc
, char*argv
[]) {
7995 setlocale(LC_ALL
, "");
7996 log_parse_environment();
8000 /* Explicitly not on_tty() to avoid setting cached value.
8001 * This becomes relevant for piping output which might be
8003 original_stdout_is_tty
= isatty(STDOUT_FILENO
);
8005 r
= parse_argv(argc
, argv
);
8009 if (arg_action
!= ACTION_SYSTEMCTL
&& running_in_chroot() > 0) {
8010 log_info("Running in chroot, ignoring request.");
8015 /* systemctl_main() will print an error message for the bus
8016 * connection, but only if it needs to */
8018 switch (arg_action
) {
8020 case ACTION_SYSTEMCTL
:
8021 r
= systemctl_main(argc
, argv
);
8025 case ACTION_POWEROFF
:
8031 case ACTION_RUNLEVEL2
:
8032 case ACTION_RUNLEVEL3
:
8033 case ACTION_RUNLEVEL4
:
8034 case ACTION_RUNLEVEL5
:
8036 case ACTION_EMERGENCY
:
8037 case ACTION_DEFAULT
:
8038 r
= start_with_fallback();
8043 r
= reload_with_fallback();
8046 case ACTION_CANCEL_SHUTDOWN
:
8047 r
= logind_cancel_shutdown();
8050 case ACTION_RUNLEVEL
:
8051 r
= runlevel_main();
8054 case _ACTION_INVALID
:
8056 assert_not_reached("Unknown action");
8063 ask_password_agent_close();
8064 polkit_agent_close();
8066 strv_free(arg_types
);
8067 strv_free(arg_states
);
8068 strv_free(arg_properties
);
8070 strv_free(arg_wall
);
8073 /* Note that we return r here, not EXIT_SUCCESS, so that we can implement the LSB-like return codes */
8074 return r
< 0 ? EXIT_FAILURE
: r
;