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"
37 #include "sd-shutdown.h"
44 #include "utmp-wtmp.h"
47 #include "path-util.h"
49 #include "cgroup-show.h"
50 #include "cgroup-util.h"
52 #include "path-lookup.h"
53 #include "exit-status.h"
55 #include "unit-name.h"
57 #include "spawn-ask-password-agent.h"
58 #include "spawn-polkit-agent.h"
60 #include "logs-show.h"
61 #include "socket-util.h"
66 #include "bus-message.h"
67 #include "bus-error.h"
68 #include "bus-common-errors.h"
72 #include "formats-util.h"
74 static char **arg_types
= NULL
;
75 static char **arg_states
= NULL
;
76 static char **arg_properties
= NULL
;
77 static bool arg_all
= false;
78 static enum dependency
{
84 } arg_dependency
= DEPENDENCY_FORWARD
;
85 static const char *arg_job_mode
= "replace";
86 static UnitFileScope arg_scope
= UNIT_FILE_SYSTEM
;
87 static bool arg_no_block
= false;
88 static bool arg_no_legend
= false;
89 static bool arg_no_pager
= false;
90 static bool arg_no_wtmp
= false;
91 static bool arg_no_wall
= false;
92 static bool arg_no_reload
= false;
93 static bool arg_show_types
= false;
94 static bool arg_ignore_inhibitors
= false;
95 static bool arg_dry
= false;
96 static bool arg_quiet
= false;
97 static bool arg_full
= false;
98 static bool arg_recursive
= false;
99 static int arg_force
= 0;
100 static bool arg_ask_password
= true;
101 static bool arg_runtime
= false;
102 static UnitFilePresetMode arg_preset_mode
= UNIT_FILE_PRESET_FULL
;
103 static char **arg_wall
= NULL
;
104 static const char *arg_kill_who
= NULL
;
105 static int arg_signal
= SIGTERM
;
106 static const char *arg_root
= NULL
;
107 static usec_t arg_when
= 0;
129 ACTION_CANCEL_SHUTDOWN
,
131 } arg_action
= ACTION_SYSTEMCTL
;
132 static BusTransport arg_transport
= BUS_TRANSPORT_LOCAL
;
133 static char *arg_host
= NULL
;
134 static unsigned arg_lines
= 10;
135 static OutputMode arg_output
= OUTPUT_SHORT
;
136 static bool arg_plain
= false;
137 static bool arg_firmware_setup
= false;
139 static bool original_stdout_is_tty
;
141 static int daemon_reload(sd_bus
*bus
, char **args
);
142 static int halt_now(enum action a
);
143 static int check_one_unit(sd_bus
*bus
, const char *name
, const char *good_states
, bool quiet
);
145 static char** strv_skip_first(char **strv
) {
146 if (strv_length(strv
) > 0)
151 static void pager_open_if_enabled(void) {
159 static void ask_password_agent_open_if_enabled(void) {
161 /* Open the password agent as a child process if necessary */
163 if (!arg_ask_password
)
166 if (arg_scope
!= UNIT_FILE_SYSTEM
)
169 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
172 ask_password_agent_open();
175 static void polkit_agent_open_if_enabled(void) {
177 /* Open the polkit agent as a child process if necessary */
179 if (!arg_ask_password
)
182 if (arg_scope
!= UNIT_FILE_SYSTEM
)
185 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
191 static OutputFlags
get_output_flags(void) {
193 arg_all
* OUTPUT_SHOW_ALL
|
194 arg_full
* OUTPUT_FULL_WIDTH
|
195 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH
|
196 on_tty() * OUTPUT_COLOR
|
197 !arg_quiet
* OUTPUT_WARN_CUTOFF
;
200 static int translate_bus_error_to_exit_status(int r
, const sd_bus_error
*error
) {
203 if (!sd_bus_error_is_set(error
))
206 if (sd_bus_error_has_name(error
, SD_BUS_ERROR_ACCESS_DENIED
) ||
207 sd_bus_error_has_name(error
, BUS_ERROR_ONLY_BY_DEPENDENCY
) ||
208 sd_bus_error_has_name(error
, BUS_ERROR_NO_ISOLATION
) ||
209 sd_bus_error_has_name(error
, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE
))
210 return EXIT_NOPERMISSION
;
212 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
))
213 return EXIT_NOTINSTALLED
;
215 if (sd_bus_error_has_name(error
, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE
) ||
216 sd_bus_error_has_name(error
, SD_BUS_ERROR_NOT_SUPPORTED
))
217 return EXIT_NOTIMPLEMENTED
;
219 if (sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
))
220 return EXIT_NOTCONFIGURED
;
228 static void warn_wall(enum action a
) {
229 static const char *table
[_ACTION_MAX
] = {
230 [ACTION_HALT
] = "The system is going down for system halt NOW!",
231 [ACTION_REBOOT
] = "The system is going down for reboot NOW!",
232 [ACTION_POWEROFF
] = "The system is going down for power-off NOW!",
233 [ACTION_KEXEC
] = "The system is going down for kexec reboot NOW!",
234 [ACTION_RESCUE
] = "The system is going down to rescue mode NOW!",
235 [ACTION_EMERGENCY
] = "The system is going down to emergency mode NOW!",
236 [ACTION_CANCEL_SHUTDOWN
] = "The system shutdown has been cancelled NOW!"
243 _cleanup_free_
char *p
;
245 p
= strv_join(arg_wall
, " ");
252 utmp_wall(p
, NULL
, NULL
);
260 utmp_wall(table
[a
], NULL
, NULL
);
263 static bool avoid_bus(void) {
265 if (running_in_chroot() > 0)
268 if (sd_booted() <= 0)
271 if (!isempty(arg_root
))
274 if (arg_scope
== UNIT_FILE_GLOBAL
)
280 static int compare_unit_info(const void *a
, const void *b
) {
281 const UnitInfo
*u
= a
, *v
= b
;
285 /* First, order by machine */
286 if (!u
->machine
&& v
->machine
)
288 if (u
->machine
&& !v
->machine
)
290 if (u
->machine
&& v
->machine
) {
291 r
= strcasecmp(u
->machine
, v
->machine
);
296 /* Second, order by unit type */
297 d1
= strrchr(u
->id
, '.');
298 d2
= strrchr(v
->id
, '.');
300 r
= strcasecmp(d1
, d2
);
305 /* Third, order by name */
306 return strcasecmp(u
->id
, v
->id
);
309 static bool output_show_unit(const UnitInfo
*u
, char **patterns
) {
310 if (!strv_fnmatch_or_empty(patterns
, u
->id
, FNM_NOESCAPE
))
316 dot
= strrchr(u
->id
, '.');
320 if (!strv_find(arg_types
, dot
+1))
330 if (streq(u
->active_state
, "inactive") || u
->following
[0])
336 static int output_units_list(const UnitInfo
*unit_infos
, unsigned c
) {
337 unsigned circle_len
= 0, id_len
, max_id_len
, load_len
, active_len
, sub_len
, job_len
, desc_len
;
339 unsigned n_shown
= 0;
342 max_id_len
= strlen("UNIT");
343 load_len
= strlen("LOAD");
344 active_len
= strlen("ACTIVE");
345 sub_len
= strlen("SUB");
346 job_len
= strlen("JOB");
349 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
350 max_id_len
= MAX(max_id_len
, strlen(u
->id
) + (u
->machine
? strlen(u
->machine
)+1 : 0));
351 load_len
= MAX(load_len
, strlen(u
->load_state
));
352 active_len
= MAX(active_len
, strlen(u
->active_state
));
353 sub_len
= MAX(sub_len
, strlen(u
->sub_state
));
355 if (u
->job_id
!= 0) {
356 job_len
= MAX(job_len
, strlen(u
->job_type
));
360 if (!arg_no_legend
&&
361 (streq(u
->active_state
, "failed") ||
362 STR_IN_SET(u
->load_state
, "error", "not-found", "masked")))
366 if (!arg_full
&& original_stdout_is_tty
) {
369 id_len
= MIN(max_id_len
, 25u);
370 basic_len
= circle_len
+ 5 + id_len
+ 5 + active_len
+ sub_len
;
373 basic_len
+= job_len
+ 1;
375 if (basic_len
< (unsigned) columns()) {
376 unsigned extra_len
, incr
;
377 extra_len
= columns() - basic_len
;
379 /* Either UNIT already got 25, or is fully satisfied.
380 * Grant up to 25 to DESC now. */
381 incr
= MIN(extra_len
, 25u);
385 /* split the remaining space between UNIT and DESC,
386 * but do not give UNIT more than it needs. */
388 incr
= MIN(extra_len
/ 2, max_id_len
- id_len
);
390 desc_len
+= extra_len
- incr
;
396 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
397 _cleanup_free_
char *e
= NULL
, *j
= NULL
;
398 const char *on_loaded
= "", *off_loaded
= "";
399 const char *on_active
= "", *off_active
= "";
400 const char *on_circle
= "", *off_circle
= "";
404 if (!n_shown
&& !arg_no_legend
) {
409 printf("%-*s %-*s %-*s %-*s ",
412 active_len
, "ACTIVE",
416 printf("%-*s ", job_len
, "JOB");
418 if (!arg_full
&& arg_no_pager
)
419 printf("%.*s\n", desc_len
, "DESCRIPTION");
421 printf("%s\n", "DESCRIPTION");
426 if (STR_IN_SET(u
->load_state
, "error", "not-found", "masked") && !arg_plain
) {
427 on_loaded
= ansi_highlight_red();
428 on_circle
= ansi_highlight_yellow();
429 off_loaded
= off_circle
= ansi_highlight_off();
431 } else if (streq(u
->active_state
, "failed") && !arg_plain
) {
432 on_circle
= on_active
= ansi_highlight_red();
433 off_circle
= off_active
= ansi_highlight_off();
438 j
= strjoin(u
->machine
, ":", u
->id
, NULL
);
447 e
= ellipsize(id
, id_len
, 33);
455 printf("%s%s%s ", on_circle
, circle
? draw_special_char(DRAW_BLACK_CIRCLE
) : " ", off_circle
);
457 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
458 on_active
, id_len
, id
, off_active
,
459 on_loaded
, load_len
, u
->load_state
, off_loaded
,
460 on_active
, active_len
, u
->active_state
,
461 sub_len
, u
->sub_state
, off_active
,
462 job_count
? job_len
+ 1 : 0, u
->job_id
? u
->job_type
: "");
465 printf("%.*s\n", desc_len
, u
->description
);
467 printf("%s\n", u
->description
);
470 if (!arg_no_legend
) {
471 const char *on
, *off
;
475 "LOAD = Reflects whether the unit definition was properly loaded.\n"
476 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
477 "SUB = The low-level unit activation state, values depend on unit type.");
478 puts(job_count
? "JOB = Pending job for the unit.\n" : "");
479 on
= ansi_highlight();
480 off
= ansi_highlight_off();
482 on
= ansi_highlight_red();
483 off
= ansi_highlight_off();
487 printf("%s%u loaded units listed.%s\n"
488 "To show all installed unit files use 'systemctl list-unit-files'.\n",
491 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
492 "To show all installed unit files use 'systemctl list-unit-files'.\n",
499 static int get_unit_list(
503 UnitInfo
**unit_infos
,
505 sd_bus_message
**_reply
) {
507 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
508 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
509 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
518 r
= sd_bus_message_new_method_call(
521 "org.freedesktop.systemd1",
522 "/org/freedesktop/systemd1",
523 "org.freedesktop.systemd1.Manager",
524 "ListUnitsFiltered");
527 return bus_log_create_error(r
);
529 r
= sd_bus_message_append_strv(m
, arg_states
);
531 return bus_log_create_error(r
);
533 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
535 log_error("Failed to list units: %s", bus_error_message(&error
, r
));
539 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssssouso)");
541 return bus_log_parse_error(r
);
543 while ((r
= bus_parse_unit_info(reply
, &u
)) > 0) {
546 if (!output_show_unit(&u
, patterns
))
549 if (!GREEDY_REALLOC(*unit_infos
, size
, c
+1))
552 (*unit_infos
)[c
++] = u
;
555 return bus_log_parse_error(r
);
557 r
= sd_bus_message_exit_container(reply
);
559 return bus_log_parse_error(r
);
567 static void message_set_freep(Set
**set
) {
570 while ((m
= set_steal_first(*set
)))
571 sd_bus_message_unref(m
);
576 static int get_unit_list_recursive(
579 UnitInfo
**_unit_infos
,
583 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
584 _cleanup_(message_set_freep
) Set
*replies
;
585 sd_bus_message
*reply
;
593 replies
= set_new(NULL
);
597 c
= get_unit_list(bus
, NULL
, patterns
, &unit_infos
, 0, &reply
);
601 r
= set_put(replies
, reply
);
603 sd_bus_message_unref(reply
);
608 _cleanup_strv_free_
char **machines
= NULL
;
611 r
= sd_get_machine_names(&machines
);
615 STRV_FOREACH(i
, machines
) {
616 _cleanup_bus_close_unref_ sd_bus
*container
= NULL
;
619 r
= sd_bus_open_system_machine(&container
, *i
);
621 log_error_errno(r
, "Failed to connect to container %s: %m", *i
);
625 k
= get_unit_list(container
, *i
, patterns
, &unit_infos
, c
, &reply
);
631 r
= set_put(replies
, reply
);
633 sd_bus_message_unref(reply
);
638 *_machines
= machines
;
643 *_unit_infos
= unit_infos
;
652 static int list_units(sd_bus
*bus
, char **args
) {
653 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
654 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
655 _cleanup_strv_free_
char **machines
= NULL
;
658 pager_open_if_enabled();
660 r
= get_unit_list_recursive(bus
, strv_skip_first(args
), &unit_infos
, &replies
, &machines
);
664 qsort_safe(unit_infos
, r
, sizeof(UnitInfo
), compare_unit_info
);
665 return output_units_list(unit_infos
, r
);
668 static int get_triggered_units(
673 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
676 r
= sd_bus_get_property_strv(
678 "org.freedesktop.systemd1",
680 "org.freedesktop.systemd1.Unit",
686 log_error("Failed to determine triggers: %s", bus_error_message(&error
, r
));
691 static int get_listening(
693 const char* unit_path
,
696 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
697 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
698 const char *type
, *path
;
701 r
= sd_bus_get_property(
703 "org.freedesktop.systemd1",
705 "org.freedesktop.systemd1.Socket",
711 log_error("Failed to get list of listening sockets: %s", bus_error_message(&error
, r
));
715 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
717 return bus_log_parse_error(r
);
719 while ((r
= sd_bus_message_read(reply
, "(ss)", &type
, &path
)) > 0) {
721 r
= strv_extend(listening
, type
);
725 r
= strv_extend(listening
, path
);
732 return bus_log_parse_error(r
);
734 r
= sd_bus_message_exit_container(reply
);
736 return bus_log_parse_error(r
);
748 /* Note: triggered is a list here, although it almost certainly
749 * will always be one unit. Nevertheless, dbus API allows for multiple
750 * values, so let's follow that. */
753 /* The strv above is shared. free is set only in the first one. */
757 static int socket_info_compare(const struct socket_info
*a
, const struct socket_info
*b
) {
763 if (!a
->machine
&& b
->machine
)
765 if (a
->machine
&& !b
->machine
)
767 if (a
->machine
&& b
->machine
) {
768 o
= strcasecmp(a
->machine
, b
->machine
);
773 o
= strcmp(a
->path
, b
->path
);
775 o
= strcmp(a
->type
, b
->type
);
780 static int output_sockets_list(struct socket_info
*socket_infos
, unsigned cs
) {
781 struct socket_info
*s
;
782 unsigned pathlen
= strlen("LISTEN"),
783 typelen
= strlen("TYPE") * arg_show_types
,
784 socklen
= strlen("UNIT"),
785 servlen
= strlen("ACTIVATES");
786 const char *on
, *off
;
788 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
792 socklen
= MAX(socklen
, strlen(s
->id
));
794 typelen
= MAX(typelen
, strlen(s
->type
));
795 pathlen
= MAX(pathlen
, strlen(s
->path
) + (s
->machine
? strlen(s
->machine
)+1 : 0));
797 STRV_FOREACH(a
, s
->triggered
)
798 tmp
+= strlen(*a
) + 2*(a
!= s
->triggered
);
799 servlen
= MAX(servlen
, tmp
);
804 printf("%-*s %-*.*s%-*s %s\n",
806 typelen
+ arg_show_types
, typelen
+ arg_show_types
, "TYPE ",
810 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
811 _cleanup_free_
char *j
= NULL
;
816 j
= strjoin(s
->machine
, ":", s
->path
, NULL
);
824 printf("%-*s %-*s %-*s",
825 pathlen
, path
, typelen
, s
->type
, socklen
, s
->id
);
828 pathlen
, path
, socklen
, s
->id
);
829 STRV_FOREACH(a
, s
->triggered
)
831 a
== s
->triggered
? "" : ",", *a
);
835 on
= ansi_highlight();
836 off
= ansi_highlight_off();
840 on
= ansi_highlight_red();
841 off
= ansi_highlight_off();
844 if (!arg_no_legend
) {
845 printf("%s%u sockets listed.%s\n", on
, cs
, off
);
847 printf("Pass --all to see loaded but inactive sockets, too.\n");
853 static int list_sockets(sd_bus
*bus
, char **args
) {
854 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
855 _cleanup_strv_free_
char **machines
= NULL
;
856 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
857 _cleanup_free_
struct socket_info
*socket_infos
= NULL
;
859 struct socket_info
*s
;
864 pager_open_if_enabled();
866 n
= get_unit_list_recursive(bus
, strv_skip_first(args
), &unit_infos
, &replies
, &machines
);
870 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
871 _cleanup_strv_free_
char **listening
= NULL
, **triggered
= NULL
;
874 if (!endswith(u
->id
, ".socket"))
877 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
881 c
= get_listening(bus
, u
->unit_path
, &listening
);
887 if (!GREEDY_REALLOC(socket_infos
, size
, cs
+ c
)) {
892 for (i
= 0; i
< c
; i
++)
893 socket_infos
[cs
+ i
] = (struct socket_info
) {
894 .machine
= u
->machine
,
896 .type
= listening
[i
*2],
897 .path
= listening
[i
*2 + 1],
898 .triggered
= triggered
,
899 .own_triggered
= i
==0,
902 /* from this point on we will cleanup those socket_infos */
905 listening
= triggered
= NULL
; /* avoid cleanup */
908 qsort_safe(socket_infos
, cs
, sizeof(struct socket_info
),
909 (__compar_fn_t
) socket_info_compare
);
911 output_sockets_list(socket_infos
, cs
);
914 assert(cs
== 0 || socket_infos
);
915 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
918 if (s
->own_triggered
)
919 strv_free(s
->triggered
);
925 static int get_next_elapse(
928 dual_timestamp
*next
) {
930 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
938 r
= sd_bus_get_property_trivial(
940 "org.freedesktop.systemd1",
942 "org.freedesktop.systemd1.Timer",
943 "NextElapseUSecMonotonic",
948 log_error("Failed to get next elapsation time: %s", bus_error_message(&error
, r
));
952 r
= sd_bus_get_property_trivial(
954 "org.freedesktop.systemd1",
956 "org.freedesktop.systemd1.Timer",
957 "NextElapseUSecRealtime",
962 log_error("Failed to get next elapsation time: %s", bus_error_message(&error
, r
));
970 static int get_last_trigger(
975 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
982 r
= sd_bus_get_property_trivial(
984 "org.freedesktop.systemd1",
986 "org.freedesktop.systemd1.Timer",
992 log_error("Failed to get last trigger time: %s", bus_error_message(&error
, r
));
1000 const char* machine
;
1003 usec_t last_trigger
;
1007 static int timer_info_compare(const struct timer_info
*a
, const struct timer_info
*b
) {
1013 if (!a
->machine
&& b
->machine
)
1015 if (a
->machine
&& !b
->machine
)
1017 if (a
->machine
&& b
->machine
) {
1018 o
= strcasecmp(a
->machine
, b
->machine
);
1023 if (a
->next_elapse
< b
->next_elapse
)
1025 if (a
->next_elapse
> b
->next_elapse
)
1028 return strcmp(a
->id
, b
->id
);
1031 static int output_timers_list(struct timer_info
*timer_infos
, unsigned n
) {
1032 struct timer_info
*t
;
1034 nextlen
= strlen("NEXT"),
1035 leftlen
= strlen("LEFT"),
1036 lastlen
= strlen("LAST"),
1037 passedlen
= strlen("PASSED"),
1038 unitlen
= strlen("UNIT"),
1039 activatelen
= strlen("ACTIVATES");
1041 const char *on
, *off
;
1043 assert(timer_infos
|| n
== 0);
1045 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1049 if (t
->next_elapse
> 0) {
1050 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1052 format_timestamp(tstamp
, sizeof(tstamp
), t
->next_elapse
);
1053 nextlen
= MAX(nextlen
, strlen(tstamp
) + 1);
1055 format_timestamp_relative(trel
, sizeof(trel
), t
->next_elapse
);
1056 leftlen
= MAX(leftlen
, strlen(trel
));
1059 if (t
->last_trigger
> 0) {
1060 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1062 format_timestamp(tstamp
, sizeof(tstamp
), t
->last_trigger
);
1063 lastlen
= MAX(lastlen
, strlen(tstamp
) + 1);
1065 format_timestamp_relative(trel
, sizeof(trel
), t
->last_trigger
);
1066 passedlen
= MAX(passedlen
, strlen(trel
));
1069 unitlen
= MAX(unitlen
, strlen(t
->id
) + (t
->machine
? strlen(t
->machine
)+1 : 0));
1071 STRV_FOREACH(a
, t
->triggered
)
1072 ul
+= strlen(*a
) + 2*(a
!= t
->triggered
);
1074 activatelen
= MAX(activatelen
, ul
);
1079 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1083 passedlen
, "PASSED",
1087 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1088 _cleanup_free_
char *j
= NULL
;
1090 char tstamp1
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel1
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1091 char tstamp2
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel2
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1094 format_timestamp(tstamp1
, sizeof(tstamp1
), t
->next_elapse
);
1095 format_timestamp_relative(trel1
, sizeof(trel1
), t
->next_elapse
);
1097 format_timestamp(tstamp2
, sizeof(tstamp2
), t
->last_trigger
);
1098 format_timestamp_relative(trel2
, sizeof(trel2
), t
->last_trigger
);
1101 j
= strjoin(t
->machine
, ":", t
->id
, NULL
);
1108 printf("%-*s %-*s %-*s %-*s %-*s",
1109 nextlen
, tstamp1
, leftlen
, trel1
, lastlen
, tstamp2
, passedlen
, trel2
, unitlen
, unit
);
1111 STRV_FOREACH(a
, t
->triggered
)
1113 a
== t
->triggered
? "" : ",", *a
);
1117 on
= ansi_highlight();
1118 off
= ansi_highlight_off();
1122 on
= ansi_highlight_red();
1123 off
= ansi_highlight_off();
1126 if (!arg_no_legend
) {
1127 printf("%s%u timers listed.%s\n", on
, n
, off
);
1129 printf("Pass --all to see loaded but inactive timers, too.\n");
1135 static usec_t
calc_next_elapse(dual_timestamp
*nw
, dual_timestamp
*next
) {
1141 if (next
->monotonic
!= USEC_INFINITY
&& next
->monotonic
> 0) {
1144 if (next
->monotonic
> nw
->monotonic
)
1145 converted
= nw
->realtime
+ (next
->monotonic
- nw
->monotonic
);
1147 converted
= nw
->realtime
- (nw
->monotonic
- next
->monotonic
);
1149 if (next
->realtime
!= USEC_INFINITY
&& next
->realtime
> 0)
1150 next_elapse
= MIN(converted
, next
->realtime
);
1152 next_elapse
= converted
;
1155 next_elapse
= next
->realtime
;
1160 static int list_timers(sd_bus
*bus
, char **args
) {
1161 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
1162 _cleanup_strv_free_
char **machines
= NULL
;
1163 _cleanup_free_
struct timer_info
*timer_infos
= NULL
;
1164 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
1165 struct timer_info
*t
;
1172 pager_open_if_enabled();
1174 n
= get_unit_list_recursive(bus
, strv_skip_first(args
), &unit_infos
, &replies
, &machines
);
1178 dual_timestamp_get(&nw
);
1180 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
1181 _cleanup_strv_free_
char **triggered
= NULL
;
1182 dual_timestamp next
= {};
1185 if (!endswith(u
->id
, ".timer"))
1188 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
1192 r
= get_next_elapse(bus
, u
->unit_path
, &next
);
1196 get_last_trigger(bus
, u
->unit_path
, &last
);
1198 if (!GREEDY_REALLOC(timer_infos
, size
, c
+1)) {
1203 m
= calc_next_elapse(&nw
, &next
);
1205 timer_infos
[c
++] = (struct timer_info
) {
1206 .machine
= u
->machine
,
1209 .last_trigger
= last
,
1210 .triggered
= triggered
,
1213 triggered
= NULL
; /* avoid cleanup */
1216 qsort_safe(timer_infos
, c
, sizeof(struct timer_info
),
1217 (__compar_fn_t
) timer_info_compare
);
1219 output_timers_list(timer_infos
, c
);
1222 for (t
= timer_infos
; t
< timer_infos
+ c
; t
++)
1223 strv_free(t
->triggered
);
1228 static int compare_unit_file_list(const void *a
, const void *b
) {
1229 const char *d1
, *d2
;
1230 const UnitFileList
*u
= a
, *v
= b
;
1232 d1
= strrchr(u
->path
, '.');
1233 d2
= strrchr(v
->path
, '.');
1238 r
= strcasecmp(d1
, d2
);
1243 return strcasecmp(basename(u
->path
), basename(v
->path
));
1246 static bool output_show_unit_file(const UnitFileList
*u
, char **patterns
) {
1247 if (!strv_fnmatch_or_empty(patterns
, basename(u
->path
), FNM_NOESCAPE
))
1250 if (!strv_isempty(arg_types
)) {
1253 dot
= strrchr(u
->path
, '.');
1257 if (!strv_find(arg_types
, dot
+1))
1261 if (!strv_isempty(arg_states
) &&
1262 !strv_find(arg_states
, unit_file_state_to_string(u
->state
)))
1268 static void output_unit_file_list(const UnitFileList
*units
, unsigned c
) {
1269 unsigned max_id_len
, id_cols
, state_cols
;
1270 const UnitFileList
*u
;
1272 max_id_len
= strlen("UNIT FILE");
1273 state_cols
= strlen("STATE");
1275 for (u
= units
; u
< units
+ c
; u
++) {
1276 max_id_len
= MAX(max_id_len
, strlen(basename(u
->path
)));
1277 state_cols
= MAX(state_cols
, strlen(unit_file_state_to_string(u
->state
)));
1281 unsigned basic_cols
;
1283 id_cols
= MIN(max_id_len
, 25u);
1284 basic_cols
= 1 + id_cols
+ state_cols
;
1285 if (basic_cols
< (unsigned) columns())
1286 id_cols
+= MIN(columns() - basic_cols
, max_id_len
- id_cols
);
1288 id_cols
= max_id_len
;
1291 printf("%-*s %-*s\n",
1292 id_cols
, "UNIT FILE",
1293 state_cols
, "STATE");
1295 for (u
= units
; u
< units
+ c
; u
++) {
1296 _cleanup_free_
char *e
= NULL
;
1297 const char *on
, *off
;
1300 if (u
->state
== UNIT_FILE_MASKED
||
1301 u
->state
== UNIT_FILE_MASKED_RUNTIME
||
1302 u
->state
== UNIT_FILE_DISABLED
||
1303 u
->state
== UNIT_FILE_INVALID
) {
1304 on
= ansi_highlight_red();
1305 off
= ansi_highlight_off();
1306 } else if (u
->state
== UNIT_FILE_ENABLED
) {
1307 on
= ansi_highlight_green();
1308 off
= ansi_highlight_off();
1312 id
= basename(u
->path
);
1314 e
= arg_full
? NULL
: ellipsize(id
, id_cols
, 33);
1316 printf("%-*s %s%-*s%s\n",
1317 id_cols
, e
? e
: id
,
1318 on
, state_cols
, unit_file_state_to_string(u
->state
), off
);
1322 printf("\n%u unit files listed.\n", c
);
1325 static int list_unit_files(sd_bus
*bus
, char **args
) {
1326 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1327 _cleanup_free_ UnitFileList
*units
= NULL
;
1335 pager_open_if_enabled();
1343 h
= hashmap_new(&string_hash_ops
);
1347 r
= unit_file_get_list(arg_scope
, arg_root
, h
);
1349 unit_file_list_free(h
);
1350 log_error_errno(r
, "Failed to get unit file list: %m");
1354 n_units
= hashmap_size(h
);
1356 units
= new(UnitFileList
, n_units
);
1357 if (!units
&& n_units
> 0) {
1358 unit_file_list_free(h
);
1362 HASHMAP_FOREACH(u
, h
, i
) {
1363 if (!output_show_unit_file(u
, strv_skip_first(args
)))
1370 assert(c
<= n_units
);
1373 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1375 r
= sd_bus_call_method(
1377 "org.freedesktop.systemd1",
1378 "/org/freedesktop/systemd1",
1379 "org.freedesktop.systemd1.Manager",
1385 log_error("Failed to list unit files: %s", bus_error_message(&error
, r
));
1389 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
1391 return bus_log_parse_error(r
);
1393 while ((r
= sd_bus_message_read(reply
, "(ss)", &path
, &state
)) > 0) {
1395 if (!GREEDY_REALLOC(units
, size
, c
+ 1))
1398 units
[c
] = (struct UnitFileList
) {
1400 unit_file_state_from_string(state
)
1403 if (output_show_unit_file(&units
[c
], strv_skip_first(args
)))
1408 return bus_log_parse_error(r
);
1410 r
= sd_bus_message_exit_container(reply
);
1412 return bus_log_parse_error(r
);
1415 qsort_safe(units
, c
, sizeof(UnitFileList
), compare_unit_file_list
);
1416 output_unit_file_list(units
, c
);
1419 for (unit
= units
; unit
< units
+ c
; unit
++)
1426 static int list_dependencies_print(const char *name
, int level
, unsigned int branches
, bool last
) {
1427 _cleanup_free_
char *n
= NULL
;
1428 size_t max_len
= MAX(columns(),20u);
1434 for (i
= level
- 1; i
>= 0; i
--) {
1436 if (len
> max_len
- 3 && !arg_full
) {
1437 printf("%s...\n",max_len
% 2 ? "" : " ");
1440 printf("%s", draw_special_char(branches
& (1 << i
) ? DRAW_TREE_VERTICAL
: DRAW_TREE_SPACE
));
1444 if (len
> max_len
- 3 && !arg_full
) {
1445 printf("%s...\n",max_len
% 2 ? "" : " ");
1449 printf("%s", draw_special_char(last
? DRAW_TREE_RIGHT
: DRAW_TREE_BRANCH
));
1453 printf("%s\n", name
);
1457 n
= ellipsize(name
, max_len
-len
, 100);
1465 static int list_dependencies_get_dependencies(sd_bus
*bus
, const char *name
, char ***deps
) {
1467 static const char *dependencies
[_DEPENDENCY_MAX
] = {
1468 [DEPENDENCY_FORWARD
] = "Requires\0"
1469 "RequiresOverridable\0"
1471 "RequisiteOverridable\0"
1474 [DEPENDENCY_REVERSE
] = "RequiredBy\0"
1475 "RequiredByOverridable\0"
1479 [DEPENDENCY_AFTER
] = "After\0",
1480 [DEPENDENCY_BEFORE
] = "Before\0",
1483 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1484 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1485 _cleanup_strv_free_
char **ret
= NULL
;
1486 _cleanup_free_
char *path
= NULL
;
1492 assert_cc(ELEMENTSOF(dependencies
) == _DEPENDENCY_MAX
);
1494 path
= unit_dbus_path_from_name(name
);
1498 r
= sd_bus_call_method(
1500 "org.freedesktop.systemd1",
1502 "org.freedesktop.DBus.Properties",
1506 "s", "org.freedesktop.systemd1.Unit");
1508 log_error("Failed to get properties of %s: %s", name
, bus_error_message(&error
, r
));
1512 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
1514 return bus_log_parse_error(r
);
1516 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
1519 r
= sd_bus_message_read(reply
, "s", &prop
);
1521 return bus_log_parse_error(r
);
1523 if (!nulstr_contains(dependencies
[arg_dependency
], prop
)) {
1524 r
= sd_bus_message_skip(reply
, "v");
1526 return bus_log_parse_error(r
);
1529 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, "as");
1531 return bus_log_parse_error(r
);
1533 r
= bus_message_read_strv_extend(reply
, &ret
);
1535 return bus_log_parse_error(r
);
1537 r
= sd_bus_message_exit_container(reply
);
1539 return bus_log_parse_error(r
);
1542 r
= sd_bus_message_exit_container(reply
);
1544 return bus_log_parse_error(r
);
1548 return bus_log_parse_error(r
);
1550 r
= sd_bus_message_exit_container(reply
);
1552 return bus_log_parse_error(r
);
1560 static int list_dependencies_compare(const void *_a
, const void *_b
) {
1561 const char **a
= (const char**) _a
, **b
= (const char**) _b
;
1563 if (unit_name_to_type(*a
) == UNIT_TARGET
&& unit_name_to_type(*b
) != UNIT_TARGET
)
1565 if (unit_name_to_type(*a
) != UNIT_TARGET
&& unit_name_to_type(*b
) == UNIT_TARGET
)
1568 return strcasecmp(*a
, *b
);
1571 static int list_dependencies_one(
1576 unsigned int branches
) {
1578 _cleanup_strv_free_
char **deps
= NULL
;
1586 r
= strv_extend(units
, name
);
1590 r
= list_dependencies_get_dependencies(bus
, name
, &deps
);
1594 qsort_safe(deps
, strv_length(deps
), sizeof (char*), list_dependencies_compare
);
1596 STRV_FOREACH(c
, deps
) {
1597 if (strv_contains(*units
, *c
)) {
1599 r
= list_dependencies_print("...", level
+ 1, (branches
<< 1) | (c
[1] == NULL
? 0 : 1), 1);
1612 state
= check_one_unit(bus
, *c
, "activating\0active\0reloading\0", true);
1613 on
= state
> 0 ? ansi_highlight_green() : ansi_highlight_red();
1614 printf("%s%s%s ", on
, draw_special_char(DRAW_BLACK_CIRCLE
), ansi_highlight_off());
1617 r
= list_dependencies_print(*c
, level
, branches
, c
[1] == NULL
);
1621 if (arg_all
|| unit_name_to_type(*c
) == UNIT_TARGET
) {
1622 r
= list_dependencies_one(bus
, *c
, level
+ 1, units
, (branches
<< 1) | (c
[1] == NULL
? 0 : 1));
1629 strv_remove(*units
, name
);
1634 static int list_dependencies(sd_bus
*bus
, char **args
) {
1635 _cleanup_strv_free_
char **units
= NULL
;
1636 _cleanup_free_
char *unit
= NULL
;
1642 unit
= unit_name_mangle(args
[1], MANGLE_NOGLOB
);
1647 u
= SPECIAL_DEFAULT_TARGET
;
1649 pager_open_if_enabled();
1653 return list_dependencies_one(bus
, u
, 0, &units
, 0);
1656 struct machine_info
{
1660 char *control_group
;
1661 uint32_t n_failed_units
;
1666 static const struct bus_properties_map machine_info_property_map
[] = {
1667 { "SystemState", "s", NULL
, offsetof(struct machine_info
, state
) },
1668 { "NJobs", "u", NULL
, offsetof(struct machine_info
, n_jobs
) },
1669 { "NFailedUnits", "u", NULL
, offsetof(struct machine_info
, n_failed_units
) },
1670 { "ControlGroup", "s", NULL
, offsetof(struct machine_info
, control_group
) },
1671 { "UserspaceTimestamp", "t", NULL
, offsetof(struct machine_info
, timestamp
) },
1675 static void free_machines_list(struct machine_info
*machine_infos
, int n
) {
1681 for (i
= 0; i
< n
; i
++) {
1682 free(machine_infos
[i
].name
);
1683 free(machine_infos
[i
].state
);
1684 free(machine_infos
[i
].control_group
);
1687 free(machine_infos
);
1690 static int compare_machine_info(const void *a
, const void *b
) {
1691 const struct machine_info
*u
= a
, *v
= b
;
1693 if (u
->is_host
!= v
->is_host
)
1694 return u
->is_host
> v
->is_host
? -1 : 1;
1696 return strcasecmp(u
->name
, v
->name
);
1699 static int get_machine_properties(sd_bus
*bus
, struct machine_info
*mi
) {
1700 _cleanup_bus_close_unref_ sd_bus
*container
= NULL
;
1706 r
= sd_bus_open_system_machine(&container
, mi
->name
);
1713 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, mi
);
1720 static bool output_show_machine(const char *name
, char **patterns
) {
1721 return strv_fnmatch_or_empty(patterns
, name
, FNM_NOESCAPE
);
1724 static int get_machine_list(
1726 struct machine_info
**_machine_infos
,
1729 struct machine_info
*machine_infos
= NULL
;
1730 _cleanup_strv_free_
char **m
= NULL
;
1731 _cleanup_free_
char *hn
= NULL
;
1736 hn
= gethostname_malloc();
1740 if (output_show_machine(hn
, patterns
)) {
1741 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1))
1744 machine_infos
[c
].is_host
= true;
1745 machine_infos
[c
].name
= hn
;
1748 get_machine_properties(bus
, &machine_infos
[c
]);
1752 sd_get_machine_names(&m
);
1753 STRV_FOREACH(i
, m
) {
1754 _cleanup_free_
char *class = NULL
;
1756 if (!output_show_machine(*i
, patterns
))
1759 sd_machine_get_class(*i
, &class);
1760 if (!streq_ptr(class, "container"))
1763 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1)) {
1764 free_machines_list(machine_infos
, c
);
1768 machine_infos
[c
].is_host
= false;
1769 machine_infos
[c
].name
= strdup(*i
);
1770 if (!machine_infos
[c
].name
) {
1771 free_machines_list(machine_infos
, c
);
1775 get_machine_properties(NULL
, &machine_infos
[c
]);
1779 *_machine_infos
= machine_infos
;
1783 static void output_machines_list(struct machine_info
*machine_infos
, unsigned n
) {
1784 struct machine_info
*m
;
1787 namelen
= sizeof("NAME") - 1,
1788 statelen
= sizeof("STATE") - 1,
1789 failedlen
= sizeof("FAILED") - 1,
1790 jobslen
= sizeof("JOBS") - 1;
1792 assert(machine_infos
|| n
== 0);
1794 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
1795 namelen
= MAX(namelen
, strlen(m
->name
) + (m
->is_host
? sizeof(" (host)") - 1 : 0));
1796 statelen
= MAX(statelen
, m
->state
? strlen(m
->state
) : 0);
1797 failedlen
= MAX(failedlen
, DECIMAL_STR_WIDTH(m
->n_failed_units
));
1798 jobslen
= MAX(jobslen
, DECIMAL_STR_WIDTH(m
->n_jobs
));
1800 if (!arg_plain
&& !streq_ptr(m
->state
, "running"))
1804 if (!arg_no_legend
) {
1808 printf("%-*s %-*s %-*s %-*s\n",
1811 failedlen
, "FAILED",
1815 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
1816 const char *on_state
= "", *off_state
= "";
1817 const char *on_failed
= "", *off_failed
= "";
1818 bool circle
= false;
1820 if (streq_ptr(m
->state
, "degraded")) {
1821 on_state
= ansi_highlight_red();
1822 off_state
= ansi_highlight_off();
1824 } else if (!streq_ptr(m
->state
, "running")) {
1825 on_state
= ansi_highlight_yellow();
1826 off_state
= ansi_highlight_off();
1830 if (m
->n_failed_units
> 0) {
1831 on_failed
= ansi_highlight_red();
1832 off_failed
= ansi_highlight_off();
1834 on_failed
= off_failed
= "";
1837 printf("%s%s%s ", on_state
, circle
? draw_special_char(DRAW_BLACK_CIRCLE
) : " ", off_state
);
1840 printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
1841 (int) (namelen
- (sizeof(" (host)")-1)), strna(m
->name
),
1842 on_state
, statelen
, strna(m
->state
), off_state
,
1843 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
1844 jobslen
, m
->n_jobs
);
1846 printf("%-*s %s%-*s%s %s%*u%s %*u\n",
1847 namelen
, strna(m
->name
),
1848 on_state
, statelen
, strna(m
->state
), off_state
,
1849 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
1850 jobslen
, m
->n_jobs
);
1854 printf("\n%u machines listed.\n", n
);
1857 static int list_machines(sd_bus
*bus
, char **args
) {
1858 struct machine_info
*machine_infos
= NULL
;
1863 if (geteuid() != 0) {
1864 log_error("Must be root.");
1868 pager_open_if_enabled();
1870 r
= get_machine_list(bus
, &machine_infos
, strv_skip_first(args
));
1874 qsort_safe(machine_infos
, r
, sizeof(struct machine_info
), compare_machine_info
);
1875 output_machines_list(machine_infos
, r
);
1876 free_machines_list(machine_infos
, r
);
1881 static int get_default(sd_bus
*bus
, char **args
) {
1882 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1883 _cleanup_free_
char *_path
= NULL
;
1887 if (!bus
|| avoid_bus()) {
1888 r
= unit_file_get_default(arg_scope
, arg_root
, &_path
);
1890 return log_error_errno(r
, "Failed to get default target: %m");
1894 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1896 r
= sd_bus_call_method(
1898 "org.freedesktop.systemd1",
1899 "/org/freedesktop/systemd1",
1900 "org.freedesktop.systemd1.Manager",
1906 log_error("Failed to get default target: %s", bus_error_message(&error
, -r
));
1910 r
= sd_bus_message_read(reply
, "s", &path
);
1912 return bus_log_parse_error(r
);
1916 printf("%s\n", path
);
1921 static void dump_unit_file_changes(const UnitFileChange
*changes
, unsigned n_changes
) {
1924 assert(changes
|| n_changes
== 0);
1926 for (i
= 0; i
< n_changes
; i
++) {
1927 if (changes
[i
].type
== UNIT_FILE_SYMLINK
)
1928 log_info("Created symlink from %s to %s.", changes
[i
].path
, changes
[i
].source
);
1930 log_info("Removed symlink %s.", changes
[i
].path
);
1934 static int set_default(sd_bus
*bus
, char **args
) {
1935 _cleanup_free_
char *unit
= NULL
;
1936 UnitFileChange
*changes
= NULL
;
1937 unsigned n_changes
= 0;
1940 unit
= unit_name_mangle_with_suffix(args
[1], MANGLE_NOGLOB
, ".target");
1944 if (!bus
|| avoid_bus()) {
1945 r
= unit_file_set_default(arg_scope
, arg_root
, unit
, true, &changes
, &n_changes
);
1947 return log_error_errno(r
, "Failed to set default target: %m");
1950 dump_unit_file_changes(changes
, n_changes
);
1954 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1955 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1957 polkit_agent_open_if_enabled();
1959 r
= sd_bus_call_method(
1961 "org.freedesktop.systemd1",
1962 "/org/freedesktop/systemd1",
1963 "org.freedesktop.systemd1.Manager",
1969 log_error("Failed to set default target: %s", bus_error_message(&error
, -r
));
1973 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
);
1977 /* Try to reload if enabled */
1979 r
= daemon_reload(bus
, args
);
1984 unit_file_changes_free(changes
, n_changes
);
1991 const char *name
, *type
, *state
;
1994 static void output_jobs_list(const struct job_info
* jobs
, unsigned n
, bool skipped
) {
1995 unsigned id_len
, unit_len
, type_len
, state_len
;
1996 const struct job_info
*j
;
1997 const char *on
, *off
;
1998 bool shorten
= false;
2000 assert(n
== 0 || jobs
);
2003 if (!arg_no_legend
) {
2004 on
= ansi_highlight_green();
2005 off
= ansi_highlight_off();
2007 printf("%sNo jobs %s.%s\n", on
, skipped
? "listed" : "running", off
);
2012 pager_open_if_enabled();
2014 id_len
= strlen("JOB");
2015 unit_len
= strlen("UNIT");
2016 type_len
= strlen("TYPE");
2017 state_len
= strlen("STATE");
2019 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2020 uint32_t id
= j
->id
;
2021 assert(j
->name
&& j
->type
&& j
->state
);
2023 id_len
= MAX(id_len
, DECIMAL_STR_WIDTH(id
));
2024 unit_len
= MAX(unit_len
, strlen(j
->name
));
2025 type_len
= MAX(type_len
, strlen(j
->type
));
2026 state_len
= MAX(state_len
, strlen(j
->state
));
2029 if (!arg_full
&& id_len
+ 1 + unit_len
+ type_len
+ 1 + state_len
> columns()) {
2030 unit_len
= MAX(33u, columns() - id_len
- type_len
- state_len
- 3);
2035 printf("%*s %-*s %-*s %-*s\n",
2039 state_len
, "STATE");
2041 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2042 _cleanup_free_
char *e
= NULL
;
2044 if (streq(j
->state
, "running")) {
2045 on
= ansi_highlight();
2046 off
= ansi_highlight_off();
2050 e
= shorten
? ellipsize(j
->name
, unit_len
, 33) : NULL
;
2051 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2053 on
, unit_len
, e
? e
: j
->name
, off
,
2055 on
, state_len
, j
->state
, off
);
2058 if (!arg_no_legend
) {
2059 on
= ansi_highlight();
2060 off
= ansi_highlight_off();
2062 printf("\n%s%u jobs listed%s.\n", on
, n
, off
);
2066 static bool output_show_job(struct job_info
*job
, char **patterns
) {
2067 return strv_fnmatch_or_empty(patterns
, job
->name
, FNM_NOESCAPE
);
2070 static int list_jobs(sd_bus
*bus
, char **args
) {
2071 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2072 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2073 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2074 _cleanup_free_
struct job_info
*jobs
= NULL
;
2079 bool skipped
= false;
2081 r
= sd_bus_call_method(
2083 "org.freedesktop.systemd1",
2084 "/org/freedesktop/systemd1",
2085 "org.freedesktop.systemd1.Manager",
2091 log_error("Failed to list jobs: %s", bus_error_message(&error
, r
));
2095 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2097 return bus_log_parse_error(r
);
2099 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0) {
2100 struct job_info job
= { id
, name
, type
, state
};
2102 if (!output_show_job(&job
, strv_skip_first(args
))) {
2107 if (!GREEDY_REALLOC(jobs
, size
, c
+ 1))
2113 return bus_log_parse_error(r
);
2115 r
= sd_bus_message_exit_container(reply
);
2117 return bus_log_parse_error(r
);
2119 output_jobs_list(jobs
, c
, skipped
);
2123 static int cancel_job(sd_bus
*bus
, char **args
) {
2129 if (strv_length(args
) <= 1)
2130 return daemon_reload(bus
, args
);
2132 polkit_agent_open_if_enabled();
2134 STRV_FOREACH(name
, args
+1) {
2135 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2139 q
= safe_atou32(*name
, &id
);
2141 return log_error_errno(q
, "Failed to parse job id \"%s\": %m", *name
);
2143 q
= sd_bus_call_method(
2145 "org.freedesktop.systemd1",
2146 "/org/freedesktop/systemd1",
2147 "org.freedesktop.systemd1.Manager",
2153 log_error("Failed to cancel job %"PRIu32
": %s", id
, bus_error_message(&error
, q
));
2162 static int need_daemon_reload(sd_bus
*bus
, const char *unit
) {
2163 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2167 /* We ignore all errors here, since this is used to show a
2170 /* We don't use unit_dbus_path_from_name() directly since we
2171 * don't want to load the unit if it isn't loaded. */
2173 r
= sd_bus_call_method(
2175 "org.freedesktop.systemd1",
2176 "/org/freedesktop/systemd1",
2177 "org.freedesktop.systemd1.Manager",
2185 r
= sd_bus_message_read(reply
, "o", &path
);
2189 r
= sd_bus_get_property_trivial(
2191 "org.freedesktop.systemd1",
2193 "org.freedesktop.systemd1.Unit",
2203 static void warn_unit_file_changed(const char *name
) {
2204 log_warning("%sWarning:%s %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
2205 ansi_highlight_red(),
2206 ansi_highlight_off(),
2208 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user");
2211 static int unit_file_find_path(LookupPaths
*lp
, const char *unit_name
, char **unit_path
) {
2218 STRV_FOREACH(p
, lp
->unit_path
) {
2219 _cleanup_free_
char *path
;
2221 path
= path_join(arg_root
, *p
, unit_name
);
2225 if (access(path
, F_OK
) == 0) {
2235 static int unit_find_paths(
2237 const char *unit_name
,
2238 bool avoid_bus_cache
,
2240 char **fragment_path
,
2241 char ***dropin_paths
) {
2243 _cleanup_free_
char *path
= NULL
;
2244 _cleanup_strv_free_
char **dropins
= NULL
;
2248 * Finds where the unit is defined on disk. Returns 0 if the unit
2249 * is not found. Returns 1 if it is found, and sets
2250 * - the path to the unit in *path, if it exists on disk,
2251 * - and a strv of existing drop-ins in *dropins,
2252 * if the arg is not NULL and any dropins were found.
2256 assert(fragment_path
);
2259 if (!avoid_bus_cache
&& !unit_name_is_template(unit_name
)) {
2260 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2261 _cleanup_bus_message_unref_ sd_bus_message
*unit_load_error
= NULL
;
2262 _cleanup_free_
char *unit
= NULL
;
2263 char *unit_load_error_name
, *unit_load_error_message
;
2265 unit
= unit_dbus_path_from_name(unit_name
);
2269 if (need_daemon_reload(bus
, unit_name
) > 0)
2270 warn_unit_file_changed(unit_name
);
2272 r
= sd_bus_get_property(
2274 "org.freedesktop.systemd1",
2276 "org.freedesktop.systemd1.Unit",
2282 return log_error_errno(r
, "Failed to get LoadError: %s", bus_error_message(&error
, r
));
2284 r
= sd_bus_message_read(
2287 &unit_load_error_name
,
2288 &unit_load_error_message
);
2290 return bus_log_parse_error(r
);
2292 if (!isempty(unit_load_error_name
)) {
2293 log_error("Unit %s is not loaded: %s", unit_name
, unit_load_error_message
);
2297 r
= sd_bus_get_property_string(
2299 "org.freedesktop.systemd1",
2301 "org.freedesktop.systemd1.Unit",
2306 return log_error_errno(r
, "Failed to get FragmentPath: %s", bus_error_message(&error
, r
));
2309 r
= sd_bus_get_property_strv(
2311 "org.freedesktop.systemd1",
2313 "org.freedesktop.systemd1.Unit",
2318 return log_error_errno(r
, "Failed to get DropInPaths: %s", bus_error_message(&error
, r
));
2321 _cleanup_set_free_ Set
*names
;
2323 names
= set_new(NULL
);
2327 r
= set_put(names
, unit_name
);
2331 r
= unit_file_find_path(lp
, unit_name
, &path
);
2336 _cleanup_free_
char *template;
2338 template = unit_name_template(unit_name
);
2342 if (!streq(template, unit_name
)) {
2343 r
= unit_file_find_path(lp
, template, &path
);
2350 r
= unit_file_find_dropin_paths(lp
->unit_path
, NULL
, names
, &dropins
);
2358 if (!isempty(path
)) {
2359 *fragment_path
= path
;
2364 if (dropin_paths
&& !strv_isempty(dropins
)) {
2365 *dropin_paths
= dropins
;
2371 log_error("No files found for %s.", unit_name
);
2376 static int check_one_unit(sd_bus
*bus
, const char *name
, const char *good_states
, bool quiet
) {
2377 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2378 _cleanup_free_
char *n
= NULL
, *state
= NULL
;
2384 n
= unit_name_mangle(name
, MANGLE_NOGLOB
);
2388 /* We don't use unit_dbus_path_from_name() directly since we
2389 * don't want to load the unit if it isn't loaded. */
2391 r
= sd_bus_call_method(
2393 "org.freedesktop.systemd1",
2394 "/org/freedesktop/systemd1",
2395 "org.freedesktop.systemd1.Manager",
2406 r
= sd_bus_message_read(reply
, "o", &path
);
2408 return bus_log_parse_error(r
);
2410 r
= sd_bus_get_property_string(
2412 "org.freedesktop.systemd1",
2414 "org.freedesktop.systemd1.Unit",
2427 return nulstr_contains(good_states
, state
);
2430 static int check_triggering_units(
2434 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2435 _cleanup_free_
char *path
= NULL
, *n
= NULL
, *state
= NULL
;
2436 _cleanup_strv_free_
char **triggered_by
= NULL
;
2437 bool print_warning_label
= true;
2441 n
= unit_name_mangle(name
, MANGLE_NOGLOB
);
2445 path
= unit_dbus_path_from_name(n
);
2449 r
= sd_bus_get_property_string(
2451 "org.freedesktop.systemd1",
2453 "org.freedesktop.systemd1.Unit",
2458 log_error("Failed to get load state of %s: %s", n
, bus_error_message(&error
, r
));
2462 if (streq(state
, "masked"))
2465 r
= sd_bus_get_property_strv(
2467 "org.freedesktop.systemd1",
2469 "org.freedesktop.systemd1.Unit",
2474 log_error("Failed to get triggered by array of %s: %s", n
, bus_error_message(&error
, r
));
2478 STRV_FOREACH(i
, triggered_by
) {
2479 r
= check_one_unit(bus
, *i
, "active\0reloading\0", true);
2481 return log_error_errno(r
, "Failed to check unit: %m");
2486 if (print_warning_label
) {
2487 log_warning("Warning: Stopping %s, but it can still be activated by:", n
);
2488 print_warning_label
= false;
2491 log_warning(" %s", *i
);
2497 static const struct {
2500 } unit_actions
[] = {
2501 { "start", "StartUnit" },
2502 { "stop", "StopUnit" },
2503 { "condstop", "StopUnit" },
2504 { "reload", "ReloadUnit" },
2505 { "restart", "RestartUnit" },
2506 { "try-restart", "TryRestartUnit" },
2507 { "condrestart", "TryRestartUnit" },
2508 { "reload-or-restart", "ReloadOrRestartUnit" },
2509 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2510 { "condreload", "ReloadOrTryRestartUnit" },
2511 { "force-reload", "ReloadOrTryRestartUnit" }
2514 static const char *verb_to_method(const char *verb
) {
2517 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2518 if (streq_ptr(unit_actions
[i
].verb
, verb
))
2519 return unit_actions
[i
].method
;
2524 static const char *method_to_verb(const char *method
) {
2527 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2528 if (streq_ptr(unit_actions
[i
].method
, method
))
2529 return unit_actions
[i
].verb
;
2534 static int start_unit_one(
2539 sd_bus_error
*error
,
2540 BusWaitForJobs
*w
) {
2542 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2551 log_debug("Calling manager for %s on %s, %s", method
, name
, mode
);
2553 r
= sd_bus_call_method(
2555 "org.freedesktop.systemd1",
2556 "/org/freedesktop/systemd1",
2557 "org.freedesktop.systemd1.Manager",
2565 if (r
== -ENOENT
&& arg_action
!= ACTION_SYSTEMCTL
)
2566 /* There's always a fallback possible for
2567 * legacy actions. */
2568 return -EADDRNOTAVAIL
;
2570 verb
= method_to_verb(method
);
2572 log_error("Failed to %s %s: %s", verb
, name
, bus_error_message(error
, r
));
2576 r
= sd_bus_message_read(reply
, "o", &path
);
2578 return bus_log_parse_error(r
);
2580 if (need_daemon_reload(bus
, name
) > 0)
2581 warn_unit_file_changed(name
);
2584 log_debug("Adding %s to the set", path
);
2585 r
= bus_wait_for_jobs_add(w
, path
);
2593 static int expand_names(sd_bus
*bus
, char **names
, const char* suffix
, char ***ret
) {
2595 _cleanup_strv_free_
char **mangled
= NULL
, **globs
= NULL
;
2599 STRV_FOREACH(name
, names
) {
2603 t
= unit_name_mangle_with_suffix(*name
, MANGLE_GLOB
, suffix
);
2605 t
= unit_name_mangle(*name
, MANGLE_GLOB
);
2609 if (string_is_glob(t
))
2610 r
= strv_consume(&globs
, t
);
2612 r
= strv_consume(&mangled
, t
);
2617 /* Query the manager only if any of the names are a glob, since
2618 * this is fairly expensive */
2619 if (!strv_isempty(globs
)) {
2620 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2621 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
2624 return log_error_errno(EOPNOTSUPP
, "Unit name globbing without bus is not implemented.");
2626 r
= get_unit_list(bus
, NULL
, globs
, &unit_infos
, 0, &reply
);
2630 for (i
= 0; i
< r
; i
++)
2631 if (strv_extend(&mangled
, unit_infos
[i
].id
) < 0)
2636 mangled
= NULL
; /* do not free */
2641 static const struct {
2645 } action_table
[_ACTION_MAX
] = {
2646 [ACTION_HALT
] = { SPECIAL_HALT_TARGET
, "halt", "replace-irreversibly" },
2647 [ACTION_POWEROFF
] = { SPECIAL_POWEROFF_TARGET
, "poweroff", "replace-irreversibly" },
2648 [ACTION_REBOOT
] = { SPECIAL_REBOOT_TARGET
, "reboot", "replace-irreversibly" },
2649 [ACTION_KEXEC
] = { SPECIAL_KEXEC_TARGET
, "kexec", "replace-irreversibly" },
2650 [ACTION_RUNLEVEL2
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2651 [ACTION_RUNLEVEL3
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2652 [ACTION_RUNLEVEL4
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2653 [ACTION_RUNLEVEL5
] = { SPECIAL_GRAPHICAL_TARGET
, NULL
, "isolate" },
2654 [ACTION_RESCUE
] = { SPECIAL_RESCUE_TARGET
, "rescue", "isolate" },
2655 [ACTION_EMERGENCY
] = { SPECIAL_EMERGENCY_TARGET
, "emergency", "isolate" },
2656 [ACTION_DEFAULT
] = { SPECIAL_DEFAULT_TARGET
, "default", "isolate" },
2657 [ACTION_EXIT
] = { SPECIAL_EXIT_TARGET
, "exit", "replace-irreversibly" },
2658 [ACTION_SUSPEND
] = { SPECIAL_SUSPEND_TARGET
, "suspend", "replace-irreversibly" },
2659 [ACTION_HIBERNATE
] = { SPECIAL_HIBERNATE_TARGET
, "hibernate", "replace-irreversibly" },
2660 [ACTION_HYBRID_SLEEP
] = { SPECIAL_HYBRID_SLEEP_TARGET
, "hybrid-sleep", "replace-irreversibly" },
2663 static enum action
verb_to_action(const char *verb
) {
2666 for (i
= _ACTION_INVALID
; i
< _ACTION_MAX
; i
++)
2667 if (streq_ptr(action_table
[i
].verb
, verb
))
2670 return _ACTION_INVALID
;
2673 static int start_unit(sd_bus
*bus
, char **args
) {
2674 _cleanup_(bus_wait_for_jobs_freep
) BusWaitForJobs
*w
= NULL
;
2675 const char *method
, *mode
, *one_name
, *suffix
= NULL
;
2676 _cleanup_strv_free_
char **names
= NULL
;
2682 ask_password_agent_open_if_enabled();
2683 polkit_agent_open_if_enabled();
2685 if (arg_action
== ACTION_SYSTEMCTL
) {
2687 method
= verb_to_method(args
[0]);
2688 action
= verb_to_action(args
[0]);
2690 if (streq(args
[0], "isolate")) {
2694 mode
= action_table
[action
].mode
?: arg_job_mode
;
2696 one_name
= action_table
[action
].target
;
2698 assert(arg_action
< ELEMENTSOF(action_table
));
2699 assert(action_table
[arg_action
].target
);
2701 method
= "StartUnit";
2703 mode
= action_table
[arg_action
].mode
;
2704 one_name
= action_table
[arg_action
].target
;
2708 names
= strv_new(one_name
, NULL
);
2710 r
= expand_names(bus
, args
+ 1, suffix
, &names
);
2712 log_error_errno(r
, "Failed to expand names: %m");
2715 if (!arg_no_block
) {
2716 r
= bus_wait_for_jobs_new(bus
, &w
);
2718 return log_error_errno(r
, "Could not watch jobs: %m");
2721 STRV_FOREACH(name
, names
) {
2722 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2725 q
= start_unit_one(bus
, method
, *name
, mode
, &error
, w
);
2726 if (r
>= 0 && q
< 0)
2727 r
= translate_bus_error_to_exit_status(q
, &error
);
2730 if (!arg_no_block
) {
2733 q
= bus_wait_for_jobs(w
, arg_quiet
);
2737 /* When stopping units, warn if they can still be triggered by
2738 * another active unit (socket, path, timer) */
2739 if (!arg_quiet
&& streq(method
, "StopUnit"))
2740 STRV_FOREACH(name
, names
)
2741 check_triggering_units(bus
, *name
);
2747 /* Ask systemd-logind, which might grant access to unprivileged users
2748 * through PolicyKit */
2749 static int reboot_with_logind(sd_bus
*bus
, enum action a
) {
2751 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2758 polkit_agent_open_if_enabled();
2766 case ACTION_POWEROFF
:
2767 method
= "PowerOff";
2770 case ACTION_SUSPEND
:
2774 case ACTION_HIBERNATE
:
2775 method
= "Hibernate";
2778 case ACTION_HYBRID_SLEEP
:
2779 method
= "HybridSleep";
2786 r
= sd_bus_call_method(
2788 "org.freedesktop.login1",
2789 "/org/freedesktop/login1",
2790 "org.freedesktop.login1.Manager",
2794 "b", arg_ask_password
);
2796 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
2804 static int check_inhibitors(sd_bus
*bus
, enum action a
) {
2806 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2807 _cleanup_strv_free_
char **sessions
= NULL
;
2808 const char *what
, *who
, *why
, *mode
;
2817 if (arg_ignore_inhibitors
|| arg_force
> 0)
2829 r
= sd_bus_call_method(
2831 "org.freedesktop.login1",
2832 "/org/freedesktop/login1",
2833 "org.freedesktop.login1.Manager",
2839 /* If logind is not around, then there are no inhibitors... */
2842 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssuu)");
2844 return bus_log_parse_error(r
);
2846 while ((r
= sd_bus_message_read(reply
, "(ssssuu)", &what
, &who
, &why
, &mode
, &uid
, &pid
)) > 0) {
2847 _cleanup_free_
char *comm
= NULL
, *user
= NULL
;
2848 _cleanup_strv_free_
char **sv
= NULL
;
2850 if (!streq(mode
, "block"))
2853 sv
= strv_split(what
, ":");
2857 if ((pid_t
) pid
< 0)
2858 return log_error_errno(ERANGE
, "Bad PID %"PRIu32
": %m", pid
);
2860 if (!strv_contains(sv
,
2862 a
== ACTION_POWEROFF
||
2863 a
== ACTION_REBOOT
||
2864 a
== ACTION_KEXEC
? "shutdown" : "sleep"))
2867 get_process_comm(pid
, &comm
);
2868 user
= uid_to_name(uid
);
2870 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT
" \"%s\", user %s), reason is \"%s\".",
2871 who
, (pid_t
) pid
, strna(comm
), strna(user
), why
);
2876 return bus_log_parse_error(r
);
2878 r
= sd_bus_message_exit_container(reply
);
2880 return bus_log_parse_error(r
);
2882 /* Check for current sessions */
2883 sd_get_sessions(&sessions
);
2884 STRV_FOREACH(s
, sessions
) {
2885 _cleanup_free_
char *type
= NULL
, *tty
= NULL
, *seat
= NULL
, *user
= NULL
, *service
= NULL
, *class = NULL
;
2887 if (sd_session_get_uid(*s
, &uid
) < 0 || uid
== getuid())
2890 if (sd_session_get_class(*s
, &class) < 0 || !streq(class, "user"))
2893 if (sd_session_get_type(*s
, &type
) < 0 || (!streq(type
, "x11") && !streq(type
, "tty")))
2896 sd_session_get_tty(*s
, &tty
);
2897 sd_session_get_seat(*s
, &seat
);
2898 sd_session_get_service(*s
, &service
);
2899 user
= uid_to_name(uid
);
2901 log_warning("User %s is logged in on %s.", strna(user
), isempty(tty
) ? (isempty(seat
) ? strna(service
) : seat
) : tty
);
2908 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2909 action_table
[a
].verb
);
2917 static int prepare_firmware_setup(sd_bus
*bus
) {
2919 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2923 if (!arg_firmware_setup
)
2926 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
2928 r
= efi_set_reboot_to_firmware(true);
2930 log_debug_errno(r
, "Cannot indicate to EFI to boot into setup mode, will retry via logind: %m");
2936 r
= sd_bus_call_method(
2938 "org.freedesktop.login1",
2939 "/org/freedesktop/login1",
2940 "org.freedesktop.login1.Manager",
2941 "SetRebootToFirmwareSetup",
2946 log_error("Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error
, r
));
2952 log_error("Cannot remotely indicate to EFI to boot into setup mode.");
2957 static int start_special(sd_bus
*bus
, char **args
) {
2963 a
= verb_to_action(args
[0]);
2965 r
= check_inhibitors(bus
, a
);
2969 if (arg_force
>= 2 && geteuid() != 0) {
2970 log_error("Must be root.");
2974 r
= prepare_firmware_setup(bus
);
2978 if (a
== ACTION_REBOOT
&& args
[1]) {
2979 r
= update_reboot_param_file(args
[1]);
2984 if (arg_force
>= 2 &&
2985 (a
== ACTION_HALT
||
2986 a
== ACTION_POWEROFF
||
2987 a
== ACTION_REBOOT
))
2990 if (arg_force
>= 1 &&
2991 (a
== ACTION_HALT
||
2992 a
== ACTION_POWEROFF
||
2993 a
== ACTION_REBOOT
||
2994 a
== ACTION_KEXEC
||
2996 return daemon_reload(bus
, args
);
2998 /* first try logind, to allow authentication with polkit */
2999 if (geteuid() != 0 &&
3000 (a
== ACTION_POWEROFF
||
3001 a
== ACTION_REBOOT
||
3002 a
== ACTION_SUSPEND
||
3003 a
== ACTION_HIBERNATE
||
3004 a
== ACTION_HYBRID_SLEEP
)) {
3005 r
= reboot_with_logind(bus
, a
);
3006 if (r
>= 0 || IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
3010 r
= start_unit(bus
, args
);
3011 if (r
== EXIT_SUCCESS
)
3017 static int check_unit_generic(sd_bus
*bus
, int code
, const char *good_states
, char **args
) {
3018 _cleanup_strv_free_
char **names
= NULL
;
3025 r
= expand_names(bus
, args
, NULL
, &names
);
3027 return log_error_errno(r
, "Failed to expand names: %m");
3029 STRV_FOREACH(name
, names
) {
3032 state
= check_one_unit(bus
, *name
, good_states
, arg_quiet
);
3042 static int check_unit_active(sd_bus
*bus
, char **args
) {
3043 /* According to LSB: 3, "program is not running" */
3044 return check_unit_generic(bus
, 3, "active\0reloading\0", args
+ 1);
3047 static int check_unit_failed(sd_bus
*bus
, char **args
) {
3048 return check_unit_generic(bus
, 1, "failed\0", args
+ 1);
3051 static int kill_unit(sd_bus
*bus
, char **args
) {
3052 _cleanup_strv_free_
char **names
= NULL
;
3059 polkit_agent_open_if_enabled();
3062 arg_kill_who
= "all";
3064 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
3066 log_error_errno(r
, "Failed to expand names: %m");
3068 STRV_FOREACH(name
, names
) {
3069 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
3071 q
= sd_bus_call_method(
3073 "org.freedesktop.systemd1",
3074 "/org/freedesktop/systemd1",
3075 "org.freedesktop.systemd1.Manager",
3079 "ssi", *names
, arg_kill_who
, arg_signal
);
3081 log_error("Failed to kill unit %s: %s", *names
, bus_error_message(&error
, q
));
3090 typedef struct ExecStatusInfo
{
3098 usec_t start_timestamp
;
3099 usec_t exit_timestamp
;
3104 LIST_FIELDS(struct ExecStatusInfo
, exec
);
3107 static void exec_status_info_free(ExecStatusInfo
*i
) {
3116 static int exec_status_info_deserialize(sd_bus_message
*m
, ExecStatusInfo
*i
) {
3117 uint64_t start_timestamp
, exit_timestamp
, start_timestamp_monotonic
, exit_timestamp_monotonic
;
3120 int32_t code
, status
;
3126 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_STRUCT
, "sasbttttuii");
3128 return bus_log_parse_error(r
);
3132 r
= sd_bus_message_read(m
, "s", &path
);
3134 return bus_log_parse_error(r
);
3136 i
->path
= strdup(path
);
3140 r
= sd_bus_message_read_strv(m
, &i
->argv
);
3142 return bus_log_parse_error(r
);
3144 r
= sd_bus_message_read(m
,
3147 &start_timestamp
, &start_timestamp_monotonic
,
3148 &exit_timestamp
, &exit_timestamp_monotonic
,
3152 return bus_log_parse_error(r
);
3155 i
->start_timestamp
= (usec_t
) start_timestamp
;
3156 i
->exit_timestamp
= (usec_t
) exit_timestamp
;
3157 i
->pid
= (pid_t
) pid
;
3161 r
= sd_bus_message_exit_container(m
);
3163 return bus_log_parse_error(r
);
3168 typedef struct UnitStatusInfo
{
3170 const char *load_state
;
3171 const char *active_state
;
3172 const char *sub_state
;
3173 const char *unit_file_state
;
3174 const char *unit_file_preset
;
3176 const char *description
;
3177 const char *following
;
3179 char **documentation
;
3181 const char *fragment_path
;
3182 const char *source_path
;
3183 const char *control_group
;
3185 char **dropin_paths
;
3187 const char *load_error
;
3190 usec_t inactive_exit_timestamp
;
3191 usec_t inactive_exit_timestamp_monotonic
;
3192 usec_t active_enter_timestamp
;
3193 usec_t active_exit_timestamp
;
3194 usec_t inactive_enter_timestamp
;
3196 bool need_daemon_reload
;
3201 const char *status_text
;
3202 const char *pid_file
;
3206 usec_t start_timestamp
;
3207 usec_t exit_timestamp
;
3209 int exit_code
, exit_status
;
3211 usec_t condition_timestamp
;
3212 bool condition_result
;
3213 bool failed_condition_trigger
;
3214 bool failed_condition_negate
;
3215 const char *failed_condition
;
3216 const char *failed_condition_parameter
;
3218 usec_t assert_timestamp
;
3220 bool failed_assert_trigger
;
3221 bool failed_assert_negate
;
3222 const char *failed_assert
;
3223 const char *failed_assert_parameter
;
3226 unsigned n_accepted
;
3227 unsigned n_connections
;
3230 /* Pairs of type, path */
3234 const char *sysfs_path
;
3236 /* Mount, Automount */
3243 uint64_t memory_current
;
3244 uint64_t memory_limit
;
3245 uint64_t cpu_usage_nsec
;
3247 LIST_HEAD(ExecStatusInfo
, exec
);
3250 static void print_status_info(
3255 const char *active_on
, *active_off
, *on
, *off
, *ss
;
3257 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], *s1
;
3258 char since2
[FORMAT_TIMESTAMP_MAX
], *s2
;
3264 /* This shows pretty information about a unit. See
3265 * print_property() for a low-level property printer */
3267 if (streq_ptr(i
->active_state
, "failed")) {
3268 active_on
= ansi_highlight_red();
3269 active_off
= ansi_highlight_off();
3270 } else if (streq_ptr(i
->active_state
, "active") || streq_ptr(i
->active_state
, "reloading")) {
3271 active_on
= ansi_highlight_green();
3272 active_off
= ansi_highlight_off();
3274 active_on
= active_off
= "";
3276 printf("%s%s%s %s", active_on
, draw_special_char(DRAW_BLACK_CIRCLE
), active_off
, strna(i
->id
));
3278 if (i
->description
&& !streq_ptr(i
->id
, i
->description
))
3279 printf(" - %s", i
->description
);
3284 printf(" Follow: unit currently follows state of %s\n", i
->following
);
3286 if (streq_ptr(i
->load_state
, "error")) {
3287 on
= ansi_highlight_red();
3288 off
= ansi_highlight_off();
3292 path
= i
->source_path
? i
->source_path
: i
->fragment_path
;
3295 printf(" Loaded: %s%s%s (Reason: %s)\n",
3296 on
, strna(i
->load_state
), off
, i
->load_error
);
3297 else if (path
&& !isempty(i
->unit_file_state
) && !isempty(i
->unit_file_preset
))
3298 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
3299 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
, i
->unit_file_preset
);
3300 else if (path
&& !isempty(i
->unit_file_state
))
3301 printf(" Loaded: %s%s%s (%s; %s)\n",
3302 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
);
3304 printf(" Loaded: %s%s%s (%s)\n",
3305 on
, strna(i
->load_state
), off
, path
);
3307 printf(" Loaded: %s%s%s\n",
3308 on
, strna(i
->load_state
), off
);
3310 if (!strv_isempty(i
->dropin_paths
)) {
3311 _cleanup_free_
char *dir
= NULL
;
3315 STRV_FOREACH(dropin
, i
->dropin_paths
) {
3316 if (! dir
|| last
) {
3317 printf(dir
? " " : " Drop-In: ");
3322 if (path_get_parent(*dropin
, &dir
) < 0) {
3327 printf("%s\n %s", dir
,
3328 draw_special_char(DRAW_TREE_RIGHT
));
3331 last
= ! (*(dropin
+ 1) && startswith(*(dropin
+ 1), dir
));
3333 printf("%s%s", basename(*dropin
), last
? "\n" : ", ");
3337 ss
= streq_ptr(i
->active_state
, i
->sub_state
) ? NULL
: i
->sub_state
;
3339 printf(" Active: %s%s (%s)%s",
3340 active_on
, strna(i
->active_state
), ss
, active_off
);
3342 printf(" Active: %s%s%s",
3343 active_on
, strna(i
->active_state
), active_off
);
3345 if (!isempty(i
->result
) && !streq(i
->result
, "success"))
3346 printf(" (Result: %s)", i
->result
);
3348 timestamp
= (streq_ptr(i
->active_state
, "active") ||
3349 streq_ptr(i
->active_state
, "reloading")) ? i
->active_enter_timestamp
:
3350 (streq_ptr(i
->active_state
, "inactive") ||
3351 streq_ptr(i
->active_state
, "failed")) ? i
->inactive_enter_timestamp
:
3352 streq_ptr(i
->active_state
, "activating") ? i
->inactive_exit_timestamp
:
3353 i
->active_exit_timestamp
;
3355 s1
= format_timestamp_relative(since1
, sizeof(since1
), timestamp
);
3356 s2
= format_timestamp(since2
, sizeof(since2
), timestamp
);
3359 printf(" since %s; %s\n", s2
, s1
);
3361 printf(" since %s\n", s2
);
3365 if (!i
->condition_result
&& i
->condition_timestamp
> 0) {
3366 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->condition_timestamp
);
3367 s2
= format_timestamp(since2
, sizeof(since2
), i
->condition_timestamp
);
3369 printf("Condition: start %scondition failed%s at %s%s%s\n",
3370 ansi_highlight_yellow(), ansi_highlight_off(),
3371 s2
, s1
? "; " : "", s1
? s1
: "");
3372 if (i
->failed_condition_trigger
)
3373 printf(" none of the trigger conditions were met\n");
3374 else if (i
->failed_condition
)
3375 printf(" %s=%s%s was not met\n",
3376 i
->failed_condition
,
3377 i
->failed_condition_negate
? "!" : "",
3378 i
->failed_condition_parameter
);
3381 if (!i
->assert_result
&& i
->assert_timestamp
> 0) {
3382 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->assert_timestamp
);
3383 s2
= format_timestamp(since2
, sizeof(since2
), i
->assert_timestamp
);
3385 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
3386 ansi_highlight_red(), ansi_highlight_off(),
3387 s2
, s1
? "; " : "", s1
? s1
: "");
3388 if (i
->failed_assert_trigger
)
3389 printf(" none of the trigger assertions were met\n");
3390 else if (i
->failed_assert
)
3391 printf(" %s=%s%s was not met\n",
3393 i
->failed_assert_negate
? "!" : "",
3394 i
->failed_assert_parameter
);
3398 printf(" Device: %s\n", i
->sysfs_path
);
3400 printf(" Where: %s\n", i
->where
);
3402 printf(" What: %s\n", i
->what
);
3404 STRV_FOREACH(t
, i
->documentation
)
3405 printf(" %*s %s\n", 9, t
== i
->documentation
? "Docs:" : "", *t
);
3407 STRV_FOREACH_PAIR(t
, t2
, i
->listen
)
3408 printf(" %*s %s (%s)\n", 9, t
== i
->listen
? "Listen:" : "", *t2
, *t
);
3411 printf(" Accepted: %u; Connected: %u\n", i
->n_accepted
, i
->n_connections
);
3413 LIST_FOREACH(exec
, p
, i
->exec
) {
3414 _cleanup_free_
char *argv
= NULL
;
3417 /* Only show exited processes here */
3421 argv
= strv_join(p
->argv
, " ");
3422 printf(" Process: "PID_FMT
" %s=%s ", p
->pid
, p
->name
, strna(argv
));
3424 good
= is_clean_exit_lsb(p
->code
, p
->status
, NULL
);
3426 on
= ansi_highlight_red();
3427 off
= ansi_highlight_off();
3431 printf("%s(code=%s, ", on
, sigchld_code_to_string(p
->code
));
3433 if (p
->code
== CLD_EXITED
) {
3436 printf("status=%i", p
->status
);
3438 c
= exit_status_to_string(p
->status
, EXIT_STATUS_SYSTEMD
);
3443 printf("signal=%s", signal_to_string(p
->status
));
3445 printf(")%s\n", off
);
3447 if (i
->main_pid
== p
->pid
&&
3448 i
->start_timestamp
== p
->start_timestamp
&&
3449 i
->exit_timestamp
== p
->start_timestamp
)
3450 /* Let's not show this twice */
3453 if (p
->pid
== i
->control_pid
)
3457 if (i
->main_pid
> 0 || i
->control_pid
> 0) {
3458 if (i
->main_pid
> 0) {
3459 printf(" Main PID: "PID_FMT
, i
->main_pid
);
3462 _cleanup_free_
char *comm
= NULL
;
3463 get_process_comm(i
->main_pid
, &comm
);
3465 printf(" (%s)", comm
);
3466 } else if (i
->exit_code
> 0) {
3467 printf(" (code=%s, ", sigchld_code_to_string(i
->exit_code
));
3469 if (i
->exit_code
== CLD_EXITED
) {
3472 printf("status=%i", i
->exit_status
);
3474 c
= exit_status_to_string(i
->exit_status
, EXIT_STATUS_SYSTEMD
);
3479 printf("signal=%s", signal_to_string(i
->exit_status
));
3483 if (i
->control_pid
> 0)
3487 if (i
->control_pid
> 0) {
3488 _cleanup_free_
char *c
= NULL
;
3490 printf(" %8s: "PID_FMT
, i
->main_pid
? "" : " Control", i
->control_pid
);
3492 get_process_comm(i
->control_pid
, &c
);
3501 printf(" Status: \"%s\"\n", i
->status_text
);
3502 if (i
->status_errno
> 0)
3503 printf(" Error: %i (%s)\n", i
->status_errno
, strerror(i
->status_errno
));
3505 if (i
->memory_current
!= (uint64_t) -1) {
3506 char buf
[FORMAT_BYTES_MAX
];
3508 printf(" Memory: %s", format_bytes(buf
, sizeof(buf
), i
->memory_current
));
3510 if (i
->memory_limit
!= (uint64_t) -1)
3511 printf(" (limit: %s)\n", format_bytes(buf
, sizeof(buf
), i
->memory_limit
));
3516 if (i
->cpu_usage_nsec
!= (uint64_t) -1) {
3517 char buf
[FORMAT_TIMESPAN_MAX
];
3518 printf(" CPU: %s\n", format_timespan(buf
, sizeof(buf
), i
->cpu_usage_nsec
/ NSEC_PER_USEC
, USEC_PER_MSEC
));
3521 if (i
->control_group
&&
3522 (i
->main_pid
> 0 || i
->control_pid
> 0 ||
3523 ((arg_transport
!= BUS_TRANSPORT_LOCAL
&& arg_transport
!= BUS_TRANSPORT_MACHINE
) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, false) == 0))) {
3526 printf(" CGroup: %s\n", i
->control_group
);
3528 if (arg_transport
== BUS_TRANSPORT_LOCAL
|| arg_transport
== BUS_TRANSPORT_MACHINE
) {
3531 static const char prefix
[] = " ";
3534 if (c
> sizeof(prefix
) - 1)
3535 c
-= sizeof(prefix
) - 1;
3539 if (i
->main_pid
> 0)
3540 extra
[k
++] = i
->main_pid
;
3542 if (i
->control_pid
> 0)
3543 extra
[k
++] = i
->control_pid
;
3545 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, prefix
, c
, false, extra
, k
, get_output_flags());
3549 if (i
->id
&& arg_transport
== BUS_TRANSPORT_LOCAL
) {
3550 show_journal_by_unit(
3555 i
->inactive_exit_timestamp_monotonic
,
3558 get_output_flags() | OUTPUT_BEGIN_NEWLINE
,
3559 SD_JOURNAL_LOCAL_ONLY
,
3560 arg_scope
== UNIT_FILE_SYSTEM
,
3564 if (i
->need_daemon_reload
)
3565 warn_unit_file_changed(i
->id
);
3568 static void show_unit_help(UnitStatusInfo
*i
) {
3573 if (!i
->documentation
) {
3574 log_info("Documentation for %s not known.", i
->id
);
3578 STRV_FOREACH(p
, i
->documentation
)
3579 if (startswith(*p
, "man:"))
3580 show_man_page(*p
+ 4, false);
3582 log_info("Can't show: %s", *p
);
3585 static int status_property(const char *name
, sd_bus_message
*m
, UnitStatusInfo
*i
, const char *contents
) {
3592 switch (contents
[0]) {
3594 case SD_BUS_TYPE_STRING
: {
3597 r
= sd_bus_message_read(m
, "s", &s
);
3599 return bus_log_parse_error(r
);
3602 if (streq(name
, "Id"))
3604 else if (streq(name
, "LoadState"))
3606 else if (streq(name
, "ActiveState"))
3607 i
->active_state
= s
;
3608 else if (streq(name
, "SubState"))
3610 else if (streq(name
, "Description"))
3612 else if (streq(name
, "FragmentPath"))
3613 i
->fragment_path
= s
;
3614 else if (streq(name
, "SourcePath"))
3617 else if (streq(name
, "DefaultControlGroup")) {
3619 e
= startswith(s
, SYSTEMD_CGROUP_CONTROLLER
":");
3621 i
->control_group
= e
;
3624 else if (streq(name
, "ControlGroup"))
3625 i
->control_group
= s
;
3626 else if (streq(name
, "StatusText"))
3628 else if (streq(name
, "PIDFile"))
3630 else if (streq(name
, "SysFSPath"))
3632 else if (streq(name
, "Where"))
3634 else if (streq(name
, "What"))
3636 else if (streq(name
, "Following"))
3638 else if (streq(name
, "UnitFileState"))
3639 i
->unit_file_state
= s
;
3640 else if (streq(name
, "UnitFilePreset"))
3641 i
->unit_file_preset
= s
;
3642 else if (streq(name
, "Result"))
3649 case SD_BUS_TYPE_BOOLEAN
: {
3652 r
= sd_bus_message_read(m
, "b", &b
);
3654 return bus_log_parse_error(r
);
3656 if (streq(name
, "Accept"))
3658 else if (streq(name
, "NeedDaemonReload"))
3659 i
->need_daemon_reload
= b
;
3660 else if (streq(name
, "ConditionResult"))
3661 i
->condition_result
= b
;
3662 else if (streq(name
, "AssertResult"))
3663 i
->assert_result
= b
;
3668 case SD_BUS_TYPE_UINT32
: {
3671 r
= sd_bus_message_read(m
, "u", &u
);
3673 return bus_log_parse_error(r
);
3675 if (streq(name
, "MainPID")) {
3677 i
->main_pid
= (pid_t
) u
;
3680 } else if (streq(name
, "ControlPID"))
3681 i
->control_pid
= (pid_t
) u
;
3682 else if (streq(name
, "ExecMainPID")) {
3684 i
->main_pid
= (pid_t
) u
;
3685 } else if (streq(name
, "NAccepted"))
3687 else if (streq(name
, "NConnections"))
3688 i
->n_connections
= u
;
3693 case SD_BUS_TYPE_INT32
: {
3696 r
= sd_bus_message_read(m
, "i", &j
);
3698 return bus_log_parse_error(r
);
3700 if (streq(name
, "ExecMainCode"))
3701 i
->exit_code
= (int) j
;
3702 else if (streq(name
, "ExecMainStatus"))
3703 i
->exit_status
= (int) j
;
3704 else if (streq(name
, "StatusErrno"))
3705 i
->status_errno
= (int) j
;
3710 case SD_BUS_TYPE_UINT64
: {
3713 r
= sd_bus_message_read(m
, "t", &u
);
3715 return bus_log_parse_error(r
);
3717 if (streq(name
, "ExecMainStartTimestamp"))
3718 i
->start_timestamp
= (usec_t
) u
;
3719 else if (streq(name
, "ExecMainExitTimestamp"))
3720 i
->exit_timestamp
= (usec_t
) u
;
3721 else if (streq(name
, "ActiveEnterTimestamp"))
3722 i
->active_enter_timestamp
= (usec_t
) u
;
3723 else if (streq(name
, "InactiveEnterTimestamp"))
3724 i
->inactive_enter_timestamp
= (usec_t
) u
;
3725 else if (streq(name
, "InactiveExitTimestamp"))
3726 i
->inactive_exit_timestamp
= (usec_t
) u
;
3727 else if (streq(name
, "InactiveExitTimestampMonotonic"))
3728 i
->inactive_exit_timestamp_monotonic
= (usec_t
) u
;
3729 else if (streq(name
, "ActiveExitTimestamp"))
3730 i
->active_exit_timestamp
= (usec_t
) u
;
3731 else if (streq(name
, "ConditionTimestamp"))
3732 i
->condition_timestamp
= (usec_t
) u
;
3733 else if (streq(name
, "AssertTimestamp"))
3734 i
->assert_timestamp
= (usec_t
) u
;
3735 else if (streq(name
, "MemoryCurrent"))
3736 i
->memory_current
= u
;
3737 else if (streq(name
, "MemoryLimit"))
3738 i
->memory_limit
= u
;
3739 else if (streq(name
, "CPUUsageNSec"))
3740 i
->cpu_usage_nsec
= u
;
3745 case SD_BUS_TYPE_ARRAY
:
3747 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
3748 _cleanup_free_ ExecStatusInfo
*info
= NULL
;
3750 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
3752 return bus_log_parse_error(r
);
3754 info
= new0(ExecStatusInfo
, 1);
3758 while ((r
= exec_status_info_deserialize(m
, info
)) > 0) {
3760 info
->name
= strdup(name
);
3764 LIST_PREPEND(exec
, i
->exec
, info
);
3766 info
= new0(ExecStatusInfo
, 1);
3772 return bus_log_parse_error(r
);
3774 r
= sd_bus_message_exit_container(m
);
3776 return bus_log_parse_error(r
);
3780 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
3781 const char *type
, *path
;
3783 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
3785 return bus_log_parse_error(r
);
3787 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0) {
3789 r
= strv_extend(&i
->listen
, type
);
3793 r
= strv_extend(&i
->listen
, path
);
3798 return bus_log_parse_error(r
);
3800 r
= sd_bus_message_exit_container(m
);
3802 return bus_log_parse_error(r
);
3806 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "DropInPaths")) {
3808 r
= sd_bus_message_read_strv(m
, &i
->dropin_paths
);
3810 return bus_log_parse_error(r
);
3812 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Documentation")) {
3814 r
= sd_bus_message_read_strv(m
, &i
->documentation
);
3816 return bus_log_parse_error(r
);
3818 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Conditions")) {
3819 const char *cond
, *param
;
3820 int trigger
, negate
;
3823 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
3825 return bus_log_parse_error(r
);
3827 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
3828 log_debug("%s %d %d %s %d", cond
, trigger
, negate
, param
, state
);
3829 if (state
< 0 && (!trigger
|| !i
->failed_condition
)) {
3830 i
->failed_condition
= cond
;
3831 i
->failed_condition_trigger
= trigger
;
3832 i
->failed_condition_negate
= negate
;
3833 i
->failed_condition_parameter
= param
;
3837 return bus_log_parse_error(r
);
3839 r
= sd_bus_message_exit_container(m
);
3841 return bus_log_parse_error(r
);
3843 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Asserts")) {
3844 const char *cond
, *param
;
3845 int trigger
, negate
;
3848 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
3850 return bus_log_parse_error(r
);
3852 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
3853 log_debug("%s %d %d %s %d", cond
, trigger
, negate
, param
, state
);
3854 if (state
< 0 && (!trigger
|| !i
->failed_assert
)) {
3855 i
->failed_assert
= cond
;
3856 i
->failed_assert_trigger
= trigger
;
3857 i
->failed_assert_negate
= negate
;
3858 i
->failed_assert_parameter
= param
;
3862 return bus_log_parse_error(r
);
3864 r
= sd_bus_message_exit_container(m
);
3866 return bus_log_parse_error(r
);
3873 case SD_BUS_TYPE_STRUCT_BEGIN
:
3875 if (streq(name
, "LoadError")) {
3876 const char *n
, *message
;
3878 r
= sd_bus_message_read(m
, "(ss)", &n
, &message
);
3880 return bus_log_parse_error(r
);
3882 if (!isempty(message
))
3883 i
->load_error
= message
;
3896 r
= sd_bus_message_skip(m
, contents
);
3898 return bus_log_parse_error(r
);
3903 static int print_property(const char *name
, sd_bus_message
*m
, const char *contents
) {
3909 /* This is a low-level property printer, see
3910 * print_status_info() for the nicer output */
3912 if (arg_properties
&& !strv_find(arg_properties
, name
)) {
3913 /* skip what we didn't read */
3914 r
= sd_bus_message_skip(m
, contents
);
3918 switch (contents
[0]) {
3920 case SD_BUS_TYPE_STRUCT_BEGIN
:
3922 if (contents
[1] == SD_BUS_TYPE_UINT32
&& streq(name
, "Job")) {
3925 r
= sd_bus_message_read(m
, "(uo)", &u
, NULL
);
3927 return bus_log_parse_error(r
);
3930 printf("%s=%"PRIu32
"\n", name
, u
);
3932 printf("%s=\n", name
);
3936 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Unit")) {
3939 r
= sd_bus_message_read(m
, "(so)", &s
, NULL
);
3941 return bus_log_parse_error(r
);
3943 if (arg_all
|| !isempty(s
))
3944 printf("%s=%s\n", name
, s
);
3948 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "LoadError")) {
3949 const char *a
= NULL
, *b
= NULL
;
3951 r
= sd_bus_message_read(m
, "(ss)", &a
, &b
);
3953 return bus_log_parse_error(r
);
3955 if (arg_all
|| !isempty(a
) || !isempty(b
))
3956 printf("%s=%s \"%s\"\n", name
, strempty(a
), strempty(b
));
3959 } else if (streq_ptr(name
, "SystemCallFilter")) {
3960 _cleanup_strv_free_
char **l
= NULL
;
3963 r
= sd_bus_message_enter_container(m
, 'r', "bas");
3965 return bus_log_parse_error(r
);
3967 r
= sd_bus_message_read(m
, "b", &whitelist
);
3969 return bus_log_parse_error(r
);
3971 r
= sd_bus_message_read_strv(m
, &l
);
3973 return bus_log_parse_error(r
);
3975 r
= sd_bus_message_exit_container(m
);
3977 return bus_log_parse_error(r
);
3979 if (arg_all
|| whitelist
|| !strv_isempty(l
)) {
3983 fputs(name
, stdout
);
3989 STRV_FOREACH(i
, l
) {
3997 fputc('\n', stdout
);
4005 case SD_BUS_TYPE_ARRAY
:
4007 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "EnvironmentFiles")) {
4011 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sb)");
4013 return bus_log_parse_error(r
);
4015 while ((r
= sd_bus_message_read(m
, "(sb)", &path
, &ignore
)) > 0)
4016 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path
, yes_no(ignore
));
4019 return bus_log_parse_error(r
);
4021 r
= sd_bus_message_exit_container(m
);
4023 return bus_log_parse_error(r
);
4027 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Paths")) {
4028 const char *type
, *path
;
4030 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4032 return bus_log_parse_error(r
);
4034 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4035 printf("%s=%s\n", type
, path
);
4037 return bus_log_parse_error(r
);
4039 r
= sd_bus_message_exit_container(m
);
4041 return bus_log_parse_error(r
);
4045 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
4046 const char *type
, *path
;
4048 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4050 return bus_log_parse_error(r
);
4052 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4053 printf("Listen%s=%s\n", type
, path
);
4055 return bus_log_parse_error(r
);
4057 r
= sd_bus_message_exit_container(m
);
4059 return bus_log_parse_error(r
);
4063 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Timers")) {
4065 uint64_t value
, next_elapse
;
4067 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(stt)");
4069 return bus_log_parse_error(r
);
4071 while ((r
= sd_bus_message_read(m
, "(stt)", &base
, &value
, &next_elapse
)) > 0) {
4072 char timespan1
[FORMAT_TIMESPAN_MAX
], timespan2
[FORMAT_TIMESPAN_MAX
];
4074 printf("%s={ value=%s ; next_elapse=%s }\n",
4076 format_timespan(timespan1
, sizeof(timespan1
), value
, 0),
4077 format_timespan(timespan2
, sizeof(timespan2
), next_elapse
, 0));
4080 return bus_log_parse_error(r
);
4082 r
= sd_bus_message_exit_container(m
);
4084 return bus_log_parse_error(r
);
4088 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
4089 ExecStatusInfo info
= {};
4091 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4093 return bus_log_parse_error(r
);
4095 while ((r
= exec_status_info_deserialize(m
, &info
)) > 0) {
4096 char timestamp1
[FORMAT_TIMESTAMP_MAX
], timestamp2
[FORMAT_TIMESTAMP_MAX
];
4097 _cleanup_free_
char *tt
;
4099 tt
= strv_join(info
.argv
, " ");
4101 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",
4105 yes_no(info
.ignore
),
4106 strna(format_timestamp(timestamp1
, sizeof(timestamp1
), info
.start_timestamp
)),
4107 strna(format_timestamp(timestamp2
, sizeof(timestamp2
), info
.exit_timestamp
)),
4109 sigchld_code_to_string(info
.code
),
4111 info
.code
== CLD_EXITED
? "" : "/",
4112 strempty(info
.code
== CLD_EXITED
? NULL
: signal_to_string(info
.status
)));
4115 strv_free(info
.argv
);
4119 r
= sd_bus_message_exit_container(m
);
4121 return bus_log_parse_error(r
);
4125 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "DeviceAllow")) {
4126 const char *path
, *rwm
;
4128 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4130 return bus_log_parse_error(r
);
4132 while ((r
= sd_bus_message_read(m
, "(ss)", &path
, &rwm
)) > 0)
4133 printf("%s=%s %s\n", name
, strna(path
), strna(rwm
));
4135 return bus_log_parse_error(r
);
4137 r
= sd_bus_message_exit_container(m
);
4139 return bus_log_parse_error(r
);
4143 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "BlockIODeviceWeight")) {
4147 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4149 return bus_log_parse_error(r
);
4151 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &weight
)) > 0)
4152 printf("%s=%s %" PRIu64
"\n", name
, strna(path
), weight
);
4154 return bus_log_parse_error(r
);
4156 r
= sd_bus_message_exit_container(m
);
4158 return bus_log_parse_error(r
);
4162 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& (streq(name
, "BlockIOReadBandwidth") || streq(name
, "BlockIOWriteBandwidth"))) {
4166 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4168 return bus_log_parse_error(r
);
4170 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &bandwidth
)) > 0)
4171 printf("%s=%s %" PRIu64
"\n", name
, strna(path
), bandwidth
);
4173 return bus_log_parse_error(r
);
4175 r
= sd_bus_message_exit_container(m
);
4177 return bus_log_parse_error(r
);
4185 r
= bus_print_property(name
, m
, arg_all
);
4187 return bus_log_parse_error(r
);
4190 r
= sd_bus_message_skip(m
, contents
);
4192 return bus_log_parse_error(r
);
4195 printf("%s=[unprintable]\n", name
);
4201 static int show_one(
4205 bool show_properties
,
4209 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4210 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4211 UnitStatusInfo info
= {
4212 .memory_current
= (uint64_t) -1,
4213 .memory_limit
= (uint64_t) -1,
4214 .cpu_usage_nsec
= (uint64_t) -1,
4222 log_debug("Showing one %s", path
);
4224 r
= sd_bus_call_method(
4226 "org.freedesktop.systemd1",
4228 "org.freedesktop.DBus.Properties",
4234 log_error("Failed to get properties: %s", bus_error_message(&error
, r
));
4238 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
4240 return bus_log_parse_error(r
);
4247 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
4248 const char *name
, *contents
;
4250 r
= sd_bus_message_read(reply
, "s", &name
);
4252 return bus_log_parse_error(r
);
4254 r
= sd_bus_message_peek_type(reply
, NULL
, &contents
);
4256 return bus_log_parse_error(r
);
4258 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, contents
);
4260 return bus_log_parse_error(r
);
4262 if (show_properties
)
4263 r
= print_property(name
, reply
, contents
);
4265 r
= status_property(name
, reply
, &info
, contents
);
4269 r
= sd_bus_message_exit_container(reply
);
4271 return bus_log_parse_error(r
);
4273 r
= sd_bus_message_exit_container(reply
);
4275 return bus_log_parse_error(r
);
4278 return bus_log_parse_error(r
);
4280 r
= sd_bus_message_exit_container(reply
);
4282 return bus_log_parse_error(r
);
4286 if (!show_properties
) {
4287 if (streq(verb
, "help"))
4288 show_unit_help(&info
);
4290 print_status_info(&info
, ellipsized
);
4293 strv_free(info
.documentation
);
4294 strv_free(info
.dropin_paths
);
4295 strv_free(info
.listen
);
4297 if (!streq_ptr(info
.active_state
, "active") &&
4298 !streq_ptr(info
.active_state
, "reloading") &&
4299 streq(verb
, "status")) {
4300 /* According to LSB: "program not running" */
4301 /* 0: program is running or service is OK
4302 * 1: program is dead and /run PID file exists
4303 * 2: program is dead and /run/lock lock file exists
4304 * 3: program is not running
4305 * 4: program or service status is unknown
4307 if (info
.pid_file
&& access(info
.pid_file
, F_OK
) == 0)
4313 while ((p
= info
.exec
)) {
4314 LIST_REMOVE(exec
, info
.exec
, p
);
4315 exec_status_info_free(p
);
4321 static int get_unit_dbus_path_by_pid(
4326 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4327 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4331 r
= sd_bus_call_method(
4333 "org.freedesktop.systemd1",
4334 "/org/freedesktop/systemd1",
4335 "org.freedesktop.systemd1.Manager",
4341 log_error("Failed to get unit for PID %"PRIu32
": %s", pid
, bus_error_message(&error
, r
));
4345 r
= sd_bus_message_read(reply
, "o", &u
);
4347 return bus_log_parse_error(r
);
4357 static int show_all(
4360 bool show_properties
,
4364 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4365 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
4370 r
= get_unit_list(bus
, NULL
, NULL
, &unit_infos
, 0, &reply
);
4374 pager_open_if_enabled();
4378 qsort_safe(unit_infos
, c
, sizeof(UnitInfo
), compare_unit_info
);
4380 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
4381 _cleanup_free_
char *p
= NULL
;
4383 p
= unit_dbus_path_from_name(u
->id
);
4387 r
= show_one(verb
, bus
, p
, show_properties
, new_line
, ellipsized
);
4390 else if (r
> 0 && ret
== 0)
4397 static int show_system_status(sd_bus
*bus
) {
4398 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], since2
[FORMAT_TIMESTAMP_MAX
];
4399 _cleanup_free_
char *hn
= NULL
;
4400 struct machine_info mi
= {};
4401 const char *on
, *off
;
4404 hn
= gethostname_malloc();
4408 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, &mi
);
4410 return log_error_errno(r
, "Failed to read server status: %m");
4412 if (streq_ptr(mi
.state
, "degraded")) {
4413 on
= ansi_highlight_red();
4414 off
= ansi_highlight_off();
4415 } else if (!streq_ptr(mi
.state
, "running")) {
4416 on
= ansi_highlight_yellow();
4417 off
= ansi_highlight_off();
4421 printf("%s%s%s %s\n", on
, draw_special_char(DRAW_BLACK_CIRCLE
), off
, arg_host
? arg_host
: hn
);
4423 printf(" State: %s%s%s\n",
4424 on
, strna(mi
.state
), off
);
4426 printf(" Jobs: %u queued\n", mi
.n_jobs
);
4427 printf(" Failed: %u units\n", mi
.n_failed_units
);
4429 printf(" Since: %s; %s\n",
4430 format_timestamp(since2
, sizeof(since2
), mi
.timestamp
),
4431 format_timestamp_relative(since1
, sizeof(since1
), mi
.timestamp
));
4433 printf(" CGroup: %s\n", mi
.control_group
?: "/");
4434 if (arg_transport
== BUS_TRANSPORT_LOCAL
|| arg_transport
== BUS_TRANSPORT_MACHINE
) {
4435 static const char prefix
[] = " ";
4439 if (c
> sizeof(prefix
) - 1)
4440 c
-= sizeof(prefix
) - 1;
4444 show_cgroup(SYSTEMD_CGROUP_CONTROLLER
, strempty(mi
.control_group
), prefix
, c
, false, get_output_flags());
4448 free(mi
.control_group
);
4453 static int show(sd_bus
*bus
, char **args
) {
4454 bool show_properties
, show_status
, new_line
= false;
4455 bool ellipsized
= false;
4461 show_properties
= streq(args
[0], "show");
4462 show_status
= streq(args
[0], "status");
4464 if (show_properties
)
4465 pager_open_if_enabled();
4467 /* If no argument is specified inspect the manager itself */
4469 if (show_properties
&& strv_length(args
) <= 1)
4470 return show_one(args
[0], bus
, "/org/freedesktop/systemd1", show_properties
, &new_line
, &ellipsized
);
4472 if (show_status
&& strv_length(args
) <= 1) {
4474 pager_open_if_enabled();
4475 show_system_status(bus
);
4479 ret
= show_all(args
[0], bus
, false, &new_line
, &ellipsized
);
4481 _cleanup_free_
char **patterns
= NULL
;
4484 STRV_FOREACH(name
, args
+ 1) {
4485 _cleanup_free_
char *unit
= NULL
;
4488 if (safe_atou32(*name
, &id
) < 0) {
4489 if (strv_push(&patterns
, *name
) < 0)
4493 } else if (show_properties
) {
4494 /* Interpret as job id */
4495 if (asprintf(&unit
, "/org/freedesktop/systemd1/job/%u", id
) < 0)
4499 /* Interpret as PID */
4500 r
= get_unit_dbus_path_by_pid(bus
, id
, &unit
);
4507 r
= show_one(args
[0], bus
, unit
, show_properties
,
4508 &new_line
, &ellipsized
);
4511 else if (r
> 0 && ret
== 0)
4515 if (!strv_isempty(patterns
)) {
4516 _cleanup_strv_free_
char **names
= NULL
;
4518 r
= expand_names(bus
, patterns
, NULL
, &names
);
4520 log_error_errno(r
, "Failed to expand names: %m");
4522 STRV_FOREACH(name
, names
) {
4523 _cleanup_free_
char *unit
;
4525 unit
= unit_dbus_path_from_name(*name
);
4529 r
= show_one(args
[0], bus
, unit
, show_properties
,
4530 &new_line
, &ellipsized
);
4533 else if (r
> 0 && ret
== 0)
4539 if (ellipsized
&& !arg_quiet
)
4540 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4545 static int init_home_and_lookup_paths(char **user_home
, char **user_runtime
, LookupPaths
*lp
) {
4549 assert(user_runtime
);
4552 if (arg_scope
== UNIT_FILE_USER
) {
4553 r
= user_config_home(user_home
);
4555 return log_error_errno(r
, "Failed to query XDG_CONFIG_HOME: %m");
4557 return log_error_errno(ENOTDIR
, "Cannot find units: $XDG_CONFIG_HOME and $HOME are not set.");
4559 r
= user_runtime_dir(user_runtime
);
4561 return log_error_errno(r
, "Failed to query XDG_CONFIG_HOME: %m");
4563 return log_error_errno(ENOTDIR
, "Cannot find units: $XDG_RUNTIME_DIR is not set.");
4566 r
= lookup_paths_init_from_scope(lp
, arg_scope
, arg_root
);
4568 return log_error_errno(r
, "Failed to query unit lookup paths: %m");
4573 static int cat_file(const char *filename
, bool newline
) {
4574 _cleanup_close_
int fd
;
4576 fd
= open(filename
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
4580 printf("%s%s# %s%s\n",
4581 newline
? "\n" : "",
4582 ansi_highlight_blue(),
4584 ansi_highlight_off());
4587 return copy_bytes(fd
, STDOUT_FILENO
, (off_t
) -1, false);
4590 static int cat(sd_bus
*bus
, char **args
) {
4591 _cleanup_free_
char *user_home
= NULL
;
4592 _cleanup_free_
char *user_runtime
= NULL
;
4593 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
4594 _cleanup_strv_free_
char **names
= NULL
;
4596 bool first
= true, avoid_bus_cache
;
4601 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
4602 log_error("Cannot remotely cat units");
4606 r
= init_home_and_lookup_paths(&user_home
, &user_runtime
, &lp
);
4610 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
4612 return log_error_errno(r
, "Failed to expand names: %m");
4614 avoid_bus_cache
= !bus
|| avoid_bus();
4616 pager_open_if_enabled();
4618 STRV_FOREACH(name
, names
) {
4619 _cleanup_free_
char *fragment_path
= NULL
;
4620 _cleanup_strv_free_
char **dropin_paths
= NULL
;
4623 r
= unit_find_paths(bus
, *name
, avoid_bus_cache
, &lp
, &fragment_path
, &dropin_paths
);
4634 if (fragment_path
) {
4635 r
= cat_file(fragment_path
, false);
4637 return log_warning_errno(r
, "Failed to cat %s: %m", fragment_path
);
4640 STRV_FOREACH(path
, dropin_paths
) {
4641 r
= cat_file(*path
, path
== dropin_paths
);
4643 return log_warning_errno(r
, "Failed to cat %s: %m", *path
);
4650 static int set_property(sd_bus
*bus
, char **args
) {
4651 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
4652 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4653 _cleanup_free_
char *n
= NULL
;
4657 polkit_agent_open_if_enabled();
4659 r
= sd_bus_message_new_method_call(
4662 "org.freedesktop.systemd1",
4663 "/org/freedesktop/systemd1",
4664 "org.freedesktop.systemd1.Manager",
4665 "SetUnitProperties");
4667 return bus_log_create_error(r
);
4669 n
= unit_name_mangle(args
[1], MANGLE_NOGLOB
);
4673 r
= sd_bus_message_append(m
, "sb", n
, arg_runtime
);
4675 return bus_log_create_error(r
);
4677 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, "(sv)");
4679 return bus_log_create_error(r
);
4681 STRV_FOREACH(i
, args
+ 2) {
4682 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_STRUCT
, "sv");
4684 return bus_log_create_error(r
);
4686 r
= bus_append_unit_property_assignment(m
, *i
);
4690 r
= sd_bus_message_close_container(m
);
4692 return bus_log_create_error(r
);
4695 r
= sd_bus_message_close_container(m
);
4697 return bus_log_create_error(r
);
4699 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
4701 log_error("Failed to set unit properties on %s: %s", n
, bus_error_message(&error
, r
));
4708 static int snapshot(sd_bus
*bus
, char **args
) {
4709 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4710 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4711 _cleanup_free_
char *n
= NULL
, *id
= NULL
;
4715 polkit_agent_open_if_enabled();
4717 if (strv_length(args
) > 1)
4718 n
= unit_name_mangle_with_suffix(args
[1], MANGLE_NOGLOB
, ".snapshot");
4724 r
= sd_bus_call_method(
4726 "org.freedesktop.systemd1",
4727 "/org/freedesktop/systemd1",
4728 "org.freedesktop.systemd1.Manager",
4734 log_error("Failed to create snapshot: %s", bus_error_message(&error
, r
));
4738 r
= sd_bus_message_read(reply
, "o", &path
);
4740 return bus_log_parse_error(r
);
4742 r
= sd_bus_get_property_string(
4744 "org.freedesktop.systemd1",
4746 "org.freedesktop.systemd1.Unit",
4751 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error
, r
));
4761 static int delete_snapshot(sd_bus
*bus
, char **args
) {
4762 _cleanup_strv_free_
char **names
= NULL
;
4768 polkit_agent_open_if_enabled();
4770 r
= expand_names(bus
, args
+ 1, ".snapshot", &names
);
4772 log_error_errno(r
, "Failed to expand names: %m");
4774 STRV_FOREACH(name
, names
) {
4775 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4778 q
= sd_bus_call_method(
4780 "org.freedesktop.systemd1",
4781 "/org/freedesktop/systemd1",
4782 "org.freedesktop.systemd1.Manager",
4788 log_error("Failed to remove snapshot %s: %s", *name
, bus_error_message(&error
, q
));
4797 static int daemon_reload(sd_bus
*bus
, char **args
) {
4798 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4802 polkit_agent_open_if_enabled();
4804 if (arg_action
== ACTION_RELOAD
)
4806 else if (arg_action
== ACTION_REEXEC
)
4807 method
= "Reexecute";
4809 assert(arg_action
== ACTION_SYSTEMCTL
);
4812 streq(args
[0], "clear-jobs") ||
4813 streq(args
[0], "cancel") ? "ClearJobs" :
4814 streq(args
[0], "daemon-reexec") ? "Reexecute" :
4815 streq(args
[0], "reset-failed") ? "ResetFailed" :
4816 streq(args
[0], "halt") ? "Halt" :
4817 streq(args
[0], "poweroff") ? "PowerOff" :
4818 streq(args
[0], "reboot") ? "Reboot" :
4819 streq(args
[0], "kexec") ? "KExec" :
4820 streq(args
[0], "exit") ? "Exit" :
4821 /* "daemon-reload" */ "Reload";
4824 r
= sd_bus_call_method(
4826 "org.freedesktop.systemd1",
4827 "/org/freedesktop/systemd1",
4828 "org.freedesktop.systemd1.Manager",
4833 if (r
== -ENOENT
&& arg_action
!= ACTION_SYSTEMCTL
)
4834 /* There's always a fallback possible for
4835 * legacy actions. */
4837 else if ((r
== -ETIMEDOUT
|| r
== -ECONNRESET
) && streq(method
, "Reexecute"))
4838 /* On reexecution, we expect a disconnect, not a
4842 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
4844 return r
< 0 ? r
: 0;
4847 static int reset_failed(sd_bus
*bus
, char **args
) {
4848 _cleanup_strv_free_
char **names
= NULL
;
4852 if (strv_length(args
) <= 1)
4853 return daemon_reload(bus
, args
);
4855 polkit_agent_open_if_enabled();
4857 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
4859 log_error_errno(r
, "Failed to expand names: %m");
4861 STRV_FOREACH(name
, names
) {
4862 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4864 q
= sd_bus_call_method(
4866 "org.freedesktop.systemd1",
4867 "/org/freedesktop/systemd1",
4868 "org.freedesktop.systemd1.Manager",
4874 log_error("Failed to reset failed state of unit %s: %s", *name
, bus_error_message(&error
, q
));
4883 static int show_environment(sd_bus
*bus
, char **args
) {
4884 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4885 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4889 pager_open_if_enabled();
4891 r
= sd_bus_get_property(
4893 "org.freedesktop.systemd1",
4894 "/org/freedesktop/systemd1",
4895 "org.freedesktop.systemd1.Manager",
4901 log_error("Failed to get environment: %s", bus_error_message(&error
, r
));
4905 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
4907 return bus_log_parse_error(r
);
4909 while ((r
= sd_bus_message_read_basic(reply
, SD_BUS_TYPE_STRING
, &text
)) > 0)
4912 return bus_log_parse_error(r
);
4914 r
= sd_bus_message_exit_container(reply
);
4916 return bus_log_parse_error(r
);
4921 static int switch_root(sd_bus
*bus
, char **args
) {
4922 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4923 _cleanup_free_
char *cmdline_init
= NULL
;
4924 const char *root
, *init
;
4928 l
= strv_length(args
);
4929 if (l
< 2 || l
> 3) {
4930 log_error("Wrong number of arguments.");
4939 r
= parse_env_file("/proc/cmdline", WHITESPACE
,
4940 "init", &cmdline_init
,
4943 log_debug_errno(r
, "Failed to parse /proc/cmdline: %m");
4945 init
= cmdline_init
;
4952 const char *root_systemd_path
= NULL
, *root_init_path
= NULL
;
4954 root_systemd_path
= strjoina(root
, "/" SYSTEMD_BINARY_PATH
);
4955 root_init_path
= strjoina(root
, "/", init
);
4957 /* If the passed init is actually the same as the
4958 * systemd binary, then let's suppress it. */
4959 if (files_same(root_init_path
, root_systemd_path
) > 0)
4963 log_debug("Switching root - root: %s; init: %s", root
, strna(init
));
4965 r
= sd_bus_call_method(
4967 "org.freedesktop.systemd1",
4968 "/org/freedesktop/systemd1",
4969 "org.freedesktop.systemd1.Manager",
4975 log_error("Failed to switch root: %s", bus_error_message(&error
, r
));
4982 static int set_environment(sd_bus
*bus
, char **args
) {
4983 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4984 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
4991 polkit_agent_open_if_enabled();
4993 method
= streq(args
[0], "set-environment")
4995 : "UnsetEnvironment";
4997 r
= sd_bus_message_new_method_call(
5000 "org.freedesktop.systemd1",
5001 "/org/freedesktop/systemd1",
5002 "org.freedesktop.systemd1.Manager",
5005 return bus_log_create_error(r
);
5007 r
= sd_bus_message_append_strv(m
, args
+ 1);
5009 return bus_log_create_error(r
);
5011 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5013 log_error("Failed to set environment: %s", bus_error_message(&error
, r
));
5020 static int import_environment(sd_bus
*bus
, char **args
) {
5021 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5022 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
5028 polkit_agent_open_if_enabled();
5030 r
= sd_bus_message_new_method_call(
5033 "org.freedesktop.systemd1",
5034 "/org/freedesktop/systemd1",
5035 "org.freedesktop.systemd1.Manager",
5038 return bus_log_create_error(r
);
5040 if (strv_isempty(args
+ 1))
5041 r
= sd_bus_message_append_strv(m
, environ
);
5045 r
= sd_bus_message_open_container(m
, 'a', "s");
5047 return bus_log_create_error(r
);
5049 STRV_FOREACH(a
, args
+ 1) {
5051 if (!env_name_is_valid(*a
)) {
5052 log_error("Not a valid environment variable name: %s", *a
);
5056 STRV_FOREACH(b
, environ
) {
5059 eq
= startswith(*b
, *a
);
5060 if (eq
&& *eq
== '=') {
5062 r
= sd_bus_message_append(m
, "s", *b
);
5064 return bus_log_create_error(r
);
5071 r
= sd_bus_message_close_container(m
);
5074 return bus_log_create_error(r
);
5076 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5078 log_error("Failed to import environment: %s", bus_error_message(&error
, r
));
5085 static int enable_sysv_units(const char *verb
, char **args
) {
5088 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
5090 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
5092 if (arg_scope
!= UNIT_FILE_SYSTEM
)
5095 if (!streq(verb
, "enable") &&
5096 !streq(verb
, "disable") &&
5097 !streq(verb
, "is-enabled"))
5100 /* Processes all SysV units, and reshuffles the array so that
5101 * afterwards only the native units remain */
5103 r
= lookup_paths_init(&paths
, SYSTEMD_SYSTEM
, false, arg_root
, NULL
, NULL
, NULL
);
5110 _cleanup_free_
char *p
= NULL
, *q
= NULL
, *l
= NULL
;
5111 bool found_native
= false, found_sysv
;
5113 const char *argv
[6] = { "/sbin/chkconfig", NULL
, NULL
, NULL
, NULL
};
5121 if (!endswith(name
, ".service"))
5124 if (path_is_absolute(name
))
5127 STRV_FOREACH(k
, paths
.unit_path
) {
5128 _cleanup_free_
char *path
= NULL
;
5130 path
= path_join(arg_root
, *k
, name
);
5134 found_native
= access(path
, F_OK
) >= 0;
5142 p
= path_join(arg_root
, SYSTEM_SYSVINIT_PATH
, name
);
5146 p
[strlen(p
) - strlen(".service")] = 0;
5147 found_sysv
= access(p
, F_OK
) >= 0;
5151 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name
);
5153 if (!isempty(arg_root
))
5154 argv
[c
++] = q
= strappend("--root=", arg_root
);
5156 argv
[c
++] = basename(p
);
5158 streq(verb
, "enable") ? "on" :
5159 streq(verb
, "disable") ? "off" : "--level=5";
5162 l
= strv_join((char**)argv
, " ");
5166 log_info("Executing %s", l
);
5170 return log_error_errno(errno
, "Failed to fork: %m");
5171 else if (pid
== 0) {
5174 execv(argv
[0], (char**) argv
);
5175 _exit(EXIT_FAILURE
);
5178 j
= wait_for_terminate(pid
, &status
);
5180 log_error_errno(r
, "Failed to wait for child: %m");
5184 if (status
.si_code
== CLD_EXITED
) {
5185 if (streq(verb
, "is-enabled")) {
5186 if (status
.si_status
== 0) {
5195 } else if (status
.si_status
!= 0)
5200 /* Remove this entry, so that we don't try enabling it as native unit */
5203 assert(args
[f
] == name
);
5204 strv_remove(args
, name
);
5211 static int mangle_names(char **original_names
, char ***mangled_names
) {
5212 char **i
, **l
, **name
;
5214 l
= new(char*, strv_length(original_names
) + 1);
5219 STRV_FOREACH(name
, original_names
) {
5221 /* When enabling units qualified path names are OK,
5222 * too, hence allow them explicitly. */
5227 *i
= unit_name_mangle(*name
, MANGLE_NOGLOB
);
5243 static int enable_unit(sd_bus
*bus
, char **args
) {
5244 _cleanup_strv_free_
char **names
= NULL
;
5245 const char *verb
= args
[0];
5246 UnitFileChange
*changes
= NULL
;
5247 unsigned n_changes
= 0;
5248 int carries_install_info
= -1;
5254 r
= mangle_names(args
+1, &names
);
5258 r
= enable_sysv_units(verb
, names
);
5262 /* If the operation was fully executed by the SysV compat,
5263 * let's finish early */
5264 if (strv_isempty(names
))
5267 if (!bus
|| avoid_bus()) {
5268 if (streq(verb
, "enable")) {
5269 r
= unit_file_enable(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5270 carries_install_info
= r
;
5271 } else if (streq(verb
, "disable"))
5272 r
= unit_file_disable(arg_scope
, arg_runtime
, arg_root
, names
, &changes
, &n_changes
);
5273 else if (streq(verb
, "reenable")) {
5274 r
= unit_file_reenable(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5275 carries_install_info
= r
;
5276 } else if (streq(verb
, "link"))
5277 r
= unit_file_link(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5278 else if (streq(verb
, "preset")) {
5279 r
= unit_file_preset(arg_scope
, arg_runtime
, arg_root
, names
, arg_preset_mode
, arg_force
, &changes
, &n_changes
);
5280 carries_install_info
= r
;
5281 } else if (streq(verb
, "mask"))
5282 r
= unit_file_mask(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5283 else if (streq(verb
, "unmask"))
5284 r
= unit_file_unmask(arg_scope
, arg_runtime
, arg_root
, names
, &changes
, &n_changes
);
5286 assert_not_reached("Unknown verb");
5289 log_error_errno(r
, "Operation failed: %m");
5294 dump_unit_file_changes(changes
, n_changes
);
5298 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
, *m
= NULL
;
5299 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5300 int expect_carries_install_info
= false;
5301 bool send_force
= true, send_preset_mode
= false;
5304 polkit_agent_open_if_enabled();
5306 if (streq(verb
, "enable")) {
5307 method
= "EnableUnitFiles";
5308 expect_carries_install_info
= true;
5309 } else if (streq(verb
, "disable")) {
5310 method
= "DisableUnitFiles";
5312 } else if (streq(verb
, "reenable")) {
5313 method
= "ReenableUnitFiles";
5314 expect_carries_install_info
= true;
5315 } else if (streq(verb
, "link"))
5316 method
= "LinkUnitFiles";
5317 else if (streq(verb
, "preset")) {
5319 if (arg_preset_mode
!= UNIT_FILE_PRESET_FULL
) {
5320 method
= "PresetUnitFilesWithMode";
5321 send_preset_mode
= true;
5323 method
= "PresetUnitFiles";
5325 expect_carries_install_info
= true;
5326 } else if (streq(verb
, "mask"))
5327 method
= "MaskUnitFiles";
5328 else if (streq(verb
, "unmask")) {
5329 method
= "UnmaskUnitFiles";
5332 assert_not_reached("Unknown verb");
5334 r
= sd_bus_message_new_method_call(
5337 "org.freedesktop.systemd1",
5338 "/org/freedesktop/systemd1",
5339 "org.freedesktop.systemd1.Manager",
5342 return bus_log_create_error(r
);
5344 r
= sd_bus_message_append_strv(m
, names
);
5346 return bus_log_create_error(r
);
5348 if (send_preset_mode
) {
5349 r
= sd_bus_message_append(m
, "s", unit_file_preset_mode_to_string(arg_preset_mode
));
5351 return bus_log_create_error(r
);
5354 r
= sd_bus_message_append(m
, "b", arg_runtime
);
5356 return bus_log_create_error(r
);
5359 r
= sd_bus_message_append(m
, "b", arg_force
);
5361 return bus_log_create_error(r
);
5364 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
5366 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
5370 if (expect_carries_install_info
) {
5371 r
= sd_bus_message_read(reply
, "b", &carries_install_info
);
5373 return bus_log_parse_error(r
);
5376 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
);
5380 /* Try to reload if enabled */
5382 r
= daemon_reload(bus
, args
);
5387 if (carries_install_info
== 0)
5388 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5389 "using systemctl.\n"
5390 "Possible reasons for having this kind of units are:\n"
5391 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5392 " .wants/ or .requires/ directory.\n"
5393 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5394 " a requirement dependency on it.\n"
5395 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5396 " D-Bus, udev, scripted systemctl call, ...).\n");
5399 unit_file_changes_free(changes
, n_changes
);
5404 static int add_dependency(sd_bus
*bus
, char **args
) {
5405 _cleanup_strv_free_
char **names
= NULL
;
5406 _cleanup_free_
char *target
= NULL
;
5407 const char *verb
= args
[0];
5414 target
= unit_name_mangle_with_suffix(args
[1], MANGLE_NOGLOB
, ".target");
5418 r
= mangle_names(args
+2, &names
);
5422 if (streq(verb
, "add-wants"))
5424 else if (streq(verb
, "add-requires"))
5425 dep
= UNIT_REQUIRES
;
5427 assert_not_reached("Unknown verb");
5429 if (!bus
|| avoid_bus()) {
5430 UnitFileChange
*changes
= NULL
;
5431 unsigned n_changes
= 0;
5433 r
= unit_file_add_dependency(arg_scope
, arg_runtime
, arg_root
, names
, target
, dep
, arg_force
, &changes
, &n_changes
);
5436 return log_error_errno(r
, "Can't add dependency: %m");
5439 dump_unit_file_changes(changes
, n_changes
);
5441 unit_file_changes_free(changes
, n_changes
);
5444 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
, *m
= NULL
;
5445 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5447 polkit_agent_open_if_enabled();
5449 r
= sd_bus_message_new_method_call(
5452 "org.freedesktop.systemd1",
5453 "/org/freedesktop/systemd1",
5454 "org.freedesktop.systemd1.Manager",
5455 "AddDependencyUnitFiles");
5457 return bus_log_create_error(r
);
5459 r
= sd_bus_message_append_strv(m
, names
);
5461 return bus_log_create_error(r
);
5463 r
= sd_bus_message_append(m
, "ssbb", target
, unit_dependency_to_string(dep
), arg_runtime
, arg_force
);
5465 return bus_log_create_error(r
);
5467 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
5469 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
5473 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
);
5478 r
= daemon_reload(bus
, args
);
5486 static int preset_all(sd_bus
*bus
, char **args
) {
5487 UnitFileChange
*changes
= NULL
;
5488 unsigned n_changes
= 0;
5491 if (!bus
|| avoid_bus()) {
5493 r
= unit_file_preset_all(arg_scope
, arg_runtime
, arg_root
, arg_preset_mode
, arg_force
, &changes
, &n_changes
);
5495 log_error_errno(r
, "Operation failed: %m");
5500 dump_unit_file_changes(changes
, n_changes
);
5505 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5506 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
5508 polkit_agent_open_if_enabled();
5510 r
= sd_bus_call_method(
5512 "org.freedesktop.systemd1",
5513 "/org/freedesktop/systemd1",
5514 "org.freedesktop.systemd1.Manager",
5515 "PresetAllUnitFiles",
5519 unit_file_preset_mode_to_string(arg_preset_mode
),
5523 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
5527 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
);
5532 r
= daemon_reload(bus
, args
);
5538 unit_file_changes_free(changes
, n_changes
);
5543 static int unit_is_enabled(sd_bus
*bus
, char **args
) {
5545 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5546 _cleanup_strv_free_
char **names
= NULL
;
5551 r
= mangle_names(args
+1, &names
);
5555 r
= enable_sysv_units(args
[0], names
);
5561 if (!bus
|| avoid_bus()) {
5563 STRV_FOREACH(name
, names
) {
5564 UnitFileState state
;
5566 state
= unit_file_get_state(arg_scope
, arg_root
, *name
);
5568 return log_error_errno(state
, "Failed to get unit file state for %s: %m", *name
);
5570 if (state
== UNIT_FILE_ENABLED
||
5571 state
== UNIT_FILE_ENABLED_RUNTIME
||
5572 state
== UNIT_FILE_STATIC
||
5573 state
== UNIT_FILE_INDIRECT
)
5577 puts(unit_file_state_to_string(state
));
5581 STRV_FOREACH(name
, names
) {
5582 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
5585 r
= sd_bus_call_method(
5587 "org.freedesktop.systemd1",
5588 "/org/freedesktop/systemd1",
5589 "org.freedesktop.systemd1.Manager",
5595 log_error("Failed to get unit file state for %s: %s", *name
, bus_error_message(&error
, r
));
5599 r
= sd_bus_message_read(reply
, "s", &s
);
5601 return bus_log_parse_error(r
);
5603 if (STR_IN_SET(s
, "enabled", "enabled-runtime", "static", "indirect"))
5614 static int is_system_running(sd_bus
*bus
, char **args
) {
5615 _cleanup_free_
char *state
= NULL
;
5618 r
= sd_bus_get_property_string(
5620 "org.freedesktop.systemd1",
5621 "/org/freedesktop/systemd1",
5622 "org.freedesktop.systemd1.Manager",
5635 return streq(state
, "running") ? EXIT_SUCCESS
: EXIT_FAILURE
;
5638 static int create_edit_temp_file(const char *new_path
, const char *original_path
, char **ret_tmp_fn
) {
5643 assert(original_path
);
5646 r
= tempfn_random(new_path
, &t
);
5648 return log_error_errno(r
, "Failed to determine temporary filename for \"%s\": %m", new_path
);
5650 r
= mkdir_parents(new_path
, 0755);
5652 log_error_errno(r
, "Failed to create directories for \"%s\": %m", new_path
);
5657 r
= copy_file(original_path
, t
, 0, 0644, 0);
5661 log_error_errno(r
, "Failed to create temporary file \"%s\": %m", t
);
5666 log_error_errno(r
, "Failed to copy \"%s\" to \"%s\": %m", original_path
, t
);
5676 static int get_file_to_edit(const char *name
, const char *user_home
, const char *user_runtime
, char **ret_path
) {
5677 _cleanup_free_
char *path
= NULL
, *path2
= NULL
, *run
= NULL
;
5679 switch (arg_scope
) {
5680 case UNIT_FILE_SYSTEM
:
5681 path
= path_join(arg_root
, SYSTEM_CONFIG_UNIT_PATH
, name
);
5683 run
= path_join(arg_root
, "/run/systemd/system/", name
);
5685 case UNIT_FILE_GLOBAL
:
5686 path
= path_join(arg_root
, USER_CONFIG_UNIT_PATH
, name
);
5688 run
= path_join(arg_root
, "/run/systemd/user/", name
);
5690 case UNIT_FILE_USER
:
5692 assert(user_runtime
);
5694 path
= path_join(arg_root
, user_home
, name
);
5696 path2
= path_join(arg_root
, USER_CONFIG_UNIT_PATH
, name
);
5699 run
= path_join(arg_root
, user_runtime
, name
);
5703 assert_not_reached("Invalid scope");
5705 if (!path
|| (arg_runtime
&& !run
))
5709 if (access(path
, F_OK
) >= 0)
5710 return log_error_errno(EEXIST
, "Refusing to create \"%s\" because it would be overriden by \"%s\" anyway.",
5712 if (path2
&& access(path2
, F_OK
) >= 0)
5713 return log_error_errno(EEXIST
, "Refusing to create \"%s\" because it would be overriden by \"%s\" anyway.",
5725 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
) {
5726 char *tmp_new_path
, *ending
;
5731 assert(ret_new_path
);
5732 assert(ret_tmp_path
);
5734 ending
= strjoina(unit_name
, ".d/override.conf");
5735 r
= get_file_to_edit(ending
, user_home
, user_runtime
, &tmp_new_path
);
5739 r
= create_edit_temp_file(tmp_new_path
, tmp_new_path
, &tmp_tmp_path
);
5745 *ret_new_path
= tmp_new_path
;
5746 *ret_tmp_path
= tmp_tmp_path
;
5751 static int unit_file_create_copy(
5752 const char *unit_name
,
5753 const char *fragment_path
,
5754 const char *user_home
,
5755 const char *user_runtime
,
5756 char **ret_new_path
,
5757 char **ret_tmp_path
) {
5763 assert(fragment_path
);
5765 assert(ret_new_path
);
5766 assert(ret_tmp_path
);
5768 r
= get_file_to_edit(unit_name
, user_home
, user_runtime
, &tmp_new_path
);
5772 if (!path_equal(fragment_path
, tmp_new_path
) && access(tmp_new_path
, F_OK
) == 0) {
5775 r
= ask_char(&response
, "yn", "\"%s\" already exists. Overwrite with \"%s\"? [(y)es, (n)o] ", tmp_new_path
, fragment_path
);
5780 if (response
!= 'y') {
5781 log_warning("%s ignored", unit_name
);
5787 r
= create_edit_temp_file(tmp_new_path
, fragment_path
, &tmp_tmp_path
);
5789 log_error_errno(r
, "Failed to create temporary file for \"%s\": %m", tmp_new_path
);
5794 *ret_new_path
= tmp_new_path
;
5795 *ret_tmp_path
= tmp_tmp_path
;
5800 static int run_editor(char **paths
) {
5808 log_error_errno(errno
, "Failed to fork: %m");
5815 char **tmp_path
, **original_path
, *p
;
5819 argc
= strv_length(paths
)/2 + 1;
5820 args
= newa(const char*, argc
+ 1);
5823 STRV_FOREACH_PAIR(original_path
, tmp_path
, paths
) {
5824 args
[i
] = *tmp_path
;
5829 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
5830 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
5831 * we try to execute well known editors
5833 editor
= getenv("SYSTEMD_EDITOR");
5835 editor
= getenv("EDITOR");
5837 editor
= getenv("VISUAL");
5839 if (!isempty(editor
)) {
5841 execvp(editor
, (char* const*) args
);
5844 FOREACH_STRING(p
, "nano", "vim", "vi") {
5846 execvp(p
, (char* const*) args
);
5847 /* We do not fail if the editor doesn't exist
5848 * because we want to try each one of them before
5851 if (errno
!= ENOENT
) {
5852 log_error("Failed to execute %s: %m", editor
);
5853 _exit(EXIT_FAILURE
);
5857 log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR, $EDITOR or $VISUAL.");
5858 _exit(EXIT_FAILURE
);
5861 r
= wait_for_terminate_and_warn("editor", pid
, true);
5863 return log_error_errno(r
, "Failed to wait for child: %m");
5868 static int find_paths_to_edit(sd_bus
*bus
, char **names
, char ***paths
) {
5869 _cleanup_free_
char *user_home
= NULL
;
5870 _cleanup_free_
char *user_runtime
= NULL
;
5871 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
5872 bool avoid_bus_cache
;
5879 r
= init_home_and_lookup_paths(&user_home
, &user_runtime
, &lp
);
5883 avoid_bus_cache
= !bus
|| avoid_bus();
5885 STRV_FOREACH(name
, names
) {
5886 _cleanup_free_
char *path
= NULL
;
5887 char *new_path
, *tmp_path
;
5889 r
= unit_find_paths(bus
, *name
, avoid_bus_cache
, &lp
, &path
, NULL
);
5895 // FIXME: support units with path==NULL (no FragmentPath)
5896 log_error("No fragment exists for %s.", *name
);
5901 r
= unit_file_create_copy(*name
, path
, user_home
, user_runtime
, &new_path
, &tmp_path
);
5903 r
= unit_file_create_dropin(*name
, user_home
, user_runtime
, &new_path
, &tmp_path
);
5907 r
= strv_push_pair(paths
, new_path
, tmp_path
);
5915 static int edit(sd_bus
*bus
, char **args
) {
5916 _cleanup_strv_free_
char **names
= NULL
;
5917 _cleanup_strv_free_
char **paths
= NULL
;
5918 char **original
, **tmp
;
5924 log_error("Cannot edit units if not on a tty");
5928 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
5929 log_error("Cannot remotely edit units");
5933 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
5935 return log_error_errno(r
, "Failed to expand names: %m");
5937 r
= find_paths_to_edit(bus
, names
, &paths
);
5941 if (strv_isempty(paths
))
5944 r
= run_editor(paths
);
5948 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
5949 /* If the temporary file is empty we ignore it.
5950 * It's useful if the user wants to cancel its modification
5952 if (null_or_empty_path(*tmp
)) {
5953 log_warning("Editing \"%s\" canceled: temporary file is empty", *original
);
5956 r
= rename(*tmp
, *original
);
5958 r
= log_error_errno(errno
, "Failed to rename \"%s\" to \"%s\": %m", *tmp
, *original
);
5963 if (!arg_no_reload
&& bus
&& !avoid_bus())
5964 r
= daemon_reload(bus
, args
);
5967 STRV_FOREACH_PAIR(original
, tmp
, paths
)
5968 unlink_noerrno(*tmp
);
5973 static void systemctl_help(void) {
5975 pager_open_if_enabled();
5977 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
5978 "Query or send control commands to the systemd manager.\n\n"
5979 " -h --help Show this help\n"
5980 " --version Show package version\n"
5981 " --system Connect to system manager\n"
5982 " --user Connect to user service manager\n"
5983 " -H --host=[USER@]HOST\n"
5984 " Operate on remote host\n"
5985 " -M --machine=CONTAINER\n"
5986 " Operate on local container\n"
5987 " -t --type=TYPE List units of a particular type\n"
5988 " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n"
5989 " -p --property=NAME Show only properties by this name\n"
5990 " -a --all Show all loaded units/properties, including dead/empty\n"
5991 " ones. To list all units installed on the system, use\n"
5992 " the 'list-unit-files' command instead.\n"
5993 " -l --full Don't ellipsize unit names on output\n"
5994 " -r --recursive Show unit list of host and local containers\n"
5995 " --reverse Show reverse dependencies with 'list-dependencies'\n"
5996 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
5997 " queueing a new job\n"
5998 " --show-types When showing sockets, explicitly show their type\n"
5999 " -i --ignore-inhibitors\n"
6000 " When shutting down or sleeping, ignore inhibitors\n"
6001 " --kill-who=WHO Who to send signal to\n"
6002 " -s --signal=SIGNAL Which signal to send\n"
6003 " -q --quiet Suppress output\n"
6004 " --no-block Do not wait until operation finished\n"
6005 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6006 " --no-reload Don't reload daemon after en-/dis-abling unit files\n"
6007 " --no-legend Do not print a legend (column headers and hints)\n"
6008 " --no-pager Do not pipe output into a pager\n"
6009 " --no-ask-password\n"
6010 " Do not ask for system passwords\n"
6011 " --global Enable/disable unit files globally\n"
6012 " --runtime Enable unit files only temporarily until next reboot\n"
6013 " -f --force When enabling unit files, override existing symlinks\n"
6014 " When shutting down, execute action immediately\n"
6015 " --preset-mode= Apply only enable, only disable, or all presets\n"
6016 " --root=PATH Enable unit files in the specified root directory\n"
6017 " -n --lines=INTEGER Number of journal entries to show\n"
6018 " -o --output=STRING Change journal output mode (short, short-iso,\n"
6019 " short-precise, short-monotonic, verbose,\n"
6020 " export, json, json-pretty, json-sse, cat)\n"
6021 " --firmware-setup Tell the firmware to show the setup menu on next boot\n"
6022 " --plain Print unit dependencies as a list instead of a tree\n\n"
6024 " list-units [PATTERN...] List loaded units\n"
6025 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
6026 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
6027 " start NAME... Start (activate) one or more units\n"
6028 " stop NAME... Stop (deactivate) one or more units\n"
6029 " reload NAME... Reload one or more units\n"
6030 " restart NAME... Start or restart one or more units\n"
6031 " try-restart NAME... Restart one or more units if active\n"
6032 " reload-or-restart NAME... Reload one or more units if possible,\n"
6033 " otherwise start or restart\n"
6034 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
6035 " otherwise restart if active\n"
6036 " isolate NAME Start one unit and stop all others\n"
6037 " kill NAME... Send signal to processes of a unit\n"
6038 " is-active PATTERN... Check whether units are active\n"
6039 " is-failed PATTERN... Check whether units are failed\n"
6040 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
6041 " show [PATTERN...|JOB...] Show properties of one or more\n"
6042 " units/jobs or the manager\n"
6043 " cat PATTERN... Show files and drop-ins of one or more units\n"
6044 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
6045 " help PATTERN...|PID... Show manual for one or more units\n"
6046 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
6048 " list-dependencies [NAME] Recursively show units which are required\n"
6049 " or wanted by this unit or by which this\n"
6050 " unit is required or wanted\n\n"
6051 "Unit File Commands:\n"
6052 " list-unit-files [PATTERN...] List installed unit files\n"
6053 " enable NAME... Enable one or more unit files\n"
6054 " disable NAME... Disable one or more unit files\n"
6055 " reenable NAME... Reenable one or more unit files\n"
6056 " preset NAME... Enable/disable one or more unit files\n"
6057 " based on preset configuration\n"
6058 " preset-all Enable/disable all unit files based on\n"
6059 " preset configuration\n"
6060 " is-enabled NAME... Check whether unit files are enabled\n"
6061 " mask NAME... Mask one or more units\n"
6062 " unmask NAME... Unmask one or more units\n"
6063 " link PATH... Link one or more units files into\n"
6064 " the search path\n"
6065 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
6066 " on specified one or more units\n"
6067 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
6068 " on specified one or more units\n"
6069 " edit NAME... Edit one or more unit files\n"
6070 " get-default Get the name of the default target\n"
6071 " set-default NAME Set the default target\n\n"
6072 "Machine Commands:\n"
6073 " list-machines [PATTERN...] List local containers and host\n\n"
6075 " list-jobs [PATTERN...] List jobs\n"
6076 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
6077 "Snapshot Commands:\n"
6078 " snapshot [NAME] Create a snapshot\n"
6079 " delete NAME... Remove one or more snapshots\n\n"
6080 "Environment Commands:\n"
6081 " show-environment Dump environment\n"
6082 " set-environment NAME=VALUE... Set one or more environment variables\n"
6083 " unset-environment NAME... Unset one or more environment variables\n"
6084 " import-environment [NAME...] Import all or some environment variables\n\n"
6085 "Manager Lifecycle Commands:\n"
6086 " daemon-reload Reload systemd manager configuration\n"
6087 " daemon-reexec Reexecute systemd manager\n\n"
6088 "System Commands:\n"
6089 " is-system-running Check whether system is fully running\n"
6090 " default Enter system default mode\n"
6091 " rescue Enter system rescue mode\n"
6092 " emergency Enter system emergency mode\n"
6093 " halt Shut down and halt the system\n"
6094 " poweroff Shut down and power-off the system\n"
6095 " reboot [ARG] Shut down and reboot the system\n"
6096 " kexec Shut down and reboot the system with kexec\n"
6097 " exit Request user instance exit\n"
6098 " switch-root ROOT [INIT] Change to a different root file system\n"
6099 " suspend Suspend the system\n"
6100 " hibernate Hibernate the system\n"
6101 " hybrid-sleep Hibernate and suspend the system\n",
6102 program_invocation_short_name
);
6105 static void halt_help(void) {
6106 printf("%s [OPTIONS...]%s\n\n"
6107 "%s the system.\n\n"
6108 " --help Show this help\n"
6109 " --halt Halt the machine\n"
6110 " -p --poweroff Switch off the machine\n"
6111 " --reboot Reboot the machine\n"
6112 " -f --force Force immediate halt/power-off/reboot\n"
6113 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
6114 " -d --no-wtmp Don't write wtmp record\n"
6115 " --no-wall Don't send wall message before halt/power-off/reboot\n",
6116 program_invocation_short_name
,
6117 arg_action
== ACTION_REBOOT
? " [ARG]" : "",
6118 arg_action
== ACTION_REBOOT
? "Reboot" :
6119 arg_action
== ACTION_POWEROFF
? "Power off" :
6123 static void shutdown_help(void) {
6124 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
6125 "Shut down the system.\n\n"
6126 " --help Show this help\n"
6127 " -H --halt Halt the machine\n"
6128 " -P --poweroff Power-off the machine\n"
6129 " -r --reboot Reboot the machine\n"
6130 " -h Equivalent to --poweroff, overridden by --halt\n"
6131 " -k Don't halt/power-off/reboot, just send warnings\n"
6132 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6133 " -c Cancel a pending shutdown\n",
6134 program_invocation_short_name
);
6137 static void telinit_help(void) {
6138 printf("%s [OPTIONS...] {COMMAND}\n\n"
6139 "Send control commands to the init daemon.\n\n"
6140 " --help Show this help\n"
6141 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
6143 " 0 Power-off the machine\n"
6144 " 6 Reboot the machine\n"
6145 " 2, 3, 4, 5 Start runlevelX.target unit\n"
6146 " 1, s, S Enter rescue mode\n"
6147 " q, Q Reload init daemon configuration\n"
6148 " u, U Reexecute init daemon\n",
6149 program_invocation_short_name
);
6152 static void runlevel_help(void) {
6153 printf("%s [OPTIONS...]\n\n"
6154 "Prints the previous and current runlevel of the init system.\n\n"
6155 " --help Show this help\n",
6156 program_invocation_short_name
);
6159 static void help_types(void) {
6164 puts("Available unit types:");
6165 for (i
= 0; i
< _UNIT_TYPE_MAX
; i
++) {
6166 t
= unit_type_to_string(i
);
6172 static int systemctl_parse_argv(int argc
, char *argv
[]) {
6181 ARG_IGNORE_DEPENDENCIES
,
6193 ARG_NO_ASK_PASSWORD
,
6204 static const struct option options
[] = {
6205 { "help", no_argument
, NULL
, 'h' },
6206 { "version", no_argument
, NULL
, ARG_VERSION
},
6207 { "type", required_argument
, NULL
, 't' },
6208 { "property", required_argument
, NULL
, 'p' },
6209 { "all", no_argument
, NULL
, 'a' },
6210 { "reverse", no_argument
, NULL
, ARG_REVERSE
},
6211 { "after", no_argument
, NULL
, ARG_AFTER
},
6212 { "before", no_argument
, NULL
, ARG_BEFORE
},
6213 { "show-types", no_argument
, NULL
, ARG_SHOW_TYPES
},
6214 { "failed", no_argument
, NULL
, ARG_FAILED
}, /* compatibility only */
6215 { "full", no_argument
, NULL
, 'l' },
6216 { "job-mode", required_argument
, NULL
, ARG_JOB_MODE
},
6217 { "fail", no_argument
, NULL
, ARG_FAIL
}, /* compatibility only */
6218 { "irreversible", no_argument
, NULL
, ARG_IRREVERSIBLE
}, /* compatibility only */
6219 { "ignore-dependencies", no_argument
, NULL
, ARG_IGNORE_DEPENDENCIES
}, /* compatibility only */
6220 { "ignore-inhibitors", no_argument
, NULL
, 'i' },
6221 { "user", no_argument
, NULL
, ARG_USER
},
6222 { "system", no_argument
, NULL
, ARG_SYSTEM
},
6223 { "global", no_argument
, NULL
, ARG_GLOBAL
},
6224 { "no-block", no_argument
, NULL
, ARG_NO_BLOCK
},
6225 { "no-legend", no_argument
, NULL
, ARG_NO_LEGEND
},
6226 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
6227 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6228 { "quiet", no_argument
, NULL
, 'q' },
6229 { "root", required_argument
, NULL
, ARG_ROOT
},
6230 { "force", no_argument
, NULL
, ARG_FORCE
},
6231 { "no-reload", no_argument
, NULL
, ARG_NO_RELOAD
},
6232 { "kill-who", required_argument
, NULL
, ARG_KILL_WHO
},
6233 { "signal", required_argument
, NULL
, 's' },
6234 { "no-ask-password", no_argument
, NULL
, ARG_NO_ASK_PASSWORD
},
6235 { "host", required_argument
, NULL
, 'H' },
6236 { "machine", required_argument
, NULL
, 'M' },
6237 { "runtime", no_argument
, NULL
, ARG_RUNTIME
},
6238 { "lines", required_argument
, NULL
, 'n' },
6239 { "output", required_argument
, NULL
, 'o' },
6240 { "plain", no_argument
, NULL
, ARG_PLAIN
},
6241 { "state", required_argument
, NULL
, ARG_STATE
},
6242 { "recursive", no_argument
, NULL
, 'r' },
6243 { "preset-mode", required_argument
, NULL
, ARG_PRESET_MODE
},
6244 { "firmware-setup", no_argument
, NULL
, ARG_FIRMWARE_SETUP
},
6253 while ((c
= getopt_long(argc
, argv
, "ht:p:alqfs:H:M:n:o:ir", options
, NULL
)) >= 0)
6262 puts(PACKAGE_STRING
);
6263 puts(SYSTEMD_FEATURES
);
6267 const char *word
, *state
;
6270 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
6271 _cleanup_free_
char *type
;
6273 type
= strndup(word
, size
);
6277 if (streq(type
, "help")) {
6282 if (unit_type_from_string(type
) >= 0) {
6283 if (strv_push(&arg_types
, type
))
6289 /* It's much nicer to use --state= for
6290 * load states, but let's support this
6291 * in --types= too for compatibility
6292 * with old versions */
6293 if (unit_load_state_from_string(optarg
) >= 0) {
6294 if (strv_push(&arg_states
, type
) < 0)
6300 log_error("Unknown unit type or load state '%s'.", type
);
6301 log_info("Use -t help to see a list of allowed values.");
6309 /* Make sure that if the empty property list
6310 was specified, we won't show any properties. */
6311 if (isempty(optarg
) && !arg_properties
) {
6312 arg_properties
= new0(char*, 1);
6313 if (!arg_properties
)
6316 const char *word
, *state
;
6319 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
6322 prop
= strndup(word
, size
);
6326 if (strv_consume(&arg_properties
, prop
) < 0)
6331 /* If the user asked for a particular
6332 * property, show it to him, even if it is
6344 arg_dependency
= DEPENDENCY_REVERSE
;
6348 arg_dependency
= DEPENDENCY_AFTER
;
6352 arg_dependency
= DEPENDENCY_BEFORE
;
6355 case ARG_SHOW_TYPES
:
6356 arg_show_types
= true;
6360 arg_job_mode
= optarg
;
6364 arg_job_mode
= "fail";
6367 case ARG_IRREVERSIBLE
:
6368 arg_job_mode
= "replace-irreversibly";
6371 case ARG_IGNORE_DEPENDENCIES
:
6372 arg_job_mode
= "ignore-dependencies";
6376 arg_scope
= UNIT_FILE_USER
;
6380 arg_scope
= UNIT_FILE_SYSTEM
;
6384 arg_scope
= UNIT_FILE_GLOBAL
;
6388 arg_no_block
= true;
6392 arg_no_legend
= true;
6396 arg_no_pager
= true;
6412 if (strv_extend(&arg_states
, "failed") < 0)
6430 arg_no_reload
= true;
6434 arg_kill_who
= optarg
;
6438 if ((arg_signal
= signal_from_string_try_harder(optarg
)) < 0) {
6439 log_error("Failed to parse signal string %s.", optarg
);
6444 case ARG_NO_ASK_PASSWORD
:
6445 arg_ask_password
= false;
6449 arg_transport
= BUS_TRANSPORT_REMOTE
;
6454 arg_transport
= BUS_TRANSPORT_MACHINE
;
6463 if (safe_atou(optarg
, &arg_lines
) < 0) {
6464 log_error("Failed to parse lines '%s'", optarg
);
6470 arg_output
= output_mode_from_string(optarg
);
6471 if (arg_output
< 0) {
6472 log_error("Unknown output '%s'.", optarg
);
6478 arg_ignore_inhibitors
= true;
6485 case ARG_FIRMWARE_SETUP
:
6486 arg_firmware_setup
= true;
6490 const char *word
, *state
;
6493 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
6496 s
= strndup(word
, size
);
6500 if (strv_consume(&arg_states
, s
) < 0)
6507 if (geteuid() != 0) {
6508 log_error("--recursive requires root privileges.");
6512 arg_recursive
= true;
6515 case ARG_PRESET_MODE
:
6517 arg_preset_mode
= unit_file_preset_mode_from_string(optarg
);
6518 if (arg_preset_mode
< 0) {
6519 log_error("Failed to parse preset mode: %s.", optarg
);
6529 assert_not_reached("Unhandled option");
6532 if (arg_transport
!= BUS_TRANSPORT_LOCAL
&& arg_scope
!= UNIT_FILE_SYSTEM
) {
6533 log_error("Cannot access user instance remotely.");
6540 static int halt_parse_argv(int argc
, char *argv
[]) {
6549 static const struct option options
[] = {
6550 { "help", no_argument
, NULL
, ARG_HELP
},
6551 { "halt", no_argument
, NULL
, ARG_HALT
},
6552 { "poweroff", no_argument
, NULL
, 'p' },
6553 { "reboot", no_argument
, NULL
, ARG_REBOOT
},
6554 { "force", no_argument
, NULL
, 'f' },
6555 { "wtmp-only", no_argument
, NULL
, 'w' },
6556 { "no-wtmp", no_argument
, NULL
, 'd' },
6557 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6566 if (utmp_get_runlevel(&runlevel
, NULL
) >= 0)
6567 if (runlevel
== '0' || runlevel
== '6')
6570 while ((c
= getopt_long(argc
, argv
, "pfwdnih", options
, NULL
)) >= 0)
6578 arg_action
= ACTION_HALT
;
6582 if (arg_action
!= ACTION_REBOOT
)
6583 arg_action
= ACTION_POWEROFF
;
6587 arg_action
= ACTION_REBOOT
;
6609 /* Compatibility nops */
6616 assert_not_reached("Unhandled option");
6619 if (arg_action
== ACTION_REBOOT
&& (argc
== optind
|| argc
== optind
+ 1)) {
6620 r
= update_reboot_param_file(argc
== optind
+ 1 ? argv
[optind
] : NULL
);
6623 } else if (optind
< argc
) {
6624 log_error("Too many arguments.");
6631 static int parse_time_spec(const char *t
, usec_t
*_u
) {
6635 if (streq(t
, "now"))
6637 else if (!strchr(t
, ':')) {
6640 if (safe_atou64(t
, &u
) < 0)
6643 *_u
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
* u
;
6652 hour
= strtol(t
, &e
, 10);
6653 if (errno
> 0 || *e
!= ':' || hour
< 0 || hour
> 23)
6656 minute
= strtol(e
+1, &e
, 10);
6657 if (errno
> 0 || *e
!= 0 || minute
< 0 || minute
> 59)
6660 n
= now(CLOCK_REALTIME
);
6661 s
= (time_t) (n
/ USEC_PER_SEC
);
6663 assert_se(localtime_r(&s
, &tm
));
6665 tm
.tm_hour
= (int) hour
;
6666 tm
.tm_min
= (int) minute
;
6669 assert_se(s
= mktime(&tm
));
6671 *_u
= (usec_t
) s
* USEC_PER_SEC
;
6674 *_u
+= USEC_PER_DAY
;
6680 static int shutdown_parse_argv(int argc
, char *argv
[]) {
6687 static const struct option options
[] = {
6688 { "help", no_argument
, NULL
, ARG_HELP
},
6689 { "halt", no_argument
, NULL
, 'H' },
6690 { "poweroff", no_argument
, NULL
, 'P' },
6691 { "reboot", no_argument
, NULL
, 'r' },
6692 { "kexec", no_argument
, NULL
, 'K' }, /* not documented extension */
6693 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6702 while ((c
= getopt_long(argc
, argv
, "HPrhkKt:afFc", options
, NULL
)) >= 0)
6710 arg_action
= ACTION_HALT
;
6714 arg_action
= ACTION_POWEROFF
;
6719 arg_action
= ACTION_KEXEC
;
6721 arg_action
= ACTION_REBOOT
;
6725 arg_action
= ACTION_KEXEC
;
6729 if (arg_action
!= ACTION_HALT
)
6730 arg_action
= ACTION_POWEROFF
;
6745 /* Compatibility nops */
6749 arg_action
= ACTION_CANCEL_SHUTDOWN
;
6756 assert_not_reached("Unhandled option");
6759 if (argc
> optind
&& arg_action
!= ACTION_CANCEL_SHUTDOWN
) {
6760 r
= parse_time_spec(argv
[optind
], &arg_when
);
6762 log_error("Failed to parse time specification: %s", argv
[optind
]);
6766 arg_when
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
;
6768 if (argc
> optind
&& arg_action
== ACTION_CANCEL_SHUTDOWN
)
6769 /* No time argument for shutdown cancel */
6770 arg_wall
= argv
+ optind
;
6771 else if (argc
> optind
+ 1)
6772 /* We skip the time argument */
6773 arg_wall
= argv
+ optind
+ 1;
6780 static int telinit_parse_argv(int argc
, char *argv
[]) {
6787 static const struct option options
[] = {
6788 { "help", no_argument
, NULL
, ARG_HELP
},
6789 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6793 static const struct {
6797 { '0', ACTION_POWEROFF
},
6798 { '6', ACTION_REBOOT
},
6799 { '1', ACTION_RESCUE
},
6800 { '2', ACTION_RUNLEVEL2
},
6801 { '3', ACTION_RUNLEVEL3
},
6802 { '4', ACTION_RUNLEVEL4
},
6803 { '5', ACTION_RUNLEVEL5
},
6804 { 's', ACTION_RESCUE
},
6805 { 'S', ACTION_RESCUE
},
6806 { 'q', ACTION_RELOAD
},
6807 { 'Q', ACTION_RELOAD
},
6808 { 'u', ACTION_REEXEC
},
6809 { 'U', ACTION_REEXEC
}
6818 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
6833 assert_not_reached("Unhandled option");
6836 if (optind
>= argc
) {
6837 log_error("%s: required argument missing.",
6838 program_invocation_short_name
);
6842 if (optind
+ 1 < argc
) {
6843 log_error("Too many arguments.");
6847 if (strlen(argv
[optind
]) != 1) {
6848 log_error("Expected single character argument.");
6852 for (i
= 0; i
< ELEMENTSOF(table
); i
++)
6853 if (table
[i
].from
== argv
[optind
][0])
6856 if (i
>= ELEMENTSOF(table
)) {
6857 log_error("Unknown command '%s'.", argv
[optind
]);
6861 arg_action
= table
[i
].to
;
6868 static int runlevel_parse_argv(int argc
, char *argv
[]) {
6874 static const struct option options
[] = {
6875 { "help", no_argument
, NULL
, ARG_HELP
},
6884 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
6895 assert_not_reached("Unhandled option");
6898 if (optind
< argc
) {
6899 log_error("Too many arguments.");
6906 static int parse_argv(int argc
, char *argv
[]) {
6910 if (program_invocation_short_name
) {
6912 if (strstr(program_invocation_short_name
, "halt")) {
6913 arg_action
= ACTION_HALT
;
6914 return halt_parse_argv(argc
, argv
);
6915 } else if (strstr(program_invocation_short_name
, "poweroff")) {
6916 arg_action
= ACTION_POWEROFF
;
6917 return halt_parse_argv(argc
, argv
);
6918 } else if (strstr(program_invocation_short_name
, "reboot")) {
6920 arg_action
= ACTION_KEXEC
;
6922 arg_action
= ACTION_REBOOT
;
6923 return halt_parse_argv(argc
, argv
);
6924 } else if (strstr(program_invocation_short_name
, "shutdown")) {
6925 arg_action
= ACTION_POWEROFF
;
6926 return shutdown_parse_argv(argc
, argv
);
6927 } else if (strstr(program_invocation_short_name
, "init")) {
6929 if (sd_booted() > 0) {
6930 arg_action
= _ACTION_INVALID
;
6931 return telinit_parse_argv(argc
, argv
);
6933 /* Hmm, so some other init system is
6934 * running, we need to forward this
6935 * request to it. For now we simply
6936 * guess that it is Upstart. */
6938 execv(TELINIT
, argv
);
6940 log_error("Couldn't find an alternative telinit implementation to spawn.");
6944 } else if (strstr(program_invocation_short_name
, "runlevel")) {
6945 arg_action
= ACTION_RUNLEVEL
;
6946 return runlevel_parse_argv(argc
, argv
);
6950 arg_action
= ACTION_SYSTEMCTL
;
6951 return systemctl_parse_argv(argc
, argv
);
6954 _pure_
static int action_to_runlevel(void) {
6956 static const char table
[_ACTION_MAX
] = {
6957 [ACTION_HALT
] = '0',
6958 [ACTION_POWEROFF
] = '0',
6959 [ACTION_REBOOT
] = '6',
6960 [ACTION_RUNLEVEL2
] = '2',
6961 [ACTION_RUNLEVEL3
] = '3',
6962 [ACTION_RUNLEVEL4
] = '4',
6963 [ACTION_RUNLEVEL5
] = '5',
6964 [ACTION_RESCUE
] = '1'
6967 assert(arg_action
< _ACTION_MAX
);
6969 return table
[arg_action
];
6972 static int talk_initctl(void) {
6974 struct init_request request
= {
6975 .magic
= INIT_MAGIC
,
6977 .cmd
= INIT_CMD_RUNLVL
6980 _cleanup_close_
int fd
= -1;
6984 rl
= action_to_runlevel();
6988 request
.runlevel
= rl
;
6990 fd
= open(INIT_FIFO
, O_WRONLY
|O_NDELAY
|O_CLOEXEC
|O_NOCTTY
);
6992 if (errno
== ENOENT
)
6995 log_error_errno(errno
, "Failed to open "INIT_FIFO
": %m");
6999 r
= loop_write(fd
, &request
, sizeof(request
), false);
7001 return log_error_errno(r
, "Failed to write to "INIT_FIFO
": %m");
7006 static int systemctl_main(sd_bus
*bus
, int argc
, char *argv
[], int bus_error
) {
7008 static const struct {
7016 int (* const dispatch
)(sd_bus
*bus
, char **args
);
7022 { "list-units", MORE
, 0, list_units
},
7023 { "list-unit-files", MORE
, 1, list_unit_files
, NOBUS
},
7024 { "list-sockets", MORE
, 1, list_sockets
},
7025 { "list-timers", MORE
, 1, list_timers
},
7026 { "list-jobs", MORE
, 1, list_jobs
},
7027 { "list-machines", MORE
, 1, list_machines
},
7028 { "clear-jobs", EQUAL
, 1, daemon_reload
},
7029 { "cancel", MORE
, 2, cancel_job
},
7030 { "start", MORE
, 2, start_unit
},
7031 { "stop", MORE
, 2, start_unit
},
7032 { "condstop", MORE
, 2, start_unit
}, /* For compatibility with ALTLinux */
7033 { "reload", MORE
, 2, start_unit
},
7034 { "restart", MORE
, 2, start_unit
},
7035 { "try-restart", MORE
, 2, start_unit
},
7036 { "reload-or-restart", MORE
, 2, start_unit
},
7037 { "reload-or-try-restart", MORE
, 2, start_unit
},
7038 { "force-reload", MORE
, 2, start_unit
}, /* For compatibility with SysV */
7039 { "condreload", MORE
, 2, start_unit
}, /* For compatibility with ALTLinux */
7040 { "condrestart", MORE
, 2, start_unit
}, /* For compatibility with RH */
7041 { "isolate", EQUAL
, 2, start_unit
},
7042 { "kill", MORE
, 2, kill_unit
},
7043 { "is-active", MORE
, 2, check_unit_active
},
7044 { "check", MORE
, 2, check_unit_active
},
7045 { "is-failed", MORE
, 2, check_unit_failed
},
7046 { "show", MORE
, 1, show
},
7047 { "cat", MORE
, 2, cat
, NOBUS
},
7048 { "status", MORE
, 1, show
},
7049 { "help", MORE
, 2, show
},
7050 { "snapshot", LESS
, 2, snapshot
},
7051 { "delete", MORE
, 2, delete_snapshot
},
7052 { "daemon-reload", EQUAL
, 1, daemon_reload
},
7053 { "daemon-reexec", EQUAL
, 1, daemon_reload
},
7054 { "show-environment", EQUAL
, 1, show_environment
},
7055 { "set-environment", MORE
, 2, set_environment
},
7056 { "unset-environment", MORE
, 2, set_environment
},
7057 { "import-environment", MORE
, 1, import_environment
},
7058 { "halt", EQUAL
, 1, start_special
, FORCE
},
7059 { "poweroff", EQUAL
, 1, start_special
, FORCE
},
7060 { "reboot", MORE
, 1, start_special
, FORCE
},
7061 { "kexec", EQUAL
, 1, start_special
},
7062 { "suspend", EQUAL
, 1, start_special
},
7063 { "hibernate", EQUAL
, 1, start_special
},
7064 { "hybrid-sleep", EQUAL
, 1, start_special
},
7065 { "default", EQUAL
, 1, start_special
},
7066 { "rescue", EQUAL
, 1, start_special
},
7067 { "emergency", EQUAL
, 1, start_special
},
7068 { "exit", EQUAL
, 1, start_special
},
7069 { "reset-failed", MORE
, 1, reset_failed
},
7070 { "enable", MORE
, 2, enable_unit
, NOBUS
},
7071 { "disable", MORE
, 2, enable_unit
, NOBUS
},
7072 { "is-enabled", MORE
, 2, unit_is_enabled
, NOBUS
},
7073 { "reenable", MORE
, 2, enable_unit
, NOBUS
},
7074 { "preset", MORE
, 2, enable_unit
, NOBUS
},
7075 { "preset-all", EQUAL
, 1, preset_all
, NOBUS
},
7076 { "mask", MORE
, 2, enable_unit
, NOBUS
},
7077 { "unmask", MORE
, 2, enable_unit
, NOBUS
},
7078 { "link", MORE
, 2, enable_unit
, NOBUS
},
7079 { "switch-root", MORE
, 2, switch_root
},
7080 { "list-dependencies", LESS
, 2, list_dependencies
},
7081 { "set-default", EQUAL
, 2, set_default
, NOBUS
},
7082 { "get-default", EQUAL
, 1, get_default
, NOBUS
},
7083 { "set-property", MORE
, 3, set_property
},
7084 { "is-system-running", EQUAL
, 1, is_system_running
},
7085 { "add-wants", MORE
, 3, add_dependency
, NOBUS
},
7086 { "add-requires", MORE
, 3, add_dependency
, NOBUS
},
7087 { "edit", MORE
, 2, edit
, NOBUS
},
7096 left
= argc
- optind
;
7098 /* Special rule: no arguments (left == 0) means "list-units" */
7100 if (streq(argv
[optind
], "help") && !argv
[optind
+1]) {
7101 log_error("This command expects one or more "
7102 "unit names. Did you mean --help?");
7106 for (; verb
->verb
; verb
++)
7107 if (streq(argv
[optind
], verb
->verb
))
7110 log_error("Unknown operation '%s'.", argv
[optind
]);
7115 switch (verb
->argc_cmp
) {
7118 if (left
!= verb
->argc
) {
7119 log_error("Invalid number of arguments.");
7126 if (left
< verb
->argc
) {
7127 log_error("Too few arguments.");
7134 if (left
> verb
->argc
) {
7135 log_error("Too many arguments.");
7142 assert_not_reached("Unknown comparison operator.");
7145 /* Require a bus connection for all operations but
7147 if (verb
->bus
== NOBUS
) {
7148 if (!bus
&& !avoid_bus()) {
7149 log_error_errno(bus_error
, "Failed to get D-Bus connection: %m");
7154 if (running_in_chroot() > 0) {
7155 log_info("Running in chroot, ignoring request.");
7159 if ((verb
->bus
!= FORCE
|| arg_force
<= 0) && !bus
) {
7160 log_error_errno(bus_error
, "Failed to get D-Bus connection: %m");
7165 /* Increase max number of open files to 16K if we can, we
7166 * might needs this when browsing journal files, which might
7167 * be split up into many files. */
7168 setrlimit_closest(RLIMIT_NOFILE
, &RLIMIT_MAKE_CONST(16384));
7170 return verb
->dispatch(bus
, argv
+ optind
);
7173 static int send_shutdownd(usec_t t
, char mode
, bool dry_run
, bool warn
, const char *message
) {
7175 struct sd_shutdown_command c
= {
7182 union sockaddr_union sockaddr
= {
7183 .un
.sun_family
= AF_UNIX
,
7184 .un
.sun_path
= "/run/systemd/shutdownd",
7187 struct iovec iovec
[2] = {{
7188 .iov_base
= (char*) &c
,
7189 .iov_len
= offsetof(struct sd_shutdown_command
, wall_message
),
7192 struct msghdr msghdr
= {
7193 .msg_name
= &sockaddr
,
7194 .msg_namelen
= offsetof(struct sockaddr_un
, sun_path
)
7195 + strlen("/run/systemd/shutdownd"),
7200 _cleanup_close_
int fd
;
7202 fd
= socket(AF_UNIX
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0);
7206 if (!isempty(message
)) {
7207 iovec
[1].iov_base
= (char*) message
;
7208 iovec
[1].iov_len
= strlen(message
);
7209 msghdr
.msg_iovlen
++;
7212 if (sendmsg(fd
, &msghdr
, MSG_NOSIGNAL
) < 0)
7218 static int reload_with_fallback(sd_bus
*bus
) {
7221 /* First, try systemd via D-Bus. */
7222 if (daemon_reload(bus
, NULL
) >= 0)
7226 /* Nothing else worked, so let's try signals */
7227 assert(arg_action
== ACTION_RELOAD
|| arg_action
== ACTION_REEXEC
);
7229 if (kill(1, arg_action
== ACTION_RELOAD
? SIGHUP
: SIGTERM
) < 0)
7230 return log_error_errno(errno
, "kill() failed: %m");
7235 static int start_with_fallback(sd_bus
*bus
) {
7238 /* First, try systemd via D-Bus. */
7239 if (start_unit(bus
, NULL
) >= 0)
7243 /* Nothing else worked, so let's try
7245 if (talk_initctl() > 0)
7248 log_error("Failed to talk to init daemon.");
7252 warn_wall(arg_action
);
7256 static int halt_now(enum action a
) {
7258 /* The kernel will automaticall flush ATA disks and suchlike
7259 * on reboot(), but the file systems need to be synce'd
7260 * explicitly in advance. */
7263 /* Make sure C-A-D is handled by the kernel from this point
7265 reboot(RB_ENABLE_CAD
);
7270 log_info("Halting.");
7271 reboot(RB_HALT_SYSTEM
);
7274 case ACTION_POWEROFF
:
7275 log_info("Powering off.");
7276 reboot(RB_POWER_OFF
);
7279 case ACTION_REBOOT
: {
7280 _cleanup_free_
char *param
= NULL
;
7282 if (read_one_line_file(REBOOT_PARAM_FILE
, ¶m
) >= 0) {
7283 log_info("Rebooting with argument '%s'.", param
);
7284 syscall(SYS_reboot
, LINUX_REBOOT_MAGIC1
, LINUX_REBOOT_MAGIC2
,
7285 LINUX_REBOOT_CMD_RESTART2
, param
);
7288 log_info("Rebooting.");
7289 reboot(RB_AUTOBOOT
);
7294 assert_not_reached("Unknown action.");
7298 static int halt_main(sd_bus
*bus
) {
7301 r
= check_inhibitors(bus
, arg_action
);
7305 if (geteuid() != 0) {
7306 /* Try logind if we are a normal user and no special
7307 * mode applies. Maybe PolicyKit allows us to shutdown
7310 if (arg_when
<= 0 &&
7313 (arg_action
== ACTION_POWEROFF
||
7314 arg_action
== ACTION_REBOOT
)) {
7315 r
= reboot_with_logind(bus
, arg_action
);
7320 log_error("Must be root.");
7325 _cleanup_free_
char *m
;
7327 m
= strv_join(arg_wall
, " ");
7331 r
= send_shutdownd(arg_when
,
7332 arg_action
== ACTION_HALT
? 'H' :
7333 arg_action
== ACTION_POWEROFF
? 'P' :
7334 arg_action
== ACTION_KEXEC
? 'K' :
7341 log_warning_errno(r
, "Failed to talk to shutdownd, proceeding with immediate shutdown: %m");
7343 char date
[FORMAT_TIMESTAMP_MAX
];
7345 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
7346 format_timestamp(date
, sizeof(date
), arg_when
));
7351 if (!arg_dry
&& !arg_force
)
7352 return start_with_fallback(bus
);
7355 if (sd_booted() > 0)
7356 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
7358 r
= utmp_put_shutdown();
7360 log_warning_errno(r
, "Failed to write utmp record: %m");
7367 r
= halt_now(arg_action
);
7368 log_error_errno(r
, "Failed to reboot: %m");
7373 static int runlevel_main(void) {
7374 int r
, runlevel
, previous
;
7376 r
= utmp_get_runlevel(&runlevel
, &previous
);
7383 previous
<= 0 ? 'N' : previous
,
7384 runlevel
<= 0 ? 'N' : runlevel
);
7389 int main(int argc
, char*argv
[]) {
7390 _cleanup_bus_close_unref_ sd_bus
*bus
= NULL
;
7393 setlocale(LC_ALL
, "");
7394 log_parse_environment();
7397 /* Explicitly not on_tty() to avoid setting cached value.
7398 * This becomes relevant for piping output which might be
7400 original_stdout_is_tty
= isatty(STDOUT_FILENO
);
7402 r
= parse_argv(argc
, argv
);
7406 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
7407 * let's shortcut this */
7408 if (arg_action
== ACTION_RUNLEVEL
) {
7409 r
= runlevel_main();
7413 if (running_in_chroot() > 0 && arg_action
!= ACTION_SYSTEMCTL
) {
7414 log_info("Running in chroot, ignoring request.");
7420 r
= bus_open_transport_systemd(arg_transport
, arg_host
, arg_scope
!= UNIT_FILE_SYSTEM
, &bus
);
7423 sd_bus_set_allow_interactive_authorization(bus
, arg_ask_password
);
7425 /* systemctl_main() will print an error message for the bus
7426 * connection, but only if it needs to */
7428 switch (arg_action
) {
7430 case ACTION_SYSTEMCTL
:
7431 r
= systemctl_main(bus
, argc
, argv
, r
);
7435 case ACTION_POWEROFF
:
7441 case ACTION_RUNLEVEL2
:
7442 case ACTION_RUNLEVEL3
:
7443 case ACTION_RUNLEVEL4
:
7444 case ACTION_RUNLEVEL5
:
7446 case ACTION_EMERGENCY
:
7447 case ACTION_DEFAULT
:
7448 r
= start_with_fallback(bus
);
7453 r
= reload_with_fallback(bus
);
7456 case ACTION_CANCEL_SHUTDOWN
: {
7457 _cleanup_free_
char *m
= NULL
;
7460 m
= strv_join(arg_wall
, " ");
7467 r
= send_shutdownd(arg_when
, SD_SHUTDOWN_NONE
, false, !arg_no_wall
, m
);
7469 log_warning_errno(r
, "Failed to talk to shutdownd, shutdown hasn't been cancelled: %m");
7473 case ACTION_RUNLEVEL
:
7474 case _ACTION_INVALID
:
7476 assert_not_reached("Unknown action");
7481 ask_password_agent_close();
7482 polkit_agent_close();
7484 strv_free(arg_types
);
7485 strv_free(arg_states
);
7486 strv_free(arg_properties
);
7488 return r
< 0 ? EXIT_FAILURE
: r
;