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>
25 #include <sys/syscall.h>
32 #include <sys/ioctl.h>
36 #include <sys/socket.h>
39 #include <sys/prctl.h>
42 #include "sd-daemon.h"
43 #include "sd-shutdown.h"
50 #include "utmp-wtmp.h"
53 #include "path-util.h"
55 #include "cgroup-show.h"
56 #include "cgroup-util.h"
58 #include "path-lookup.h"
59 #include "conf-parser.h"
60 #include "exit-status.h"
62 #include "unit-name.h"
64 #include "spawn-ask-password-agent.h"
65 #include "spawn-polkit-agent.h"
67 #include "logs-show.h"
68 #include "socket-util.h"
72 #include "bus-message.h"
73 #include "bus-error.h"
74 #include "bus-errors.h"
76 static char **arg_types
= NULL
;
77 static char **arg_states
= NULL
;
78 static char **arg_properties
= NULL
;
79 static bool arg_all
= false;
80 static enum dependency
{
86 } arg_dependency
= DEPENDENCY_FORWARD
;
87 static const char *arg_job_mode
= "replace";
88 static UnitFileScope arg_scope
= UNIT_FILE_SYSTEM
;
89 static bool arg_no_block
= false;
90 static bool arg_no_legend
= false;
91 static bool arg_no_pager
= false;
92 static bool arg_no_wtmp
= false;
93 static bool arg_no_wall
= false;
94 static bool arg_no_reload
= false;
95 static bool arg_show_types
= false;
96 static bool arg_ignore_inhibitors
= false;
97 static bool arg_dry
= false;
98 static bool arg_quiet
= false;
99 static bool arg_full
= false;
100 static bool arg_recursive
= false;
101 static int arg_force
= 0;
102 static bool arg_ask_password
= true;
103 static bool arg_runtime
= false;
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;
139 static const struct {
143 { "start", "StartUnit" },
144 { "stop", "StopUnit" },
145 { "condstop", "StopUnit" },
146 { "reload", "ReloadUnit" },
147 { "restart", "RestartUnit" },
148 { "try-restart", "TryRestartUnit" },
149 { "condrestart", "TryRestartUnit" },
150 { "reload-or-restart", "ReloadOrRestartUnit" },
151 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
152 { "condreload", "ReloadOrTryRestartUnit" },
153 { "force-reload", "ReloadOrTryRestartUnit" }
156 static bool original_stdout_is_tty
;
158 static int daemon_reload(sd_bus
*bus
, char **args
);
159 static int halt_now(enum action a
);
160 static int check_one_unit(sd_bus
*bus
, const char *name
, const char *good_states
, bool quiet
);
162 static char** strv_skip_first(char **strv
) {
163 if (strv_length(strv
) > 0)
168 static void pager_open_if_enabled(void) {
176 static void ask_password_agent_open_if_enabled(void) {
178 /* Open the password 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
)
189 ask_password_agent_open();
193 static void polkit_agent_open_if_enabled(void) {
195 /* Open the polkit agent as a child process if necessary */
197 if (!arg_ask_password
)
200 if (arg_scope
!= UNIT_FILE_SYSTEM
)
203 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
210 static int translate_bus_error_to_exit_status(int r
, const sd_bus_error
*error
) {
213 if (!sd_bus_error_is_set(error
))
216 if (sd_bus_error_has_name(error
, SD_BUS_ERROR_ACCESS_DENIED
) ||
217 sd_bus_error_has_name(error
, BUS_ERROR_ONLY_BY_DEPENDENCY
) ||
218 sd_bus_error_has_name(error
, BUS_ERROR_NO_ISOLATION
) ||
219 sd_bus_error_has_name(error
, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE
))
220 return EXIT_NOPERMISSION
;
222 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
))
223 return EXIT_NOTINSTALLED
;
225 if (sd_bus_error_has_name(error
, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE
) ||
226 sd_bus_error_has_name(error
, SD_BUS_ERROR_NOT_SUPPORTED
))
227 return EXIT_NOTIMPLEMENTED
;
229 if (sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
))
230 return EXIT_NOTCONFIGURED
;
238 static void warn_wall(enum action a
) {
239 static const char *table
[_ACTION_MAX
] = {
240 [ACTION_HALT
] = "The system is going down for system halt NOW!",
241 [ACTION_REBOOT
] = "The system is going down for reboot NOW!",
242 [ACTION_POWEROFF
] = "The system is going down for power-off NOW!",
243 [ACTION_KEXEC
] = "The system is going down for kexec reboot NOW!",
244 [ACTION_RESCUE
] = "The system is going down to rescue mode NOW!",
245 [ACTION_EMERGENCY
] = "The system is going down to emergency mode NOW!",
246 [ACTION_CANCEL_SHUTDOWN
] = "The system shutdown has been cancelled NOW!"
253 _cleanup_free_
char *p
;
255 p
= strv_join(arg_wall
, " ");
262 utmp_wall(p
, NULL
, NULL
);
270 utmp_wall(table
[a
], NULL
, NULL
);
273 static bool avoid_bus(void) {
275 if (running_in_chroot() > 0)
278 if (sd_booted() <= 0)
281 if (!isempty(arg_root
))
284 if (arg_scope
== UNIT_FILE_GLOBAL
)
290 static int compare_unit_info(const void *a
, const void *b
) {
291 const UnitInfo
*u
= a
, *v
= b
;
295 /* First, order by machine */
296 if (!u
->machine
&& v
->machine
)
298 if (u
->machine
&& !v
->machine
)
300 if (u
->machine
&& v
->machine
) {
301 r
= strcasecmp(u
->machine
, v
->machine
);
306 /* Second, order by unit type */
307 d1
= strrchr(u
->id
, '.');
308 d2
= strrchr(v
->id
, '.');
310 r
= strcasecmp(d1
, d2
);
315 /* Third, order by name */
316 return strcasecmp(u
->id
, v
->id
);
319 static bool output_show_unit(const UnitInfo
*u
, char **patterns
) {
322 if (!strv_isempty(arg_states
))
324 strv_contains(arg_states
, u
->load_state
) ||
325 strv_contains(arg_states
, u
->sub_state
) ||
326 strv_contains(arg_states
, u
->active_state
);
328 if (!strv_isempty(patterns
)) {
331 STRV_FOREACH(pattern
, patterns
)
332 if (fnmatch(*pattern
, u
->id
, FNM_NOESCAPE
) == 0)
337 return (!arg_types
|| ((dot
= strrchr(u
->id
, '.')) &&
338 strv_find(arg_types
, dot
+1))) &&
339 (arg_all
|| !(streq(u
->active_state
, "inactive")
340 || u
->following
[0]) || u
->job_id
> 0);
343 static int output_units_list(const UnitInfo
*unit_infos
, unsigned c
) {
344 unsigned circle_len
= 0, id_len
, max_id_len
, load_len
, active_len
, sub_len
, job_len
, desc_len
;
346 unsigned n_shown
= 0;
349 max_id_len
= strlen("UNIT");
350 load_len
= strlen("LOAD");
351 active_len
= strlen("ACTIVE");
352 sub_len
= strlen("SUB");
353 job_len
= strlen("JOB");
356 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
357 max_id_len
= MAX(max_id_len
, strlen(u
->id
) + (u
->machine
? strlen(u
->machine
)+1 : 0));
358 load_len
= MAX(load_len
, strlen(u
->load_state
));
359 active_len
= MAX(active_len
, strlen(u
->active_state
));
360 sub_len
= MAX(sub_len
, strlen(u
->sub_state
));
362 if (u
->job_id
!= 0) {
363 job_len
= MAX(job_len
, strlen(u
->job_type
));
367 if (!arg_no_legend
&&
368 (streq(u
->active_state
, "failed") ||
369 STR_IN_SET(u
->load_state
, "error", "not-found", "masked")))
373 if (!arg_full
&& original_stdout_is_tty
) {
376 id_len
= MIN(max_id_len
, 25u);
377 basic_len
= circle_len
+ 5 + id_len
+ 5 + active_len
+ sub_len
;
380 basic_len
+= job_len
+ 1;
382 if (basic_len
< (unsigned) columns()) {
383 unsigned extra_len
, incr
;
384 extra_len
= columns() - basic_len
;
386 /* Either UNIT already got 25, or is fully satisfied.
387 * Grant up to 25 to DESC now. */
388 incr
= MIN(extra_len
, 25u);
392 /* split the remaining space between UNIT and DESC,
393 * but do not give UNIT more than it needs. */
395 incr
= MIN(extra_len
/ 2, max_id_len
- id_len
);
397 desc_len
+= extra_len
- incr
;
403 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
404 _cleanup_free_
char *e
= NULL
, *j
= NULL
;
405 const char *on_loaded
= "", *off_loaded
= "";
406 const char *on_active
= "", *off_active
= "";
407 const char *on_circle
= "", *off_circle
= "";
411 if (!n_shown
&& !arg_no_legend
) {
416 printf("%-*s %-*s %-*s %-*s ",
419 active_len
, "ACTIVE",
423 printf("%-*s ", job_len
, "JOB");
425 if (!arg_full
&& arg_no_pager
)
426 printf("%.*s\n", desc_len
, "DESCRIPTION");
428 printf("%s\n", "DESCRIPTION");
433 if (STR_IN_SET(u
->load_state
, "error", "not-found", "masked")) {
434 on_loaded
= ansi_highlight_red();
435 on_circle
= ansi_highlight_yellow();
436 off_loaded
= off_circle
= ansi_highlight_off();
440 if (streq(u
->active_state
, "failed")) {
441 on_circle
= on_active
= ansi_highlight_red();
442 off_circle
= off_active
= ansi_highlight_off();
447 j
= strjoin(u
->machine
, ":", u
->id
, NULL
);
456 e
= ellipsize(id
, id_len
, 33);
464 printf("%s%s%s", on_circle
, circle
? draw_special_char(DRAW_BLACK_CIRCLE
) : " ", off_circle
);
466 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
467 on_active
, id_len
, id
, off_active
,
468 on_loaded
, load_len
, u
->load_state
, off_loaded
,
469 on_active
, active_len
, u
->active_state
,
470 sub_len
, u
->sub_state
, off_active
,
471 job_count
? job_len
+ 1 : 0, u
->job_id
? u
->job_type
: "");
474 printf("%.*s\n", desc_len
, u
->description
);
476 printf("%s\n", u
->description
);
479 if (!arg_no_legend
) {
480 const char *on
, *off
;
484 "LOAD = Reflects whether the unit definition was properly loaded.\n"
485 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
486 "SUB = The low-level unit activation state, values depend on unit type.");
487 puts(job_count
? "JOB = Pending job for the unit.\n" : "");
488 on
= ansi_highlight();
489 off
= ansi_highlight_off();
491 on
= ansi_highlight_red();
492 off
= ansi_highlight_off();
496 printf("%s%u loaded units listed.%s\n"
497 "To show all installed unit files use 'systemctl list-unit-files'.\n",
500 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
501 "To show all installed unit files use 'systemctl list-unit-files'.\n",
508 static int get_unit_list(
512 UnitInfo
**unit_infos
,
514 sd_bus_message
**_reply
) {
516 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
517 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
526 size
= sizeof(UnitInfo
) * c
;
528 r
= sd_bus_call_method(
530 "org.freedesktop.systemd1",
531 "/org/freedesktop/systemd1",
532 "org.freedesktop.systemd1.Manager",
538 log_error("Failed to list units: %s", bus_error_message(&error
, r
));
542 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssssouso)");
544 return bus_log_parse_error(r
);
546 while ((r
= bus_parse_unit_info(reply
, &u
)) > 0) {
549 if (!output_show_unit(&u
, patterns
))
552 if (!GREEDY_REALLOC(*unit_infos
, size
, c
+1))
555 (*unit_infos
)[c
++] = u
;
558 return bus_log_parse_error(r
);
560 r
= sd_bus_message_exit_container(reply
);
562 return bus_log_parse_error(r
);
570 static void message_set_freep(Set
**set
) {
573 while ((m
= set_steal_first(*set
)))
574 sd_bus_message_unref(m
);
579 static int get_unit_list_recursive(
582 UnitInfo
**_unit_infos
,
586 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
587 _cleanup_(message_set_freep
) Set
*replies
;
588 sd_bus_message
*reply
;
596 replies
= set_new(NULL
, NULL
);
600 c
= get_unit_list(bus
, NULL
, patterns
, &unit_infos
, 0, &reply
);
604 r
= set_put(replies
, reply
);
606 sd_bus_message_unref(reply
);
611 _cleanup_strv_free_
char **machines
= NULL
;
614 r
= sd_get_machine_names(&machines
);
618 STRV_FOREACH(i
, machines
) {
619 _cleanup_bus_unref_ sd_bus
*container
= NULL
;
622 r
= sd_bus_open_system_container(&container
, *i
);
624 log_error("Failed to connect to container %s: %s", *i
, strerror(-r
));
628 k
= get_unit_list(container
, *i
, patterns
, &unit_infos
, c
, &reply
);
634 r
= set_put(replies
, reply
);
636 sd_bus_message_unref(reply
);
641 *_machines
= machines
;
646 *_unit_infos
= unit_infos
;
655 static int list_units(sd_bus
*bus
, char **args
) {
656 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
657 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
658 _cleanup_strv_free_
char **machines
= NULL
;
661 pager_open_if_enabled();
663 r
= get_unit_list_recursive(bus
, strv_skip_first(args
), &unit_infos
, &replies
, &machines
);
667 qsort_safe(unit_infos
, r
, sizeof(UnitInfo
), compare_unit_info
);
668 return output_units_list(unit_infos
, r
);
671 static int get_triggered_units(
676 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
679 r
= sd_bus_get_property_strv(
681 "org.freedesktop.systemd1",
683 "org.freedesktop.systemd1.Unit",
689 log_error("Failed to determine triggers: %s", bus_error_message(&error
, r
));
694 static int get_listening(
696 const char* unit_path
,
699 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
700 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
701 const char *type
, *path
;
704 r
= sd_bus_get_property(
706 "org.freedesktop.systemd1",
708 "org.freedesktop.systemd1.Socket",
714 log_error("Failed to get list of listening sockets: %s", bus_error_message(&error
, r
));
718 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
720 return bus_log_parse_error(r
);
722 while ((r
= sd_bus_message_read(reply
, "(ss)", &type
, &path
)) > 0) {
724 r
= strv_extend(listening
, type
);
728 r
= strv_extend(listening
, path
);
735 return bus_log_parse_error(r
);
737 r
= sd_bus_message_exit_container(reply
);
739 return bus_log_parse_error(r
);
750 /* Note: triggered is a list here, although it almost certainly
751 * will always be one unit. Nevertheless, dbus API allows for multiple
752 * values, so let's follow that.*/
755 /* The strv above is shared. free is set only in the first one. */
759 static int socket_info_compare(const struct socket_info
*a
, const struct socket_info
*b
) {
765 o
= strcmp(a
->path
, b
->path
);
767 o
= strcmp(a
->type
, b
->type
);
772 static int output_sockets_list(struct socket_info
*socket_infos
, unsigned cs
) {
773 struct socket_info
*s
;
774 unsigned pathlen
= strlen("LISTEN"),
775 typelen
= strlen("TYPE") * arg_show_types
,
776 socklen
= strlen("UNIT"),
777 servlen
= strlen("ACTIVATES");
778 const char *on
, *off
;
780 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
784 socklen
= MAX(socklen
, strlen(s
->id
));
786 typelen
= MAX(typelen
, strlen(s
->type
));
787 pathlen
= MAX(pathlen
, strlen(s
->path
));
789 STRV_FOREACH(a
, s
->triggered
)
790 tmp
+= strlen(*a
) + 2*(a
!= s
->triggered
);
791 servlen
= MAX(servlen
, tmp
);
796 printf("%-*s %-*.*s%-*s %s\n",
798 typelen
+ arg_show_types
, typelen
+ arg_show_types
, "TYPE ",
802 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
806 printf("%-*s %-*s %-*s",
807 pathlen
, s
->path
, typelen
, s
->type
, socklen
, s
->id
);
810 pathlen
, s
->path
, socklen
, s
->id
);
811 STRV_FOREACH(a
, s
->triggered
)
813 a
== s
->triggered
? "" : ",", *a
);
817 on
= ansi_highlight();
818 off
= ansi_highlight_off();
822 on
= ansi_highlight_red();
823 off
= ansi_highlight_off();
826 if (!arg_no_legend
) {
827 printf("%s%u sockets listed.%s\n", on
, cs
, off
);
829 printf("Pass --all to see loaded but inactive sockets, too.\n");
835 static int list_sockets(sd_bus
*bus
, char **args
) {
836 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
837 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
838 _cleanup_free_
struct socket_info
*socket_infos
= NULL
;
840 struct socket_info
*s
;
845 pager_open_if_enabled();
847 n
= get_unit_list(bus
, NULL
, strv_skip_first(args
), &unit_infos
, 0, &reply
);
851 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
852 _cleanup_strv_free_
char **listening
= NULL
, **triggered
= NULL
;
855 if (!endswith(u
->id
, ".socket"))
858 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
862 c
= get_listening(bus
, u
->unit_path
, &listening
);
868 if (!GREEDY_REALLOC(socket_infos
, size
, cs
+ c
)) {
873 for (i
= 0; i
< c
; i
++)
874 socket_infos
[cs
+ i
] = (struct socket_info
) {
876 .type
= listening
[i
*2],
877 .path
= listening
[i
*2 + 1],
878 .triggered
= triggered
,
879 .own_triggered
= i
==0,
882 /* from this point on we will cleanup those socket_infos */
885 listening
= triggered
= NULL
; /* avoid cleanup */
888 qsort_safe(socket_infos
, cs
, sizeof(struct socket_info
),
889 (__compar_fn_t
) socket_info_compare
);
891 output_sockets_list(socket_infos
, cs
);
894 assert(cs
== 0 || socket_infos
);
895 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
898 if (s
->own_triggered
)
899 strv_free(s
->triggered
);
905 static int get_next_elapse(
908 dual_timestamp
*next
) {
910 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
918 r
= sd_bus_get_property_trivial(
920 "org.freedesktop.systemd1",
922 "org.freedesktop.systemd1.Timer",
923 "NextElapseUSecMonotonic",
928 log_error("Failed to get next elapsation time: %s", bus_error_message(&error
, r
));
932 r
= sd_bus_get_property_trivial(
934 "org.freedesktop.systemd1",
936 "org.freedesktop.systemd1.Timer",
937 "NextElapseUSecRealtime",
942 log_error("Failed to get next elapsation time: %s", bus_error_message(&error
, r
));
950 static int get_last_trigger(
955 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
962 r
= sd_bus_get_property_trivial(
964 "org.freedesktop.systemd1",
966 "org.freedesktop.systemd1.Timer",
972 log_error("Failed to get last trigger time: %s", bus_error_message(&error
, r
));
986 static int timer_info_compare(const struct timer_info
*a
, const struct timer_info
*b
) {
990 if (a
->next_elapse
< b
->next_elapse
)
992 if (a
->next_elapse
> b
->next_elapse
)
995 return strcmp(a
->id
, b
->id
);
998 static int output_timers_list(struct timer_info
*timer_infos
, unsigned n
) {
999 struct timer_info
*t
;
1001 nextlen
= strlen("NEXT"),
1002 leftlen
= strlen("LEFT"),
1003 lastlen
= strlen("LAST"),
1004 passedlen
= strlen("PASSED"),
1005 unitlen
= strlen("UNIT"),
1006 activatelen
= strlen("ACTIVATES");
1008 const char *on
, *off
;
1010 assert(timer_infos
|| n
== 0);
1012 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1016 if (t
->next_elapse
> 0) {
1017 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1019 format_timestamp(tstamp
, sizeof(tstamp
), t
->next_elapse
);
1020 nextlen
= MAX(nextlen
, strlen(tstamp
) + 1);
1022 format_timestamp_relative(trel
, sizeof(trel
), t
->next_elapse
);
1023 leftlen
= MAX(leftlen
, strlen(trel
));
1026 if (t
->last_trigger
> 0) {
1027 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1029 format_timestamp(tstamp
, sizeof(tstamp
), t
->last_trigger
);
1030 lastlen
= MAX(lastlen
, strlen(tstamp
) + 1);
1032 format_timestamp_relative(trel
, sizeof(trel
), t
->last_trigger
);
1033 passedlen
= MAX(passedlen
, strlen(trel
));
1036 unitlen
= MAX(unitlen
, strlen(t
->id
));
1038 STRV_FOREACH(a
, t
->triggered
)
1039 ul
+= strlen(*a
) + 2*(a
!= t
->triggered
);
1041 activatelen
= MAX(activatelen
, ul
);
1046 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1050 passedlen
, "PASSED",
1054 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1055 char tstamp1
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel1
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1056 char tstamp2
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel2
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1059 format_timestamp(tstamp1
, sizeof(tstamp1
), t
->next_elapse
);
1060 format_timestamp_relative(trel1
, sizeof(trel1
), t
->next_elapse
);
1062 format_timestamp(tstamp2
, sizeof(tstamp2
), t
->last_trigger
);
1063 format_timestamp_relative(trel2
, sizeof(trel2
), t
->last_trigger
);
1065 printf("%-*s %-*s %-*s %-*s %-*s",
1066 nextlen
, tstamp1
, leftlen
, trel1
, lastlen
, tstamp2
, passedlen
, trel2
, unitlen
, t
->id
);
1068 STRV_FOREACH(a
, t
->triggered
)
1070 a
== t
->triggered
? "" : ",", *a
);
1074 on
= ansi_highlight();
1075 off
= ansi_highlight_off();
1079 on
= ansi_highlight_red();
1080 off
= ansi_highlight_off();
1083 if (!arg_no_legend
) {
1084 printf("%s%u timers listed.%s\n", on
, n
, off
);
1086 printf("Pass --all to see loaded but inactive timers, too.\n");
1092 static usec_t
calc_next_elapse(dual_timestamp
*nw
, dual_timestamp
*next
) {
1098 if (next
->monotonic
!= (usec_t
) -1 && next
->monotonic
> 0) {
1101 if (next
->monotonic
> nw
->monotonic
)
1102 converted
= nw
->realtime
+ (next
->monotonic
- nw
->monotonic
);
1104 converted
= nw
->realtime
- (nw
->monotonic
- next
->monotonic
);
1106 if (next
->realtime
!= (usec_t
) -1 && next
->realtime
> 0)
1107 next_elapse
= MIN(converted
, next
->realtime
);
1109 next_elapse
= converted
;
1112 next_elapse
= next
->realtime
;
1117 static int list_timers(sd_bus
*bus
, char **args
) {
1119 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1120 _cleanup_free_
struct timer_info
*timer_infos
= NULL
;
1121 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
1122 struct timer_info
*t
;
1129 pager_open_if_enabled();
1131 n
= get_unit_list(bus
, NULL
, strv_skip_first(args
), &unit_infos
, 0, &reply
);
1135 dual_timestamp_get(&nw
);
1137 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
1138 _cleanup_strv_free_
char **triggered
= NULL
;
1139 dual_timestamp next
= {};
1142 if (!endswith(u
->id
, ".timer"))
1145 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
1149 r
= get_next_elapse(bus
, u
->unit_path
, &next
);
1153 get_last_trigger(bus
, u
->unit_path
, &last
);
1155 if (!GREEDY_REALLOC(timer_infos
, size
, c
+1)) {
1160 m
= calc_next_elapse(&nw
, &next
);
1162 timer_infos
[c
++] = (struct timer_info
) {
1165 .last_trigger
= last
,
1166 .triggered
= triggered
,
1169 triggered
= NULL
; /* avoid cleanup */
1172 qsort_safe(timer_infos
, c
, sizeof(struct timer_info
),
1173 (__compar_fn_t
) timer_info_compare
);
1175 output_timers_list(timer_infos
, c
);
1178 for (t
= timer_infos
; t
< timer_infos
+ c
; t
++)
1179 strv_free(t
->triggered
);
1184 static int compare_unit_file_list(const void *a
, const void *b
) {
1185 const char *d1
, *d2
;
1186 const UnitFileList
*u
= a
, *v
= b
;
1188 d1
= strrchr(u
->path
, '.');
1189 d2
= strrchr(v
->path
, '.');
1194 r
= strcasecmp(d1
, d2
);
1199 return strcasecmp(basename(u
->path
), basename(v
->path
));
1202 static bool output_show_unit_file(const UnitFileList
*u
, char **patterns
) {
1205 if (!strv_isempty(patterns
)) {
1208 STRV_FOREACH(pattern
, patterns
)
1209 if (fnmatch(*pattern
, basename(u
->path
), FNM_NOESCAPE
) == 0)
1214 return !arg_types
|| ((dot
= strrchr(u
->path
, '.')) && strv_find(arg_types
, dot
+1));
1217 static void output_unit_file_list(const UnitFileList
*units
, unsigned c
) {
1218 unsigned max_id_len
, id_cols
, state_cols
;
1219 const UnitFileList
*u
;
1221 max_id_len
= strlen("UNIT FILE");
1222 state_cols
= strlen("STATE");
1224 for (u
= units
; u
< units
+ c
; u
++) {
1225 max_id_len
= MAX(max_id_len
, strlen(basename(u
->path
)));
1226 state_cols
= MAX(state_cols
, strlen(unit_file_state_to_string(u
->state
)));
1230 unsigned basic_cols
;
1232 id_cols
= MIN(max_id_len
, 25u);
1233 basic_cols
= 1 + id_cols
+ state_cols
;
1234 if (basic_cols
< (unsigned) columns())
1235 id_cols
+= MIN(columns() - basic_cols
, max_id_len
- id_cols
);
1237 id_cols
= max_id_len
;
1240 printf("%-*s %-*s\n",
1241 id_cols
, "UNIT FILE",
1242 state_cols
, "STATE");
1244 for (u
= units
; u
< units
+ c
; u
++) {
1245 _cleanup_free_
char *e
= NULL
;
1246 const char *on
, *off
;
1249 if (u
->state
== UNIT_FILE_MASKED
||
1250 u
->state
== UNIT_FILE_MASKED_RUNTIME
||
1251 u
->state
== UNIT_FILE_DISABLED
||
1252 u
->state
== UNIT_FILE_INVALID
) {
1253 on
= ansi_highlight_red();
1254 off
= ansi_highlight_off();
1255 } else if (u
->state
== UNIT_FILE_ENABLED
) {
1256 on
= ansi_highlight_green();
1257 off
= ansi_highlight_off();
1261 id
= basename(u
->path
);
1263 e
= arg_full
? NULL
: ellipsize(id
, id_cols
, 33);
1265 printf("%-*s %s%-*s%s\n",
1266 id_cols
, e
? e
: id
,
1267 on
, state_cols
, unit_file_state_to_string(u
->state
), off
);
1271 printf("\n%u unit files listed.\n", c
);
1274 static int list_unit_files(sd_bus
*bus
, char **args
) {
1275 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1276 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1277 _cleanup_free_ UnitFileList
*units
= NULL
;
1285 pager_open_if_enabled();
1293 h
= hashmap_new(string_hash_func
, string_compare_func
);
1297 r
= unit_file_get_list(arg_scope
, arg_root
, h
);
1299 unit_file_list_free(h
);
1300 log_error("Failed to get unit file list: %s", strerror(-r
));
1304 n_units
= hashmap_size(h
);
1305 units
= new(UnitFileList
, n_units
);
1307 unit_file_list_free(h
);
1311 HASHMAP_FOREACH(u
, h
, i
) {
1312 if (!output_show_unit_file(u
, strv_skip_first(args
)))
1319 assert(c
<= n_units
);
1322 r
= sd_bus_call_method(
1324 "org.freedesktop.systemd1",
1325 "/org/freedesktop/systemd1",
1326 "org.freedesktop.systemd1.Manager",
1332 log_error("Failed to list unit files: %s", bus_error_message(&error
, r
));
1336 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
1338 return bus_log_parse_error(r
);
1340 while ((r
= sd_bus_message_read(reply
, "(ss)", &path
, &state
)) > 0) {
1342 if (!GREEDY_REALLOC(units
, size
, c
+ 1))
1345 units
[c
] = (struct UnitFileList
) {
1347 unit_file_state_from_string(state
)
1350 if (output_show_unit_file(&units
[c
], strv_skip_first(args
)))
1355 return bus_log_parse_error(r
);
1357 r
= sd_bus_message_exit_container(reply
);
1359 return bus_log_parse_error(r
);
1363 qsort(units
, c
, sizeof(UnitFileList
), compare_unit_file_list
);
1364 output_unit_file_list(units
, c
);
1368 for (unit
= units
; unit
< units
+ c
; unit
++)
1374 static int list_dependencies_print(const char *name
, int level
, unsigned int branches
, bool last
) {
1375 _cleanup_free_
char *n
= NULL
;
1376 size_t max_len
= MAX(columns(),20u);
1382 for (i
= level
- 1; i
>= 0; i
--) {
1384 if (len
> max_len
- 3 && !arg_full
) {
1385 printf("%s...\n",max_len
% 2 ? "" : " ");
1388 printf("%s", draw_special_char(branches
& (1 << i
) ? DRAW_TREE_VERT
: DRAW_TREE_SPACE
));
1392 if (len
> max_len
- 3 && !arg_full
) {
1393 printf("%s...\n",max_len
% 2 ? "" : " ");
1397 printf("%s", draw_special_char(last
? DRAW_TREE_RIGHT
: DRAW_TREE_BRANCH
));
1401 printf("%s\n", name
);
1405 n
= ellipsize(name
, max_len
-len
, 100);
1413 static int list_dependencies_get_dependencies(sd_bus
*bus
, const char *name
, char ***deps
) {
1415 static const char *dependencies
[_DEPENDENCY_MAX
] = {
1416 [DEPENDENCY_FORWARD
] = "Requires\0"
1417 "RequiresOverridable\0"
1419 "RequisiteOverridable\0"
1421 [DEPENDENCY_REVERSE
] = "RequiredBy\0"
1422 "RequiredByOverridable\0"
1425 [DEPENDENCY_AFTER
] = "After\0",
1426 [DEPENDENCY_BEFORE
] = "Before\0",
1429 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1430 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1431 _cleanup_strv_free_
char **ret
= NULL
;
1432 _cleanup_free_
char *path
= NULL
;
1438 assert_cc(ELEMENTSOF(dependencies
) == _DEPENDENCY_MAX
);
1440 path
= unit_dbus_path_from_name(name
);
1444 r
= sd_bus_call_method(
1446 "org.freedesktop.systemd1",
1448 "org.freedesktop.DBus.Properties",
1452 "s", "org.freedesktop.systemd1.Unit");
1454 log_error("Failed to get properties of %s: %s", name
, bus_error_message(&error
, r
));
1458 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
1460 return bus_log_parse_error(r
);
1462 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
1465 r
= sd_bus_message_read(reply
, "s", &prop
);
1467 return bus_log_parse_error(r
);
1469 if (!nulstr_contains(dependencies
[arg_dependency
], prop
)) {
1470 r
= sd_bus_message_skip(reply
, "v");
1472 return bus_log_parse_error(r
);
1475 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, "as");
1477 return bus_log_parse_error(r
);
1479 r
= bus_message_read_strv_extend(reply
, &ret
);
1481 return bus_log_parse_error(r
);
1483 r
= sd_bus_message_exit_container(reply
);
1485 return bus_log_parse_error(r
);
1488 r
= sd_bus_message_exit_container(reply
);
1490 return bus_log_parse_error(r
);
1494 return bus_log_parse_error(r
);
1496 r
= sd_bus_message_exit_container(reply
);
1498 return bus_log_parse_error(r
);
1506 static int list_dependencies_compare(const void *_a
, const void *_b
) {
1507 const char **a
= (const char**) _a
, **b
= (const char**) _b
;
1509 if (unit_name_to_type(*a
) == UNIT_TARGET
&& unit_name_to_type(*b
) != UNIT_TARGET
)
1511 if (unit_name_to_type(*a
) != UNIT_TARGET
&& unit_name_to_type(*b
) == UNIT_TARGET
)
1514 return strcasecmp(*a
, *b
);
1517 static int list_dependencies_one(
1522 unsigned int branches
) {
1524 _cleanup_strv_free_
char **deps
= NULL
;
1532 r
= strv_extend(units
, name
);
1536 r
= list_dependencies_get_dependencies(bus
, name
, &deps
);
1540 qsort_safe(deps
, strv_length(deps
), sizeof (char*), list_dependencies_compare
);
1542 STRV_FOREACH(c
, deps
) {
1545 if (strv_contains(*units
, *c
)) {
1547 r
= list_dependencies_print("...", level
+ 1, (branches
<< 1) | (c
[1] == NULL
? 0 : 1), 1);
1554 state
= check_one_unit(bus
, *c
, "activating\0active\0reloading\0", true);
1556 printf("%s%s%s", ansi_highlight_green(), draw_special_char(DRAW_BLACK_CIRCLE
), ansi_highlight_off());
1558 printf("%s%s%s", ansi_highlight_red(), draw_special_char(DRAW_BLACK_CIRCLE
), ansi_highlight_off());
1560 r
= list_dependencies_print(*c
, level
, branches
, c
[1] == NULL
);
1564 if (arg_all
|| unit_name_to_type(*c
) == UNIT_TARGET
) {
1565 r
= list_dependencies_one(bus
, *c
, level
+ 1, units
, (branches
<< 1) | (c
[1] == NULL
? 0 : 1));
1572 strv_remove(*units
, name
);
1577 static int list_dependencies(sd_bus
*bus
, char **args
) {
1578 _cleanup_strv_free_
char **units
= NULL
;
1579 _cleanup_free_
char *unit
= NULL
;
1585 unit
= unit_name_mangle(args
[1], MANGLE_NOGLOB
);
1590 u
= SPECIAL_DEFAULT_TARGET
;
1592 pager_open_if_enabled();
1596 return list_dependencies_one(bus
, u
, 0, &units
, 0);
1599 struct machine_info
{
1603 char *control_group
;
1604 uint32_t n_failed_units
;
1609 static const struct bus_properties_map machine_info_property_map
[] = {
1610 { "SystemState", "s", NULL
, offsetof(struct machine_info
, state
) },
1611 { "NJobs", "u", NULL
, offsetof(struct machine_info
, n_jobs
) },
1612 { "NFailedUnits", "u", NULL
, offsetof(struct machine_info
, n_failed_units
) },
1613 { "ControlGroup", "s", NULL
, offsetof(struct machine_info
, control_group
) },
1614 { "UserspaceTimestamp", "t", NULL
, offsetof(struct machine_info
, timestamp
) },
1618 static void free_machines_list(struct machine_info
*machine_infos
, int n
) {
1624 for (i
= 0; i
< n
; i
++) {
1625 free(machine_infos
[i
].name
);
1626 free(machine_infos
[i
].state
);
1627 free(machine_infos
[i
].control_group
);
1630 free(machine_infos
);
1633 static int compare_machine_info(const void *a
, const void *b
) {
1634 const struct machine_info
*u
= a
, *v
= b
;
1636 if (u
->is_host
!= v
->is_host
)
1637 return u
->is_host
> v
->is_host
? -1 : 1;
1639 return strcasecmp(u
->name
, v
->name
);
1642 static int get_machine_properties(sd_bus
*bus
, struct machine_info
*mi
) {
1643 _cleanup_bus_unref_ sd_bus
*container
= NULL
;
1649 r
= sd_bus_open_system_container(&container
, mi
->name
);
1656 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, mi
);
1663 static bool output_show_machine(const char *name
, char **patterns
) {
1668 if (strv_isempty(patterns
))
1671 STRV_FOREACH(i
, patterns
)
1672 if (fnmatch(*i
, name
, FNM_NOESCAPE
) == 0)
1678 static int get_machine_list(
1680 struct machine_info
**_machine_infos
,
1683 struct machine_info
*machine_infos
= NULL
;
1684 _cleanup_strv_free_
char **m
= NULL
;
1685 _cleanup_free_
char *hn
= NULL
;
1690 hn
= gethostname_malloc();
1694 if (output_show_machine(hn
, patterns
)) {
1695 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1))
1698 machine_infos
[c
].is_host
= true;
1699 machine_infos
[c
].name
= hn
;
1702 get_machine_properties(bus
, &machine_infos
[c
]);
1706 sd_get_machine_names(&m
);
1707 STRV_FOREACH(i
, m
) {
1708 _cleanup_free_
char *class = NULL
;
1710 if (!output_show_machine(*i
, patterns
))
1713 sd_machine_get_class(*i
, &class);
1714 if (!streq_ptr(class, "container"))
1717 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1)) {
1718 free_machines_list(machine_infos
, c
);
1722 machine_infos
[c
].is_host
= false;
1723 machine_infos
[c
].name
= strdup(*i
);
1724 if (!machine_infos
[c
].name
) {
1725 free_machines_list(machine_infos
, c
);
1729 get_machine_properties(NULL
, &machine_infos
[c
]);
1733 *_machine_infos
= machine_infos
;
1737 static void output_machines_list(struct machine_info
*machine_infos
, unsigned n
) {
1738 struct machine_info
*m
;
1741 namelen
= sizeof("NAME") - 1,
1742 statelen
= sizeof("STATE") - 1,
1743 failedlen
= sizeof("FAILED") - 1,
1744 jobslen
= sizeof("JOBS") - 1;
1746 assert(machine_infos
|| n
== 0);
1748 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
1749 namelen
= MAX(namelen
, strlen(m
->name
) + (m
->is_host
? sizeof(" (host)") - 1 : 0));
1750 statelen
= MAX(statelen
, m
->state
? strlen(m
->state
) : 0);
1751 failedlen
= MAX(failedlen
, DECIMAL_STR_WIDTH(m
->n_failed_units
));
1752 jobslen
= MAX(jobslen
, DECIMAL_STR_WIDTH(m
->n_jobs
));
1754 if (!arg_no_legend
&& !streq_ptr(m
->state
, "running"))
1758 if (!arg_no_legend
) {
1762 printf("%-*s %-*s %-*s %-*s\n",
1765 failedlen
, "FAILED",
1769 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
1770 const char *on_state
= "", *off_state
= "";
1771 const char *on_failed
= "", *off_failed
= "";
1772 bool circle
= false;
1774 if (streq_ptr(m
->state
, "degraded")) {
1775 on_state
= ansi_highlight_red();
1776 off_state
= ansi_highlight_off();
1778 } else if (!streq_ptr(m
->state
, "running")) {
1779 on_state
= ansi_highlight_yellow();
1780 off_state
= ansi_highlight_off();
1784 if (m
->n_failed_units
> 0) {
1785 on_failed
= ansi_highlight_red();
1786 off_failed
= ansi_highlight_off();
1788 on_failed
= off_failed
= "";
1791 printf("%s%s%s", on_state
, circle
? draw_special_char(DRAW_BLACK_CIRCLE
) : " ", off_state
);
1794 printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
1795 (int) (namelen
- (sizeof(" (host)")-1)), strna(m
->name
),
1796 on_state
, statelen
, strna(m
->state
), off_state
,
1797 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
1798 jobslen
, m
->n_jobs
);
1800 printf("%-*s %s%-*s%s %s%*u%s %*u\n",
1801 namelen
, strna(m
->name
),
1802 on_state
, statelen
, strna(m
->state
), off_state
,
1803 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
1804 jobslen
, m
->n_jobs
);
1808 printf("\n%u machines listed.\n", n
);
1811 static int list_machines(sd_bus
*bus
, char **args
) {
1812 struct machine_info
*machine_infos
= NULL
;
1817 if (geteuid() != 0) {
1818 log_error("Must be root.");
1822 pager_open_if_enabled();
1824 r
= get_machine_list(bus
, &machine_infos
, strv_skip_first(args
));
1828 qsort_safe(machine_infos
, r
, sizeof(struct machine_info
), compare_machine_info
);
1829 output_machines_list(machine_infos
, r
);
1830 free_machines_list(machine_infos
, r
);
1835 static int get_default(sd_bus
*bus
, char **args
) {
1836 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1837 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1838 _cleanup_free_
char *_path
= NULL
;
1842 if (!bus
|| avoid_bus()) {
1843 r
= unit_file_get_default(arg_scope
, arg_root
, &_path
);
1845 log_error("Failed to get default target: %s", strerror(-r
));
1851 r
= sd_bus_call_method(
1853 "org.freedesktop.systemd1",
1854 "/org/freedesktop/systemd1",
1855 "org.freedesktop.systemd1.Manager",
1861 log_error("Failed to get default target: %s", bus_error_message(&error
, -r
));
1865 r
= sd_bus_message_read(reply
, "s", &path
);
1867 return bus_log_parse_error(r
);
1871 printf("%s\n", path
);
1876 static void dump_unit_file_changes(const UnitFileChange
*changes
, unsigned n_changes
) {
1879 assert(changes
|| n_changes
== 0);
1881 for (i
= 0; i
< n_changes
; i
++) {
1882 if (changes
[i
].type
== UNIT_FILE_SYMLINK
)
1883 log_info("ln -s '%s' '%s'", changes
[i
].source
, changes
[i
].path
);
1885 log_info("rm '%s'", changes
[i
].path
);
1889 static int deserialize_and_dump_unit_file_changes(sd_bus_message
*m
) {
1890 const char *type
, *path
, *source
;
1893 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sss)");
1895 return bus_log_parse_error(r
);
1897 while ((r
= sd_bus_message_read(m
, "(sss)", &type
, &path
, &source
)) > 0) {
1899 if (streq(type
, "symlink"))
1900 log_info("ln -s '%s' '%s'", source
, path
);
1902 log_info("rm '%s'", path
);
1906 return bus_log_parse_error(r
);
1908 r
= sd_bus_message_exit_container(m
);
1910 return bus_log_parse_error(r
);
1915 static int set_default(sd_bus
*bus
, char **args
) {
1916 _cleanup_free_
char *unit
= NULL
;
1917 UnitFileChange
*changes
= NULL
;
1918 unsigned n_changes
= 0;
1921 unit
= unit_name_mangle_with_suffix(args
[1], MANGLE_NOGLOB
, ".target");
1925 if (!bus
|| avoid_bus()) {
1926 r
= unit_file_set_default(arg_scope
, arg_root
, unit
, arg_force
, &changes
, &n_changes
);
1928 log_error("Failed to set default target: %s", strerror(-r
));
1933 dump_unit_file_changes(changes
, n_changes
);
1937 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1938 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1940 r
= sd_bus_call_method(
1942 "org.freedesktop.systemd1",
1943 "/org/freedesktop/systemd1",
1944 "org.freedesktop.systemd1.Manager",
1948 "sb", unit
, arg_force
);
1950 log_error("Failed to set default target: %s", bus_error_message(&error
, -r
));
1954 r
= deserialize_and_dump_unit_file_changes(reply
);
1958 /* Try to reload if enabled */
1960 r
= daemon_reload(bus
, args
);
1965 unit_file_changes_free(changes
, n_changes
);
1972 const char *name
, *type
, *state
;
1975 static void output_jobs_list(const struct job_info
* jobs
, unsigned n
, bool skipped
) {
1976 unsigned id_len
, unit_len
, type_len
, state_len
;
1977 const struct job_info
*j
;
1978 const char *on
, *off
;
1979 bool shorten
= false;
1981 assert(n
== 0 || jobs
);
1984 on
= ansi_highlight_green();
1985 off
= ansi_highlight_off();
1987 printf("%sNo jobs %s.%s\n", on
, skipped
? "listed" : "running", off
);
1991 pager_open_if_enabled();
1993 id_len
= strlen("JOB");
1994 unit_len
= strlen("UNIT");
1995 type_len
= strlen("TYPE");
1996 state_len
= strlen("STATE");
1998 for (j
= jobs
; j
< jobs
+ n
; j
++) {
1999 uint32_t id
= j
->id
;
2000 assert(j
->name
&& j
->type
&& j
->state
);
2002 id_len
= MAX(id_len
, DECIMAL_STR_WIDTH(id
));
2003 unit_len
= MAX(unit_len
, strlen(j
->name
));
2004 type_len
= MAX(type_len
, strlen(j
->type
));
2005 state_len
= MAX(state_len
, strlen(j
->state
));
2008 if (!arg_full
&& id_len
+ 1 + unit_len
+ type_len
+ 1 + state_len
> columns()) {
2009 unit_len
= MAX(33u, columns() - id_len
- type_len
- state_len
- 3);
2014 printf("%*s %-*s %-*s %-*s\n",
2018 state_len
, "STATE");
2020 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2021 _cleanup_free_
char *e
= NULL
;
2023 if (streq(j
->state
, "running")) {
2024 on
= ansi_highlight();
2025 off
= ansi_highlight_off();
2029 e
= shorten
? ellipsize(j
->name
, unit_len
, 33) : NULL
;
2030 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2032 on
, unit_len
, e
? e
: j
->name
, off
,
2034 on
, state_len
, j
->state
, off
);
2037 if (!arg_no_legend
) {
2038 on
= ansi_highlight();
2039 off
= ansi_highlight_off();
2041 printf("\n%s%u jobs listed%s.\n", on
, n
, off
);
2045 static bool output_show_job(struct job_info
*job
, char **patterns
) {
2050 if (strv_isempty(patterns
))
2053 STRV_FOREACH(pattern
, patterns
)
2054 if (fnmatch(*pattern
, job
->name
, FNM_NOESCAPE
) == 0)
2059 static int list_jobs(sd_bus
*bus
, char **args
) {
2060 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2061 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2062 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2063 _cleanup_free_
struct job_info
*jobs
= NULL
;
2068 bool skipped
= false;
2070 r
= sd_bus_call_method(
2072 "org.freedesktop.systemd1",
2073 "/org/freedesktop/systemd1",
2074 "org.freedesktop.systemd1.Manager",
2080 log_error("Failed to list jobs: %s", bus_error_message(&error
, r
));
2084 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2086 return bus_log_parse_error(r
);
2088 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0) {
2089 struct job_info job
= { id
, name
, type
, state
};
2091 if (!output_show_job(&job
, strv_skip_first(args
))) {
2096 if (!GREEDY_REALLOC(jobs
, size
, c
+ 1))
2102 return bus_log_parse_error(r
);
2104 r
= sd_bus_message_exit_container(reply
);
2106 return bus_log_parse_error(r
);
2108 output_jobs_list(jobs
, c
, skipped
);
2112 static int cancel_job(sd_bus
*bus
, char **args
) {
2113 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2118 if (strv_length(args
) <= 1)
2119 return daemon_reload(bus
, args
);
2121 STRV_FOREACH(name
, args
+1) {
2125 r
= safe_atou32(*name
, &id
);
2127 log_error("Failed to parse job id \"%s\": %s", *name
, strerror(-r
));
2131 r
= sd_bus_call_method(
2133 "org.freedesktop.systemd1",
2134 "/org/freedesktop/systemd1",
2135 "org.freedesktop.systemd1.Manager",
2141 log_error("Failed to cancel job %u: %s", (unsigned) id
, bus_error_message(&error
, r
));
2149 static int need_daemon_reload(sd_bus
*bus
, const char *unit
) {
2150 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2154 /* We ignore all errors here, since this is used to show a
2157 /* We don't use unit_dbus_path_from_name() directly since we
2158 * don't want to load the unit if it isn't loaded. */
2160 r
= sd_bus_call_method(
2162 "org.freedesktop.systemd1",
2163 "/org/freedesktop/systemd1",
2164 "org.freedesktop.systemd1.Manager",
2172 r
= sd_bus_message_read(reply
, "o", &path
);
2176 r
= sd_bus_get_property_trivial(
2178 "org.freedesktop.systemd1",
2180 "org.freedesktop.systemd1.Unit",
2190 typedef struct WaitData
{
2197 static int wait_filter(sd_bus
*bus
, sd_bus_message
*m
, void *data
, sd_bus_error
*error
) {
2204 log_debug("Got D-Bus request: %s.%s() on %s",
2205 sd_bus_message_get_interface(m
),
2206 sd_bus_message_get_member(m
),
2207 sd_bus_message_get_path(m
));
2209 if (sd_bus_message_is_signal(m
, "org.freedesktop.DBus.Local", "Disconnected")) {
2210 log_error("Warning! D-Bus connection terminated.");
2212 } else if (sd_bus_message_is_signal(m
, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
2214 const char *path
, *result
, *unit
;
2218 r
= sd_bus_message_read(m
, "uoss", &id
, &path
, &unit
, &result
);
2220 ret
= set_remove(d
->set
, (char*) path
);
2226 if (!isempty(result
))
2227 d
->result
= strdup(result
);
2230 d
->name
= strdup(unit
);
2235 r
= sd_bus_message_read(m
, "uos", &id
, &path
, &result
);
2237 ret
= set_remove(d
->set
, (char*) path
);
2244 d
->result
= strdup(result
);
2250 bus_log_parse_error(r
);
2256 static int enable_wait_for_jobs(sd_bus
*bus
) {
2261 r
= sd_bus_add_match(
2264 "sender='org.freedesktop.systemd1',"
2265 "interface='org.freedesktop.systemd1.Manager',"
2266 "member='JobRemoved',"
2267 "path='/org/freedesktop/systemd1'",
2270 log_error("Failed to add match");
2274 /* This is slightly dirty, since we don't undo the match registrations. */
2278 static int bus_process_wait(sd_bus
*bus
) {
2282 r
= sd_bus_process(bus
, NULL
);
2287 r
= sd_bus_wait(bus
, (uint64_t) -1);
2293 static int check_wait_response(WaitData
*d
) {
2299 if (streq(d
->result
, "timeout"))
2300 log_error("Job for %s timed out.", strna(d
->name
));
2301 else if (streq(d
->result
, "canceled"))
2302 log_error("Job for %s canceled.", strna(d
->name
));
2303 else if (streq(d
->result
, "dependency"))
2304 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d
->name
));
2305 else if (!streq(d
->result
, "done") && !streq(d
->result
, "skipped"))
2306 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d
->name
), strna(d
->name
));
2309 if (streq(d
->result
, "timeout"))
2311 else if (streq(d
->result
, "canceled"))
2313 else if (streq(d
->result
, "dependency"))
2315 else if (!streq(d
->result
, "done") && !streq(d
->result
, "skipped"))
2321 static int wait_for_jobs(sd_bus
*bus
, Set
*s
) {
2322 WaitData d
= { .set
= s
};
2328 q
= sd_bus_add_filter(bus
, wait_filter
, &d
);
2332 while (!set_isempty(s
)) {
2333 q
= bus_process_wait(bus
);
2335 log_error("Failed to wait for response: %s", strerror(-r
));
2340 q
= check_wait_response(&d
);
2341 /* Return the first error as it is most likely to be
2343 if (q
< 0 && r
== 0)
2345 log_debug("Got result %s/%s for job %s",
2346 strna(d
.result
), strerror(-q
), strna(d
.name
));
2356 q
= sd_bus_remove_filter(bus
, wait_filter
, &d
);
2357 if (q
< 0 && r
== 0)
2363 static int check_one_unit(sd_bus
*bus
, const char *name
, const char *good_states
, bool quiet
) {
2364 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2365 _cleanup_free_
char *n
= NULL
, *state
= NULL
;
2371 n
= unit_name_mangle(name
, MANGLE_NOGLOB
);
2375 /* We don't use unit_dbus_path_from_name() directly since we
2376 * don't want to load the unit if it isn't loaded. */
2378 r
= sd_bus_call_method(
2380 "org.freedesktop.systemd1",
2381 "/org/freedesktop/systemd1",
2382 "org.freedesktop.systemd1.Manager",
2393 r
= sd_bus_message_read(reply
, "o", &path
);
2395 return bus_log_parse_error(r
);
2397 r
= sd_bus_get_property_string(
2399 "org.freedesktop.systemd1",
2401 "org.freedesktop.systemd1.Unit",
2414 return nulstr_contains(good_states
, state
);
2417 static int check_triggering_units(
2421 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2422 _cleanup_free_
char *path
= NULL
, *n
= NULL
, *state
= NULL
;
2423 _cleanup_strv_free_
char **triggered_by
= NULL
;
2424 bool print_warning_label
= true;
2428 n
= unit_name_mangle(name
, MANGLE_NOGLOB
);
2432 path
= unit_dbus_path_from_name(n
);
2436 r
= sd_bus_get_property_string(
2438 "org.freedesktop.systemd1",
2440 "org.freedesktop.systemd1.Unit",
2445 log_error("Failed to get load state of %s: %s", n
, bus_error_message(&error
, r
));
2449 if (streq(state
, "masked"))
2452 r
= sd_bus_get_property_strv(
2454 "org.freedesktop.systemd1",
2456 "org.freedesktop.systemd1.Unit",
2461 log_error("Failed to get triggered by array of %s: %s", n
, bus_error_message(&error
, r
));
2465 STRV_FOREACH(i
, triggered_by
) {
2466 r
= check_one_unit(bus
, *i
, "active\0reloading\0", true);
2468 log_error("Failed to check unit: %s", strerror(-r
));
2475 if (print_warning_label
) {
2476 log_warning("Warning: Stopping %s, but it can still be activated by:", n
);
2477 print_warning_label
= false;
2480 log_warning(" %s", *i
);
2486 static const char *verb_to_method(const char *verb
) {
2489 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2490 if (streq_ptr(unit_actions
[i
].verb
, verb
))
2491 return unit_actions
[i
].method
;
2496 static const char *method_to_verb(const char *method
) {
2499 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2500 if (streq_ptr(unit_actions
[i
].method
, method
))
2501 return unit_actions
[i
].verb
;
2506 static int start_unit_one(
2511 sd_bus_error
*error
,
2514 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2523 log_debug("Calling manager for %s on %s, %s", method
, name
, mode
);
2524 r
= sd_bus_call_method(
2526 "org.freedesktop.systemd1",
2527 "/org/freedesktop/systemd1",
2528 "org.freedesktop.systemd1.Manager",
2536 if (r
== -ENOENT
&& arg_action
!= ACTION_SYSTEMCTL
)
2537 /* There's always a fallback possible for
2538 * legacy actions. */
2539 return -EADDRNOTAVAIL
;
2541 verb
= method_to_verb(method
);
2543 log_error("Failed to %s %s: %s", verb
, name
, bus_error_message(error
, r
));
2547 r
= sd_bus_message_read(reply
, "o", &path
);
2549 return bus_log_parse_error(r
);
2551 if (need_daemon_reload(bus
, name
) > 0)
2552 log_warning("Warning: Unit file of %s changed on disk, 'systemctl%s daemon-reload' recommended.",
2553 name
, arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user");
2562 log_debug("Adding %s to the set", p
);
2563 r
= set_consume(s
, p
);
2571 static int expand_names(sd_bus
*bus
, char **names
, const char* suffix
, char ***ret
) {
2573 _cleanup_strv_free_
char **mangled
= NULL
, **globs
= NULL
;
2577 STRV_FOREACH(name
, names
) {
2581 t
= unit_name_mangle_with_suffix(*name
, MANGLE_GLOB
, suffix
);
2583 t
= unit_name_mangle(*name
, MANGLE_GLOB
);
2587 if (string_is_glob(t
))
2588 r
= strv_consume(&globs
, t
);
2590 r
= strv_consume(&mangled
, t
);
2595 /* Query the manager only if any of the names are a glob, since
2596 * this is fairly expensive */
2597 if (!strv_isempty(globs
)) {
2598 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2599 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
2601 r
= get_unit_list(bus
, NULL
, globs
, &unit_infos
, 0, &reply
);
2605 for (i
= 0; i
< r
; i
++)
2606 if (strv_extend(&mangled
, unit_infos
[i
].id
) < 0)
2611 mangled
= NULL
; /* do not free */
2616 static const struct {
2620 } action_table
[_ACTION_MAX
] = {
2621 [ACTION_HALT
] = { SPECIAL_HALT_TARGET
, "halt", "replace-irreversibly" },
2622 [ACTION_POWEROFF
] = { SPECIAL_POWEROFF_TARGET
, "poweroff", "replace-irreversibly" },
2623 [ACTION_REBOOT
] = { SPECIAL_REBOOT_TARGET
, "reboot", "replace-irreversibly" },
2624 [ACTION_KEXEC
] = { SPECIAL_KEXEC_TARGET
, "kexec", "replace-irreversibly" },
2625 [ACTION_RUNLEVEL2
] = { SPECIAL_RUNLEVEL2_TARGET
, NULL
, "isolate" },
2626 [ACTION_RUNLEVEL3
] = { SPECIAL_RUNLEVEL3_TARGET
, NULL
, "isolate" },
2627 [ACTION_RUNLEVEL4
] = { SPECIAL_RUNLEVEL4_TARGET
, NULL
, "isolate" },
2628 [ACTION_RUNLEVEL5
] = { SPECIAL_RUNLEVEL5_TARGET
, NULL
, "isolate" },
2629 [ACTION_RESCUE
] = { SPECIAL_RESCUE_TARGET
, "rescue", "isolate" },
2630 [ACTION_EMERGENCY
] = { SPECIAL_EMERGENCY_TARGET
, "emergency", "isolate" },
2631 [ACTION_DEFAULT
] = { SPECIAL_DEFAULT_TARGET
, "default", "isolate" },
2632 [ACTION_EXIT
] = { SPECIAL_EXIT_TARGET
, "exit", "replace-irreversibly" },
2633 [ACTION_SUSPEND
] = { SPECIAL_SUSPEND_TARGET
, "suspend", "replace-irreversibly" },
2634 [ACTION_HIBERNATE
] = { SPECIAL_HIBERNATE_TARGET
, "hibernate", "replace-irreversibly" },
2635 [ACTION_HYBRID_SLEEP
] = { SPECIAL_HYBRID_SLEEP_TARGET
, "hybrid-sleep", "replace-irreversibly" },
2638 static enum action
verb_to_action(const char *verb
) {
2641 for (i
= _ACTION_INVALID
; i
< _ACTION_MAX
; i
++)
2642 if (streq_ptr(action_table
[i
].verb
, verb
))
2645 return _ACTION_INVALID
;
2648 static int start_unit(sd_bus
*bus
, char **args
) {
2649 _cleanup_set_free_free_ Set
*s
= NULL
;
2650 _cleanup_strv_free_
char **names
= NULL
;
2651 const char *method
, *mode
, *one_name
;
2657 ask_password_agent_open_if_enabled();
2659 if (arg_action
== ACTION_SYSTEMCTL
) {
2661 method
= verb_to_method(args
[0]);
2662 action
= verb_to_action(args
[0]);
2664 mode
= streq(args
[0], "isolate") ? "isolate" :
2665 action_table
[action
].mode
?: arg_job_mode
;
2667 one_name
= action_table
[action
].target
;
2669 assert(arg_action
< ELEMENTSOF(action_table
));
2670 assert(action_table
[arg_action
].target
);
2672 method
= "StartUnit";
2674 mode
= action_table
[arg_action
].mode
;
2675 one_name
= action_table
[arg_action
].target
;
2679 names
= strv_new(one_name
, NULL
);
2681 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
2683 log_error("Failed to expand names: %s", strerror(-r
));
2686 if (!arg_no_block
) {
2687 r
= enable_wait_for_jobs(bus
);
2689 log_error("Could not watch jobs: %s", strerror(-r
));
2693 s
= set_new(string_hash_func
, string_compare_func
);
2698 STRV_FOREACH(name
, names
) {
2699 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2702 q
= start_unit_one(bus
, method
, *name
, mode
, &error
, s
);
2703 if (r
>= 0 && q
< 0)
2704 r
= translate_bus_error_to_exit_status(q
, &error
);
2707 if (!arg_no_block
) {
2710 q
= wait_for_jobs(bus
, s
);
2714 /* When stopping units, warn if they can still be triggered by
2715 * another active unit (socket, path, timer) */
2716 if (!arg_quiet
&& streq(method
, "StopUnit"))
2717 STRV_FOREACH(name
, names
)
2718 check_triggering_units(bus
, *name
);
2724 /* Ask systemd-logind, which might grant access to unprivileged users
2725 * through PolicyKit */
2726 static int reboot_with_logind(sd_bus
*bus
, enum action a
) {
2728 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2735 polkit_agent_open_if_enabled();
2743 case ACTION_POWEROFF
:
2744 method
= "PowerOff";
2747 case ACTION_SUSPEND
:
2751 case ACTION_HIBERNATE
:
2752 method
= "Hibernate";
2755 case ACTION_HYBRID_SLEEP
:
2756 method
= "HybridSleep";
2763 r
= sd_bus_call_method(
2765 "org.freedesktop.login1",
2766 "/org/freedesktop/login1",
2767 "org.freedesktop.login1.Manager",
2773 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
2781 static int check_inhibitors(sd_bus
*bus
, enum action a
) {
2783 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2784 _cleanup_strv_free_
char **sessions
= NULL
;
2785 const char *what
, *who
, *why
, *mode
;
2794 if (arg_ignore_inhibitors
|| arg_force
> 0)
2806 r
= sd_bus_call_method(
2808 "org.freedesktop.login1",
2809 "/org/freedesktop/login1",
2810 "org.freedesktop.login1.Manager",
2816 /* If logind is not around, then there are no inhibitors... */
2819 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssuu)");
2821 return bus_log_parse_error(r
);
2823 while ((r
= sd_bus_message_read(reply
, "(ssssuu)", &what
, &who
, &why
, &mode
, &uid
, &pid
)) > 0) {
2824 _cleanup_free_
char *comm
= NULL
, *user
= NULL
;
2825 _cleanup_strv_free_
char **sv
= NULL
;
2827 if (!streq(mode
, "block"))
2830 sv
= strv_split(what
, ":");
2834 if (!strv_contains(sv
,
2836 a
== ACTION_POWEROFF
||
2837 a
== ACTION_REBOOT
||
2838 a
== ACTION_KEXEC
? "shutdown" : "sleep"))
2841 get_process_comm(pid
, &comm
);
2842 user
= uid_to_name(uid
);
2844 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
2845 who
, (unsigned long) pid
, strna(comm
), strna(user
), why
);
2850 return bus_log_parse_error(r
);
2852 r
= sd_bus_message_exit_container(reply
);
2854 return bus_log_parse_error(r
);
2856 /* Check for current sessions */
2857 sd_get_sessions(&sessions
);
2858 STRV_FOREACH(s
, sessions
) {
2859 _cleanup_free_
char *type
= NULL
, *tty
= NULL
, *seat
= NULL
, *user
= NULL
, *service
= NULL
, *class = NULL
;
2861 if (sd_session_get_uid(*s
, &uid
) < 0 || uid
== getuid())
2864 if (sd_session_get_class(*s
, &class) < 0 || !streq(class, "user"))
2867 if (sd_session_get_type(*s
, &type
) < 0 || (!streq(type
, "x11") && !streq(type
, "tty")))
2870 sd_session_get_tty(*s
, &tty
);
2871 sd_session_get_seat(*s
, &seat
);
2872 sd_session_get_service(*s
, &service
);
2873 user
= uid_to_name(uid
);
2875 log_warning("User %s is logged in on %s.", strna(user
), isempty(tty
) ? (isempty(seat
) ? strna(service
) : seat
) : tty
);
2882 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2883 action_table
[a
].verb
);
2891 static int start_special(sd_bus
*bus
, char **args
) {
2897 a
= verb_to_action(args
[0]);
2899 r
= check_inhibitors(bus
, a
);
2903 if (arg_force
>= 2 && geteuid() != 0) {
2904 log_error("Must be root.");
2908 if (arg_force
>= 2 &&
2909 (a
== ACTION_HALT
||
2910 a
== ACTION_POWEROFF
||
2911 a
== ACTION_REBOOT
))
2914 if (arg_force
>= 1 &&
2915 (a
== ACTION_HALT
||
2916 a
== ACTION_POWEROFF
||
2917 a
== ACTION_REBOOT
||
2918 a
== ACTION_KEXEC
||
2920 return daemon_reload(bus
, args
);
2922 /* first try logind, to allow authentication with polkit */
2923 if (geteuid() != 0 &&
2924 (a
== ACTION_POWEROFF
||
2925 a
== ACTION_REBOOT
||
2926 a
== ACTION_SUSPEND
||
2927 a
== ACTION_HIBERNATE
||
2928 a
== ACTION_HYBRID_SLEEP
)) {
2929 r
= reboot_with_logind(bus
, a
);
2934 r
= start_unit(bus
, args
);
2935 if (r
== EXIT_SUCCESS
)
2941 static int check_unit_generic(sd_bus
*bus
, int code
, const char *good_states
, char **args
) {
2942 _cleanup_strv_free_
char **names
= NULL
;
2949 r
= expand_names(bus
, args
, NULL
, &names
);
2951 log_error("Failed to expand names: %s", strerror(-r
));
2955 STRV_FOREACH(name
, names
) {
2958 state
= check_one_unit(bus
, *name
, good_states
, arg_quiet
);
2968 static int check_unit_active(sd_bus
*bus
, char **args
) {
2969 /* According to LSB: 3, "program is not running" */
2970 return check_unit_generic(bus
, 3, "active\0reloading\0", args
+ 1);
2973 static int check_unit_failed(sd_bus
*bus
, char **args
) {
2974 return check_unit_generic(bus
, 1, "failed\0", args
+ 1);
2977 static int kill_unit(sd_bus
*bus
, char **args
) {
2978 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2979 _cleanup_strv_free_
char **names
= NULL
;
2987 arg_kill_who
= "all";
2989 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
2991 log_error("Failed to expand names: %s", strerror(-r
));
2993 STRV_FOREACH(name
, names
) {
2994 q
= sd_bus_call_method(
2996 "org.freedesktop.systemd1",
2997 "/org/freedesktop/systemd1",
2998 "org.freedesktop.systemd1.Manager",
3002 "ssi", *names
, arg_kill_who
, arg_signal
);
3004 log_error("Failed to kill unit %s: %s",
3005 *names
, bus_error_message(&error
, r
));
3014 typedef struct ExecStatusInfo
{
3022 usec_t start_timestamp
;
3023 usec_t exit_timestamp
;
3028 LIST_FIELDS(struct ExecStatusInfo
, exec
);
3031 static void exec_status_info_free(ExecStatusInfo
*i
) {
3040 static int exec_status_info_deserialize(sd_bus_message
*m
, ExecStatusInfo
*i
) {
3041 uint64_t start_timestamp
, exit_timestamp
, start_timestamp_monotonic
, exit_timestamp_monotonic
;
3044 int32_t code
, status
;
3050 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_STRUCT
, "sasbttttuii");
3052 return bus_log_parse_error(r
);
3056 r
= sd_bus_message_read(m
, "s", &path
);
3058 return bus_log_parse_error(r
);
3060 i
->path
= strdup(path
);
3064 r
= sd_bus_message_read_strv(m
, &i
->argv
);
3066 return bus_log_parse_error(r
);
3068 r
= sd_bus_message_read(m
,
3071 &start_timestamp
, &start_timestamp_monotonic
,
3072 &exit_timestamp
, &exit_timestamp_monotonic
,
3076 return bus_log_parse_error(r
);
3079 i
->start_timestamp
= (usec_t
) start_timestamp
;
3080 i
->exit_timestamp
= (usec_t
) exit_timestamp
;
3081 i
->pid
= (pid_t
) pid
;
3085 r
= sd_bus_message_exit_container(m
);
3087 return bus_log_parse_error(r
);
3092 typedef struct UnitStatusInfo
{
3094 const char *load_state
;
3095 const char *active_state
;
3096 const char *sub_state
;
3097 const char *unit_file_state
;
3099 const char *description
;
3100 const char *following
;
3102 char **documentation
;
3104 const char *fragment_path
;
3105 const char *source_path
;
3106 const char *control_group
;
3108 char **dropin_paths
;
3110 const char *load_error
;
3113 usec_t inactive_exit_timestamp
;
3114 usec_t inactive_exit_timestamp_monotonic
;
3115 usec_t active_enter_timestamp
;
3116 usec_t active_exit_timestamp
;
3117 usec_t inactive_enter_timestamp
;
3119 bool need_daemon_reload
;
3124 const char *status_text
;
3125 const char *pid_file
;
3128 usec_t start_timestamp
;
3129 usec_t exit_timestamp
;
3131 int exit_code
, exit_status
;
3133 usec_t condition_timestamp
;
3134 bool condition_result
;
3135 bool failed_condition_trigger
;
3136 bool failed_condition_negate
;
3137 const char *failed_condition
;
3138 const char *failed_condition_param
;
3141 unsigned n_accepted
;
3142 unsigned n_connections
;
3145 /* Pairs of type, path */
3149 const char *sysfs_path
;
3151 /* Mount, Automount */
3157 LIST_HEAD(ExecStatusInfo
, exec
);
3160 static void print_status_info(
3165 const char *active_on
, *active_off
, *on
, *off
, *ss
;
3167 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], *s1
;
3168 char since2
[FORMAT_TIMESTAMP_MAX
], *s2
;
3171 arg_all
* OUTPUT_SHOW_ALL
|
3172 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH
|
3173 on_tty() * OUTPUT_COLOR
|
3174 !arg_quiet
* OUTPUT_WARN_CUTOFF
|
3175 arg_full
* OUTPUT_FULL_WIDTH
;
3180 /* This shows pretty information about a unit. See
3181 * print_property() for a low-level property printer */
3183 if (streq_ptr(i
->active_state
, "failed")) {
3184 active_on
= ansi_highlight_red();
3185 active_off
= ansi_highlight_off();
3186 } else if (streq_ptr(i
->active_state
, "active") || streq_ptr(i
->active_state
, "reloading")) {
3187 active_on
= ansi_highlight_green();
3188 active_off
= ansi_highlight_off();
3190 active_on
= active_off
= "";
3192 printf("%s%s%s%s", active_on
, draw_special_char(DRAW_BLACK_CIRCLE
), active_off
, strna(i
->id
));
3194 if (i
->description
&& !streq_ptr(i
->id
, i
->description
))
3195 printf(" - %s", i
->description
);
3200 printf(" Follow: unit currently follows state of %s\n", i
->following
);
3202 if (streq_ptr(i
->load_state
, "error")) {
3203 on
= ansi_highlight_red();
3204 off
= ansi_highlight_off();
3208 path
= i
->source_path
? i
->source_path
: i
->fragment_path
;
3211 printf(" Loaded: %s%s%s (Reason: %s)\n",
3212 on
, strna(i
->load_state
), off
, i
->load_error
);
3213 else if (path
&& i
->unit_file_state
)
3214 printf(" Loaded: %s%s%s (%s; %s)\n",
3215 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
);
3217 printf(" Loaded: %s%s%s (%s)\n",
3218 on
, strna(i
->load_state
), off
, path
);
3220 printf(" Loaded: %s%s%s\n",
3221 on
, strna(i
->load_state
), off
);
3223 if (!strv_isempty(i
->dropin_paths
)) {
3224 _cleanup_free_
char *dir
= NULL
;
3228 STRV_FOREACH(dropin
, i
->dropin_paths
) {
3229 if (! dir
|| last
) {
3230 printf(dir
? " " : " Drop-In: ");
3235 if (path_get_parent(*dropin
, &dir
) < 0) {
3240 printf("%s\n %s", dir
,
3241 draw_special_char(DRAW_TREE_RIGHT
));
3244 last
= ! (*(dropin
+ 1) && startswith(*(dropin
+ 1), dir
));
3246 printf("%s%s", basename(*dropin
), last
? "\n" : ", ");
3250 ss
= streq_ptr(i
->active_state
, i
->sub_state
) ? NULL
: i
->sub_state
;
3252 printf(" Active: %s%s (%s)%s",
3253 active_on
, strna(i
->active_state
), ss
, active_off
);
3255 printf(" Active: %s%s%s",
3256 active_on
, strna(i
->active_state
), active_off
);
3258 if (!isempty(i
->result
) && !streq(i
->result
, "success"))
3259 printf(" (Result: %s)", i
->result
);
3261 timestamp
= (streq_ptr(i
->active_state
, "active") ||
3262 streq_ptr(i
->active_state
, "reloading")) ? i
->active_enter_timestamp
:
3263 (streq_ptr(i
->active_state
, "inactive") ||
3264 streq_ptr(i
->active_state
, "failed")) ? i
->inactive_enter_timestamp
:
3265 streq_ptr(i
->active_state
, "activating") ? i
->inactive_exit_timestamp
:
3266 i
->active_exit_timestamp
;
3268 s1
= format_timestamp_relative(since1
, sizeof(since1
), timestamp
);
3269 s2
= format_timestamp(since2
, sizeof(since2
), timestamp
);
3272 printf(" since %s; %s\n", s2
, s1
);
3274 printf(" since %s\n", s2
);
3278 if (!i
->condition_result
&& i
->condition_timestamp
> 0) {
3279 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->condition_timestamp
);
3280 s2
= format_timestamp(since2
, sizeof(since2
), i
->condition_timestamp
);
3282 printf(" start condition failed at %s%s%s\n",
3283 s2
, s1
? "; " : "", s1
? s1
: "");
3284 if (i
->failed_condition_trigger
)
3285 printf(" none of the trigger conditions were met\n");
3286 else if (i
->failed_condition
)
3287 printf(" %s=%s%s was not met\n",
3288 i
->failed_condition
,
3289 i
->failed_condition_negate
? "!" : "",
3290 i
->failed_condition_param
);
3294 printf(" Device: %s\n", i
->sysfs_path
);
3296 printf(" Where: %s\n", i
->where
);
3298 printf(" What: %s\n", i
->what
);
3300 STRV_FOREACH(t
, i
->documentation
)
3301 printf(" %*s %s\n", 9, t
== i
->documentation
? "Docs:" : "", *t
);
3303 STRV_FOREACH_PAIR(t
, t2
, i
->listen
)
3304 printf(" %*s %s (%s)\n", 9, t
== i
->listen
? "Listen:" : "", *t2
, *t
);
3307 printf(" Accepted: %u; Connected: %u\n", i
->n_accepted
, i
->n_connections
);
3309 LIST_FOREACH(exec
, p
, i
->exec
) {
3310 _cleanup_free_
char *argv
= NULL
;
3313 /* Only show exited processes here */
3317 argv
= strv_join(p
->argv
, " ");
3318 printf(" Process: %u %s=%s ", p
->pid
, p
->name
, strna(argv
));
3320 good
= is_clean_exit_lsb(p
->code
, p
->status
, NULL
);
3322 on
= ansi_highlight_red();
3323 off
= ansi_highlight_off();
3327 printf("%s(code=%s, ", on
, sigchld_code_to_string(p
->code
));
3329 if (p
->code
== CLD_EXITED
) {
3332 printf("status=%i", p
->status
);
3334 c
= exit_status_to_string(p
->status
, EXIT_STATUS_SYSTEMD
);
3339 printf("signal=%s", signal_to_string(p
->status
));
3341 printf(")%s\n", off
);
3343 if (i
->main_pid
== p
->pid
&&
3344 i
->start_timestamp
== p
->start_timestamp
&&
3345 i
->exit_timestamp
== p
->start_timestamp
)
3346 /* Let's not show this twice */
3349 if (p
->pid
== i
->control_pid
)
3353 if (i
->main_pid
> 0 || i
->control_pid
> 0) {
3354 if (i
->main_pid
> 0) {
3355 printf(" Main PID: %u", (unsigned) i
->main_pid
);
3358 _cleanup_free_
char *comm
= NULL
;
3359 get_process_comm(i
->main_pid
, &comm
);
3361 printf(" (%s)", comm
);
3362 } else if (i
->exit_code
> 0) {
3363 printf(" (code=%s, ", sigchld_code_to_string(i
->exit_code
));
3365 if (i
->exit_code
== CLD_EXITED
) {
3368 printf("status=%i", i
->exit_status
);
3370 c
= exit_status_to_string(i
->exit_status
, EXIT_STATUS_SYSTEMD
);
3375 printf("signal=%s", signal_to_string(i
->exit_status
));
3379 if (i
->control_pid
> 0)
3383 if (i
->control_pid
> 0) {
3384 _cleanup_free_
char *c
= NULL
;
3386 printf(" %8s: %u", i
->main_pid
? "" : " Control", (unsigned) i
->control_pid
);
3388 get_process_comm(i
->control_pid
, &c
);
3397 printf(" Status: \"%s\"\n", i
->status_text
);
3399 if (i
->control_group
&&
3400 (i
->main_pid
> 0 || i
->control_pid
> 0 ||
3401 ((arg_transport
!= BUS_TRANSPORT_LOCAL
&& arg_transport
!= BUS_TRANSPORT_CONTAINER
) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, false) == 0))) {
3404 printf(" CGroup: %s\n", i
->control_group
);
3406 if (arg_transport
== BUS_TRANSPORT_LOCAL
|| arg_transport
== BUS_TRANSPORT_CONTAINER
) {
3409 static const char prefix
[] = " ";
3412 if (c
> sizeof(prefix
) - 1)
3413 c
-= sizeof(prefix
) - 1;
3417 if (i
->main_pid
> 0)
3418 extra
[k
++] = i
->main_pid
;
3420 if (i
->control_pid
> 0)
3421 extra
[k
++] = i
->control_pid
;
3423 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, prefix
, c
, false, extra
, k
, flags
);
3427 if (i
->id
&& arg_transport
== BUS_TRANSPORT_LOCAL
) {
3428 show_journal_by_unit(stdout
,
3432 i
->inactive_exit_timestamp_monotonic
,
3435 flags
| OUTPUT_BEGIN_NEWLINE
,
3436 arg_scope
== UNIT_FILE_SYSTEM
,
3440 if (i
->need_daemon_reload
)
3441 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
3442 ansi_highlight_red(),
3443 ansi_highlight_off(),
3444 arg_scope
== UNIT_FILE_SYSTEM
? "" : "--user ");
3447 static void show_unit_help(UnitStatusInfo
*i
) {
3452 if (!i
->documentation
) {
3453 log_info("Documentation for %s not known.", i
->id
);
3457 STRV_FOREACH(p
, i
->documentation
) {
3459 if (startswith(*p
, "man:")) {
3460 const char *args
[4] = { "man", NULL
, NULL
, NULL
};
3461 _cleanup_free_
char *page
= NULL
, *section
= NULL
;
3468 if ((*p
)[k
-1] == ')')
3469 e
= strrchr(*p
, '(');
3472 page
= strndup((*p
) + 4, e
- *p
- 4);
3473 section
= strndup(e
+ 1, *p
+ k
- e
- 2);
3474 if (!page
|| !section
) {
3486 log_error("Failed to fork: %m");
3492 execvp(args
[0], (char**) args
);
3493 log_error("Failed to execute man: %m");
3494 _exit(EXIT_FAILURE
);
3497 wait_for_terminate(pid
, NULL
);
3499 log_info("Can't show: %s", *p
);
3503 static int status_property(const char *name
, sd_bus_message
*m
, UnitStatusInfo
*i
, const char *contents
) {
3510 switch (contents
[0]) {
3512 case SD_BUS_TYPE_STRING
: {
3515 r
= sd_bus_message_read(m
, "s", &s
);
3517 return bus_log_parse_error(r
);
3520 if (streq(name
, "Id"))
3522 else if (streq(name
, "LoadState"))
3524 else if (streq(name
, "ActiveState"))
3525 i
->active_state
= s
;
3526 else if (streq(name
, "SubState"))
3528 else if (streq(name
, "Description"))
3530 else if (streq(name
, "FragmentPath"))
3531 i
->fragment_path
= s
;
3532 else if (streq(name
, "SourcePath"))
3535 else if (streq(name
, "DefaultControlGroup")) {
3537 e
= startswith(s
, SYSTEMD_CGROUP_CONTROLLER
":");
3539 i
->control_group
= e
;
3542 else if (streq(name
, "ControlGroup"))
3543 i
->control_group
= s
;
3544 else if (streq(name
, "StatusText"))
3546 else if (streq(name
, "PIDFile"))
3548 else if (streq(name
, "SysFSPath"))
3550 else if (streq(name
, "Where"))
3552 else if (streq(name
, "What"))
3554 else if (streq(name
, "Following"))
3556 else if (streq(name
, "UnitFileState"))
3557 i
->unit_file_state
= s
;
3558 else if (streq(name
, "Result"))
3565 case SD_BUS_TYPE_BOOLEAN
: {
3568 r
= sd_bus_message_read(m
, "b", &b
);
3570 return bus_log_parse_error(r
);
3572 if (streq(name
, "Accept"))
3574 else if (streq(name
, "NeedDaemonReload"))
3575 i
->need_daemon_reload
= b
;
3576 else if (streq(name
, "ConditionResult"))
3577 i
->condition_result
= b
;
3582 case SD_BUS_TYPE_UINT32
: {
3585 r
= sd_bus_message_read(m
, "u", &u
);
3587 return bus_log_parse_error(r
);
3589 if (streq(name
, "MainPID")) {
3591 i
->main_pid
= (pid_t
) u
;
3594 } else if (streq(name
, "ControlPID"))
3595 i
->control_pid
= (pid_t
) u
;
3596 else if (streq(name
, "ExecMainPID")) {
3598 i
->main_pid
= (pid_t
) u
;
3599 } else if (streq(name
, "NAccepted"))
3601 else if (streq(name
, "NConnections"))
3602 i
->n_connections
= u
;
3607 case SD_BUS_TYPE_INT32
: {
3610 r
= sd_bus_message_read(m
, "i", &j
);
3612 return bus_log_parse_error(r
);
3614 if (streq(name
, "ExecMainCode"))
3615 i
->exit_code
= (int) j
;
3616 else if (streq(name
, "ExecMainStatus"))
3617 i
->exit_status
= (int) j
;
3622 case SD_BUS_TYPE_UINT64
: {
3625 r
= sd_bus_message_read(m
, "t", &u
);
3627 return bus_log_parse_error(r
);
3629 if (streq(name
, "ExecMainStartTimestamp"))
3630 i
->start_timestamp
= (usec_t
) u
;
3631 else if (streq(name
, "ExecMainExitTimestamp"))
3632 i
->exit_timestamp
= (usec_t
) u
;
3633 else if (streq(name
, "ActiveEnterTimestamp"))
3634 i
->active_enter_timestamp
= (usec_t
) u
;
3635 else if (streq(name
, "InactiveEnterTimestamp"))
3636 i
->inactive_enter_timestamp
= (usec_t
) u
;
3637 else if (streq(name
, "InactiveExitTimestamp"))
3638 i
->inactive_exit_timestamp
= (usec_t
) u
;
3639 else if (streq(name
, "InactiveExitTimestampMonotonic"))
3640 i
->inactive_exit_timestamp_monotonic
= (usec_t
) u
;
3641 else if (streq(name
, "ActiveExitTimestamp"))
3642 i
->active_exit_timestamp
= (usec_t
) u
;
3643 else if (streq(name
, "ConditionTimestamp"))
3644 i
->condition_timestamp
= (usec_t
) u
;
3649 case SD_BUS_TYPE_ARRAY
:
3651 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
3652 _cleanup_free_ ExecStatusInfo
*info
= NULL
;
3654 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
3656 return bus_log_parse_error(r
);
3658 info
= new0(ExecStatusInfo
, 1);
3662 while ((r
= exec_status_info_deserialize(m
, info
)) > 0) {
3664 info
->name
= strdup(name
);
3668 LIST_PREPEND(exec
, i
->exec
, info
);
3670 info
= new0(ExecStatusInfo
, 1);
3676 return bus_log_parse_error(r
);
3678 r
= sd_bus_message_exit_container(m
);
3680 return bus_log_parse_error(r
);
3684 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
3685 const char *type
, *path
;
3687 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
3689 return bus_log_parse_error(r
);
3691 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0) {
3693 r
= strv_extend(&i
->listen
, type
);
3697 r
= strv_extend(&i
->listen
, path
);
3702 return bus_log_parse_error(r
);
3704 r
= sd_bus_message_exit_container(m
);
3706 return bus_log_parse_error(r
);
3710 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "DropInPaths")) {
3712 r
= sd_bus_message_read_strv(m
, &i
->dropin_paths
);
3714 return bus_log_parse_error(r
);
3716 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Documentation")) {
3718 r
= sd_bus_message_read_strv(m
, &i
->documentation
);
3720 return bus_log_parse_error(r
);
3722 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Conditions")) {
3723 const char *cond
, *param
;
3724 int trigger
, negate
;
3727 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
3729 return bus_log_parse_error(r
);
3731 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
3732 log_debug("%s %d %d %s %d", cond
, trigger
, negate
, param
, state
);
3733 if (state
< 0 && (!trigger
|| !i
->failed_condition
)) {
3734 i
->failed_condition
= cond
;
3735 i
->failed_condition_trigger
= trigger
;
3736 i
->failed_condition_negate
= negate
;
3737 i
->failed_condition_param
= param
;
3741 return bus_log_parse_error(r
);
3743 r
= sd_bus_message_exit_container(m
);
3745 return bus_log_parse_error(r
);
3752 case SD_BUS_TYPE_STRUCT_BEGIN
:
3754 if (streq(name
, "LoadError")) {
3755 const char *n
, *message
;
3757 r
= sd_bus_message_read(m
, "(ss)", &n
, &message
);
3759 return bus_log_parse_error(r
);
3761 if (!isempty(message
))
3762 i
->load_error
= message
;
3775 r
= sd_bus_message_skip(m
, contents
);
3777 return bus_log_parse_error(r
);
3782 static int print_property(const char *name
, sd_bus_message
*m
, const char *contents
) {
3788 /* This is a low-level property printer, see
3789 * print_status_info() for the nicer output */
3791 if (arg_properties
&& !strv_find(arg_properties
, name
)) {
3792 /* skip what we didn't read */
3793 r
= sd_bus_message_skip(m
, contents
);
3797 switch (contents
[0]) {
3799 case SD_BUS_TYPE_STRUCT_BEGIN
:
3801 if (contents
[1] == SD_BUS_TYPE_UINT32
&& streq(name
, "Job")) {
3804 r
= sd_bus_message_read(m
, "(uo)", &u
, NULL
);
3806 return bus_log_parse_error(r
);
3809 printf("%s=%u\n", name
, (unsigned) u
);
3811 printf("%s=\n", name
);
3815 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Unit")) {
3818 r
= sd_bus_message_read(m
, "(so)", &s
, NULL
);
3820 return bus_log_parse_error(r
);
3822 if (arg_all
|| !isempty(s
))
3823 printf("%s=%s\n", name
, s
);
3827 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "LoadError")) {
3828 const char *a
= NULL
, *b
= NULL
;
3830 r
= sd_bus_message_read(m
, "(ss)", &a
, &b
);
3832 return bus_log_parse_error(r
);
3834 if (arg_all
|| !isempty(a
) || !isempty(b
))
3835 printf("%s=%s \"%s\"\n", name
, strempty(a
), strempty(b
));
3838 } else if (streq_ptr(name
, "SystemCallFilter")) {
3839 _cleanup_strv_free_
char **l
= NULL
;
3842 r
= sd_bus_message_enter_container(m
, 'r', "bas");
3844 return bus_log_parse_error(r
);
3846 r
= sd_bus_message_read(m
, "b", &whitelist
);
3848 return bus_log_parse_error(r
);
3850 r
= sd_bus_message_read_strv(m
, &l
);
3852 return bus_log_parse_error(r
);
3854 r
= sd_bus_message_exit_container(m
);
3856 return bus_log_parse_error(r
);
3858 if (arg_all
|| whitelist
|| !strv_isempty(l
)) {
3862 fputs(name
, stdout
);
3868 STRV_FOREACH(i
, l
) {
3876 fputc('\n', stdout
);
3884 case SD_BUS_TYPE_ARRAY
:
3886 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "EnvironmentFiles")) {
3890 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sb)");
3892 return bus_log_parse_error(r
);
3894 while ((r
= sd_bus_message_read(m
, "(sb)", &path
, &ignore
)) > 0)
3895 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path
, yes_no(ignore
));
3898 return bus_log_parse_error(r
);
3900 r
= sd_bus_message_exit_container(m
);
3902 return bus_log_parse_error(r
);
3906 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Paths")) {
3907 const char *type
, *path
;
3909 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
3911 return bus_log_parse_error(r
);
3913 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
3914 printf("%s=%s\n", type
, path
);
3916 return bus_log_parse_error(r
);
3918 r
= sd_bus_message_exit_container(m
);
3920 return bus_log_parse_error(r
);
3924 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
3925 const char *type
, *path
;
3927 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
3929 return bus_log_parse_error(r
);
3931 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
3932 printf("Listen%s=%s\n", type
, path
);
3934 return bus_log_parse_error(r
);
3936 r
= sd_bus_message_exit_container(m
);
3938 return bus_log_parse_error(r
);
3942 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Timers")) {
3944 uint64_t value
, next_elapse
;
3946 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(stt)");
3948 return bus_log_parse_error(r
);
3950 while ((r
= sd_bus_message_read(m
, "(stt)", &base
, &value
, &next_elapse
)) > 0) {
3951 char timespan1
[FORMAT_TIMESPAN_MAX
], timespan2
[FORMAT_TIMESPAN_MAX
];
3953 printf("%s={ value=%s ; next_elapse=%s }\n",
3955 format_timespan(timespan1
, sizeof(timespan1
), value
, 0),
3956 format_timespan(timespan2
, sizeof(timespan2
), next_elapse
, 0));
3959 return bus_log_parse_error(r
);
3961 r
= sd_bus_message_exit_container(m
);
3963 return bus_log_parse_error(r
);
3967 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
3968 ExecStatusInfo info
= {};
3970 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
3972 return bus_log_parse_error(r
);
3974 while ((r
= exec_status_info_deserialize(m
, &info
)) > 0) {
3975 char timestamp1
[FORMAT_TIMESTAMP_MAX
], timestamp2
[FORMAT_TIMESTAMP_MAX
];
3976 _cleanup_free_
char *tt
;
3978 tt
= strv_join(info
.argv
, " ");
3980 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3984 yes_no(info
.ignore
),
3985 strna(format_timestamp(timestamp1
, sizeof(timestamp1
), info
.start_timestamp
)),
3986 strna(format_timestamp(timestamp2
, sizeof(timestamp2
), info
.exit_timestamp
)),
3987 (unsigned) info
. pid
,
3988 sigchld_code_to_string(info
.code
),
3990 info
.code
== CLD_EXITED
? "" : "/",
3991 strempty(info
.code
== CLD_EXITED
? NULL
: signal_to_string(info
.status
)));
3994 strv_free(info
.argv
);
3998 r
= sd_bus_message_exit_container(m
);
4000 return bus_log_parse_error(r
);
4004 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "DeviceAllow")) {
4005 const char *path
, *rwm
;
4007 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4009 return bus_log_parse_error(r
);
4011 while ((r
= sd_bus_message_read(m
, "(ss)", &path
, &rwm
)) > 0)
4012 printf("%s=%s %s\n", name
, strna(path
), strna(rwm
));
4014 return bus_log_parse_error(r
);
4016 r
= sd_bus_message_exit_container(m
);
4018 return bus_log_parse_error(r
);
4022 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "BlockIODeviceWeight")) {
4026 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4028 return bus_log_parse_error(r
);
4030 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &weight
)) > 0)
4031 printf("%s=%s %" PRIu64
"\n", name
, strna(path
), weight
);
4033 return bus_log_parse_error(r
);
4035 r
= sd_bus_message_exit_container(m
);
4037 return bus_log_parse_error(r
);
4041 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& (streq(name
, "BlockIOReadBandwidth") || streq(name
, "BlockIOWriteBandwidth"))) {
4045 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4047 return bus_log_parse_error(r
);
4049 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &bandwidth
)) > 0)
4050 printf("%s=%s %" PRIu64
"\n", name
, strna(path
), bandwidth
);
4052 return bus_log_parse_error(r
);
4054 r
= sd_bus_message_exit_container(m
);
4056 return bus_log_parse_error(r
);
4064 r
= bus_print_property(name
, m
, arg_all
);
4066 return bus_log_parse_error(r
);
4069 r
= sd_bus_message_skip(m
, contents
);
4071 return bus_log_parse_error(r
);
4074 printf("%s=[unprintable]\n", name
);
4080 static int show_one(
4084 bool show_properties
,
4088 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4089 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4090 UnitStatusInfo info
= {};
4097 log_debug("Showing one %s", path
);
4099 r
= sd_bus_call_method(
4101 "org.freedesktop.systemd1",
4103 "org.freedesktop.DBus.Properties",
4109 log_error("Failed to get properties: %s", bus_error_message(&error
, r
));
4113 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
4115 return bus_log_parse_error(r
);
4122 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
4123 const char *name
, *contents
;
4125 r
= sd_bus_message_read(reply
, "s", &name
);
4127 return bus_log_parse_error(r
);
4129 r
= sd_bus_message_peek_type(reply
, NULL
, &contents
);
4131 return bus_log_parse_error(r
);
4133 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, contents
);
4135 return bus_log_parse_error(r
);
4137 if (show_properties
)
4138 r
= print_property(name
, reply
, contents
);
4140 r
= status_property(name
, reply
, &info
, contents
);
4144 r
= sd_bus_message_exit_container(reply
);
4146 return bus_log_parse_error(r
);
4148 r
= sd_bus_message_exit_container(reply
);
4150 return bus_log_parse_error(r
);
4153 return bus_log_parse_error(r
);
4155 r
= sd_bus_message_exit_container(reply
);
4157 return bus_log_parse_error(r
);
4161 if (!show_properties
) {
4162 if (streq(verb
, "help"))
4163 show_unit_help(&info
);
4165 print_status_info(&info
, ellipsized
);
4168 strv_free(info
.documentation
);
4169 strv_free(info
.dropin_paths
);
4170 strv_free(info
.listen
);
4172 if (!streq_ptr(info
.active_state
, "active") &&
4173 !streq_ptr(info
.active_state
, "reloading") &&
4174 streq(verb
, "status")) {
4175 /* According to LSB: "program not running" */
4176 /* 0: program is running or service is OK
4177 * 1: program is dead and /run PID file exists
4178 * 2: program is dead and /run/lock lock file exists
4179 * 3: program is not running
4180 * 4: program or service status is unknown
4182 if (info
.pid_file
&& access(info
.pid_file
, F_OK
) == 0)
4188 while ((p
= info
.exec
)) {
4189 LIST_REMOVE(exec
, info
.exec
, p
);
4190 exec_status_info_free(p
);
4196 static int get_unit_dbus_path_by_pid(
4201 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4202 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4206 r
= sd_bus_call_method(
4208 "org.freedesktop.systemd1",
4209 "/org/freedesktop/systemd1",
4210 "org.freedesktop.systemd1.Manager",
4216 log_error("Failed to get unit for PID %lu: %s", (unsigned long) pid
, bus_error_message(&error
, r
));
4220 r
= sd_bus_message_read(reply
, "o", &u
);
4222 return bus_log_parse_error(r
);
4232 static int show_all(
4235 bool show_properties
,
4239 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4240 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
4245 r
= get_unit_list(bus
, NULL
, NULL
, &unit_infos
, 0, &reply
);
4249 pager_open_if_enabled();
4253 qsort_safe(unit_infos
, c
, sizeof(UnitInfo
), compare_unit_info
);
4255 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
4256 _cleanup_free_
char *p
= NULL
;
4258 p
= unit_dbus_path_from_name(u
->id
);
4262 r
= show_one(verb
, bus
, p
, show_properties
, new_line
, ellipsized
);
4270 static int show_system_status(sd_bus
*bus
) {
4271 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], since2
[FORMAT_TIMESTAMP_MAX
];
4272 _cleanup_free_
char *hn
= NULL
;
4273 struct machine_info mi
= {};
4274 const char *on
, *off
;
4277 hn
= gethostname_malloc();
4281 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, &mi
);
4283 log_error("Failed to read server status: %s", strerror(-r
));
4287 if (streq_ptr(mi
.state
, "degraded")) {
4288 on
= ansi_highlight_red();
4289 off
= ansi_highlight_off();
4290 } else if (!streq_ptr(mi
.state
, "running")) {
4291 on
= ansi_highlight_yellow();
4292 off
= ansi_highlight_off();
4296 printf("%s%s%s%s\n", on
, draw_special_char(DRAW_BLACK_CIRCLE
), off
, arg_host
? arg_host
: hn
);
4298 printf(" State: %s%s%s\n",
4299 on
, strna(mi
.state
), off
);
4301 printf(" Jobs: %u queued\n", mi
.n_jobs
);
4302 printf(" Failed: %u units\n", mi
.n_failed_units
);
4304 printf(" Since: %s; %s\n",
4305 format_timestamp(since2
, sizeof(since2
), mi
.timestamp
),
4306 format_timestamp_relative(since1
, sizeof(since1
), mi
.timestamp
));
4308 printf(" CGroup: %s\n", mi
.control_group
?: "/");
4309 if (arg_transport
== BUS_TRANSPORT_LOCAL
|| arg_transport
== BUS_TRANSPORT_CONTAINER
) {
4311 arg_all
* OUTPUT_SHOW_ALL
|
4312 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH
|
4313 on_tty() * OUTPUT_COLOR
|
4314 !arg_quiet
* OUTPUT_WARN_CUTOFF
|
4315 arg_full
* OUTPUT_FULL_WIDTH
;
4317 static const char prefix
[] = " ";
4321 if (c
> sizeof(prefix
) - 1)
4322 c
-= sizeof(prefix
) - 1;
4326 show_cgroup(SYSTEMD_CGROUP_CONTROLLER
, strempty(mi
.control_group
), prefix
, c
, false, flags
);
4330 free(mi
.control_group
);
4335 static int show(sd_bus
*bus
, char **args
) {
4336 bool show_properties
, show_status
, new_line
= false;
4337 bool ellipsized
= false;
4343 show_properties
= streq(args
[0], "show");
4344 show_status
= streq(args
[0], "status");
4346 if (show_properties
)
4347 pager_open_if_enabled();
4349 /* If no argument is specified inspect the manager itself */
4351 if (show_properties
&& strv_length(args
) <= 1)
4352 return show_one(args
[0], bus
, "/org/freedesktop/systemd1", show_properties
, &new_line
, &ellipsized
);
4354 if (show_status
&& strv_length(args
) <= 1) {
4356 pager_open_if_enabled();
4357 show_system_status(bus
);
4361 ret
= show_all(args
[0], bus
, false, &new_line
, &ellipsized
);
4363 _cleanup_free_
char **patterns
= NULL
;
4366 STRV_FOREACH(name
, args
+ 1) {
4367 _cleanup_free_
char *unit
= NULL
;
4370 if (safe_atou32(*name
, &id
) < 0) {
4371 if (strv_push(&patterns
, *name
) < 0)
4375 } else if (show_properties
) {
4376 /* Interpret as job id */
4377 if (asprintf(&unit
, "/org/freedesktop/systemd1/job/%u", id
) < 0)
4381 /* Interpret as PID */
4382 r
= get_unit_dbus_path_by_pid(bus
, id
, &unit
);
4389 show_one(args
[0], bus
, unit
, show_properties
, &new_line
, &ellipsized
);
4392 if (!strv_isempty(patterns
)) {
4393 _cleanup_strv_free_
char **names
= NULL
;
4395 r
= expand_names(bus
, patterns
, NULL
, &names
);
4397 log_error("Failed to expand names: %s", strerror(-r
));
4399 STRV_FOREACH(name
, names
) {
4400 _cleanup_free_
char *unit
;
4402 unit
= unit_dbus_path_from_name(*name
);
4406 show_one(args
[0], bus
, unit
, show_properties
, &new_line
, &ellipsized
);
4411 if (ellipsized
&& !arg_quiet
)
4412 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4417 static int cat(sd_bus
*bus
, char **args
) {
4418 _cleanup_free_
char *unit
= NULL
;
4419 _cleanup_strv_free_
char **names
= NULL
;
4427 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
4429 log_error("Failed to expand names: %s", strerror(-r
));
4431 pager_open_if_enabled();
4433 STRV_FOREACH(name
, names
) {
4434 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4435 _cleanup_strv_free_
char **dropin_paths
= NULL
;
4436 _cleanup_free_
char *fragment_path
= NULL
;
4439 unit
= unit_dbus_path_from_name(*name
);
4443 if (need_daemon_reload(bus
, *name
) > 0)
4444 log_warning("Unit file of %s changed on disk. Run 'systemctl%s daemon-reload'.",
4445 *name
, arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user");
4447 r
= sd_bus_get_property_string(
4449 "org.freedesktop.systemd1",
4451 "org.freedesktop.systemd1.Unit",
4456 log_warning("Failed to get FragmentPath: %s", bus_error_message(&error
, r
));
4460 r
= sd_bus_get_property_strv(
4462 "org.freedesktop.systemd1",
4464 "org.freedesktop.systemd1.Unit",
4469 log_warning("Failed to get DropInPaths: %s", bus_error_message(&error
, r
));
4478 if (!isempty(fragment_path
)) {
4479 printf("%s# %s%s\n",
4480 ansi_highlight_blue(),
4482 ansi_highlight_off());
4485 r
= sendfile_full(STDOUT_FILENO
, fragment_path
);
4487 log_warning("Failed to cat %s: %s", fragment_path
, strerror(-r
));
4492 STRV_FOREACH(path
, dropin_paths
) {
4493 printf("%s%s# %s%s\n",
4494 isempty(fragment_path
) && path
== dropin_paths
? "" : "\n",
4495 ansi_highlight_blue(),
4497 ansi_highlight_off());
4500 r
= sendfile_full(STDOUT_FILENO
, *path
);
4502 log_warning("Failed to cat %s: %s", *path
, strerror(-r
));
4508 return r
< 0 ? r
: 0;
4511 static int set_property(sd_bus
*bus
, char **args
) {
4512 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
4513 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4514 _cleanup_free_
char *n
= NULL
;
4518 r
= sd_bus_message_new_method_call(
4521 "org.freedesktop.systemd1",
4522 "/org/freedesktop/systemd1",
4523 "org.freedesktop.systemd1.Manager",
4524 "SetUnitProperties");
4526 return bus_log_create_error(r
);
4528 n
= unit_name_mangle(args
[1], MANGLE_NOGLOB
);
4532 r
= sd_bus_message_append(m
, "sb", n
, arg_runtime
);
4534 return bus_log_create_error(r
);
4536 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, "(sv)");
4538 return bus_log_create_error(r
);
4540 STRV_FOREACH(i
, args
+ 2) {
4541 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_STRUCT
, "sv");
4543 return bus_log_create_error(r
);
4545 r
= bus_append_unit_property_assignment(m
, *i
);
4549 r
= sd_bus_message_close_container(m
);
4551 return bus_log_create_error(r
);
4554 r
= sd_bus_message_close_container(m
);
4556 return bus_log_create_error(r
);
4558 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
4560 log_error("Failed to set unit properties on %s: %s", n
, bus_error_message(&error
, r
));
4567 static int snapshot(sd_bus
*bus
, char **args
) {
4568 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4569 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4570 _cleanup_free_
char *n
= NULL
, *id
= NULL
;
4574 if (strv_length(args
) > 1)
4575 n
= unit_name_mangle_with_suffix(args
[1], MANGLE_NOGLOB
, ".snapshot");
4581 r
= sd_bus_call_method(
4583 "org.freedesktop.systemd1",
4584 "/org/freedesktop/systemd1",
4585 "org.freedesktop.systemd1.Manager",
4591 log_error("Failed to create snapshot: %s", bus_error_message(&error
, r
));
4595 r
= sd_bus_message_read(reply
, "o", &path
);
4597 return bus_log_parse_error(r
);
4599 r
= sd_bus_get_property_string(
4601 "org.freedesktop.systemd1",
4603 "org.freedesktop.systemd1.Unit",
4608 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error
, r
));
4618 static int delete_snapshot(sd_bus
*bus
, char **args
) {
4619 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4620 _cleanup_strv_free_
char **names
= NULL
;
4626 r
= expand_names(bus
, args
+ 1, ".snapshot", &names
);
4628 log_error("Failed to expand names: %s", strerror(-r
));
4630 STRV_FOREACH(name
, names
) {
4631 q
= sd_bus_call_method(
4633 "org.freedesktop.systemd1",
4634 "/org/freedesktop/systemd1",
4635 "org.freedesktop.systemd1.Manager",
4641 log_error("Failed to remove snapshot %s: %s",
4642 *name
, bus_error_message(&error
, r
));
4651 static int daemon_reload(sd_bus
*bus
, char **args
) {
4652 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4656 if (arg_action
== ACTION_RELOAD
)
4658 else if (arg_action
== ACTION_REEXEC
)
4659 method
= "Reexecute";
4661 assert(arg_action
== ACTION_SYSTEMCTL
);
4664 streq(args
[0], "clear-jobs") ||
4665 streq(args
[0], "cancel") ? "ClearJobs" :
4666 streq(args
[0], "daemon-reexec") ? "Reexecute" :
4667 streq(args
[0], "reset-failed") ? "ResetFailed" :
4668 streq(args
[0], "halt") ? "Halt" :
4669 streq(args
[0], "poweroff") ? "PowerOff" :
4670 streq(args
[0], "reboot") ? "Reboot" :
4671 streq(args
[0], "kexec") ? "KExec" :
4672 streq(args
[0], "exit") ? "Exit" :
4673 /* "daemon-reload" */ "Reload";
4676 r
= sd_bus_call_method(
4678 "org.freedesktop.systemd1",
4679 "/org/freedesktop/systemd1",
4680 "org.freedesktop.systemd1.Manager",
4686 if (r
== -ENOENT
&& arg_action
!= ACTION_SYSTEMCTL
)
4687 /* There's always a fallback possible for
4688 * legacy actions. */
4690 else if ((r
== -ETIMEDOUT
|| r
== -ECONNRESET
) && streq(method
, "Reexecute"))
4691 /* On reexecution, we expect a disconnect, not a
4695 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
4697 return r
< 0 ? r
: 0;
4700 static int reset_failed(sd_bus
*bus
, char **args
) {
4701 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4702 _cleanup_strv_free_
char **names
= NULL
;
4706 if (strv_length(args
) <= 1)
4707 return daemon_reload(bus
, args
);
4709 r
= expand_names(bus
, args
+ 1, NULL
, &names
);
4711 log_error("Failed to expand names: %s", strerror(-r
));
4713 STRV_FOREACH(name
, names
) {
4714 q
= sd_bus_call_method(
4716 "org.freedesktop.systemd1",
4717 "/org/freedesktop/systemd1",
4718 "org.freedesktop.systemd1.Manager",
4724 log_error("Failed to reset failed state of unit %s: %s",
4725 *name
, bus_error_message(&error
, r
));
4734 static int show_environment(sd_bus
*bus
, char **args
) {
4735 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4736 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
4740 pager_open_if_enabled();
4742 r
= sd_bus_get_property(
4744 "org.freedesktop.systemd1",
4745 "/org/freedesktop/systemd1",
4746 "org.freedesktop.systemd1.Manager",
4752 log_error("Failed to get environment: %s", bus_error_message(&error
, r
));
4756 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
4758 return bus_log_parse_error(r
);
4760 while ((r
= sd_bus_message_read_basic(reply
, SD_BUS_TYPE_STRING
, &text
)) > 0)
4763 return bus_log_parse_error(r
);
4765 r
= sd_bus_message_exit_container(reply
);
4767 return bus_log_parse_error(r
);
4772 static int switch_root(sd_bus
*bus
, char **args
) {
4773 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4774 _cleanup_free_
char *cmdline_init
= NULL
;
4775 const char *root
, *init
;
4779 l
= strv_length(args
);
4780 if (l
< 2 || l
> 3) {
4781 log_error("Wrong number of arguments.");
4790 r
= parse_env_file("/proc/cmdline", WHITESPACE
,
4791 "init", &cmdline_init
,
4794 log_debug("Failed to parse /proc/cmdline: %s", strerror(-r
));
4796 init
= cmdline_init
;
4803 const char *root_systemd_path
= NULL
, *root_init_path
= NULL
;
4805 root_systemd_path
= strappenda(root
, "/" SYSTEMD_BINARY_PATH
);
4806 root_init_path
= strappenda3(root
, "/", init
);
4808 /* If the passed init is actually the same as the
4809 * systemd binary, then let's suppress it. */
4810 if (files_same(root_init_path
, root_systemd_path
) > 0)
4814 log_debug("Switching root - root: %s; init: %s", root
, strna(init
));
4816 r
= sd_bus_call_method(
4818 "org.freedesktop.systemd1",
4819 "/org/freedesktop/systemd1",
4820 "org.freedesktop.systemd1.Manager",
4826 log_error("Failed to switch root: %s", bus_error_message(&error
, r
));
4833 static int set_environment(sd_bus
*bus
, char **args
) {
4834 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4835 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
4842 method
= streq(args
[0], "set-environment")
4844 : "UnsetEnvironment";
4846 r
= sd_bus_message_new_method_call(
4849 "org.freedesktop.systemd1",
4850 "/org/freedesktop/systemd1",
4851 "org.freedesktop.systemd1.Manager",
4854 return bus_log_create_error(r
);
4856 r
= sd_bus_message_append_strv(m
, args
+ 1);
4858 return bus_log_create_error(r
);
4860 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
4862 log_error("Failed to set environment: %s", bus_error_message(&error
, r
));
4869 static int import_environment(sd_bus
*bus
, char **args
) {
4870 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
4871 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
4877 r
= sd_bus_message_new_method_call(
4880 "org.freedesktop.systemd1",
4881 "/org/freedesktop/systemd1",
4882 "org.freedesktop.systemd1.Manager",
4885 return bus_log_create_error(r
);
4887 if (strv_isempty(args
+ 1))
4888 r
= sd_bus_message_append_strv(m
, environ
);
4892 r
= sd_bus_message_open_container(m
, 'a', "s");
4894 return bus_log_create_error(r
);
4896 STRV_FOREACH(a
, args
+ 1) {
4898 if (!env_name_is_valid(*a
)) {
4899 log_error("Not a valid environment variable name: %s", *a
);
4903 STRV_FOREACH(b
, environ
) {
4906 eq
= startswith(*b
, *a
);
4907 if (eq
&& *eq
== '=') {
4909 r
= sd_bus_message_append(m
, "s", *b
);
4911 return bus_log_create_error(r
);
4918 r
= sd_bus_message_close_container(m
);
4921 return bus_log_create_error(r
);
4923 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
4925 log_error("Failed to import environment: %s", bus_error_message(&error
, r
));
4932 static int enable_sysv_units(const char *verb
, char **args
) {
4935 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4936 unsigned f
= 1, t
= 1;
4937 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
4939 if (arg_scope
!= UNIT_FILE_SYSTEM
)
4942 if (!streq(verb
, "enable") &&
4943 !streq(verb
, "disable") &&
4944 !streq(verb
, "is-enabled"))
4947 /* Processes all SysV units, and reshuffles the array so that
4948 * afterwards only the native units remain */
4950 r
= lookup_paths_init(&paths
, SYSTEMD_SYSTEM
, false, NULL
, NULL
, NULL
);
4955 for (f
= 0; args
[f
]; f
++) {
4957 _cleanup_free_
char *p
= NULL
, *q
= NULL
;
4958 bool found_native
= false, found_sysv
;
4960 const char *argv
[6] = { "/sbin/chkconfig", NULL
, NULL
, NULL
, NULL
};
4968 if (!endswith(name
, ".service"))
4971 if (path_is_absolute(name
))
4974 STRV_FOREACH(k
, paths
.unit_path
) {
4975 if (!isempty(arg_root
))
4976 asprintf(&p
, "%s/%s/%s", arg_root
, *k
, name
);
4978 asprintf(&p
, "%s/%s", *k
, name
);
4985 found_native
= access(p
, F_OK
) >= 0;
4996 if (!isempty(arg_root
))
4997 asprintf(&p
, "%s/" SYSTEM_SYSVINIT_PATH
"/%s", arg_root
, name
);
4999 asprintf(&p
, SYSTEM_SYSVINIT_PATH
"/%s", name
);
5005 p
[strlen(p
) - sizeof(".service") + 1] = 0;
5006 found_sysv
= access(p
, F_OK
) >= 0;
5011 /* Mark this entry, so that we don't try enabling it as native unit */
5012 args
[f
] = (char*) "";
5014 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name
);
5016 if (!isempty(arg_root
))
5017 argv
[c
++] = q
= strappend("--root=", arg_root
);
5019 argv
[c
++] = basename(p
);
5021 streq(verb
, "enable") ? "on" :
5022 streq(verb
, "disable") ? "off" : "--level=5";
5025 l
= strv_join((char**)argv
, " ");
5031 log_info("Executing %s", l
);
5036 log_error("Failed to fork: %m");
5039 } else if (pid
== 0) {
5042 execv(argv
[0], (char**) argv
);
5043 _exit(EXIT_FAILURE
);
5046 j
= wait_for_terminate(pid
, &status
);
5048 log_error("Failed to wait for child: %s", strerror(-r
));
5053 if (status
.si_code
== CLD_EXITED
) {
5054 if (streq(verb
, "is-enabled")) {
5055 if (status
.si_status
== 0) {
5064 } else if (status
.si_status
!= 0) {
5075 /* Drop all SysV units */
5076 for (f
= 0, t
= 0; args
[f
]; f
++) {
5078 if (isempty(args
[f
]))
5081 args
[t
++] = args
[f
];
5090 static int mangle_names(char **original_names
, char ***mangled_names
) {
5091 char **i
, **l
, **name
;
5093 l
= new(char*, strv_length(original_names
) + 1);
5098 STRV_FOREACH(name
, original_names
) {
5100 /* When enabling units qualified path names are OK,
5101 * too, hence allow them explicitly. */
5106 *i
= unit_name_mangle(*name
, MANGLE_NOGLOB
);
5122 static int enable_unit(sd_bus
*bus
, char **args
) {
5123 _cleanup_strv_free_
char **names
= NULL
;
5124 const char *verb
= args
[0];
5125 UnitFileChange
*changes
= NULL
;
5126 unsigned n_changes
= 0;
5127 int carries_install_info
= -1;
5133 r
= mangle_names(args
+1, &names
);
5137 r
= enable_sysv_units(verb
, names
);
5141 /* If the operation was fully executed by the SysV compat,
5142 * let's finish early */
5143 if (strv_isempty(names
))
5146 if (!bus
|| avoid_bus()) {
5147 if (streq(verb
, "enable")) {
5148 r
= unit_file_enable(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5149 carries_install_info
= r
;
5150 } else if (streq(verb
, "disable"))
5151 r
= unit_file_disable(arg_scope
, arg_runtime
, arg_root
, names
, &changes
, &n_changes
);
5152 else if (streq(verb
, "reenable")) {
5153 r
= unit_file_reenable(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5154 carries_install_info
= r
;
5155 } else if (streq(verb
, "link"))
5156 r
= unit_file_link(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5157 else if (streq(verb
, "preset")) {
5158 r
= unit_file_preset(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5159 carries_install_info
= r
;
5160 } else if (streq(verb
, "mask"))
5161 r
= unit_file_mask(arg_scope
, arg_runtime
, arg_root
, names
, arg_force
, &changes
, &n_changes
);
5162 else if (streq(verb
, "unmask"))
5163 r
= unit_file_unmask(arg_scope
, arg_runtime
, arg_root
, names
, &changes
, &n_changes
);
5165 assert_not_reached("Unknown verb");
5168 log_error("Operation failed: %s", strerror(-r
));
5173 dump_unit_file_changes(changes
, n_changes
);
5177 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
, *m
= NULL
;
5178 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5179 int expect_carries_install_info
= false;
5180 bool send_force
= true;
5183 if (streq(verb
, "enable")) {
5184 method
= "EnableUnitFiles";
5185 expect_carries_install_info
= true;
5186 } else if (streq(verb
, "disable")) {
5187 method
= "DisableUnitFiles";
5189 } else if (streq(verb
, "reenable")) {
5190 method
= "ReenableUnitFiles";
5191 expect_carries_install_info
= true;
5192 } else if (streq(verb
, "link"))
5193 method
= "LinkUnitFiles";
5194 else if (streq(verb
, "preset")) {
5195 method
= "PresetUnitFiles";
5196 expect_carries_install_info
= true;
5197 } else if (streq(verb
, "mask"))
5198 method
= "MaskUnitFiles";
5199 else if (streq(verb
, "unmask")) {
5200 method
= "UnmaskUnitFiles";
5203 assert_not_reached("Unknown verb");
5205 r
= sd_bus_message_new_method_call(
5208 "org.freedesktop.systemd1",
5209 "/org/freedesktop/systemd1",
5210 "org.freedesktop.systemd1.Manager",
5213 return bus_log_create_error(r
);
5215 r
= sd_bus_message_append_strv(m
, names
);
5217 return bus_log_create_error(r
);
5219 r
= sd_bus_message_append(m
, "b", arg_runtime
);
5221 return bus_log_create_error(r
);
5224 r
= sd_bus_message_append(m
, "b", arg_force
);
5226 return bus_log_create_error(r
);
5229 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
5231 log_error("Failed to execute operation: %s", bus_error_message(&error
, r
));
5235 if (expect_carries_install_info
) {
5236 r
= sd_bus_message_read(reply
, "b", &carries_install_info
);
5238 return bus_log_parse_error(r
);
5241 r
= deserialize_and_dump_unit_file_changes(reply
);
5245 /* Try to reload if enabled */
5247 r
= daemon_reload(bus
, args
);
5252 if (carries_install_info
== 0)
5253 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5254 "using systemctl.\n"
5255 "Possible reasons for having this kind of units are:\n"
5256 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5257 " .wants/ or .requires/ directory.\n"
5258 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5259 " a requirement dependency on it.\n"
5260 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5261 " D-Bus, udev, scripted systemctl call, ...).\n");
5264 unit_file_changes_free(changes
, n_changes
);
5269 static int unit_is_enabled(sd_bus
*bus
, char **args
) {
5271 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
5272 _cleanup_strv_free_
char **names
= NULL
;
5277 r
= mangle_names(args
+1, &names
);
5281 r
= enable_sysv_units(args
[0], names
);
5287 if (!bus
|| avoid_bus()) {
5289 STRV_FOREACH(name
, names
) {
5290 UnitFileState state
;
5292 state
= unit_file_get_state(arg_scope
, arg_root
, *name
);
5294 log_error("Failed to get unit file state for %s: %s", *name
, strerror(-state
));
5298 if (state
== UNIT_FILE_ENABLED
||
5299 state
== UNIT_FILE_ENABLED_RUNTIME
||
5300 state
== UNIT_FILE_STATIC
)
5304 puts(unit_file_state_to_string(state
));
5308 STRV_FOREACH(name
, names
) {
5309 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
5312 r
= sd_bus_call_method(
5314 "org.freedesktop.systemd1",
5315 "/org/freedesktop/systemd1",
5316 "org.freedesktop.systemd1.Manager",
5322 log_error("Failed to get unit file state for %s: %s", *name
, bus_error_message(&error
, r
));
5326 r
= sd_bus_message_read(reply
, "s", &s
);
5328 return bus_log_parse_error(r
);
5330 if (streq(s
, "enabled") ||
5331 streq(s
, "enabled-runtime") ||
5343 static int systemctl_help(void) {
5345 pager_open_if_enabled();
5347 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
5348 "Query or send control commands to the systemd manager.\n\n"
5349 " -h --help Show this help\n"
5350 " --version Show package version\n"
5351 " --system Connect to system manager\n"
5352 " --user Connect to user service manager\n"
5353 " -H --host=[USER@]HOST\n"
5354 " Operate on remote host\n"
5355 " -M --machine=CONTAINER\n"
5356 " Operate on local container\n"
5357 " -t --type=TYPE List only units of a particular type\n"
5358 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
5359 " -p --property=NAME Show only properties by this name\n"
5360 " -a --all Show all loaded units/properties, including dead/empty\n"
5361 " ones. To list all units installed on the system, use\n"
5362 " the 'list-unit-files' command instead.\n"
5363 " -l --full Don't ellipsize unit names on output\n"
5364 " -r --recursive Show unit list of host and local containers\n"
5365 " --reverse Show reverse dependencies with 'list-dependencies'\n"
5366 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
5367 " queueing a new job\n"
5368 " --show-types When showing sockets, explicitly show their type\n"
5369 " -i --ignore-inhibitors\n"
5370 " When shutting down or sleeping, ignore inhibitors\n"
5371 " --kill-who=WHO Who to send signal to\n"
5372 " -s --signal=SIGNAL Which signal to send\n"
5373 " -q --quiet Suppress output\n"
5374 " --no-block Do not wait until operation finished\n"
5375 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5376 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
5378 " --no-legend Do not print a legend (column headers and hints)\n"
5379 " --no-pager Do not pipe output into a pager\n"
5380 " --no-ask-password\n"
5381 " Do not ask for system passwords\n"
5382 " --global Enable/disable unit files globally\n"
5383 " --runtime Enable unit files only temporarily until next reboot\n"
5384 " -f --force When enabling unit files, override existing symlinks\n"
5385 " When shutting down, execute action immediately\n"
5386 " --root=PATH Enable unit files in the specified root directory\n"
5387 " -n --lines=INTEGER Number of journal entries to show\n"
5388 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
5389 " verbose, export, json, json-pretty, json-sse, cat)\n"
5390 " --plain Print unit dependencies as a list instead of a tree\n\n"
5392 " list-units [PATTERN...] List loaded units\n"
5393 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
5394 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
5395 " start NAME... Start (activate) one or more units\n"
5396 " stop NAME... Stop (deactivate) one or more units\n"
5397 " reload NAME... Reload one or more units\n"
5398 " restart NAME... Start or restart one or more units\n"
5399 " try-restart NAME... Restart one or more units if active\n"
5400 " reload-or-restart NAME... Reload one or more units if possible,\n"
5401 " otherwise start or restart\n"
5402 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
5403 " otherwise restart if active\n"
5404 " isolate NAME Start one unit and stop all others\n"
5405 " kill NAME... Send signal to processes of a unit\n"
5406 " is-active NAME... Check whether units are active\n"
5407 " is-failed NAME... Check whether units are failed\n"
5408 " status [NAME...|PID...] Show runtime status of one or more units\n"
5409 " show [NAME...|JOB...] Show properties of one or more\n"
5410 " units/jobs or the manager\n"
5411 " cat NAME... Show files and drop-ins of one or more units\n"
5412 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
5413 " help NAME...|PID... Show manual for one or more units\n"
5414 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
5416 " list-dependencies [NAME] Recursively show units which are required\n"
5417 " or wanted by this unit or by which this\n"
5418 " unit is required or wanted\n\n"
5419 "Unit File Commands:\n"
5420 " list-unit-files [PATTERN...] List installed unit files\n"
5421 " enable NAME... Enable one or more unit files\n"
5422 " disable NAME... Disable one or more unit files\n"
5423 " reenable NAME... Reenable one or more unit files\n"
5424 " preset NAME... Enable/disable one or more unit files\n"
5425 " based on preset configuration\n"
5426 " is-enabled NAME... Check whether unit files are enabled\n\n"
5427 " mask NAME... Mask one or more units\n"
5428 " unmask NAME... Unmask one or more units\n"
5429 " link PATH... Link one or more units files into\n"
5430 " the search path\n"
5431 " get-default Get the name of the default target\n"
5432 " set-default NAME Set the default target\n\n"
5433 "Machine Commands:\n"
5434 " list-machines [PATTERN...] List local containers and host\n\n"
5436 " list-jobs [PATTERN...] List jobs\n"
5437 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
5438 "Snapshot Commands:\n"
5439 " snapshot [NAME] Create a snapshot\n"
5440 " delete NAME... Remove one or more snapshots\n\n"
5441 "Environment Commands:\n"
5442 " show-environment Dump environment\n"
5443 " set-environment NAME=VALUE... Set one or more environment variables\n"
5444 " unset-environment NAME... Unset one or more environment variables\n"
5445 " import-environment NAME... Import all, one or more environment variables\n\n"
5446 "Manager Lifecycle Commands:\n"
5447 " daemon-reload Reload systemd manager configuration\n"
5448 " daemon-reexec Reexecute systemd manager\n\n"
5449 "System Commands:\n"
5450 " default Enter system default mode\n"
5451 " rescue Enter system rescue mode\n"
5452 " emergency Enter system emergency mode\n"
5453 " halt Shut down and halt the system\n"
5454 " poweroff Shut down and power-off the system\n"
5455 " reboot [ARG] Shut down and reboot the system\n"
5456 " kexec Shut down and reboot the system with kexec\n"
5457 " exit Request user instance exit\n"
5458 " switch-root ROOT [INIT] Change to a different root file system\n"
5459 " suspend Suspend the system\n"
5460 " hibernate Hibernate the system\n"
5461 " hybrid-sleep Hibernate and suspend the system\n",
5462 program_invocation_short_name
);
5467 static int halt_help(void) {
5469 printf("%s [OPTIONS...]%s\n\n"
5470 "%s the system.\n\n"
5471 " --help Show this help\n"
5472 " --halt Halt the machine\n"
5473 " -p --poweroff Switch off the machine\n"
5474 " --reboot Reboot the machine\n"
5475 " -f --force Force immediate halt/power-off/reboot\n"
5476 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
5477 " -d --no-wtmp Don't write wtmp record\n"
5478 " --no-wall Don't send wall message before halt/power-off/reboot\n",
5479 program_invocation_short_name
,
5480 arg_action
== ACTION_REBOOT
? " [ARG]" : "",
5481 arg_action
== ACTION_REBOOT
? "Reboot" :
5482 arg_action
== ACTION_POWEROFF
? "Power off" :
5488 static int shutdown_help(void) {
5490 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
5491 "Shut down the system.\n\n"
5492 " --help Show this help\n"
5493 " -H --halt Halt the machine\n"
5494 " -P --poweroff Power-off the machine\n"
5495 " -r --reboot Reboot the machine\n"
5496 " -h Equivalent to --poweroff, overridden by --halt\n"
5497 " -k Don't halt/power-off/reboot, just send warnings\n"
5498 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5499 " -c Cancel a pending shutdown\n",
5500 program_invocation_short_name
);
5505 static int telinit_help(void) {
5507 printf("%s [OPTIONS...] {COMMAND}\n\n"
5508 "Send control commands to the init daemon.\n\n"
5509 " --help Show this help\n"
5510 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
5512 " 0 Power-off the machine\n"
5513 " 6 Reboot the machine\n"
5514 " 2, 3, 4, 5 Start runlevelX.target unit\n"
5515 " 1, s, S Enter rescue mode\n"
5516 " q, Q Reload init daemon configuration\n"
5517 " u, U Reexecute init daemon\n",
5518 program_invocation_short_name
);
5523 static int runlevel_help(void) {
5525 printf("%s [OPTIONS...]\n\n"
5526 "Prints the previous and current runlevel of the init system.\n\n"
5527 " --help Show this help\n",
5528 program_invocation_short_name
);
5533 static int help_types(void) {
5537 puts("Available unit types:");
5538 for (i
= 0; i
< _UNIT_TYPE_MAX
; i
++) {
5539 t
= unit_type_to_string(i
);
5547 static int systemctl_parse_argv(int argc
, char *argv
[]) {
5556 ARG_IGNORE_DEPENDENCIES
,
5568 ARG_NO_ASK_PASSWORD
,
5577 static const struct option options
[] = {
5578 { "help", no_argument
, NULL
, 'h' },
5579 { "version", no_argument
, NULL
, ARG_VERSION
},
5580 { "type", required_argument
, NULL
, 't' },
5581 { "property", required_argument
, NULL
, 'p' },
5582 { "all", no_argument
, NULL
, 'a' },
5583 { "reverse", no_argument
, NULL
, ARG_REVERSE
},
5584 { "after", no_argument
, NULL
, ARG_AFTER
},
5585 { "before", no_argument
, NULL
, ARG_BEFORE
},
5586 { "show-types", no_argument
, NULL
, ARG_SHOW_TYPES
},
5587 { "failed", no_argument
, NULL
, ARG_FAILED
}, /* compatibility only */
5588 { "full", no_argument
, NULL
, 'l' },
5589 { "job-mode", required_argument
, NULL
, ARG_JOB_MODE
},
5590 { "fail", no_argument
, NULL
, ARG_FAIL
}, /* compatibility only */
5591 { "irreversible", no_argument
, NULL
, ARG_IRREVERSIBLE
}, /* compatibility only */
5592 { "ignore-dependencies", no_argument
, NULL
, ARG_IGNORE_DEPENDENCIES
}, /* compatibility only */
5593 { "ignore-inhibitors", no_argument
, NULL
, 'i' },
5594 { "user", no_argument
, NULL
, ARG_USER
},
5595 { "system", no_argument
, NULL
, ARG_SYSTEM
},
5596 { "global", no_argument
, NULL
, ARG_GLOBAL
},
5597 { "no-block", no_argument
, NULL
, ARG_NO_BLOCK
},
5598 { "no-legend", no_argument
, NULL
, ARG_NO_LEGEND
},
5599 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
5600 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
5601 { "quiet", no_argument
, NULL
, 'q' },
5602 { "root", required_argument
, NULL
, ARG_ROOT
},
5603 { "force", no_argument
, NULL
, ARG_FORCE
},
5604 { "no-reload", no_argument
, NULL
, ARG_NO_RELOAD
},
5605 { "kill-who", required_argument
, NULL
, ARG_KILL_WHO
},
5606 { "signal", required_argument
, NULL
, 's' },
5607 { "no-ask-password", no_argument
, NULL
, ARG_NO_ASK_PASSWORD
},
5608 { "host", required_argument
, NULL
, 'H' },
5609 { "machine", required_argument
, NULL
, 'M' },
5610 { "runtime", no_argument
, NULL
, ARG_RUNTIME
},
5611 { "lines", required_argument
, NULL
, 'n' },
5612 { "output", required_argument
, NULL
, 'o' },
5613 { "plain", no_argument
, NULL
, ARG_PLAIN
},
5614 { "state", required_argument
, NULL
, ARG_STATE
},
5615 { "recursive", no_argument
, NULL
, 'r' },
5624 while ((c
= getopt_long(argc
, argv
, "ht:p:alqfs:H:M:n:o:ir", options
, NULL
)) >= 0) {
5629 return systemctl_help();
5632 puts(PACKAGE_STRING
);
5633 puts(SYSTEMD_FEATURES
);
5640 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
5641 _cleanup_free_
char *type
;
5643 type
= strndup(word
, size
);
5647 if (streq(type
, "help")) {
5652 if (unit_type_from_string(type
) >= 0) {
5653 if (strv_push(&arg_types
, type
))
5659 /* It's much nicer to use --state= for
5660 * load states, but let's support this
5661 * in --types= too for compatibility
5662 * with old versions */
5663 if (unit_load_state_from_string(optarg
) >= 0) {
5664 if (strv_push(&arg_states
, type
) < 0)
5670 log_error("Unknown unit type or load state '%s'.", type
);
5671 log_info("Use -t help to see a list of allowed values.");
5679 /* Make sure that if the empty property list
5680 was specified, we won't show any properties. */
5681 if (isempty(optarg
) && !arg_properties
) {
5682 arg_properties
= new0(char*, 1);
5683 if (!arg_properties
)
5689 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
5692 prop
= strndup(word
, size
);
5696 if (strv_consume(&arg_properties
, prop
) < 0)
5701 /* If the user asked for a particular
5702 * property, show it to him, even if it is
5714 arg_dependency
= DEPENDENCY_REVERSE
;
5718 arg_dependency
= DEPENDENCY_AFTER
;
5722 arg_dependency
= DEPENDENCY_BEFORE
;
5725 case ARG_SHOW_TYPES
:
5726 arg_show_types
= true;
5730 arg_job_mode
= optarg
;
5734 arg_job_mode
= "fail";
5737 case ARG_IRREVERSIBLE
:
5738 arg_job_mode
= "replace-irreversibly";
5741 case ARG_IGNORE_DEPENDENCIES
:
5742 arg_job_mode
= "ignore-dependencies";
5746 arg_scope
= UNIT_FILE_USER
;
5750 arg_scope
= UNIT_FILE_SYSTEM
;
5754 arg_scope
= UNIT_FILE_GLOBAL
;
5758 arg_no_block
= true;
5762 arg_no_legend
= true;
5766 arg_no_pager
= true;
5782 if (strv_extend(&arg_states
, "failed") < 0)
5800 arg_no_reload
= true;
5804 arg_kill_who
= optarg
;
5808 if ((arg_signal
= signal_from_string_try_harder(optarg
)) < 0) {
5809 log_error("Failed to parse signal string %s.", optarg
);
5814 case ARG_NO_ASK_PASSWORD
:
5815 arg_ask_password
= false;
5819 arg_transport
= BUS_TRANSPORT_REMOTE
;
5824 arg_transport
= BUS_TRANSPORT_CONTAINER
;
5833 if (safe_atou(optarg
, &arg_lines
) < 0) {
5834 log_error("Failed to parse lines '%s'", optarg
);
5840 arg_output
= output_mode_from_string(optarg
);
5841 if (arg_output
< 0) {
5842 log_error("Unknown output '%s'.", optarg
);
5848 arg_ignore_inhibitors
= true;
5859 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
5862 s
= strndup(word
, size
);
5866 if (strv_consume(&arg_states
, s
) < 0)
5873 if (geteuid() != 0) {
5874 log_error("--recursive requires root priviliges.");
5878 arg_recursive
= true;
5885 assert_not_reached("Unhandled option");
5889 if (arg_transport
!= BUS_TRANSPORT_LOCAL
&& arg_scope
!= UNIT_FILE_SYSTEM
) {
5890 log_error("Cannot access user instance remotely.");
5897 static int halt_parse_argv(int argc
, char *argv
[]) {
5906 static const struct option options
[] = {
5907 { "help", no_argument
, NULL
, ARG_HELP
},
5908 { "halt", no_argument
, NULL
, ARG_HALT
},
5909 { "poweroff", no_argument
, NULL
, 'p' },
5910 { "reboot", no_argument
, NULL
, ARG_REBOOT
},
5911 { "force", no_argument
, NULL
, 'f' },
5912 { "wtmp-only", no_argument
, NULL
, 'w' },
5913 { "no-wtmp", no_argument
, NULL
, 'd' },
5914 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
5923 if (utmp_get_runlevel(&runlevel
, NULL
) >= 0)
5924 if (runlevel
== '0' || runlevel
== '6')
5927 while ((c
= getopt_long(argc
, argv
, "pfwdnih", options
, NULL
)) >= 0) {
5934 arg_action
= ACTION_HALT
;
5938 if (arg_action
!= ACTION_REBOOT
)
5939 arg_action
= ACTION_POWEROFF
;
5943 arg_action
= ACTION_REBOOT
;
5965 /* Compatibility nops */
5972 assert_not_reached("Unhandled option");
5976 if (arg_action
== ACTION_REBOOT
&& argc
== optind
+ 1) {
5977 r
= write_string_file(REBOOT_PARAM_FILE
, argv
[optind
]);
5979 log_error("Failed to write reboot param to "
5980 REBOOT_PARAM_FILE
": %s", strerror(-r
));
5983 } else if (optind
< argc
) {
5984 log_error("Too many arguments.");
5991 static int parse_time_spec(const char *t
, usec_t
*_u
) {
5995 if (streq(t
, "now"))
5997 else if (!strchr(t
, ':')) {
6000 if (safe_atou64(t
, &u
) < 0)
6003 *_u
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
* u
;
6012 hour
= strtol(t
, &e
, 10);
6013 if (errno
> 0 || *e
!= ':' || hour
< 0 || hour
> 23)
6016 minute
= strtol(e
+1, &e
, 10);
6017 if (errno
> 0 || *e
!= 0 || minute
< 0 || minute
> 59)
6020 n
= now(CLOCK_REALTIME
);
6021 s
= (time_t) (n
/ USEC_PER_SEC
);
6023 assert_se(localtime_r(&s
, &tm
));
6025 tm
.tm_hour
= (int) hour
;
6026 tm
.tm_min
= (int) minute
;
6029 assert_se(s
= mktime(&tm
));
6031 *_u
= (usec_t
) s
* USEC_PER_SEC
;
6034 *_u
+= USEC_PER_DAY
;
6040 static int shutdown_parse_argv(int argc
, char *argv
[]) {
6047 static const struct option options
[] = {
6048 { "help", no_argument
, NULL
, ARG_HELP
},
6049 { "halt", no_argument
, NULL
, 'H' },
6050 { "poweroff", no_argument
, NULL
, 'P' },
6051 { "reboot", no_argument
, NULL
, 'r' },
6052 { "kexec", no_argument
, NULL
, 'K' }, /* not documented extension */
6053 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6062 while ((c
= getopt_long(argc
, argv
, "HPrhkt:afFc", options
, NULL
)) >= 0) {
6066 return shutdown_help();
6069 arg_action
= ACTION_HALT
;
6073 arg_action
= ACTION_POWEROFF
;
6078 arg_action
= ACTION_KEXEC
;
6080 arg_action
= ACTION_REBOOT
;
6084 arg_action
= ACTION_KEXEC
;
6088 if (arg_action
!= ACTION_HALT
)
6089 arg_action
= ACTION_POWEROFF
;
6102 /* Compatibility nops */
6106 arg_action
= ACTION_CANCEL_SHUTDOWN
;
6113 assert_not_reached("Unhandled option");
6117 if (argc
> optind
&& arg_action
!= ACTION_CANCEL_SHUTDOWN
) {
6118 r
= parse_time_spec(argv
[optind
], &arg_when
);
6120 log_error("Failed to parse time specification: %s", argv
[optind
]);
6124 arg_when
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
;
6126 if (argc
> optind
&& arg_action
== ACTION_CANCEL_SHUTDOWN
)
6127 /* No time argument for shutdown cancel */
6128 arg_wall
= argv
+ optind
;
6129 else if (argc
> optind
+ 1)
6130 /* We skip the time argument */
6131 arg_wall
= argv
+ optind
+ 1;
6138 static int telinit_parse_argv(int argc
, char *argv
[]) {
6145 static const struct option options
[] = {
6146 { "help", no_argument
, NULL
, ARG_HELP
},
6147 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
6151 static const struct {
6155 { '0', ACTION_POWEROFF
},
6156 { '6', ACTION_REBOOT
},
6157 { '1', ACTION_RESCUE
},
6158 { '2', ACTION_RUNLEVEL2
},
6159 { '3', ACTION_RUNLEVEL3
},
6160 { '4', ACTION_RUNLEVEL4
},
6161 { '5', ACTION_RUNLEVEL5
},
6162 { 's', ACTION_RESCUE
},
6163 { 'S', ACTION_RESCUE
},
6164 { 'q', ACTION_RELOAD
},
6165 { 'Q', ACTION_RELOAD
},
6166 { 'u', ACTION_REEXEC
},
6167 { 'U', ACTION_REEXEC
}
6176 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0) {
6180 return telinit_help();
6190 assert_not_reached("Unhandled option");
6194 if (optind
>= argc
) {
6199 if (optind
+ 1 < argc
) {
6200 log_error("Too many arguments.");
6204 if (strlen(argv
[optind
]) != 1) {
6205 log_error("Expected single character argument.");
6209 for (i
= 0; i
< ELEMENTSOF(table
); i
++)
6210 if (table
[i
].from
== argv
[optind
][0])
6213 if (i
>= ELEMENTSOF(table
)) {
6214 log_error("Unknown command '%s'.", argv
[optind
]);
6218 arg_action
= table
[i
].to
;
6225 static int runlevel_parse_argv(int argc
, char *argv
[]) {
6231 static const struct option options
[] = {
6232 { "help", no_argument
, NULL
, ARG_HELP
},
6241 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0) {
6245 return runlevel_help();
6251 assert_not_reached("Unhandled option");
6255 if (optind
< argc
) {
6256 log_error("Too many arguments.");
6263 static int parse_argv(int argc
, char *argv
[]) {
6267 if (program_invocation_short_name
) {
6269 if (strstr(program_invocation_short_name
, "halt")) {
6270 arg_action
= ACTION_HALT
;
6271 return halt_parse_argv(argc
, argv
);
6272 } else if (strstr(program_invocation_short_name
, "poweroff")) {
6273 arg_action
= ACTION_POWEROFF
;
6274 return halt_parse_argv(argc
, argv
);
6275 } else if (strstr(program_invocation_short_name
, "reboot")) {
6277 arg_action
= ACTION_KEXEC
;
6279 arg_action
= ACTION_REBOOT
;
6280 return halt_parse_argv(argc
, argv
);
6281 } else if (strstr(program_invocation_short_name
, "shutdown")) {
6282 arg_action
= ACTION_POWEROFF
;
6283 return shutdown_parse_argv(argc
, argv
);
6284 } else if (strstr(program_invocation_short_name
, "init")) {
6286 if (sd_booted() > 0) {
6287 arg_action
= _ACTION_INVALID
;
6288 return telinit_parse_argv(argc
, argv
);
6290 /* Hmm, so some other init system is
6291 * running, we need to forward this
6292 * request to it. For now we simply
6293 * guess that it is Upstart. */
6295 execv(TELINIT
, argv
);
6297 log_error("Couldn't find an alternative telinit implementation to spawn.");
6301 } else if (strstr(program_invocation_short_name
, "runlevel")) {
6302 arg_action
= ACTION_RUNLEVEL
;
6303 return runlevel_parse_argv(argc
, argv
);
6307 arg_action
= ACTION_SYSTEMCTL
;
6308 return systemctl_parse_argv(argc
, argv
);
6311 _pure_
static int action_to_runlevel(void) {
6313 static const char table
[_ACTION_MAX
] = {
6314 [ACTION_HALT
] = '0',
6315 [ACTION_POWEROFF
] = '0',
6316 [ACTION_REBOOT
] = '6',
6317 [ACTION_RUNLEVEL2
] = '2',
6318 [ACTION_RUNLEVEL3
] = '3',
6319 [ACTION_RUNLEVEL4
] = '4',
6320 [ACTION_RUNLEVEL5
] = '5',
6321 [ACTION_RESCUE
] = '1'
6324 assert(arg_action
< _ACTION_MAX
);
6326 return table
[arg_action
];
6329 static int talk_initctl(void) {
6331 struct init_request request
= {
6332 .magic
= INIT_MAGIC
,
6334 .cmd
= INIT_CMD_RUNLVL
6337 _cleanup_close_
int fd
= -1;
6341 rl
= action_to_runlevel();
6345 request
.runlevel
= rl
;
6347 fd
= open(INIT_FIFO
, O_WRONLY
|O_NDELAY
|O_CLOEXEC
|O_NOCTTY
);
6349 if (errno
== ENOENT
)
6352 log_error("Failed to open "INIT_FIFO
": %m");
6357 r
= loop_write(fd
, &request
, sizeof(request
), false) != sizeof(request
);
6359 log_error("Failed to write to "INIT_FIFO
": %m");
6360 return errno
> 0 ? -errno
: -EIO
;
6366 static int systemctl_main(sd_bus
*bus
, int argc
, char *argv
[], int bus_error
) {
6368 static const struct {
6376 int (* const dispatch
)(sd_bus
*bus
, char **args
);
6382 { "list-units", MORE
, 0, list_units
},
6383 { "list-unit-files", MORE
, 1, list_unit_files
, NOBUS
},
6384 { "list-sockets", MORE
, 1, list_sockets
},
6385 { "list-timers", MORE
, 1, list_timers
},
6386 { "list-jobs", MORE
, 1, list_jobs
},
6387 { "list-machines", MORE
, 1, list_machines
},
6388 { "clear-jobs", EQUAL
, 1, daemon_reload
},
6389 { "cancel", MORE
, 2, cancel_job
},
6390 { "start", MORE
, 2, start_unit
},
6391 { "stop", MORE
, 2, start_unit
},
6392 { "condstop", MORE
, 2, start_unit
}, /* For compatibility with ALTLinux */
6393 { "reload", MORE
, 2, start_unit
},
6394 { "restart", MORE
, 2, start_unit
},
6395 { "try-restart", MORE
, 2, start_unit
},
6396 { "reload-or-restart", MORE
, 2, start_unit
},
6397 { "reload-or-try-restart", MORE
, 2, start_unit
},
6398 { "force-reload", MORE
, 2, start_unit
}, /* For compatibility with SysV */
6399 { "condreload", MORE
, 2, start_unit
}, /* For compatibility with ALTLinux */
6400 { "condrestart", MORE
, 2, start_unit
}, /* For compatibility with RH */
6401 { "isolate", EQUAL
, 2, start_unit
},
6402 { "kill", MORE
, 2, kill_unit
},
6403 { "is-active", MORE
, 2, check_unit_active
},
6404 { "check", MORE
, 2, check_unit_active
},
6405 { "is-failed", MORE
, 2, check_unit_failed
},
6406 { "show", MORE
, 1, show
},
6407 { "cat", MORE
, 2, cat
},
6408 { "status", MORE
, 1, show
},
6409 { "help", MORE
, 2, show
},
6410 { "snapshot", LESS
, 2, snapshot
},
6411 { "delete", MORE
, 2, delete_snapshot
},
6412 { "daemon-reload", EQUAL
, 1, daemon_reload
},
6413 { "daemon-reexec", EQUAL
, 1, daemon_reload
},
6414 { "show-environment", EQUAL
, 1, show_environment
},
6415 { "set-environment", MORE
, 2, set_environment
},
6416 { "unset-environment", MORE
, 2, set_environment
},
6417 { "import-environment", MORE
, 1, import_environment
},
6418 { "halt", EQUAL
, 1, start_special
, FORCE
},
6419 { "poweroff", EQUAL
, 1, start_special
, FORCE
},
6420 { "reboot", EQUAL
, 1, start_special
, FORCE
},
6421 { "kexec", EQUAL
, 1, start_special
},
6422 { "suspend", EQUAL
, 1, start_special
},
6423 { "hibernate", EQUAL
, 1, start_special
},
6424 { "hybrid-sleep", EQUAL
, 1, start_special
},
6425 { "default", EQUAL
, 1, start_special
},
6426 { "rescue", EQUAL
, 1, start_special
},
6427 { "emergency", EQUAL
, 1, start_special
},
6428 { "exit", EQUAL
, 1, start_special
},
6429 { "reset-failed", MORE
, 1, reset_failed
},
6430 { "enable", MORE
, 2, enable_unit
, NOBUS
},
6431 { "disable", MORE
, 2, enable_unit
, NOBUS
},
6432 { "is-enabled", MORE
, 2, unit_is_enabled
, NOBUS
},
6433 { "reenable", MORE
, 2, enable_unit
, NOBUS
},
6434 { "preset", MORE
, 2, enable_unit
, NOBUS
},
6435 { "mask", MORE
, 2, enable_unit
, NOBUS
},
6436 { "unmask", MORE
, 2, enable_unit
, NOBUS
},
6437 { "link", MORE
, 2, enable_unit
, NOBUS
},
6438 { "switch-root", MORE
, 2, switch_root
},
6439 { "list-dependencies", LESS
, 2, list_dependencies
},
6440 { "set-default", EQUAL
, 2, set_default
, NOBUS
},
6441 { "get-default", EQUAL
, 1, get_default
, NOBUS
},
6442 { "set-property", MORE
, 3, set_property
},
6451 left
= argc
- optind
;
6453 /* Special rule: no arguments (left == 0) means "list-units" */
6455 if (streq(argv
[optind
], "help") && !argv
[optind
+1]) {
6456 log_error("This command expects one or more "
6457 "unit names. Did you mean --help?");
6461 for (; verb
->verb
; verb
++)
6462 if (streq(argv
[optind
], verb
->verb
))
6465 log_error("Unknown operation '%s'.", argv
[optind
]);
6470 switch (verb
->argc_cmp
) {
6473 if (left
!= verb
->argc
) {
6474 log_error("Invalid number of arguments.");
6481 if (left
< verb
->argc
) {
6482 log_error("Too few arguments.");
6489 if (left
> verb
->argc
) {
6490 log_error("Too many arguments.");
6497 assert_not_reached("Unknown comparison operator.");
6500 /* Require a bus connection for all operations but
6502 if (verb
->bus
== NOBUS
) {
6503 if (!bus
&& !avoid_bus()) {
6504 log_error("Failed to get D-Bus connection: %s", strerror(-bus_error
));
6509 if (running_in_chroot() > 0) {
6510 log_info("Running in chroot, ignoring request.");
6514 if ((verb
->bus
!= FORCE
|| arg_force
<= 0) && !bus
) {
6515 log_error("Failed to get D-Bus connection: %s", strerror(-bus_error
));
6520 return verb
->dispatch(bus
, argv
+ optind
);
6523 static int send_shutdownd(usec_t t
, char mode
, bool dry_run
, bool warn
, const char *message
) {
6525 struct sd_shutdown_command c
= {
6532 union sockaddr_union sockaddr
= {
6533 .un
.sun_family
= AF_UNIX
,
6534 .un
.sun_path
= "/run/systemd/shutdownd",
6537 struct iovec iovec
[2] = {{
6538 .iov_base
= (char*) &c
,
6539 .iov_len
= offsetof(struct sd_shutdown_command
, wall_message
),
6542 struct msghdr msghdr
= {
6543 .msg_name
= &sockaddr
,
6544 .msg_namelen
= offsetof(struct sockaddr_un
, sun_path
)
6545 + strlen("/run/systemd/shutdownd"),
6550 _cleanup_close_
int fd
;
6552 fd
= socket(AF_UNIX
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0);
6556 if (!isempty(message
)) {
6557 iovec
[1].iov_base
= (char*) message
;
6558 iovec
[1].iov_len
= strlen(message
);
6559 msghdr
.msg_iovlen
++;
6562 if (sendmsg(fd
, &msghdr
, MSG_NOSIGNAL
) < 0)
6568 static int reload_with_fallback(sd_bus
*bus
) {
6571 /* First, try systemd via D-Bus. */
6572 if (daemon_reload(bus
, NULL
) >= 0)
6576 /* Nothing else worked, so let's try signals */
6577 assert(arg_action
== ACTION_RELOAD
|| arg_action
== ACTION_REEXEC
);
6579 if (kill(1, arg_action
== ACTION_RELOAD
? SIGHUP
: SIGTERM
) < 0) {
6580 log_error("kill() failed: %m");
6587 static int start_with_fallback(sd_bus
*bus
) {
6590 /* First, try systemd via D-Bus. */
6591 if (start_unit(bus
, NULL
) >= 0)
6595 /* Nothing else worked, so let's try
6597 if (talk_initctl() > 0)
6600 log_error("Failed to talk to init daemon.");
6604 warn_wall(arg_action
);
6608 static int halt_now(enum action a
) {
6610 /* Make sure C-A-D is handled by the kernel from this
6612 reboot(RB_ENABLE_CAD
);
6617 log_info("Halting.");
6618 reboot(RB_HALT_SYSTEM
);
6621 case ACTION_POWEROFF
:
6622 log_info("Powering off.");
6623 reboot(RB_POWER_OFF
);
6626 case ACTION_REBOOT
: {
6627 _cleanup_free_
char *param
= NULL
;
6629 if (read_one_line_file(REBOOT_PARAM_FILE
, ¶m
) >= 0) {
6630 log_info("Rebooting with argument '%s'.", param
);
6631 syscall(SYS_reboot
, LINUX_REBOOT_MAGIC1
, LINUX_REBOOT_MAGIC2
,
6632 LINUX_REBOOT_CMD_RESTART2
, param
);
6635 log_info("Rebooting.");
6636 reboot(RB_AUTOBOOT
);
6641 assert_not_reached("Unknown action.");
6645 static int halt_main(sd_bus
*bus
) {
6648 r
= check_inhibitors(bus
, arg_action
);
6652 if (geteuid() != 0) {
6653 /* Try logind if we are a normal user and no special
6654 * mode applies. Maybe PolicyKit allows us to shutdown
6657 if (arg_when
<= 0 &&
6660 (arg_action
== ACTION_POWEROFF
||
6661 arg_action
== ACTION_REBOOT
)) {
6662 r
= reboot_with_logind(bus
, arg_action
);
6667 log_error("Must be root.");
6672 _cleanup_free_
char *m
;
6674 m
= strv_join(arg_wall
, " ");
6678 r
= send_shutdownd(arg_when
,
6679 arg_action
== ACTION_HALT
? 'H' :
6680 arg_action
== ACTION_POWEROFF
? 'P' :
6681 arg_action
== ACTION_KEXEC
? 'K' :
6688 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r
));
6690 char date
[FORMAT_TIMESTAMP_MAX
];
6692 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
6693 format_timestamp(date
, sizeof(date
), arg_when
));
6698 if (!arg_dry
&& !arg_force
)
6699 return start_with_fallback(bus
);
6702 if (sd_booted() > 0)
6703 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
6705 r
= utmp_put_shutdown();
6707 log_warning("Failed to write utmp record: %s", strerror(-r
));
6714 r
= halt_now(arg_action
);
6715 log_error("Failed to reboot: %s", strerror(-r
));
6720 static int runlevel_main(void) {
6721 int r
, runlevel
, previous
;
6723 r
= utmp_get_runlevel(&runlevel
, &previous
);
6730 previous
<= 0 ? 'N' : previous
,
6731 runlevel
<= 0 ? 'N' : runlevel
);
6736 int main(int argc
, char*argv
[]) {
6737 _cleanup_bus_unref_ sd_bus
*bus
= NULL
;
6740 setlocale(LC_ALL
, "");
6741 log_parse_environment();
6744 /* Explicitly not on_tty() to avoid setting cached value.
6745 * This becomes relevant for piping output which might be
6747 original_stdout_is_tty
= isatty(STDOUT_FILENO
);
6749 r
= parse_argv(argc
, argv
);
6753 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
6754 * let's shortcut this */
6755 if (arg_action
== ACTION_RUNLEVEL
) {
6756 r
= runlevel_main();
6760 if (running_in_chroot() > 0 && arg_action
!= ACTION_SYSTEMCTL
) {
6761 log_info("Running in chroot, ignoring request.");
6767 r
= bus_open_transport_systemd(arg_transport
, arg_host
, arg_scope
!= UNIT_FILE_SYSTEM
, &bus
);
6769 /* systemctl_main() will print an error message for the bus
6770 * connection, but only if it needs to */
6772 switch (arg_action
) {
6774 case ACTION_SYSTEMCTL
:
6775 r
= systemctl_main(bus
, argc
, argv
, r
);
6779 case ACTION_POWEROFF
:
6785 case ACTION_RUNLEVEL2
:
6786 case ACTION_RUNLEVEL3
:
6787 case ACTION_RUNLEVEL4
:
6788 case ACTION_RUNLEVEL5
:
6790 case ACTION_EMERGENCY
:
6791 case ACTION_DEFAULT
:
6792 r
= start_with_fallback(bus
);
6797 r
= reload_with_fallback(bus
);
6800 case ACTION_CANCEL_SHUTDOWN
: {
6801 _cleanup_free_
char *m
= NULL
;
6804 m
= strv_join(arg_wall
, " ");
6811 r
= send_shutdownd(arg_when
, SD_SHUTDOWN_NONE
, false, !arg_no_wall
, m
);
6813 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r
));
6817 case ACTION_RUNLEVEL
:
6818 case _ACTION_INVALID
:
6820 assert_not_reached("Unknown action");
6825 ask_password_agent_close();
6826 polkit_agent_close();
6828 strv_free(arg_types
);
6829 strv_free(arg_states
);
6830 strv_free(arg_properties
);
6832 return r
< 0 ? EXIT_FAILURE
: r
;