1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
7 Copyright 2013 Marc-Antoine Perennou
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include <sys/reboot.h>
24 #include <linux/reboot.h>
33 #include <sys/socket.h>
36 #include "sd-daemon.h"
43 #include "utmp-wtmp.h"
46 #include "path-util.h"
48 #include "cgroup-show.h"
49 #include "cgroup-util.h"
51 #include "path-lookup.h"
52 #include "exit-status.h"
54 #include "unit-name.h"
56 #include "spawn-ask-password-agent.h"
57 #include "spawn-polkit-agent.h"
59 #include "logs-show.h"
60 #include "socket-util.h"
65 #include "bus-message.h"
66 #include "bus-error.h"
67 #include "bus-common-errors.h"
71 #include "formats-util.h"
72 #include "process-util.h"
73 #include "terminal-util.h"
74 #include "hostname-util.h"
75 #include "signal-util.h"
77 static char **arg_types
= NULL
;
78 static char **arg_states
= NULL
;
79 static char **arg_properties
= NULL
;
80 static bool arg_all
= false;
81 static enum dependency
{
87 } arg_dependency
= DEPENDENCY_FORWARD
;
88 static const char *arg_job_mode
= "replace";
89 static UnitFileScope arg_scope
= UNIT_FILE_SYSTEM
;
90 static bool arg_no_block
= false;
91 static bool arg_no_legend
= false;
92 static bool arg_no_pager
= false;
93 static bool arg_no_wtmp
= false;
94 static bool arg_no_wall
= false;
95 static bool arg_no_reload
= false;
96 static bool arg_show_types
= false;
97 static bool arg_ignore_inhibitors
= false;
98 static bool arg_dry
= false;
99 static bool arg_quiet
= false;
100 static bool arg_full
= false;
101 static bool arg_recursive
= false;
102 static int arg_force
= 0;
103 static bool arg_ask_password
= true;
104 static bool arg_runtime
= false;
105 static UnitFilePresetMode arg_preset_mode
= UNIT_FILE_PRESET_FULL
;
106 static char **arg_wall
= NULL
;
107 static const char *arg_kill_who
= NULL
;
108 static int arg_signal
= SIGTERM
;
109 static const char *arg_root
= NULL
;
110 static usec_t arg_when
= 0;
132 ACTION_CANCEL_SHUTDOWN
,
134 } arg_action
= ACTION_SYSTEMCTL
;
135 static BusTransport arg_transport
= BUS_TRANSPORT_LOCAL
;
136 static char *arg_host
= NULL
;
137 static unsigned arg_lines
= 10;
138 static OutputMode arg_output
= OUTPUT_SHORT
;
139 static bool arg_plain
= false;
140 static bool arg_firmware_setup
= false;
141 static bool arg_now
= false;
143 static bool original_stdout_is_tty
;
145 static int daemon_reload(sd_bus
*bus
, char **args
);
146 static int halt_now(enum action a
);
147 static int check_one_unit(sd_bus
*bus
, const char *name
, const char *good_states
, bool quiet
);
149 static char** strv_skip_first(char **strv
) {
150 if (strv_length(strv
) > 0)
155 static void pager_open_if_enabled(void) {
163 static void ask_password_agent_open_if_enabled(void) {
165 /* Open the password agent as a child process if necessary */
167 if (!arg_ask_password
)
170 if (arg_scope
!= UNIT_FILE_SYSTEM
)
173 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
176 ask_password_agent_open();
179 static void polkit_agent_open_if_enabled(void) {
181 /* Open the polkit agent as a child process if necessary */
183 if (!arg_ask_password
)
186 if (arg_scope
!= UNIT_FILE_SYSTEM
)
189 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
195 static OutputFlags
get_output_flags(void) {
197 arg_all
* OUTPUT_SHOW_ALL
|
198 arg_full
* OUTPUT_FULL_WIDTH
|
199 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH
|
200 on_tty() * OUTPUT_COLOR
|
201 !arg_quiet
* OUTPUT_WARN_CUTOFF
;
204 static int translate_bus_error_to_exit_status(int r
, const sd_bus_error
*error
) {
207 if (!sd_bus_error_is_set(error
))
210 if (sd_bus_error_has_name(error
, SD_BUS_ERROR_ACCESS_DENIED
) ||
211 sd_bus_error_has_name(error
, BUS_ERROR_ONLY_BY_DEPENDENCY
) ||
212 sd_bus_error_has_name(error
, BUS_ERROR_NO_ISOLATION
) ||
213 sd_bus_error_has_name(error
, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE
))
214 return EXIT_NOPERMISSION
;
216 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
))
217 return EXIT_NOTINSTALLED
;
219 if (sd_bus_error_has_name(error
, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE
) ||
220 sd_bus_error_has_name(error
, SD_BUS_ERROR_NOT_SUPPORTED
))
221 return EXIT_NOTIMPLEMENTED
;
223 if (sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
))
224 return EXIT_NOTCONFIGURED
;
232 static void warn_wall(enum action a
) {
233 static const char *table
[_ACTION_MAX
] = {
234 [ACTION_HALT
] = "The system is going down for system halt NOW!",
235 [ACTION_REBOOT
] = "The system is going down for reboot NOW!",
236 [ACTION_POWEROFF
] = "The system is going down for power-off NOW!",
237 [ACTION_KEXEC
] = "The system is going down for kexec reboot NOW!",
238 [ACTION_RESCUE
] = "The system is going down to rescue mode NOW!",
239 [ACTION_EMERGENCY
] = "The system is going down to emergency mode NOW!",
240 [ACTION_CANCEL_SHUTDOWN
] = "The system shutdown has been cancelled NOW!"
247 _cleanup_free_
char *p
;
249 p
= strv_join(arg_wall
, " ");
256 utmp_wall(p
, NULL
, NULL
, NULL
, NULL
);
264 utmp_wall(table
[a
], NULL
, NULL
, NULL
, NULL
);
267 static bool avoid_bus(void) {
269 if (running_in_chroot() > 0)
272 if (sd_booted() <= 0)
275 if (!isempty(arg_root
))
278 if (arg_scope
== UNIT_FILE_GLOBAL
)
284 static int compare_unit_info(const void *a
, const void *b
) {
285 const UnitInfo
*u
= a
, *v
= b
;
289 /* First, order by machine */
290 if (!u
->machine
&& v
->machine
)
292 if (u
->machine
&& !v
->machine
)
294 if (u
->machine
&& v
->machine
) {
295 r
= strcasecmp(u
->machine
, v
->machine
);
300 /* Second, order by unit type */
301 d1
= strrchr(u
->id
, '.');
302 d2
= strrchr(v
->id
, '.');
304 r
= strcasecmp(d1
, d2
);
309 /* Third, order by name */
310 return strcasecmp(u
->id
, v
->id
);
313 static bool output_show_unit(const UnitInfo
*u
, char **patterns
) {
314 if (!strv_fnmatch_or_empty(patterns
, u
->id
, FNM_NOESCAPE
))
320 dot
= strrchr(u
->id
, '.');
324 if (!strv_find(arg_types
, dot
+1))
334 if (streq(u
->active_state
, "inactive") || u
->following
[0])
340 static int output_units_list(const UnitInfo
*unit_infos
, unsigned c
) {
341 unsigned circle_len
= 0, id_len
, max_id_len
, load_len
, active_len
, sub_len
, job_len
, desc_len
;
343 unsigned n_shown
= 0;
346 max_id_len
= strlen("UNIT");
347 load_len
= strlen("LOAD");
348 active_len
= strlen("ACTIVE");
349 sub_len
= strlen("SUB");
350 job_len
= strlen("JOB");
353 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
354 max_id_len
= MAX(max_id_len
, strlen(u
->id
) + (u
->machine
? strlen(u
->machine
)+1 : 0));
355 load_len
= MAX(load_len
, strlen(u
->load_state
));
356 active_len
= MAX(active_len
, strlen(u
->active_state
));
357 sub_len
= MAX(sub_len
, strlen(u
->sub_state
));
359 if (u
->job_id
!= 0) {
360 job_len
= MAX(job_len
, strlen(u
->job_type
));
364 if (!arg_no_legend
&&
365 (streq(u
->active_state
, "failed") ||
366 STR_IN_SET(u
->load_state
, "error", "not-found", "masked")))
370 if (!arg_full
&& original_stdout_is_tty
) {
373 id_len
= MIN(max_id_len
, 25u);
374 basic_len
= circle_len
+ 5 + id_len
+ 5 + active_len
+ sub_len
;
377 basic_len
+= job_len
+ 1;
379 if (basic_len
< (unsigned) columns()) {
380 unsigned extra_len
, incr
;
381 extra_len
= columns() - basic_len
;
383 /* Either UNIT already got 25, or is fully satisfied.
384 * Grant up to 25 to DESC now. */
385 incr
= MIN(extra_len
, 25u);
389 /* split the remaining space between UNIT and DESC,
390 * but do not give UNIT more than it needs. */
392 incr
= MIN(extra_len
/ 2, max_id_len
- id_len
);
394 desc_len
+= extra_len
- incr
;
400 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
401 _cleanup_free_
char *e
= NULL
, *j
= NULL
;
402 const char *on_loaded
= "", *off_loaded
= "";
403 const char *on_active
= "", *off_active
= "";
404 const char *on_circle
= "", *off_circle
= "";
408 if (!n_shown
&& !arg_no_legend
) {
413 printf("%-*s %-*s %-*s %-*s ",
416 active_len
, "ACTIVE",
420 printf("%-*s ", job_len
, "JOB");
422 if (!arg_full
&& arg_no_pager
)
423 printf("%.*s\n", desc_len
, "DESCRIPTION");
425 printf("%s\n", "DESCRIPTION");
430 if (STR_IN_SET(u
->load_state
, "error", "not-found", "masked") && !arg_plain
) {
431 on_loaded
= ansi_highlight_red();
432 on_circle
= ansi_highlight_yellow();
433 off_loaded
= off_circle
= ansi_highlight_off();
435 } else if (streq(u
->active_state
, "failed") && !arg_plain
) {
436 on_circle
= on_active
= ansi_highlight_red();
437 off_circle
= off_active
= ansi_highlight_off();
442 j
= strjoin(u
->machine
, ":", u
->id
, NULL
);
451 e
= ellipsize(id
, id_len
, 33);
459 printf("%s%s%s ", on_circle
, circle
? draw_special_char(DRAW_BLACK_CIRCLE
) : " ", off_circle
);
461 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
462 on_active
, id_len
, id
, off_active
,
463 on_loaded
, load_len
, u
->load_state
, off_loaded
,
464 on_active
, active_len
, u
->active_state
,
465 sub_len
, u
->sub_state
, off_active
,
466 job_count
? job_len
+ 1 : 0, u
->job_id
? u
->job_type
: "");
469 printf("%.*s\n", desc_len
, u
->description
);
471 printf("%s\n", u
->description
);
474 if (!arg_no_legend
) {
475 const char *on
, *off
;
479 "LOAD = Reflects whether the unit definition was properly loaded.\n"
480 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
481 "SUB = The low-level unit activation state, values depend on unit type.");
482 puts(job_count
? "JOB = Pending job for the unit.\n" : "");
483 on
= ansi_highlight();
484 off
= ansi_highlight_off();
486 on
= ansi_highlight_red();
487 off
= ansi_highlight_off();
491 printf("%s%u loaded units listed.%s\n"
492 "To show all installed unit files use 'systemctl list-unit-files'.\n",
495 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
496 "To show all installed unit files use 'systemctl list-unit-files'.\n",
503 static int get_unit_list(
507 UnitInfo
**unit_infos
,
509 sd_bus_message
**_reply
) {
511 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
512 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
513 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
522 r
= sd_bus_message_new_method_call(
525 "org.freedesktop.systemd1",
526 "/org/freedesktop/systemd1",
527 "org.freedesktop.systemd1.Manager",
528 "ListUnitsFiltered");
531 return bus_log_create_error(r
);
533 r
= sd_bus_message_append_strv(m
, arg_states
);
535 return bus_log_create_error(r
);
537 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
539 return log_error_errno(r
, "Failed to list units: %s", bus_error_message(&error
, r
));
541 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssssouso)");
543 return bus_log_parse_error(r
);
545 while ((r
= bus_parse_unit_info(reply
, &u
)) > 0) {
548 if (!output_show_unit(&u
, patterns
))
551 if (!GREEDY_REALLOC(*unit_infos
, size
, c
+1))
554 (*unit_infos
)[c
++] = u
;
557 return bus_log_parse_error(r
);
559 r
= sd_bus_message_exit_container(reply
);
561 return bus_log_parse_error(r
);
569 static void message_set_freep(Set
**set
) {
572 while ((m
= set_steal_first(*set
)))
573 sd_bus_message_unref(m
);
578 static int get_unit_list_recursive(
581 UnitInfo
**_unit_infos
,
585 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
586 _cleanup_(message_set_freep
) Set
*replies
;
587 sd_bus_message
*reply
;
595 replies
= set_new(NULL
);
599 c
= get_unit_list(bus
, NULL
, patterns
, &unit_infos
, 0, &reply
);
603 r
= set_put(replies
, reply
);
605 sd_bus_message_unref(reply
);
610 _cleanup_strv_free_
char **machines
= NULL
;
613 r
= sd_get_machine_names(&machines
);
615 return log_error_errno(r
, "Failed to get machine names: %m");
617 STRV_FOREACH(i
, machines
) {
618 _cleanup_bus_flush_close_unref_ sd_bus
*container
= NULL
;
621 r
= sd_bus_open_system_machine(&container
, *i
);
623 log_warning_errno(r
, "Failed to connect to container %s, ignoring: %m", *i
);
627 k
= get_unit_list(container
, *i
, patterns
, &unit_infos
, c
, &reply
);
633 r
= set_put(replies
, reply
);
635 sd_bus_message_unref(reply
);
640 *_machines
= machines
;
645 *_unit_infos
= unit_infos
;
654 static int list_units(sd_bus
*bus
, char **args
) {
655 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
656 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
657 _cleanup_strv_free_
char **machines
= NULL
;
660 pager_open_if_enabled();
662 r
= get_unit_list_recursive(bus
, strv_skip_first(args
), &unit_infos
, &replies
, &machines
);
666 qsort_safe(unit_infos
, r
, sizeof(UnitInfo
), compare_unit_info
);
667 return output_units_list(unit_infos
, r
);
670 static int get_triggered_units(
675 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
678 r
= sd_bus_get_property_strv(
680 "org.freedesktop.systemd1",
682 "org.freedesktop.systemd1.Unit",
688 log_error("Failed to determine triggers: %s", bus_error_message(&error
, r
));
693 static int get_listening(
695 const char* unit_path
,
698 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
699 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
700 const char *type
, *path
;
703 r
= sd_bus_get_property(
705 "org.freedesktop.systemd1",
707 "org.freedesktop.systemd1.Socket",
713 log_error("Failed to get list of listening sockets: %s", bus_error_message(&error
, r
));
717 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
719 return bus_log_parse_error(r
);
721 while ((r
= sd_bus_message_read(reply
, "(ss)", &type
, &path
)) > 0) {
723 r
= strv_extend(listening
, type
);
727 r
= strv_extend(listening
, path
);
734 return bus_log_parse_error(r
);
736 r
= sd_bus_message_exit_container(reply
);
738 return bus_log_parse_error(r
);
750 /* Note: triggered is a list here, although it almost certainly
751 * will always be one unit. Nevertheless, dbus API allows for multiple
752 * values, so let's follow that. */
755 /* The strv above is shared. free is set only in the first one. */
759 static int socket_info_compare(const struct socket_info
*a
, const struct socket_info
*b
) {
765 if (!a
->machine
&& b
->machine
)
767 if (a
->machine
&& !b
->machine
)
769 if (a
->machine
&& b
->machine
) {
770 o
= strcasecmp(a
->machine
, b
->machine
);
775 o
= strcmp(a
->path
, b
->path
);
777 o
= strcmp(a
->type
, b
->type
);
782 static int output_sockets_list(struct socket_info
*socket_infos
, unsigned cs
) {
783 struct socket_info
*s
;
784 unsigned pathlen
= strlen("LISTEN"),
785 typelen
= strlen("TYPE") * arg_show_types
,
786 socklen
= strlen("UNIT"),
787 servlen
= strlen("ACTIVATES");
788 const char *on
, *off
;
790 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
794 socklen
= MAX(socklen
, strlen(s
->id
));
796 typelen
= MAX(typelen
, strlen(s
->type
));
797 pathlen
= MAX(pathlen
, strlen(s
->path
) + (s
->machine
? strlen(s
->machine
)+1 : 0));
799 STRV_FOREACH(a
, s
->triggered
)
800 tmp
+= strlen(*a
) + 2*(a
!= s
->triggered
);
801 servlen
= MAX(servlen
, tmp
);
806 printf("%-*s %-*.*s%-*s %s\n",
808 typelen
+ arg_show_types
, typelen
+ arg_show_types
, "TYPE ",
812 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
813 _cleanup_free_
char *j
= NULL
;
818 j
= strjoin(s
->machine
, ":", s
->path
, NULL
);
826 printf("%-*s %-*s %-*s",
827 pathlen
, path
, typelen
, s
->type
, socklen
, s
->id
);
830 pathlen
, path
, socklen
, s
->id
);
831 STRV_FOREACH(a
, s
->triggered
)
833 a
== s
->triggered
? "" : ",", *a
);
837 on
= ansi_highlight();
838 off
= ansi_highlight_off();
842 on
= ansi_highlight_red();
843 off
= ansi_highlight_off();
846 if (!arg_no_legend
) {
847 printf("%s%u sockets listed.%s\n", on
, cs
, off
);
849 printf("Pass --all to see loaded but inactive sockets, too.\n");
855 static int list_sockets(sd_bus
*bus
, char **args
) {
856 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
857 _cleanup_strv_free_
char **machines
= NULL
;
858 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
859 _cleanup_free_
struct socket_info
*socket_infos
= NULL
;
861 struct socket_info
*s
;
866 pager_open_if_enabled();
868 n
= get_unit_list_recursive(bus
, strv_skip_first(args
), &unit_infos
, &replies
, &machines
);
872 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
873 _cleanup_strv_free_
char **listening
= NULL
, **triggered
= NULL
;
876 if (!endswith(u
->id
, ".socket"))
879 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
883 c
= get_listening(bus
, u
->unit_path
, &listening
);
889 if (!GREEDY_REALLOC(socket_infos
, size
, cs
+ c
)) {
894 for (i
= 0; i
< c
; i
++)
895 socket_infos
[cs
+ i
] = (struct socket_info
) {
896 .machine
= u
->machine
,
898 .type
= listening
[i
*2],
899 .path
= listening
[i
*2 + 1],
900 .triggered
= triggered
,
901 .own_triggered
= i
==0,
904 /* from this point on we will cleanup those socket_infos */
907 listening
= triggered
= NULL
; /* avoid cleanup */
910 qsort_safe(socket_infos
, cs
, sizeof(struct socket_info
),
911 (__compar_fn_t
) socket_info_compare
);
913 output_sockets_list(socket_infos
, cs
);
916 assert(cs
== 0 || socket_infos
);
917 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
920 if (s
->own_triggered
)
921 strv_free(s
->triggered
);
927 static int get_next_elapse(
930 dual_timestamp
*next
) {
932 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
940 r
= sd_bus_get_property_trivial(
942 "org.freedesktop.systemd1",
944 "org.freedesktop.systemd1.Timer",
945 "NextElapseUSecMonotonic",
950 log_error("Failed to get next elapsation time: %s", bus_error_message(&error
, r
));
954 r
= sd_bus_get_property_trivial(
956 "org.freedesktop.systemd1",
958 "org.freedesktop.systemd1.Timer",
959 "NextElapseUSecRealtime",
964 log_error("Failed to get next elapsation time: %s", bus_error_message(&error
, r
));
972 static int get_last_trigger(
977 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
984 r
= sd_bus_get_property_trivial(
986 "org.freedesktop.systemd1",
988 "org.freedesktop.systemd1.Timer",
994 log_error("Failed to get last trigger time: %s", bus_error_message(&error
, r
));
1002 const char* machine
;
1005 usec_t last_trigger
;
1009 static int timer_info_compare(const struct timer_info
*a
, const struct timer_info
*b
) {
1015 if (!a
->machine
&& b
->machine
)
1017 if (a
->machine
&& !b
->machine
)
1019 if (a
->machine
&& b
->machine
) {
1020 o
= strcasecmp(a
->machine
, b
->machine
);
1025 if (a
->next_elapse
< b
->next_elapse
)
1027 if (a
->next_elapse
> b
->next_elapse
)
1030 return strcmp(a
->id
, b
->id
);
1033 static int output_timers_list(struct timer_info
*timer_infos
, unsigned n
) {
1034 struct timer_info
*t
;
1036 nextlen
= strlen("NEXT"),
1037 leftlen
= strlen("LEFT"),
1038 lastlen
= strlen("LAST"),
1039 passedlen
= strlen("PASSED"),
1040 unitlen
= strlen("UNIT"),
1041 activatelen
= strlen("ACTIVATES");
1043 const char *on
, *off
;
1045 assert(timer_infos
|| n
== 0);
1047 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1051 if (t
->next_elapse
> 0) {
1052 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1054 format_timestamp(tstamp
, sizeof(tstamp
), t
->next_elapse
);
1055 nextlen
= MAX(nextlen
, strlen(tstamp
) + 1);
1057 format_timestamp_relative(trel
, sizeof(trel
), t
->next_elapse
);
1058 leftlen
= MAX(leftlen
, strlen(trel
));
1061 if (t
->last_trigger
> 0) {
1062 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1064 format_timestamp(tstamp
, sizeof(tstamp
), t
->last_trigger
);
1065 lastlen
= MAX(lastlen
, strlen(tstamp
) + 1);
1067 format_timestamp_relative(trel
, sizeof(trel
), t
->last_trigger
);
1068 passedlen
= MAX(passedlen
, strlen(trel
));
1071 unitlen
= MAX(unitlen
, strlen(t
->id
) + (t
->machine
? strlen(t
->machine
)+1 : 0));
1073 STRV_FOREACH(a
, t
->triggered
)
1074 ul
+= strlen(*a
) + 2*(a
!= t
->triggered
);
1076 activatelen
= MAX(activatelen
, ul
);
1081 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1085 passedlen
, "PASSED",
1089 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1090 _cleanup_free_
char *j
= NULL
;
1092 char tstamp1
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel1
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1093 char tstamp2
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel2
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1096 format_timestamp(tstamp1
, sizeof(tstamp1
), t
->next_elapse
);
1097 format_timestamp_relative(trel1
, sizeof(trel1
), t
->next_elapse
);
1099 format_timestamp(tstamp2
, sizeof(tstamp2
), t
->last_trigger
);
1100 format_timestamp_relative(trel2
, sizeof(trel2
), t
->last_trigger
);
1103 j
= strjoin(t
->machine
, ":", t
->id
, NULL
);
1110 printf("%-*s %-*s %-*s %-*s %-*s",
1111 nextlen
, tstamp1
, leftlen
, trel1
, lastlen
, tstamp2
, passedlen
, trel2
, unitlen
, unit
);
1113 STRV_FOREACH(a
, t
->triggered
)
1115 a
== t
->triggered
? "" : ",", *a
);
1119 on
= ansi_highlight();
1120 off
= ansi_highlight_off();
1124 on
= ansi_highlight_red();
1125 off
= ansi_highlight_off();
1128 if (!arg_no_legend
) {
1129 printf("%s%u timers listed.%s\n", on
, n
, off
);
1131 printf("Pass --all to see loaded but inactive timers, too.\n");
1137 static usec_t
calc_next_elapse(dual_timestamp
*nw
, dual_timestamp
*next
) {
1143 if (next
->monotonic
!= USEC_INFINITY
&& next
->monotonic
> 0) {
1146 if (next
->monotonic
> nw
->monotonic
)
1147 converted
= nw
->realtime
+ (next
->monotonic
- nw
->monotonic
);
1149 converted
= nw
->realtime
- (nw
->monotonic
- next
->monotonic
);
1151 if (next
->realtime
!= USEC_INFINITY
&& next
->realtime
> 0)
1152 next_elapse
= MIN(converted
, next
->realtime
);
1154 next_elapse
= converted
;
1157 next_elapse
= next
->realtime
;
1162 static int list_timers(sd_bus
*bus
, char **args
) {
1163 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
1164 _cleanup_strv_free_
char **machines
= NULL
;
1165 _cleanup_free_
struct timer_info
*timer_infos
= NULL
;
1166 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
1167 struct timer_info
*t
;
1174 pager_open_if_enabled();
1176 n
= get_unit_list_recursive(bus
, strv_skip_first(args
), &unit_infos
, &replies
, &machines
);
1180 dual_timestamp_get(&nw
);
1182 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
1183 _cleanup_strv_free_
char **triggered
= NULL
;
1184 dual_timestamp next
= DUAL_TIMESTAMP_NULL
;
1187 if (!endswith(u
->id
, ".timer"))
1190 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
1194 r
= get_next_elapse(bus
, u
->unit_path
, &next
);
1198 get_last_trigger(bus
, u
->unit_path
, &last
);
1200 if (!GREEDY_REALLOC(timer_infos
, size
, c
+1)) {
1205 m
= calc_next_elapse(&nw
, &next
);
1207 timer_infos
[c
++] = (struct timer_info
) {
1208 .machine
= u
->machine
,
1211 .last_trigger
= last
,
1212 .triggered
= triggered
,
1215 triggered
= NULL
; /* avoid cleanup */
1218 qsort_safe(timer_infos
, c
, sizeof(struct timer_info
),
1219 (__compar_fn_t
) timer_info_compare
);
1221 output_timers_list(timer_infos
, c
);
1224 for (t
= timer_infos
; t
< timer_infos
+ c
; t
++)
1225 strv_free(t
->triggered
);
1230 static int compare_unit_file_list(const void *a
, const void *b
) {
1231 const char *d1
, *d2
;
1232 const UnitFileList
*u
= a
, *v
= b
;
1234 d1
= strrchr(u
->path
, '.');
1235 d2
= strrchr(v
->path
, '.');
1240 r
= strcasecmp(d1
, d2
);
1245 return strcasecmp(basename(u
->path
), basename(v
->path
));
1248 static bool output_show_unit_file(const UnitFileList
*u
, char **patterns
) {
1249 if (!strv_fnmatch_or_empty(patterns
, basename(u
->path
), FNM_NOESCAPE
))
1252 if (!strv_isempty(arg_types
)) {
1255 dot
= strrchr(u
->path
, '.');
1259 if (!strv_find(arg_types
, dot
+1))
1263 if (!strv_isempty(arg_states
) &&
1264 !strv_find(arg_states
, unit_file_state_to_string(u
->state
)))
1270 static void output_unit_file_list(const UnitFileList
*units
, unsigned c
) {
1271 unsigned max_id_len
, id_cols
, state_cols
;
1272 const UnitFileList
*u
;
1274 max_id_len
= strlen("UNIT FILE");
1275 state_cols
= strlen("STATE");
1277 for (u
= units
; u
< units
+ c
; u
++) {
1278 max_id_len
= MAX(max_id_len
, strlen(basename(u
->path
)));
1279 state_cols
= MAX(state_cols
, strlen(unit_file_state_to_string(u
->state
)));
1283 unsigned basic_cols
;
1285 id_cols
= MIN(max_id_len
, 25u);
1286 basic_cols
= 1 + id_cols
+ state_cols
;
1287 if (basic_cols
< (unsigned) columns())
1288 id_cols
+= MIN(columns() - basic_cols
, max_id_len
- id_cols
);
1290 id_cols
= max_id_len
;
1293 printf("%-*s %-*s\n",
1294 id_cols
, "UNIT FILE",
1295 state_cols
, "STATE");
1297 for (u
= units
; u
< units
+ c
; u
++) {
1298 _cleanup_free_
char *e
= NULL
;
1299 const char *on
, *off
;
1302 if (u
->state
== UNIT_FILE_MASKED
||
1303 u
->state
== UNIT_FILE_MASKED_RUNTIME
||
1304 u
->state
== UNIT_FILE_DISABLED
||
1305 u
->state
== UNIT_FILE_INVALID
) {
1306 on
= ansi_highlight_red();
1307 off
= ansi_highlight_off();
1308 } else if (u
->state
== UNIT_FILE_ENABLED
) {
1309 on
= ansi_highlight_green();
1310 off
= ansi_highlight_off();
1314 id
= basename(u
->path
);
1316 e
= arg_full
? NULL
: ellipsize(id
, id_cols
, 33);
1318 printf("%-*s %s%-*s%s\n",
1319 id_cols
, e
? e
: id
,
1320 on
, state_cols
, unit_file_state_to_string(u
->state
), off
);
1324 printf("\n%u unit files listed.\n", c
);
1327 static int list_unit_files(sd_bus
*bus
, char **args
) {
1328 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1329 _cleanup_free_ UnitFileList
*units
= NULL
;
1337 pager_open_if_enabled();
1345 h
= hashmap_new(&string_hash_ops
);
1349 r
= unit_file_get_list(arg_scope
, arg_root
, h
);
1351 unit_file_list_free(h
);
1352 log_error_errno(r
, "Failed to get unit file list: %m");
1356 n_units
= hashmap_size(h
);
1358 units
= new(UnitFileList
, n_units
);
1359 if (!units
&& n_units
> 0) {
1360 unit_file_list_free(h
);
1364 HASHMAP_FOREACH(u
, h
, i
) {
1365 if (!output_show_unit_file(u
, strv_skip_first(args
)))
1372 assert(c
<= n_units
);
1375 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1377 r
= sd_bus_call_method(
1379 "org.freedesktop.systemd1",
1380 "/org/freedesktop/systemd1",
1381 "org.freedesktop.systemd1.Manager",
1387 log_error("Failed to list unit files: %s", bus_error_message(&error
, r
));
1391 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
1393 return bus_log_parse_error(r
);
1395 while ((r
= sd_bus_message_read(reply
, "(ss)", &path
, &state
)) > 0) {
1397 if (!GREEDY_REALLOC(units
, size
, c
+ 1))
1400 units
[c
] = (struct UnitFileList
) {
1402 unit_file_state_from_string(state
)
1405 if (output_show_unit_file(&units
[c
], strv_skip_first(args
)))
1410 return bus_log_parse_error(r
);
1412 r
= sd_bus_message_exit_container(reply
);
1414 return bus_log_parse_error(r
);
1417 qsort_safe(units
, c
, sizeof(UnitFileList
), compare_unit_file_list
);
1418 output_unit_file_list(units
, c
);
1421 for (unit
= units
; unit
< units
+ c
; unit
++)
1428 static int list_dependencies_print(const char *name
, int level
, unsigned int branches
, bool last
) {
1429 _cleanup_free_
char *n
= NULL
;
1430 size_t max_len
= MAX(columns(),20u);
1436 for (i
= level
- 1; i
>= 0; i
--) {
1438 if (len
> max_len
- 3 && !arg_full
) {
1439 printf("%s...\n",max_len
% 2 ? "" : " ");
1442 printf("%s", draw_special_char(branches
& (1 << i
) ? DRAW_TREE_VERTICAL
: DRAW_TREE_SPACE
));
1446 if (len
> max_len
- 3 && !arg_full
) {
1447 printf("%s...\n",max_len
% 2 ? "" : " ");
1451 printf("%s", draw_special_char(last
? DRAW_TREE_RIGHT
: DRAW_TREE_BRANCH
));
1455 printf("%s\n", name
);
1459 n
= ellipsize(name
, max_len
-len
, 100);
1467 static int list_dependencies_get_dependencies(sd_bus
*bus
, const char *name
, char ***deps
) {
1469 static const char *dependencies
[_DEPENDENCY_MAX
] = {
1470 [DEPENDENCY_FORWARD
] = "Requires\0"
1471 "RequiresOverridable\0"
1473 "RequisiteOverridable\0"
1477 [DEPENDENCY_REVERSE
] = "RequiredBy\0"
1478 "RequiredByOverridable\0"
1480 "RequisiteOfOverridable\0"
1484 [DEPENDENCY_AFTER
] = "After\0",
1485 [DEPENDENCY_BEFORE
] = "Before\0",
1488 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1489 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1490 _cleanup_strv_free_
char **ret
= NULL
;
1491 _cleanup_free_
char *path
= NULL
;
1497 assert_cc(ELEMENTSOF(dependencies
) == _DEPENDENCY_MAX
);
1499 path
= unit_dbus_path_from_name(name
);
1503 r
= sd_bus_call_method(
1505 "org.freedesktop.systemd1",
1507 "org.freedesktop.DBus.Properties",
1511 "s", "org.freedesktop.systemd1.Unit");
1513 log_error("Failed to get properties of %s: %s", name
, bus_error_message(&error
, r
));
1517 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
1519 return bus_log_parse_error(r
);
1521 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
1524 r
= sd_bus_message_read(reply
, "s", &prop
);
1526 return bus_log_parse_error(r
);
1528 if (!nulstr_contains(dependencies
[arg_dependency
], prop
)) {
1529 r
= sd_bus_message_skip(reply
, "v");
1531 return bus_log_parse_error(r
);
1534 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, "as");
1536 return bus_log_parse_error(r
);
1538 r
= bus_message_read_strv_extend(reply
, &ret
);
1540 return bus_log_parse_error(r
);
1542 r
= sd_bus_message_exit_container(reply
);
1544 return bus_log_parse_error(r
);
1547 r
= sd_bus_message_exit_container(reply
);
1549 return bus_log_parse_error(r
);
1553 return bus_log_parse_error(r
);
1555 r
= sd_bus_message_exit_container(reply
);
1557 return bus_log_parse_error(r
);
1565 static int list_dependencies_compare(const void *_a
, const void *_b
) {
1566 const char **a
= (const char**) _a
, **b
= (const char**) _b
;
1568 if (unit_name_to_type(*a
) == UNIT_TARGET
&& unit_name_to_type(*b
) != UNIT_TARGET
)
1570 if (unit_name_to_type(*a
) != UNIT_TARGET
&& unit_name_to_type(*b
) == UNIT_TARGET
)
1573 return strcasecmp(*a
, *b
);
1576 static int list_dependencies_one(
1581 unsigned int branches
) {
1583 _cleanup_strv_free_
char **deps
= NULL
;
1591 r
= strv_extend(units
, name
);
1595 r
= list_dependencies_get_dependencies(bus
, name
, &deps
);
1599 qsort_safe(deps
, strv_length(deps
), sizeof (char*), list_dependencies_compare
);
1601 STRV_FOREACH(c
, deps
) {
1602 if (strv_contains(*units
, *c
)) {
1604 r
= list_dependencies_print("...", level
+ 1, (branches
<< 1) | (c
[1] == NULL
? 0 : 1), 1);
1617 state
= check_one_unit(bus
, *c
, "activating\0active\0reloading\0", true);
1618 on
= state
> 0 ? ansi_highlight_green() : ansi_highlight_red();
1619 printf("%s%s%s ", on
, draw_special_char(DRAW_BLACK_CIRCLE
), ansi_highlight_off());
1622 r
= list_dependencies_print(*c
, level
, branches
, c
[1] == NULL
);
1626 if (arg_all
|| unit_name_to_type(*c
) == UNIT_TARGET
) {
1627 r
= list_dependencies_one(bus
, *c
, level
+ 1, units
, (branches
<< 1) | (c
[1] == NULL
? 0 : 1));
1634 strv_remove(*units
, name
);
1639 static int list_dependencies(sd_bus
*bus
, char **args
) {
1640 _cleanup_strv_free_
char **units
= NULL
;
1641 _cleanup_free_
char *unit
= NULL
;
1648 r
= unit_name_mangle(args
[1], UNIT_NAME_NOGLOB
, &unit
);
1650 return log_error_errno(r
, "Failed to mangle unit name: %m");
1654 u
= SPECIAL_DEFAULT_TARGET
;
1656 pager_open_if_enabled();
1660 return list_dependencies_one(bus
, u
, 0, &units
, 0);
1663 struct machine_info
{
1667 char *control_group
;
1668 uint32_t n_failed_units
;
1673 static const struct bus_properties_map machine_info_property_map
[] = {
1674 { "SystemState", "s", NULL
, offsetof(struct machine_info
, state
) },
1675 { "NJobs", "u", NULL
, offsetof(struct machine_info
, n_jobs
) },
1676 { "NFailedUnits", "u", NULL
, offsetof(struct machine_info
, n_failed_units
) },
1677 { "ControlGroup", "s", NULL
, offsetof(struct machine_info
, control_group
) },
1678 { "UserspaceTimestamp", "t", NULL
, offsetof(struct machine_info
, timestamp
) },
1682 static void machine_info_clear(struct machine_info
*info
) {
1686 free(info
->control_group
);
1691 static void free_machines_list(struct machine_info
*machine_infos
, int n
) {
1697 for (i
= 0; i
< n
; i
++)
1698 machine_info_clear(&machine_infos
[i
]);
1700 free(machine_infos
);
1703 static int compare_machine_info(const void *a
, const void *b
) {
1704 const struct machine_info
*u
= a
, *v
= b
;
1706 if (u
->is_host
!= v
->is_host
)
1707 return u
->is_host
> v
->is_host
? -1 : 1;
1709 return strcasecmp(u
->name
, v
->name
);
1712 static int get_machine_properties(sd_bus
*bus
, struct machine_info
*mi
) {
1713 _cleanup_bus_flush_close_unref_ sd_bus
*container
= NULL
;
1719 r
= sd_bus_open_system_machine(&container
, mi
->name
);
1726 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, mi
);
1733 static bool output_show_machine(const char *name
, char **patterns
) {
1734 return strv_fnmatch_or_empty(patterns
, name
, FNM_NOESCAPE
);
1737 static int get_machine_list(
1739 struct machine_info
**_machine_infos
,
1742 struct machine_info
*machine_infos
= NULL
;
1743 _cleanup_strv_free_
char **m
= NULL
;
1744 _cleanup_free_
char *hn
= NULL
;
1749 hn
= gethostname_malloc();
1753 if (output_show_machine(hn
, patterns
)) {
1754 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1))
1757 machine_infos
[c
].is_host
= true;
1758 machine_infos
[c
].name
= hn
;
1761 get_machine_properties(bus
, &machine_infos
[c
]);
1765 r
= sd_get_machine_names(&m
);
1767 return log_error_errno(r
, "Failed to get machine list: %m");
1769 STRV_FOREACH(i
, m
) {
1770 _cleanup_free_
char *class = NULL
;
1772 if (!output_show_machine(*i
, patterns
))
1775 sd_machine_get_class(*i
, &class);
1776 if (!streq_ptr(class, "container"))
1779 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1)) {
1780 free_machines_list(machine_infos
, c
);
1784 machine_infos
[c
].is_host
= false;
1785 machine_infos
[c
].name
= strdup(*i
);
1786 if (!machine_infos
[c
].name
) {
1787 free_machines_list(machine_infos
, c
);
1791 get_machine_properties(NULL
, &machine_infos
[c
]);
1795 *_machine_infos
= machine_infos
;
1799 static void output_machines_list(struct machine_info
*machine_infos
, unsigned n
) {
1800 struct machine_info
*m
;
1803 namelen
= sizeof("NAME") - 1,
1804 statelen
= sizeof("STATE") - 1,
1805 failedlen
= sizeof("FAILED") - 1,
1806 jobslen
= sizeof("JOBS") - 1;
1808 assert(machine_infos
|| n
== 0);
1810 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
1811 namelen
= MAX(namelen
, strlen(m
->name
) + (m
->is_host
? sizeof(" (host)") - 1 : 0));
1812 statelen
= MAX(statelen
, m
->state
? strlen(m
->state
) : 0);
1813 failedlen
= MAX(failedlen
, DECIMAL_STR_WIDTH(m
->n_failed_units
));
1814 jobslen
= MAX(jobslen
, DECIMAL_STR_WIDTH(m
->n_jobs
));
1816 if (!arg_plain
&& !streq_ptr(m
->state
, "running"))
1820 if (!arg_no_legend
) {
1824 printf("%-*s %-*s %-*s %-*s\n",
1827 failedlen
, "FAILED",
1831 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
1832 const char *on_state
= "", *off_state
= "";
1833 const char *on_failed
= "", *off_failed
= "";
1834 bool circle
= false;
1836 if (streq_ptr(m
->state
, "degraded")) {
1837 on_state
= ansi_highlight_red();
1838 off_state
= ansi_highlight_off();
1840 } else if (!streq_ptr(m
->state
, "running")) {
1841 on_state
= ansi_highlight_yellow();
1842 off_state
= ansi_highlight_off();
1846 if (m
->n_failed_units
> 0) {
1847 on_failed
= ansi_highlight_red();
1848 off_failed
= ansi_highlight_off();
1850 on_failed
= off_failed
= "";
1853 printf("%s%s%s ", on_state
, circle
? draw_special_char(DRAW_BLACK_CIRCLE
) : " ", off_state
);
1856 printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
1857 (int) (namelen
- (sizeof(" (host)")-1)), strna(m
->name
),
1858 on_state
, statelen
, strna(m
->state
), off_state
,
1859 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
1860 jobslen
, m
->n_jobs
);
1862 printf("%-*s %s%-*s%s %s%*u%s %*u\n",
1863 namelen
, strna(m
->name
),
1864 on_state
, statelen
, strna(m
->state
), off_state
,
1865 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
1866 jobslen
, m
->n_jobs
);
1870 printf("\n%u machines listed.\n", n
);
1873 static int list_machines(sd_bus
*bus
, char **args
) {
1874 struct machine_info
*machine_infos
= NULL
;
1879 if (geteuid() != 0) {
1880 log_error("Must be root.");
1884 pager_open_if_enabled();
1886 r
= get_machine_list(bus
, &machine_infos
, strv_skip_first(args
));
1890 qsort_safe(machine_infos
, r
, sizeof(struct machine_info
), compare_machine_info
);
1891 output_machines_list(machine_infos
, r
);
1892 free_machines_list(machine_infos
, r
);
1897 static int get_default(sd_bus
*bus
, char **args
) {
1898 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1899 _cleanup_free_
char *_path
= NULL
;
1903 if (!bus
|| avoid_bus()) {
1904 r
= unit_file_get_default(arg_scope
, arg_root
, &_path
);
1906 return log_error_errno(r
, "Failed to get default target: %m");
1910 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1912 r
= sd_bus_call_method(
1914 "org.freedesktop.systemd1",
1915 "/org/freedesktop/systemd1",
1916 "org.freedesktop.systemd1.Manager",
1922 log_error("Failed to get default target: %s", bus_error_message(&error
, -r
));
1926 r
= sd_bus_message_read(reply
, "s", &path
);
1928 return bus_log_parse_error(r
);
1932 printf("%s\n", path
);
1937 static void dump_unit_file_changes(const UnitFileChange
*changes
, unsigned n_changes
) {
1940 assert(changes
|| n_changes
== 0);
1942 for (i
= 0; i
< n_changes
; i
++) {
1943 if (changes
[i
].type
== UNIT_FILE_SYMLINK
)
1944 log_info("Created symlink from %s to %s.", changes
[i
].path
, changes
[i
].source
);
1946 log_info("Removed symlink %s.", changes
[i
].path
);
1950 static int set_default(sd_bus
*bus
, char **args
) {
1951 _cleanup_free_
char *unit
= NULL
;
1952 UnitFileChange
*changes
= NULL
;
1953 unsigned n_changes
= 0;
1956 r
= unit_name_mangle_with_suffix(args
[1], UNIT_NAME_NOGLOB
, ".target", &unit
);
1958 return log_error_errno(r
, "Failed to mangle unit name: %m");
1960 if (!bus
|| avoid_bus()) {
1961 r
= unit_file_set_default(arg_scope
, arg_root
, unit
, true, &changes
, &n_changes
);
1963 return log_error_errno(r
, "Failed to set default target: %m");
1966 dump_unit_file_changes(changes
, n_changes
);
1970 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1971 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1973 polkit_agent_open_if_enabled();
1975 r
= sd_bus_call_method(
1977 "org.freedesktop.systemd1",
1978 "/org/freedesktop/systemd1",
1979 "org.freedesktop.systemd1.Manager",
1985 log_error("Failed to set default target: %s", bus_error_message(&error
, -r
));
1989 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, NULL
, NULL
);
1993 /* Try to reload if enabled */
1995 r
= daemon_reload(bus
, args
);
2000 unit_file_changes_free(changes
, n_changes
);
2007 const char *name
, *type
, *state
;
2010 static void output_jobs_list(const struct job_info
* jobs
, unsigned n
, bool skipped
) {
2011 unsigned id_len
, unit_len
, type_len
, state_len
;
2012 const struct job_info
*j
;
2013 const char *on
, *off
;
2014 bool shorten
= false;
2016 assert(n
== 0 || jobs
);
2019 if (!arg_no_legend
) {
2020 on
= ansi_highlight_green();
2021 off
= ansi_highlight_off();
2023 printf("%sNo jobs %s.%s\n", on
, skipped
? "listed" : "running", off
);
2028 pager_open_if_enabled();
2030 id_len
= strlen("JOB");
2031 unit_len
= strlen("UNIT");
2032 type_len
= strlen("TYPE");
2033 state_len
= strlen("STATE");
2035 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2036 uint32_t id
= j
->id
;
2037 assert(j
->name
&& j
->type
&& j
->state
);
2039 id_len
= MAX(id_len
, DECIMAL_STR_WIDTH(id
));
2040 unit_len
= MAX(unit_len
, strlen(j
->name
));
2041 type_len
= MAX(type_len
, strlen(j
->type
));
2042 state_len
= MAX(state_len
, strlen(j
->state
));
2045 if (!arg_full
&& id_len
+ 1 + unit_len
+ type_len
+ 1 + state_len
> columns()) {
2046 unit_len
= MAX(33u, columns() - id_len
- type_len
- state_len
- 3);
2051 printf("%*s %-*s %-*s %-*s\n",
2055 state_len
, "STATE");
2057 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2058 _cleanup_free_
char *e
= NULL
;
2060 if (streq(j
->state
, "running")) {
2061 on
= ansi_highlight();
2062 off
= ansi_highlight_off();
2066 e
= shorten
? ellipsize(j
->name
, unit_len
, 33) : NULL
;
2067 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2069 on
, unit_len
, e
? e
: j
->name
, off
,
2071 on
, state_len
, j
->state
, off
);
2074 if (!arg_no_legend
) {
2075 on
= ansi_highlight();
2076 off
= ansi_highlight_off();
2078 printf("\n%s%u jobs listed%s.\n", on
, n
, off
);
2082 static bool output_show_job(struct job_info
*job
, char **patterns
) {
2083 return strv_fnmatch_or_empty(patterns
, job
->name
, FNM_NOESCAPE
);
2086 static int list_jobs(sd_bus
*bus
, char **args
) {
2087 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2088 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2089 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2090 _cleanup_free_
struct job_info
*jobs
= NULL
;
2095 bool skipped
= false;
2097 r
= sd_bus_call_method(
2099 "org.freedesktop.systemd1",
2100 "/org/freedesktop/systemd1",
2101 "org.freedesktop.systemd1.Manager",
2107 log_error("Failed to list jobs: %s", bus_error_message(&error
, r
));
2111 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2113 return bus_log_parse_error(r
);
2115 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0) {
2116 struct job_info job
= { id
, name
, type
, state
};
2118 if (!output_show_job(&job
, strv_skip_first(args
))) {
2123 if (!GREEDY_REALLOC(jobs
, size
, c
+ 1))
2129 return bus_log_parse_error(r
);
2131 r
= sd_bus_message_exit_container(reply
);
2133 return bus_log_parse_error(r
);
2135 output_jobs_list(jobs
, c
, skipped
);
2139 static int cancel_job(sd_bus
*bus
, char **args
) {
2145 if (strv_length(args
) <= 1)
2146 return daemon_reload(bus
, args
);
2148 polkit_agent_open_if_enabled();
2150 STRV_FOREACH(name
, args
+1) {
2151 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2155 q
= safe_atou32(*name
, &id
);
2157 return log_error_errno(q
, "Failed to parse job id \"%s\": %m", *name
);
2159 q
= sd_bus_call_method(
2161 "org.freedesktop.systemd1",
2162 "/org/freedesktop/systemd1",
2163 "org.freedesktop.systemd1.Manager",
2169 log_error("Failed to cancel job %"PRIu32
": %s", id
, bus_error_message(&error
, q
));
2178 static int need_daemon_reload(sd_bus
*bus
, const char *unit
) {
2179 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2183 /* We ignore all errors here, since this is used to show a
2186 /* We don't use unit_dbus_path_from_name() directly since we
2187 * don't want to load the unit if it isn't loaded. */
2189 r
= sd_bus_call_method(
2191 "org.freedesktop.systemd1",
2192 "/org/freedesktop/systemd1",
2193 "org.freedesktop.systemd1.Manager",
2201 r
= sd_bus_message_read(reply
, "o", &path
);
2205 r
= sd_bus_get_property_trivial(
2207 "org.freedesktop.systemd1",
2209 "org.freedesktop.systemd1.Unit",
2219 static void warn_unit_file_changed(const char *name
) {
2220 log_warning("%sWarning:%s %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
2221 ansi_highlight_red(),
2222 ansi_highlight_off(),
2224 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user");
2227 static int unit_file_find_path(LookupPaths
*lp
, const char *unit_name
, char **unit_path
) {
2234 STRV_FOREACH(p
, lp
->unit_path
) {
2235 _cleanup_free_
char *path
;
2237 path
= path_join(arg_root
, *p
, unit_name
);
2241 if (access(path
, F_OK
) == 0) {
2251 static int unit_find_paths(
2253 const char *unit_name
,
2254 bool avoid_bus_cache
,
2256 char **fragment_path
,
2257 char ***dropin_paths
) {
2259 _cleanup_free_
char *path
= NULL
;
2260 _cleanup_strv_free_
char **dropins
= NULL
;
2264 * Finds where the unit is defined on disk. Returns 0 if the unit
2265 * is not found. Returns 1 if it is found, and sets
2266 * - the path to the unit in *path, if it exists on disk,
2267 * - and a strv of existing drop-ins in *dropins,
2268 * if the arg is not NULL and any dropins were found.
2272 assert(fragment_path
);
2275 if (!avoid_bus_cache
&& !unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
2276 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2277 _cleanup_bus_message_unref_ sd_bus_message
*unit_load_error
= NULL
;
2278 _cleanup_free_
char *unit
= NULL
;
2279 char *unit_load_error_name
, *unit_load_error_message
;
2281 unit
= unit_dbus_path_from_name(unit_name
);
2285 if (need_daemon_reload(bus
, unit_name
) > 0)
2286 warn_unit_file_changed(unit_name
);
2288 r
= sd_bus_get_property(
2290 "org.freedesktop.systemd1",
2292 "org.freedesktop.systemd1.Unit",
2298 return log_error_errno(r
, "Failed to get LoadError: %s", bus_error_message(&error
, r
));
2300 r
= sd_bus_message_read(
2303 &unit_load_error_name
,
2304 &unit_load_error_message
);
2306 return bus_log_parse_error(r
);
2308 if (!isempty(unit_load_error_name
)) {
2309 log_error("Unit %s is not loaded: %s", unit_name
, unit_load_error_message
);
2313 r
= sd_bus_get_property_string(
2315 "org.freedesktop.systemd1",
2317 "org.freedesktop.systemd1.Unit",
2322 return log_error_errno(r
, "Failed to get FragmentPath: %s", bus_error_message(&error
, r
));
2325 r
= sd_bus_get_property_strv(
2327 "org.freedesktop.systemd1",
2329 "org.freedesktop.systemd1.Unit",
2334 return log_error_errno(r
, "Failed to get DropInPaths: %s", bus_error_message(&error
, r
));
2337 _cleanup_set_free_ Set
*names
;
2339 names
= set_new(NULL
);
2343 r
= set_put(names
, unit_name
);
2345 return log_error_errno(r
, "Failed to add unit name: %m");
2347 r
= unit_file_find_path(lp
, unit_name
, &path
);
2352 _cleanup_free_
char *template = NULL
;
2354 r
= unit_name_template(unit_name
, &template);
2355 if (r
< 0 && r
!= -EINVAL
)
2356 return log_error_errno(r
, "Failed to determine template name: %m");
2358 r
= unit_file_find_path(lp
, template, &path
);
2365 r
= unit_file_find_dropin_paths(lp
->unit_path
, NULL
, names
, &dropins
);
2373 if (!isempty(path
)) {
2374 *fragment_path
= path
;
2379 if (dropin_paths
&& !strv_isempty(dropins
)) {
2380 *dropin_paths
= dropins
;
2386 log_error("No files found for %s.", unit_name
);
2391 static int check_one_unit(sd_bus
*bus
, const char *name
, const char *good_states
, bool quiet
) {
2392 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2393 _cleanup_free_
char *n
= NULL
, *state
= NULL
;
2399 r
= unit_name_mangle(name
, UNIT_NAME_NOGLOB
, &n
);
2401 return log_error_errno(r
, "Failed to mangle unit name: %m");
2403 /* We don't use unit_dbus_path_from_name() directly since we
2404 * don't want to load the unit if it isn't loaded. */
2406 r
= sd_bus_call_method(
2408 "org.freedesktop.systemd1",
2409 "/org/freedesktop/systemd1",
2410 "org.freedesktop.systemd1.Manager",
2421 r
= sd_bus_message_read(reply
, "o", &path
);
2423 return bus_log_parse_error(r
);
2425 r
= sd_bus_get_property_string(
2427 "org.freedesktop.systemd1",
2429 "org.freedesktop.systemd1.Unit",
2442 return nulstr_contains(good_states
, state
);
2445 static int check_triggering_units(
2449 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2450 _cleanup_free_
char *path
= NULL
, *n
= NULL
, *state
= NULL
;
2451 _cleanup_strv_free_
char **triggered_by
= NULL
;
2452 bool print_warning_label
= true;
2456 r
= unit_name_mangle(name
, UNIT_NAME_NOGLOB
, &n
);
2458 return log_error_errno(r
, "Failed to mangle unit name: %m");
2460 path
= unit_dbus_path_from_name(n
);
2464 r
= sd_bus_get_property_string(
2466 "org.freedesktop.systemd1",
2468 "org.freedesktop.systemd1.Unit",
2473 log_error("Failed to get load state of %s: %s", n
, bus_error_message(&error
, r
));
2477 if (streq(state
, "masked"))
2480 r
= sd_bus_get_property_strv(
2482 "org.freedesktop.systemd1",
2484 "org.freedesktop.systemd1.Unit",
2489 log_error("Failed to get triggered by array of %s: %s", n
, bus_error_message(&error
, r
));
2493 STRV_FOREACH(i
, triggered_by
) {
2494 r
= check_one_unit(bus
, *i
, "active\0reloading\0", true);
2496 return log_error_errno(r
, "Failed to check unit: %m");
2501 if (print_warning_label
) {
2502 log_warning("Warning: Stopping %s, but it can still be activated by:", n
);
2503 print_warning_label
= false;
2506 log_warning(" %s", *i
);
2512 static const struct {
2515 } unit_actions
[] = {
2516 { "start", "StartUnit" },
2517 { "stop", "StopUnit" },
2518 { "condstop", "StopUnit" },
2519 { "reload", "ReloadUnit" },
2520 { "restart", "RestartUnit" },
2521 { "try-restart", "TryRestartUnit" },
2522 { "condrestart", "TryRestartUnit" },
2523 { "reload-or-restart", "ReloadOrRestartUnit" },
2524 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2525 { "condreload", "ReloadOrTryRestartUnit" },
2526 { "force-reload", "ReloadOrTryRestartUnit" }
2529 static const char *verb_to_method(const char *verb
) {
2532 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2533 if (streq_ptr(unit_actions
[i
].verb
, verb
))
2534 return unit_actions
[i
].method
;
2539 static const char *method_to_verb(const char *method
) {
2542 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2543 if (streq_ptr(unit_actions
[i
].method
, method
))
2544 return unit_actions
[i
].verb
;
2549 static int start_unit_one(
2554 sd_bus_error
*error
,
2555 BusWaitForJobs
*w
) {
2557 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2566 log_debug("Calling manager for %s on %s, %s", method
, name
, mode
);
2568 r
= sd_bus_call_method(
2570 "org.freedesktop.systemd1",
2571 "/org/freedesktop/systemd1",
2572 "org.freedesktop.systemd1.Manager",
2580 if (r
== -ENOENT
&& arg_action
!= ACTION_SYSTEMCTL
)
2581 /* There's always a fallback possible for
2582 * legacy actions. */
2583 return -EADDRNOTAVAIL
;
2585 verb
= method_to_verb(method
);
2587 log_error("Failed to %s %s: %s", verb
, name
, bus_error_message(error
, r
));
2591 r
= sd_bus_message_read(reply
, "o", &path
);
2593 return bus_log_parse_error(r
);
2595 if (need_daemon_reload(bus
, name
) > 0)
2596 warn_unit_file_changed(name
);
2599 log_debug("Adding %s to the set", path
);
2600 r
= bus_wait_for_jobs_add(w
, path
);
2608 static int expand_names(sd_bus
*bus
, char **names
, const char* suffix
, char ***ret
) {
2610 _cleanup_strv_free_
char **mangled
= NULL
, **globs
= NULL
;
2614 STRV_FOREACH(name
, names
) {
2618 r
= unit_name_mangle_with_suffix(*name
, UNIT_NAME_GLOB
, suffix
, &t
);
2620 r
= unit_name_mangle(*name
, UNIT_NAME_GLOB
, &t
);
2622 return log_error_errno(r
, "Failed to mangle name: %m");
2624 if (string_is_glob(t
))
2625 r
= strv_consume(&globs
, t
);
2627 r
= strv_consume(&mangled
, t
);
2632 /* Query the manager only if any of the names are a glob, since
2633 * this is fairly expensive */
2634 if (!strv_isempty(globs
)) {
2635 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2636 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
2639 return log_error_errno(EOPNOTSUPP
, "Unit name globbing without bus is not implemented.");
2641 r
= get_unit_list(bus
, NULL
, globs
, &unit_infos
, 0, &reply
);
2645 for (i
= 0; i
< r
; i
++)
2646 if (strv_extend(&mangled
, unit_infos
[i
].id
) < 0)
2651 mangled
= NULL
; /* do not free */
2656 static const struct {
2660 } action_table
[_ACTION_MAX
] = {
2661 [ACTION_HALT
] = { SPECIAL_HALT_TARGET
, "halt", "replace-irreversibly" },
2662 [ACTION_POWEROFF
] = { SPECIAL_POWEROFF_TARGET
, "poweroff", "replace-irreversibly" },
2663 [ACTION_REBOOT
] = { SPECIAL_REBOOT_TARGET
, "reboot", "replace-irreversibly" },
2664 [ACTION_KEXEC
] = { SPECIAL_KEXEC_TARGET
, "kexec", "replace-irreversibly" },
2665 [ACTION_RUNLEVEL2
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2666 [ACTION_RUNLEVEL3
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2667 [ACTION_RUNLEVEL4
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2668 [ACTION_RUNLEVEL5
] = { SPECIAL_GRAPHICAL_TARGET
, NULL
, "isolate" },
2669 [ACTION_RESCUE
] = { SPECIAL_RESCUE_TARGET
, "rescue", "isolate" },
2670 [ACTION_EMERGENCY
] = { SPECIAL_EMERGENCY_TARGET
, "emergency", "isolate" },
2671 [ACTION_DEFAULT
] = { SPECIAL_DEFAULT_TARGET
, "default", "isolate" },
2672 [ACTION_EXIT
] = { SPECIAL_EXIT_TARGET
, "exit", "replace-irreversibly" },
2673 [ACTION_SUSPEND
] = { SPECIAL_SUSPEND_TARGET
, "suspend", "replace-irreversibly" },
2674 [ACTION_HIBERNATE
] = { SPECIAL_HIBERNATE_TARGET
, "hibernate", "replace-irreversibly" },
2675 [ACTION_HYBRID_SLEEP
] = { SPECIAL_HYBRID_SLEEP_TARGET
, "hybrid-sleep", "replace-irreversibly" },
2678 static enum action
verb_to_action(const char *verb
) {
2681 for (i
= _ACTION_INVALID
; i
< _ACTION_MAX
; i
++)
2682 if (streq_ptr(action_table
[i
].verb
, verb
))
2685 return _ACTION_INVALID
;
2688 static int start_unit(sd_bus
*bus
, char **args
) {
2689 _cleanup_(bus_wait_for_jobs_freep
) BusWaitForJobs
*w
= NULL
;
2690 const char *method
, *mode
, *one_name
, *suffix
= NULL
;
2691 _cleanup_strv_free_
char **names
= NULL
;
2697 ask_password_agent_open_if_enabled();
2698 polkit_agent_open_if_enabled();
2700 if (arg_action
== ACTION_SYSTEMCTL
) {
2702 method
= verb_to_method(args
[0]);
2703 action
= verb_to_action(args
[0]);
2705 if (streq(args
[0], "isolate")) {
2709 mode
= action_table
[action
].mode
?: arg_job_mode
;
2711 one_name
= action_table
[action
].target
;
2713 assert(arg_action
< ELEMENTSOF(action_table
));
2714 assert(action_table
[arg_action
].target
);
2716 method
= "StartUnit";
2718 mode
= action_table
[arg_action
].mode
;
2719 one_name
= action_table
[arg_action
].target
;
2723 names
= strv_new(one_name
, NULL
);
2725 r
= expand_names(bus
, args
+ 1, suffix
, &names
);
2727 log_error_errno(r
, "Failed to expand names: %m");
2730 if (!arg_no_block
) {
2731 r
= bus_wait_for_jobs_new(bus
, &w
);
2733 return log_error_errno(r
, "Could not watch jobs: %m");
2736 STRV_FOREACH(name
, names
) {
2737 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2740 q
= start_unit_one(bus
, method
, *name
, mode
, &error
, w
);
2741 if (r
>= 0 && q
< 0)
2742 r
= translate_bus_error_to_exit_status(q
, &error
);
2745 if (!arg_no_block
) {
2748 q
= bus_wait_for_jobs(w
, arg_quiet
);
2752 /* When stopping units, warn if they can still be triggered by
2753 * another active unit (socket, path, timer) */
2754 if (!arg_quiet
&& streq(method
, "StopUnit"))
2755 STRV_FOREACH(name
, names
)
2756 check_triggering_units(bus
, *name
);
2762 /* Ask systemd-logind, which might grant access to unprivileged users
2763 * through PolicyKit */
2764 static int reboot_with_logind(sd_bus
*bus
, enum action a
) {
2766 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2773 polkit_agent_open_if_enabled();
2781 case ACTION_POWEROFF
:
2782 method
= "PowerOff";
2785 case ACTION_SUSPEND
:
2789 case ACTION_HIBERNATE
:
2790 method
= "Hibernate";
2793 case ACTION_HYBRID_SLEEP
:
2794 method
= "HybridSleep";
2801 if (!strv_isempty(arg_wall
)) {
2802 _cleanup_free_
char *m
;
2804 m
= strv_join(arg_wall
, " ");
2808 r
= sd_bus_call_method(
2810 "org.freedesktop.login1",
2811 "/org/freedesktop/login1",
2812 "org.freedesktop.login1.Manager",
2821 log_warning_errno(r
, "Failed to set wall message, ignoring: %s",
2822 bus_error_message(&error
, r
));
2823 sd_bus_error_free(&error
);
2828 r
= sd_bus_call_method(
2830 "org.freedesktop.login1",
2831 "/org/freedesktop/login1",
2832 "org.freedesktop.login1.Manager",
2836 "b", arg_ask_password
);
2838 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
2846 static int check_inhibitors(sd_bus
*bus
, enum action a
) {
2848 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2849 _cleanup_strv_free_
char **sessions
= NULL
;
2850 const char *what
, *who
, *why
, *mode
;
2859 if (arg_ignore_inhibitors
|| arg_force
> 0)
2871 r
= sd_bus_call_method(
2873 "org.freedesktop.login1",
2874 "/org/freedesktop/login1",
2875 "org.freedesktop.login1.Manager",
2881 /* If logind is not around, then there are no inhibitors... */
2884 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssuu)");
2886 return bus_log_parse_error(r
);
2888 while ((r
= sd_bus_message_read(reply
, "(ssssuu)", &what
, &who
, &why
, &mode
, &uid
, &pid
)) > 0) {
2889 _cleanup_free_
char *comm
= NULL
, *user
= NULL
;
2890 _cleanup_strv_free_
char **sv
= NULL
;
2892 if (!streq(mode
, "block"))
2895 sv
= strv_split(what
, ":");
2899 if ((pid_t
) pid
< 0)
2900 return log_error_errno(ERANGE
, "Bad PID %"PRIu32
": %m", pid
);
2902 if (!strv_contains(sv
,
2904 a
== ACTION_POWEROFF
||
2905 a
== ACTION_REBOOT
||
2906 a
== ACTION_KEXEC
? "shutdown" : "sleep"))
2909 get_process_comm(pid
, &comm
);
2910 user
= uid_to_name(uid
);
2912 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT
" \"%s\", user %s), reason is \"%s\".",
2913 who
, (pid_t
) pid
, strna(comm
), strna(user
), why
);
2918 return bus_log_parse_error(r
);
2920 r
= sd_bus_message_exit_container(reply
);
2922 return bus_log_parse_error(r
);
2924 /* Check for current sessions */
2925 sd_get_sessions(&sessions
);
2926 STRV_FOREACH(s
, sessions
) {
2927 _cleanup_free_
char *type
= NULL
, *tty
= NULL
, *seat
= NULL
, *user
= NULL
, *service
= NULL
, *class = NULL
;
2929 if (sd_session_get_uid(*s
, &uid
) < 0 || uid
== getuid())
2932 if (sd_session_get_class(*s
, &class) < 0 || !streq(class, "user"))
2935 if (sd_session_get_type(*s
, &type
) < 0 || (!streq(type
, "x11") && !streq(type
, "tty")))
2938 sd_session_get_tty(*s
, &tty
);
2939 sd_session_get_seat(*s
, &seat
);
2940 sd_session_get_service(*s
, &service
);
2941 user
= uid_to_name(uid
);
2943 log_warning("User %s is logged in on %s.", strna(user
), isempty(tty
) ? (isempty(seat
) ? strna(service
) : seat
) : tty
);
2950 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2951 action_table
[a
].verb
);
2959 static int prepare_firmware_setup(sd_bus
*bus
) {
2961 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2965 if (!arg_firmware_setup
)
2968 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
2970 r
= efi_set_reboot_to_firmware(true);
2972 log_debug_errno(r
, "Cannot indicate to EFI to boot into setup mode, will retry via logind: %m");
2978 r
= sd_bus_call_method(
2980 "org.freedesktop.login1",
2981 "/org/freedesktop/login1",
2982 "org.freedesktop.login1.Manager",
2983 "SetRebootToFirmwareSetup",
2988 log_error("Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error
, r
));
2994 log_error("Cannot remotely indicate to EFI to boot into setup mode.");
2999 static int start_special(sd_bus
*bus
, char **args
) {
3005 a
= verb_to_action(args
[0]);
3007 r
= check_inhibitors(bus
, a
);
3011 if (arg_force
>= 2 && geteuid() != 0) {
3012 log_error("Must be root.");
3016 r
= prepare_firmware_setup(bus
);
3020 if (a
== ACTION_REBOOT
&& args
[1]) {
3021 r
= update_reboot_param_file(args
[1]);
3026 if (arg_force
>= 2 &&
3027 (a
== ACTION_HALT
||
3028 a
== ACTION_POWEROFF
||
3029 a
== ACTION_REBOOT
))
3032 if (arg_force
>= 1 &&
3033 (a
== ACTION_HALT
||
3034 a
== ACTION_POWEROFF
||
3035 a
== ACTION_REBOOT
||
3036 a
== ACTION_KEXEC
||
3038 return daemon_reload(bus
, args
);
3040 /* first try logind, to allow authentication with polkit */
3041 if (geteuid() != 0 &&
3042 (a
== ACTION_POWEROFF
||
3043 a
== ACTION_REBOOT
||
3044 a
== ACTION_SUSPEND
||
3045 a
== ACTION_HIBERNATE
||
3046 a
== ACTION_HYBRID_SLEEP
)) {
3047 r
= reboot_with_logind(bus
, a
);
3048 if (r
>= 0 || IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
3052 r
= start_unit(bus
, args
);
3053 if (r
== EXIT_SUCCESS
)
3059 static int check_unit_generic(sd_bus
*bus
, int code
, const char *good_states
, char **args
) {
3060 _cleanup_strv_free_
char **names
= NULL
;
3067 r
= expand_names(bus
, args
, NULL
, &names
);
3069 return log_error_errno(r
, "Failed to expand names: %m");
3071 STRV_FOREACH(name
, names
) {
3074 state
= check_one_unit(bus
, *name
, good_states
, arg_quiet
);
3084 static int check_unit_active(sd_bus
*bus
, char **args
) {
3085 /* According to LSB: 3, "program is not running" */
3086 return check_unit_generic(bus
, 3, "active\0reloading\0", args
+ 1);
3089 static int check_unit_failed(sd_bus
*bus
, char **args
) {
3090 return check_unit_generic(bus
, 1, "failed\0", args
+ 1);
3093 static int kill_unit(sd_bus
*bus
, char **args
) {
3094 _cleanup_strv_free_
char **names
= NULL
;
3101 polkit_agent_open_if_enabled();
3104 arg_kill_who
= "all";
3106 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
3108 log_error_errno(r
, "Failed to expand names: %m");
3110 STRV_FOREACH(name
, names
) {
3111 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
3113 q
= sd_bus_call_method(
3115 "org.freedesktop.systemd1",
3116 "/org/freedesktop/systemd1",
3117 "org.freedesktop.systemd1.Manager",
3121 "ssi", *names
, arg_kill_who
, arg_signal
);
3123 log_error("Failed to kill unit %s: %s", *names
, bus_error_message(&error
, q
));
3132 typedef struct ExecStatusInfo
{
3140 usec_t start_timestamp
;
3141 usec_t exit_timestamp
;
3146 LIST_FIELDS(struct ExecStatusInfo
, exec
);
3149 static void exec_status_info_free(ExecStatusInfo
*i
) {
3158 static int exec_status_info_deserialize(sd_bus_message
*m
, ExecStatusInfo
*i
) {
3159 uint64_t start_timestamp
, exit_timestamp
, start_timestamp_monotonic
, exit_timestamp_monotonic
;
3162 int32_t code
, status
;
3168 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_STRUCT
, "sasbttttuii");
3170 return bus_log_parse_error(r
);
3174 r
= sd_bus_message_read(m
, "s", &path
);
3176 return bus_log_parse_error(r
);
3178 i
->path
= strdup(path
);
3182 r
= sd_bus_message_read_strv(m
, &i
->argv
);
3184 return bus_log_parse_error(r
);
3186 r
= sd_bus_message_read(m
,
3189 &start_timestamp
, &start_timestamp_monotonic
,
3190 &exit_timestamp
, &exit_timestamp_monotonic
,
3194 return bus_log_parse_error(r
);
3197 i
->start_timestamp
= (usec_t
) start_timestamp
;
3198 i
->exit_timestamp
= (usec_t
) exit_timestamp
;
3199 i
->pid
= (pid_t
) pid
;
3203 r
= sd_bus_message_exit_container(m
);
3205 return bus_log_parse_error(r
);
3210 typedef struct UnitStatusInfo
{
3212 const char *load_state
;
3213 const char *active_state
;
3214 const char *sub_state
;
3215 const char *unit_file_state
;
3216 const char *unit_file_preset
;
3218 const char *description
;
3219 const char *following
;
3221 char **documentation
;
3223 const char *fragment_path
;
3224 const char *source_path
;
3225 const char *control_group
;
3227 char **dropin_paths
;
3229 const char *load_error
;
3232 usec_t inactive_exit_timestamp
;
3233 usec_t inactive_exit_timestamp_monotonic
;
3234 usec_t active_enter_timestamp
;
3235 usec_t active_exit_timestamp
;
3236 usec_t inactive_enter_timestamp
;
3238 bool need_daemon_reload
;
3243 const char *status_text
;
3244 const char *pid_file
;
3248 usec_t start_timestamp
;
3249 usec_t exit_timestamp
;
3251 int exit_code
, exit_status
;
3253 usec_t condition_timestamp
;
3254 bool condition_result
;
3255 bool failed_condition_trigger
;
3256 bool failed_condition_negate
;
3257 const char *failed_condition
;
3258 const char *failed_condition_parameter
;
3260 usec_t assert_timestamp
;
3262 bool failed_assert_trigger
;
3263 bool failed_assert_negate
;
3264 const char *failed_assert
;
3265 const char *failed_assert_parameter
;
3268 unsigned n_accepted
;
3269 unsigned n_connections
;
3272 /* Pairs of type, path */
3276 const char *sysfs_path
;
3278 /* Mount, Automount */
3285 uint64_t memory_current
;
3286 uint64_t memory_limit
;
3287 uint64_t cpu_usage_nsec
;
3289 LIST_HEAD(ExecStatusInfo
, exec
);
3292 static void print_status_info(
3297 const char *active_on
, *active_off
, *on
, *off
, *ss
;
3299 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], *s1
;
3300 char since2
[FORMAT_TIMESTAMP_MAX
], *s2
;
3306 /* This shows pretty information about a unit. See
3307 * print_property() for a low-level property printer */
3309 if (streq_ptr(i
->active_state
, "failed")) {
3310 active_on
= ansi_highlight_red();
3311 active_off
= ansi_highlight_off();
3312 } else if (streq_ptr(i
->active_state
, "active") || streq_ptr(i
->active_state
, "reloading")) {
3313 active_on
= ansi_highlight_green();
3314 active_off
= ansi_highlight_off();
3316 active_on
= active_off
= "";
3318 printf("%s%s%s %s", active_on
, draw_special_char(DRAW_BLACK_CIRCLE
), active_off
, strna(i
->id
));
3320 if (i
->description
&& !streq_ptr(i
->id
, i
->description
))
3321 printf(" - %s", i
->description
);
3326 printf(" Follow: unit currently follows state of %s\n", i
->following
);
3328 if (streq_ptr(i
->load_state
, "error")) {
3329 on
= ansi_highlight_red();
3330 off
= ansi_highlight_off();
3334 path
= i
->source_path
? i
->source_path
: i
->fragment_path
;
3337 printf(" Loaded: %s%s%s (Reason: %s)\n",
3338 on
, strna(i
->load_state
), off
, i
->load_error
);
3339 else if (path
&& !isempty(i
->unit_file_state
) && !isempty(i
->unit_file_preset
))
3340 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
3341 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
, i
->unit_file_preset
);
3342 else if (path
&& !isempty(i
->unit_file_state
))
3343 printf(" Loaded: %s%s%s (%s; %s)\n",
3344 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
);
3346 printf(" Loaded: %s%s%s (%s)\n",
3347 on
, strna(i
->load_state
), off
, path
);
3349 printf(" Loaded: %s%s%s\n",
3350 on
, strna(i
->load_state
), off
);
3352 if (!strv_isempty(i
->dropin_paths
)) {
3353 _cleanup_free_
char *dir
= NULL
;
3357 STRV_FOREACH(dropin
, i
->dropin_paths
) {
3358 if (! dir
|| last
) {
3359 printf(dir
? " " : " Drop-In: ");
3363 if (path_get_parent(*dropin
, &dir
) < 0) {
3368 printf("%s\n %s", dir
,
3369 draw_special_char(DRAW_TREE_RIGHT
));
3372 last
= ! (*(dropin
+ 1) && startswith(*(dropin
+ 1), dir
));
3374 printf("%s%s", basename(*dropin
), last
? "\n" : ", ");
3378 ss
= streq_ptr(i
->active_state
, i
->sub_state
) ? NULL
: i
->sub_state
;
3380 printf(" Active: %s%s (%s)%s",
3381 active_on
, strna(i
->active_state
), ss
, active_off
);
3383 printf(" Active: %s%s%s",
3384 active_on
, strna(i
->active_state
), active_off
);
3386 if (!isempty(i
->result
) && !streq(i
->result
, "success"))
3387 printf(" (Result: %s)", i
->result
);
3389 timestamp
= (streq_ptr(i
->active_state
, "active") ||
3390 streq_ptr(i
->active_state
, "reloading")) ? i
->active_enter_timestamp
:
3391 (streq_ptr(i
->active_state
, "inactive") ||
3392 streq_ptr(i
->active_state
, "failed")) ? i
->inactive_enter_timestamp
:
3393 streq_ptr(i
->active_state
, "activating") ? i
->inactive_exit_timestamp
:
3394 i
->active_exit_timestamp
;
3396 s1
= format_timestamp_relative(since1
, sizeof(since1
), timestamp
);
3397 s2
= format_timestamp(since2
, sizeof(since2
), timestamp
);
3400 printf(" since %s; %s\n", s2
, s1
);
3402 printf(" since %s\n", s2
);
3406 if (!i
->condition_result
&& i
->condition_timestamp
> 0) {
3407 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->condition_timestamp
);
3408 s2
= format_timestamp(since2
, sizeof(since2
), i
->condition_timestamp
);
3410 printf("Condition: start %scondition failed%s at %s%s%s\n",
3411 ansi_highlight_yellow(), ansi_highlight_off(),
3412 s2
, s1
? "; " : "", s1
? s1
: "");
3413 if (i
->failed_condition_trigger
)
3414 printf(" none of the trigger conditions were met\n");
3415 else if (i
->failed_condition
)
3416 printf(" %s=%s%s was not met\n",
3417 i
->failed_condition
,
3418 i
->failed_condition_negate
? "!" : "",
3419 i
->failed_condition_parameter
);
3422 if (!i
->assert_result
&& i
->assert_timestamp
> 0) {
3423 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->assert_timestamp
);
3424 s2
= format_timestamp(since2
, sizeof(since2
), i
->assert_timestamp
);
3426 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
3427 ansi_highlight_red(), ansi_highlight_off(),
3428 s2
, s1
? "; " : "", s1
? s1
: "");
3429 if (i
->failed_assert_trigger
)
3430 printf(" none of the trigger assertions were met\n");
3431 else if (i
->failed_assert
)
3432 printf(" %s=%s%s was not met\n",
3434 i
->failed_assert_negate
? "!" : "",
3435 i
->failed_assert_parameter
);
3439 printf(" Device: %s\n", i
->sysfs_path
);
3441 printf(" Where: %s\n", i
->where
);
3443 printf(" What: %s\n", i
->what
);
3445 STRV_FOREACH(t
, i
->documentation
)
3446 printf(" %*s %s\n", 9, t
== i
->documentation
? "Docs:" : "", *t
);
3448 STRV_FOREACH_PAIR(t
, t2
, i
->listen
)
3449 printf(" %*s %s (%s)\n", 9, t
== i
->listen
? "Listen:" : "", *t2
, *t
);
3452 printf(" Accepted: %u; Connected: %u\n", i
->n_accepted
, i
->n_connections
);
3454 LIST_FOREACH(exec
, p
, i
->exec
) {
3455 _cleanup_free_
char *argv
= NULL
;
3458 /* Only show exited processes here */
3462 argv
= strv_join(p
->argv
, " ");
3463 printf(" Process: "PID_FMT
" %s=%s ", p
->pid
, p
->name
, strna(argv
));
3465 good
= is_clean_exit_lsb(p
->code
, p
->status
, NULL
);
3467 on
= ansi_highlight_red();
3468 off
= ansi_highlight_off();
3472 printf("%s(code=%s, ", on
, sigchld_code_to_string(p
->code
));
3474 if (p
->code
== CLD_EXITED
) {
3477 printf("status=%i", p
->status
);
3479 c
= exit_status_to_string(p
->status
, EXIT_STATUS_SYSTEMD
);
3484 printf("signal=%s", signal_to_string(p
->status
));
3486 printf(")%s\n", off
);
3488 if (i
->main_pid
== p
->pid
&&
3489 i
->start_timestamp
== p
->start_timestamp
&&
3490 i
->exit_timestamp
== p
->start_timestamp
)
3491 /* Let's not show this twice */
3494 if (p
->pid
== i
->control_pid
)
3498 if (i
->main_pid
> 0 || i
->control_pid
> 0) {
3499 if (i
->main_pid
> 0) {
3500 printf(" Main PID: "PID_FMT
, i
->main_pid
);
3503 _cleanup_free_
char *comm
= NULL
;
3504 get_process_comm(i
->main_pid
, &comm
);
3506 printf(" (%s)", comm
);
3507 } else if (i
->exit_code
> 0) {
3508 printf(" (code=%s, ", sigchld_code_to_string(i
->exit_code
));
3510 if (i
->exit_code
== CLD_EXITED
) {
3513 printf("status=%i", i
->exit_status
);
3515 c
= exit_status_to_string(i
->exit_status
, EXIT_STATUS_SYSTEMD
);
3520 printf("signal=%s", signal_to_string(i
->exit_status
));
3524 if (i
->control_pid
> 0)
3528 if (i
->control_pid
> 0) {
3529 _cleanup_free_
char *c
= NULL
;
3531 printf(" %8s: "PID_FMT
, i
->main_pid
? "" : " Control", i
->control_pid
);
3533 get_process_comm(i
->control_pid
, &c
);
3542 printf(" Status: \"%s\"\n", i
->status_text
);
3543 if (i
->status_errno
> 0)
3544 printf(" Error: %i (%s)\n", i
->status_errno
, strerror(i
->status_errno
));
3546 if (i
->memory_current
!= (uint64_t) -1) {
3547 char buf
[FORMAT_BYTES_MAX
];
3549 printf(" Memory: %s", format_bytes(buf
, sizeof(buf
), i
->memory_current
));
3551 if (i
->memory_limit
!= (uint64_t) -1)
3552 printf(" (limit: %s)\n", format_bytes(buf
, sizeof(buf
), i
->memory_limit
));
3557 if (i
->cpu_usage_nsec
!= (uint64_t) -1) {
3558 char buf
[FORMAT_TIMESPAN_MAX
];
3559 printf(" CPU: %s\n", format_timespan(buf
, sizeof(buf
), i
->cpu_usage_nsec
/ NSEC_PER_USEC
, USEC_PER_MSEC
));
3562 if (i
->control_group
&&
3563 (i
->main_pid
> 0 || i
->control_pid
> 0 ||
3564 ((arg_transport
!= BUS_TRANSPORT_LOCAL
&& arg_transport
!= BUS_TRANSPORT_MACHINE
) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
) == 0))) {
3567 printf(" CGroup: %s\n", i
->control_group
);
3569 if (arg_transport
== BUS_TRANSPORT_LOCAL
|| arg_transport
== BUS_TRANSPORT_MACHINE
) {
3572 static const char prefix
[] = " ";
3575 if (c
> sizeof(prefix
) - 1)
3576 c
-= sizeof(prefix
) - 1;
3580 if (i
->main_pid
> 0)
3581 extra
[k
++] = i
->main_pid
;
3583 if (i
->control_pid
> 0)
3584 extra
[k
++] = i
->control_pid
;
3586 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, prefix
, c
, false, extra
, k
, get_output_flags());
3590 if (i
->id
&& arg_transport
== BUS_TRANSPORT_LOCAL
)
3591 show_journal_by_unit(
3596 i
->inactive_exit_timestamp_monotonic
,
3599 get_output_flags() | OUTPUT_BEGIN_NEWLINE
,
3600 SD_JOURNAL_LOCAL_ONLY
,
3601 arg_scope
== UNIT_FILE_SYSTEM
,
3604 if (i
->need_daemon_reload
)
3605 warn_unit_file_changed(i
->id
);
3608 static void show_unit_help(UnitStatusInfo
*i
) {
3613 if (!i
->documentation
) {
3614 log_info("Documentation for %s not known.", i
->id
);
3618 STRV_FOREACH(p
, i
->documentation
)
3619 if (startswith(*p
, "man:"))
3620 show_man_page(*p
+ 4, false);
3622 log_info("Can't show: %s", *p
);
3625 static int status_property(const char *name
, sd_bus_message
*m
, UnitStatusInfo
*i
, const char *contents
) {
3632 switch (contents
[0]) {
3634 case SD_BUS_TYPE_STRING
: {
3637 r
= sd_bus_message_read(m
, "s", &s
);
3639 return bus_log_parse_error(r
);
3642 if (streq(name
, "Id"))
3644 else if (streq(name
, "LoadState"))
3646 else if (streq(name
, "ActiveState"))
3647 i
->active_state
= s
;
3648 else if (streq(name
, "SubState"))
3650 else if (streq(name
, "Description"))
3652 else if (streq(name
, "FragmentPath"))
3653 i
->fragment_path
= s
;
3654 else if (streq(name
, "SourcePath"))
3657 else if (streq(name
, "DefaultControlGroup")) {
3659 e
= startswith(s
, SYSTEMD_CGROUP_CONTROLLER
":");
3661 i
->control_group
= e
;
3664 else if (streq(name
, "ControlGroup"))
3665 i
->control_group
= s
;
3666 else if (streq(name
, "StatusText"))
3668 else if (streq(name
, "PIDFile"))
3670 else if (streq(name
, "SysFSPath"))
3672 else if (streq(name
, "Where"))
3674 else if (streq(name
, "What"))
3676 else if (streq(name
, "Following"))
3678 else if (streq(name
, "UnitFileState"))
3679 i
->unit_file_state
= s
;
3680 else if (streq(name
, "UnitFilePreset"))
3681 i
->unit_file_preset
= s
;
3682 else if (streq(name
, "Result"))
3689 case SD_BUS_TYPE_BOOLEAN
: {
3692 r
= sd_bus_message_read(m
, "b", &b
);
3694 return bus_log_parse_error(r
);
3696 if (streq(name
, "Accept"))
3698 else if (streq(name
, "NeedDaemonReload"))
3699 i
->need_daemon_reload
= b
;
3700 else if (streq(name
, "ConditionResult"))
3701 i
->condition_result
= b
;
3702 else if (streq(name
, "AssertResult"))
3703 i
->assert_result
= b
;
3708 case SD_BUS_TYPE_UINT32
: {
3711 r
= sd_bus_message_read(m
, "u", &u
);
3713 return bus_log_parse_error(r
);
3715 if (streq(name
, "MainPID")) {
3717 i
->main_pid
= (pid_t
) u
;
3720 } else if (streq(name
, "ControlPID"))
3721 i
->control_pid
= (pid_t
) u
;
3722 else if (streq(name
, "ExecMainPID")) {
3724 i
->main_pid
= (pid_t
) u
;
3725 } else if (streq(name
, "NAccepted"))
3727 else if (streq(name
, "NConnections"))
3728 i
->n_connections
= u
;
3733 case SD_BUS_TYPE_INT32
: {
3736 r
= sd_bus_message_read(m
, "i", &j
);
3738 return bus_log_parse_error(r
);
3740 if (streq(name
, "ExecMainCode"))
3741 i
->exit_code
= (int) j
;
3742 else if (streq(name
, "ExecMainStatus"))
3743 i
->exit_status
= (int) j
;
3744 else if (streq(name
, "StatusErrno"))
3745 i
->status_errno
= (int) j
;
3750 case SD_BUS_TYPE_UINT64
: {
3753 r
= sd_bus_message_read(m
, "t", &u
);
3755 return bus_log_parse_error(r
);
3757 if (streq(name
, "ExecMainStartTimestamp"))
3758 i
->start_timestamp
= (usec_t
) u
;
3759 else if (streq(name
, "ExecMainExitTimestamp"))
3760 i
->exit_timestamp
= (usec_t
) u
;
3761 else if (streq(name
, "ActiveEnterTimestamp"))
3762 i
->active_enter_timestamp
= (usec_t
) u
;
3763 else if (streq(name
, "InactiveEnterTimestamp"))
3764 i
->inactive_enter_timestamp
= (usec_t
) u
;
3765 else if (streq(name
, "InactiveExitTimestamp"))
3766 i
->inactive_exit_timestamp
= (usec_t
) u
;
3767 else if (streq(name
, "InactiveExitTimestampMonotonic"))
3768 i
->inactive_exit_timestamp_monotonic
= (usec_t
) u
;
3769 else if (streq(name
, "ActiveExitTimestamp"))
3770 i
->active_exit_timestamp
= (usec_t
) u
;
3771 else if (streq(name
, "ConditionTimestamp"))
3772 i
->condition_timestamp
= (usec_t
) u
;
3773 else if (streq(name
, "AssertTimestamp"))
3774 i
->assert_timestamp
= (usec_t
) u
;
3775 else if (streq(name
, "MemoryCurrent"))
3776 i
->memory_current
= u
;
3777 else if (streq(name
, "MemoryLimit"))
3778 i
->memory_limit
= u
;
3779 else if (streq(name
, "CPUUsageNSec"))
3780 i
->cpu_usage_nsec
= u
;
3785 case SD_BUS_TYPE_ARRAY
:
3787 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
3788 _cleanup_free_ ExecStatusInfo
*info
= NULL
;
3790 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
3792 return bus_log_parse_error(r
);
3794 info
= new0(ExecStatusInfo
, 1);
3798 while ((r
= exec_status_info_deserialize(m
, info
)) > 0) {
3800 info
->name
= strdup(name
);
3804 LIST_PREPEND(exec
, i
->exec
, info
);
3806 info
= new0(ExecStatusInfo
, 1);
3812 return bus_log_parse_error(r
);
3814 r
= sd_bus_message_exit_container(m
);
3816 return bus_log_parse_error(r
);
3820 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
3821 const char *type
, *path
;
3823 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
3825 return bus_log_parse_error(r
);
3827 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0) {
3829 r
= strv_extend(&i
->listen
, type
);
3833 r
= strv_extend(&i
->listen
, path
);
3838 return bus_log_parse_error(r
);
3840 r
= sd_bus_message_exit_container(m
);
3842 return bus_log_parse_error(r
);
3846 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "DropInPaths")) {
3848 r
= sd_bus_message_read_strv(m
, &i
->dropin_paths
);
3850 return bus_log_parse_error(r
);
3852 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Documentation")) {
3854 r
= sd_bus_message_read_strv(m
, &i
->documentation
);
3856 return bus_log_parse_error(r
);
3858 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Conditions")) {
3859 const char *cond
, *param
;
3860 int trigger
, negate
;
3863 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
3865 return bus_log_parse_error(r
);
3867 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
3868 log_debug("%s %d %d %s %d", cond
, trigger
, negate
, param
, state
);
3869 if (state
< 0 && (!trigger
|| !i
->failed_condition
)) {
3870 i
->failed_condition
= cond
;
3871 i
->failed_condition_trigger
= trigger
;
3872 i
->failed_condition_negate
= negate
;
3873 i
->failed_condition_parameter
= param
;
3877 return bus_log_parse_error(r
);
3879 r
= sd_bus_message_exit_container(m
);
3881 return bus_log_parse_error(r
);
3883 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Asserts")) {
3884 const char *cond
, *param
;
3885 int trigger
, negate
;
3888 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
3890 return bus_log_parse_error(r
);
3892 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
3893 log_debug("%s %d %d %s %d", cond
, trigger
, negate
, param
, state
);
3894 if (state
< 0 && (!trigger
|| !i
->failed_assert
)) {
3895 i
->failed_assert
= cond
;
3896 i
->failed_assert_trigger
= trigger
;
3897 i
->failed_assert_negate
= negate
;
3898 i
->failed_assert_parameter
= param
;
3902 return bus_log_parse_error(r
);
3904 r
= sd_bus_message_exit_container(m
);
3906 return bus_log_parse_error(r
);
3913 case SD_BUS_TYPE_STRUCT_BEGIN
:
3915 if (streq(name
, "LoadError")) {
3916 const char *n
, *message
;
3918 r
= sd_bus_message_read(m
, "(ss)", &n
, &message
);
3920 return bus_log_parse_error(r
);
3922 if (!isempty(message
))
3923 i
->load_error
= message
;
3936 r
= sd_bus_message_skip(m
, contents
);
3938 return bus_log_parse_error(r
);
3943 static int print_property(const char *name
, sd_bus_message
*m
, const char *contents
) {
3949 /* This is a low-level property printer, see
3950 * print_status_info() for the nicer output */
3952 if (arg_properties
&& !strv_find(arg_properties
, name
)) {
3953 /* skip what we didn't read */
3954 r
= sd_bus_message_skip(m
, contents
);
3958 switch (contents
[0]) {
3960 case SD_BUS_TYPE_STRUCT_BEGIN
:
3962 if (contents
[1] == SD_BUS_TYPE_UINT32
&& streq(name
, "Job")) {
3965 r
= sd_bus_message_read(m
, "(uo)", &u
, NULL
);
3967 return bus_log_parse_error(r
);
3970 printf("%s=%"PRIu32
"\n", name
, u
);
3972 printf("%s=\n", name
);
3976 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Unit")) {
3979 r
= sd_bus_message_read(m
, "(so)", &s
, NULL
);
3981 return bus_log_parse_error(r
);
3983 if (arg_all
|| !isempty(s
))
3984 printf("%s=%s\n", name
, s
);
3988 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "LoadError")) {
3989 const char *a
= NULL
, *b
= NULL
;
3991 r
= sd_bus_message_read(m
, "(ss)", &a
, &b
);
3993 return bus_log_parse_error(r
);
3995 if (arg_all
|| !isempty(a
) || !isempty(b
))
3996 printf("%s=%s \"%s\"\n", name
, strempty(a
), strempty(b
));
3999 } else if (streq_ptr(name
, "SystemCallFilter")) {
4000 _cleanup_strv_free_
char **l
= NULL
;
4003 r
= sd_bus_message_enter_container(m
, 'r', "bas");
4005 return bus_log_parse_error(r
);
4007 r
= sd_bus_message_read(m
, "b", &whitelist
);
4009 return bus_log_parse_error(r
);
4011 r
= sd_bus_message_read_strv(m
, &l
);
4013 return bus_log_parse_error(r
);
4015 r
= sd_bus_message_exit_container(m
);
4017 return bus_log_parse_error(r
);
4019 if (arg_all
|| whitelist
|| !strv_isempty(l
)) {
4023 fputs(name
, stdout
);
4029 STRV_FOREACH(i
, l
) {
4037 fputc('\n', stdout
);
4045 case SD_BUS_TYPE_ARRAY
:
4047 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "EnvironmentFiles")) {
4051 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sb)");
4053 return bus_log_parse_error(r
);
4055 while ((r
= sd_bus_message_read(m
, "(sb)", &path
, &ignore
)) > 0)
4056 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path
, yes_no(ignore
));
4059 return bus_log_parse_error(r
);
4061 r
= sd_bus_message_exit_container(m
);
4063 return bus_log_parse_error(r
);
4067 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Paths")) {
4068 const char *type
, *path
;
4070 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4072 return bus_log_parse_error(r
);
4074 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4075 printf("%s=%s\n", type
, path
);
4077 return bus_log_parse_error(r
);
4079 r
= sd_bus_message_exit_container(m
);
4081 return bus_log_parse_error(r
);
4085 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
4086 const char *type
, *path
;
4088 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4090 return bus_log_parse_error(r
);
4092 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4093 printf("Listen%s=%s\n", type
, path
);
4095 return bus_log_parse_error(r
);
4097 r
= sd_bus_message_exit_container(m
);
4099 return bus_log_parse_error(r
);
4103 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Timers")) {
4105 uint64_t value
, next_elapse
;
4107 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(stt)");
4109 return bus_log_parse_error(r
);
4111 while ((r
= sd_bus_message_read(m
, "(stt)", &base
, &value
, &next_elapse
)) > 0) {
4112 char timespan1
[FORMAT_TIMESPAN_MAX
], timespan2
[FORMAT_TIMESPAN_MAX
];
4114 printf("%s={ value=%s ; next_elapse=%s }\n",
4116 format_timespan(timespan1
, sizeof(timespan1
), value
, 0),
4117 format_timespan(timespan2
, sizeof(timespan2
), next_elapse
, 0));
4120 return bus_log_parse_error(r
);
4122 r
= sd_bus_message_exit_container(m
);
4124 return bus_log_parse_error(r
);
4128 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
4129 ExecStatusInfo info
= {};
4131 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4133 return bus_log_parse_error(r
);
4135 while ((r
= exec_status_info_deserialize(m
, &info
)) > 0) {
4136 char timestamp1
[FORMAT_TIMESTAMP_MAX
], timestamp2
[FORMAT_TIMESTAMP_MAX
];
4137 _cleanup_free_
char *tt
;
4139 tt
= strv_join(info
.argv
, " ");
4141 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT
" ; code=%s ; status=%i%s%s }\n",
4145 yes_no(info
.ignore
),
4146 strna(format_timestamp(timestamp1
, sizeof(timestamp1
), info
.start_timestamp
)),
4147 strna(format_timestamp(timestamp2
, sizeof(timestamp2
), info
.exit_timestamp
)),
4149 sigchld_code_to_string(info
.code
),
4151 info
.code
== CLD_EXITED
? "" : "/",
4152 strempty(info
.code
== CLD_EXITED
? NULL
: signal_to_string(info
.status
)));
4155 strv_free(info
.argv
);
4159 r
= sd_bus_message_exit_container(m
);
4161 return bus_log_parse_error(r
);
4165 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "DeviceAllow")) {
4166 const char *path
, *rwm
;
4168 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4170 return bus_log_parse_error(r
);
4172 while ((r
= sd_bus_message_read(m
, "(ss)", &path
, &rwm
)) > 0)
4173 printf("%s=%s %s\n", name
, strna(path
), strna(rwm
));
4175 return bus_log_parse_error(r
);
4177 r
= sd_bus_message_exit_container(m
);
4179 return bus_log_parse_error(r
);
4183 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "BlockIODeviceWeight")) {
4187 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4189 return bus_log_parse_error(r
);
4191 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &weight
)) > 0)
4192 printf("%s=%s %" PRIu64
"\n", name
, strna(path
), weight
);
4194 return bus_log_parse_error(r
);
4196 r
= sd_bus_message_exit_container(m
);
4198 return bus_log_parse_error(r
);
4202 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& (streq(name
, "BlockIOReadBandwidth") || streq(name
, "BlockIOWriteBandwidth"))) {
4206 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4208 return bus_log_parse_error(r
);
4210 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &bandwidth
)) > 0)
4211 printf("%s=%s %" PRIu64
"\n", name
, strna(path
), bandwidth
);
4213 return bus_log_parse_error(r
);
4215 r
= sd_bus_message_exit_container(m
);
4217 return bus_log_parse_error(r
);
4225 r
= bus_print_property(name
, m
, arg_all
);
4227 return bus_log_parse_error(r
);
4230 r
= sd_bus_message_skip(m
, contents
);
4232 return bus_log_parse_error(r
);
4235 printf("%s=[unprintable]\n", name
);
4241 static int show_one(
4245 bool show_properties
,
4249 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4250 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4251 UnitStatusInfo info
= {
4252 .memory_current
= (uint64_t) -1,
4253 .memory_limit
= (uint64_t) -1,
4254 .cpu_usage_nsec
= (uint64_t) -1,
4262 log_debug("Showing one %s", path
);
4264 r
= sd_bus_call_method(
4266 "org.freedesktop.systemd1",
4268 "org.freedesktop.DBus.Properties",
4274 return log_error_errno(r
, "Failed to get properties: %s", bus_error_message(&error
, r
));
4276 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
4278 return bus_log_parse_error(r
);
4285 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
4286 const char *name
, *contents
;
4288 r
= sd_bus_message_read(reply
, "s", &name
);
4290 return bus_log_parse_error(r
);
4292 r
= sd_bus_message_peek_type(reply
, NULL
, &contents
);
4294 return bus_log_parse_error(r
);
4296 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, contents
);
4298 return bus_log_parse_error(r
);
4300 if (show_properties
)
4301 r
= print_property(name
, reply
, contents
);
4303 r
= status_property(name
, reply
, &info
, contents
);
4307 r
= sd_bus_message_exit_container(reply
);
4309 return bus_log_parse_error(r
);
4311 r
= sd_bus_message_exit_container(reply
);
4313 return bus_log_parse_error(r
);
4316 return bus_log_parse_error(r
);
4318 r
= sd_bus_message_exit_container(reply
);
4320 return bus_log_parse_error(r
);
4324 if (!show_properties
) {
4325 if (streq(verb
, "help"))
4326 show_unit_help(&info
);
4328 print_status_info(&info
, ellipsized
);
4331 strv_free(info
.documentation
);
4332 strv_free(info
.dropin_paths
);
4333 strv_free(info
.listen
);
4335 if (!streq_ptr(info
.active_state
, "active") &&
4336 !streq_ptr(info
.active_state
, "reloading") &&
4337 streq(verb
, "status")) {
4338 /* According to LSB: "program not running" */
4339 /* 0: program is running or service is OK
4340 * 1: program is dead and /run PID file exists
4341 * 2: program is dead and /run/lock lock file exists
4342 * 3: program is not running
4343 * 4: program or service status is unknown
4345 if (info
.pid_file
&& access(info
.pid_file
, F_OK
) == 0)
4351 while ((p
= info
.exec
)) {
4352 LIST_REMOVE(exec
, info
.exec
, p
);
4353 exec_status_info_free(p
);
4359 static int get_unit_dbus_path_by_pid(
4364 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4365 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4369 r
= sd_bus_call_method(
4371 "org.freedesktop.systemd1",
4372 "/org/freedesktop/systemd1",
4373 "org.freedesktop.systemd1.Manager",
4379 log_error("Failed to get unit for PID %"PRIu32
": %s", pid
, bus_error_message(&error
, r
));
4383 r
= sd_bus_message_read(reply
, "o", &u
);
4385 return bus_log_parse_error(r
);
4395 static int show_all(
4398 bool show_properties
,
4402 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4403 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
4408 r
= get_unit_list(bus
, NULL
, NULL
, &unit_infos
, 0, &reply
);
4412 pager_open_if_enabled();
4416 qsort_safe(unit_infos
, c
, sizeof(UnitInfo
), compare_unit_info
);
4418 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
4419 _cleanup_free_
char *p
= NULL
;
4421 p
= unit_dbus_path_from_name(u
->id
);
4425 r
= show_one(verb
, bus
, p
, show_properties
, new_line
, ellipsized
);
4428 else if (r
> 0 && ret
== 0)
4435 static int show_system_status(sd_bus
*bus
) {
4436 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], since2
[FORMAT_TIMESTAMP_MAX
];
4437 _cleanup_free_
char *hn
= NULL
;
4438 _cleanup_(machine_info_clear
) struct machine_info mi
= {};
4439 const char *on
, *off
;
4442 hn
= gethostname_malloc();
4446 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, &mi
);
4448 return log_error_errno(r
, "Failed to read server status: %m");
4450 if (streq_ptr(mi
.state
, "degraded")) {
4451 on
= ansi_highlight_red();
4452 off
= ansi_highlight_off();
4453 } else if (!streq_ptr(mi
.state
, "running")) {
4454 on
= ansi_highlight_yellow();
4455 off
= ansi_highlight_off();
4459 printf("%s%s%s %s\n", on
, draw_special_char(DRAW_BLACK_CIRCLE
), off
, arg_host
? arg_host
: hn
);
4461 printf(" State: %s%s%s\n",
4462 on
, strna(mi
.state
), off
);
4464 printf(" Jobs: %u queued\n", mi
.n_jobs
);
4465 printf(" Failed: %u units\n", mi
.n_failed_units
);
4467 printf(" Since: %s; %s\n",
4468 format_timestamp(since2
, sizeof(since2
), mi
.timestamp
),
4469 format_timestamp_relative(since1
, sizeof(since1
), mi
.timestamp
));
4471 printf(" CGroup: %s\n", mi
.control_group
?: "/");
4472 if (arg_transport
== BUS_TRANSPORT_LOCAL
|| arg_transport
== BUS_TRANSPORT_MACHINE
) {
4473 static const char prefix
[] = " ";
4477 if (c
> sizeof(prefix
) - 1)
4478 c
-= sizeof(prefix
) - 1;
4482 show_cgroup(SYSTEMD_CGROUP_CONTROLLER
, strempty(mi
.control_group
), prefix
, c
, false, get_output_flags());
4488 static int show(sd_bus
*bus
, char **args
) {
4489 bool show_properties
, show_status
, new_line
= false;
4490 bool ellipsized
= false;
4496 show_properties
= streq(args
[0], "show");
4497 show_status
= streq(args
[0], "status");
4499 if (show_properties
)
4500 pager_open_if_enabled();
4503 /* Increase max number of open files to 16K if we can, we
4504 * might needs this when browsing journal files, which might
4505 * be split up into many files. */
4506 setrlimit_closest(RLIMIT_NOFILE
, &RLIMIT_MAKE_CONST(16384));
4508 /* If no argument is specified inspect the manager itself */
4510 if (show_properties
&& strv_length(args
) <= 1)
4511 return show_one(args
[0], bus
, "/org/freedesktop/systemd1", show_properties
, &new_line
, &ellipsized
);
4513 if (show_status
&& strv_length(args
) <= 1) {
4515 pager_open_if_enabled();
4516 show_system_status(bus
);
4520 ret
= show_all(args
[0], bus
, false, &new_line
, &ellipsized
);
4522 _cleanup_free_
char **patterns
= NULL
;
4525 STRV_FOREACH(name
, args
+ 1) {
4526 _cleanup_free_
char *unit
= NULL
;
4529 if (safe_atou32(*name
, &id
) < 0) {
4530 if (strv_push(&patterns
, *name
) < 0)
4534 } else if (show_properties
) {
4535 /* Interpret as job id */
4536 if (asprintf(&unit
, "/org/freedesktop/systemd1/job/%u", id
) < 0)
4540 /* Interpret as PID */
4541 r
= get_unit_dbus_path_by_pid(bus
, id
, &unit
);
4548 r
= show_one(args
[0], bus
, unit
, show_properties
,
4549 &new_line
, &ellipsized
);
4552 else if (r
> 0 && ret
== 0)
4556 if (!strv_isempty(patterns
)) {
4557 _cleanup_strv_free_
char **names
= NULL
;
4559 r
= expand_names(bus
, patterns
, NULL
, &names
);
4561 log_error_errno(r
, "Failed to expand names: %m");
4563 STRV_FOREACH(name
, names
) {
4564 _cleanup_free_
char *unit
;
4566 unit
= unit_dbus_path_from_name(*name
);
4570 r
= show_one(args
[0], bus
, unit
, show_properties
,
4571 &new_line
, &ellipsized
);
4574 else if (r
> 0 && ret
== 0)
4580 if (ellipsized
&& !arg_quiet
)
4581 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4586 static int init_home_and_lookup_paths(char **user_home
, char **user_runtime
, LookupPaths
*lp
) {
4590 assert(user_runtime
);
4593 if (arg_scope
== UNIT_FILE_USER
) {
4594 r
= user_config_home(user_home
);
4596 return log_error_errno(r
, "Failed to query XDG_CONFIG_HOME: %m");
4598 return log_error_errno(ENOTDIR
, "Cannot find units: $XDG_CONFIG_HOME and $HOME are not set.");
4600 r
= user_runtime_dir(user_runtime
);
4602 return log_error_errno(r
, "Failed to query XDG_CONFIG_HOME: %m");
4604 return log_error_errno(ENOTDIR
, "Cannot find units: $XDG_RUNTIME_DIR is not set.");
4607 r
= lookup_paths_init_from_scope(lp
, arg_scope
, arg_root
);
4609 return log_error_errno(r
, "Failed to query unit lookup paths: %m");
4614 static int cat_file(const char *filename
, bool newline
) {
4615 _cleanup_close_
int fd
;
4617 fd
= open(filename
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
4621 printf("%s%s# %s%s\n",
4622 newline
? "\n" : "",
4623 ansi_highlight_blue(),
4625 ansi_highlight_off());
4628 return copy_bytes(fd
, STDOUT_FILENO
, (off_t
) -1, false);
4631 static int cat(sd_bus
*bus
, char **args
) {
4632 _cleanup_free_
char *user_home
= NULL
;
4633 _cleanup_free_
char *user_runtime
= NULL
;
4634 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
4635 _cleanup_strv_free_
char **names
= NULL
;
4637 bool first
= true, avoid_bus_cache
;
4642 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
4643 log_error("Cannot remotely cat units");
4647 r
= init_home_and_lookup_paths(&user_home
, &user_runtime
, &lp
);
4651 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
4653 return log_error_errno(r
, "Failed to expand names: %m");
4655 avoid_bus_cache
= !bus
|| avoid_bus();
4657 pager_open_if_enabled();
4659 STRV_FOREACH(name
, names
) {
4660 _cleanup_free_
char *fragment_path
= NULL
;
4661 _cleanup_strv_free_
char **dropin_paths
= NULL
;
4664 r
= unit_find_paths(bus
, *name
, avoid_bus_cache
, &lp
, &fragment_path
, &dropin_paths
);
4675 if (fragment_path
) {
4676 r
= cat_file(fragment_path
, false);
4678 return log_warning_errno(r
, "Failed to cat %s: %m", fragment_path
);
4681 STRV_FOREACH(path
, dropin_paths
) {
4682 r
= cat_file(*path
, path
== dropin_paths
);
4684 return log_warning_errno(r
, "Failed to cat %s: %m", *path
);
4691 static int set_property(sd_bus
*bus
, char **args
) {
4692 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
4693 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4694 _cleanup_free_
char *n
= NULL
;
4698 polkit_agent_open_if_enabled();
4700 r
= sd_bus_message_new_method_call(
4703 "org.freedesktop.systemd1",
4704 "/org/freedesktop/systemd1",
4705 "org.freedesktop.systemd1.Manager",
4706 "SetUnitProperties");
4708 return bus_log_create_error(r
);
4710 r
= unit_name_mangle(args
[1], UNIT_NAME_NOGLOB
, &n
);
4712 return log_error_errno(r
, "Failed to mangle unit name: %m");
4714 r
= sd_bus_message_append(m
, "sb", n
, arg_runtime
);
4716 return bus_log_create_error(r
);
4718 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, "(sv)");
4720 return bus_log_create_error(r
);
4722 STRV_FOREACH(i
, args
+ 2) {
4723 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_STRUCT
, "sv");
4725 return bus_log_create_error(r
);
4727 r
= bus_append_unit_property_assignment(m
, *i
);
4731 r
= sd_bus_message_close_container(m
);
4733 return bus_log_create_error(r
);
4736 r
= sd_bus_message_close_container(m
);
4738 return bus_log_create_error(r
);
4740 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
4742 log_error("Failed to set unit properties on %s: %s", n
, bus_error_message(&error
, r
));
4749 static int snapshot(sd_bus
*bus
, char **args
) {
4750 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4751 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4752 _cleanup_free_
char *n
= NULL
, *id
= NULL
;
4756 polkit_agent_open_if_enabled();
4758 if (strv_length(args
) > 1) {
4759 r
= unit_name_mangle_with_suffix(args
[1], UNIT_NAME_NOGLOB
, ".snapshot", &n
);
4761 return log_error_errno(r
, "Failed to generate unit name: %m");
4768 r
= sd_bus_call_method(
4770 "org.freedesktop.systemd1",
4771 "/org/freedesktop/systemd1",
4772 "org.freedesktop.systemd1.Manager",
4778 log_error("Failed to create snapshot: %s", bus_error_message(&error
, r
));
4782 r
= sd_bus_message_read(reply
, "o", &path
);
4784 return bus_log_parse_error(r
);
4786 r
= sd_bus_get_property_string(
4788 "org.freedesktop.systemd1",
4790 "org.freedesktop.systemd1.Unit",
4795 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error
, r
));
4805 static int delete_snapshot(sd_bus
*bus
, char **args
) {
4806 _cleanup_strv_free_
char **names
= NULL
;
4812 polkit_agent_open_if_enabled();
4814 r
= expand_names(bus
, args
+ 1, ".snapshot", &names
);
4816 log_error_errno(r
, "Failed to expand names: %m");
4818 STRV_FOREACH(name
, names
) {
4819 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4822 q
= sd_bus_call_method(
4824 "org.freedesktop.systemd1",
4825 "/org/freedesktop/systemd1",
4826 "org.freedesktop.systemd1.Manager",
4832 log_error("Failed to remove snapshot %s: %s", *name
, bus_error_message(&error
, q
));
4841 static int daemon_reload(sd_bus
*bus
, char **args
) {
4842 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4846 polkit_agent_open_if_enabled();
4848 if (arg_action
== ACTION_RELOAD
)
4850 else if (arg_action
== ACTION_REEXEC
)
4851 method
= "Reexecute";
4853 assert(arg_action
== ACTION_SYSTEMCTL
);
4856 streq(args
[0], "clear-jobs") ||
4857 streq(args
[0], "cancel") ? "ClearJobs" :
4858 streq(args
[0], "daemon-reexec") ? "Reexecute" :
4859 streq(args
[0], "reset-failed") ? "ResetFailed" :
4860 streq(args
[0], "halt") ? "Halt" :
4861 streq(args
[0], "poweroff") ? "PowerOff" :
4862 streq(args
[0], "reboot") ? "Reboot" :
4863 streq(args
[0], "kexec") ? "KExec" :
4864 streq(args
[0], "exit") ? "Exit" :
4865 /* "daemon-reload" */ "Reload";
4868 r
= sd_bus_call_method(
4870 "org.freedesktop.systemd1",
4871 "/org/freedesktop/systemd1",
4872 "org.freedesktop.systemd1.Manager",
4877 if (r
== -ENOENT
&& arg_action
!= ACTION_SYSTEMCTL
)
4878 /* There's always a fallback possible for
4879 * legacy actions. */
4881 else if ((r
== -ETIMEDOUT
|| r
== -ECONNRESET
) && streq(method
, "Reexecute"))
4882 /* On reexecution, we expect a disconnect, not a
4886 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
4888 return r
< 0 ? r
: 0;
4891 static int reset_failed(sd_bus
*bus
, char **args
) {
4892 _cleanup_strv_free_
char **names
= NULL
;
4896 if (strv_length(args
) <= 1)
4897 return daemon_reload(bus
, args
);
4899 polkit_agent_open_if_enabled();
4901 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
4903 log_error_errno(r
, "Failed to expand names: %m");
4905 STRV_FOREACH(name
, names
) {
4906 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4908 q
= sd_bus_call_method(
4910 "org.freedesktop.systemd1",
4911 "/org/freedesktop/systemd1",
4912 "org.freedesktop.systemd1.Manager",
4918 log_error("Failed to reset failed state of unit %s: %s", *name
, bus_error_message(&error
, q
));
4927 static int show_environment(sd_bus
*bus
, char **args
) {
4928 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4929 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4933 pager_open_if_enabled();
4935 r
= sd_bus_get_property(
4937 "org.freedesktop.systemd1",
4938 "/org/freedesktop/systemd1",
4939 "org.freedesktop.systemd1.Manager",
4945 log_error("Failed to get environment: %s", bus_error_message(&error
, r
));
4949 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
4951 return bus_log_parse_error(r
);
4953 while ((r
= sd_bus_message_read_basic(reply
, SD_BUS_TYPE_STRING
, &text
)) > 0)
4956 return bus_log_parse_error(r
);
4958 r
= sd_bus_message_exit_container(reply
);
4960 return bus_log_parse_error(r
);
4965 static int switch_root(sd_bus
*bus
, char **args
) {
4966 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4967 _cleanup_free_
char *cmdline_init
= NULL
;
4968 const char *root
, *init
;
4972 l
= strv_length(args
);
4973 if (l
< 2 || l
> 3) {
4974 log_error("Wrong number of arguments.");
4983 r
= parse_env_file("/proc/cmdline", WHITESPACE
,
4984 "init", &cmdline_init
,
4987 log_debug_errno(r
, "Failed to parse /proc/cmdline: %m");
4989 init
= cmdline_init
;
4996 const char *root_systemd_path
= NULL
, *root_init_path
= NULL
;
4998 root_systemd_path
= strjoina(root
, "/" SYSTEMD_BINARY_PATH
);
4999 root_init_path
= strjoina(root
, "/", init
);
5001 /* If the passed init is actually the same as the
5002 * systemd binary, then let's suppress it. */
5003 if (files_same(root_init_path
, root_systemd_path
) > 0)
5007 log_debug("Switching root - root: %s; init: %s", root
, strna(init
));
5009 r
= sd_bus_call_method(
5011 "org.freedesktop.systemd1",
5012 "/org/freedesktop/systemd1",
5013 "org.freedesktop.systemd1.Manager",
5019 log_error("Failed to switch root: %s", bus_error_message(&error
, r
));
5026 static int set_environment(sd_bus
*bus
, char **args
) {
5027 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5028 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
5035 polkit_agent_open_if_enabled();
5037 method
= streq(args
[0], "set-environment")
5039 : "UnsetEnvironment";
5041 r
= sd_bus_message_new_method_call(
5044 "org.freedesktop.systemd1",
5045 "/org/freedesktop/systemd1",
5046 "org.freedesktop.systemd1.Manager",
5049 return bus_log_create_error(r
);
5051 r
= sd_bus_message_append_strv(m
, args
+ 1);
5053 return bus_log_create_error(r
);
5055 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5057 log_error("Failed to set environment: %s", bus_error_message(&error
, r
));
5064 static int import_environment(sd_bus
*bus
, char **args
) {
5065 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5066 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
5072 polkit_agent_open_if_enabled();
5074 r
= sd_bus_message_new_method_call(
5077 "org.freedesktop.systemd1",
5078 "/org/freedesktop/systemd1",
5079 "org.freedesktop.systemd1.Manager",
5082 return bus_log_create_error(r
);
5084 if (strv_isempty(args
+ 1))
5085 r
= sd_bus_message_append_strv(m
, environ
);
5089 r
= sd_bus_message_open_container(m
, 'a', "s");
5091 return bus_log_create_error(r
);
5093 STRV_FOREACH(a
, args
+ 1) {
5095 if (!env_name_is_valid(*a
)) {
5096 log_error("Not a valid environment variable name: %s", *a
);
5100 STRV_FOREACH(b
, environ
) {
5103 eq
= startswith(*b
, *a
);
5104 if (eq
&& *eq
== '=') {
5106 r
= sd_bus_message_append(m
, "s", *b
);
5108 return bus_log_create_error(r
);
5115 r
= sd_bus_message_close_container(m
);
5118 return bus_log_create_error(r
);
5120 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5122 log_error("Failed to import environment: %s", bus_error_message(&error
, r
));
5129 static int enable_sysv_units(const char *verb
, char **args
) {
5132 #if defined(HAVE_SYSV_COMPAT)
5134 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
5136 if (arg_scope
!= UNIT_FILE_SYSTEM
)
5139 if (!streq(verb
, "enable") &&
5140 !streq(verb
, "disable") &&
5141 !streq(verb
, "is-enabled"))
5144 /* Processes all SysV units, and reshuffles the array so that
5145 * afterwards only the native units remain */
5147 r
= lookup_paths_init(&paths
, MANAGER_SYSTEM
, false, arg_root
, NULL
, NULL
, NULL
);
5154 _cleanup_free_
char *p
= NULL
, *q
= NULL
, *l
= NULL
;
5155 bool found_native
= false, found_sysv
;
5157 const char *argv
[6] = { ROOTLIBEXECDIR
"/systemd-sysv-install", NULL
, NULL
, NULL
, NULL
};
5165 if (!endswith(name
, ".service"))
5168 if (path_is_absolute(name
))
5171 STRV_FOREACH(k
, paths
.unit_path
) {
5172 _cleanup_free_
char *path
= NULL
;
5174 path
= path_join(arg_root
, *k
, name
);
5178 found_native
= access(path
, F_OK
) >= 0;
5183 /* If we have both a native unit and a SysV script,
5184 * enable/disable them both (below); for is-enabled, prefer the
5186 if (found_native
&& streq(verb
, "is-enabled"))
5189 p
= path_join(arg_root
, SYSTEM_SYSVINIT_PATH
, name
);
5193 p
[strlen(p
) - strlen(".service")] = 0;
5194 found_sysv
= access(p
, F_OK
) >= 0;
5199 log_info("Synchronizing state of %s with SysV init with %s...", name
, argv
[0]);
5201 log_info("%s is not a native service, redirecting to systemd-sysv-install", name
);
5203 if (!isempty(arg_root
))
5204 argv
[c
++] = q
= strappend("--root=", arg_root
);
5207 argv
[c
++] = basename(p
);
5210 l
= strv_join((char**)argv
, " ");
5214 log_info("Executing %s", l
);
5218 return log_error_errno(errno
, "Failed to fork: %m");
5219 else if (pid
== 0) {
5222 (void) reset_all_signal_handlers();
5223 (void) reset_signal_mask();
5225 execv(argv
[0], (char**) argv
);
5226 log_error("Failed to execute %s: %m", argv
[0]);
5227 _exit(EXIT_FAILURE
);
5230 j
= wait_for_terminate(pid
, &status
);
5232 log_error_errno(r
, "Failed to wait for child: %m");
5236 if (status
.si_code
== CLD_EXITED
) {
5237 if (streq(verb
, "is-enabled")) {
5238 if (status
.si_status
== 0) {
5247 } else if (status
.si_status
!= 0)
5255 /* Remove this entry, so that we don't try enabling it as native unit */
5258 assert(args
[f
] == name
);
5259 strv_remove(args
, name
);
5266 static int mangle_names(char **original_names
, char ***mangled_names
) {
5267 char **i
, **l
, **name
;
5270 l
= i
= new(char*, strv_length(original_names
) + 1);
5274 STRV_FOREACH(name
, original_names
) {
5276 /* When enabling units qualified path names are OK,
5277 * too, hence allow them explicitly. */
5279 if (is_path(*name
)) {
5286 r
= unit_name_mangle(*name
, UNIT_NAME_NOGLOB
, i
);
5289 return log_error_errno(r
, "Failed to mangle unit name: %m");
5302 static int enable_unit(sd_bus
*bus
, char **args
) {
5303 _cleanup_strv_free_
char **names
= NULL
;
5304 const char *verb
= args
[0];
5305 UnitFileChange
*changes
= NULL
;
5306 unsigned n_changes
= 0;
5307 int carries_install_info
= -1;
5313 r
= mangle_names(args
+1, &names
);
5317 r
= enable_sysv_units(verb
, names
);
5321 /* If the operation was fully executed by the SysV compat,
5322 * let's finish early */
5323 if (strv_isempty(names
))
5326 if (!bus
|| avoid_bus()) {
5327 if (streq(verb
, "enable")) {
5328 r
= unit_file_enable(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5329 carries_install_info
= r
;
5330 } else if (streq(verb
, "disable"))
5331 r
= unit_file_disable(arg_scope
, arg_runtime
, arg_root
, names
, &changes
, &n_changes
);
5332 else if (streq(verb
, "reenable")) {
5333 r
= unit_file_reenable(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5334 carries_install_info
= r
;
5335 } else if (streq(verb
, "link"))
5336 r
= unit_file_link(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5337 else if (streq(verb
, "preset")) {
5338 r
= unit_file_preset(arg_scope
, arg_runtime
, arg_root
, names
, arg_preset_mode
, arg_force
, &changes
, &n_changes
);
5339 carries_install_info
= r
;
5340 } else if (streq(verb
, "mask"))
5341 r
= unit_file_mask(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5342 else if (streq(verb
, "unmask"))
5343 r
= unit_file_unmask(arg_scope
, arg_runtime
, arg_root
, names
, &changes
, &n_changes
);
5345 assert_not_reached("Unknown verb");
5348 log_error_errno(r
, "Operation failed: %m");
5353 dump_unit_file_changes(changes
, n_changes
);
5357 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
, *m
= NULL
;
5358 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5359 int expect_carries_install_info
= false;
5360 bool send_force
= true, send_preset_mode
= false;
5363 polkit_agent_open_if_enabled();
5365 if (streq(verb
, "enable")) {
5366 method
= "EnableUnitFiles";
5367 expect_carries_install_info
= true;
5368 } else if (streq(verb
, "disable")) {
5369 method
= "DisableUnitFiles";
5371 } else if (streq(verb
, "reenable")) {
5372 method
= "ReenableUnitFiles";
5373 expect_carries_install_info
= true;
5374 } else if (streq(verb
, "link"))
5375 method
= "LinkUnitFiles";
5376 else if (streq(verb
, "preset")) {
5378 if (arg_preset_mode
!= UNIT_FILE_PRESET_FULL
) {
5379 method
= "PresetUnitFilesWithMode";
5380 send_preset_mode
= true;
5382 method
= "PresetUnitFiles";
5384 expect_carries_install_info
= true;
5385 } else if (streq(verb
, "mask"))
5386 method
= "MaskUnitFiles";
5387 else if (streq(verb
, "unmask")) {
5388 method
= "UnmaskUnitFiles";
5391 assert_not_reached("Unknown verb");
5393 r
= sd_bus_message_new_method_call(
5396 "org.freedesktop.systemd1",
5397 "/org/freedesktop/systemd1",
5398 "org.freedesktop.systemd1.Manager",
5401 return bus_log_create_error(r
);
5403 r
= sd_bus_message_append_strv(m
, names
);
5405 return bus_log_create_error(r
);
5407 if (send_preset_mode
) {
5408 r
= sd_bus_message_append(m
, "s", unit_file_preset_mode_to_string(arg_preset_mode
));
5410 return bus_log_create_error(r
);
5413 r
= sd_bus_message_append(m
, "b", arg_runtime
);
5415 return bus_log_create_error(r
);
5418 r
= sd_bus_message_append(m
, "b", arg_force
);
5420 return bus_log_create_error(r
);
5423 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
5425 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
5429 if (expect_carries_install_info
) {
5430 r
= sd_bus_message_read(reply
, "b", &carries_install_info
);
5432 return bus_log_parse_error(r
);
5435 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
5439 /* Try to reload if enabled */
5441 r
= daemon_reload(bus
, args
);
5446 if (carries_install_info
== 0)
5447 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5448 "using systemctl.\n"
5449 "Possible reasons for having this kind of units are:\n"
5450 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5451 " .wants/ or .requires/ directory.\n"
5452 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5453 " a requirement dependency on it.\n"
5454 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5455 " D-Bus, udev, scripted systemctl call, ...).\n");
5457 if (arg_now
&& n_changes
> 0 && STR_IN_SET(args
[0], "enable", "disable", "mask")) {
5458 char *new_args
[n_changes
+ 2];
5461 new_args
[0] = streq(args
[0], "enable") ? (char *)"start" : (char *)"stop";
5462 for (i
= 0; i
< n_changes
; i
++)
5463 new_args
[i
+ 1] = basename(changes
[i
].path
);
5464 new_args
[i
+ 1] = NULL
;
5466 r
= start_unit(bus
, new_args
);
5470 unit_file_changes_free(changes
, n_changes
);
5475 static int add_dependency(sd_bus
*bus
, char **args
) {
5476 _cleanup_strv_free_
char **names
= NULL
;
5477 _cleanup_free_
char *target
= NULL
;
5478 const char *verb
= args
[0];
5485 r
= unit_name_mangle_with_suffix(args
[1], UNIT_NAME_NOGLOB
, ".target", &target
);
5487 return log_error_errno(r
, "Failed to mangle unit name: %m");
5489 r
= mangle_names(args
+2, &names
);
5493 if (streq(verb
, "add-wants"))
5495 else if (streq(verb
, "add-requires"))
5496 dep
= UNIT_REQUIRES
;
5498 assert_not_reached("Unknown verb");
5500 if (!bus
|| avoid_bus()) {
5501 UnitFileChange
*changes
= NULL
;
5502 unsigned n_changes
= 0;
5504 r
= unit_file_add_dependency(arg_scope
, arg_runtime
, arg_root
, names
, target
, dep
, arg_force
, &changes
, &n_changes
);
5507 return log_error_errno(r
, "Can't add dependency: %m");
5510 dump_unit_file_changes(changes
, n_changes
);
5512 unit_file_changes_free(changes
, n_changes
);
5515 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
, *m
= NULL
;
5516 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5518 polkit_agent_open_if_enabled();
5520 r
= sd_bus_message_new_method_call(
5523 "org.freedesktop.systemd1",
5524 "/org/freedesktop/systemd1",
5525 "org.freedesktop.systemd1.Manager",
5526 "AddDependencyUnitFiles");
5528 return bus_log_create_error(r
);
5530 r
= sd_bus_message_append_strv(m
, names
);
5532 return bus_log_create_error(r
);
5534 r
= sd_bus_message_append(m
, "ssbb", target
, unit_dependency_to_string(dep
), arg_runtime
, arg_force
);
5536 return bus_log_create_error(r
);
5538 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
5540 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
5544 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, NULL
, NULL
);
5549 r
= daemon_reload(bus
, args
);
5557 static int preset_all(sd_bus
*bus
, char **args
) {
5558 UnitFileChange
*changes
= NULL
;
5559 unsigned n_changes
= 0;
5562 if (!bus
|| avoid_bus()) {
5564 r
= unit_file_preset_all(arg_scope
, arg_runtime
, arg_root
, arg_preset_mode
, arg_force
, &changes
, &n_changes
);
5566 log_error_errno(r
, "Operation failed: %m");
5571 dump_unit_file_changes(changes
, n_changes
);
5576 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5577 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
5579 polkit_agent_open_if_enabled();
5581 r
= sd_bus_call_method(
5583 "org.freedesktop.systemd1",
5584 "/org/freedesktop/systemd1",
5585 "org.freedesktop.systemd1.Manager",
5586 "PresetAllUnitFiles",
5590 unit_file_preset_mode_to_string(arg_preset_mode
),
5594 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
5598 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, NULL
, NULL
);
5603 r
= daemon_reload(bus
, args
);
5609 unit_file_changes_free(changes
, n_changes
);
5614 static int unit_is_enabled(sd_bus
*bus
, char **args
) {
5616 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5617 _cleanup_strv_free_
char **names
= NULL
;
5622 r
= mangle_names(args
+1, &names
);
5626 r
= enable_sysv_units(args
[0], names
);
5632 if (!bus
|| avoid_bus()) {
5634 STRV_FOREACH(name
, names
) {
5635 UnitFileState state
;
5637 state
= unit_file_get_state(arg_scope
, arg_root
, *name
);
5639 return log_error_errno(state
, "Failed to get unit file state for %s: %m", *name
);
5641 if (state
== UNIT_FILE_ENABLED
||
5642 state
== UNIT_FILE_ENABLED_RUNTIME
||
5643 state
== UNIT_FILE_STATIC
||
5644 state
== UNIT_FILE_INDIRECT
)
5648 puts(unit_file_state_to_string(state
));
5652 STRV_FOREACH(name
, names
) {
5653 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
5656 r
= sd_bus_call_method(
5658 "org.freedesktop.systemd1",
5659 "/org/freedesktop/systemd1",
5660 "org.freedesktop.systemd1.Manager",
5666 log_error("Failed to get unit file state for %s: %s", *name
, bus_error_message(&error
, r
));
5670 r
= sd_bus_message_read(reply
, "s", &s
);
5672 return bus_log_parse_error(r
);
5674 if (STR_IN_SET(s
, "enabled", "enabled-runtime", "static", "indirect"))
5685 static int is_system_running(sd_bus
*bus
, char **args
) {
5686 _cleanup_free_
char *state
= NULL
;
5689 r
= sd_bus_get_property_string(
5691 "org.freedesktop.systemd1",
5692 "/org/freedesktop/systemd1",
5693 "org.freedesktop.systemd1.Manager",
5706 return streq(state
, "running") ? EXIT_SUCCESS
: EXIT_FAILURE
;
5709 static int create_edit_temp_file(const char *new_path
, const char *original_path
, char **ret_tmp_fn
) {
5714 assert(original_path
);
5717 r
= tempfn_random(new_path
, NULL
, &t
);
5719 return log_error_errno(r
, "Failed to determine temporary filename for \"%s\": %m", new_path
);
5721 r
= mkdir_parents(new_path
, 0755);
5723 log_error_errno(r
, "Failed to create directories for \"%s\": %m", new_path
);
5728 r
= copy_file(original_path
, t
, 0, 0644, 0);
5732 log_error_errno(r
, "Failed to create temporary file \"%s\": %m", t
);
5737 log_error_errno(r
, "Failed to copy \"%s\" to \"%s\": %m", original_path
, t
);
5747 static int get_file_to_edit(const char *name
, const char *user_home
, const char *user_runtime
, char **ret_path
) {
5748 _cleanup_free_
char *path
= NULL
, *path2
= NULL
, *run
= NULL
;
5750 switch (arg_scope
) {
5751 case UNIT_FILE_SYSTEM
:
5752 path
= path_join(arg_root
, SYSTEM_CONFIG_UNIT_PATH
, name
);
5754 run
= path_join(arg_root
, "/run/systemd/system/", name
);
5756 case UNIT_FILE_GLOBAL
:
5757 path
= path_join(arg_root
, USER_CONFIG_UNIT_PATH
, name
);
5759 run
= path_join(arg_root
, "/run/systemd/user/", name
);
5761 case UNIT_FILE_USER
:
5763 assert(user_runtime
);
5765 path
= path_join(arg_root
, user_home
, name
);
5767 path2
= path_join(arg_root
, USER_CONFIG_UNIT_PATH
, name
);
5770 run
= path_join(arg_root
, user_runtime
, name
);
5774 assert_not_reached("Invalid scope");
5776 if (!path
|| (arg_runtime
&& !run
))
5780 if (access(path
, F_OK
) >= 0)
5781 return log_error_errno(EEXIST
, "Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.",
5783 if (path2
&& access(path2
, F_OK
) >= 0)
5784 return log_error_errno(EEXIST
, "Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.",
5796 static int unit_file_create_dropin(const char *unit_name
, const char *user_home
, const char *user_runtime
, char **ret_new_path
, char **ret_tmp_path
) {
5797 char *tmp_new_path
, *ending
;
5802 assert(ret_new_path
);
5803 assert(ret_tmp_path
);
5805 ending
= strjoina(unit_name
, ".d/override.conf");
5806 r
= get_file_to_edit(ending
, user_home
, user_runtime
, &tmp_new_path
);
5810 r
= create_edit_temp_file(tmp_new_path
, tmp_new_path
, &tmp_tmp_path
);
5816 *ret_new_path
= tmp_new_path
;
5817 *ret_tmp_path
= tmp_tmp_path
;
5822 static int unit_file_create_copy(
5823 const char *unit_name
,
5824 const char *fragment_path
,
5825 const char *user_home
,
5826 const char *user_runtime
,
5827 char **ret_new_path
,
5828 char **ret_tmp_path
) {
5834 assert(fragment_path
);
5836 assert(ret_new_path
);
5837 assert(ret_tmp_path
);
5839 r
= get_file_to_edit(unit_name
, user_home
, user_runtime
, &tmp_new_path
);
5843 if (!path_equal(fragment_path
, tmp_new_path
) && access(tmp_new_path
, F_OK
) == 0) {
5846 r
= ask_char(&response
, "yn", "\"%s\" already exists. Overwrite with \"%s\"? [(y)es, (n)o] ", tmp_new_path
, fragment_path
);
5851 if (response
!= 'y') {
5852 log_warning("%s ignored", unit_name
);
5858 r
= create_edit_temp_file(tmp_new_path
, fragment_path
, &tmp_tmp_path
);
5860 log_error_errno(r
, "Failed to create temporary file for \"%s\": %m", tmp_new_path
);
5865 *ret_new_path
= tmp_new_path
;
5866 *ret_tmp_path
= tmp_tmp_path
;
5871 static int run_editor(char **paths
) {
5879 log_error_errno(errno
, "Failed to fork: %m");
5885 char *editor
, **editor_args
= NULL
;
5886 char **tmp_path
, **original_path
, *p
;
5887 unsigned n_editor_args
= 0, i
= 1;
5890 (void) reset_all_signal_handlers();
5891 (void) reset_signal_mask();
5893 argc
= strv_length(paths
)/2 + 1;
5895 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
5896 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
5897 * we try to execute well known editors
5899 editor
= getenv("SYSTEMD_EDITOR");
5901 editor
= getenv("EDITOR");
5903 editor
= getenv("VISUAL");
5905 if (!isempty(editor
)) {
5906 editor_args
= strv_split(editor
, WHITESPACE
);
5909 _exit(EXIT_FAILURE
);
5911 n_editor_args
= strv_length(editor_args
);
5912 argc
+= n_editor_args
- 1;
5914 args
= newa(const char*, argc
+ 1);
5916 if (n_editor_args
> 0) {
5917 args
[0] = editor_args
[0];
5918 for (; i
< n_editor_args
; i
++)
5919 args
[i
] = editor_args
[i
];
5922 STRV_FOREACH_PAIR(original_path
, tmp_path
, paths
) {
5923 args
[i
] = *tmp_path
;
5928 if (n_editor_args
> 0)
5929 execvp(args
[0], (char* const*) args
);
5931 FOREACH_STRING(p
, "editor", "nano", "vim", "vi") {
5933 execvp(p
, (char* const*) args
);
5934 /* We do not fail if the editor doesn't exist
5935 * because we want to try each one of them before
5938 if (errno
!= ENOENT
) {
5939 log_error("Failed to execute %s: %m", editor
);
5940 _exit(EXIT_FAILURE
);
5944 log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR, $EDITOR or $VISUAL.");
5945 _exit(EXIT_FAILURE
);
5948 r
= wait_for_terminate_and_warn("editor", pid
, true);
5950 return log_error_errno(r
, "Failed to wait for child: %m");
5955 static int find_paths_to_edit(sd_bus
*bus
, char **names
, char ***paths
) {
5956 _cleanup_free_
char *user_home
= NULL
;
5957 _cleanup_free_
char *user_runtime
= NULL
;
5958 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
5959 bool avoid_bus_cache
;
5966 r
= init_home_and_lookup_paths(&user_home
, &user_runtime
, &lp
);
5970 avoid_bus_cache
= !bus
|| avoid_bus();
5972 STRV_FOREACH(name
, names
) {
5973 _cleanup_free_
char *path
= NULL
;
5974 char *new_path
, *tmp_path
;
5976 r
= unit_find_paths(bus
, *name
, avoid_bus_cache
, &lp
, &path
, NULL
);
5982 // FIXME: support units with path==NULL (no FragmentPath)
5983 log_error("No fragment exists for %s.", *name
);
5988 r
= unit_file_create_copy(*name
, path
, user_home
, user_runtime
, &new_path
, &tmp_path
);
5990 r
= unit_file_create_dropin(*name
, user_home
, user_runtime
, &new_path
, &tmp_path
);
5994 r
= strv_push_pair(paths
, new_path
, tmp_path
);
6002 static int edit(sd_bus
*bus
, char **args
) {
6003 _cleanup_strv_free_
char **names
= NULL
;
6004 _cleanup_strv_free_
char **paths
= NULL
;
6005 char **original
, **tmp
;
6011 log_error("Cannot edit units if not on a tty");
6015 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
6016 log_error("Cannot remotely edit units");
6020 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
6022 return log_error_errno(r
, "Failed to expand names: %m");
6024 r
= find_paths_to_edit(bus
, names
, &paths
);
6028 if (strv_isempty(paths
))
6031 r
= run_editor(paths
);
6035 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
6036 /* If the temporary file is empty we ignore it.
6037 * It's useful if the user wants to cancel its modification
6039 if (null_or_empty_path(*tmp
)) {
6040 log_warning("Editing \"%s\" canceled: temporary file is empty", *original
);
6043 r
= rename(*tmp
, *original
);
6045 r
= log_error_errno(errno
, "Failed to rename \"%s\" to \"%s\": %m", *tmp
, *original
);
6050 if (!arg_no_reload
&& bus
&& !avoid_bus())
6051 r
= daemon_reload(bus
, args
);
6054 STRV_FOREACH_PAIR(original
, tmp
, paths
)
6055 unlink_noerrno(*tmp
);
6060 static void systemctl_help(void) {
6062 pager_open_if_enabled();
6064 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
6065 "Query or send control commands to the systemd manager.\n\n"
6066 " -h --help Show this help\n"
6067 " --version Show package version\n"
6068 " --system Connect to system manager\n"
6069 " --user Connect to user service manager\n"
6070 " -H --host=[USER@]HOST\n"
6071 " Operate on remote host\n"
6072 " -M --machine=CONTAINER\n"
6073 " Operate on local container\n"
6074 " -t --type=TYPE List units of a particular type\n"
6075 " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n"
6076 " -p --property=NAME Show only properties by this name\n"
6077 " -a --all Show all loaded units/properties, including dead/empty\n"
6078 " ones. To list all units installed on the system, use\n"
6079 " the 'list-unit-files' command instead.\n"
6080 " -l --full Don't ellipsize unit names on output\n"
6081 " -r --recursive Show unit list of host and local containers\n"
6082 " --reverse Show reverse dependencies with 'list-dependencies'\n"
6083 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
6084 " queueing a new job\n"
6085 " --show-types When showing sockets, explicitly show their type\n"
6086 " -i --ignore-inhibitors\n"
6087 " When shutting down or sleeping, ignore inhibitors\n"
6088 " --kill-who=WHO Who to send signal to\n"
6089 " -s --signal=SIGNAL Which signal to send\n"
6090 " --now Start or stop unit in addition to enabling or disabling it\n"
6091 " -q --quiet Suppress output\n"
6092 " --no-block Do not wait until operation finished\n"
6093 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6094 " --no-reload Don't reload daemon after en-/dis-abling unit files\n"
6095 " --no-legend Do not print a legend (column headers and hints)\n"
6096 " --no-pager Do not pipe output into a pager\n"
6097 " --no-ask-password\n"
6098 " Do not ask for system passwords\n"
6099 " --global Enable/disable unit files globally\n"
6100 " --runtime Enable unit files only temporarily until next reboot\n"
6101 " -f --force When enabling unit files, override existing symlinks\n"
6102 " When shutting down, execute action immediately\n"
6103 " --preset-mode= Apply only enable, only disable, or all presets\n"
6104 " --root=PATH Enable unit files in the specified root directory\n"
6105 " -n --lines=INTEGER Number of journal entries to show\n"
6106 " -o --output=STRING Change journal output mode (short, short-iso,\n"
6107 " short-precise, short-monotonic, verbose,\n"
6108 " export, json, json-pretty, json-sse, cat)\n"
6109 " --firmware-setup Tell the firmware to show the setup menu on next boot\n"
6110 " --plain Print unit dependencies as a list instead of a tree\n\n"
6112 " list-units [PATTERN...] List loaded units\n"
6113 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
6114 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
6115 " start NAME... Start (activate) one or more units\n"
6116 " stop NAME... Stop (deactivate) one or more units\n"
6117 " reload NAME... Reload one or more units\n"
6118 " restart NAME... Start or restart one or more units\n"
6119 " try-restart NAME... Restart one or more units if active\n"
6120 " reload-or-restart NAME... Reload one or more units if possible,\n"
6121 " otherwise start or restart\n"
6122 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
6123 " otherwise restart if active\n"
6124 " isolate NAME Start one unit and stop all others\n"
6125 " kill NAME... Send signal to processes of a unit\n"
6126 " is-active PATTERN... Check whether units are active\n"
6127 " is-failed PATTERN... Check whether units are failed\n"
6128 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
6129 " show [PATTERN...|JOB...] Show properties of one or more\n"
6130 " units/jobs or the manager\n"
6131 " cat PATTERN... Show files and drop-ins of one or more units\n"
6132 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
6133 " help PATTERN...|PID... Show manual for one or more units\n"
6134 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
6136 " list-dependencies [NAME] Recursively show units which are required\n"
6137 " or wanted by this unit or by which this\n"
6138 " unit is required or wanted\n\n"
6139 "Unit File Commands:\n"
6140 " list-unit-files [PATTERN...] List installed unit files\n"
6141 " enable NAME... Enable one or more unit files\n"
6142 " disable NAME... Disable one or more unit files\n"
6143 " reenable NAME... Reenable one or more unit files\n"
6144 " preset NAME... Enable/disable one or more unit files\n"
6145 " based on preset configuration\n"
6146 " preset-all Enable/disable all unit files based on\n"
6147 " preset configuration\n"
6148 " is-enabled NAME... Check whether unit files are enabled\n"
6149 " mask NAME... Mask one or more units\n"
6150 " unmask NAME... Unmask one or more units\n"
6151 " link PATH... Link one or more units files into\n"
6152 " the search path\n"
6153 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
6154 " on specified one or more units\n"
6155 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
6156 " on specified one or more units\n"
6157 " edit NAME... Edit one or more unit files\n"
6158 " get-default Get the name of the default target\n"
6159 " set-default NAME Set the default target\n\n"
6160 "Machine Commands:\n"
6161 " list-machines [PATTERN...] List local containers and host\n\n"
6163 " list-jobs [PATTERN...] List jobs\n"
6164 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
6165 "Snapshot Commands:\n"
6166 " snapshot [NAME] Create a snapshot\n"
6167 " delete NAME... Remove one or more snapshots\n\n"
6168 "Environment Commands:\n"
6169 " show-environment Dump environment\n"
6170 " set-environment NAME=VALUE... Set one or more environment variables\n"
6171 " unset-environment NAME... Unset one or more environment variables\n"
6172 " import-environment [NAME...] Import all or some environment variables\n\n"
6173 "Manager Lifecycle Commands:\n"
6174 " daemon-reload Reload systemd manager configuration\n"
6175 " daemon-reexec Reexecute systemd manager\n\n"
6176 "System Commands:\n"
6177 " is-system-running Check whether system is fully running\n"
6178 " default Enter system default mode\n"
6179 " rescue Enter system rescue mode\n"
6180 " emergency Enter system emergency mode\n"
6181 " halt Shut down and halt the system\n"
6182 " poweroff Shut down and power-off the system\n"
6183 " reboot [ARG] Shut down and reboot the system\n"
6184 " kexec Shut down and reboot the system with kexec\n"
6185 " exit Request user instance exit\n"
6186 " switch-root ROOT [INIT] Change to a different root file system\n"
6187 " suspend Suspend the system\n"
6188 " hibernate Hibernate the system\n"
6189 " hybrid-sleep Hibernate and suspend the system\n",
6190 program_invocation_short_name
);
6193 static void halt_help(void) {
6194 printf("%s [OPTIONS...]%s\n\n"
6195 "%s the system.\n\n"
6196 " --help Show this help\n"
6197 " --halt Halt the machine\n"
6198 " -p --poweroff Switch off the machine\n"
6199 " --reboot Reboot the machine\n"
6200 " -f --force Force immediate halt/power-off/reboot\n"
6201 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
6202 " -d --no-wtmp Don't write wtmp record\n"
6203 " --no-wall Don't send wall message before halt/power-off/reboot\n",
6204 program_invocation_short_name
,
6205 arg_action
== ACTION_REBOOT
? " [ARG]" : "",
6206 arg_action
== ACTION_REBOOT
? "Reboot" :
6207 arg_action
== ACTION_POWEROFF
? "Power off" :
6211 static void shutdown_help(void) {
6212 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
6213 "Shut down the system.\n\n"
6214 " --help Show this help\n"
6215 " -H --halt Halt the machine\n"
6216 " -P --poweroff Power-off the machine\n"
6217 " -r --reboot Reboot the machine\n"
6218 " -h Equivalent to --poweroff, overridden by --halt\n"
6219 " -k Don't halt/power-off/reboot, just send warnings\n"
6220 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6221 " -c Cancel a pending shutdown\n",
6222 program_invocation_short_name
);
6225 static void telinit_help(void) {
6226 printf("%s [OPTIONS...] {COMMAND}\n\n"
6227 "Send control commands to the init daemon.\n\n"
6228 " --help Show this help\n"
6229 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
6231 " 0 Power-off the machine\n"
6232 " 6 Reboot the machine\n"
6233 " 2, 3, 4, 5 Start runlevelX.target unit\n"
6234 " 1, s, S Enter rescue mode\n"
6235 " q, Q Reload init daemon configuration\n"
6236 " u, U Reexecute init daemon\n",
6237 program_invocation_short_name
);
6240 static void runlevel_help(void) {
6241 printf("%s [OPTIONS...]\n\n"
6242 "Prints the previous and current runlevel of the init system.\n\n"
6243 " --help Show this help\n",
6244 program_invocation_short_name
);
6247 static void help_types(void) {
6252 puts("Available unit types:");
6253 for (i
= 0; i
< _UNIT_TYPE_MAX
; i
++) {
6254 t
= unit_type_to_string(i
);
6260 static int systemctl_parse_argv(int argc
, char *argv
[]) {
6269 ARG_IGNORE_DEPENDENCIES
,
6281 ARG_NO_ASK_PASSWORD
,
6294 static const struct option options
[] = {
6295 { "help", no_argument
, NULL
, 'h' },
6296 { "version", no_argument
, NULL
, ARG_VERSION
},
6297 { "type", required_argument
, NULL
, 't' },
6298 { "property", required_argument
, NULL
, 'p' },
6299 { "all", no_argument
, NULL
, 'a' },
6300 { "reverse", no_argument
, NULL
, ARG_REVERSE
},
6301 { "after", no_argument
, NULL
, ARG_AFTER
},
6302 { "before", no_argument
, NULL
, ARG_BEFORE
},
6303 { "show-types", no_argument
, NULL
, ARG_SHOW_TYPES
},
6304 { "failed", no_argument
, NULL
, ARG_FAILED
}, /* compatibility only */
6305 { "full", no_argument
, NULL
, 'l' },
6306 { "job-mode", required_argument
, NULL
, ARG_JOB_MODE
},
6307 { "fail", no_argument
, NULL
, ARG_FAIL
}, /* compatibility only */
6308 { "irreversible", no_argument
, NULL
, ARG_IRREVERSIBLE
}, /* compatibility only */
6309 { "ignore-dependencies", no_argument
, NULL
, ARG_IGNORE_DEPENDENCIES
}, /* compatibility only */
6310 { "ignore-inhibitors", no_argument
, NULL
, 'i' },
6311 { "user", no_argument
, NULL
, ARG_USER
},
6312 { "system", no_argument
, NULL
, ARG_SYSTEM
},
6313 { "global", no_argument
, NULL
, ARG_GLOBAL
},
6314 { "no-block", no_argument
, NULL
, ARG_NO_BLOCK
},
6315 { "no-legend", no_argument
, NULL
, ARG_NO_LEGEND
},
6316 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
6317 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6318 { "quiet", no_argument
, NULL
, 'q' },
6319 { "root", required_argument
, NULL
, ARG_ROOT
},
6320 { "force", no_argument
, NULL
, ARG_FORCE
},
6321 { "no-reload", no_argument
, NULL
, ARG_NO_RELOAD
},
6322 { "kill-who", required_argument
, NULL
, ARG_KILL_WHO
},
6323 { "signal", required_argument
, NULL
, 's' },
6324 { "no-ask-password", no_argument
, NULL
, ARG_NO_ASK_PASSWORD
},
6325 { "host", required_argument
, NULL
, 'H' },
6326 { "machine", required_argument
, NULL
, 'M' },
6327 { "runtime", no_argument
, NULL
, ARG_RUNTIME
},
6328 { "lines", required_argument
, NULL
, 'n' },
6329 { "output", required_argument
, NULL
, 'o' },
6330 { "plain", no_argument
, NULL
, ARG_PLAIN
},
6331 { "state", required_argument
, NULL
, ARG_STATE
},
6332 { "recursive", no_argument
, NULL
, 'r' },
6333 { "preset-mode", required_argument
, NULL
, ARG_PRESET_MODE
},
6334 { "firmware-setup", no_argument
, NULL
, ARG_FIRMWARE_SETUP
},
6335 { "now", no_argument
, NULL
, ARG_NOW
},
6336 { "message", required_argument
, NULL
, ARG_MESSAGE
},
6345 while ((c
= getopt_long(argc
, argv
, "ht:p:alqfs:H:M:n:o:ir", options
, NULL
)) >= 0)
6354 puts(PACKAGE_STRING
);
6355 puts(SYSTEMD_FEATURES
);
6359 const char *word
, *state
;
6362 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
6363 _cleanup_free_
char *type
;
6365 type
= strndup(word
, size
);
6369 if (streq(type
, "help")) {
6374 if (unit_type_from_string(type
) >= 0) {
6375 if (strv_push(&arg_types
, type
))
6381 /* It's much nicer to use --state= for
6382 * load states, but let's support this
6383 * in --types= too for compatibility
6384 * with old versions */
6385 if (unit_load_state_from_string(optarg
) >= 0) {
6386 if (strv_push(&arg_states
, type
) < 0)
6392 log_error("Unknown unit type or load state '%s'.", type
);
6393 log_info("Use -t help to see a list of allowed values.");
6401 /* Make sure that if the empty property list
6402 was specified, we won't show any properties. */
6403 if (isempty(optarg
) && !arg_properties
) {
6404 arg_properties
= new0(char*, 1);
6405 if (!arg_properties
)
6408 const char *word
, *state
;
6411 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
6414 prop
= strndup(word
, size
);
6418 if (strv_consume(&arg_properties
, prop
) < 0)
6423 /* If the user asked for a particular
6424 * property, show it to him, even if it is
6436 arg_dependency
= DEPENDENCY_REVERSE
;
6440 arg_dependency
= DEPENDENCY_AFTER
;
6444 arg_dependency
= DEPENDENCY_BEFORE
;
6447 case ARG_SHOW_TYPES
:
6448 arg_show_types
= true;
6452 arg_job_mode
= optarg
;
6456 arg_job_mode
= "fail";
6459 case ARG_IRREVERSIBLE
:
6460 arg_job_mode
= "replace-irreversibly";
6463 case ARG_IGNORE_DEPENDENCIES
:
6464 arg_job_mode
= "ignore-dependencies";
6468 arg_scope
= UNIT_FILE_USER
;
6472 arg_scope
= UNIT_FILE_SYSTEM
;
6476 arg_scope
= UNIT_FILE_GLOBAL
;
6480 arg_no_block
= true;
6484 arg_no_legend
= true;
6488 arg_no_pager
= true;
6504 if (strv_extend(&arg_states
, "failed") < 0)
6522 arg_no_reload
= true;
6526 arg_kill_who
= optarg
;
6530 if ((arg_signal
= signal_from_string_try_harder(optarg
)) < 0) {
6531 log_error("Failed to parse signal string %s.", optarg
);
6536 case ARG_NO_ASK_PASSWORD
:
6537 arg_ask_password
= false;
6541 arg_transport
= BUS_TRANSPORT_REMOTE
;
6546 arg_transport
= BUS_TRANSPORT_MACHINE
;
6555 if (safe_atou(optarg
, &arg_lines
) < 0) {
6556 log_error("Failed to parse lines '%s'", optarg
);
6562 arg_output
= output_mode_from_string(optarg
);
6563 if (arg_output
< 0) {
6564 log_error("Unknown output '%s'.", optarg
);
6570 arg_ignore_inhibitors
= true;
6577 case ARG_FIRMWARE_SETUP
:
6578 arg_firmware_setup
= true;
6582 const char *word
, *state
;
6585 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
6588 s
= strndup(word
, size
);
6592 if (strv_consume(&arg_states
, s
) < 0)
6599 if (geteuid() != 0) {
6600 log_error("--recursive requires root privileges.");
6604 arg_recursive
= true;
6607 case ARG_PRESET_MODE
:
6609 arg_preset_mode
= unit_file_preset_mode_from_string(optarg
);
6610 if (arg_preset_mode
< 0) {
6611 log_error("Failed to parse preset mode: %s.", optarg
);
6622 if (strv_extend(&arg_wall
, optarg
) < 0)
6630 assert_not_reached("Unhandled option");
6633 if (arg_transport
!= BUS_TRANSPORT_LOCAL
&& arg_scope
!= UNIT_FILE_SYSTEM
) {
6634 log_error("Cannot access user instance remotely.");
6641 static int halt_parse_argv(int argc
, char *argv
[]) {
6650 static const struct option options
[] = {
6651 { "help", no_argument
, NULL
, ARG_HELP
},
6652 { "halt", no_argument
, NULL
, ARG_HALT
},
6653 { "poweroff", no_argument
, NULL
, 'p' },
6654 { "reboot", no_argument
, NULL
, ARG_REBOOT
},
6655 { "force", no_argument
, NULL
, 'f' },
6656 { "wtmp-only", no_argument
, NULL
, 'w' },
6657 { "no-wtmp", no_argument
, NULL
, 'd' },
6658 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6667 if (utmp_get_runlevel(&runlevel
, NULL
) >= 0)
6668 if (runlevel
== '0' || runlevel
== '6')
6671 while ((c
= getopt_long(argc
, argv
, "pfwdnih", options
, NULL
)) >= 0)
6679 arg_action
= ACTION_HALT
;
6683 if (arg_action
!= ACTION_REBOOT
)
6684 arg_action
= ACTION_POWEROFF
;
6688 arg_action
= ACTION_REBOOT
;
6710 /* Compatibility nops */
6717 assert_not_reached("Unhandled option");
6720 if (arg_action
== ACTION_REBOOT
&& (argc
== optind
|| argc
== optind
+ 1)) {
6721 r
= update_reboot_param_file(argc
== optind
+ 1 ? argv
[optind
] : NULL
);
6724 } else if (optind
< argc
) {
6725 log_error("Too many arguments.");
6732 static int parse_time_spec(const char *t
, usec_t
*_u
) {
6736 if (streq(t
, "now"))
6738 else if (!strchr(t
, ':')) {
6741 if (safe_atou64(t
, &u
) < 0)
6744 *_u
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
* u
;
6753 hour
= strtol(t
, &e
, 10);
6754 if (errno
> 0 || *e
!= ':' || hour
< 0 || hour
> 23)
6757 minute
= strtol(e
+1, &e
, 10);
6758 if (errno
> 0 || *e
!= 0 || minute
< 0 || minute
> 59)
6761 n
= now(CLOCK_REALTIME
);
6762 s
= (time_t) (n
/ USEC_PER_SEC
);
6764 assert_se(localtime_r(&s
, &tm
));
6766 tm
.tm_hour
= (int) hour
;
6767 tm
.tm_min
= (int) minute
;
6770 assert_se(s
= mktime(&tm
));
6772 *_u
= (usec_t
) s
* USEC_PER_SEC
;
6775 *_u
+= USEC_PER_DAY
;
6781 static int shutdown_parse_argv(int argc
, char *argv
[]) {
6788 static const struct option options
[] = {
6789 { "help", no_argument
, NULL
, ARG_HELP
},
6790 { "halt", no_argument
, NULL
, 'H' },
6791 { "poweroff", no_argument
, NULL
, 'P' },
6792 { "reboot", no_argument
, NULL
, 'r' },
6793 { "kexec", no_argument
, NULL
, 'K' }, /* not documented extension */
6794 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6803 while ((c
= getopt_long(argc
, argv
, "HPrhkKt:afFc", options
, NULL
)) >= 0)
6811 arg_action
= ACTION_HALT
;
6815 arg_action
= ACTION_POWEROFF
;
6820 arg_action
= ACTION_KEXEC
;
6822 arg_action
= ACTION_REBOOT
;
6826 arg_action
= ACTION_KEXEC
;
6830 if (arg_action
!= ACTION_HALT
)
6831 arg_action
= ACTION_POWEROFF
;
6846 /* Compatibility nops */
6850 arg_action
= ACTION_CANCEL_SHUTDOWN
;
6857 assert_not_reached("Unhandled option");
6860 if (argc
> optind
&& arg_action
!= ACTION_CANCEL_SHUTDOWN
) {
6861 r
= parse_time_spec(argv
[optind
], &arg_when
);
6863 log_error("Failed to parse time specification: %s", argv
[optind
]);
6867 arg_when
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
;
6869 if (argc
> optind
&& arg_action
== ACTION_CANCEL_SHUTDOWN
)
6870 /* No time argument for shutdown cancel */
6871 arg_wall
= argv
+ optind
;
6872 else if (argc
> optind
+ 1)
6873 /* We skip the time argument */
6874 arg_wall
= argv
+ optind
+ 1;
6881 static int telinit_parse_argv(int argc
, char *argv
[]) {
6888 static const struct option options
[] = {
6889 { "help", no_argument
, NULL
, ARG_HELP
},
6890 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6894 static const struct {
6898 { '0', ACTION_POWEROFF
},
6899 { '6', ACTION_REBOOT
},
6900 { '1', ACTION_RESCUE
},
6901 { '2', ACTION_RUNLEVEL2
},
6902 { '3', ACTION_RUNLEVEL3
},
6903 { '4', ACTION_RUNLEVEL4
},
6904 { '5', ACTION_RUNLEVEL5
},
6905 { 's', ACTION_RESCUE
},
6906 { 'S', ACTION_RESCUE
},
6907 { 'q', ACTION_RELOAD
},
6908 { 'Q', ACTION_RELOAD
},
6909 { 'u', ACTION_REEXEC
},
6910 { 'U', ACTION_REEXEC
}
6919 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
6934 assert_not_reached("Unhandled option");
6937 if (optind
>= argc
) {
6938 log_error("%s: required argument missing.",
6939 program_invocation_short_name
);
6943 if (optind
+ 1 < argc
) {
6944 log_error("Too many arguments.");
6948 if (strlen(argv
[optind
]) != 1) {
6949 log_error("Expected single character argument.");
6953 for (i
= 0; i
< ELEMENTSOF(table
); i
++)
6954 if (table
[i
].from
== argv
[optind
][0])
6957 if (i
>= ELEMENTSOF(table
)) {
6958 log_error("Unknown command '%s'.", argv
[optind
]);
6962 arg_action
= table
[i
].to
;
6969 static int runlevel_parse_argv(int argc
, char *argv
[]) {
6975 static const struct option options
[] = {
6976 { "help", no_argument
, NULL
, ARG_HELP
},
6985 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
6996 assert_not_reached("Unhandled option");
6999 if (optind
< argc
) {
7000 log_error("Too many arguments.");
7007 static int parse_argv(int argc
, char *argv
[]) {
7011 if (program_invocation_short_name
) {
7013 if (strstr(program_invocation_short_name
, "halt")) {
7014 arg_action
= ACTION_HALT
;
7015 return halt_parse_argv(argc
, argv
);
7016 } else if (strstr(program_invocation_short_name
, "poweroff")) {
7017 arg_action
= ACTION_POWEROFF
;
7018 return halt_parse_argv(argc
, argv
);
7019 } else if (strstr(program_invocation_short_name
, "reboot")) {
7021 arg_action
= ACTION_KEXEC
;
7023 arg_action
= ACTION_REBOOT
;
7024 return halt_parse_argv(argc
, argv
);
7025 } else if (strstr(program_invocation_short_name
, "shutdown")) {
7026 arg_action
= ACTION_POWEROFF
;
7027 return shutdown_parse_argv(argc
, argv
);
7028 } else if (strstr(program_invocation_short_name
, "init")) {
7030 if (sd_booted() > 0) {
7031 arg_action
= _ACTION_INVALID
;
7032 return telinit_parse_argv(argc
, argv
);
7034 /* Hmm, so some other init system is
7035 * running, we need to forward this
7036 * request to it. For now we simply
7037 * guess that it is Upstart. */
7039 execv(TELINIT
, argv
);
7041 log_error("Couldn't find an alternative telinit implementation to spawn.");
7045 } else if (strstr(program_invocation_short_name
, "runlevel")) {
7046 arg_action
= ACTION_RUNLEVEL
;
7047 return runlevel_parse_argv(argc
, argv
);
7051 arg_action
= ACTION_SYSTEMCTL
;
7052 return systemctl_parse_argv(argc
, argv
);
7055 _pure_
static int action_to_runlevel(void) {
7057 static const char table
[_ACTION_MAX
] = {
7058 [ACTION_HALT
] = '0',
7059 [ACTION_POWEROFF
] = '0',
7060 [ACTION_REBOOT
] = '6',
7061 [ACTION_RUNLEVEL2
] = '2',
7062 [ACTION_RUNLEVEL3
] = '3',
7063 [ACTION_RUNLEVEL4
] = '4',
7064 [ACTION_RUNLEVEL5
] = '5',
7065 [ACTION_RESCUE
] = '1'
7068 assert(arg_action
< _ACTION_MAX
);
7070 return table
[arg_action
];
7073 static int talk_initctl(void) {
7075 struct init_request request
= {
7076 .magic
= INIT_MAGIC
,
7078 .cmd
= INIT_CMD_RUNLVL
7081 _cleanup_close_
int fd
= -1;
7085 rl
= action_to_runlevel();
7089 request
.runlevel
= rl
;
7091 fd
= open(INIT_FIFO
, O_WRONLY
|O_NDELAY
|O_CLOEXEC
|O_NOCTTY
);
7093 if (errno
== ENOENT
)
7096 log_error_errno(errno
, "Failed to open "INIT_FIFO
": %m");
7100 r
= loop_write(fd
, &request
, sizeof(request
), false);
7102 return log_error_errno(r
, "Failed to write to "INIT_FIFO
": %m");
7107 static int systemctl_main(sd_bus
*bus
, int argc
, char *argv
[], int bus_error
) {
7109 static const struct {
7117 int (* const dispatch
)(sd_bus
*bus
, char **args
);
7123 { "list-units", MORE
, 0, list_units
},
7124 { "list-unit-files", MORE
, 1, list_unit_files
, NOBUS
},
7125 { "list-sockets", MORE
, 1, list_sockets
},
7126 { "list-timers", MORE
, 1, list_timers
},
7127 { "list-jobs", MORE
, 1, list_jobs
},
7128 { "list-machines", MORE
, 1, list_machines
},
7129 { "clear-jobs", EQUAL
, 1, daemon_reload
},
7130 { "cancel", MORE
, 2, cancel_job
},
7131 { "start", MORE
, 2, start_unit
},
7132 { "stop", MORE
, 2, start_unit
},
7133 { "condstop", MORE
, 2, start_unit
}, /* For compatibility with ALTLinux */
7134 { "reload", MORE
, 2, start_unit
},
7135 { "restart", MORE
, 2, start_unit
},
7136 { "try-restart", MORE
, 2, start_unit
},
7137 { "reload-or-restart", MORE
, 2, start_unit
},
7138 { "reload-or-try-restart", MORE
, 2, start_unit
},
7139 { "force-reload", MORE
, 2, start_unit
}, /* For compatibility with SysV */
7140 { "condreload", MORE
, 2, start_unit
}, /* For compatibility with ALTLinux */
7141 { "condrestart", MORE
, 2, start_unit
}, /* For compatibility with RH */
7142 { "isolate", EQUAL
, 2, start_unit
},
7143 { "kill", MORE
, 2, kill_unit
},
7144 { "is-active", MORE
, 2, check_unit_active
},
7145 { "check", MORE
, 2, check_unit_active
},
7146 { "is-failed", MORE
, 2, check_unit_failed
},
7147 { "show", MORE
, 1, show
},
7148 { "cat", MORE
, 2, cat
, NOBUS
},
7149 { "status", MORE
, 1, show
},
7150 { "help", MORE
, 2, show
},
7151 { "snapshot", LESS
, 2, snapshot
},
7152 { "delete", MORE
, 2, delete_snapshot
},
7153 { "daemon-reload", EQUAL
, 1, daemon_reload
},
7154 { "daemon-reexec", EQUAL
, 1, daemon_reload
},
7155 { "show-environment", EQUAL
, 1, show_environment
},
7156 { "set-environment", MORE
, 2, set_environment
},
7157 { "unset-environment", MORE
, 2, set_environment
},
7158 { "import-environment", MORE
, 1, import_environment
},
7159 { "halt", EQUAL
, 1, start_special
, FORCE
},
7160 { "poweroff", EQUAL
, 1, start_special
, FORCE
},
7161 { "reboot", MORE
, 1, start_special
, FORCE
},
7162 { "kexec", EQUAL
, 1, start_special
},
7163 { "suspend", EQUAL
, 1, start_special
},
7164 { "hibernate", EQUAL
, 1, start_special
},
7165 { "hybrid-sleep", EQUAL
, 1, start_special
},
7166 { "default", EQUAL
, 1, start_special
},
7167 { "rescue", EQUAL
, 1, start_special
},
7168 { "emergency", EQUAL
, 1, start_special
},
7169 { "exit", EQUAL
, 1, start_special
},
7170 { "reset-failed", MORE
, 1, reset_failed
},
7171 { "enable", MORE
, 2, enable_unit
, NOBUS
},
7172 { "disable", MORE
, 2, enable_unit
, NOBUS
},
7173 { "is-enabled", MORE
, 2, unit_is_enabled
, NOBUS
},
7174 { "reenable", MORE
, 2, enable_unit
, NOBUS
},
7175 { "preset", MORE
, 2, enable_unit
, NOBUS
},
7176 { "preset-all", EQUAL
, 1, preset_all
, NOBUS
},
7177 { "mask", MORE
, 2, enable_unit
, NOBUS
},
7178 { "unmask", MORE
, 2, enable_unit
, NOBUS
},
7179 { "link", MORE
, 2, enable_unit
, NOBUS
},
7180 { "switch-root", MORE
, 2, switch_root
},
7181 { "list-dependencies", LESS
, 2, list_dependencies
},
7182 { "set-default", EQUAL
, 2, set_default
, NOBUS
},
7183 { "get-default", EQUAL
, 1, get_default
, NOBUS
},
7184 { "set-property", MORE
, 3, set_property
},
7185 { "is-system-running", EQUAL
, 1, is_system_running
},
7186 { "add-wants", MORE
, 3, add_dependency
, NOBUS
},
7187 { "add-requires", MORE
, 3, add_dependency
, NOBUS
},
7188 { "edit", MORE
, 2, edit
, NOBUS
},
7197 left
= argc
- optind
;
7199 /* Special rule: no arguments (left == 0) means "list-units" */
7201 if (streq(argv
[optind
], "help") && !argv
[optind
+1]) {
7202 log_error("This command expects one or more "
7203 "unit names. Did you mean --help?");
7207 for (; verb
->verb
; verb
++)
7208 if (streq(argv
[optind
], verb
->verb
))
7211 log_error("Unknown operation '%s'.", argv
[optind
]);
7216 switch (verb
->argc_cmp
) {
7219 if (left
!= verb
->argc
) {
7220 log_error("Invalid number of arguments.");
7227 if (left
< verb
->argc
) {
7228 log_error("Too few arguments.");
7235 if (left
> verb
->argc
) {
7236 log_error("Too many arguments.");
7243 assert_not_reached("Unknown comparison operator.");
7246 /* Require a bus connection for all operations but
7248 if (verb
->bus
== NOBUS
) {
7249 if (!bus
&& !avoid_bus()) {
7250 log_error_errno(bus_error
, "Failed to get D-Bus connection: %m");
7255 if (running_in_chroot() > 0) {
7256 log_info("Running in chroot, ignoring request.");
7260 if ((verb
->bus
!= FORCE
|| arg_force
<= 0) && !bus
) {
7261 log_error_errno(bus_error
, "Failed to get D-Bus connection: %m");
7266 return verb
->dispatch(bus
, argv
+ optind
);
7269 static int reload_with_fallback(sd_bus
*bus
) {
7272 /* First, try systemd via D-Bus. */
7273 if (daemon_reload(bus
, NULL
) >= 0)
7277 /* Nothing else worked, so let's try signals */
7278 assert(arg_action
== ACTION_RELOAD
|| arg_action
== ACTION_REEXEC
);
7280 if (kill(1, arg_action
== ACTION_RELOAD
? SIGHUP
: SIGTERM
) < 0)
7281 return log_error_errno(errno
, "kill() failed: %m");
7286 static int start_with_fallback(sd_bus
*bus
) {
7289 /* First, try systemd via D-Bus. */
7290 if (start_unit(bus
, NULL
) >= 0)
7294 /* Nothing else worked, so let's try
7296 if (talk_initctl() > 0)
7299 log_error("Failed to talk to init daemon.");
7303 warn_wall(arg_action
);
7307 static int halt_now(enum action a
) {
7309 /* The kernel will automaticall flush ATA disks and suchlike
7310 * on reboot(), but the file systems need to be synce'd
7311 * explicitly in advance. */
7314 /* Make sure C-A-D is handled by the kernel from this point
7316 reboot(RB_ENABLE_CAD
);
7321 log_info("Halting.");
7322 reboot(RB_HALT_SYSTEM
);
7325 case ACTION_POWEROFF
:
7326 log_info("Powering off.");
7327 reboot(RB_POWER_OFF
);
7331 case ACTION_REBOOT
: {
7332 _cleanup_free_
char *param
= NULL
;
7334 if (read_one_line_file(REBOOT_PARAM_FILE
, ¶m
) >= 0) {
7335 log_info("Rebooting with argument '%s'.", param
);
7336 syscall(SYS_reboot
, LINUX_REBOOT_MAGIC1
, LINUX_REBOOT_MAGIC2
,
7337 LINUX_REBOOT_CMD_RESTART2
, param
);
7340 log_info("Rebooting.");
7341 reboot(RB_AUTOBOOT
);
7346 assert_not_reached("Unknown action.");
7350 static int halt_main(sd_bus
*bus
) {
7353 r
= check_inhibitors(bus
, arg_action
);
7357 if (geteuid() != 0) {
7358 /* Try logind if we are a normal user and no special
7359 * mode applies. Maybe PolicyKit allows us to shutdown
7362 if (arg_when
<= 0 &&
7364 (arg_action
== ACTION_POWEROFF
||
7365 arg_action
== ACTION_REBOOT
)) {
7366 r
= reboot_with_logind(bus
, arg_action
);
7371 log_error("Must be root.");
7376 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
7377 _cleanup_bus_flush_close_unref_ sd_bus
*b
= NULL
;
7378 _cleanup_free_
char *m
= NULL
;
7382 log_error("Unable to perform operation without bus connection.");
7386 r
= sd_bus_open_system(&b
);
7388 return log_error_errno(r
, "Unable to open system bus: %m");
7390 m
= strv_join(arg_wall
, " ");
7394 r
= sd_bus_call_method(
7396 "org.freedesktop.login1",
7397 "/org/freedesktop/login1",
7398 "org.freedesktop.login1.Manager",
7407 log_warning_errno(r
, "Failed to set wall message, ignoring: %s",
7408 bus_error_message(&error
, r
));
7409 sd_bus_error_free(&error
);
7412 switch (arg_action
) {
7416 case ACTION_POWEROFF
:
7417 action
= "poweroff";
7428 action
= strjoina("dry-", action
);
7430 r
= sd_bus_call_method(
7432 "org.freedesktop.login1",
7433 "/org/freedesktop/login1",
7434 "org.freedesktop.login1.Manager",
7442 log_warning_errno(r
, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s",
7443 bus_error_message(&error
, r
));
7445 char date
[FORMAT_TIMESTAMP_MAX
];
7447 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
7448 format_timestamp(date
, sizeof(date
), arg_when
));
7453 if (!arg_dry
&& !arg_force
)
7454 return start_with_fallback(bus
);
7457 if (sd_booted() > 0)
7458 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
7460 r
= utmp_put_shutdown();
7462 log_warning_errno(r
, "Failed to write utmp record: %m");
7469 r
= halt_now(arg_action
);
7470 log_error_errno(r
, "Failed to reboot: %m");
7475 static int runlevel_main(void) {
7476 int r
, runlevel
, previous
;
7478 r
= utmp_get_runlevel(&runlevel
, &previous
);
7485 previous
<= 0 ? 'N' : previous
,
7486 runlevel
<= 0 ? 'N' : runlevel
);
7491 int main(int argc
, char*argv
[]) {
7492 _cleanup_bus_flush_close_unref_ sd_bus
*bus
= NULL
;
7495 setlocale(LC_ALL
, "");
7496 log_parse_environment();
7499 /* Explicitly not on_tty() to avoid setting cached value.
7500 * This becomes relevant for piping output which might be
7502 original_stdout_is_tty
= isatty(STDOUT_FILENO
);
7504 r
= parse_argv(argc
, argv
);
7508 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
7509 * let's shortcut this */
7510 if (arg_action
== ACTION_RUNLEVEL
) {
7511 r
= runlevel_main();
7515 if (running_in_chroot() > 0 && arg_action
!= ACTION_SYSTEMCTL
) {
7516 log_info("Running in chroot, ignoring request.");
7522 r
= bus_open_transport_systemd(arg_transport
, arg_host
, arg_scope
!= UNIT_FILE_SYSTEM
, &bus
);
7525 sd_bus_set_allow_interactive_authorization(bus
, arg_ask_password
);
7527 /* systemctl_main() will print an error message for the bus
7528 * connection, but only if it needs to */
7530 switch (arg_action
) {
7532 case ACTION_SYSTEMCTL
:
7533 r
= systemctl_main(bus
, argc
, argv
, r
);
7537 case ACTION_POWEROFF
:
7543 case ACTION_RUNLEVEL2
:
7544 case ACTION_RUNLEVEL3
:
7545 case ACTION_RUNLEVEL4
:
7546 case ACTION_RUNLEVEL5
:
7548 case ACTION_EMERGENCY
:
7549 case ACTION_DEFAULT
:
7550 r
= start_with_fallback(bus
);
7555 r
= reload_with_fallback(bus
);
7558 case ACTION_CANCEL_SHUTDOWN
: {
7559 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
7560 _cleanup_bus_flush_close_unref_ sd_bus
*b
= NULL
;
7561 _cleanup_free_
char *m
= NULL
;
7564 log_error("Unable to perform operation without bus connection.");
7568 r
= sd_bus_open_system(&b
);
7570 return log_error_errno(r
, "Unable to open system bus: %m");
7573 m
= strv_join(arg_wall
, " ");
7580 r
= sd_bus_call_method(
7582 "org.freedesktop.login1",
7583 "/org/freedesktop/login1",
7584 "org.freedesktop.login1.Manager",
7593 log_warning_errno(r
, "Failed to set wall message, ignoring: %s",
7594 bus_error_message(&error
, r
));
7595 sd_bus_error_free(&error
);
7598 r
= sd_bus_call_method(
7600 "org.freedesktop.login1",
7601 "/org/freedesktop/login1",
7602 "org.freedesktop.login1.Manager",
7603 "CancelScheduledShutdown",
7607 log_warning_errno(r
, "Failed to talk to logind, shutdown hasn't been cancelled: %s",
7608 bus_error_message(&error
, r
));
7612 case ACTION_RUNLEVEL
:
7613 case _ACTION_INVALID
:
7615 assert_not_reached("Unknown action");
7620 ask_password_agent_close();
7621 polkit_agent_close();
7623 strv_free(arg_types
);
7624 strv_free(arg_states
);
7625 strv_free(arg_properties
);
7627 return r
< 0 ? EXIT_FAILURE
: r
;