1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
7 Copyright 2013 Marc-Antoine Perennou
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include <sys/reboot.h>
24 #include <linux/reboot.h>
33 #include <sys/socket.h>
36 #include "sd-daemon.h"
43 #include "utmp-wtmp.h"
46 #include "path-util.h"
48 #include "cgroup-show.h"
49 #include "cgroup-util.h"
51 #include "path-lookup.h"
52 #include "exit-status.h"
54 #include "unit-name.h"
56 #include "spawn-ask-password-agent.h"
57 #include "spawn-polkit-agent.h"
59 #include "logs-show.h"
60 #include "socket-util.h"
65 #include "bus-message.h"
66 #include "bus-error.h"
67 #include "bus-common-errors.h"
71 #include "formats-util.h"
72 #include "process-util.h"
73 #include "terminal-util.h"
75 static char **arg_types
= NULL
;
76 static char **arg_states
= NULL
;
77 static char **arg_properties
= NULL
;
78 static bool arg_all
= false;
79 static enum dependency
{
85 } arg_dependency
= DEPENDENCY_FORWARD
;
86 static const char *arg_job_mode
= "replace";
87 static UnitFileScope arg_scope
= UNIT_FILE_SYSTEM
;
88 static bool arg_no_block
= false;
89 static bool arg_no_legend
= false;
90 static bool arg_no_pager
= false;
91 static bool arg_no_wtmp
= false;
92 static bool arg_no_wall
= false;
93 static bool arg_no_reload
= false;
94 static bool arg_show_types
= false;
95 static bool arg_ignore_inhibitors
= false;
96 static bool arg_dry
= false;
97 static bool arg_quiet
= false;
98 static bool arg_full
= false;
99 static bool arg_recursive
= false;
100 static int arg_force
= 0;
101 static bool arg_ask_password
= true;
102 static bool arg_runtime
= false;
103 static UnitFilePresetMode arg_preset_mode
= UNIT_FILE_PRESET_FULL
;
104 static char **arg_wall
= NULL
;
105 static const char *arg_kill_who
= NULL
;
106 static int arg_signal
= SIGTERM
;
107 static const char *arg_root
= NULL
;
108 static usec_t arg_when
= 0;
130 ACTION_CANCEL_SHUTDOWN
,
132 } arg_action
= ACTION_SYSTEMCTL
;
133 static BusTransport arg_transport
= BUS_TRANSPORT_LOCAL
;
134 static char *arg_host
= NULL
;
135 static unsigned arg_lines
= 10;
136 static OutputMode arg_output
= OUTPUT_SHORT
;
137 static bool arg_plain
= false;
138 static bool arg_firmware_setup
= false;
140 static bool original_stdout_is_tty
;
142 static int daemon_reload(sd_bus
*bus
, char **args
);
143 static int halt_now(enum action a
);
144 static int check_one_unit(sd_bus
*bus
, const char *name
, const char *good_states
, bool quiet
);
146 static char** strv_skip_first(char **strv
) {
147 if (strv_length(strv
) > 0)
152 static void pager_open_if_enabled(void) {
160 static void ask_password_agent_open_if_enabled(void) {
162 /* Open the password agent as a child process if necessary */
164 if (!arg_ask_password
)
167 if (arg_scope
!= UNIT_FILE_SYSTEM
)
170 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
173 ask_password_agent_open();
176 static void polkit_agent_open_if_enabled(void) {
178 /* Open the polkit agent as a child process if necessary */
180 if (!arg_ask_password
)
183 if (arg_scope
!= UNIT_FILE_SYSTEM
)
186 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
192 static OutputFlags
get_output_flags(void) {
194 arg_all
* OUTPUT_SHOW_ALL
|
195 arg_full
* OUTPUT_FULL_WIDTH
|
196 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH
|
197 on_tty() * OUTPUT_COLOR
|
198 !arg_quiet
* OUTPUT_WARN_CUTOFF
;
201 static int translate_bus_error_to_exit_status(int r
, const sd_bus_error
*error
) {
204 if (!sd_bus_error_is_set(error
))
207 if (sd_bus_error_has_name(error
, SD_BUS_ERROR_ACCESS_DENIED
) ||
208 sd_bus_error_has_name(error
, BUS_ERROR_ONLY_BY_DEPENDENCY
) ||
209 sd_bus_error_has_name(error
, BUS_ERROR_NO_ISOLATION
) ||
210 sd_bus_error_has_name(error
, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE
))
211 return EXIT_NOPERMISSION
;
213 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
))
214 return EXIT_NOTINSTALLED
;
216 if (sd_bus_error_has_name(error
, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE
) ||
217 sd_bus_error_has_name(error
, SD_BUS_ERROR_NOT_SUPPORTED
))
218 return EXIT_NOTIMPLEMENTED
;
220 if (sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
))
221 return EXIT_NOTCONFIGURED
;
229 static void warn_wall(enum action a
) {
230 static const char *table
[_ACTION_MAX
] = {
231 [ACTION_HALT
] = "The system is going down for system halt NOW!",
232 [ACTION_REBOOT
] = "The system is going down for reboot NOW!",
233 [ACTION_POWEROFF
] = "The system is going down for power-off NOW!",
234 [ACTION_KEXEC
] = "The system is going down for kexec reboot NOW!",
235 [ACTION_RESCUE
] = "The system is going down to rescue mode NOW!",
236 [ACTION_EMERGENCY
] = "The system is going down to emergency mode NOW!",
237 [ACTION_CANCEL_SHUTDOWN
] = "The system shutdown has been cancelled NOW!"
244 _cleanup_free_
char *p
;
246 p
= strv_join(arg_wall
, " ");
253 utmp_wall(p
, NULL
, NULL
, NULL
, NULL
);
261 utmp_wall(table
[a
], NULL
, NULL
, NULL
, NULL
);
264 static bool avoid_bus(void) {
266 if (running_in_chroot() > 0)
269 if (sd_booted() <= 0)
272 if (!isempty(arg_root
))
275 if (arg_scope
== UNIT_FILE_GLOBAL
)
281 static int compare_unit_info(const void *a
, const void *b
) {
282 const UnitInfo
*u
= a
, *v
= b
;
286 /* First, order by machine */
287 if (!u
->machine
&& v
->machine
)
289 if (u
->machine
&& !v
->machine
)
291 if (u
->machine
&& v
->machine
) {
292 r
= strcasecmp(u
->machine
, v
->machine
);
297 /* Second, order by unit type */
298 d1
= strrchr(u
->id
, '.');
299 d2
= strrchr(v
->id
, '.');
301 r
= strcasecmp(d1
, d2
);
306 /* Third, order by name */
307 return strcasecmp(u
->id
, v
->id
);
310 static bool output_show_unit(const UnitInfo
*u
, char **patterns
) {
311 if (!strv_fnmatch_or_empty(patterns
, u
->id
, FNM_NOESCAPE
))
317 dot
= strrchr(u
->id
, '.');
321 if (!strv_find(arg_types
, dot
+1))
331 if (streq(u
->active_state
, "inactive") || u
->following
[0])
337 static int output_units_list(const UnitInfo
*unit_infos
, unsigned c
) {
338 unsigned circle_len
= 0, id_len
, max_id_len
, load_len
, active_len
, sub_len
, job_len
, desc_len
;
340 unsigned n_shown
= 0;
343 max_id_len
= strlen("UNIT");
344 load_len
= strlen("LOAD");
345 active_len
= strlen("ACTIVE");
346 sub_len
= strlen("SUB");
347 job_len
= strlen("JOB");
350 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
351 max_id_len
= MAX(max_id_len
, strlen(u
->id
) + (u
->machine
? strlen(u
->machine
)+1 : 0));
352 load_len
= MAX(load_len
, strlen(u
->load_state
));
353 active_len
= MAX(active_len
, strlen(u
->active_state
));
354 sub_len
= MAX(sub_len
, strlen(u
->sub_state
));
356 if (u
->job_id
!= 0) {
357 job_len
= MAX(job_len
, strlen(u
->job_type
));
361 if (!arg_no_legend
&&
362 (streq(u
->active_state
, "failed") ||
363 STR_IN_SET(u
->load_state
, "error", "not-found", "masked")))
367 if (!arg_full
&& original_stdout_is_tty
) {
370 id_len
= MIN(max_id_len
, 25u);
371 basic_len
= circle_len
+ 5 + id_len
+ 5 + active_len
+ sub_len
;
374 basic_len
+= job_len
+ 1;
376 if (basic_len
< (unsigned) columns()) {
377 unsigned extra_len
, incr
;
378 extra_len
= columns() - basic_len
;
380 /* Either UNIT already got 25, or is fully satisfied.
381 * Grant up to 25 to DESC now. */
382 incr
= MIN(extra_len
, 25u);
386 /* split the remaining space between UNIT and DESC,
387 * but do not give UNIT more than it needs. */
389 incr
= MIN(extra_len
/ 2, max_id_len
- id_len
);
391 desc_len
+= extra_len
- incr
;
397 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
398 _cleanup_free_
char *e
= NULL
, *j
= NULL
;
399 const char *on_loaded
= "", *off_loaded
= "";
400 const char *on_active
= "", *off_active
= "";
401 const char *on_circle
= "", *off_circle
= "";
405 if (!n_shown
&& !arg_no_legend
) {
410 printf("%-*s %-*s %-*s %-*s ",
413 active_len
, "ACTIVE",
417 printf("%-*s ", job_len
, "JOB");
419 if (!arg_full
&& arg_no_pager
)
420 printf("%.*s\n", desc_len
, "DESCRIPTION");
422 printf("%s\n", "DESCRIPTION");
427 if (STR_IN_SET(u
->load_state
, "error", "not-found", "masked") && !arg_plain
) {
428 on_loaded
= ansi_highlight_red();
429 on_circle
= ansi_highlight_yellow();
430 off_loaded
= off_circle
= ansi_highlight_off();
432 } else if (streq(u
->active_state
, "failed") && !arg_plain
) {
433 on_circle
= on_active
= ansi_highlight_red();
434 off_circle
= off_active
= ansi_highlight_off();
439 j
= strjoin(u
->machine
, ":", u
->id
, NULL
);
448 e
= ellipsize(id
, id_len
, 33);
456 printf("%s%s%s ", on_circle
, circle
? draw_special_char(DRAW_BLACK_CIRCLE
) : " ", off_circle
);
458 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
459 on_active
, id_len
, id
, off_active
,
460 on_loaded
, load_len
, u
->load_state
, off_loaded
,
461 on_active
, active_len
, u
->active_state
,
462 sub_len
, u
->sub_state
, off_active
,
463 job_count
? job_len
+ 1 : 0, u
->job_id
? u
->job_type
: "");
466 printf("%.*s\n", desc_len
, u
->description
);
468 printf("%s\n", u
->description
);
471 if (!arg_no_legend
) {
472 const char *on
, *off
;
476 "LOAD = Reflects whether the unit definition was properly loaded.\n"
477 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
478 "SUB = The low-level unit activation state, values depend on unit type.");
479 puts(job_count
? "JOB = Pending job for the unit.\n" : "");
480 on
= ansi_highlight();
481 off
= ansi_highlight_off();
483 on
= ansi_highlight_red();
484 off
= ansi_highlight_off();
488 printf("%s%u loaded units listed.%s\n"
489 "To show all installed unit files use 'systemctl list-unit-files'.\n",
492 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
493 "To show all installed unit files use 'systemctl list-unit-files'.\n",
500 static int get_unit_list(
504 UnitInfo
**unit_infos
,
506 sd_bus_message
**_reply
) {
508 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
509 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
510 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
519 r
= sd_bus_message_new_method_call(
522 "org.freedesktop.systemd1",
523 "/org/freedesktop/systemd1",
524 "org.freedesktop.systemd1.Manager",
525 "ListUnitsFiltered");
528 return bus_log_create_error(r
);
530 r
= sd_bus_message_append_strv(m
, arg_states
);
532 return bus_log_create_error(r
);
534 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
536 log_error("Failed to list units: %s", bus_error_message(&error
, r
));
540 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssssouso)");
542 return bus_log_parse_error(r
);
544 while ((r
= bus_parse_unit_info(reply
, &u
)) > 0) {
547 if (!output_show_unit(&u
, patterns
))
550 if (!GREEDY_REALLOC(*unit_infos
, size
, c
+1))
553 (*unit_infos
)[c
++] = u
;
556 return bus_log_parse_error(r
);
558 r
= sd_bus_message_exit_container(reply
);
560 return bus_log_parse_error(r
);
568 static void message_set_freep(Set
**set
) {
571 while ((m
= set_steal_first(*set
)))
572 sd_bus_message_unref(m
);
577 static int get_unit_list_recursive(
580 UnitInfo
**_unit_infos
,
584 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
585 _cleanup_(message_set_freep
) Set
*replies
;
586 sd_bus_message
*reply
;
594 replies
= set_new(NULL
);
598 c
= get_unit_list(bus
, NULL
, patterns
, &unit_infos
, 0, &reply
);
602 r
= set_put(replies
, reply
);
604 sd_bus_message_unref(reply
);
609 _cleanup_strv_free_
char **machines
= NULL
;
612 r
= sd_get_machine_names(&machines
);
616 STRV_FOREACH(i
, machines
) {
617 _cleanup_bus_close_unref_ sd_bus
*container
= NULL
;
620 r
= sd_bus_open_system_machine(&container
, *i
);
622 log_error_errno(r
, "Failed to connect to container %s: %m", *i
);
626 k
= get_unit_list(container
, *i
, patterns
, &unit_infos
, c
, &reply
);
632 r
= set_put(replies
, reply
);
634 sd_bus_message_unref(reply
);
639 *_machines
= machines
;
644 *_unit_infos
= unit_infos
;
653 static int list_units(sd_bus
*bus
, char **args
) {
654 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
655 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
656 _cleanup_strv_free_
char **machines
= NULL
;
659 pager_open_if_enabled();
661 r
= get_unit_list_recursive(bus
, strv_skip_first(args
), &unit_infos
, &replies
, &machines
);
665 qsort_safe(unit_infos
, r
, sizeof(UnitInfo
), compare_unit_info
);
666 return output_units_list(unit_infos
, r
);
669 static int get_triggered_units(
674 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
677 r
= sd_bus_get_property_strv(
679 "org.freedesktop.systemd1",
681 "org.freedesktop.systemd1.Unit",
687 log_error("Failed to determine triggers: %s", bus_error_message(&error
, r
));
692 static int get_listening(
694 const char* unit_path
,
697 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
698 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
699 const char *type
, *path
;
702 r
= sd_bus_get_property(
704 "org.freedesktop.systemd1",
706 "org.freedesktop.systemd1.Socket",
712 log_error("Failed to get list of listening sockets: %s", bus_error_message(&error
, r
));
716 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
718 return bus_log_parse_error(r
);
720 while ((r
= sd_bus_message_read(reply
, "(ss)", &type
, &path
)) > 0) {
722 r
= strv_extend(listening
, type
);
726 r
= strv_extend(listening
, path
);
733 return bus_log_parse_error(r
);
735 r
= sd_bus_message_exit_container(reply
);
737 return bus_log_parse_error(r
);
749 /* Note: triggered is a list here, although it almost certainly
750 * will always be one unit. Nevertheless, dbus API allows for multiple
751 * values, so let's follow that. */
754 /* The strv above is shared. free is set only in the first one. */
758 static int socket_info_compare(const struct socket_info
*a
, const struct socket_info
*b
) {
764 if (!a
->machine
&& b
->machine
)
766 if (a
->machine
&& !b
->machine
)
768 if (a
->machine
&& b
->machine
) {
769 o
= strcasecmp(a
->machine
, b
->machine
);
774 o
= strcmp(a
->path
, b
->path
);
776 o
= strcmp(a
->type
, b
->type
);
781 static int output_sockets_list(struct socket_info
*socket_infos
, unsigned cs
) {
782 struct socket_info
*s
;
783 unsigned pathlen
= strlen("LISTEN"),
784 typelen
= strlen("TYPE") * arg_show_types
,
785 socklen
= strlen("UNIT"),
786 servlen
= strlen("ACTIVATES");
787 const char *on
, *off
;
789 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
793 socklen
= MAX(socklen
, strlen(s
->id
));
795 typelen
= MAX(typelen
, strlen(s
->type
));
796 pathlen
= MAX(pathlen
, strlen(s
->path
) + (s
->machine
? strlen(s
->machine
)+1 : 0));
798 STRV_FOREACH(a
, s
->triggered
)
799 tmp
+= strlen(*a
) + 2*(a
!= s
->triggered
);
800 servlen
= MAX(servlen
, tmp
);
805 printf("%-*s %-*.*s%-*s %s\n",
807 typelen
+ arg_show_types
, typelen
+ arg_show_types
, "TYPE ",
811 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
812 _cleanup_free_
char *j
= NULL
;
817 j
= strjoin(s
->machine
, ":", s
->path
, NULL
);
825 printf("%-*s %-*s %-*s",
826 pathlen
, path
, typelen
, s
->type
, socklen
, s
->id
);
829 pathlen
, path
, socklen
, s
->id
);
830 STRV_FOREACH(a
, s
->triggered
)
832 a
== s
->triggered
? "" : ",", *a
);
836 on
= ansi_highlight();
837 off
= ansi_highlight_off();
841 on
= ansi_highlight_red();
842 off
= ansi_highlight_off();
845 if (!arg_no_legend
) {
846 printf("%s%u sockets listed.%s\n", on
, cs
, off
);
848 printf("Pass --all to see loaded but inactive sockets, too.\n");
854 static int list_sockets(sd_bus
*bus
, char **args
) {
855 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
856 _cleanup_strv_free_
char **machines
= NULL
;
857 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
858 _cleanup_free_
struct socket_info
*socket_infos
= NULL
;
860 struct socket_info
*s
;
865 pager_open_if_enabled();
867 n
= get_unit_list_recursive(bus
, strv_skip_first(args
), &unit_infos
, &replies
, &machines
);
871 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
872 _cleanup_strv_free_
char **listening
= NULL
, **triggered
= NULL
;
875 if (!endswith(u
->id
, ".socket"))
878 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
882 c
= get_listening(bus
, u
->unit_path
, &listening
);
888 if (!GREEDY_REALLOC(socket_infos
, size
, cs
+ c
)) {
893 for (i
= 0; i
< c
; i
++)
894 socket_infos
[cs
+ i
] = (struct socket_info
) {
895 .machine
= u
->machine
,
897 .type
= listening
[i
*2],
898 .path
= listening
[i
*2 + 1],
899 .triggered
= triggered
,
900 .own_triggered
= i
==0,
903 /* from this point on we will cleanup those socket_infos */
906 listening
= triggered
= NULL
; /* avoid cleanup */
909 qsort_safe(socket_infos
, cs
, sizeof(struct socket_info
),
910 (__compar_fn_t
) socket_info_compare
);
912 output_sockets_list(socket_infos
, cs
);
915 assert(cs
== 0 || socket_infos
);
916 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
919 if (s
->own_triggered
)
920 strv_free(s
->triggered
);
926 static int get_next_elapse(
929 dual_timestamp
*next
) {
931 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
939 r
= sd_bus_get_property_trivial(
941 "org.freedesktop.systemd1",
943 "org.freedesktop.systemd1.Timer",
944 "NextElapseUSecMonotonic",
949 log_error("Failed to get next elapsation time: %s", bus_error_message(&error
, r
));
953 r
= sd_bus_get_property_trivial(
955 "org.freedesktop.systemd1",
957 "org.freedesktop.systemd1.Timer",
958 "NextElapseUSecRealtime",
963 log_error("Failed to get next elapsation time: %s", bus_error_message(&error
, r
));
971 static int get_last_trigger(
976 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
983 r
= sd_bus_get_property_trivial(
985 "org.freedesktop.systemd1",
987 "org.freedesktop.systemd1.Timer",
993 log_error("Failed to get last trigger time: %s", bus_error_message(&error
, r
));
1001 const char* machine
;
1004 usec_t last_trigger
;
1008 static int timer_info_compare(const struct timer_info
*a
, const struct timer_info
*b
) {
1014 if (!a
->machine
&& b
->machine
)
1016 if (a
->machine
&& !b
->machine
)
1018 if (a
->machine
&& b
->machine
) {
1019 o
= strcasecmp(a
->machine
, b
->machine
);
1024 if (a
->next_elapse
< b
->next_elapse
)
1026 if (a
->next_elapse
> b
->next_elapse
)
1029 return strcmp(a
->id
, b
->id
);
1032 static int output_timers_list(struct timer_info
*timer_infos
, unsigned n
) {
1033 struct timer_info
*t
;
1035 nextlen
= strlen("NEXT"),
1036 leftlen
= strlen("LEFT"),
1037 lastlen
= strlen("LAST"),
1038 passedlen
= strlen("PASSED"),
1039 unitlen
= strlen("UNIT"),
1040 activatelen
= strlen("ACTIVATES");
1042 const char *on
, *off
;
1044 assert(timer_infos
|| n
== 0);
1046 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1050 if (t
->next_elapse
> 0) {
1051 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1053 format_timestamp(tstamp
, sizeof(tstamp
), t
->next_elapse
);
1054 nextlen
= MAX(nextlen
, strlen(tstamp
) + 1);
1056 format_timestamp_relative(trel
, sizeof(trel
), t
->next_elapse
);
1057 leftlen
= MAX(leftlen
, strlen(trel
));
1060 if (t
->last_trigger
> 0) {
1061 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1063 format_timestamp(tstamp
, sizeof(tstamp
), t
->last_trigger
);
1064 lastlen
= MAX(lastlen
, strlen(tstamp
) + 1);
1066 format_timestamp_relative(trel
, sizeof(trel
), t
->last_trigger
);
1067 passedlen
= MAX(passedlen
, strlen(trel
));
1070 unitlen
= MAX(unitlen
, strlen(t
->id
) + (t
->machine
? strlen(t
->machine
)+1 : 0));
1072 STRV_FOREACH(a
, t
->triggered
)
1073 ul
+= strlen(*a
) + 2*(a
!= t
->triggered
);
1075 activatelen
= MAX(activatelen
, ul
);
1080 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1084 passedlen
, "PASSED",
1088 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1089 _cleanup_free_
char *j
= NULL
;
1091 char tstamp1
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel1
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1092 char tstamp2
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel2
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1095 format_timestamp(tstamp1
, sizeof(tstamp1
), t
->next_elapse
);
1096 format_timestamp_relative(trel1
, sizeof(trel1
), t
->next_elapse
);
1098 format_timestamp(tstamp2
, sizeof(tstamp2
), t
->last_trigger
);
1099 format_timestamp_relative(trel2
, sizeof(trel2
), t
->last_trigger
);
1102 j
= strjoin(t
->machine
, ":", t
->id
, NULL
);
1109 printf("%-*s %-*s %-*s %-*s %-*s",
1110 nextlen
, tstamp1
, leftlen
, trel1
, lastlen
, tstamp2
, passedlen
, trel2
, unitlen
, unit
);
1112 STRV_FOREACH(a
, t
->triggered
)
1114 a
== t
->triggered
? "" : ",", *a
);
1118 on
= ansi_highlight();
1119 off
= ansi_highlight_off();
1123 on
= ansi_highlight_red();
1124 off
= ansi_highlight_off();
1127 if (!arg_no_legend
) {
1128 printf("%s%u timers listed.%s\n", on
, n
, off
);
1130 printf("Pass --all to see loaded but inactive timers, too.\n");
1136 static usec_t
calc_next_elapse(dual_timestamp
*nw
, dual_timestamp
*next
) {
1142 if (next
->monotonic
!= USEC_INFINITY
&& next
->monotonic
> 0) {
1145 if (next
->monotonic
> nw
->monotonic
)
1146 converted
= nw
->realtime
+ (next
->monotonic
- nw
->monotonic
);
1148 converted
= nw
->realtime
- (nw
->monotonic
- next
->monotonic
);
1150 if (next
->realtime
!= USEC_INFINITY
&& next
->realtime
> 0)
1151 next_elapse
= MIN(converted
, next
->realtime
);
1153 next_elapse
= converted
;
1156 next_elapse
= next
->realtime
;
1161 static int list_timers(sd_bus
*bus
, char **args
) {
1162 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
1163 _cleanup_strv_free_
char **machines
= NULL
;
1164 _cleanup_free_
struct timer_info
*timer_infos
= NULL
;
1165 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
1166 struct timer_info
*t
;
1173 pager_open_if_enabled();
1175 n
= get_unit_list_recursive(bus
, strv_skip_first(args
), &unit_infos
, &replies
, &machines
);
1179 dual_timestamp_get(&nw
);
1181 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
1182 _cleanup_strv_free_
char **triggered
= NULL
;
1183 dual_timestamp next
= {};
1186 if (!endswith(u
->id
, ".timer"))
1189 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
1193 r
= get_next_elapse(bus
, u
->unit_path
, &next
);
1197 get_last_trigger(bus
, u
->unit_path
, &last
);
1199 if (!GREEDY_REALLOC(timer_infos
, size
, c
+1)) {
1204 m
= calc_next_elapse(&nw
, &next
);
1206 timer_infos
[c
++] = (struct timer_info
) {
1207 .machine
= u
->machine
,
1210 .last_trigger
= last
,
1211 .triggered
= triggered
,
1214 triggered
= NULL
; /* avoid cleanup */
1217 qsort_safe(timer_infos
, c
, sizeof(struct timer_info
),
1218 (__compar_fn_t
) timer_info_compare
);
1220 output_timers_list(timer_infos
, c
);
1223 for (t
= timer_infos
; t
< timer_infos
+ c
; t
++)
1224 strv_free(t
->triggered
);
1229 static int compare_unit_file_list(const void *a
, const void *b
) {
1230 const char *d1
, *d2
;
1231 const UnitFileList
*u
= a
, *v
= b
;
1233 d1
= strrchr(u
->path
, '.');
1234 d2
= strrchr(v
->path
, '.');
1239 r
= strcasecmp(d1
, d2
);
1244 return strcasecmp(basename(u
->path
), basename(v
->path
));
1247 static bool output_show_unit_file(const UnitFileList
*u
, char **patterns
) {
1248 if (!strv_fnmatch_or_empty(patterns
, basename(u
->path
), FNM_NOESCAPE
))
1251 if (!strv_isempty(arg_types
)) {
1254 dot
= strrchr(u
->path
, '.');
1258 if (!strv_find(arg_types
, dot
+1))
1262 if (!strv_isempty(arg_states
) &&
1263 !strv_find(arg_states
, unit_file_state_to_string(u
->state
)))
1269 static void output_unit_file_list(const UnitFileList
*units
, unsigned c
) {
1270 unsigned max_id_len
, id_cols
, state_cols
;
1271 const UnitFileList
*u
;
1273 max_id_len
= strlen("UNIT FILE");
1274 state_cols
= strlen("STATE");
1276 for (u
= units
; u
< units
+ c
; u
++) {
1277 max_id_len
= MAX(max_id_len
, strlen(basename(u
->path
)));
1278 state_cols
= MAX(state_cols
, strlen(unit_file_state_to_string(u
->state
)));
1282 unsigned basic_cols
;
1284 id_cols
= MIN(max_id_len
, 25u);
1285 basic_cols
= 1 + id_cols
+ state_cols
;
1286 if (basic_cols
< (unsigned) columns())
1287 id_cols
+= MIN(columns() - basic_cols
, max_id_len
- id_cols
);
1289 id_cols
= max_id_len
;
1292 printf("%-*s %-*s\n",
1293 id_cols
, "UNIT FILE",
1294 state_cols
, "STATE");
1296 for (u
= units
; u
< units
+ c
; u
++) {
1297 _cleanup_free_
char *e
= NULL
;
1298 const char *on
, *off
;
1301 if (u
->state
== UNIT_FILE_MASKED
||
1302 u
->state
== UNIT_FILE_MASKED_RUNTIME
||
1303 u
->state
== UNIT_FILE_DISABLED
||
1304 u
->state
== UNIT_FILE_INVALID
) {
1305 on
= ansi_highlight_red();
1306 off
= ansi_highlight_off();
1307 } else if (u
->state
== UNIT_FILE_ENABLED
) {
1308 on
= ansi_highlight_green();
1309 off
= ansi_highlight_off();
1313 id
= basename(u
->path
);
1315 e
= arg_full
? NULL
: ellipsize(id
, id_cols
, 33);
1317 printf("%-*s %s%-*s%s\n",
1318 id_cols
, e
? e
: id
,
1319 on
, state_cols
, unit_file_state_to_string(u
->state
), off
);
1323 printf("\n%u unit files listed.\n", c
);
1326 static int list_unit_files(sd_bus
*bus
, char **args
) {
1327 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1328 _cleanup_free_ UnitFileList
*units
= NULL
;
1336 pager_open_if_enabled();
1344 h
= hashmap_new(&string_hash_ops
);
1348 r
= unit_file_get_list(arg_scope
, arg_root
, h
);
1350 unit_file_list_free(h
);
1351 log_error_errno(r
, "Failed to get unit file list: %m");
1355 n_units
= hashmap_size(h
);
1357 units
= new(UnitFileList
, n_units
);
1358 if (!units
&& n_units
> 0) {
1359 unit_file_list_free(h
);
1363 HASHMAP_FOREACH(u
, h
, i
) {
1364 if (!output_show_unit_file(u
, strv_skip_first(args
)))
1371 assert(c
<= n_units
);
1374 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1376 r
= sd_bus_call_method(
1378 "org.freedesktop.systemd1",
1379 "/org/freedesktop/systemd1",
1380 "org.freedesktop.systemd1.Manager",
1386 log_error("Failed to list unit files: %s", bus_error_message(&error
, r
));
1390 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
1392 return bus_log_parse_error(r
);
1394 while ((r
= sd_bus_message_read(reply
, "(ss)", &path
, &state
)) > 0) {
1396 if (!GREEDY_REALLOC(units
, size
, c
+ 1))
1399 units
[c
] = (struct UnitFileList
) {
1401 unit_file_state_from_string(state
)
1404 if (output_show_unit_file(&units
[c
], strv_skip_first(args
)))
1409 return bus_log_parse_error(r
);
1411 r
= sd_bus_message_exit_container(reply
);
1413 return bus_log_parse_error(r
);
1416 qsort_safe(units
, c
, sizeof(UnitFileList
), compare_unit_file_list
);
1417 output_unit_file_list(units
, c
);
1420 for (unit
= units
; unit
< units
+ c
; unit
++)
1427 static int list_dependencies_print(const char *name
, int level
, unsigned int branches
, bool last
) {
1428 _cleanup_free_
char *n
= NULL
;
1429 size_t max_len
= MAX(columns(),20u);
1435 for (i
= level
- 1; i
>= 0; i
--) {
1437 if (len
> max_len
- 3 && !arg_full
) {
1438 printf("%s...\n",max_len
% 2 ? "" : " ");
1441 printf("%s", draw_special_char(branches
& (1 << i
) ? DRAW_TREE_VERTICAL
: DRAW_TREE_SPACE
));
1445 if (len
> max_len
- 3 && !arg_full
) {
1446 printf("%s...\n",max_len
% 2 ? "" : " ");
1450 printf("%s", draw_special_char(last
? DRAW_TREE_RIGHT
: DRAW_TREE_BRANCH
));
1454 printf("%s\n", name
);
1458 n
= ellipsize(name
, max_len
-len
, 100);
1466 static int list_dependencies_get_dependencies(sd_bus
*bus
, const char *name
, char ***deps
) {
1468 static const char *dependencies
[_DEPENDENCY_MAX
] = {
1469 [DEPENDENCY_FORWARD
] = "Requires\0"
1470 "RequiresOverridable\0"
1472 "RequisiteOverridable\0"
1475 [DEPENDENCY_REVERSE
] = "RequiredBy\0"
1476 "RequiredByOverridable\0"
1480 [DEPENDENCY_AFTER
] = "After\0",
1481 [DEPENDENCY_BEFORE
] = "Before\0",
1484 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1485 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1486 _cleanup_strv_free_
char **ret
= NULL
;
1487 _cleanup_free_
char *path
= NULL
;
1493 assert_cc(ELEMENTSOF(dependencies
) == _DEPENDENCY_MAX
);
1495 path
= unit_dbus_path_from_name(name
);
1499 r
= sd_bus_call_method(
1501 "org.freedesktop.systemd1",
1503 "org.freedesktop.DBus.Properties",
1507 "s", "org.freedesktop.systemd1.Unit");
1509 log_error("Failed to get properties of %s: %s", name
, bus_error_message(&error
, r
));
1513 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
1515 return bus_log_parse_error(r
);
1517 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
1520 r
= sd_bus_message_read(reply
, "s", &prop
);
1522 return bus_log_parse_error(r
);
1524 if (!nulstr_contains(dependencies
[arg_dependency
], prop
)) {
1525 r
= sd_bus_message_skip(reply
, "v");
1527 return bus_log_parse_error(r
);
1530 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, "as");
1532 return bus_log_parse_error(r
);
1534 r
= bus_message_read_strv_extend(reply
, &ret
);
1536 return bus_log_parse_error(r
);
1538 r
= sd_bus_message_exit_container(reply
);
1540 return bus_log_parse_error(r
);
1543 r
= sd_bus_message_exit_container(reply
);
1545 return bus_log_parse_error(r
);
1549 return bus_log_parse_error(r
);
1551 r
= sd_bus_message_exit_container(reply
);
1553 return bus_log_parse_error(r
);
1561 static int list_dependencies_compare(const void *_a
, const void *_b
) {
1562 const char **a
= (const char**) _a
, **b
= (const char**) _b
;
1564 if (unit_name_to_type(*a
) == UNIT_TARGET
&& unit_name_to_type(*b
) != UNIT_TARGET
)
1566 if (unit_name_to_type(*a
) != UNIT_TARGET
&& unit_name_to_type(*b
) == UNIT_TARGET
)
1569 return strcasecmp(*a
, *b
);
1572 static int list_dependencies_one(
1577 unsigned int branches
) {
1579 _cleanup_strv_free_
char **deps
= NULL
;
1587 r
= strv_extend(units
, name
);
1591 r
= list_dependencies_get_dependencies(bus
, name
, &deps
);
1595 qsort_safe(deps
, strv_length(deps
), sizeof (char*), list_dependencies_compare
);
1597 STRV_FOREACH(c
, deps
) {
1598 if (strv_contains(*units
, *c
)) {
1600 r
= list_dependencies_print("...", level
+ 1, (branches
<< 1) | (c
[1] == NULL
? 0 : 1), 1);
1613 state
= check_one_unit(bus
, *c
, "activating\0active\0reloading\0", true);
1614 on
= state
> 0 ? ansi_highlight_green() : ansi_highlight_red();
1615 printf("%s%s%s ", on
, draw_special_char(DRAW_BLACK_CIRCLE
), ansi_highlight_off());
1618 r
= list_dependencies_print(*c
, level
, branches
, c
[1] == NULL
);
1622 if (arg_all
|| unit_name_to_type(*c
) == UNIT_TARGET
) {
1623 r
= list_dependencies_one(bus
, *c
, level
+ 1, units
, (branches
<< 1) | (c
[1] == NULL
? 0 : 1));
1630 strv_remove(*units
, name
);
1635 static int list_dependencies(sd_bus
*bus
, char **args
) {
1636 _cleanup_strv_free_
char **units
= NULL
;
1637 _cleanup_free_
char *unit
= NULL
;
1643 unit
= unit_name_mangle(args
[1], MANGLE_NOGLOB
);
1648 u
= SPECIAL_DEFAULT_TARGET
;
1650 pager_open_if_enabled();
1654 return list_dependencies_one(bus
, u
, 0, &units
, 0);
1657 struct machine_info
{
1661 char *control_group
;
1662 uint32_t n_failed_units
;
1667 static const struct bus_properties_map machine_info_property_map
[] = {
1668 { "SystemState", "s", NULL
, offsetof(struct machine_info
, state
) },
1669 { "NJobs", "u", NULL
, offsetof(struct machine_info
, n_jobs
) },
1670 { "NFailedUnits", "u", NULL
, offsetof(struct machine_info
, n_failed_units
) },
1671 { "ControlGroup", "s", NULL
, offsetof(struct machine_info
, control_group
) },
1672 { "UserspaceTimestamp", "t", NULL
, offsetof(struct machine_info
, timestamp
) },
1676 static void free_machines_list(struct machine_info
*machine_infos
, int n
) {
1682 for (i
= 0; i
< n
; i
++) {
1683 free(machine_infos
[i
].name
);
1684 free(machine_infos
[i
].state
);
1685 free(machine_infos
[i
].control_group
);
1688 free(machine_infos
);
1691 static int compare_machine_info(const void *a
, const void *b
) {
1692 const struct machine_info
*u
= a
, *v
= b
;
1694 if (u
->is_host
!= v
->is_host
)
1695 return u
->is_host
> v
->is_host
? -1 : 1;
1697 return strcasecmp(u
->name
, v
->name
);
1700 static int get_machine_properties(sd_bus
*bus
, struct machine_info
*mi
) {
1701 _cleanup_bus_close_unref_ sd_bus
*container
= NULL
;
1707 r
= sd_bus_open_system_machine(&container
, mi
->name
);
1714 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, mi
);
1721 static bool output_show_machine(const char *name
, char **patterns
) {
1722 return strv_fnmatch_or_empty(patterns
, name
, FNM_NOESCAPE
);
1725 static int get_machine_list(
1727 struct machine_info
**_machine_infos
,
1730 struct machine_info
*machine_infos
= NULL
;
1731 _cleanup_strv_free_
char **m
= NULL
;
1732 _cleanup_free_
char *hn
= NULL
;
1737 hn
= gethostname_malloc();
1741 if (output_show_machine(hn
, patterns
)) {
1742 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1))
1745 machine_infos
[c
].is_host
= true;
1746 machine_infos
[c
].name
= hn
;
1749 get_machine_properties(bus
, &machine_infos
[c
]);
1753 sd_get_machine_names(&m
);
1754 STRV_FOREACH(i
, m
) {
1755 _cleanup_free_
char *class = NULL
;
1757 if (!output_show_machine(*i
, patterns
))
1760 sd_machine_get_class(*i
, &class);
1761 if (!streq_ptr(class, "container"))
1764 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1)) {
1765 free_machines_list(machine_infos
, c
);
1769 machine_infos
[c
].is_host
= false;
1770 machine_infos
[c
].name
= strdup(*i
);
1771 if (!machine_infos
[c
].name
) {
1772 free_machines_list(machine_infos
, c
);
1776 get_machine_properties(NULL
, &machine_infos
[c
]);
1780 *_machine_infos
= machine_infos
;
1784 static void output_machines_list(struct machine_info
*machine_infos
, unsigned n
) {
1785 struct machine_info
*m
;
1788 namelen
= sizeof("NAME") - 1,
1789 statelen
= sizeof("STATE") - 1,
1790 failedlen
= sizeof("FAILED") - 1,
1791 jobslen
= sizeof("JOBS") - 1;
1793 assert(machine_infos
|| n
== 0);
1795 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
1796 namelen
= MAX(namelen
, strlen(m
->name
) + (m
->is_host
? sizeof(" (host)") - 1 : 0));
1797 statelen
= MAX(statelen
, m
->state
? strlen(m
->state
) : 0);
1798 failedlen
= MAX(failedlen
, DECIMAL_STR_WIDTH(m
->n_failed_units
));
1799 jobslen
= MAX(jobslen
, DECIMAL_STR_WIDTH(m
->n_jobs
));
1801 if (!arg_plain
&& !streq_ptr(m
->state
, "running"))
1805 if (!arg_no_legend
) {
1809 printf("%-*s %-*s %-*s %-*s\n",
1812 failedlen
, "FAILED",
1816 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
1817 const char *on_state
= "", *off_state
= "";
1818 const char *on_failed
= "", *off_failed
= "";
1819 bool circle
= false;
1821 if (streq_ptr(m
->state
, "degraded")) {
1822 on_state
= ansi_highlight_red();
1823 off_state
= ansi_highlight_off();
1825 } else if (!streq_ptr(m
->state
, "running")) {
1826 on_state
= ansi_highlight_yellow();
1827 off_state
= ansi_highlight_off();
1831 if (m
->n_failed_units
> 0) {
1832 on_failed
= ansi_highlight_red();
1833 off_failed
= ansi_highlight_off();
1835 on_failed
= off_failed
= "";
1838 printf("%s%s%s ", on_state
, circle
? draw_special_char(DRAW_BLACK_CIRCLE
) : " ", off_state
);
1841 printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
1842 (int) (namelen
- (sizeof(" (host)")-1)), strna(m
->name
),
1843 on_state
, statelen
, strna(m
->state
), off_state
,
1844 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
1845 jobslen
, m
->n_jobs
);
1847 printf("%-*s %s%-*s%s %s%*u%s %*u\n",
1848 namelen
, strna(m
->name
),
1849 on_state
, statelen
, strna(m
->state
), off_state
,
1850 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
1851 jobslen
, m
->n_jobs
);
1855 printf("\n%u machines listed.\n", n
);
1858 static int list_machines(sd_bus
*bus
, char **args
) {
1859 struct machine_info
*machine_infos
= NULL
;
1864 if (geteuid() != 0) {
1865 log_error("Must be root.");
1869 pager_open_if_enabled();
1871 r
= get_machine_list(bus
, &machine_infos
, strv_skip_first(args
));
1875 qsort_safe(machine_infos
, r
, sizeof(struct machine_info
), compare_machine_info
);
1876 output_machines_list(machine_infos
, r
);
1877 free_machines_list(machine_infos
, r
);
1882 static int get_default(sd_bus
*bus
, char **args
) {
1883 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1884 _cleanup_free_
char *_path
= NULL
;
1888 if (!bus
|| avoid_bus()) {
1889 r
= unit_file_get_default(arg_scope
, arg_root
, &_path
);
1891 return log_error_errno(r
, "Failed to get default target: %m");
1895 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1897 r
= sd_bus_call_method(
1899 "org.freedesktop.systemd1",
1900 "/org/freedesktop/systemd1",
1901 "org.freedesktop.systemd1.Manager",
1907 log_error("Failed to get default target: %s", bus_error_message(&error
, -r
));
1911 r
= sd_bus_message_read(reply
, "s", &path
);
1913 return bus_log_parse_error(r
);
1917 printf("%s\n", path
);
1922 static void dump_unit_file_changes(const UnitFileChange
*changes
, unsigned n_changes
) {
1925 assert(changes
|| n_changes
== 0);
1927 for (i
= 0; i
< n_changes
; i
++) {
1928 if (changes
[i
].type
== UNIT_FILE_SYMLINK
)
1929 log_info("Created symlink from %s to %s.", changes
[i
].path
, changes
[i
].source
);
1931 log_info("Removed symlink %s.", changes
[i
].path
);
1935 static int set_default(sd_bus
*bus
, char **args
) {
1936 _cleanup_free_
char *unit
= NULL
;
1937 UnitFileChange
*changes
= NULL
;
1938 unsigned n_changes
= 0;
1941 unit
= unit_name_mangle_with_suffix(args
[1], MANGLE_NOGLOB
, ".target");
1945 if (!bus
|| avoid_bus()) {
1946 r
= unit_file_set_default(arg_scope
, arg_root
, unit
, true, &changes
, &n_changes
);
1948 return log_error_errno(r
, "Failed to set default target: %m");
1951 dump_unit_file_changes(changes
, n_changes
);
1955 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1956 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1958 polkit_agent_open_if_enabled();
1960 r
= sd_bus_call_method(
1962 "org.freedesktop.systemd1",
1963 "/org/freedesktop/systemd1",
1964 "org.freedesktop.systemd1.Manager",
1970 log_error("Failed to set default target: %s", bus_error_message(&error
, -r
));
1974 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
);
1978 /* Try to reload if enabled */
1980 r
= daemon_reload(bus
, args
);
1985 unit_file_changes_free(changes
, n_changes
);
1992 const char *name
, *type
, *state
;
1995 static void output_jobs_list(const struct job_info
* jobs
, unsigned n
, bool skipped
) {
1996 unsigned id_len
, unit_len
, type_len
, state_len
;
1997 const struct job_info
*j
;
1998 const char *on
, *off
;
1999 bool shorten
= false;
2001 assert(n
== 0 || jobs
);
2004 if (!arg_no_legend
) {
2005 on
= ansi_highlight_green();
2006 off
= ansi_highlight_off();
2008 printf("%sNo jobs %s.%s\n", on
, skipped
? "listed" : "running", off
);
2013 pager_open_if_enabled();
2015 id_len
= strlen("JOB");
2016 unit_len
= strlen("UNIT");
2017 type_len
= strlen("TYPE");
2018 state_len
= strlen("STATE");
2020 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2021 uint32_t id
= j
->id
;
2022 assert(j
->name
&& j
->type
&& j
->state
);
2024 id_len
= MAX(id_len
, DECIMAL_STR_WIDTH(id
));
2025 unit_len
= MAX(unit_len
, strlen(j
->name
));
2026 type_len
= MAX(type_len
, strlen(j
->type
));
2027 state_len
= MAX(state_len
, strlen(j
->state
));
2030 if (!arg_full
&& id_len
+ 1 + unit_len
+ type_len
+ 1 + state_len
> columns()) {
2031 unit_len
= MAX(33u, columns() - id_len
- type_len
- state_len
- 3);
2036 printf("%*s %-*s %-*s %-*s\n",
2040 state_len
, "STATE");
2042 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2043 _cleanup_free_
char *e
= NULL
;
2045 if (streq(j
->state
, "running")) {
2046 on
= ansi_highlight();
2047 off
= ansi_highlight_off();
2051 e
= shorten
? ellipsize(j
->name
, unit_len
, 33) : NULL
;
2052 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2054 on
, unit_len
, e
? e
: j
->name
, off
,
2056 on
, state_len
, j
->state
, off
);
2059 if (!arg_no_legend
) {
2060 on
= ansi_highlight();
2061 off
= ansi_highlight_off();
2063 printf("\n%s%u jobs listed%s.\n", on
, n
, off
);
2067 static bool output_show_job(struct job_info
*job
, char **patterns
) {
2068 return strv_fnmatch_or_empty(patterns
, job
->name
, FNM_NOESCAPE
);
2071 static int list_jobs(sd_bus
*bus
, char **args
) {
2072 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2073 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2074 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2075 _cleanup_free_
struct job_info
*jobs
= NULL
;
2080 bool skipped
= false;
2082 r
= sd_bus_call_method(
2084 "org.freedesktop.systemd1",
2085 "/org/freedesktop/systemd1",
2086 "org.freedesktop.systemd1.Manager",
2092 log_error("Failed to list jobs: %s", bus_error_message(&error
, r
));
2096 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2098 return bus_log_parse_error(r
);
2100 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0) {
2101 struct job_info job
= { id
, name
, type
, state
};
2103 if (!output_show_job(&job
, strv_skip_first(args
))) {
2108 if (!GREEDY_REALLOC(jobs
, size
, c
+ 1))
2114 return bus_log_parse_error(r
);
2116 r
= sd_bus_message_exit_container(reply
);
2118 return bus_log_parse_error(r
);
2120 output_jobs_list(jobs
, c
, skipped
);
2124 static int cancel_job(sd_bus
*bus
, char **args
) {
2130 if (strv_length(args
) <= 1)
2131 return daemon_reload(bus
, args
);
2133 polkit_agent_open_if_enabled();
2135 STRV_FOREACH(name
, args
+1) {
2136 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2140 q
= safe_atou32(*name
, &id
);
2142 return log_error_errno(q
, "Failed to parse job id \"%s\": %m", *name
);
2144 q
= sd_bus_call_method(
2146 "org.freedesktop.systemd1",
2147 "/org/freedesktop/systemd1",
2148 "org.freedesktop.systemd1.Manager",
2154 log_error("Failed to cancel job %"PRIu32
": %s", id
, bus_error_message(&error
, q
));
2163 static int need_daemon_reload(sd_bus
*bus
, const char *unit
) {
2164 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2168 /* We ignore all errors here, since this is used to show a
2171 /* We don't use unit_dbus_path_from_name() directly since we
2172 * don't want to load the unit if it isn't loaded. */
2174 r
= sd_bus_call_method(
2176 "org.freedesktop.systemd1",
2177 "/org/freedesktop/systemd1",
2178 "org.freedesktop.systemd1.Manager",
2186 r
= sd_bus_message_read(reply
, "o", &path
);
2190 r
= sd_bus_get_property_trivial(
2192 "org.freedesktop.systemd1",
2194 "org.freedesktop.systemd1.Unit",
2204 static void warn_unit_file_changed(const char *name
) {
2205 log_warning("%sWarning:%s %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
2206 ansi_highlight_red(),
2207 ansi_highlight_off(),
2209 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user");
2212 static int unit_file_find_path(LookupPaths
*lp
, const char *unit_name
, char **unit_path
) {
2219 STRV_FOREACH(p
, lp
->unit_path
) {
2220 _cleanup_free_
char *path
;
2222 path
= path_join(arg_root
, *p
, unit_name
);
2226 if (access(path
, F_OK
) == 0) {
2236 static int unit_find_paths(
2238 const char *unit_name
,
2239 bool avoid_bus_cache
,
2241 char **fragment_path
,
2242 char ***dropin_paths
) {
2244 _cleanup_free_
char *path
= NULL
;
2245 _cleanup_strv_free_
char **dropins
= NULL
;
2249 * Finds where the unit is defined on disk. Returns 0 if the unit
2250 * is not found. Returns 1 if it is found, and sets
2251 * - the path to the unit in *path, if it exists on disk,
2252 * - and a strv of existing drop-ins in *dropins,
2253 * if the arg is not NULL and any dropins were found.
2257 assert(fragment_path
);
2260 if (!avoid_bus_cache
&& !unit_name_is_template(unit_name
)) {
2261 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2262 _cleanup_bus_message_unref_ sd_bus_message
*unit_load_error
= NULL
;
2263 _cleanup_free_
char *unit
= NULL
;
2264 char *unit_load_error_name
, *unit_load_error_message
;
2266 unit
= unit_dbus_path_from_name(unit_name
);
2270 if (need_daemon_reload(bus
, unit_name
) > 0)
2271 warn_unit_file_changed(unit_name
);
2273 r
= sd_bus_get_property(
2275 "org.freedesktop.systemd1",
2277 "org.freedesktop.systemd1.Unit",
2283 return log_error_errno(r
, "Failed to get LoadError: %s", bus_error_message(&error
, r
));
2285 r
= sd_bus_message_read(
2288 &unit_load_error_name
,
2289 &unit_load_error_message
);
2291 return bus_log_parse_error(r
);
2293 if (!isempty(unit_load_error_name
)) {
2294 log_error("Unit %s is not loaded: %s", unit_name
, unit_load_error_message
);
2298 r
= sd_bus_get_property_string(
2300 "org.freedesktop.systemd1",
2302 "org.freedesktop.systemd1.Unit",
2307 return log_error_errno(r
, "Failed to get FragmentPath: %s", bus_error_message(&error
, r
));
2310 r
= sd_bus_get_property_strv(
2312 "org.freedesktop.systemd1",
2314 "org.freedesktop.systemd1.Unit",
2319 return log_error_errno(r
, "Failed to get DropInPaths: %s", bus_error_message(&error
, r
));
2322 _cleanup_set_free_ Set
*names
;
2324 names
= set_new(NULL
);
2328 r
= set_put(names
, unit_name
);
2332 r
= unit_file_find_path(lp
, unit_name
, &path
);
2337 _cleanup_free_
char *template;
2339 template = unit_name_template(unit_name
);
2343 if (!streq(template, unit_name
)) {
2344 r
= unit_file_find_path(lp
, template, &path
);
2351 r
= unit_file_find_dropin_paths(lp
->unit_path
, NULL
, names
, &dropins
);
2359 if (!isempty(path
)) {
2360 *fragment_path
= path
;
2365 if (dropin_paths
&& !strv_isempty(dropins
)) {
2366 *dropin_paths
= dropins
;
2372 log_error("No files found for %s.", unit_name
);
2377 static int check_one_unit(sd_bus
*bus
, const char *name
, const char *good_states
, bool quiet
) {
2378 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2379 _cleanup_free_
char *n
= NULL
, *state
= NULL
;
2385 n
= unit_name_mangle(name
, MANGLE_NOGLOB
);
2389 /* We don't use unit_dbus_path_from_name() directly since we
2390 * don't want to load the unit if it isn't loaded. */
2392 r
= sd_bus_call_method(
2394 "org.freedesktop.systemd1",
2395 "/org/freedesktop/systemd1",
2396 "org.freedesktop.systemd1.Manager",
2407 r
= sd_bus_message_read(reply
, "o", &path
);
2409 return bus_log_parse_error(r
);
2411 r
= sd_bus_get_property_string(
2413 "org.freedesktop.systemd1",
2415 "org.freedesktop.systemd1.Unit",
2428 return nulstr_contains(good_states
, state
);
2431 static int check_triggering_units(
2435 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2436 _cleanup_free_
char *path
= NULL
, *n
= NULL
, *state
= NULL
;
2437 _cleanup_strv_free_
char **triggered_by
= NULL
;
2438 bool print_warning_label
= true;
2442 n
= unit_name_mangle(name
, MANGLE_NOGLOB
);
2446 path
= unit_dbus_path_from_name(n
);
2450 r
= sd_bus_get_property_string(
2452 "org.freedesktop.systemd1",
2454 "org.freedesktop.systemd1.Unit",
2459 log_error("Failed to get load state of %s: %s", n
, bus_error_message(&error
, r
));
2463 if (streq(state
, "masked"))
2466 r
= sd_bus_get_property_strv(
2468 "org.freedesktop.systemd1",
2470 "org.freedesktop.systemd1.Unit",
2475 log_error("Failed to get triggered by array of %s: %s", n
, bus_error_message(&error
, r
));
2479 STRV_FOREACH(i
, triggered_by
) {
2480 r
= check_one_unit(bus
, *i
, "active\0reloading\0", true);
2482 return log_error_errno(r
, "Failed to check unit: %m");
2487 if (print_warning_label
) {
2488 log_warning("Warning: Stopping %s, but it can still be activated by:", n
);
2489 print_warning_label
= false;
2492 log_warning(" %s", *i
);
2498 static const struct {
2501 } unit_actions
[] = {
2502 { "start", "StartUnit" },
2503 { "stop", "StopUnit" },
2504 { "condstop", "StopUnit" },
2505 { "reload", "ReloadUnit" },
2506 { "restart", "RestartUnit" },
2507 { "try-restart", "TryRestartUnit" },
2508 { "condrestart", "TryRestartUnit" },
2509 { "reload-or-restart", "ReloadOrRestartUnit" },
2510 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2511 { "condreload", "ReloadOrTryRestartUnit" },
2512 { "force-reload", "ReloadOrTryRestartUnit" }
2515 static const char *verb_to_method(const char *verb
) {
2518 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2519 if (streq_ptr(unit_actions
[i
].verb
, verb
))
2520 return unit_actions
[i
].method
;
2525 static const char *method_to_verb(const char *method
) {
2528 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2529 if (streq_ptr(unit_actions
[i
].method
, method
))
2530 return unit_actions
[i
].verb
;
2535 static int start_unit_one(
2540 sd_bus_error
*error
,
2541 BusWaitForJobs
*w
) {
2543 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2552 log_debug("Calling manager for %s on %s, %s", method
, name
, mode
);
2554 r
= sd_bus_call_method(
2556 "org.freedesktop.systemd1",
2557 "/org/freedesktop/systemd1",
2558 "org.freedesktop.systemd1.Manager",
2566 if (r
== -ENOENT
&& arg_action
!= ACTION_SYSTEMCTL
)
2567 /* There's always a fallback possible for
2568 * legacy actions. */
2569 return -EADDRNOTAVAIL
;
2571 verb
= method_to_verb(method
);
2573 log_error("Failed to %s %s: %s", verb
, name
, bus_error_message(error
, r
));
2577 r
= sd_bus_message_read(reply
, "o", &path
);
2579 return bus_log_parse_error(r
);
2581 if (need_daemon_reload(bus
, name
) > 0)
2582 warn_unit_file_changed(name
);
2585 log_debug("Adding %s to the set", path
);
2586 r
= bus_wait_for_jobs_add(w
, path
);
2594 static int expand_names(sd_bus
*bus
, char **names
, const char* suffix
, char ***ret
) {
2596 _cleanup_strv_free_
char **mangled
= NULL
, **globs
= NULL
;
2600 STRV_FOREACH(name
, names
) {
2604 t
= unit_name_mangle_with_suffix(*name
, MANGLE_GLOB
, suffix
);
2606 t
= unit_name_mangle(*name
, MANGLE_GLOB
);
2610 if (string_is_glob(t
))
2611 r
= strv_consume(&globs
, t
);
2613 r
= strv_consume(&mangled
, t
);
2618 /* Query the manager only if any of the names are a glob, since
2619 * this is fairly expensive */
2620 if (!strv_isempty(globs
)) {
2621 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2622 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
2625 return log_error_errno(EOPNOTSUPP
, "Unit name globbing without bus is not implemented.");
2627 r
= get_unit_list(bus
, NULL
, globs
, &unit_infos
, 0, &reply
);
2631 for (i
= 0; i
< r
; i
++)
2632 if (strv_extend(&mangled
, unit_infos
[i
].id
) < 0)
2637 mangled
= NULL
; /* do not free */
2642 static const struct {
2646 } action_table
[_ACTION_MAX
] = {
2647 [ACTION_HALT
] = { SPECIAL_HALT_TARGET
, "halt", "replace-irreversibly" },
2648 [ACTION_POWEROFF
] = { SPECIAL_POWEROFF_TARGET
, "poweroff", "replace-irreversibly" },
2649 [ACTION_REBOOT
] = { SPECIAL_REBOOT_TARGET
, "reboot", "replace-irreversibly" },
2650 [ACTION_KEXEC
] = { SPECIAL_KEXEC_TARGET
, "kexec", "replace-irreversibly" },
2651 [ACTION_RUNLEVEL2
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2652 [ACTION_RUNLEVEL3
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2653 [ACTION_RUNLEVEL4
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
2654 [ACTION_RUNLEVEL5
] = { SPECIAL_GRAPHICAL_TARGET
, NULL
, "isolate" },
2655 [ACTION_RESCUE
] = { SPECIAL_RESCUE_TARGET
, "rescue", "isolate" },
2656 [ACTION_EMERGENCY
] = { SPECIAL_EMERGENCY_TARGET
, "emergency", "isolate" },
2657 [ACTION_DEFAULT
] = { SPECIAL_DEFAULT_TARGET
, "default", "isolate" },
2658 [ACTION_EXIT
] = { SPECIAL_EXIT_TARGET
, "exit", "replace-irreversibly" },
2659 [ACTION_SUSPEND
] = { SPECIAL_SUSPEND_TARGET
, "suspend", "replace-irreversibly" },
2660 [ACTION_HIBERNATE
] = { SPECIAL_HIBERNATE_TARGET
, "hibernate", "replace-irreversibly" },
2661 [ACTION_HYBRID_SLEEP
] = { SPECIAL_HYBRID_SLEEP_TARGET
, "hybrid-sleep", "replace-irreversibly" },
2664 static enum action
verb_to_action(const char *verb
) {
2667 for (i
= _ACTION_INVALID
; i
< _ACTION_MAX
; i
++)
2668 if (streq_ptr(action_table
[i
].verb
, verb
))
2671 return _ACTION_INVALID
;
2674 static int start_unit(sd_bus
*bus
, char **args
) {
2675 _cleanup_(bus_wait_for_jobs_freep
) BusWaitForJobs
*w
= NULL
;
2676 const char *method
, *mode
, *one_name
, *suffix
= NULL
;
2677 _cleanup_strv_free_
char **names
= NULL
;
2683 ask_password_agent_open_if_enabled();
2684 polkit_agent_open_if_enabled();
2686 if (arg_action
== ACTION_SYSTEMCTL
) {
2688 method
= verb_to_method(args
[0]);
2689 action
= verb_to_action(args
[0]);
2691 if (streq(args
[0], "isolate")) {
2695 mode
= action_table
[action
].mode
?: arg_job_mode
;
2697 one_name
= action_table
[action
].target
;
2699 assert(arg_action
< ELEMENTSOF(action_table
));
2700 assert(action_table
[arg_action
].target
);
2702 method
= "StartUnit";
2704 mode
= action_table
[arg_action
].mode
;
2705 one_name
= action_table
[arg_action
].target
;
2709 names
= strv_new(one_name
, NULL
);
2711 r
= expand_names(bus
, args
+ 1, suffix
, &names
);
2713 log_error_errno(r
, "Failed to expand names: %m");
2716 if (!arg_no_block
) {
2717 r
= bus_wait_for_jobs_new(bus
, &w
);
2719 return log_error_errno(r
, "Could not watch jobs: %m");
2722 STRV_FOREACH(name
, names
) {
2723 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2726 q
= start_unit_one(bus
, method
, *name
, mode
, &error
, w
);
2727 if (r
>= 0 && q
< 0)
2728 r
= translate_bus_error_to_exit_status(q
, &error
);
2731 if (!arg_no_block
) {
2734 q
= bus_wait_for_jobs(w
, arg_quiet
);
2738 /* When stopping units, warn if they can still be triggered by
2739 * another active unit (socket, path, timer) */
2740 if (!arg_quiet
&& streq(method
, "StopUnit"))
2741 STRV_FOREACH(name
, names
)
2742 check_triggering_units(bus
, *name
);
2748 /* Ask systemd-logind, which might grant access to unprivileged users
2749 * through PolicyKit */
2750 static int reboot_with_logind(sd_bus
*bus
, enum action a
) {
2752 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2759 polkit_agent_open_if_enabled();
2767 case ACTION_POWEROFF
:
2768 method
= "PowerOff";
2771 case ACTION_SUSPEND
:
2775 case ACTION_HIBERNATE
:
2776 method
= "Hibernate";
2779 case ACTION_HYBRID_SLEEP
:
2780 method
= "HybridSleep";
2787 r
= sd_bus_call_method(
2789 "org.freedesktop.login1",
2790 "/org/freedesktop/login1",
2791 "org.freedesktop.login1.Manager",
2795 "b", arg_ask_password
);
2797 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
2805 static int check_inhibitors(sd_bus
*bus
, enum action a
) {
2807 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2808 _cleanup_strv_free_
char **sessions
= NULL
;
2809 const char *what
, *who
, *why
, *mode
;
2818 if (arg_ignore_inhibitors
|| arg_force
> 0)
2830 r
= sd_bus_call_method(
2832 "org.freedesktop.login1",
2833 "/org/freedesktop/login1",
2834 "org.freedesktop.login1.Manager",
2840 /* If logind is not around, then there are no inhibitors... */
2843 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssuu)");
2845 return bus_log_parse_error(r
);
2847 while ((r
= sd_bus_message_read(reply
, "(ssssuu)", &what
, &who
, &why
, &mode
, &uid
, &pid
)) > 0) {
2848 _cleanup_free_
char *comm
= NULL
, *user
= NULL
;
2849 _cleanup_strv_free_
char **sv
= NULL
;
2851 if (!streq(mode
, "block"))
2854 sv
= strv_split(what
, ":");
2858 if ((pid_t
) pid
< 0)
2859 return log_error_errno(ERANGE
, "Bad PID %"PRIu32
": %m", pid
);
2861 if (!strv_contains(sv
,
2863 a
== ACTION_POWEROFF
||
2864 a
== ACTION_REBOOT
||
2865 a
== ACTION_KEXEC
? "shutdown" : "sleep"))
2868 get_process_comm(pid
, &comm
);
2869 user
= uid_to_name(uid
);
2871 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT
" \"%s\", user %s), reason is \"%s\".",
2872 who
, (pid_t
) pid
, strna(comm
), strna(user
), why
);
2877 return bus_log_parse_error(r
);
2879 r
= sd_bus_message_exit_container(reply
);
2881 return bus_log_parse_error(r
);
2883 /* Check for current sessions */
2884 sd_get_sessions(&sessions
);
2885 STRV_FOREACH(s
, sessions
) {
2886 _cleanup_free_
char *type
= NULL
, *tty
= NULL
, *seat
= NULL
, *user
= NULL
, *service
= NULL
, *class = NULL
;
2888 if (sd_session_get_uid(*s
, &uid
) < 0 || uid
== getuid())
2891 if (sd_session_get_class(*s
, &class) < 0 || !streq(class, "user"))
2894 if (sd_session_get_type(*s
, &type
) < 0 || (!streq(type
, "x11") && !streq(type
, "tty")))
2897 sd_session_get_tty(*s
, &tty
);
2898 sd_session_get_seat(*s
, &seat
);
2899 sd_session_get_service(*s
, &service
);
2900 user
= uid_to_name(uid
);
2902 log_warning("User %s is logged in on %s.", strna(user
), isempty(tty
) ? (isempty(seat
) ? strna(service
) : seat
) : tty
);
2909 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2910 action_table
[a
].verb
);
2918 static int prepare_firmware_setup(sd_bus
*bus
) {
2920 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2924 if (!arg_firmware_setup
)
2927 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
2929 r
= efi_set_reboot_to_firmware(true);
2931 log_debug_errno(r
, "Cannot indicate to EFI to boot into setup mode, will retry via logind: %m");
2937 r
= sd_bus_call_method(
2939 "org.freedesktop.login1",
2940 "/org/freedesktop/login1",
2941 "org.freedesktop.login1.Manager",
2942 "SetRebootToFirmwareSetup",
2947 log_error("Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error
, r
));
2953 log_error("Cannot remotely indicate to EFI to boot into setup mode.");
2958 static int start_special(sd_bus
*bus
, char **args
) {
2964 a
= verb_to_action(args
[0]);
2966 r
= check_inhibitors(bus
, a
);
2970 if (arg_force
>= 2 && geteuid() != 0) {
2971 log_error("Must be root.");
2975 r
= prepare_firmware_setup(bus
);
2979 if (a
== ACTION_REBOOT
&& args
[1]) {
2980 r
= update_reboot_param_file(args
[1]);
2985 if (arg_force
>= 2 &&
2986 (a
== ACTION_HALT
||
2987 a
== ACTION_POWEROFF
||
2988 a
== ACTION_REBOOT
))
2991 if (arg_force
>= 1 &&
2992 (a
== ACTION_HALT
||
2993 a
== ACTION_POWEROFF
||
2994 a
== ACTION_REBOOT
||
2995 a
== ACTION_KEXEC
||
2997 return daemon_reload(bus
, args
);
2999 /* first try logind, to allow authentication with polkit */
3000 if (geteuid() != 0 &&
3001 (a
== ACTION_POWEROFF
||
3002 a
== ACTION_REBOOT
||
3003 a
== ACTION_SUSPEND
||
3004 a
== ACTION_HIBERNATE
||
3005 a
== ACTION_HYBRID_SLEEP
)) {
3006 r
= reboot_with_logind(bus
, a
);
3007 if (r
>= 0 || IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
3011 r
= start_unit(bus
, args
);
3012 if (r
== EXIT_SUCCESS
)
3018 static int check_unit_generic(sd_bus
*bus
, int code
, const char *good_states
, char **args
) {
3019 _cleanup_strv_free_
char **names
= NULL
;
3026 r
= expand_names(bus
, args
, NULL
, &names
);
3028 return log_error_errno(r
, "Failed to expand names: %m");
3030 STRV_FOREACH(name
, names
) {
3033 state
= check_one_unit(bus
, *name
, good_states
, arg_quiet
);
3043 static int check_unit_active(sd_bus
*bus
, char **args
) {
3044 /* According to LSB: 3, "program is not running" */
3045 return check_unit_generic(bus
, 3, "active\0reloading\0", args
+ 1);
3048 static int check_unit_failed(sd_bus
*bus
, char **args
) {
3049 return check_unit_generic(bus
, 1, "failed\0", args
+ 1);
3052 static int kill_unit(sd_bus
*bus
, char **args
) {
3053 _cleanup_strv_free_
char **names
= NULL
;
3060 polkit_agent_open_if_enabled();
3063 arg_kill_who
= "all";
3065 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
3067 log_error_errno(r
, "Failed to expand names: %m");
3069 STRV_FOREACH(name
, names
) {
3070 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
3072 q
= sd_bus_call_method(
3074 "org.freedesktop.systemd1",
3075 "/org/freedesktop/systemd1",
3076 "org.freedesktop.systemd1.Manager",
3080 "ssi", *names
, arg_kill_who
, arg_signal
);
3082 log_error("Failed to kill unit %s: %s", *names
, bus_error_message(&error
, q
));
3091 typedef struct ExecStatusInfo
{
3099 usec_t start_timestamp
;
3100 usec_t exit_timestamp
;
3105 LIST_FIELDS(struct ExecStatusInfo
, exec
);
3108 static void exec_status_info_free(ExecStatusInfo
*i
) {
3117 static int exec_status_info_deserialize(sd_bus_message
*m
, ExecStatusInfo
*i
) {
3118 uint64_t start_timestamp
, exit_timestamp
, start_timestamp_monotonic
, exit_timestamp_monotonic
;
3121 int32_t code
, status
;
3127 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_STRUCT
, "sasbttttuii");
3129 return bus_log_parse_error(r
);
3133 r
= sd_bus_message_read(m
, "s", &path
);
3135 return bus_log_parse_error(r
);
3137 i
->path
= strdup(path
);
3141 r
= sd_bus_message_read_strv(m
, &i
->argv
);
3143 return bus_log_parse_error(r
);
3145 r
= sd_bus_message_read(m
,
3148 &start_timestamp
, &start_timestamp_monotonic
,
3149 &exit_timestamp
, &exit_timestamp_monotonic
,
3153 return bus_log_parse_error(r
);
3156 i
->start_timestamp
= (usec_t
) start_timestamp
;
3157 i
->exit_timestamp
= (usec_t
) exit_timestamp
;
3158 i
->pid
= (pid_t
) pid
;
3162 r
= sd_bus_message_exit_container(m
);
3164 return bus_log_parse_error(r
);
3169 typedef struct UnitStatusInfo
{
3171 const char *load_state
;
3172 const char *active_state
;
3173 const char *sub_state
;
3174 const char *unit_file_state
;
3175 const char *unit_file_preset
;
3177 const char *description
;
3178 const char *following
;
3180 char **documentation
;
3182 const char *fragment_path
;
3183 const char *source_path
;
3184 const char *control_group
;
3186 char **dropin_paths
;
3188 const char *load_error
;
3191 usec_t inactive_exit_timestamp
;
3192 usec_t inactive_exit_timestamp_monotonic
;
3193 usec_t active_enter_timestamp
;
3194 usec_t active_exit_timestamp
;
3195 usec_t inactive_enter_timestamp
;
3197 bool need_daemon_reload
;
3202 const char *status_text
;
3203 const char *pid_file
;
3207 usec_t start_timestamp
;
3208 usec_t exit_timestamp
;
3210 int exit_code
, exit_status
;
3212 usec_t condition_timestamp
;
3213 bool condition_result
;
3214 bool failed_condition_trigger
;
3215 bool failed_condition_negate
;
3216 const char *failed_condition
;
3217 const char *failed_condition_parameter
;
3219 usec_t assert_timestamp
;
3221 bool failed_assert_trigger
;
3222 bool failed_assert_negate
;
3223 const char *failed_assert
;
3224 const char *failed_assert_parameter
;
3227 unsigned n_accepted
;
3228 unsigned n_connections
;
3231 /* Pairs of type, path */
3235 const char *sysfs_path
;
3237 /* Mount, Automount */
3244 uint64_t memory_current
;
3245 uint64_t memory_limit
;
3246 uint64_t cpu_usage_nsec
;
3248 LIST_HEAD(ExecStatusInfo
, exec
);
3251 static void print_status_info(
3256 const char *active_on
, *active_off
, *on
, *off
, *ss
;
3258 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], *s1
;
3259 char since2
[FORMAT_TIMESTAMP_MAX
], *s2
;
3265 /* This shows pretty information about a unit. See
3266 * print_property() for a low-level property printer */
3268 if (streq_ptr(i
->active_state
, "failed")) {
3269 active_on
= ansi_highlight_red();
3270 active_off
= ansi_highlight_off();
3271 } else if (streq_ptr(i
->active_state
, "active") || streq_ptr(i
->active_state
, "reloading")) {
3272 active_on
= ansi_highlight_green();
3273 active_off
= ansi_highlight_off();
3275 active_on
= active_off
= "";
3277 printf("%s%s%s %s", active_on
, draw_special_char(DRAW_BLACK_CIRCLE
), active_off
, strna(i
->id
));
3279 if (i
->description
&& !streq_ptr(i
->id
, i
->description
))
3280 printf(" - %s", i
->description
);
3285 printf(" Follow: unit currently follows state of %s\n", i
->following
);
3287 if (streq_ptr(i
->load_state
, "error")) {
3288 on
= ansi_highlight_red();
3289 off
= ansi_highlight_off();
3293 path
= i
->source_path
? i
->source_path
: i
->fragment_path
;
3296 printf(" Loaded: %s%s%s (Reason: %s)\n",
3297 on
, strna(i
->load_state
), off
, i
->load_error
);
3298 else if (path
&& !isempty(i
->unit_file_state
) && !isempty(i
->unit_file_preset
))
3299 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
3300 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
, i
->unit_file_preset
);
3301 else if (path
&& !isempty(i
->unit_file_state
))
3302 printf(" Loaded: %s%s%s (%s; %s)\n",
3303 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
);
3305 printf(" Loaded: %s%s%s (%s)\n",
3306 on
, strna(i
->load_state
), off
, path
);
3308 printf(" Loaded: %s%s%s\n",
3309 on
, strna(i
->load_state
), off
);
3311 if (!strv_isempty(i
->dropin_paths
)) {
3312 _cleanup_free_
char *dir
= NULL
;
3316 STRV_FOREACH(dropin
, i
->dropin_paths
) {
3317 if (! dir
|| last
) {
3318 printf(dir
? " " : " Drop-In: ");
3323 if (path_get_parent(*dropin
, &dir
) < 0) {
3328 printf("%s\n %s", dir
,
3329 draw_special_char(DRAW_TREE_RIGHT
));
3332 last
= ! (*(dropin
+ 1) && startswith(*(dropin
+ 1), dir
));
3334 printf("%s%s", basename(*dropin
), last
? "\n" : ", ");
3338 ss
= streq_ptr(i
->active_state
, i
->sub_state
) ? NULL
: i
->sub_state
;
3340 printf(" Active: %s%s (%s)%s",
3341 active_on
, strna(i
->active_state
), ss
, active_off
);
3343 printf(" Active: %s%s%s",
3344 active_on
, strna(i
->active_state
), active_off
);
3346 if (!isempty(i
->result
) && !streq(i
->result
, "success"))
3347 printf(" (Result: %s)", i
->result
);
3349 timestamp
= (streq_ptr(i
->active_state
, "active") ||
3350 streq_ptr(i
->active_state
, "reloading")) ? i
->active_enter_timestamp
:
3351 (streq_ptr(i
->active_state
, "inactive") ||
3352 streq_ptr(i
->active_state
, "failed")) ? i
->inactive_enter_timestamp
:
3353 streq_ptr(i
->active_state
, "activating") ? i
->inactive_exit_timestamp
:
3354 i
->active_exit_timestamp
;
3356 s1
= format_timestamp_relative(since1
, sizeof(since1
), timestamp
);
3357 s2
= format_timestamp(since2
, sizeof(since2
), timestamp
);
3360 printf(" since %s; %s\n", s2
, s1
);
3362 printf(" since %s\n", s2
);
3366 if (!i
->condition_result
&& i
->condition_timestamp
> 0) {
3367 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->condition_timestamp
);
3368 s2
= format_timestamp(since2
, sizeof(since2
), i
->condition_timestamp
);
3370 printf("Condition: start %scondition failed%s at %s%s%s\n",
3371 ansi_highlight_yellow(), ansi_highlight_off(),
3372 s2
, s1
? "; " : "", s1
? s1
: "");
3373 if (i
->failed_condition_trigger
)
3374 printf(" none of the trigger conditions were met\n");
3375 else if (i
->failed_condition
)
3376 printf(" %s=%s%s was not met\n",
3377 i
->failed_condition
,
3378 i
->failed_condition_negate
? "!" : "",
3379 i
->failed_condition_parameter
);
3382 if (!i
->assert_result
&& i
->assert_timestamp
> 0) {
3383 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->assert_timestamp
);
3384 s2
= format_timestamp(since2
, sizeof(since2
), i
->assert_timestamp
);
3386 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
3387 ansi_highlight_red(), ansi_highlight_off(),
3388 s2
, s1
? "; " : "", s1
? s1
: "");
3389 if (i
->failed_assert_trigger
)
3390 printf(" none of the trigger assertions were met\n");
3391 else if (i
->failed_assert
)
3392 printf(" %s=%s%s was not met\n",
3394 i
->failed_assert_negate
? "!" : "",
3395 i
->failed_assert_parameter
);
3399 printf(" Device: %s\n", i
->sysfs_path
);
3401 printf(" Where: %s\n", i
->where
);
3403 printf(" What: %s\n", i
->what
);
3405 STRV_FOREACH(t
, i
->documentation
)
3406 printf(" %*s %s\n", 9, t
== i
->documentation
? "Docs:" : "", *t
);
3408 STRV_FOREACH_PAIR(t
, t2
, i
->listen
)
3409 printf(" %*s %s (%s)\n", 9, t
== i
->listen
? "Listen:" : "", *t2
, *t
);
3412 printf(" Accepted: %u; Connected: %u\n", i
->n_accepted
, i
->n_connections
);
3414 LIST_FOREACH(exec
, p
, i
->exec
) {
3415 _cleanup_free_
char *argv
= NULL
;
3418 /* Only show exited processes here */
3422 argv
= strv_join(p
->argv
, " ");
3423 printf(" Process: "PID_FMT
" %s=%s ", p
->pid
, p
->name
, strna(argv
));
3425 good
= is_clean_exit_lsb(p
->code
, p
->status
, NULL
);
3427 on
= ansi_highlight_red();
3428 off
= ansi_highlight_off();
3432 printf("%s(code=%s, ", on
, sigchld_code_to_string(p
->code
));
3434 if (p
->code
== CLD_EXITED
) {
3437 printf("status=%i", p
->status
);
3439 c
= exit_status_to_string(p
->status
, EXIT_STATUS_SYSTEMD
);
3444 printf("signal=%s", signal_to_string(p
->status
));
3446 printf(")%s\n", off
);
3448 if (i
->main_pid
== p
->pid
&&
3449 i
->start_timestamp
== p
->start_timestamp
&&
3450 i
->exit_timestamp
== p
->start_timestamp
)
3451 /* Let's not show this twice */
3454 if (p
->pid
== i
->control_pid
)
3458 if (i
->main_pid
> 0 || i
->control_pid
> 0) {
3459 if (i
->main_pid
> 0) {
3460 printf(" Main PID: "PID_FMT
, i
->main_pid
);
3463 _cleanup_free_
char *comm
= NULL
;
3464 get_process_comm(i
->main_pid
, &comm
);
3466 printf(" (%s)", comm
);
3467 } else if (i
->exit_code
> 0) {
3468 printf(" (code=%s, ", sigchld_code_to_string(i
->exit_code
));
3470 if (i
->exit_code
== CLD_EXITED
) {
3473 printf("status=%i", i
->exit_status
);
3475 c
= exit_status_to_string(i
->exit_status
, EXIT_STATUS_SYSTEMD
);
3480 printf("signal=%s", signal_to_string(i
->exit_status
));
3484 if (i
->control_pid
> 0)
3488 if (i
->control_pid
> 0) {
3489 _cleanup_free_
char *c
= NULL
;
3491 printf(" %8s: "PID_FMT
, i
->main_pid
? "" : " Control", i
->control_pid
);
3493 get_process_comm(i
->control_pid
, &c
);
3502 printf(" Status: \"%s\"\n", i
->status_text
);
3503 if (i
->status_errno
> 0)
3504 printf(" Error: %i (%s)\n", i
->status_errno
, strerror(i
->status_errno
));
3506 if (i
->memory_current
!= (uint64_t) -1) {
3507 char buf
[FORMAT_BYTES_MAX
];
3509 printf(" Memory: %s", format_bytes(buf
, sizeof(buf
), i
->memory_current
));
3511 if (i
->memory_limit
!= (uint64_t) -1)
3512 printf(" (limit: %s)\n", format_bytes(buf
, sizeof(buf
), i
->memory_limit
));
3517 if (i
->cpu_usage_nsec
!= (uint64_t) -1) {
3518 char buf
[FORMAT_TIMESPAN_MAX
];
3519 printf(" CPU: %s\n", format_timespan(buf
, sizeof(buf
), i
->cpu_usage_nsec
/ NSEC_PER_USEC
, USEC_PER_MSEC
));
3522 if (i
->control_group
&&
3523 (i
->main_pid
> 0 || i
->control_pid
> 0 ||
3524 ((arg_transport
!= BUS_TRANSPORT_LOCAL
&& arg_transport
!= BUS_TRANSPORT_MACHINE
) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, false) == 0))) {
3527 printf(" CGroup: %s\n", i
->control_group
);
3529 if (arg_transport
== BUS_TRANSPORT_LOCAL
|| arg_transport
== BUS_TRANSPORT_MACHINE
) {
3532 static const char prefix
[] = " ";
3535 if (c
> sizeof(prefix
) - 1)
3536 c
-= sizeof(prefix
) - 1;
3540 if (i
->main_pid
> 0)
3541 extra
[k
++] = i
->main_pid
;
3543 if (i
->control_pid
> 0)
3544 extra
[k
++] = i
->control_pid
;
3546 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, prefix
, c
, false, extra
, k
, get_output_flags());
3550 if (i
->id
&& arg_transport
== BUS_TRANSPORT_LOCAL
) {
3551 show_journal_by_unit(
3556 i
->inactive_exit_timestamp_monotonic
,
3559 get_output_flags() | OUTPUT_BEGIN_NEWLINE
,
3560 SD_JOURNAL_LOCAL_ONLY
,
3561 arg_scope
== UNIT_FILE_SYSTEM
,
3565 if (i
->need_daemon_reload
)
3566 warn_unit_file_changed(i
->id
);
3569 static void show_unit_help(UnitStatusInfo
*i
) {
3574 if (!i
->documentation
) {
3575 log_info("Documentation for %s not known.", i
->id
);
3579 STRV_FOREACH(p
, i
->documentation
)
3580 if (startswith(*p
, "man:"))
3581 show_man_page(*p
+ 4, false);
3583 log_info("Can't show: %s", *p
);
3586 static int status_property(const char *name
, sd_bus_message
*m
, UnitStatusInfo
*i
, const char *contents
) {
3593 switch (contents
[0]) {
3595 case SD_BUS_TYPE_STRING
: {
3598 r
= sd_bus_message_read(m
, "s", &s
);
3600 return bus_log_parse_error(r
);
3603 if (streq(name
, "Id"))
3605 else if (streq(name
, "LoadState"))
3607 else if (streq(name
, "ActiveState"))
3608 i
->active_state
= s
;
3609 else if (streq(name
, "SubState"))
3611 else if (streq(name
, "Description"))
3613 else if (streq(name
, "FragmentPath"))
3614 i
->fragment_path
= s
;
3615 else if (streq(name
, "SourcePath"))
3618 else if (streq(name
, "DefaultControlGroup")) {
3620 e
= startswith(s
, SYSTEMD_CGROUP_CONTROLLER
":");
3622 i
->control_group
= e
;
3625 else if (streq(name
, "ControlGroup"))
3626 i
->control_group
= s
;
3627 else if (streq(name
, "StatusText"))
3629 else if (streq(name
, "PIDFile"))
3631 else if (streq(name
, "SysFSPath"))
3633 else if (streq(name
, "Where"))
3635 else if (streq(name
, "What"))
3637 else if (streq(name
, "Following"))
3639 else if (streq(name
, "UnitFileState"))
3640 i
->unit_file_state
= s
;
3641 else if (streq(name
, "UnitFilePreset"))
3642 i
->unit_file_preset
= s
;
3643 else if (streq(name
, "Result"))
3650 case SD_BUS_TYPE_BOOLEAN
: {
3653 r
= sd_bus_message_read(m
, "b", &b
);
3655 return bus_log_parse_error(r
);
3657 if (streq(name
, "Accept"))
3659 else if (streq(name
, "NeedDaemonReload"))
3660 i
->need_daemon_reload
= b
;
3661 else if (streq(name
, "ConditionResult"))
3662 i
->condition_result
= b
;
3663 else if (streq(name
, "AssertResult"))
3664 i
->assert_result
= b
;
3669 case SD_BUS_TYPE_UINT32
: {
3672 r
= sd_bus_message_read(m
, "u", &u
);
3674 return bus_log_parse_error(r
);
3676 if (streq(name
, "MainPID")) {
3678 i
->main_pid
= (pid_t
) u
;
3681 } else if (streq(name
, "ControlPID"))
3682 i
->control_pid
= (pid_t
) u
;
3683 else if (streq(name
, "ExecMainPID")) {
3685 i
->main_pid
= (pid_t
) u
;
3686 } else if (streq(name
, "NAccepted"))
3688 else if (streq(name
, "NConnections"))
3689 i
->n_connections
= u
;
3694 case SD_BUS_TYPE_INT32
: {
3697 r
= sd_bus_message_read(m
, "i", &j
);
3699 return bus_log_parse_error(r
);
3701 if (streq(name
, "ExecMainCode"))
3702 i
->exit_code
= (int) j
;
3703 else if (streq(name
, "ExecMainStatus"))
3704 i
->exit_status
= (int) j
;
3705 else if (streq(name
, "StatusErrno"))
3706 i
->status_errno
= (int) j
;
3711 case SD_BUS_TYPE_UINT64
: {
3714 r
= sd_bus_message_read(m
, "t", &u
);
3716 return bus_log_parse_error(r
);
3718 if (streq(name
, "ExecMainStartTimestamp"))
3719 i
->start_timestamp
= (usec_t
) u
;
3720 else if (streq(name
, "ExecMainExitTimestamp"))
3721 i
->exit_timestamp
= (usec_t
) u
;
3722 else if (streq(name
, "ActiveEnterTimestamp"))
3723 i
->active_enter_timestamp
= (usec_t
) u
;
3724 else if (streq(name
, "InactiveEnterTimestamp"))
3725 i
->inactive_enter_timestamp
= (usec_t
) u
;
3726 else if (streq(name
, "InactiveExitTimestamp"))
3727 i
->inactive_exit_timestamp
= (usec_t
) u
;
3728 else if (streq(name
, "InactiveExitTimestampMonotonic"))
3729 i
->inactive_exit_timestamp_monotonic
= (usec_t
) u
;
3730 else if (streq(name
, "ActiveExitTimestamp"))
3731 i
->active_exit_timestamp
= (usec_t
) u
;
3732 else if (streq(name
, "ConditionTimestamp"))
3733 i
->condition_timestamp
= (usec_t
) u
;
3734 else if (streq(name
, "AssertTimestamp"))
3735 i
->assert_timestamp
= (usec_t
) u
;
3736 else if (streq(name
, "MemoryCurrent"))
3737 i
->memory_current
= u
;
3738 else if (streq(name
, "MemoryLimit"))
3739 i
->memory_limit
= u
;
3740 else if (streq(name
, "CPUUsageNSec"))
3741 i
->cpu_usage_nsec
= u
;
3746 case SD_BUS_TYPE_ARRAY
:
3748 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
3749 _cleanup_free_ ExecStatusInfo
*info
= NULL
;
3751 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
3753 return bus_log_parse_error(r
);
3755 info
= new0(ExecStatusInfo
, 1);
3759 while ((r
= exec_status_info_deserialize(m
, info
)) > 0) {
3761 info
->name
= strdup(name
);
3765 LIST_PREPEND(exec
, i
->exec
, info
);
3767 info
= new0(ExecStatusInfo
, 1);
3773 return bus_log_parse_error(r
);
3775 r
= sd_bus_message_exit_container(m
);
3777 return bus_log_parse_error(r
);
3781 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
3782 const char *type
, *path
;
3784 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
3786 return bus_log_parse_error(r
);
3788 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0) {
3790 r
= strv_extend(&i
->listen
, type
);
3794 r
= strv_extend(&i
->listen
, path
);
3799 return bus_log_parse_error(r
);
3801 r
= sd_bus_message_exit_container(m
);
3803 return bus_log_parse_error(r
);
3807 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "DropInPaths")) {
3809 r
= sd_bus_message_read_strv(m
, &i
->dropin_paths
);
3811 return bus_log_parse_error(r
);
3813 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Documentation")) {
3815 r
= sd_bus_message_read_strv(m
, &i
->documentation
);
3817 return bus_log_parse_error(r
);
3819 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Conditions")) {
3820 const char *cond
, *param
;
3821 int trigger
, negate
;
3824 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
3826 return bus_log_parse_error(r
);
3828 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
3829 log_debug("%s %d %d %s %d", cond
, trigger
, negate
, param
, state
);
3830 if (state
< 0 && (!trigger
|| !i
->failed_condition
)) {
3831 i
->failed_condition
= cond
;
3832 i
->failed_condition_trigger
= trigger
;
3833 i
->failed_condition_negate
= negate
;
3834 i
->failed_condition_parameter
= param
;
3838 return bus_log_parse_error(r
);
3840 r
= sd_bus_message_exit_container(m
);
3842 return bus_log_parse_error(r
);
3844 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Asserts")) {
3845 const char *cond
, *param
;
3846 int trigger
, negate
;
3849 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
3851 return bus_log_parse_error(r
);
3853 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
3854 log_debug("%s %d %d %s %d", cond
, trigger
, negate
, param
, state
);
3855 if (state
< 0 && (!trigger
|| !i
->failed_assert
)) {
3856 i
->failed_assert
= cond
;
3857 i
->failed_assert_trigger
= trigger
;
3858 i
->failed_assert_negate
= negate
;
3859 i
->failed_assert_parameter
= param
;
3863 return bus_log_parse_error(r
);
3865 r
= sd_bus_message_exit_container(m
);
3867 return bus_log_parse_error(r
);
3874 case SD_BUS_TYPE_STRUCT_BEGIN
:
3876 if (streq(name
, "LoadError")) {
3877 const char *n
, *message
;
3879 r
= sd_bus_message_read(m
, "(ss)", &n
, &message
);
3881 return bus_log_parse_error(r
);
3883 if (!isempty(message
))
3884 i
->load_error
= message
;
3897 r
= sd_bus_message_skip(m
, contents
);
3899 return bus_log_parse_error(r
);
3904 static int print_property(const char *name
, sd_bus_message
*m
, const char *contents
) {
3910 /* This is a low-level property printer, see
3911 * print_status_info() for the nicer output */
3913 if (arg_properties
&& !strv_find(arg_properties
, name
)) {
3914 /* skip what we didn't read */
3915 r
= sd_bus_message_skip(m
, contents
);
3919 switch (contents
[0]) {
3921 case SD_BUS_TYPE_STRUCT_BEGIN
:
3923 if (contents
[1] == SD_BUS_TYPE_UINT32
&& streq(name
, "Job")) {
3926 r
= sd_bus_message_read(m
, "(uo)", &u
, NULL
);
3928 return bus_log_parse_error(r
);
3931 printf("%s=%"PRIu32
"\n", name
, u
);
3933 printf("%s=\n", name
);
3937 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Unit")) {
3940 r
= sd_bus_message_read(m
, "(so)", &s
, NULL
);
3942 return bus_log_parse_error(r
);
3944 if (arg_all
|| !isempty(s
))
3945 printf("%s=%s\n", name
, s
);
3949 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "LoadError")) {
3950 const char *a
= NULL
, *b
= NULL
;
3952 r
= sd_bus_message_read(m
, "(ss)", &a
, &b
);
3954 return bus_log_parse_error(r
);
3956 if (arg_all
|| !isempty(a
) || !isempty(b
))
3957 printf("%s=%s \"%s\"\n", name
, strempty(a
), strempty(b
));
3960 } else if (streq_ptr(name
, "SystemCallFilter")) {
3961 _cleanup_strv_free_
char **l
= NULL
;
3964 r
= sd_bus_message_enter_container(m
, 'r', "bas");
3966 return bus_log_parse_error(r
);
3968 r
= sd_bus_message_read(m
, "b", &whitelist
);
3970 return bus_log_parse_error(r
);
3972 r
= sd_bus_message_read_strv(m
, &l
);
3974 return bus_log_parse_error(r
);
3976 r
= sd_bus_message_exit_container(m
);
3978 return bus_log_parse_error(r
);
3980 if (arg_all
|| whitelist
|| !strv_isempty(l
)) {
3984 fputs(name
, stdout
);
3990 STRV_FOREACH(i
, l
) {
3998 fputc('\n', stdout
);
4006 case SD_BUS_TYPE_ARRAY
:
4008 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "EnvironmentFiles")) {
4012 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sb)");
4014 return bus_log_parse_error(r
);
4016 while ((r
= sd_bus_message_read(m
, "(sb)", &path
, &ignore
)) > 0)
4017 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path
, yes_no(ignore
));
4020 return bus_log_parse_error(r
);
4022 r
= sd_bus_message_exit_container(m
);
4024 return bus_log_parse_error(r
);
4028 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Paths")) {
4029 const char *type
, *path
;
4031 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4033 return bus_log_parse_error(r
);
4035 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4036 printf("%s=%s\n", type
, path
);
4038 return bus_log_parse_error(r
);
4040 r
= sd_bus_message_exit_container(m
);
4042 return bus_log_parse_error(r
);
4046 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
4047 const char *type
, *path
;
4049 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4051 return bus_log_parse_error(r
);
4053 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4054 printf("Listen%s=%s\n", type
, path
);
4056 return bus_log_parse_error(r
);
4058 r
= sd_bus_message_exit_container(m
);
4060 return bus_log_parse_error(r
);
4064 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Timers")) {
4066 uint64_t value
, next_elapse
;
4068 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(stt)");
4070 return bus_log_parse_error(r
);
4072 while ((r
= sd_bus_message_read(m
, "(stt)", &base
, &value
, &next_elapse
)) > 0) {
4073 char timespan1
[FORMAT_TIMESPAN_MAX
], timespan2
[FORMAT_TIMESPAN_MAX
];
4075 printf("%s={ value=%s ; next_elapse=%s }\n",
4077 format_timespan(timespan1
, sizeof(timespan1
), value
, 0),
4078 format_timespan(timespan2
, sizeof(timespan2
), next_elapse
, 0));
4081 return bus_log_parse_error(r
);
4083 r
= sd_bus_message_exit_container(m
);
4085 return bus_log_parse_error(r
);
4089 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
4090 ExecStatusInfo info
= {};
4092 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4094 return bus_log_parse_error(r
);
4096 while ((r
= exec_status_info_deserialize(m
, &info
)) > 0) {
4097 char timestamp1
[FORMAT_TIMESTAMP_MAX
], timestamp2
[FORMAT_TIMESTAMP_MAX
];
4098 _cleanup_free_
char *tt
;
4100 tt
= strv_join(info
.argv
, " ");
4102 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",
4106 yes_no(info
.ignore
),
4107 strna(format_timestamp(timestamp1
, sizeof(timestamp1
), info
.start_timestamp
)),
4108 strna(format_timestamp(timestamp2
, sizeof(timestamp2
), info
.exit_timestamp
)),
4110 sigchld_code_to_string(info
.code
),
4112 info
.code
== CLD_EXITED
? "" : "/",
4113 strempty(info
.code
== CLD_EXITED
? NULL
: signal_to_string(info
.status
)));
4116 strv_free(info
.argv
);
4120 r
= sd_bus_message_exit_container(m
);
4122 return bus_log_parse_error(r
);
4126 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "DeviceAllow")) {
4127 const char *path
, *rwm
;
4129 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4131 return bus_log_parse_error(r
);
4133 while ((r
= sd_bus_message_read(m
, "(ss)", &path
, &rwm
)) > 0)
4134 printf("%s=%s %s\n", name
, strna(path
), strna(rwm
));
4136 return bus_log_parse_error(r
);
4138 r
= sd_bus_message_exit_container(m
);
4140 return bus_log_parse_error(r
);
4144 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "BlockIODeviceWeight")) {
4148 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4150 return bus_log_parse_error(r
);
4152 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &weight
)) > 0)
4153 printf("%s=%s %" PRIu64
"\n", name
, strna(path
), weight
);
4155 return bus_log_parse_error(r
);
4157 r
= sd_bus_message_exit_container(m
);
4159 return bus_log_parse_error(r
);
4163 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& (streq(name
, "BlockIOReadBandwidth") || streq(name
, "BlockIOWriteBandwidth"))) {
4167 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4169 return bus_log_parse_error(r
);
4171 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &bandwidth
)) > 0)
4172 printf("%s=%s %" PRIu64
"\n", name
, strna(path
), bandwidth
);
4174 return bus_log_parse_error(r
);
4176 r
= sd_bus_message_exit_container(m
);
4178 return bus_log_parse_error(r
);
4186 r
= bus_print_property(name
, m
, arg_all
);
4188 return bus_log_parse_error(r
);
4191 r
= sd_bus_message_skip(m
, contents
);
4193 return bus_log_parse_error(r
);
4196 printf("%s=[unprintable]\n", name
);
4202 static int show_one(
4206 bool show_properties
,
4210 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4211 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4212 UnitStatusInfo info
= {
4213 .memory_current
= (uint64_t) -1,
4214 .memory_limit
= (uint64_t) -1,
4215 .cpu_usage_nsec
= (uint64_t) -1,
4223 log_debug("Showing one %s", path
);
4225 r
= sd_bus_call_method(
4227 "org.freedesktop.systemd1",
4229 "org.freedesktop.DBus.Properties",
4235 log_error("Failed to get properties: %s", bus_error_message(&error
, r
));
4239 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
4241 return bus_log_parse_error(r
);
4248 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
4249 const char *name
, *contents
;
4251 r
= sd_bus_message_read(reply
, "s", &name
);
4253 return bus_log_parse_error(r
);
4255 r
= sd_bus_message_peek_type(reply
, NULL
, &contents
);
4257 return bus_log_parse_error(r
);
4259 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, contents
);
4261 return bus_log_parse_error(r
);
4263 if (show_properties
)
4264 r
= print_property(name
, reply
, contents
);
4266 r
= status_property(name
, reply
, &info
, contents
);
4270 r
= sd_bus_message_exit_container(reply
);
4272 return bus_log_parse_error(r
);
4274 r
= sd_bus_message_exit_container(reply
);
4276 return bus_log_parse_error(r
);
4279 return bus_log_parse_error(r
);
4281 r
= sd_bus_message_exit_container(reply
);
4283 return bus_log_parse_error(r
);
4287 if (!show_properties
) {
4288 if (streq(verb
, "help"))
4289 show_unit_help(&info
);
4291 print_status_info(&info
, ellipsized
);
4294 strv_free(info
.documentation
);
4295 strv_free(info
.dropin_paths
);
4296 strv_free(info
.listen
);
4298 if (!streq_ptr(info
.active_state
, "active") &&
4299 !streq_ptr(info
.active_state
, "reloading") &&
4300 streq(verb
, "status")) {
4301 /* According to LSB: "program not running" */
4302 /* 0: program is running or service is OK
4303 * 1: program is dead and /run PID file exists
4304 * 2: program is dead and /run/lock lock file exists
4305 * 3: program is not running
4306 * 4: program or service status is unknown
4308 if (info
.pid_file
&& access(info
.pid_file
, F_OK
) == 0)
4314 while ((p
= info
.exec
)) {
4315 LIST_REMOVE(exec
, info
.exec
, p
);
4316 exec_status_info_free(p
);
4322 static int get_unit_dbus_path_by_pid(
4327 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4328 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4332 r
= sd_bus_call_method(
4334 "org.freedesktop.systemd1",
4335 "/org/freedesktop/systemd1",
4336 "org.freedesktop.systemd1.Manager",
4342 log_error("Failed to get unit for PID %"PRIu32
": %s", pid
, bus_error_message(&error
, r
));
4346 r
= sd_bus_message_read(reply
, "o", &u
);
4348 return bus_log_parse_error(r
);
4358 static int show_all(
4361 bool show_properties
,
4365 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4366 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
4371 r
= get_unit_list(bus
, NULL
, NULL
, &unit_infos
, 0, &reply
);
4375 pager_open_if_enabled();
4379 qsort_safe(unit_infos
, c
, sizeof(UnitInfo
), compare_unit_info
);
4381 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
4382 _cleanup_free_
char *p
= NULL
;
4384 p
= unit_dbus_path_from_name(u
->id
);
4388 r
= show_one(verb
, bus
, p
, show_properties
, new_line
, ellipsized
);
4391 else if (r
> 0 && ret
== 0)
4398 static int show_system_status(sd_bus
*bus
) {
4399 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], since2
[FORMAT_TIMESTAMP_MAX
];
4400 _cleanup_free_
char *hn
= NULL
;
4401 struct machine_info mi
= {};
4402 const char *on
, *off
;
4405 hn
= gethostname_malloc();
4409 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, &mi
);
4411 return log_error_errno(r
, "Failed to read server status: %m");
4413 if (streq_ptr(mi
.state
, "degraded")) {
4414 on
= ansi_highlight_red();
4415 off
= ansi_highlight_off();
4416 } else if (!streq_ptr(mi
.state
, "running")) {
4417 on
= ansi_highlight_yellow();
4418 off
= ansi_highlight_off();
4422 printf("%s%s%s %s\n", on
, draw_special_char(DRAW_BLACK_CIRCLE
), off
, arg_host
? arg_host
: hn
);
4424 printf(" State: %s%s%s\n",
4425 on
, strna(mi
.state
), off
);
4427 printf(" Jobs: %u queued\n", mi
.n_jobs
);
4428 printf(" Failed: %u units\n", mi
.n_failed_units
);
4430 printf(" Since: %s; %s\n",
4431 format_timestamp(since2
, sizeof(since2
), mi
.timestamp
),
4432 format_timestamp_relative(since1
, sizeof(since1
), mi
.timestamp
));
4434 printf(" CGroup: %s\n", mi
.control_group
?: "/");
4435 if (arg_transport
== BUS_TRANSPORT_LOCAL
|| arg_transport
== BUS_TRANSPORT_MACHINE
) {
4436 static const char prefix
[] = " ";
4440 if (c
> sizeof(prefix
) - 1)
4441 c
-= sizeof(prefix
) - 1;
4445 show_cgroup(SYSTEMD_CGROUP_CONTROLLER
, strempty(mi
.control_group
), prefix
, c
, false, get_output_flags());
4449 free(mi
.control_group
);
4454 static int show(sd_bus
*bus
, char **args
) {
4455 bool show_properties
, show_status
, new_line
= false;
4456 bool ellipsized
= false;
4462 show_properties
= streq(args
[0], "show");
4463 show_status
= streq(args
[0], "status");
4465 if (show_properties
)
4466 pager_open_if_enabled();
4469 /* Increase max number of open files to 16K if we can, we
4470 * might needs this when browsing journal files, which might
4471 * be split up into many files. */
4472 setrlimit_closest(RLIMIT_NOFILE
, &RLIMIT_MAKE_CONST(16384));
4474 /* If no argument is specified inspect the manager itself */
4476 if (show_properties
&& strv_length(args
) <= 1)
4477 return show_one(args
[0], bus
, "/org/freedesktop/systemd1", show_properties
, &new_line
, &ellipsized
);
4479 if (show_status
&& strv_length(args
) <= 1) {
4481 pager_open_if_enabled();
4482 show_system_status(bus
);
4486 ret
= show_all(args
[0], bus
, false, &new_line
, &ellipsized
);
4488 _cleanup_free_
char **patterns
= NULL
;
4491 STRV_FOREACH(name
, args
+ 1) {
4492 _cleanup_free_
char *unit
= NULL
;
4495 if (safe_atou32(*name
, &id
) < 0) {
4496 if (strv_push(&patterns
, *name
) < 0)
4500 } else if (show_properties
) {
4501 /* Interpret as job id */
4502 if (asprintf(&unit
, "/org/freedesktop/systemd1/job/%u", id
) < 0)
4506 /* Interpret as PID */
4507 r
= get_unit_dbus_path_by_pid(bus
, id
, &unit
);
4514 r
= show_one(args
[0], bus
, unit
, show_properties
,
4515 &new_line
, &ellipsized
);
4518 else if (r
> 0 && ret
== 0)
4522 if (!strv_isempty(patterns
)) {
4523 _cleanup_strv_free_
char **names
= NULL
;
4525 r
= expand_names(bus
, patterns
, NULL
, &names
);
4527 log_error_errno(r
, "Failed to expand names: %m");
4529 STRV_FOREACH(name
, names
) {
4530 _cleanup_free_
char *unit
;
4532 unit
= unit_dbus_path_from_name(*name
);
4536 r
= show_one(args
[0], bus
, unit
, show_properties
,
4537 &new_line
, &ellipsized
);
4540 else if (r
> 0 && ret
== 0)
4546 if (ellipsized
&& !arg_quiet
)
4547 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4552 static int init_home_and_lookup_paths(char **user_home
, char **user_runtime
, LookupPaths
*lp
) {
4556 assert(user_runtime
);
4559 if (arg_scope
== UNIT_FILE_USER
) {
4560 r
= user_config_home(user_home
);
4562 return log_error_errno(r
, "Failed to query XDG_CONFIG_HOME: %m");
4564 return log_error_errno(ENOTDIR
, "Cannot find units: $XDG_CONFIG_HOME and $HOME are not set.");
4566 r
= user_runtime_dir(user_runtime
);
4568 return log_error_errno(r
, "Failed to query XDG_CONFIG_HOME: %m");
4570 return log_error_errno(ENOTDIR
, "Cannot find units: $XDG_RUNTIME_DIR is not set.");
4573 r
= lookup_paths_init_from_scope(lp
, arg_scope
, arg_root
);
4575 return log_error_errno(r
, "Failed to query unit lookup paths: %m");
4580 static int cat_file(const char *filename
, bool newline
) {
4581 _cleanup_close_
int fd
;
4583 fd
= open(filename
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
4587 printf("%s%s# %s%s\n",
4588 newline
? "\n" : "",
4589 ansi_highlight_blue(),
4591 ansi_highlight_off());
4594 return copy_bytes(fd
, STDOUT_FILENO
, (off_t
) -1, false);
4597 static int cat(sd_bus
*bus
, char **args
) {
4598 _cleanup_free_
char *user_home
= NULL
;
4599 _cleanup_free_
char *user_runtime
= NULL
;
4600 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
4601 _cleanup_strv_free_
char **names
= NULL
;
4603 bool first
= true, avoid_bus_cache
;
4608 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
4609 log_error("Cannot remotely cat units");
4613 r
= init_home_and_lookup_paths(&user_home
, &user_runtime
, &lp
);
4617 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
4619 return log_error_errno(r
, "Failed to expand names: %m");
4621 avoid_bus_cache
= !bus
|| avoid_bus();
4623 pager_open_if_enabled();
4625 STRV_FOREACH(name
, names
) {
4626 _cleanup_free_
char *fragment_path
= NULL
;
4627 _cleanup_strv_free_
char **dropin_paths
= NULL
;
4630 r
= unit_find_paths(bus
, *name
, avoid_bus_cache
, &lp
, &fragment_path
, &dropin_paths
);
4641 if (fragment_path
) {
4642 r
= cat_file(fragment_path
, false);
4644 return log_warning_errno(r
, "Failed to cat %s: %m", fragment_path
);
4647 STRV_FOREACH(path
, dropin_paths
) {
4648 r
= cat_file(*path
, path
== dropin_paths
);
4650 return log_warning_errno(r
, "Failed to cat %s: %m", *path
);
4657 static int set_property(sd_bus
*bus
, char **args
) {
4658 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
4659 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4660 _cleanup_free_
char *n
= NULL
;
4664 polkit_agent_open_if_enabled();
4666 r
= sd_bus_message_new_method_call(
4669 "org.freedesktop.systemd1",
4670 "/org/freedesktop/systemd1",
4671 "org.freedesktop.systemd1.Manager",
4672 "SetUnitProperties");
4674 return bus_log_create_error(r
);
4676 n
= unit_name_mangle(args
[1], MANGLE_NOGLOB
);
4680 r
= sd_bus_message_append(m
, "sb", n
, arg_runtime
);
4682 return bus_log_create_error(r
);
4684 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, "(sv)");
4686 return bus_log_create_error(r
);
4688 STRV_FOREACH(i
, args
+ 2) {
4689 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_STRUCT
, "sv");
4691 return bus_log_create_error(r
);
4693 r
= bus_append_unit_property_assignment(m
, *i
);
4697 r
= sd_bus_message_close_container(m
);
4699 return bus_log_create_error(r
);
4702 r
= sd_bus_message_close_container(m
);
4704 return bus_log_create_error(r
);
4706 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
4708 log_error("Failed to set unit properties on %s: %s", n
, bus_error_message(&error
, r
));
4715 static int snapshot(sd_bus
*bus
, char **args
) {
4716 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4717 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4718 _cleanup_free_
char *n
= NULL
, *id
= NULL
;
4722 polkit_agent_open_if_enabled();
4724 if (strv_length(args
) > 1)
4725 n
= unit_name_mangle_with_suffix(args
[1], MANGLE_NOGLOB
, ".snapshot");
4731 r
= sd_bus_call_method(
4733 "org.freedesktop.systemd1",
4734 "/org/freedesktop/systemd1",
4735 "org.freedesktop.systemd1.Manager",
4741 log_error("Failed to create snapshot: %s", bus_error_message(&error
, r
));
4745 r
= sd_bus_message_read(reply
, "o", &path
);
4747 return bus_log_parse_error(r
);
4749 r
= sd_bus_get_property_string(
4751 "org.freedesktop.systemd1",
4753 "org.freedesktop.systemd1.Unit",
4758 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error
, r
));
4768 static int delete_snapshot(sd_bus
*bus
, char **args
) {
4769 _cleanup_strv_free_
char **names
= NULL
;
4775 polkit_agent_open_if_enabled();
4777 r
= expand_names(bus
, args
+ 1, ".snapshot", &names
);
4779 log_error_errno(r
, "Failed to expand names: %m");
4781 STRV_FOREACH(name
, names
) {
4782 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4785 q
= sd_bus_call_method(
4787 "org.freedesktop.systemd1",
4788 "/org/freedesktop/systemd1",
4789 "org.freedesktop.systemd1.Manager",
4795 log_error("Failed to remove snapshot %s: %s", *name
, bus_error_message(&error
, q
));
4804 static int daemon_reload(sd_bus
*bus
, char **args
) {
4805 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4809 polkit_agent_open_if_enabled();
4811 if (arg_action
== ACTION_RELOAD
)
4813 else if (arg_action
== ACTION_REEXEC
)
4814 method
= "Reexecute";
4816 assert(arg_action
== ACTION_SYSTEMCTL
);
4819 streq(args
[0], "clear-jobs") ||
4820 streq(args
[0], "cancel") ? "ClearJobs" :
4821 streq(args
[0], "daemon-reexec") ? "Reexecute" :
4822 streq(args
[0], "reset-failed") ? "ResetFailed" :
4823 streq(args
[0], "halt") ? "Halt" :
4824 streq(args
[0], "poweroff") ? "PowerOff" :
4825 streq(args
[0], "reboot") ? "Reboot" :
4826 streq(args
[0], "kexec") ? "KExec" :
4827 streq(args
[0], "exit") ? "Exit" :
4828 /* "daemon-reload" */ "Reload";
4831 r
= sd_bus_call_method(
4833 "org.freedesktop.systemd1",
4834 "/org/freedesktop/systemd1",
4835 "org.freedesktop.systemd1.Manager",
4840 if (r
== -ENOENT
&& arg_action
!= ACTION_SYSTEMCTL
)
4841 /* There's always a fallback possible for
4842 * legacy actions. */
4844 else if ((r
== -ETIMEDOUT
|| r
== -ECONNRESET
) && streq(method
, "Reexecute"))
4845 /* On reexecution, we expect a disconnect, not a
4849 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
4851 return r
< 0 ? r
: 0;
4854 static int reset_failed(sd_bus
*bus
, char **args
) {
4855 _cleanup_strv_free_
char **names
= NULL
;
4859 if (strv_length(args
) <= 1)
4860 return daemon_reload(bus
, args
);
4862 polkit_agent_open_if_enabled();
4864 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
4866 log_error_errno(r
, "Failed to expand names: %m");
4868 STRV_FOREACH(name
, names
) {
4869 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4871 q
= sd_bus_call_method(
4873 "org.freedesktop.systemd1",
4874 "/org/freedesktop/systemd1",
4875 "org.freedesktop.systemd1.Manager",
4881 log_error("Failed to reset failed state of unit %s: %s", *name
, bus_error_message(&error
, q
));
4890 static int show_environment(sd_bus
*bus
, char **args
) {
4891 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4892 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4896 pager_open_if_enabled();
4898 r
= sd_bus_get_property(
4900 "org.freedesktop.systemd1",
4901 "/org/freedesktop/systemd1",
4902 "org.freedesktop.systemd1.Manager",
4908 log_error("Failed to get environment: %s", bus_error_message(&error
, r
));
4912 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
4914 return bus_log_parse_error(r
);
4916 while ((r
= sd_bus_message_read_basic(reply
, SD_BUS_TYPE_STRING
, &text
)) > 0)
4919 return bus_log_parse_error(r
);
4921 r
= sd_bus_message_exit_container(reply
);
4923 return bus_log_parse_error(r
);
4928 static int switch_root(sd_bus
*bus
, char **args
) {
4929 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4930 _cleanup_free_
char *cmdline_init
= NULL
;
4931 const char *root
, *init
;
4935 l
= strv_length(args
);
4936 if (l
< 2 || l
> 3) {
4937 log_error("Wrong number of arguments.");
4946 r
= parse_env_file("/proc/cmdline", WHITESPACE
,
4947 "init", &cmdline_init
,
4950 log_debug_errno(r
, "Failed to parse /proc/cmdline: %m");
4952 init
= cmdline_init
;
4959 const char *root_systemd_path
= NULL
, *root_init_path
= NULL
;
4961 root_systemd_path
= strjoina(root
, "/" SYSTEMD_BINARY_PATH
);
4962 root_init_path
= strjoina(root
, "/", init
);
4964 /* If the passed init is actually the same as the
4965 * systemd binary, then let's suppress it. */
4966 if (files_same(root_init_path
, root_systemd_path
) > 0)
4970 log_debug("Switching root - root: %s; init: %s", root
, strna(init
));
4972 r
= sd_bus_call_method(
4974 "org.freedesktop.systemd1",
4975 "/org/freedesktop/systemd1",
4976 "org.freedesktop.systemd1.Manager",
4982 log_error("Failed to switch root: %s", bus_error_message(&error
, r
));
4989 static int set_environment(sd_bus
*bus
, char **args
) {
4990 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4991 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
4998 polkit_agent_open_if_enabled();
5000 method
= streq(args
[0], "set-environment")
5002 : "UnsetEnvironment";
5004 r
= sd_bus_message_new_method_call(
5007 "org.freedesktop.systemd1",
5008 "/org/freedesktop/systemd1",
5009 "org.freedesktop.systemd1.Manager",
5012 return bus_log_create_error(r
);
5014 r
= sd_bus_message_append_strv(m
, args
+ 1);
5016 return bus_log_create_error(r
);
5018 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5020 log_error("Failed to set environment: %s", bus_error_message(&error
, r
));
5027 static int import_environment(sd_bus
*bus
, char **args
) {
5028 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5029 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
5035 polkit_agent_open_if_enabled();
5037 r
= sd_bus_message_new_method_call(
5040 "org.freedesktop.systemd1",
5041 "/org/freedesktop/systemd1",
5042 "org.freedesktop.systemd1.Manager",
5045 return bus_log_create_error(r
);
5047 if (strv_isempty(args
+ 1))
5048 r
= sd_bus_message_append_strv(m
, environ
);
5052 r
= sd_bus_message_open_container(m
, 'a', "s");
5054 return bus_log_create_error(r
);
5056 STRV_FOREACH(a
, args
+ 1) {
5058 if (!env_name_is_valid(*a
)) {
5059 log_error("Not a valid environment variable name: %s", *a
);
5063 STRV_FOREACH(b
, environ
) {
5066 eq
= startswith(*b
, *a
);
5067 if (eq
&& *eq
== '=') {
5069 r
= sd_bus_message_append(m
, "s", *b
);
5071 return bus_log_create_error(r
);
5078 r
= sd_bus_message_close_container(m
);
5081 return bus_log_create_error(r
);
5083 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5085 log_error("Failed to import environment: %s", bus_error_message(&error
, r
));
5092 static int enable_sysv_units(const char *verb
, char **args
) {
5095 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
5097 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
5099 if (arg_scope
!= UNIT_FILE_SYSTEM
)
5102 if (!streq(verb
, "enable") &&
5103 !streq(verb
, "disable") &&
5104 !streq(verb
, "is-enabled"))
5107 /* Processes all SysV units, and reshuffles the array so that
5108 * afterwards only the native units remain */
5110 r
= lookup_paths_init(&paths
, SYSTEMD_SYSTEM
, false, arg_root
, NULL
, NULL
, NULL
);
5117 _cleanup_free_
char *p
= NULL
, *q
= NULL
, *l
= NULL
;
5118 bool found_native
= false, found_sysv
;
5120 const char *argv
[6] = { "/sbin/chkconfig", NULL
, NULL
, NULL
, NULL
};
5128 if (!endswith(name
, ".service"))
5131 if (path_is_absolute(name
))
5134 STRV_FOREACH(k
, paths
.unit_path
) {
5135 _cleanup_free_
char *path
= NULL
;
5137 path
= path_join(arg_root
, *k
, name
);
5141 found_native
= access(path
, F_OK
) >= 0;
5149 p
= path_join(arg_root
, SYSTEM_SYSVINIT_PATH
, name
);
5153 p
[strlen(p
) - strlen(".service")] = 0;
5154 found_sysv
= access(p
, F_OK
) >= 0;
5158 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name
);
5160 if (!isempty(arg_root
))
5161 argv
[c
++] = q
= strappend("--root=", arg_root
);
5163 argv
[c
++] = basename(p
);
5165 streq(verb
, "enable") ? "on" :
5166 streq(verb
, "disable") ? "off" : "--level=5";
5169 l
= strv_join((char**)argv
, " ");
5173 log_info("Executing %s", l
);
5177 return log_error_errno(errno
, "Failed to fork: %m");
5178 else if (pid
== 0) {
5181 execv(argv
[0], (char**) argv
);
5182 _exit(EXIT_FAILURE
);
5185 j
= wait_for_terminate(pid
, &status
);
5187 log_error_errno(r
, "Failed to wait for child: %m");
5191 if (status
.si_code
== CLD_EXITED
) {
5192 if (streq(verb
, "is-enabled")) {
5193 if (status
.si_status
== 0) {
5202 } else if (status
.si_status
!= 0)
5207 /* Remove this entry, so that we don't try enabling it as native unit */
5210 assert(args
[f
] == name
);
5211 strv_remove(args
, name
);
5218 static int mangle_names(char **original_names
, char ***mangled_names
) {
5219 char **i
, **l
, **name
;
5221 l
= new(char*, strv_length(original_names
) + 1);
5226 STRV_FOREACH(name
, original_names
) {
5228 /* When enabling units qualified path names are OK,
5229 * too, hence allow them explicitly. */
5234 *i
= unit_name_mangle(*name
, MANGLE_NOGLOB
);
5250 static int enable_unit(sd_bus
*bus
, char **args
) {
5251 _cleanup_strv_free_
char **names
= NULL
;
5252 const char *verb
= args
[0];
5253 UnitFileChange
*changes
= NULL
;
5254 unsigned n_changes
= 0;
5255 int carries_install_info
= -1;
5261 r
= mangle_names(args
+1, &names
);
5265 r
= enable_sysv_units(verb
, names
);
5269 /* If the operation was fully executed by the SysV compat,
5270 * let's finish early */
5271 if (strv_isempty(names
))
5274 if (!bus
|| avoid_bus()) {
5275 if (streq(verb
, "enable")) {
5276 r
= unit_file_enable(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5277 carries_install_info
= r
;
5278 } else if (streq(verb
, "disable"))
5279 r
= unit_file_disable(arg_scope
, arg_runtime
, arg_root
, names
, &changes
, &n_changes
);
5280 else if (streq(verb
, "reenable")) {
5281 r
= unit_file_reenable(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5282 carries_install_info
= r
;
5283 } else if (streq(verb
, "link"))
5284 r
= unit_file_link(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5285 else if (streq(verb
, "preset")) {
5286 r
= unit_file_preset(arg_scope
, arg_runtime
, arg_root
, names
, arg_preset_mode
, arg_force
, &changes
, &n_changes
);
5287 carries_install_info
= r
;
5288 } else if (streq(verb
, "mask"))
5289 r
= unit_file_mask(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5290 else if (streq(verb
, "unmask"))
5291 r
= unit_file_unmask(arg_scope
, arg_runtime
, arg_root
, names
, &changes
, &n_changes
);
5293 assert_not_reached("Unknown verb");
5296 log_error_errno(r
, "Operation failed: %m");
5301 dump_unit_file_changes(changes
, n_changes
);
5305 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
, *m
= NULL
;
5306 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5307 int expect_carries_install_info
= false;
5308 bool send_force
= true, send_preset_mode
= false;
5311 polkit_agent_open_if_enabled();
5313 if (streq(verb
, "enable")) {
5314 method
= "EnableUnitFiles";
5315 expect_carries_install_info
= true;
5316 } else if (streq(verb
, "disable")) {
5317 method
= "DisableUnitFiles";
5319 } else if (streq(verb
, "reenable")) {
5320 method
= "ReenableUnitFiles";
5321 expect_carries_install_info
= true;
5322 } else if (streq(verb
, "link"))
5323 method
= "LinkUnitFiles";
5324 else if (streq(verb
, "preset")) {
5326 if (arg_preset_mode
!= UNIT_FILE_PRESET_FULL
) {
5327 method
= "PresetUnitFilesWithMode";
5328 send_preset_mode
= true;
5330 method
= "PresetUnitFiles";
5332 expect_carries_install_info
= true;
5333 } else if (streq(verb
, "mask"))
5334 method
= "MaskUnitFiles";
5335 else if (streq(verb
, "unmask")) {
5336 method
= "UnmaskUnitFiles";
5339 assert_not_reached("Unknown verb");
5341 r
= sd_bus_message_new_method_call(
5344 "org.freedesktop.systemd1",
5345 "/org/freedesktop/systemd1",
5346 "org.freedesktop.systemd1.Manager",
5349 return bus_log_create_error(r
);
5351 r
= sd_bus_message_append_strv(m
, names
);
5353 return bus_log_create_error(r
);
5355 if (send_preset_mode
) {
5356 r
= sd_bus_message_append(m
, "s", unit_file_preset_mode_to_string(arg_preset_mode
));
5358 return bus_log_create_error(r
);
5361 r
= sd_bus_message_append(m
, "b", arg_runtime
);
5363 return bus_log_create_error(r
);
5366 r
= sd_bus_message_append(m
, "b", arg_force
);
5368 return bus_log_create_error(r
);
5371 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
5373 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
5377 if (expect_carries_install_info
) {
5378 r
= sd_bus_message_read(reply
, "b", &carries_install_info
);
5380 return bus_log_parse_error(r
);
5383 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
);
5387 /* Try to reload if enabled */
5389 r
= daemon_reload(bus
, args
);
5394 if (carries_install_info
== 0)
5395 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5396 "using systemctl.\n"
5397 "Possible reasons for having this kind of units are:\n"
5398 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5399 " .wants/ or .requires/ directory.\n"
5400 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5401 " a requirement dependency on it.\n"
5402 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5403 " D-Bus, udev, scripted systemctl call, ...).\n");
5406 unit_file_changes_free(changes
, n_changes
);
5411 static int add_dependency(sd_bus
*bus
, char **args
) {
5412 _cleanup_strv_free_
char **names
= NULL
;
5413 _cleanup_free_
char *target
= NULL
;
5414 const char *verb
= args
[0];
5421 target
= unit_name_mangle_with_suffix(args
[1], MANGLE_NOGLOB
, ".target");
5425 r
= mangle_names(args
+2, &names
);
5429 if (streq(verb
, "add-wants"))
5431 else if (streq(verb
, "add-requires"))
5432 dep
= UNIT_REQUIRES
;
5434 assert_not_reached("Unknown verb");
5436 if (!bus
|| avoid_bus()) {
5437 UnitFileChange
*changes
= NULL
;
5438 unsigned n_changes
= 0;
5440 r
= unit_file_add_dependency(arg_scope
, arg_runtime
, arg_root
, names
, target
, dep
, arg_force
, &changes
, &n_changes
);
5443 return log_error_errno(r
, "Can't add dependency: %m");
5446 dump_unit_file_changes(changes
, n_changes
);
5448 unit_file_changes_free(changes
, n_changes
);
5451 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
, *m
= NULL
;
5452 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5454 polkit_agent_open_if_enabled();
5456 r
= sd_bus_message_new_method_call(
5459 "org.freedesktop.systemd1",
5460 "/org/freedesktop/systemd1",
5461 "org.freedesktop.systemd1.Manager",
5462 "AddDependencyUnitFiles");
5464 return bus_log_create_error(r
);
5466 r
= sd_bus_message_append_strv(m
, names
);
5468 return bus_log_create_error(r
);
5470 r
= sd_bus_message_append(m
, "ssbb", target
, unit_dependency_to_string(dep
), arg_runtime
, arg_force
);
5472 return bus_log_create_error(r
);
5474 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
5476 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
5480 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
);
5485 r
= daemon_reload(bus
, args
);
5493 static int preset_all(sd_bus
*bus
, char **args
) {
5494 UnitFileChange
*changes
= NULL
;
5495 unsigned n_changes
= 0;
5498 if (!bus
|| avoid_bus()) {
5500 r
= unit_file_preset_all(arg_scope
, arg_runtime
, arg_root
, arg_preset_mode
, arg_force
, &changes
, &n_changes
);
5502 log_error_errno(r
, "Operation failed: %m");
5507 dump_unit_file_changes(changes
, n_changes
);
5512 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5513 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
5515 polkit_agent_open_if_enabled();
5517 r
= sd_bus_call_method(
5519 "org.freedesktop.systemd1",
5520 "/org/freedesktop/systemd1",
5521 "org.freedesktop.systemd1.Manager",
5522 "PresetAllUnitFiles",
5526 unit_file_preset_mode_to_string(arg_preset_mode
),
5530 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
5534 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
);
5539 r
= daemon_reload(bus
, args
);
5545 unit_file_changes_free(changes
, n_changes
);
5550 static int unit_is_enabled(sd_bus
*bus
, char **args
) {
5552 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5553 _cleanup_strv_free_
char **names
= NULL
;
5558 r
= mangle_names(args
+1, &names
);
5562 r
= enable_sysv_units(args
[0], names
);
5568 if (!bus
|| avoid_bus()) {
5570 STRV_FOREACH(name
, names
) {
5571 UnitFileState state
;
5573 state
= unit_file_get_state(arg_scope
, arg_root
, *name
);
5575 return log_error_errno(state
, "Failed to get unit file state for %s: %m", *name
);
5577 if (state
== UNIT_FILE_ENABLED
||
5578 state
== UNIT_FILE_ENABLED_RUNTIME
||
5579 state
== UNIT_FILE_STATIC
||
5580 state
== UNIT_FILE_INDIRECT
)
5584 puts(unit_file_state_to_string(state
));
5588 STRV_FOREACH(name
, names
) {
5589 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
5592 r
= sd_bus_call_method(
5594 "org.freedesktop.systemd1",
5595 "/org/freedesktop/systemd1",
5596 "org.freedesktop.systemd1.Manager",
5602 log_error("Failed to get unit file state for %s: %s", *name
, bus_error_message(&error
, r
));
5606 r
= sd_bus_message_read(reply
, "s", &s
);
5608 return bus_log_parse_error(r
);
5610 if (STR_IN_SET(s
, "enabled", "enabled-runtime", "static", "indirect"))
5621 static int is_system_running(sd_bus
*bus
, char **args
) {
5622 _cleanup_free_
char *state
= NULL
;
5625 r
= sd_bus_get_property_string(
5627 "org.freedesktop.systemd1",
5628 "/org/freedesktop/systemd1",
5629 "org.freedesktop.systemd1.Manager",
5642 return streq(state
, "running") ? EXIT_SUCCESS
: EXIT_FAILURE
;
5645 static int create_edit_temp_file(const char *new_path
, const char *original_path
, char **ret_tmp_fn
) {
5650 assert(original_path
);
5653 r
= tempfn_random(new_path
, &t
);
5655 return log_error_errno(r
, "Failed to determine temporary filename for \"%s\": %m", new_path
);
5657 r
= mkdir_parents(new_path
, 0755);
5659 log_error_errno(r
, "Failed to create directories for \"%s\": %m", new_path
);
5664 r
= copy_file(original_path
, t
, 0, 0644, 0);
5668 log_error_errno(r
, "Failed to create temporary file \"%s\": %m", t
);
5673 log_error_errno(r
, "Failed to copy \"%s\" to \"%s\": %m", original_path
, t
);
5683 static int get_file_to_edit(const char *name
, const char *user_home
, const char *user_runtime
, char **ret_path
) {
5684 _cleanup_free_
char *path
= NULL
, *path2
= NULL
, *run
= NULL
;
5686 switch (arg_scope
) {
5687 case UNIT_FILE_SYSTEM
:
5688 path
= path_join(arg_root
, SYSTEM_CONFIG_UNIT_PATH
, name
);
5690 run
= path_join(arg_root
, "/run/systemd/system/", name
);
5692 case UNIT_FILE_GLOBAL
:
5693 path
= path_join(arg_root
, USER_CONFIG_UNIT_PATH
, name
);
5695 run
= path_join(arg_root
, "/run/systemd/user/", name
);
5697 case UNIT_FILE_USER
:
5699 assert(user_runtime
);
5701 path
= path_join(arg_root
, user_home
, name
);
5703 path2
= path_join(arg_root
, USER_CONFIG_UNIT_PATH
, name
);
5706 run
= path_join(arg_root
, user_runtime
, name
);
5710 assert_not_reached("Invalid scope");
5712 if (!path
|| (arg_runtime
&& !run
))
5716 if (access(path
, F_OK
) >= 0)
5717 return log_error_errno(EEXIST
, "Refusing to create \"%s\" because it would be overriden by \"%s\" anyway.",
5719 if (path2
&& access(path2
, F_OK
) >= 0)
5720 return log_error_errno(EEXIST
, "Refusing to create \"%s\" because it would be overriden by \"%s\" anyway.",
5732 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
) {
5733 char *tmp_new_path
, *ending
;
5738 assert(ret_new_path
);
5739 assert(ret_tmp_path
);
5741 ending
= strjoina(unit_name
, ".d/override.conf");
5742 r
= get_file_to_edit(ending
, user_home
, user_runtime
, &tmp_new_path
);
5746 r
= create_edit_temp_file(tmp_new_path
, tmp_new_path
, &tmp_tmp_path
);
5752 *ret_new_path
= tmp_new_path
;
5753 *ret_tmp_path
= tmp_tmp_path
;
5758 static int unit_file_create_copy(
5759 const char *unit_name
,
5760 const char *fragment_path
,
5761 const char *user_home
,
5762 const char *user_runtime
,
5763 char **ret_new_path
,
5764 char **ret_tmp_path
) {
5770 assert(fragment_path
);
5772 assert(ret_new_path
);
5773 assert(ret_tmp_path
);
5775 r
= get_file_to_edit(unit_name
, user_home
, user_runtime
, &tmp_new_path
);
5779 if (!path_equal(fragment_path
, tmp_new_path
) && access(tmp_new_path
, F_OK
) == 0) {
5782 r
= ask_char(&response
, "yn", "\"%s\" already exists. Overwrite with \"%s\"? [(y)es, (n)o] ", tmp_new_path
, fragment_path
);
5787 if (response
!= 'y') {
5788 log_warning("%s ignored", unit_name
);
5794 r
= create_edit_temp_file(tmp_new_path
, fragment_path
, &tmp_tmp_path
);
5796 log_error_errno(r
, "Failed to create temporary file for \"%s\": %m", tmp_new_path
);
5801 *ret_new_path
= tmp_new_path
;
5802 *ret_tmp_path
= tmp_tmp_path
;
5807 static int run_editor(char **paths
) {
5815 log_error_errno(errno
, "Failed to fork: %m");
5822 char **tmp_path
, **original_path
, *p
;
5826 argc
= strv_length(paths
)/2 + 1;
5827 args
= newa(const char*, argc
+ 1);
5830 STRV_FOREACH_PAIR(original_path
, tmp_path
, paths
) {
5831 args
[i
] = *tmp_path
;
5836 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
5837 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
5838 * we try to execute well known editors
5840 editor
= getenv("SYSTEMD_EDITOR");
5842 editor
= getenv("EDITOR");
5844 editor
= getenv("VISUAL");
5846 if (!isempty(editor
)) {
5848 execvp(editor
, (char* const*) args
);
5851 FOREACH_STRING(p
, "nano", "vim", "vi") {
5853 execvp(p
, (char* const*) args
);
5854 /* We do not fail if the editor doesn't exist
5855 * because we want to try each one of them before
5858 if (errno
!= ENOENT
) {
5859 log_error("Failed to execute %s: %m", editor
);
5860 _exit(EXIT_FAILURE
);
5864 log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR, $EDITOR or $VISUAL.");
5865 _exit(EXIT_FAILURE
);
5868 r
= wait_for_terminate_and_warn("editor", pid
, true);
5870 return log_error_errno(r
, "Failed to wait for child: %m");
5875 static int find_paths_to_edit(sd_bus
*bus
, char **names
, char ***paths
) {
5876 _cleanup_free_
char *user_home
= NULL
;
5877 _cleanup_free_
char *user_runtime
= NULL
;
5878 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
5879 bool avoid_bus_cache
;
5886 r
= init_home_and_lookup_paths(&user_home
, &user_runtime
, &lp
);
5890 avoid_bus_cache
= !bus
|| avoid_bus();
5892 STRV_FOREACH(name
, names
) {
5893 _cleanup_free_
char *path
= NULL
;
5894 char *new_path
, *tmp_path
;
5896 r
= unit_find_paths(bus
, *name
, avoid_bus_cache
, &lp
, &path
, NULL
);
5902 // FIXME: support units with path==NULL (no FragmentPath)
5903 log_error("No fragment exists for %s.", *name
);
5908 r
= unit_file_create_copy(*name
, path
, user_home
, user_runtime
, &new_path
, &tmp_path
);
5910 r
= unit_file_create_dropin(*name
, user_home
, user_runtime
, &new_path
, &tmp_path
);
5914 r
= strv_push_pair(paths
, new_path
, tmp_path
);
5922 static int edit(sd_bus
*bus
, char **args
) {
5923 _cleanup_strv_free_
char **names
= NULL
;
5924 _cleanup_strv_free_
char **paths
= NULL
;
5925 char **original
, **tmp
;
5931 log_error("Cannot edit units if not on a tty");
5935 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
5936 log_error("Cannot remotely edit units");
5940 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
5942 return log_error_errno(r
, "Failed to expand names: %m");
5944 r
= find_paths_to_edit(bus
, names
, &paths
);
5948 if (strv_isempty(paths
))
5951 r
= run_editor(paths
);
5955 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
5956 /* If the temporary file is empty we ignore it.
5957 * It's useful if the user wants to cancel its modification
5959 if (null_or_empty_path(*tmp
)) {
5960 log_warning("Editing \"%s\" canceled: temporary file is empty", *original
);
5963 r
= rename(*tmp
, *original
);
5965 r
= log_error_errno(errno
, "Failed to rename \"%s\" to \"%s\": %m", *tmp
, *original
);
5970 if (!arg_no_reload
&& bus
&& !avoid_bus())
5971 r
= daemon_reload(bus
, args
);
5974 STRV_FOREACH_PAIR(original
, tmp
, paths
)
5975 unlink_noerrno(*tmp
);
5980 static void systemctl_help(void) {
5982 pager_open_if_enabled();
5984 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
5985 "Query or send control commands to the systemd manager.\n\n"
5986 " -h --help Show this help\n"
5987 " --version Show package version\n"
5988 " --system Connect to system manager\n"
5989 " --user Connect to user service manager\n"
5990 " -H --host=[USER@]HOST\n"
5991 " Operate on remote host\n"
5992 " -M --machine=CONTAINER\n"
5993 " Operate on local container\n"
5994 " -t --type=TYPE List units of a particular type\n"
5995 " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n"
5996 " -p --property=NAME Show only properties by this name\n"
5997 " -a --all Show all loaded units/properties, including dead/empty\n"
5998 " ones. To list all units installed on the system, use\n"
5999 " the 'list-unit-files' command instead.\n"
6000 " -l --full Don't ellipsize unit names on output\n"
6001 " -r --recursive Show unit list of host and local containers\n"
6002 " --reverse Show reverse dependencies with 'list-dependencies'\n"
6003 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
6004 " queueing a new job\n"
6005 " --show-types When showing sockets, explicitly show their type\n"
6006 " -i --ignore-inhibitors\n"
6007 " When shutting down or sleeping, ignore inhibitors\n"
6008 " --kill-who=WHO Who to send signal to\n"
6009 " -s --signal=SIGNAL Which signal to send\n"
6010 " -q --quiet Suppress output\n"
6011 " --no-block Do not wait until operation finished\n"
6012 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6013 " --no-reload Don't reload daemon after en-/dis-abling unit files\n"
6014 " --no-legend Do not print a legend (column headers and hints)\n"
6015 " --no-pager Do not pipe output into a pager\n"
6016 " --no-ask-password\n"
6017 " Do not ask for system passwords\n"
6018 " --global Enable/disable unit files globally\n"
6019 " --runtime Enable unit files only temporarily until next reboot\n"
6020 " -f --force When enabling unit files, override existing symlinks\n"
6021 " When shutting down, execute action immediately\n"
6022 " --preset-mode= Apply only enable, only disable, or all presets\n"
6023 " --root=PATH Enable unit files in the specified root directory\n"
6024 " -n --lines=INTEGER Number of journal entries to show\n"
6025 " -o --output=STRING Change journal output mode (short, short-iso,\n"
6026 " short-precise, short-monotonic, verbose,\n"
6027 " export, json, json-pretty, json-sse, cat)\n"
6028 " --firmware-setup Tell the firmware to show the setup menu on next boot\n"
6029 " --plain Print unit dependencies as a list instead of a tree\n\n"
6031 " list-units [PATTERN...] List loaded units\n"
6032 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
6033 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
6034 " start NAME... Start (activate) one or more units\n"
6035 " stop NAME... Stop (deactivate) one or more units\n"
6036 " reload NAME... Reload one or more units\n"
6037 " restart NAME... Start or restart one or more units\n"
6038 " try-restart NAME... Restart one or more units if active\n"
6039 " reload-or-restart NAME... Reload one or more units if possible,\n"
6040 " otherwise start or restart\n"
6041 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
6042 " otherwise restart if active\n"
6043 " isolate NAME Start one unit and stop all others\n"
6044 " kill NAME... Send signal to processes of a unit\n"
6045 " is-active PATTERN... Check whether units are active\n"
6046 " is-failed PATTERN... Check whether units are failed\n"
6047 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
6048 " show [PATTERN...|JOB...] Show properties of one or more\n"
6049 " units/jobs or the manager\n"
6050 " cat PATTERN... Show files and drop-ins of one or more units\n"
6051 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
6052 " help PATTERN...|PID... Show manual for one or more units\n"
6053 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
6055 " list-dependencies [NAME] Recursively show units which are required\n"
6056 " or wanted by this unit or by which this\n"
6057 " unit is required or wanted\n\n"
6058 "Unit File Commands:\n"
6059 " list-unit-files [PATTERN...] List installed unit files\n"
6060 " enable NAME... Enable one or more unit files\n"
6061 " disable NAME... Disable one or more unit files\n"
6062 " reenable NAME... Reenable one or more unit files\n"
6063 " preset NAME... Enable/disable one or more unit files\n"
6064 " based on preset configuration\n"
6065 " preset-all Enable/disable all unit files based on\n"
6066 " preset configuration\n"
6067 " is-enabled NAME... Check whether unit files are enabled\n"
6068 " mask NAME... Mask one or more units\n"
6069 " unmask NAME... Unmask one or more units\n"
6070 " link PATH... Link one or more units files into\n"
6071 " the search path\n"
6072 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
6073 " on specified one or more units\n"
6074 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
6075 " on specified one or more units\n"
6076 " edit NAME... Edit one or more unit files\n"
6077 " get-default Get the name of the default target\n"
6078 " set-default NAME Set the default target\n\n"
6079 "Machine Commands:\n"
6080 " list-machines [PATTERN...] List local containers and host\n\n"
6082 " list-jobs [PATTERN...] List jobs\n"
6083 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
6084 "Snapshot Commands:\n"
6085 " snapshot [NAME] Create a snapshot\n"
6086 " delete NAME... Remove one or more snapshots\n\n"
6087 "Environment Commands:\n"
6088 " show-environment Dump environment\n"
6089 " set-environment NAME=VALUE... Set one or more environment variables\n"
6090 " unset-environment NAME... Unset one or more environment variables\n"
6091 " import-environment [NAME...] Import all or some environment variables\n\n"
6092 "Manager Lifecycle Commands:\n"
6093 " daemon-reload Reload systemd manager configuration\n"
6094 " daemon-reexec Reexecute systemd manager\n\n"
6095 "System Commands:\n"
6096 " is-system-running Check whether system is fully running\n"
6097 " default Enter system default mode\n"
6098 " rescue Enter system rescue mode\n"
6099 " emergency Enter system emergency mode\n"
6100 " halt Shut down and halt the system\n"
6101 " poweroff Shut down and power-off the system\n"
6102 " reboot [ARG] Shut down and reboot the system\n"
6103 " kexec Shut down and reboot the system with kexec\n"
6104 " exit Request user instance exit\n"
6105 " switch-root ROOT [INIT] Change to a different root file system\n"
6106 " suspend Suspend the system\n"
6107 " hibernate Hibernate the system\n"
6108 " hybrid-sleep Hibernate and suspend the system\n",
6109 program_invocation_short_name
);
6112 static void halt_help(void) {
6113 printf("%s [OPTIONS...]%s\n\n"
6114 "%s the system.\n\n"
6115 " --help Show this help\n"
6116 " --halt Halt the machine\n"
6117 " -p --poweroff Switch off the machine\n"
6118 " --reboot Reboot the machine\n"
6119 " -f --force Force immediate halt/power-off/reboot\n"
6120 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
6121 " -d --no-wtmp Don't write wtmp record\n"
6122 " --no-wall Don't send wall message before halt/power-off/reboot\n",
6123 program_invocation_short_name
,
6124 arg_action
== ACTION_REBOOT
? " [ARG]" : "",
6125 arg_action
== ACTION_REBOOT
? "Reboot" :
6126 arg_action
== ACTION_POWEROFF
? "Power off" :
6130 static void shutdown_help(void) {
6131 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
6132 "Shut down the system.\n\n"
6133 " --help Show this help\n"
6134 " -H --halt Halt the machine\n"
6135 " -P --poweroff Power-off the machine\n"
6136 " -r --reboot Reboot the machine\n"
6137 " -h Equivalent to --poweroff, overridden by --halt\n"
6138 " -k Don't halt/power-off/reboot, just send warnings\n"
6139 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6140 " -c Cancel a pending shutdown\n",
6141 program_invocation_short_name
);
6144 static void telinit_help(void) {
6145 printf("%s [OPTIONS...] {COMMAND}\n\n"
6146 "Send control commands to the init daemon.\n\n"
6147 " --help Show this help\n"
6148 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
6150 " 0 Power-off the machine\n"
6151 " 6 Reboot the machine\n"
6152 " 2, 3, 4, 5 Start runlevelX.target unit\n"
6153 " 1, s, S Enter rescue mode\n"
6154 " q, Q Reload init daemon configuration\n"
6155 " u, U Reexecute init daemon\n",
6156 program_invocation_short_name
);
6159 static void runlevel_help(void) {
6160 printf("%s [OPTIONS...]\n\n"
6161 "Prints the previous and current runlevel of the init system.\n\n"
6162 " --help Show this help\n",
6163 program_invocation_short_name
);
6166 static void help_types(void) {
6171 puts("Available unit types:");
6172 for (i
= 0; i
< _UNIT_TYPE_MAX
; i
++) {
6173 t
= unit_type_to_string(i
);
6179 static int systemctl_parse_argv(int argc
, char *argv
[]) {
6188 ARG_IGNORE_DEPENDENCIES
,
6200 ARG_NO_ASK_PASSWORD
,
6211 static const struct option options
[] = {
6212 { "help", no_argument
, NULL
, 'h' },
6213 { "version", no_argument
, NULL
, ARG_VERSION
},
6214 { "type", required_argument
, NULL
, 't' },
6215 { "property", required_argument
, NULL
, 'p' },
6216 { "all", no_argument
, NULL
, 'a' },
6217 { "reverse", no_argument
, NULL
, ARG_REVERSE
},
6218 { "after", no_argument
, NULL
, ARG_AFTER
},
6219 { "before", no_argument
, NULL
, ARG_BEFORE
},
6220 { "show-types", no_argument
, NULL
, ARG_SHOW_TYPES
},
6221 { "failed", no_argument
, NULL
, ARG_FAILED
}, /* compatibility only */
6222 { "full", no_argument
, NULL
, 'l' },
6223 { "job-mode", required_argument
, NULL
, ARG_JOB_MODE
},
6224 { "fail", no_argument
, NULL
, ARG_FAIL
}, /* compatibility only */
6225 { "irreversible", no_argument
, NULL
, ARG_IRREVERSIBLE
}, /* compatibility only */
6226 { "ignore-dependencies", no_argument
, NULL
, ARG_IGNORE_DEPENDENCIES
}, /* compatibility only */
6227 { "ignore-inhibitors", no_argument
, NULL
, 'i' },
6228 { "user", no_argument
, NULL
, ARG_USER
},
6229 { "system", no_argument
, NULL
, ARG_SYSTEM
},
6230 { "global", no_argument
, NULL
, ARG_GLOBAL
},
6231 { "no-block", no_argument
, NULL
, ARG_NO_BLOCK
},
6232 { "no-legend", no_argument
, NULL
, ARG_NO_LEGEND
},
6233 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
6234 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6235 { "quiet", no_argument
, NULL
, 'q' },
6236 { "root", required_argument
, NULL
, ARG_ROOT
},
6237 { "force", no_argument
, NULL
, ARG_FORCE
},
6238 { "no-reload", no_argument
, NULL
, ARG_NO_RELOAD
},
6239 { "kill-who", required_argument
, NULL
, ARG_KILL_WHO
},
6240 { "signal", required_argument
, NULL
, 's' },
6241 { "no-ask-password", no_argument
, NULL
, ARG_NO_ASK_PASSWORD
},
6242 { "host", required_argument
, NULL
, 'H' },
6243 { "machine", required_argument
, NULL
, 'M' },
6244 { "runtime", no_argument
, NULL
, ARG_RUNTIME
},
6245 { "lines", required_argument
, NULL
, 'n' },
6246 { "output", required_argument
, NULL
, 'o' },
6247 { "plain", no_argument
, NULL
, ARG_PLAIN
},
6248 { "state", required_argument
, NULL
, ARG_STATE
},
6249 { "recursive", no_argument
, NULL
, 'r' },
6250 { "preset-mode", required_argument
, NULL
, ARG_PRESET_MODE
},
6251 { "firmware-setup", no_argument
, NULL
, ARG_FIRMWARE_SETUP
},
6260 while ((c
= getopt_long(argc
, argv
, "ht:p:alqfs:H:M:n:o:ir", options
, NULL
)) >= 0)
6269 puts(PACKAGE_STRING
);
6270 puts(SYSTEMD_FEATURES
);
6274 const char *word
, *state
;
6277 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
6278 _cleanup_free_
char *type
;
6280 type
= strndup(word
, size
);
6284 if (streq(type
, "help")) {
6289 if (unit_type_from_string(type
) >= 0) {
6290 if (strv_push(&arg_types
, type
))
6296 /* It's much nicer to use --state= for
6297 * load states, but let's support this
6298 * in --types= too for compatibility
6299 * with old versions */
6300 if (unit_load_state_from_string(optarg
) >= 0) {
6301 if (strv_push(&arg_states
, type
) < 0)
6307 log_error("Unknown unit type or load state '%s'.", type
);
6308 log_info("Use -t help to see a list of allowed values.");
6316 /* Make sure that if the empty property list
6317 was specified, we won't show any properties. */
6318 if (isempty(optarg
) && !arg_properties
) {
6319 arg_properties
= new0(char*, 1);
6320 if (!arg_properties
)
6323 const char *word
, *state
;
6326 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
6329 prop
= strndup(word
, size
);
6333 if (strv_consume(&arg_properties
, prop
) < 0)
6338 /* If the user asked for a particular
6339 * property, show it to him, even if it is
6351 arg_dependency
= DEPENDENCY_REVERSE
;
6355 arg_dependency
= DEPENDENCY_AFTER
;
6359 arg_dependency
= DEPENDENCY_BEFORE
;
6362 case ARG_SHOW_TYPES
:
6363 arg_show_types
= true;
6367 arg_job_mode
= optarg
;
6371 arg_job_mode
= "fail";
6374 case ARG_IRREVERSIBLE
:
6375 arg_job_mode
= "replace-irreversibly";
6378 case ARG_IGNORE_DEPENDENCIES
:
6379 arg_job_mode
= "ignore-dependencies";
6383 arg_scope
= UNIT_FILE_USER
;
6387 arg_scope
= UNIT_FILE_SYSTEM
;
6391 arg_scope
= UNIT_FILE_GLOBAL
;
6395 arg_no_block
= true;
6399 arg_no_legend
= true;
6403 arg_no_pager
= true;
6419 if (strv_extend(&arg_states
, "failed") < 0)
6437 arg_no_reload
= true;
6441 arg_kill_who
= optarg
;
6445 if ((arg_signal
= signal_from_string_try_harder(optarg
)) < 0) {
6446 log_error("Failed to parse signal string %s.", optarg
);
6451 case ARG_NO_ASK_PASSWORD
:
6452 arg_ask_password
= false;
6456 arg_transport
= BUS_TRANSPORT_REMOTE
;
6461 arg_transport
= BUS_TRANSPORT_MACHINE
;
6470 if (safe_atou(optarg
, &arg_lines
) < 0) {
6471 log_error("Failed to parse lines '%s'", optarg
);
6477 arg_output
= output_mode_from_string(optarg
);
6478 if (arg_output
< 0) {
6479 log_error("Unknown output '%s'.", optarg
);
6485 arg_ignore_inhibitors
= true;
6492 case ARG_FIRMWARE_SETUP
:
6493 arg_firmware_setup
= true;
6497 const char *word
, *state
;
6500 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
6503 s
= strndup(word
, size
);
6507 if (strv_consume(&arg_states
, s
) < 0)
6514 if (geteuid() != 0) {
6515 log_error("--recursive requires root privileges.");
6519 arg_recursive
= true;
6522 case ARG_PRESET_MODE
:
6524 arg_preset_mode
= unit_file_preset_mode_from_string(optarg
);
6525 if (arg_preset_mode
< 0) {
6526 log_error("Failed to parse preset mode: %s.", optarg
);
6536 assert_not_reached("Unhandled option");
6539 if (arg_transport
!= BUS_TRANSPORT_LOCAL
&& arg_scope
!= UNIT_FILE_SYSTEM
) {
6540 log_error("Cannot access user instance remotely.");
6547 static int halt_parse_argv(int argc
, char *argv
[]) {
6556 static const struct option options
[] = {
6557 { "help", no_argument
, NULL
, ARG_HELP
},
6558 { "halt", no_argument
, NULL
, ARG_HALT
},
6559 { "poweroff", no_argument
, NULL
, 'p' },
6560 { "reboot", no_argument
, NULL
, ARG_REBOOT
},
6561 { "force", no_argument
, NULL
, 'f' },
6562 { "wtmp-only", no_argument
, NULL
, 'w' },
6563 { "no-wtmp", no_argument
, NULL
, 'd' },
6564 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6573 if (utmp_get_runlevel(&runlevel
, NULL
) >= 0)
6574 if (runlevel
== '0' || runlevel
== '6')
6577 while ((c
= getopt_long(argc
, argv
, "pfwdnih", options
, NULL
)) >= 0)
6585 arg_action
= ACTION_HALT
;
6589 if (arg_action
!= ACTION_REBOOT
)
6590 arg_action
= ACTION_POWEROFF
;
6594 arg_action
= ACTION_REBOOT
;
6616 /* Compatibility nops */
6623 assert_not_reached("Unhandled option");
6626 if (arg_action
== ACTION_REBOOT
&& (argc
== optind
|| argc
== optind
+ 1)) {
6627 r
= update_reboot_param_file(argc
== optind
+ 1 ? argv
[optind
] : NULL
);
6630 } else if (optind
< argc
) {
6631 log_error("Too many arguments.");
6638 static int parse_time_spec(const char *t
, usec_t
*_u
) {
6642 if (streq(t
, "now"))
6644 else if (!strchr(t
, ':')) {
6647 if (safe_atou64(t
, &u
) < 0)
6650 *_u
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
* u
;
6659 hour
= strtol(t
, &e
, 10);
6660 if (errno
> 0 || *e
!= ':' || hour
< 0 || hour
> 23)
6663 minute
= strtol(e
+1, &e
, 10);
6664 if (errno
> 0 || *e
!= 0 || minute
< 0 || minute
> 59)
6667 n
= now(CLOCK_REALTIME
);
6668 s
= (time_t) (n
/ USEC_PER_SEC
);
6670 assert_se(localtime_r(&s
, &tm
));
6672 tm
.tm_hour
= (int) hour
;
6673 tm
.tm_min
= (int) minute
;
6676 assert_se(s
= mktime(&tm
));
6678 *_u
= (usec_t
) s
* USEC_PER_SEC
;
6681 *_u
+= USEC_PER_DAY
;
6687 static int shutdown_parse_argv(int argc
, char *argv
[]) {
6694 static const struct option options
[] = {
6695 { "help", no_argument
, NULL
, ARG_HELP
},
6696 { "halt", no_argument
, NULL
, 'H' },
6697 { "poweroff", no_argument
, NULL
, 'P' },
6698 { "reboot", no_argument
, NULL
, 'r' },
6699 { "kexec", no_argument
, NULL
, 'K' }, /* not documented extension */
6700 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6709 while ((c
= getopt_long(argc
, argv
, "HPrhkKt:afFc", options
, NULL
)) >= 0)
6717 arg_action
= ACTION_HALT
;
6721 arg_action
= ACTION_POWEROFF
;
6726 arg_action
= ACTION_KEXEC
;
6728 arg_action
= ACTION_REBOOT
;
6732 arg_action
= ACTION_KEXEC
;
6736 if (arg_action
!= ACTION_HALT
)
6737 arg_action
= ACTION_POWEROFF
;
6752 /* Compatibility nops */
6756 arg_action
= ACTION_CANCEL_SHUTDOWN
;
6763 assert_not_reached("Unhandled option");
6766 if (argc
> optind
&& arg_action
!= ACTION_CANCEL_SHUTDOWN
) {
6767 r
= parse_time_spec(argv
[optind
], &arg_when
);
6769 log_error("Failed to parse time specification: %s", argv
[optind
]);
6773 arg_when
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
;
6775 if (argc
> optind
&& arg_action
== ACTION_CANCEL_SHUTDOWN
)
6776 /* No time argument for shutdown cancel */
6777 arg_wall
= argv
+ optind
;
6778 else if (argc
> optind
+ 1)
6779 /* We skip the time argument */
6780 arg_wall
= argv
+ optind
+ 1;
6787 static int telinit_parse_argv(int argc
, char *argv
[]) {
6794 static const struct option options
[] = {
6795 { "help", no_argument
, NULL
, ARG_HELP
},
6796 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6800 static const struct {
6804 { '0', ACTION_POWEROFF
},
6805 { '6', ACTION_REBOOT
},
6806 { '1', ACTION_RESCUE
},
6807 { '2', ACTION_RUNLEVEL2
},
6808 { '3', ACTION_RUNLEVEL3
},
6809 { '4', ACTION_RUNLEVEL4
},
6810 { '5', ACTION_RUNLEVEL5
},
6811 { 's', ACTION_RESCUE
},
6812 { 'S', ACTION_RESCUE
},
6813 { 'q', ACTION_RELOAD
},
6814 { 'Q', ACTION_RELOAD
},
6815 { 'u', ACTION_REEXEC
},
6816 { 'U', ACTION_REEXEC
}
6825 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
6840 assert_not_reached("Unhandled option");
6843 if (optind
>= argc
) {
6844 log_error("%s: required argument missing.",
6845 program_invocation_short_name
);
6849 if (optind
+ 1 < argc
) {
6850 log_error("Too many arguments.");
6854 if (strlen(argv
[optind
]) != 1) {
6855 log_error("Expected single character argument.");
6859 for (i
= 0; i
< ELEMENTSOF(table
); i
++)
6860 if (table
[i
].from
== argv
[optind
][0])
6863 if (i
>= ELEMENTSOF(table
)) {
6864 log_error("Unknown command '%s'.", argv
[optind
]);
6868 arg_action
= table
[i
].to
;
6875 static int runlevel_parse_argv(int argc
, char *argv
[]) {
6881 static const struct option options
[] = {
6882 { "help", no_argument
, NULL
, ARG_HELP
},
6891 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
6902 assert_not_reached("Unhandled option");
6905 if (optind
< argc
) {
6906 log_error("Too many arguments.");
6913 static int parse_argv(int argc
, char *argv
[]) {
6917 if (program_invocation_short_name
) {
6919 if (strstr(program_invocation_short_name
, "halt")) {
6920 arg_action
= ACTION_HALT
;
6921 return halt_parse_argv(argc
, argv
);
6922 } else if (strstr(program_invocation_short_name
, "poweroff")) {
6923 arg_action
= ACTION_POWEROFF
;
6924 return halt_parse_argv(argc
, argv
);
6925 } else if (strstr(program_invocation_short_name
, "reboot")) {
6927 arg_action
= ACTION_KEXEC
;
6929 arg_action
= ACTION_REBOOT
;
6930 return halt_parse_argv(argc
, argv
);
6931 } else if (strstr(program_invocation_short_name
, "shutdown")) {
6932 arg_action
= ACTION_POWEROFF
;
6933 return shutdown_parse_argv(argc
, argv
);
6934 } else if (strstr(program_invocation_short_name
, "init")) {
6936 if (sd_booted() > 0) {
6937 arg_action
= _ACTION_INVALID
;
6938 return telinit_parse_argv(argc
, argv
);
6940 /* Hmm, so some other init system is
6941 * running, we need to forward this
6942 * request to it. For now we simply
6943 * guess that it is Upstart. */
6945 execv(TELINIT
, argv
);
6947 log_error("Couldn't find an alternative telinit implementation to spawn.");
6951 } else if (strstr(program_invocation_short_name
, "runlevel")) {
6952 arg_action
= ACTION_RUNLEVEL
;
6953 return runlevel_parse_argv(argc
, argv
);
6957 arg_action
= ACTION_SYSTEMCTL
;
6958 return systemctl_parse_argv(argc
, argv
);
6961 _pure_
static int action_to_runlevel(void) {
6963 static const char table
[_ACTION_MAX
] = {
6964 [ACTION_HALT
] = '0',
6965 [ACTION_POWEROFF
] = '0',
6966 [ACTION_REBOOT
] = '6',
6967 [ACTION_RUNLEVEL2
] = '2',
6968 [ACTION_RUNLEVEL3
] = '3',
6969 [ACTION_RUNLEVEL4
] = '4',
6970 [ACTION_RUNLEVEL5
] = '5',
6971 [ACTION_RESCUE
] = '1'
6974 assert(arg_action
< _ACTION_MAX
);
6976 return table
[arg_action
];
6979 static int talk_initctl(void) {
6981 struct init_request request
= {
6982 .magic
= INIT_MAGIC
,
6984 .cmd
= INIT_CMD_RUNLVL
6987 _cleanup_close_
int fd
= -1;
6991 rl
= action_to_runlevel();
6995 request
.runlevel
= rl
;
6997 fd
= open(INIT_FIFO
, O_WRONLY
|O_NDELAY
|O_CLOEXEC
|O_NOCTTY
);
6999 if (errno
== ENOENT
)
7002 log_error_errno(errno
, "Failed to open "INIT_FIFO
": %m");
7006 r
= loop_write(fd
, &request
, sizeof(request
), false);
7008 return log_error_errno(r
, "Failed to write to "INIT_FIFO
": %m");
7013 static int systemctl_main(sd_bus
*bus
, int argc
, char *argv
[], int bus_error
) {
7015 static const struct {
7023 int (* const dispatch
)(sd_bus
*bus
, char **args
);
7029 { "list-units", MORE
, 0, list_units
},
7030 { "list-unit-files", MORE
, 1, list_unit_files
, NOBUS
},
7031 { "list-sockets", MORE
, 1, list_sockets
},
7032 { "list-timers", MORE
, 1, list_timers
},
7033 { "list-jobs", MORE
, 1, list_jobs
},
7034 { "list-machines", MORE
, 1, list_machines
},
7035 { "clear-jobs", EQUAL
, 1, daemon_reload
},
7036 { "cancel", MORE
, 2, cancel_job
},
7037 { "start", MORE
, 2, start_unit
},
7038 { "stop", MORE
, 2, start_unit
},
7039 { "condstop", MORE
, 2, start_unit
}, /* For compatibility with ALTLinux */
7040 { "reload", MORE
, 2, start_unit
},
7041 { "restart", MORE
, 2, start_unit
},
7042 { "try-restart", MORE
, 2, start_unit
},
7043 { "reload-or-restart", MORE
, 2, start_unit
},
7044 { "reload-or-try-restart", MORE
, 2, start_unit
},
7045 { "force-reload", MORE
, 2, start_unit
}, /* For compatibility with SysV */
7046 { "condreload", MORE
, 2, start_unit
}, /* For compatibility with ALTLinux */
7047 { "condrestart", MORE
, 2, start_unit
}, /* For compatibility with RH */
7048 { "isolate", EQUAL
, 2, start_unit
},
7049 { "kill", MORE
, 2, kill_unit
},
7050 { "is-active", MORE
, 2, check_unit_active
},
7051 { "check", MORE
, 2, check_unit_active
},
7052 { "is-failed", MORE
, 2, check_unit_failed
},
7053 { "show", MORE
, 1, show
},
7054 { "cat", MORE
, 2, cat
, NOBUS
},
7055 { "status", MORE
, 1, show
},
7056 { "help", MORE
, 2, show
},
7057 { "snapshot", LESS
, 2, snapshot
},
7058 { "delete", MORE
, 2, delete_snapshot
},
7059 { "daemon-reload", EQUAL
, 1, daemon_reload
},
7060 { "daemon-reexec", EQUAL
, 1, daemon_reload
},
7061 { "show-environment", EQUAL
, 1, show_environment
},
7062 { "set-environment", MORE
, 2, set_environment
},
7063 { "unset-environment", MORE
, 2, set_environment
},
7064 { "import-environment", MORE
, 1, import_environment
},
7065 { "halt", EQUAL
, 1, start_special
, FORCE
},
7066 { "poweroff", EQUAL
, 1, start_special
, FORCE
},
7067 { "reboot", MORE
, 1, start_special
, FORCE
},
7068 { "kexec", EQUAL
, 1, start_special
},
7069 { "suspend", EQUAL
, 1, start_special
},
7070 { "hibernate", EQUAL
, 1, start_special
},
7071 { "hybrid-sleep", EQUAL
, 1, start_special
},
7072 { "default", EQUAL
, 1, start_special
},
7073 { "rescue", EQUAL
, 1, start_special
},
7074 { "emergency", EQUAL
, 1, start_special
},
7075 { "exit", EQUAL
, 1, start_special
},
7076 { "reset-failed", MORE
, 1, reset_failed
},
7077 { "enable", MORE
, 2, enable_unit
, NOBUS
},
7078 { "disable", MORE
, 2, enable_unit
, NOBUS
},
7079 { "is-enabled", MORE
, 2, unit_is_enabled
, NOBUS
},
7080 { "reenable", MORE
, 2, enable_unit
, NOBUS
},
7081 { "preset", MORE
, 2, enable_unit
, NOBUS
},
7082 { "preset-all", EQUAL
, 1, preset_all
, NOBUS
},
7083 { "mask", MORE
, 2, enable_unit
, NOBUS
},
7084 { "unmask", MORE
, 2, enable_unit
, NOBUS
},
7085 { "link", MORE
, 2, enable_unit
, NOBUS
},
7086 { "switch-root", MORE
, 2, switch_root
},
7087 { "list-dependencies", LESS
, 2, list_dependencies
},
7088 { "set-default", EQUAL
, 2, set_default
, NOBUS
},
7089 { "get-default", EQUAL
, 1, get_default
, NOBUS
},
7090 { "set-property", MORE
, 3, set_property
},
7091 { "is-system-running", EQUAL
, 1, is_system_running
},
7092 { "add-wants", MORE
, 3, add_dependency
, NOBUS
},
7093 { "add-requires", MORE
, 3, add_dependency
, NOBUS
},
7094 { "edit", MORE
, 2, edit
, NOBUS
},
7103 left
= argc
- optind
;
7105 /* Special rule: no arguments (left == 0) means "list-units" */
7107 if (streq(argv
[optind
], "help") && !argv
[optind
+1]) {
7108 log_error("This command expects one or more "
7109 "unit names. Did you mean --help?");
7113 for (; verb
->verb
; verb
++)
7114 if (streq(argv
[optind
], verb
->verb
))
7117 log_error("Unknown operation '%s'.", argv
[optind
]);
7122 switch (verb
->argc_cmp
) {
7125 if (left
!= verb
->argc
) {
7126 log_error("Invalid number of arguments.");
7133 if (left
< verb
->argc
) {
7134 log_error("Too few arguments.");
7141 if (left
> verb
->argc
) {
7142 log_error("Too many arguments.");
7149 assert_not_reached("Unknown comparison operator.");
7152 /* Require a bus connection for all operations but
7154 if (verb
->bus
== NOBUS
) {
7155 if (!bus
&& !avoid_bus()) {
7156 log_error_errno(bus_error
, "Failed to get D-Bus connection: %m");
7161 if (running_in_chroot() > 0) {
7162 log_info("Running in chroot, ignoring request.");
7166 if ((verb
->bus
!= FORCE
|| arg_force
<= 0) && !bus
) {
7167 log_error_errno(bus_error
, "Failed to get D-Bus connection: %m");
7172 return verb
->dispatch(bus
, argv
+ optind
);
7175 static int reload_with_fallback(sd_bus
*bus
) {
7178 /* First, try systemd via D-Bus. */
7179 if (daemon_reload(bus
, NULL
) >= 0)
7183 /* Nothing else worked, so let's try signals */
7184 assert(arg_action
== ACTION_RELOAD
|| arg_action
== ACTION_REEXEC
);
7186 if (kill(1, arg_action
== ACTION_RELOAD
? SIGHUP
: SIGTERM
) < 0)
7187 return log_error_errno(errno
, "kill() failed: %m");
7192 static int start_with_fallback(sd_bus
*bus
) {
7195 /* First, try systemd via D-Bus. */
7196 if (start_unit(bus
, NULL
) >= 0)
7200 /* Nothing else worked, so let's try
7202 if (talk_initctl() > 0)
7205 log_error("Failed to talk to init daemon.");
7209 warn_wall(arg_action
);
7213 static int halt_now(enum action a
) {
7215 /* The kernel will automaticall flush ATA disks and suchlike
7216 * on reboot(), but the file systems need to be synce'd
7217 * explicitly in advance. */
7220 /* Make sure C-A-D is handled by the kernel from this point
7222 reboot(RB_ENABLE_CAD
);
7227 log_info("Halting.");
7228 reboot(RB_HALT_SYSTEM
);
7231 case ACTION_POWEROFF
:
7232 log_info("Powering off.");
7233 reboot(RB_POWER_OFF
);
7236 case ACTION_REBOOT
: {
7237 _cleanup_free_
char *param
= NULL
;
7239 if (read_one_line_file(REBOOT_PARAM_FILE
, ¶m
) >= 0) {
7240 log_info("Rebooting with argument '%s'.", param
);
7241 syscall(SYS_reboot
, LINUX_REBOOT_MAGIC1
, LINUX_REBOOT_MAGIC2
,
7242 LINUX_REBOOT_CMD_RESTART2
, param
);
7245 log_info("Rebooting.");
7246 reboot(RB_AUTOBOOT
);
7251 assert_not_reached("Unknown action.");
7255 static int halt_main(sd_bus
*bus
) {
7258 r
= check_inhibitors(bus
, arg_action
);
7262 if (geteuid() != 0) {
7263 /* Try logind if we are a normal user and no special
7264 * mode applies. Maybe PolicyKit allows us to shutdown
7267 if (arg_when
<= 0 &&
7270 (arg_action
== ACTION_POWEROFF
||
7271 arg_action
== ACTION_REBOOT
)) {
7272 r
= reboot_with_logind(bus
, arg_action
);
7277 log_error("Must be root.");
7282 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
7283 _cleanup_bus_close_unref_ sd_bus
*b
= NULL
;
7284 _cleanup_free_
char *m
;
7287 log_error("Unable to perform operation without bus connection.");
7291 r
= sd_bus_open_system(&b
);
7293 return log_error_errno(r
, "Unable to open system bus: %m");
7295 m
= strv_join(arg_wall
, " ");
7299 r
= sd_bus_set_property(
7301 "org.freedesktop.login1",
7302 "/org/freedesktop/login1",
7303 "org.freedesktop.login1.Manager",
7308 log_warning_errno(r
, "Failed to set WallMessage property in logind: %s",
7309 bus_error_message(&error
, r
));
7310 sd_bus_error_free(&error
);
7313 r
= sd_bus_set_property(
7315 "org.freedesktop.login1",
7316 "/org/freedesktop/login1",
7317 "org.freedesktop.login1.Manager",
7318 "EnableWallMessages",
7322 log_warning_errno(r
, "Failed to set EnableWallMessages property in logind: %s",
7323 bus_error_message(&error
, r
));
7324 sd_bus_error_free(&error
);
7327 r
= sd_bus_call_method(
7329 "org.freedesktop.login1",
7330 "/org/freedesktop/login1",
7331 "org.freedesktop.login1.Manager",
7336 arg_action
== ACTION_HALT
? "halt" :
7337 arg_action
== ACTION_POWEROFF
? "poweroff" :
7338 arg_action
== ACTION_KEXEC
? "kexec" :
7342 log_warning_errno(r
, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s",
7343 bus_error_message(&error
, r
));
7345 char date
[FORMAT_TIMESTAMP_MAX
];
7347 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
7348 format_timestamp(date
, sizeof(date
), arg_when
));
7353 if (!arg_dry
&& !arg_force
)
7354 return start_with_fallback(bus
);
7357 if (sd_booted() > 0)
7358 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
7360 r
= utmp_put_shutdown();
7362 log_warning_errno(r
, "Failed to write utmp record: %m");
7369 r
= halt_now(arg_action
);
7370 log_error_errno(r
, "Failed to reboot: %m");
7375 static int runlevel_main(void) {
7376 int r
, runlevel
, previous
;
7378 r
= utmp_get_runlevel(&runlevel
, &previous
);
7385 previous
<= 0 ? 'N' : previous
,
7386 runlevel
<= 0 ? 'N' : runlevel
);
7391 int main(int argc
, char*argv
[]) {
7392 _cleanup_bus_close_unref_ sd_bus
*bus
= NULL
;
7395 setlocale(LC_ALL
, "");
7396 log_parse_environment();
7399 /* Explicitly not on_tty() to avoid setting cached value.
7400 * This becomes relevant for piping output which might be
7402 original_stdout_is_tty
= isatty(STDOUT_FILENO
);
7404 r
= parse_argv(argc
, argv
);
7408 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
7409 * let's shortcut this */
7410 if (arg_action
== ACTION_RUNLEVEL
) {
7411 r
= runlevel_main();
7415 if (running_in_chroot() > 0 && arg_action
!= ACTION_SYSTEMCTL
) {
7416 log_info("Running in chroot, ignoring request.");
7422 r
= bus_open_transport_systemd(arg_transport
, arg_host
, arg_scope
!= UNIT_FILE_SYSTEM
, &bus
);
7425 sd_bus_set_allow_interactive_authorization(bus
, arg_ask_password
);
7427 /* systemctl_main() will print an error message for the bus
7428 * connection, but only if it needs to */
7430 switch (arg_action
) {
7432 case ACTION_SYSTEMCTL
:
7433 r
= systemctl_main(bus
, argc
, argv
, r
);
7437 case ACTION_POWEROFF
:
7443 case ACTION_RUNLEVEL2
:
7444 case ACTION_RUNLEVEL3
:
7445 case ACTION_RUNLEVEL4
:
7446 case ACTION_RUNLEVEL5
:
7448 case ACTION_EMERGENCY
:
7449 case ACTION_DEFAULT
:
7450 r
= start_with_fallback(bus
);
7455 r
= reload_with_fallback(bus
);
7458 case ACTION_CANCEL_SHUTDOWN
: {
7459 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
7460 _cleanup_bus_close_unref_ sd_bus
*b
= NULL
;
7461 _cleanup_free_
char *m
= NULL
;
7464 log_error("Unable to perform operation without bus connection.");
7468 r
= sd_bus_open_system(&b
);
7470 return log_error_errno(r
, "Unable to open system bus: %m");
7473 m
= strv_join(arg_wall
, " ");
7480 r
= sd_bus_set_property(
7482 "org.freedesktop.login1",
7483 "/org/freedesktop/login1",
7484 "org.freedesktop.login1.Manager",
7489 log_warning_errno(r
, "Failed to set WallMessage property in logind: %s",
7490 bus_error_message(&error
, r
));
7491 sd_bus_error_free(&error
);
7494 r
= sd_bus_set_property(
7496 "org.freedesktop.login1",
7497 "/org/freedesktop/login1",
7498 "org.freedesktop.login1.Manager",
7499 "EnableWallMessages",
7503 log_warning_errno(r
, "Failed to set EnableWallMessages property in logind: %s",
7504 bus_error_message(&error
, r
));
7505 sd_bus_error_free(&error
);
7508 r
= sd_bus_call_method(
7510 "org.freedesktop.login1",
7511 "/org/freedesktop/login1",
7512 "org.freedesktop.login1.Manager",
7513 "CancelScheduledShutdown",
7517 log_warning_errno(r
, "Failed to talk to logind, shutdown hasn't been cancelled: %s",
7518 bus_error_message(&error
, r
));
7522 case ACTION_RUNLEVEL
:
7523 case _ACTION_INVALID
:
7525 assert_not_reached("Unknown action");
7530 ask_password_agent_close();
7531 polkit_agent_close();
7533 strv_free(arg_types
);
7534 strv_free(arg_states
);
7535 strv_free(arg_properties
);
7537 return r
< 0 ? EXIT_FAILURE
: r
;