1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/reboot.h>
29 #include <sys/ioctl.h>
33 #include <sys/socket.h>
36 #include <sys/prctl.h>
37 #include <dbus/dbus.h>
39 #include <systemd/sd-daemon.h>
40 #include <systemd/sd-shutdown.h>
41 #include <systemd/sd-login.h>
47 #include "utmp-wtmp.h"
50 #include "path-util.h"
52 #include "dbus-common.h"
53 #include "cgroup-show.h"
54 #include "cgroup-util.h"
56 #include "path-lookup.h"
57 #include "conf-parser.h"
58 #include "exit-status.h"
59 #include "bus-errors.h"
61 #include "unit-name.h"
63 #include "spawn-ask-password-agent.h"
64 #include "spawn-polkit-agent.h"
66 #include "logs-show.h"
67 #include "path-util.h"
68 #include "socket-util.h"
71 static char **arg_types
= NULL
;
72 static char **arg_load_states
= NULL
;
73 static char **arg_properties
= NULL
;
74 static bool arg_all
= false;
75 static enum dependency
{
80 } arg_dependency
= DEPENDENCY_FORWARD
;
81 static const char *arg_job_mode
= "replace";
82 static UnitFileScope arg_scope
= UNIT_FILE_SYSTEM
;
83 static bool arg_no_block
= false;
84 static bool arg_no_legend
= false;
85 static bool arg_no_pager
= false;
86 static bool arg_no_wtmp
= false;
87 static bool arg_no_wall
= false;
88 static bool arg_no_reload
= false;
89 static bool arg_show_types
= false;
90 static bool arg_ignore_inhibitors
= false;
91 static bool arg_dry
= false;
92 static bool arg_quiet
= false;
93 static bool arg_full
= false;
94 static int arg_force
= 0;
95 static bool arg_ask_password
= true;
96 static bool arg_failed
= false;
97 static bool arg_runtime
= false;
98 static char **arg_wall
= NULL
;
99 static const char *arg_kill_who
= NULL
;
100 static int arg_signal
= SIGTERM
;
101 static const char *arg_root
= NULL
;
102 static usec_t arg_when
= 0;
124 ACTION_CANCEL_SHUTDOWN
,
126 } arg_action
= ACTION_SYSTEMCTL
;
127 static enum transport
{
131 } arg_transport
= TRANSPORT_NORMAL
;
132 static const char *arg_host
= NULL
;
133 static unsigned arg_lines
= 10;
134 static OutputMode arg_output
= OUTPUT_SHORT
;
135 static bool arg_plain
= false;
137 static bool private_bus
= false;
139 static int daemon_reload(DBusConnection
*bus
, char **args
);
140 static void halt_now(enum action a
);
142 static void pager_open_if_enabled(void) {
150 static void ask_password_agent_open_if_enabled(void) {
152 /* Open the password agent as a child process if necessary */
154 if (!arg_ask_password
)
157 if (arg_scope
!= UNIT_FILE_SYSTEM
)
160 ask_password_agent_open();
164 static void polkit_agent_open_if_enabled(void) {
166 /* Open the polkit agent as a child process if necessary */
168 if (!arg_ask_password
)
171 if (arg_scope
!= UNIT_FILE_SYSTEM
)
178 static const char *ansi_highlight(bool b
) {
183 return b
? ANSI_HIGHLIGHT_ON
: ANSI_HIGHLIGHT_OFF
;
186 static const char *ansi_highlight_red(bool b
) {
191 return b
? ANSI_HIGHLIGHT_RED_ON
: ANSI_HIGHLIGHT_OFF
;
194 static const char *ansi_highlight_green(bool b
) {
199 return b
? ANSI_HIGHLIGHT_GREEN_ON
: ANSI_HIGHLIGHT_OFF
;
202 static int translate_bus_error_to_exit_status(int r
, const DBusError
*error
) {
205 if (!dbus_error_is_set(error
))
208 if (dbus_error_has_name(error
, DBUS_ERROR_ACCESS_DENIED
) ||
209 dbus_error_has_name(error
, BUS_ERROR_ONLY_BY_DEPENDENCY
) ||
210 dbus_error_has_name(error
, BUS_ERROR_NO_ISOLATION
) ||
211 dbus_error_has_name(error
, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE
))
212 return EXIT_NOPERMISSION
;
214 if (dbus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
))
215 return EXIT_NOTINSTALLED
;
217 if (dbus_error_has_name(error
, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE
) ||
218 dbus_error_has_name(error
, BUS_ERROR_NOT_SUPPORTED
))
219 return EXIT_NOTIMPLEMENTED
;
221 if (dbus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
))
222 return EXIT_NOTCONFIGURED
;
230 static void warn_wall(enum action a
) {
231 static const char *table
[_ACTION_MAX
] = {
232 [ACTION_HALT
] = "The system is going down for system halt NOW!",
233 [ACTION_REBOOT
] = "The system is going down for reboot NOW!",
234 [ACTION_POWEROFF
] = "The system is going down for power-off NOW!",
235 [ACTION_KEXEC
] = "The system is going down for kexec reboot NOW!",
236 [ACTION_RESCUE
] = "The system is going down to rescue mode NOW!",
237 [ACTION_EMERGENCY
] = "The system is going down to emergency mode NOW!",
238 [ACTION_CANCEL_SHUTDOWN
] = "The system shutdown has been cancelled NOW!"
245 _cleanup_free_
char *p
;
247 p
= strv_join(arg_wall
, " ");
262 utmp_wall(table
[a
], NULL
);
265 static bool avoid_bus(void) {
267 if (running_in_chroot() > 0)
270 if (sd_booted() <= 0)
273 if (!isempty(arg_root
))
276 if (arg_scope
== UNIT_FILE_GLOBAL
)
282 static int compare_unit_info(const void *a
, const void *b
) {
284 const struct unit_info
*u
= a
, *v
= b
;
286 d1
= strrchr(u
->id
, '.');
287 d2
= strrchr(v
->id
, '.');
292 r
= strcasecmp(d1
, d2
);
297 return strcasecmp(u
->id
, v
->id
);
300 static bool output_show_unit(const struct unit_info
*u
) {
304 return streq(u
->active_state
, "failed");
306 return (!arg_types
|| ((dot
= strrchr(u
->id
, '.')) &&
307 strv_find(arg_types
, dot
+1))) &&
308 (!arg_load_states
|| strv_find(arg_load_states
, u
->load_state
)) &&
309 (arg_all
|| !(streq(u
->active_state
, "inactive")
310 || u
->following
[0]) || u
->job_id
> 0);
313 static void output_units_list(const struct unit_info
*unit_infos
, unsigned c
) {
314 unsigned id_len
, max_id_len
, active_len
, sub_len
, job_len
, desc_len
, n_shown
= 0;
315 const struct unit_info
*u
;
318 max_id_len
= sizeof("UNIT")-1;
319 active_len
= sizeof("ACTIVE")-1;
320 sub_len
= sizeof("SUB")-1;
321 job_len
= sizeof("JOB")-1;
324 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
325 if (!output_show_unit(u
))
328 max_id_len
= MAX(max_id_len
, strlen(u
->id
));
329 active_len
= MAX(active_len
, strlen(u
->active_state
));
330 sub_len
= MAX(sub_len
, strlen(u
->sub_state
));
331 if (u
->job_id
!= 0) {
332 job_len
= MAX(job_len
, strlen(u
->job_type
));
339 id_len
= MIN(max_id_len
, 25u);
340 basic_len
= 5 + id_len
+ 5 + active_len
+ sub_len
;
342 basic_len
+= job_len
+ 1;
343 if (basic_len
< (unsigned) columns()) {
344 unsigned extra_len
, incr
;
345 extra_len
= columns() - basic_len
;
346 /* Either UNIT already got 25, or is fully satisfied.
347 * Grant up to 25 to DESC now. */
348 incr
= MIN(extra_len
, 25u);
351 /* split the remaining space between UNIT and DESC,
352 * but do not give UNIT more than it needs. */
354 incr
= MIN(extra_len
/ 2, max_id_len
- id_len
);
356 desc_len
+= extra_len
- incr
;
362 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
363 _cleanup_free_
char *e
= NULL
;
364 const char *on_loaded
, *off_loaded
, *on
= "";
365 const char *on_active
, *off_active
, *off
= "";
367 if (!output_show_unit(u
))
370 if (!n_shown
&& !arg_no_legend
) {
371 printf("%-*s %-6s %-*s %-*s ", id_len
, "UNIT", "LOAD",
372 active_len
, "ACTIVE", sub_len
, "SUB");
374 printf("%-*s ", job_len
, "JOB");
375 if (!arg_full
&& arg_no_pager
)
376 printf("%.*s\n", desc_len
, "DESCRIPTION");
378 printf("%s\n", "DESCRIPTION");
383 if (streq(u
->load_state
, "error")) {
384 on_loaded
= on
= ansi_highlight_red(true);
385 off_loaded
= off
= ansi_highlight_red(false);
387 on_loaded
= off_loaded
= "";
389 if (streq(u
->active_state
, "failed")) {
390 on_active
= on
= ansi_highlight_red(true);
391 off_active
= off
= ansi_highlight_red(false);
393 on_active
= off_active
= "";
395 e
= arg_full
? NULL
: ellipsize(u
->id
, id_len
, 33);
397 printf("%s%-*s%s %s%-6s%s %s%-*s %-*s%s %-*s",
398 on
, id_len
, e
? e
: u
->id
, off
,
399 on_loaded
, u
->load_state
, off_loaded
,
400 on_active
, active_len
, u
->active_state
,
401 sub_len
, u
->sub_state
, off_active
,
402 job_count
? job_len
+ 1 : 0, u
->job_id
? u
->job_type
: "");
403 if (!arg_full
&& arg_no_pager
)
404 printf("%.*s\n", desc_len
, u
->description
);
406 printf("%s\n", u
->description
);
409 if (!arg_no_legend
) {
410 const char *on
, *off
;
413 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
414 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
415 "SUB = The low-level unit activation state, values depend on unit type.\n");
417 printf("JOB = Pending job for the unit.\n");
419 on
= ansi_highlight(true);
420 off
= ansi_highlight(false);
422 on
= ansi_highlight_red(true);
423 off
= ansi_highlight_red(false);
427 printf("%s%u loaded units listed.%s\n"
428 "To show all installed unit files use 'systemctl list-unit-files'.\n",
431 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
432 "To show all installed unit files use 'systemctl list-unit-files'.\n",
437 static int get_unit_list(DBusConnection
*bus
, DBusMessage
**reply
,
438 struct unit_info
**unit_infos
, unsigned *c
) {
439 DBusMessageIter iter
, sub
;
447 r
= bus_method_call_with_reply(
449 "org.freedesktop.systemd1",
450 "/org/freedesktop/systemd1",
451 "org.freedesktop.systemd1.Manager",
459 if (!dbus_message_iter_init(*reply
, &iter
) ||
460 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_ARRAY
||
461 dbus_message_iter_get_element_type(&iter
) != DBUS_TYPE_STRUCT
) {
462 log_error("Failed to parse reply.");
466 dbus_message_iter_recurse(&iter
, &sub
);
468 while (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_INVALID
) {
469 if (!GREEDY_REALLOC(*unit_infos
, size
, *c
+ 1))
472 bus_parse_unit_info(&sub
, *unit_infos
+ *c
);
475 dbus_message_iter_next(&sub
);
481 static int list_units(DBusConnection
*bus
, char **args
) {
482 _cleanup_dbus_message_unref_ DBusMessage
*reply
= NULL
;
483 _cleanup_free_
struct unit_info
*unit_infos
= NULL
;
487 pager_open_if_enabled();
489 r
= get_unit_list(bus
, &reply
, &unit_infos
, &c
);
493 qsort(unit_infos
, c
, sizeof(struct unit_info
), compare_unit_info
);
495 output_units_list(unit_infos
, c
);
500 static int get_triggered_units(DBusConnection
*bus
, const char* unit_path
,
503 const char *interface
= "org.freedesktop.systemd1.Unit",
504 *triggers_property
= "Triggers";
505 _cleanup_dbus_message_unref_ DBusMessage
*reply
= NULL
;
506 DBusMessageIter iter
, sub
;
509 r
= bus_method_call_with_reply(bus
,
510 "org.freedesktop.systemd1",
512 "org.freedesktop.DBus.Properties",
516 DBUS_TYPE_STRING
, &interface
,
517 DBUS_TYPE_STRING
, &triggers_property
,
522 if (!dbus_message_iter_init(reply
, &iter
) ||
523 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_VARIANT
) {
524 log_error("Failed to parse reply.");
528 dbus_message_iter_recurse(&iter
, &sub
);
529 dbus_message_iter_recurse(&sub
, &iter
);
532 while (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_INVALID
) {
535 if (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_STRING
) {
536 log_error("Failed to parse reply.");
540 dbus_message_iter_get_basic(&sub
, &unit
);
541 r
= strv_extend(triggered
, unit
);
545 dbus_message_iter_next(&sub
);
551 static int get_listening(DBusConnection
*bus
, const char* unit_path
,
552 char*** listen
, unsigned *c
)
554 const char *interface
= "org.freedesktop.systemd1.Socket",
555 *listen_property
= "Listen";
556 _cleanup_dbus_message_unref_ DBusMessage
*reply
= NULL
;
557 DBusMessageIter iter
, sub
;
560 r
= bus_method_call_with_reply(bus
,
561 "org.freedesktop.systemd1",
563 "org.freedesktop.DBus.Properties",
567 DBUS_TYPE_STRING
, &interface
,
568 DBUS_TYPE_STRING
, &listen_property
,
573 if (!dbus_message_iter_init(reply
, &iter
) ||
574 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_VARIANT
) {
575 log_error("Failed to parse reply.");
579 dbus_message_iter_recurse(&iter
, &sub
);
580 dbus_message_iter_recurse(&sub
, &iter
);
583 while (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_INVALID
) {
584 DBusMessageIter sub2
;
585 const char *type
, *path
;
587 if (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_STRUCT
) {
588 log_error("Failed to parse reply.");
592 dbus_message_iter_recurse(&sub
, &sub2
);
594 if (bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &type
, true) >= 0 &&
595 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &path
, false) >= 0) {
596 r
= strv_extend(listen
, type
);
600 r
= strv_extend(listen
, path
);
607 dbus_message_iter_next(&sub
);
619 /* Note: triggered is a list here, although it almost certainly
620 * will always be one unit. Nevertheless, dbus API allows for multiple
621 * values, so let's follow that.*/
624 /* The strv above is shared. free is set only in the first one. */
628 static int socket_info_compare(struct socket_info
*a
, struct socket_info
*b
) {
629 int o
= strcmp(a
->path
, b
->path
);
631 o
= strcmp(a
->type
, b
->type
);
635 static int output_sockets_list(struct socket_info
*socket_infos
, unsigned cs
) {
636 struct socket_info
*s
;
637 unsigned pathlen
= sizeof("LISTEN") - 1,
638 typelen
= (sizeof("TYPE") - 1) * arg_show_types
,
639 socklen
= sizeof("UNIT") - 1,
640 servlen
= sizeof("ACTIVATES") - 1;
641 const char *on
, *off
;
643 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
647 socklen
= MAX(socklen
, strlen(s
->id
));
649 typelen
= MAX(typelen
, strlen(s
->type
));
650 pathlen
= MAX(pathlen
, strlen(s
->path
));
652 STRV_FOREACH(a
, s
->triggered
)
653 tmp
+= strlen(*a
) + 2*(a
!= s
->triggered
);
654 servlen
= MAX(servlen
, tmp
);
658 printf("%-*s %-*.*s%-*s %s\n",
660 typelen
+ arg_show_types
, typelen
+ arg_show_types
, "TYPE ",
664 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
668 printf("%-*s %-*s %-*s",
669 pathlen
, s
->path
, typelen
, s
->type
, socklen
, s
->id
);
672 pathlen
, s
->path
, socklen
, s
->id
);
673 STRV_FOREACH(a
, s
->triggered
)
675 a
== s
->triggered
? "" : ",", *a
);
679 on
= ansi_highlight(true);
680 off
= ansi_highlight(false);
683 on
= ansi_highlight_red(true);
684 off
= ansi_highlight_red(false);
687 printf("%s%u sockets listed.%s\n", on
, cs
, off
);
689 printf("Pass --all to see loaded but inactive sockets, too.\n");
694 static int list_sockets(DBusConnection
*bus
, char **args
) {
695 _cleanup_dbus_message_unref_ DBusMessage
*reply
= NULL
;
696 _cleanup_free_
struct unit_info
*unit_infos
= NULL
;
697 struct socket_info
*socket_infos
= NULL
;
698 const struct unit_info
*u
;
699 struct socket_info
*s
;
700 unsigned cu
= 0, cs
= 0;
704 pager_open_if_enabled();
706 r
= get_unit_list(bus
, &reply
, &unit_infos
, &cu
);
710 for (u
= unit_infos
; u
< unit_infos
+ cu
; u
++) {
712 _cleanup_strv_free_
char **listen
= NULL
, **triggered
= NULL
;
715 if (!output_show_unit(u
))
718 if ((dot
= strrchr(u
->id
, '.')) && !streq(dot
+1, "socket"))
721 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
725 r
= get_listening(bus
, u
->unit_path
, &listen
, &c
);
729 if (!GREEDY_REALLOC(socket_infos
, size
, cs
+ c
)) {
734 for (i
= 0; i
< c
; i
++)
735 socket_infos
[cs
+ i
] = (struct socket_info
) {
738 .path
= listen
[i
*2 + 1],
739 .triggered
= triggered
,
740 .own_triggered
= i
==0,
743 /* from this point on we will cleanup those socket_infos */
746 listen
= triggered
= NULL
; /* avoid cleanup */
749 qsort(socket_infos
, cs
, sizeof(struct socket_info
),
750 (__compar_fn_t
) socket_info_compare
);
752 output_sockets_list(socket_infos
, cs
);
755 assert(cs
== 0 || socket_infos
);
756 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
759 if (s
->own_triggered
)
760 strv_free(s
->triggered
);
767 static int compare_unit_file_list(const void *a
, const void *b
) {
769 const UnitFileList
*u
= a
, *v
= b
;
771 d1
= strrchr(u
->path
, '.');
772 d2
= strrchr(v
->path
, '.');
777 r
= strcasecmp(d1
, d2
);
782 return strcasecmp(path_get_file_name(u
->path
), path_get_file_name(v
->path
));
785 static bool output_show_unit_file(const UnitFileList
*u
) {
788 return !arg_types
|| ((dot
= strrchr(u
->path
, '.')) && strv_find(arg_types
, dot
+1));
791 static void output_unit_file_list(const UnitFileList
*units
, unsigned c
) {
792 unsigned max_id_len
, id_cols
, state_cols
, n_shown
= 0;
793 const UnitFileList
*u
;
795 max_id_len
= sizeof("UNIT FILE")-1;
796 state_cols
= sizeof("STATE")-1;
797 for (u
= units
; u
< units
+ c
; u
++) {
798 if (!output_show_unit_file(u
))
801 max_id_len
= MAX(max_id_len
, strlen(path_get_file_name(u
->path
)));
802 state_cols
= MAX(state_cols
, strlen(unit_file_state_to_string(u
->state
)));
807 id_cols
= MIN(max_id_len
, 25u);
808 basic_cols
= 1 + id_cols
+ state_cols
;
809 if (basic_cols
< (unsigned) columns())
810 id_cols
+= MIN(columns() - basic_cols
, max_id_len
- id_cols
);
812 id_cols
= max_id_len
;
815 printf("%-*s %-*s\n", id_cols
, "UNIT FILE", state_cols
, "STATE");
817 for (u
= units
; u
< units
+ c
; u
++) {
818 _cleanup_free_
char *e
= NULL
;
819 const char *on
, *off
;
822 if (!output_show_unit_file(u
))
827 if (u
->state
== UNIT_FILE_MASKED
||
828 u
->state
== UNIT_FILE_MASKED_RUNTIME
||
829 u
->state
== UNIT_FILE_DISABLED
||
830 u
->state
== UNIT_FILE_INVALID
) {
831 on
= ansi_highlight_red(true);
832 off
= ansi_highlight_red(false);
833 } else if (u
->state
== UNIT_FILE_ENABLED
) {
834 on
= ansi_highlight_green(true);
835 off
= ansi_highlight_green(false);
839 id
= path_get_file_name(u
->path
);
841 e
= arg_full
? NULL
: ellipsize(id
, id_cols
, 33);
843 printf("%-*s %s%-*s%s\n",
845 on
, state_cols
, unit_file_state_to_string(u
->state
), off
);
849 printf("\n%u unit files listed.\n", n_shown
);
852 static int list_unit_files(DBusConnection
*bus
, char **args
) {
853 _cleanup_dbus_message_unref_ DBusMessage
*reply
= NULL
;
854 _cleanup_free_ UnitFileList
*units
= NULL
;
855 DBusMessageIter iter
, sub
, sub2
;
856 unsigned c
= 0, n_units
= 0;
859 pager_open_if_enabled();
866 h
= hashmap_new(string_hash_func
, string_compare_func
);
870 r
= unit_file_get_list(arg_scope
, arg_root
, h
);
872 unit_file_list_free(h
);
873 log_error("Failed to get unit file list: %s", strerror(-r
));
877 n_units
= hashmap_size(h
);
878 units
= new(UnitFileList
, n_units
);
880 unit_file_list_free(h
);
884 HASHMAP_FOREACH(u
, h
, i
) {
885 memcpy(units
+ c
++, u
, sizeof(UnitFileList
));
891 r
= bus_method_call_with_reply(
893 "org.freedesktop.systemd1",
894 "/org/freedesktop/systemd1",
895 "org.freedesktop.systemd1.Manager",
903 if (!dbus_message_iter_init(reply
, &iter
) ||
904 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_ARRAY
||
905 dbus_message_iter_get_element_type(&iter
) != DBUS_TYPE_STRUCT
) {
906 log_error("Failed to parse reply.");
910 dbus_message_iter_recurse(&iter
, &sub
);
912 while (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_INVALID
) {
916 assert(dbus_message_iter_get_arg_type(&sub
) == DBUS_TYPE_STRUCT
);
921 n_units
= MAX(2*c
, 16u);
922 w
= realloc(units
, sizeof(struct UnitFileList
) * n_units
);
931 dbus_message_iter_recurse(&sub
, &sub2
);
933 if (bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &u
->path
, true) < 0 ||
934 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &state
, false) < 0) {
935 log_error("Failed to parse reply.");
939 u
->state
= unit_file_state_from_string(state
);
941 dbus_message_iter_next(&sub
);
947 qsort(units
, c
, sizeof(UnitFileList
), compare_unit_file_list
);
948 output_unit_file_list(units
, c
);
954 static int list_dependencies_print(const char *name
, int level
, unsigned int branches
, bool last
) {
956 _cleanup_free_
char *n
= NULL
;
958 size_t max_len
= MAX(columns(),20u);
961 for (i
= level
- 1; i
>= 0; i
--) {
963 if(len
> max_len
- 3 && !arg_full
) {
964 printf("%s...\n",max_len
% 2 ? "" : " ");
967 printf("%s", draw_special_char(branches
& (1 << i
) ? DRAW_TREE_VERT
: DRAW_TREE_SPACE
));
970 if(len
> max_len
- 3 && !arg_full
) {
971 printf("%s...\n",max_len
% 2 ? "" : " ");
974 printf("%s", draw_special_char(last
? DRAW_TREE_RIGHT
: DRAW_TREE_BRANCH
));
978 printf("%s\n", name
);
982 n
= ellipsize(name
, max_len
-len
, 100);
990 static int list_dependencies_get_dependencies(DBusConnection
*bus
, const char *name
, char ***deps
) {
991 static const char *dependencies
[] = {
992 [DEPENDENCY_FORWARD
] = "Requires\0"
993 "RequiresOverridable\0"
995 "RequisiteOverridable\0"
997 [DEPENDENCY_REVERSE
] = "RequiredBy\0"
998 "RequiredByOverridable\0"
1001 [DEPENDENCY_AFTER
] = "After\0",
1002 [DEPENDENCY_BEFORE
] = "Before\0",
1005 _cleanup_free_
char *path
;
1006 const char *interface
= "org.freedesktop.systemd1.Unit";
1008 _cleanup_dbus_message_unref_ DBusMessage
*reply
= NULL
;
1009 DBusMessageIter iter
, sub
, sub2
, sub3
;
1018 path
= unit_dbus_path_from_name(name
);
1024 r
= bus_method_call_with_reply(
1026 "org.freedesktop.systemd1",
1028 "org.freedesktop.DBus.Properties",
1032 DBUS_TYPE_STRING
, &interface
,
1037 if (!dbus_message_iter_init(reply
, &iter
) ||
1038 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_ARRAY
||
1039 dbus_message_iter_get_element_type(&iter
) != DBUS_TYPE_DICT_ENTRY
) {
1040 log_error("Failed to parse reply.");
1045 dbus_message_iter_recurse(&iter
, &sub
);
1047 while (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_INVALID
) {
1050 assert(dbus_message_iter_get_arg_type(&sub
) == DBUS_TYPE_DICT_ENTRY
);
1051 dbus_message_iter_recurse(&sub
, &sub2
);
1053 if (bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &prop
, true) < 0) {
1054 log_error("Failed to parse reply.");
1059 if (dbus_message_iter_get_arg_type(&sub2
) != DBUS_TYPE_VARIANT
) {
1060 log_error("Failed to parse reply.");
1065 dbus_message_iter_recurse(&sub2
, &sub3
);
1066 dbus_message_iter_next(&sub
);
1068 assert(arg_dependency
< ELEMENTSOF(dependencies
));
1069 if (!nulstr_contains(dependencies
[arg_dependency
], prop
))
1072 if (dbus_message_iter_get_arg_type(&sub3
) == DBUS_TYPE_ARRAY
) {
1073 if (dbus_message_iter_get_element_type(&sub3
) == DBUS_TYPE_STRING
) {
1074 DBusMessageIter sub4
;
1075 dbus_message_iter_recurse(&sub3
, &sub4
);
1077 while (dbus_message_iter_get_arg_type(&sub4
) != DBUS_TYPE_INVALID
) {
1080 assert(dbus_message_iter_get_arg_type(&sub4
) == DBUS_TYPE_STRING
);
1081 dbus_message_iter_get_basic(&sub4
, &s
);
1083 r
= strv_extend(&ret
, s
);
1089 dbus_message_iter_next(&sub4
);
1102 static int list_dependencies_compare(const void *_a
, const void *_b
) {
1103 const char **a
= (const char**) _a
, **b
= (const char**) _b
;
1104 if (unit_name_to_type(*a
) == UNIT_TARGET
&& unit_name_to_type(*b
) != UNIT_TARGET
)
1106 if (unit_name_to_type(*a
) != UNIT_TARGET
&& unit_name_to_type(*b
) == UNIT_TARGET
)
1108 return strcasecmp(*a
, *b
);
1111 static int list_dependencies_one(DBusConnection
*bus
, const char *name
, int level
, char ***units
, unsigned int branches
) {
1112 _cleanup_strv_free_
char **deps
= NULL
, **u
;
1116 u
= strv_append(*units
, name
);
1120 r
= list_dependencies_get_dependencies(bus
, name
, &deps
);
1124 qsort(deps
, strv_length(deps
), sizeof (char*), list_dependencies_compare
);
1126 STRV_FOREACH(c
, deps
) {
1127 if (strv_contains(u
, *c
)) {
1129 r
= list_dependencies_print("...", level
+ 1, (branches
<< 1) | (c
[1] == NULL
? 0 : 1), 1);
1136 r
= list_dependencies_print(*c
, level
, branches
, c
[1] == NULL
);
1140 if (arg_all
|| unit_name_to_type(*c
) == UNIT_TARGET
) {
1141 r
= list_dependencies_one(bus
, *c
, level
+ 1, &u
, (branches
<< 1) | (c
[1] == NULL
? 0 : 1));
1154 static int list_dependencies(DBusConnection
*bus
, char **args
) {
1155 _cleanup_free_
char *unit
= NULL
;
1156 _cleanup_strv_free_
char **units
= NULL
;
1162 unit
= unit_name_mangle(args
[1]);
1167 u
= SPECIAL_DEFAULT_TARGET
;
1169 pager_open_if_enabled();
1173 return list_dependencies_one(bus
, u
, 0, &units
, 0);
1178 char *name
, *type
, *state
;
1181 static void list_jobs_print(struct job_info
* jobs
, size_t n
) {
1184 const char *on
, *off
;
1185 bool shorten
= false;
1187 assert(n
== 0 || jobs
);
1190 on
= ansi_highlight_green(true);
1191 off
= ansi_highlight_green(false);
1193 printf("%sNo jobs running.%s\n", on
, off
);
1197 pager_open_if_enabled();
1200 /* JOB UNIT TYPE STATE */
1201 unsigned l0
= 3, l1
= 4, l2
= 4, l3
= 5;
1203 for (i
= 0, j
= jobs
; i
< n
; i
++, j
++) {
1204 assert(j
->name
&& j
->type
&& j
->state
);
1205 l0
= MAX(l0
, DECIMAL_STR_WIDTH(j
->id
));
1206 l1
= MAX(l1
, strlen(j
->name
));
1207 l2
= MAX(l2
, strlen(j
->type
));
1208 l3
= MAX(l3
, strlen(j
->state
));
1211 if (!arg_full
&& l0
+ 1 + l1
+ l2
+ 1 + l3
> columns()) {
1212 l1
= MAX(33u, columns() - l0
- l2
- l3
- 3);
1217 printf("%*s %-*s %-*s %-*s\n",
1223 for (i
= 0, j
= jobs
; i
< n
; i
++, j
++) {
1224 _cleanup_free_
char *e
= NULL
;
1226 if (streq(j
->state
, "running")) {
1227 on
= ansi_highlight(true);
1228 off
= ansi_highlight(false);
1232 e
= shorten
? ellipsize(j
->name
, l1
, 33) : NULL
;
1233 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
1235 on
, l1
, e
? e
: j
->name
, off
,
1237 on
, l3
, j
->state
, off
);
1241 on
= ansi_highlight(true);
1242 off
= ansi_highlight(false);
1245 printf("\n%s%zu jobs listed%s.\n", on
, n
, off
);
1248 static int list_jobs(DBusConnection
*bus
, char **args
) {
1249 _cleanup_dbus_message_unref_ DBusMessage
*reply
= NULL
;
1250 DBusMessageIter iter
, sub
, sub2
;
1252 struct job_info
*jobs
= NULL
;
1253 size_t size
= 0, used
= 0;
1255 r
= bus_method_call_with_reply(
1257 "org.freedesktop.systemd1",
1258 "/org/freedesktop/systemd1",
1259 "org.freedesktop.systemd1.Manager",
1267 if (!dbus_message_iter_init(reply
, &iter
) ||
1268 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_ARRAY
||
1269 dbus_message_iter_get_element_type(&iter
) != DBUS_TYPE_STRUCT
) {
1270 log_error("Failed to parse reply.");
1274 dbus_message_iter_recurse(&iter
, &sub
);
1276 while (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_INVALID
) {
1277 const char *name
, *type
, *state
, *job_path
, *unit_path
;
1280 if (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_STRUCT
) {
1281 log_error("Failed to parse reply.");
1285 dbus_message_iter_recurse(&sub
, &sub2
);
1287 if (bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_UINT32
, &id
, true) < 0 ||
1288 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &name
, true) < 0 ||
1289 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &type
, true) < 0 ||
1290 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &state
, true) < 0 ||
1291 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_OBJECT_PATH
, &job_path
, true) < 0 ||
1292 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_OBJECT_PATH
, &unit_path
, false) < 0) {
1293 log_error("Failed to parse reply.");
1298 if (!greedy_realloc((void**) &jobs
, &size
,
1299 sizeof(struct job_info
) * (used
+ 1))) {
1304 jobs
[used
++] = (struct job_info
) { id
,
1308 if (!jobs
[used
-1].name
|| !jobs
[used
-1].type
|| !jobs
[used
-1].state
) {
1313 dbus_message_iter_next(&sub
);
1316 list_jobs_print(jobs
, used
);
1320 free(jobs
[used
].name
);
1321 free(jobs
[used
].type
);
1322 free(jobs
[used
].state
);
1329 static int load_unit(DBusConnection
*bus
, char **args
) {
1334 STRV_FOREACH(name
, args
+1) {
1335 _cleanup_free_
char *n
= NULL
;
1338 n
= unit_name_mangle(*name
);
1342 r
= bus_method_call_with_reply(
1344 "org.freedesktop.systemd1",
1345 "/org/freedesktop/systemd1",
1346 "org.freedesktop.systemd1.Manager",
1350 DBUS_TYPE_STRING
, &n
,
1359 static int cancel_job(DBusConnection
*bus
, char **args
) {
1364 if (strv_length(args
) <= 1)
1365 return daemon_reload(bus
, args
);
1367 STRV_FOREACH(name
, args
+1) {
1371 r
= safe_atou32(*name
, &id
);
1373 log_error("Failed to parse job id: %s", strerror(-r
));
1377 r
= bus_method_call_with_reply(
1379 "org.freedesktop.systemd1",
1380 "/org/freedesktop/systemd1",
1381 "org.freedesktop.systemd1.Manager",
1385 DBUS_TYPE_UINT32
, &id
,
1394 static bool need_daemon_reload(DBusConnection
*bus
, const char *unit
) {
1395 _cleanup_dbus_message_unref_ DBusMessage
*reply
= NULL
;
1396 dbus_bool_t b
= FALSE
;
1397 DBusMessageIter iter
, sub
;
1399 *interface
= "org.freedesktop.systemd1.Unit",
1400 *property
= "NeedDaemonReload",
1402 _cleanup_free_
char *n
= NULL
;
1405 /* We ignore all errors here, since this is used to show a warning only */
1407 n
= unit_name_mangle(unit
);
1411 r
= bus_method_call_with_reply(
1413 "org.freedesktop.systemd1",
1414 "/org/freedesktop/systemd1",
1415 "org.freedesktop.systemd1.Manager",
1419 DBUS_TYPE_STRING
, &n
,
1424 if (!dbus_message_get_args(reply
, NULL
,
1425 DBUS_TYPE_OBJECT_PATH
, &path
,
1429 dbus_message_unref(reply
);
1432 r
= bus_method_call_with_reply(
1434 "org.freedesktop.systemd1",
1436 "org.freedesktop.DBus.Properties",
1440 DBUS_TYPE_STRING
, &interface
,
1441 DBUS_TYPE_STRING
, &property
,
1446 if (!dbus_message_iter_init(reply
, &iter
) ||
1447 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_VARIANT
)
1450 dbus_message_iter_recurse(&iter
, &sub
);
1451 if (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_BOOLEAN
)
1454 dbus_message_iter_get_basic(&sub
, &b
);
1458 typedef struct WaitData
{
1465 static DBusHandlerResult
wait_filter(DBusConnection
*connection
, DBusMessage
*message
, void *data
) {
1466 _cleanup_dbus_error_free_ DBusError error
;
1469 dbus_error_init(&error
);
1475 log_debug("Got D-Bus request: %s.%s() on %s",
1476 dbus_message_get_interface(message
),
1477 dbus_message_get_member(message
),
1478 dbus_message_get_path(message
));
1480 if (dbus_message_is_signal(message
, DBUS_INTERFACE_LOCAL
, "Disconnected")) {
1481 log_error("Warning! D-Bus connection terminated.");
1482 dbus_connection_close(connection
);
1484 } else if (dbus_message_is_signal(message
, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1486 const char *path
, *result
, *unit
;
1488 if (dbus_message_get_args(message
, &error
,
1489 DBUS_TYPE_UINT32
, &id
,
1490 DBUS_TYPE_OBJECT_PATH
, &path
,
1491 DBUS_TYPE_STRING
, &unit
,
1492 DBUS_TYPE_STRING
, &result
,
1493 DBUS_TYPE_INVALID
)) {
1495 free(set_remove(d
->set
, (char*) path
));
1497 if (!isempty(result
))
1498 d
->result
= strdup(result
);
1501 d
->name
= strdup(unit
);
1503 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED
;
1506 dbus_error_free(&error
);
1507 if (dbus_message_get_args(message
, &error
,
1508 DBUS_TYPE_UINT32
, &id
,
1509 DBUS_TYPE_OBJECT_PATH
, &path
,
1510 DBUS_TYPE_STRING
, &result
,
1511 DBUS_TYPE_INVALID
)) {
1512 /* Compatibility with older systemd versions <
1513 * 183 during upgrades. This should be dropped
1515 free(set_remove(d
->set
, (char*) path
));
1518 d
->result
= strdup(result
);
1520 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED
;
1524 log_error("Failed to parse message: %s", bus_error_message(&error
));
1527 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED
;
1530 static int enable_wait_for_jobs(DBusConnection
*bus
) {
1538 dbus_error_init(&error
);
1539 dbus_bus_add_match(bus
,
1541 "sender='org.freedesktop.systemd1',"
1542 "interface='org.freedesktop.systemd1.Manager',"
1543 "member='JobRemoved',"
1544 "path='/org/freedesktop/systemd1'",
1547 if (dbus_error_is_set(&error
)) {
1548 log_error("Failed to add match: %s", bus_error_message(&error
));
1549 dbus_error_free(&error
);
1553 /* This is slightly dirty, since we don't undo the match registrations. */
1557 static int wait_for_jobs(DBusConnection
*bus
, Set
*s
) {
1559 WaitData d
= { .set
= s
};
1564 if (!dbus_connection_add_filter(bus
, wait_filter
, &d
, NULL
))
1567 while (!set_isempty(s
)) {
1569 if (!dbus_connection_read_write_dispatch(bus
, -1)) {
1570 log_error("Disconnected from bus.");
1571 return -ECONNREFUSED
;
1578 if (streq(d
.result
, "timeout"))
1579 log_error("Job for %s timed out.", strna(d
.name
));
1580 else if (streq(d
.result
, "canceled"))
1581 log_error("Job for %s canceled.", strna(d
.name
));
1582 else if (streq(d
.result
, "dependency"))
1583 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d
.name
));
1584 else if (!streq(d
.result
, "done") && !streq(d
.result
, "skipped"))
1585 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d
.name
), strna(d
.name
));
1588 if (streq_ptr(d
.result
, "timeout"))
1590 else if (streq_ptr(d
.result
, "canceled"))
1592 else if (!streq_ptr(d
.result
, "done") && !streq_ptr(d
.result
, "skipped"))
1603 dbus_connection_remove_filter(bus
, wait_filter
, &d
);
1607 static int check_one_unit(DBusConnection
*bus
, const char *name
, char **check_states
, bool quiet
) {
1608 _cleanup_dbus_message_unref_ DBusMessage
*reply
= NULL
;
1609 _cleanup_free_
char *n
= NULL
;
1610 DBusMessageIter iter
, sub
;
1612 *interface
= "org.freedesktop.systemd1.Unit",
1613 *property
= "ActiveState";
1614 const char *state
, *path
;
1620 dbus_error_init(&error
);
1622 n
= unit_name_mangle(name
);
1626 r
= bus_method_call_with_reply (
1628 "org.freedesktop.systemd1",
1629 "/org/freedesktop/systemd1",
1630 "org.freedesktop.systemd1.Manager",
1634 DBUS_TYPE_STRING
, &n
,
1637 dbus_error_free(&error
);
1644 if (!dbus_message_get_args(reply
, NULL
,
1645 DBUS_TYPE_OBJECT_PATH
, &path
,
1646 DBUS_TYPE_INVALID
)) {
1647 log_error("Failed to parse reply.");
1651 dbus_message_unref(reply
);
1654 r
= bus_method_call_with_reply(
1656 "org.freedesktop.systemd1",
1658 "org.freedesktop.DBus.Properties",
1662 DBUS_TYPE_STRING
, &interface
,
1663 DBUS_TYPE_STRING
, &property
,
1671 if (!dbus_message_iter_init(reply
, &iter
) ||
1672 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_VARIANT
) {
1673 log_error("Failed to parse reply.");
1677 dbus_message_iter_recurse(&iter
, &sub
);
1679 if (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_STRING
) {
1680 log_error("Failed to parse reply.");
1684 dbus_message_iter_get_basic(&sub
, &state
);
1689 return strv_find(check_states
, state
) ? 1 : 0;
1692 static void check_triggering_units(
1693 DBusConnection
*bus
,
1694 const char *unit_name
) {
1696 _cleanup_dbus_message_unref_ DBusMessage
*reply
= NULL
;
1697 DBusMessageIter iter
, sub
;
1698 const char *interface
= "org.freedesktop.systemd1.Unit",
1699 *load_state_property
= "LoadState",
1700 *triggered_by_property
= "TriggeredBy",
1702 _cleanup_free_
char *unit_path
= NULL
, *n
= NULL
;
1703 bool print_warning_label
= true;
1706 n
= unit_name_mangle(unit_name
);
1712 unit_path
= unit_dbus_path_from_name(n
);
1718 r
= bus_method_call_with_reply(
1720 "org.freedesktop.systemd1",
1722 "org.freedesktop.DBus.Properties",
1726 DBUS_TYPE_STRING
, &interface
,
1727 DBUS_TYPE_STRING
, &load_state_property
,
1732 if (!dbus_message_iter_init(reply
, &iter
) ||
1733 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_VARIANT
) {
1734 log_error("Failed to parse reply.");
1738 dbus_message_iter_recurse(&iter
, &sub
);
1740 if (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_STRING
) {
1741 log_error("Failed to parse reply.");
1745 dbus_message_iter_get_basic(&sub
, &state
);
1747 if (streq(state
, "masked"))
1750 dbus_message_unref(reply
);
1753 r
= bus_method_call_with_reply(
1755 "org.freedesktop.systemd1",
1757 "org.freedesktop.DBus.Properties",
1761 DBUS_TYPE_STRING
, &interface
,
1762 DBUS_TYPE_STRING
, &triggered_by_property
,
1767 if (!dbus_message_iter_init(reply
, &iter
) ||
1768 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_VARIANT
) {
1769 log_error("Failed to parse reply.");
1773 dbus_message_iter_recurse(&iter
, &sub
);
1774 dbus_message_iter_recurse(&sub
, &iter
);
1777 while (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_INVALID
) {
1778 const char * const check_states
[] = {
1783 const char *service_trigger
;
1785 if (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_STRING
) {
1786 log_error("Failed to parse reply.");
1790 dbus_message_iter_get_basic(&sub
, &service_trigger
);
1792 r
= check_one_unit(bus
, service_trigger
, (char**) check_states
, true);
1796 if (print_warning_label
) {
1797 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name
);
1798 print_warning_label
= false;
1801 log_warning(" %s", service_trigger
);
1804 dbus_message_iter_next(&sub
);
1808 static int start_unit_one(
1809 DBusConnection
*bus
,
1816 _cleanup_dbus_message_unref_ DBusMessage
*reply
= NULL
;
1817 _cleanup_free_
char *n
;
1826 n
= unit_name_mangle(name
);
1830 r
= bus_method_call_with_reply(
1832 "org.freedesktop.systemd1",
1833 "/org/freedesktop/systemd1",
1834 "org.freedesktop.systemd1.Manager",
1838 DBUS_TYPE_STRING
, &n
,
1839 DBUS_TYPE_STRING
, &mode
,
1842 if (r
== -ENOENT
&& arg_action
!= ACTION_SYSTEMCTL
)
1843 /* There's always a fallback possible for
1844 * legacy actions. */
1847 log_error("Failed to issue method call: %s", bus_error_message(error
));
1852 if (!dbus_message_get_args(reply
, error
,
1853 DBUS_TYPE_OBJECT_PATH
, &path
,
1854 DBUS_TYPE_INVALID
)) {
1855 log_error("Failed to parse reply: %s", bus_error_message(error
));
1859 if (need_daemon_reload(bus
, n
))
1860 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1861 n
, arg_scope
== UNIT_FILE_SYSTEM
? "--system" : "--user");
1870 r
= set_consume(s
, p
);
1872 log_error("Failed to add path to set.");
1880 static const struct {
1884 } action_table
[_ACTION_MAX
] = {
1885 [ACTION_HALT
] = { SPECIAL_HALT_TARGET
, "halt", "replace-irreversibly" },
1886 [ACTION_POWEROFF
] = { SPECIAL_POWEROFF_TARGET
, "poweroff", "replace-irreversibly" },
1887 [ACTION_REBOOT
] = { SPECIAL_REBOOT_TARGET
, "reboot", "replace-irreversibly" },
1888 [ACTION_KEXEC
] = { SPECIAL_KEXEC_TARGET
, "kexec", "replace-irreversibly" },
1889 [ACTION_RUNLEVEL2
] = { SPECIAL_RUNLEVEL2_TARGET
, NULL
, "isolate" },
1890 [ACTION_RUNLEVEL3
] = { SPECIAL_RUNLEVEL3_TARGET
, NULL
, "isolate" },
1891 [ACTION_RUNLEVEL4
] = { SPECIAL_RUNLEVEL4_TARGET
, NULL
, "isolate" },
1892 [ACTION_RUNLEVEL5
] = { SPECIAL_RUNLEVEL5_TARGET
, NULL
, "isolate" },
1893 [ACTION_RESCUE
] = { SPECIAL_RESCUE_TARGET
, "rescue", "isolate" },
1894 [ACTION_EMERGENCY
] = { SPECIAL_EMERGENCY_TARGET
, "emergency", "isolate" },
1895 [ACTION_DEFAULT
] = { SPECIAL_DEFAULT_TARGET
, "default", "isolate" },
1896 [ACTION_EXIT
] = { SPECIAL_EXIT_TARGET
, "exit", "replace-irreversibly" },
1897 [ACTION_SUSPEND
] = { SPECIAL_SUSPEND_TARGET
, "suspend", "replace-irreversibly" },
1898 [ACTION_HIBERNATE
] = { SPECIAL_HIBERNATE_TARGET
, "hibernate", "replace-irreversibly" },
1899 [ACTION_HYBRID_SLEEP
] = { SPECIAL_HYBRID_SLEEP_TARGET
, "hybrid-sleep", "replace-irreversibly" },
1902 static enum action
verb_to_action(const char *verb
) {
1905 for (i
= ACTION_INVALID
; i
< _ACTION_MAX
; i
++)
1906 if (action_table
[i
].verb
&& streq(verb
, action_table
[i
].verb
))
1908 return ACTION_INVALID
;
1911 static int start_unit(DBusConnection
*bus
, char **args
) {
1914 const char *method
, *mode
, *one_name
;
1915 _cleanup_set_free_free_ Set
*s
= NULL
;
1916 _cleanup_dbus_error_free_ DBusError error
;
1919 dbus_error_init(&error
);
1923 ask_password_agent_open_if_enabled();
1925 if (arg_action
== ACTION_SYSTEMCTL
) {
1928 streq(args
[0], "stop") ||
1929 streq(args
[0], "condstop") ? "StopUnit" :
1930 streq(args
[0], "reload") ? "ReloadUnit" :
1931 streq(args
[0], "restart") ? "RestartUnit" :
1933 streq(args
[0], "try-restart") ||
1934 streq(args
[0], "condrestart") ? "TryRestartUnit" :
1936 streq(args
[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1938 streq(args
[0], "reload-or-try-restart") ||
1939 streq(args
[0], "condreload") ||
1941 streq(args
[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1943 action
= verb_to_action(args
[0]);
1945 mode
= streq(args
[0], "isolate") ? "isolate" :
1946 action_table
[action
].mode
?: arg_job_mode
;
1948 one_name
= action_table
[action
].target
;
1951 assert(arg_action
< ELEMENTSOF(action_table
));
1952 assert(action_table
[arg_action
].target
);
1954 method
= "StartUnit";
1956 mode
= action_table
[arg_action
].mode
;
1957 one_name
= action_table
[arg_action
].target
;
1960 if (!arg_no_block
) {
1961 ret
= enable_wait_for_jobs(bus
);
1963 log_error("Could not watch jobs: %s", strerror(-ret
));
1967 s
= set_new(string_hash_func
, string_compare_func
);
1973 ret
= start_unit_one(bus
, method
, one_name
, mode
, &error
, s
);
1975 ret
= translate_bus_error_to_exit_status(ret
, &error
);
1977 STRV_FOREACH(name
, args
+1) {
1978 r
= start_unit_one(bus
, method
, *name
, mode
, &error
, s
);
1980 ret
= translate_bus_error_to_exit_status(r
, &error
);
1981 dbus_error_free(&error
);
1986 if (!arg_no_block
) {
1987 r
= wait_for_jobs(bus
, s
);
1991 /* When stopping units, warn if they can still be triggered by
1992 * another active unit (socket, path, timer) */
1993 if (!arg_quiet
&& streq(method
, "StopUnit")) {
1995 check_triggering_units(bus
, one_name
);
1997 STRV_FOREACH(name
, args
+1)
1998 check_triggering_units(bus
, *name
);
2005 /* Ask systemd-logind, which might grant access to unprivileged users
2006 * through PolicyKit */
2007 static int reboot_with_logind(DBusConnection
*bus
, enum action a
) {
2010 dbus_bool_t interactive
= true;
2015 polkit_agent_open_if_enabled();
2023 case ACTION_POWEROFF
:
2024 method
= "PowerOff";
2027 case ACTION_SUSPEND
:
2031 case ACTION_HIBERNATE
:
2032 method
= "Hibernate";
2035 case ACTION_HYBRID_SLEEP
:
2036 method
= "HybridSleep";
2043 return bus_method_call_with_reply(
2045 "org.freedesktop.login1",
2046 "/org/freedesktop/login1",
2047 "org.freedesktop.login1.Manager",
2051 DBUS_TYPE_BOOLEAN
, &interactive
,
2058 static int check_inhibitors(DBusConnection
*bus
, enum action a
) {
2060 _cleanup_dbus_message_unref_ DBusMessage
*reply
= NULL
;
2061 DBusMessageIter iter
, sub
, sub2
;
2064 _cleanup_strv_free_
char **sessions
= NULL
;
2070 if (arg_ignore_inhibitors
|| arg_force
> 0)
2082 r
= bus_method_call_with_reply(
2084 "org.freedesktop.login1",
2085 "/org/freedesktop/login1",
2086 "org.freedesktop.login1.Manager",
2092 /* If logind is not around, then there are no inhibitors... */
2095 if (!dbus_message_iter_init(reply
, &iter
) ||
2096 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_ARRAY
||
2097 dbus_message_iter_get_element_type(&iter
) != DBUS_TYPE_STRUCT
) {
2098 log_error("Failed to parse reply.");
2102 dbus_message_iter_recurse(&iter
, &sub
);
2103 while (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_INVALID
) {
2104 const char *what
, *who
, *why
, *mode
;
2106 _cleanup_strv_free_
char **sv
= NULL
;
2107 _cleanup_free_
char *comm
= NULL
, *user
= NULL
;
2109 if (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_STRUCT
) {
2110 log_error("Failed to parse reply.");
2114 dbus_message_iter_recurse(&sub
, &sub2
);
2116 if (bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &what
, true) < 0 ||
2117 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &who
, true) < 0 ||
2118 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &why
, true) < 0 ||
2119 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &mode
, true) < 0 ||
2120 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_UINT32
, &uid
, true) < 0 ||
2121 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_UINT32
, &pid
, false) < 0) {
2122 log_error("Failed to parse reply.");
2126 if (!streq(mode
, "block"))
2129 sv
= strv_split(what
, ":");
2133 if (!strv_contains(sv
,
2135 a
== ACTION_POWEROFF
||
2136 a
== ACTION_REBOOT
||
2137 a
== ACTION_KEXEC
? "shutdown" : "sleep"))
2140 get_process_comm(pid
, &comm
);
2141 user
= uid_to_name(uid
);
2142 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
2143 who
, (unsigned long) pid
, strna(comm
), strna(user
), why
);
2147 dbus_message_iter_next(&sub
);
2150 dbus_message_iter_recurse(&iter
, &sub
);
2152 /* Check for current sessions */
2153 sd_get_sessions(&sessions
);
2154 STRV_FOREACH(s
, sessions
) {
2156 _cleanup_free_
char *type
= NULL
, *tty
= NULL
, *seat
= NULL
, *user
= NULL
, *service
= NULL
, *class = NULL
;
2158 if (sd_session_get_uid(*s
, &uid
) < 0 || uid
== getuid())
2161 if (sd_session_get_class(*s
, &class) < 0 || !streq(class, "user"))
2164 if (sd_session_get_type(*s
, &type
) < 0 || (!streq(type
, "x11") && !streq(type
, "tty")))
2167 sd_session_get_tty(*s
, &tty
);
2168 sd_session_get_seat(*s
, &seat
);
2169 sd_session_get_service(*s
, &service
);
2170 user
= uid_to_name(uid
);
2172 log_warning("User %s is logged in on %s.", strna(user
), isempty(tty
) ? (isempty(seat
) ? strna(service
) : seat
) : tty
);
2179 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2180 action_table
[a
].verb
);
2188 static int start_special(DBusConnection
*bus
, char **args
) {
2194 a
= verb_to_action(args
[0]);
2196 r
= check_inhibitors(bus
, a
);
2200 if (arg_force
>= 2 && geteuid() != 0) {
2201 log_error("Must be root.");
2205 if (arg_force
>= 2 &&
2206 (a
== ACTION_HALT
||
2207 a
== ACTION_POWEROFF
||
2208 a
== ACTION_REBOOT
))
2211 if (arg_force
>= 1 &&
2212 (a
== ACTION_HALT
||
2213 a
== ACTION_POWEROFF
||
2214 a
== ACTION_REBOOT
||
2215 a
== ACTION_KEXEC
||
2217 return daemon_reload(bus
, args
);
2219 /* first try logind, to allow authentication with polkit */
2220 if (geteuid() != 0 &&
2221 (a
== ACTION_POWEROFF
||
2222 a
== ACTION_REBOOT
||
2223 a
== ACTION_SUSPEND
||
2224 a
== ACTION_HIBERNATE
||
2225 a
== ACTION_HYBRID_SLEEP
)) {
2226 r
= reboot_with_logind(bus
, a
);
2231 r
= start_unit(bus
, args
);
2232 if (r
== EXIT_SUCCESS
)
2238 static int check_unit_active(DBusConnection
*bus
, char **args
) {
2239 const char * const check_states
[] = {
2246 int r
= 3; /* According to LSB: "program is not running" */
2251 STRV_FOREACH(name
, args
+1) {
2254 state
= check_one_unit(bus
, *name
, (char**) check_states
, arg_quiet
);
2264 static int check_unit_failed(DBusConnection
*bus
, char **args
) {
2265 const char * const check_states
[] = {
2276 STRV_FOREACH(name
, args
+1) {
2279 state
= check_one_unit(bus
, *name
, (char**) check_states
, arg_quiet
);
2289 static int kill_unit(DBusConnection
*bus
, char **args
) {
2297 arg_kill_who
= "all";
2299 STRV_FOREACH(name
, args
+1) {
2300 _cleanup_free_
char *n
= NULL
;
2302 n
= unit_name_mangle(*name
);
2306 r
= bus_method_call_with_reply(
2308 "org.freedesktop.systemd1",
2309 "/org/freedesktop/systemd1",
2310 "org.freedesktop.systemd1.Manager",
2314 DBUS_TYPE_STRING
, &n
,
2315 DBUS_TYPE_STRING
, &arg_kill_who
,
2316 DBUS_TYPE_INT32
, &arg_signal
,
2324 static int set_cgroup(DBusConnection
*bus
, char **args
) {
2325 _cleanup_free_
char *n
= NULL
;
2326 const char *method
, *runtime
;
2334 streq(args
[0], "set-cgroup") ? "SetUnitControlGroup" :
2335 streq(args
[0], "unset-cgroup") ? "UnsetUnitControlGroup"
2336 : "UnsetUnitControlGroupAttribute";
2338 runtime
= arg_runtime
? "runtime" : "persistent";
2340 n
= unit_name_mangle(args
[1]);
2344 STRV_FOREACH(argument
, args
+ 2) {
2346 r
= bus_method_call_with_reply(
2348 "org.freedesktop.systemd1",
2349 "/org/freedesktop/systemd1",
2350 "org.freedesktop.systemd1.Manager",
2354 DBUS_TYPE_STRING
, &n
,
2355 DBUS_TYPE_STRING
, argument
,
2356 DBUS_TYPE_STRING
, &runtime
,
2365 static int set_cgroup_attr(DBusConnection
*bus
, char **args
) {
2366 _cleanup_dbus_message_unref_ DBusMessage
*m
= NULL
, *reply
= NULL
;
2368 DBusMessageIter iter
;
2369 _cleanup_free_
char *n
= NULL
;
2370 const char *runtime
;
2376 dbus_error_init(&error
);
2378 runtime
= arg_runtime
? "runtime" : "persistent";
2380 n
= unit_name_mangle(args
[1]);
2384 m
= dbus_message_new_method_call(
2385 "org.freedesktop.systemd1",
2386 "/org/freedesktop/systemd1",
2387 "org.freedesktop.systemd1.Manager",
2388 "SetUnitControlGroupAttribute");
2392 dbus_message_iter_init_append(m
, &iter
);
2393 if (!dbus_message_iter_append_basic(&iter
, DBUS_TYPE_STRING
, &n
) ||
2394 !dbus_message_iter_append_basic(&iter
, DBUS_TYPE_STRING
, &args
[2]))
2397 r
= bus_append_strv_iter(&iter
, args
+ 3);
2401 if (!dbus_message_iter_append_basic(&iter
, DBUS_TYPE_STRING
, &runtime
))
2404 reply
= dbus_connection_send_with_reply_and_block(bus
, m
, -1, &error
);
2406 log_error("Failed to issue method call: %s", bus_error_message(&error
));
2407 dbus_error_free(&error
);
2414 static int get_cgroup_attr(DBusConnection
*bus
, char **args
) {
2415 _cleanup_dbus_message_unref_ DBusMessage
*reply
= NULL
;
2416 _cleanup_free_
char *n
= NULL
;
2423 n
= unit_name_mangle(args
[1]);
2427 STRV_FOREACH(argument
, args
+ 2) {
2428 _cleanup_strv_free_
char **list
= NULL
;
2429 DBusMessageIter iter
;
2432 r
= bus_method_call_with_reply(
2434 "org.freedesktop.systemd1",
2435 "/org/freedesktop/systemd1",
2436 "org.freedesktop.systemd1.Manager",
2437 "GetUnitControlGroupAttribute",
2440 DBUS_TYPE_STRING
, &n
,
2441 DBUS_TYPE_STRING
, argument
,
2446 if (!dbus_message_iter_init(reply
, &iter
)) {
2447 log_error("Failed to initialize iterator.");
2451 r
= bus_parse_strv_iter(&iter
, &list
);
2453 log_error("Failed to parse value list.");
2457 STRV_FOREACH(a
, list
) {
2458 if (endswith(*a
, "\n"))
2468 typedef struct ExecStatusInfo
{
2476 usec_t start_timestamp
;
2477 usec_t exit_timestamp
;
2482 LIST_FIELDS(struct ExecStatusInfo
, exec
);
2485 static void exec_status_info_free(ExecStatusInfo
*i
) {
2494 static int exec_status_info_deserialize(DBusMessageIter
*sub
, ExecStatusInfo
*i
) {
2495 uint64_t start_timestamp
, exit_timestamp
, start_timestamp_monotonic
, exit_timestamp_monotonic
;
2496 DBusMessageIter sub2
, sub3
;
2500 int32_t code
, status
;
2506 if (dbus_message_iter_get_arg_type(sub
) != DBUS_TYPE_STRUCT
)
2509 dbus_message_iter_recurse(sub
, &sub2
);
2511 if (bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &path
, true) < 0)
2514 i
->path
= strdup(path
);
2518 if (dbus_message_iter_get_arg_type(&sub2
) != DBUS_TYPE_ARRAY
||
2519 dbus_message_iter_get_element_type(&sub2
) != DBUS_TYPE_STRING
)
2523 dbus_message_iter_recurse(&sub2
, &sub3
);
2524 while (dbus_message_iter_get_arg_type(&sub3
) != DBUS_TYPE_INVALID
) {
2525 assert(dbus_message_iter_get_arg_type(&sub3
) == DBUS_TYPE_STRING
);
2526 dbus_message_iter_next(&sub3
);
2530 i
->argv
= new0(char*, n
+1);
2535 dbus_message_iter_recurse(&sub2
, &sub3
);
2536 while (dbus_message_iter_get_arg_type(&sub3
) != DBUS_TYPE_INVALID
) {
2539 assert(dbus_message_iter_get_arg_type(&sub3
) == DBUS_TYPE_STRING
);
2540 dbus_message_iter_get_basic(&sub3
, &s
);
2541 dbus_message_iter_next(&sub3
);
2543 i
->argv
[n
] = strdup(s
);
2550 if (!dbus_message_iter_next(&sub2
) ||
2551 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_BOOLEAN
, &ignore
, true) < 0 ||
2552 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_UINT64
, &start_timestamp
, true) < 0 ||
2553 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_UINT64
, &start_timestamp_monotonic
, true) < 0 ||
2554 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_UINT64
, &exit_timestamp
, true) < 0 ||
2555 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_UINT64
, &exit_timestamp_monotonic
, true) < 0 ||
2556 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_UINT32
, &pid
, true) < 0 ||
2557 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_INT32
, &code
, true) < 0 ||
2558 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_INT32
, &status
, false) < 0)
2562 i
->start_timestamp
= (usec_t
) start_timestamp
;
2563 i
->exit_timestamp
= (usec_t
) exit_timestamp
;
2564 i
->pid
= (pid_t
) pid
;
2571 typedef struct UnitStatusInfo
{
2573 const char *load_state
;
2574 const char *active_state
;
2575 const char *sub_state
;
2576 const char *unit_file_state
;
2578 const char *description
;
2579 const char *following
;
2581 char **documentation
;
2583 const char *fragment_path
;
2584 const char *source_path
;
2585 const char *default_control_group
;
2587 char **dropin_paths
;
2589 const char *load_error
;
2592 usec_t inactive_exit_timestamp
;
2593 usec_t inactive_exit_timestamp_monotonic
;
2594 usec_t active_enter_timestamp
;
2595 usec_t active_exit_timestamp
;
2596 usec_t inactive_enter_timestamp
;
2598 bool need_daemon_reload
;
2603 const char *status_text
;
2606 usec_t start_timestamp
;
2607 usec_t exit_timestamp
;
2609 int exit_code
, exit_status
;
2611 usec_t condition_timestamp
;
2612 bool condition_result
;
2615 unsigned n_accepted
;
2616 unsigned n_connections
;
2619 /* Pairs of type, path */
2623 const char *sysfs_path
;
2625 /* Mount, Automount */
2631 LIST_HEAD(ExecStatusInfo
, exec
);
2634 static void print_status_info(UnitStatusInfo
*i
) {
2636 const char *on
, *off
, *ss
;
2638 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], *s1
;
2639 char since2
[FORMAT_TIMESTAMP_MAX
], *s2
;
2642 arg_all
* OUTPUT_SHOW_ALL
|
2643 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH
|
2644 on_tty() * OUTPUT_COLOR
|
2645 !arg_quiet
* OUTPUT_WARN_CUTOFF
|
2646 arg_full
* OUTPUT_FULL_WIDTH
;
2647 int maxlen
= 8; /* a value that'll suffice most of the time */
2652 STRV_FOREACH_PAIR(t
, t2
, i
->listen
)
2653 maxlen
= MAX(maxlen
, (int)(sizeof("Listen") - 1 + strlen(*t
)));
2655 maxlen
= MAX(maxlen
, (int)sizeof("Accept") - 1);
2656 if (i
->main_pid
> 0)
2657 maxlen
= MAX(maxlen
, (int)sizeof("Main PID") - 1);
2658 else if (i
->control_pid
> 0)
2659 maxlen
= MAX(maxlen
, (int)sizeof("Control") - 1);
2661 /* This shows pretty information about a unit. See
2662 * print_property() for a low-level property printer */
2664 printf("%s", strna(i
->id
));
2666 if (i
->description
&& !streq_ptr(i
->id
, i
->description
))
2667 printf(" - %s", i
->description
);
2672 printf(" %*s: unit currently follows state of %s\n", maxlen
, "Follow", i
->following
);
2674 if (streq_ptr(i
->load_state
, "error")) {
2675 on
= ansi_highlight_red(true);
2676 off
= ansi_highlight_red(false);
2680 path
= i
->source_path
? i
->source_path
: i
->fragment_path
;
2683 printf(" %*s: %s%s%s (Reason: %s)\n",
2684 maxlen
, "Loaded", on
, strna(i
->load_state
), off
, i
->load_error
);
2685 else if (path
&& i
->unit_file_state
)
2686 printf(" %*s: %s%s%s (%s; %s)\n",
2687 maxlen
, "Loaded", on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
);
2689 printf(" %*s: %s%s%s (%s)\n",
2690 maxlen
, "Loaded", on
, strna(i
->load_state
), off
, path
);
2692 printf(" %*s: %s%s%s\n",
2693 maxlen
, "Loaded", on
, strna(i
->load_state
), off
);
2695 if (!strv_isempty(i
->dropin_paths
)) {
2700 STRV_FOREACH(dropin
, i
->dropin_paths
) {
2701 if (! dir
|| last
) {
2702 printf(" %*s ", maxlen
, dir
? "" : "Drop-In:");
2706 if (path_get_parent(*dropin
, &dir
) < 0) {
2711 printf("%s\n %*s %s", dir
, maxlen
, "",
2712 draw_special_char(DRAW_TREE_RIGHT
));
2715 last
= ! (*(dropin
+ 1) && startswith(*(dropin
+ 1), dir
));
2717 printf("%s%s", path_get_file_name(*dropin
), last
? "\n" : ", ");
2723 ss
= streq_ptr(i
->active_state
, i
->sub_state
) ? NULL
: i
->sub_state
;
2725 if (streq_ptr(i
->active_state
, "failed")) {
2726 on
= ansi_highlight_red(true);
2727 off
= ansi_highlight_red(false);
2728 } else if (streq_ptr(i
->active_state
, "active") || streq_ptr(i
->active_state
, "reloading")) {
2729 on
= ansi_highlight_green(true);
2730 off
= ansi_highlight_green(false);
2735 printf(" %*s: %s%s (%s)%s",
2736 maxlen
, "Active", on
, strna(i
->active_state
), ss
, off
);
2738 printf(" %*s: %s%s%s",
2739 maxlen
, "Active", on
, strna(i
->active_state
), off
);
2741 if (!isempty(i
->result
) && !streq(i
->result
, "success"))
2742 printf(" (Result: %s)", i
->result
);
2744 timestamp
= (streq_ptr(i
->active_state
, "active") ||
2745 streq_ptr(i
->active_state
, "reloading")) ? i
->active_enter_timestamp
:
2746 (streq_ptr(i
->active_state
, "inactive") ||
2747 streq_ptr(i
->active_state
, "failed")) ? i
->inactive_enter_timestamp
:
2748 streq_ptr(i
->active_state
, "activating") ? i
->inactive_exit_timestamp
:
2749 i
->active_exit_timestamp
;
2751 s1
= format_timestamp_relative(since1
, sizeof(since1
), timestamp
);
2752 s2
= format_timestamp(since2
, sizeof(since2
), timestamp
);
2755 printf(" since %s; %s\n", s2
, s1
);
2757 printf(" since %s\n", s2
);
2761 if (!i
->condition_result
&& i
->condition_timestamp
> 0) {
2762 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->condition_timestamp
);
2763 s2
= format_timestamp(since2
, sizeof(since2
), i
->condition_timestamp
);
2766 printf(" %*s start condition failed at %s; %s\n", maxlen
, "", s2
, s1
);
2768 printf(" %*s start condition failed at %s\n", maxlen
, "", s2
);
2772 printf(" %*s: %s\n", maxlen
, "Device", i
->sysfs_path
);
2774 printf(" %*s: %s\n", maxlen
, "Where", i
->where
);
2776 printf(" %*s: %s\n", maxlen
, "What", i
->what
);
2778 STRV_FOREACH(t
, i
->documentation
)
2779 printf(" %*s %s\n", maxlen
+1, t
== i
->documentation
? "Docs:" : "", *t
);
2781 STRV_FOREACH_PAIR(t
, t2
, i
->listen
)
2782 printf(" %*s %s (%s)\n", maxlen
+1, t
== i
->listen
? "Listen:" : "", *t2
, *t
);
2785 printf(" %*s: %u; Connected: %u\n", maxlen
, "Accepted", i
->n_accepted
, i
->n_connections
);
2787 LIST_FOREACH(exec
, p
, i
->exec
) {
2788 _cleanup_free_
char *argv
= NULL
;
2791 /* Only show exited processes here */
2795 argv
= strv_join(p
->argv
, " ");
2796 printf(" %*s: %u %s=%s ", maxlen
, "Process", p
->pid
, p
->name
, strna(argv
));
2798 good
= is_clean_exit_lsb(p
->code
, p
->status
, NULL
);
2800 on
= ansi_highlight_red(true);
2801 off
= ansi_highlight_red(false);
2805 printf("%s(code=%s, ", on
, sigchld_code_to_string(p
->code
));
2807 if (p
->code
== CLD_EXITED
) {
2810 printf("status=%i", p
->status
);
2812 c
= exit_status_to_string(p
->status
, EXIT_STATUS_SYSTEMD
);
2817 printf("signal=%s", signal_to_string(p
->status
));
2819 printf(")%s\n", off
);
2821 if (i
->main_pid
== p
->pid
&&
2822 i
->start_timestamp
== p
->start_timestamp
&&
2823 i
->exit_timestamp
== p
->start_timestamp
)
2824 /* Let's not show this twice */
2827 if (p
->pid
== i
->control_pid
)
2831 if (i
->main_pid
> 0 || i
->control_pid
> 0) {
2832 if (i
->main_pid
> 0) {
2833 printf(" %*s: %u", maxlen
, "Main PID", (unsigned) i
->main_pid
);
2836 _cleanup_free_
char *comm
= NULL
;
2837 get_process_comm(i
->main_pid
, &comm
);
2839 printf(" (%s)", comm
);
2840 } else if (i
->exit_code
> 0) {
2841 printf(" (code=%s, ", sigchld_code_to_string(i
->exit_code
));
2843 if (i
->exit_code
== CLD_EXITED
) {
2846 printf("status=%i", i
->exit_status
);
2848 c
= exit_status_to_string(i
->exit_status
, EXIT_STATUS_SYSTEMD
);
2853 printf("signal=%s", signal_to_string(i
->exit_status
));
2857 if (i
->control_pid
> 0)
2861 if (i
->control_pid
> 0) {
2862 _cleanup_free_
char *c
= NULL
;
2864 printf(" %*s: %u", i
->main_pid
? 0 : maxlen
, "Control", (unsigned) i
->control_pid
);
2866 get_process_comm(i
->control_pid
, &c
);
2875 printf(" %*s: \"%s\"\n", maxlen
, "Status", i
->status_text
);
2877 if (i
->default_control_group
&&
2878 (i
->main_pid
> 0 || i
->control_pid
> 0 || cg_is_empty_by_spec(i
->default_control_group
, false) == 0)) {
2881 printf(" %*s: %s\n", maxlen
, "CGroup", i
->default_control_group
);
2883 if (arg_transport
!= TRANSPORT_SSH
) {
2886 char prefix
[maxlen
+ 4];
2887 memset(prefix
, ' ', sizeof(prefix
) - 1);
2888 prefix
[sizeof(prefix
) - 1] = '\0';
2891 if (c
> sizeof(prefix
) - 1)
2892 c
-= sizeof(prefix
) - 1;
2896 if (i
->main_pid
> 0)
2897 extra
[k
++] = i
->main_pid
;
2899 if (i
->control_pid
> 0)
2900 extra
[k
++] = i
->control_pid
;
2902 show_cgroup_and_extra_by_spec(i
->default_control_group
, prefix
,
2903 c
, false, extra
, k
, flags
);
2907 if (i
->id
&& arg_transport
!= TRANSPORT_SSH
) {
2909 show_journal_by_unit(stdout
,
2913 i
->inactive_exit_timestamp_monotonic
,
2917 arg_scope
== UNIT_FILE_SYSTEM
);
2920 if (i
->need_daemon_reload
)
2921 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2922 ansi_highlight_red(true),
2923 ansi_highlight_red(false),
2924 arg_scope
== UNIT_FILE_SYSTEM
? "--system" : "--user");
2927 static void show_unit_help(UnitStatusInfo
*i
) {
2932 if (!i
->documentation
) {
2933 log_info("Documentation for %s not known.", i
->id
);
2937 STRV_FOREACH(p
, i
->documentation
) {
2939 if (startswith(*p
, "man:")) {
2942 _cleanup_free_
char *page
= NULL
, *section
= NULL
;
2943 const char *args
[4] = { "man", NULL
, NULL
, NULL
};
2948 if ((*p
)[k
-1] == ')')
2949 e
= strrchr(*p
, '(');
2952 page
= strndup((*p
) + 4, e
- *p
- 4);
2953 section
= strndup(e
+ 1, *p
+ k
- e
- 2);
2954 if (!page
|| !section
) {
2966 log_error("Failed to fork: %m");
2972 execvp(args
[0], (char**) args
);
2973 log_error("Failed to execute man: %m");
2974 _exit(EXIT_FAILURE
);
2977 wait_for_terminate(pid
, NULL
);
2979 log_info("Can't show: %s", *p
);
2983 static int status_property(const char *name
, DBusMessageIter
*iter
, UnitStatusInfo
*i
) {
2989 switch (dbus_message_iter_get_arg_type(iter
)) {
2991 case DBUS_TYPE_STRING
: {
2994 dbus_message_iter_get_basic(iter
, &s
);
2997 if (streq(name
, "Id"))
2999 else if (streq(name
, "LoadState"))
3001 else if (streq(name
, "ActiveState"))
3002 i
->active_state
= s
;
3003 else if (streq(name
, "SubState"))
3005 else if (streq(name
, "Description"))
3007 else if (streq(name
, "FragmentPath"))
3008 i
->fragment_path
= s
;
3009 else if (streq(name
, "SourcePath"))
3011 else if (streq(name
, "DefaultControlGroup"))
3012 i
->default_control_group
= s
;
3013 else if (streq(name
, "StatusText"))
3015 else if (streq(name
, "SysFSPath"))
3017 else if (streq(name
, "Where"))
3019 else if (streq(name
, "What"))
3021 else if (streq(name
, "Following"))
3023 else if (streq(name
, "UnitFileState"))
3024 i
->unit_file_state
= s
;
3025 else if (streq(name
, "Result"))
3032 case DBUS_TYPE_BOOLEAN
: {
3035 dbus_message_iter_get_basic(iter
, &b
);
3037 if (streq(name
, "Accept"))
3039 else if (streq(name
, "NeedDaemonReload"))
3040 i
->need_daemon_reload
= b
;
3041 else if (streq(name
, "ConditionResult"))
3042 i
->condition_result
= b
;
3047 case DBUS_TYPE_UINT32
: {
3050 dbus_message_iter_get_basic(iter
, &u
);
3052 if (streq(name
, "MainPID")) {
3054 i
->main_pid
= (pid_t
) u
;
3057 } else if (streq(name
, "ControlPID"))
3058 i
->control_pid
= (pid_t
) u
;
3059 else if (streq(name
, "ExecMainPID")) {
3061 i
->main_pid
= (pid_t
) u
;
3062 } else if (streq(name
, "NAccepted"))
3064 else if (streq(name
, "NConnections"))
3065 i
->n_connections
= u
;
3070 case DBUS_TYPE_INT32
: {
3073 dbus_message_iter_get_basic(iter
, &j
);
3075 if (streq(name
, "ExecMainCode"))
3076 i
->exit_code
= (int) j
;
3077 else if (streq(name
, "ExecMainStatus"))
3078 i
->exit_status
= (int) j
;
3083 case DBUS_TYPE_UINT64
: {
3086 dbus_message_iter_get_basic(iter
, &u
);
3088 if (streq(name
, "ExecMainStartTimestamp"))
3089 i
->start_timestamp
= (usec_t
) u
;
3090 else if (streq(name
, "ExecMainExitTimestamp"))
3091 i
->exit_timestamp
= (usec_t
) u
;
3092 else if (streq(name
, "ActiveEnterTimestamp"))
3093 i
->active_enter_timestamp
= (usec_t
) u
;
3094 else if (streq(name
, "InactiveEnterTimestamp"))
3095 i
->inactive_enter_timestamp
= (usec_t
) u
;
3096 else if (streq(name
, "InactiveExitTimestamp"))
3097 i
->inactive_exit_timestamp
= (usec_t
) u
;
3098 else if (streq(name
, "InactiveExitTimestampMonotonic"))
3099 i
->inactive_exit_timestamp_monotonic
= (usec_t
) u
;
3100 else if (streq(name
, "ActiveExitTimestamp"))
3101 i
->active_exit_timestamp
= (usec_t
) u
;
3102 else if (streq(name
, "ConditionTimestamp"))
3103 i
->condition_timestamp
= (usec_t
) u
;
3108 case DBUS_TYPE_ARRAY
: {
3110 if (dbus_message_iter_get_element_type(iter
) == DBUS_TYPE_STRUCT
&&
3111 startswith(name
, "Exec")) {
3112 DBusMessageIter sub
;
3114 dbus_message_iter_recurse(iter
, &sub
);
3115 while (dbus_message_iter_get_arg_type(&sub
) == DBUS_TYPE_STRUCT
) {
3116 ExecStatusInfo
*info
;
3119 if (!(info
= new0(ExecStatusInfo
, 1)))
3122 if (!(info
->name
= strdup(name
))) {
3127 if ((r
= exec_status_info_deserialize(&sub
, info
)) < 0) {
3132 LIST_PREPEND(ExecStatusInfo
, exec
, i
->exec
, info
);
3134 dbus_message_iter_next(&sub
);
3137 } else if (dbus_message_iter_get_element_type(iter
) == DBUS_TYPE_STRUCT
&& streq(name
, "Listen")) {
3138 DBusMessageIter sub
, sub2
;
3140 dbus_message_iter_recurse(iter
, &sub
);
3141 while (dbus_message_iter_get_arg_type(&sub
) == DBUS_TYPE_STRUCT
) {
3142 const char *type
, *path
;
3144 dbus_message_iter_recurse(&sub
, &sub2
);
3146 if (bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &type
, true) >= 0 &&
3147 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &path
, false) >= 0) {
3150 r
= strv_extend(&i
->listen
, type
);
3153 r
= strv_extend(&i
->listen
, path
);
3158 dbus_message_iter_next(&sub
);
3163 } else if (dbus_message_iter_get_element_type(iter
) == DBUS_TYPE_STRING
&& streq(name
, "DropInPaths")) {
3164 int r
= bus_parse_strv_iter(iter
, &i
->dropin_paths
);
3168 } else if (dbus_message_iter_get_element_type(iter
) == DBUS_TYPE_STRING
&&
3169 streq(name
, "Documentation")) {
3171 DBusMessageIter sub
;
3173 dbus_message_iter_recurse(iter
, &sub
);
3174 while (dbus_message_iter_get_arg_type(&sub
) == DBUS_TYPE_STRING
) {
3178 dbus_message_iter_get_basic(&sub
, &s
);
3180 r
= strv_extend(&i
->documentation
, s
);
3184 dbus_message_iter_next(&sub
);
3191 case DBUS_TYPE_STRUCT
: {
3193 if (streq(name
, "LoadError")) {
3194 DBusMessageIter sub
;
3195 const char *n
, *message
;
3198 dbus_message_iter_recurse(iter
, &sub
);
3200 r
= bus_iter_get_basic_and_next(&sub
, DBUS_TYPE_STRING
, &n
, true);
3204 r
= bus_iter_get_basic_and_next(&sub
, DBUS_TYPE_STRING
, &message
, false);
3208 if (!isempty(message
))
3209 i
->load_error
= message
;
3219 static int print_property(const char *name
, DBusMessageIter
*iter
) {
3223 /* This is a low-level property printer, see
3224 * print_status_info() for the nicer output */
3226 if (arg_properties
&& !strv_find(arg_properties
, name
))
3229 switch (dbus_message_iter_get_arg_type(iter
)) {
3231 case DBUS_TYPE_STRUCT
: {
3232 DBusMessageIter sub
;
3233 dbus_message_iter_recurse(iter
, &sub
);
3235 if (dbus_message_iter_get_arg_type(&sub
) == DBUS_TYPE_UINT32
&& streq(name
, "Job")) {
3238 dbus_message_iter_get_basic(&sub
, &u
);
3241 printf("%s=%u\n", name
, (unsigned) u
);
3243 printf("%s=\n", name
);
3246 } else if (dbus_message_iter_get_arg_type(&sub
) == DBUS_TYPE_STRING
&& streq(name
, "Unit")) {
3249 dbus_message_iter_get_basic(&sub
, &s
);
3251 if (arg_all
|| s
[0])
3252 printf("%s=%s\n", name
, s
);
3255 } else if (dbus_message_iter_get_arg_type(&sub
) == DBUS_TYPE_STRING
&& streq(name
, "LoadError")) {
3256 const char *a
= NULL
, *b
= NULL
;
3258 if (bus_iter_get_basic_and_next(&sub
, DBUS_TYPE_STRING
, &a
, true) >= 0)
3259 bus_iter_get_basic_and_next(&sub
, DBUS_TYPE_STRING
, &b
, false);
3261 if (arg_all
|| !isempty(a
) || !isempty(b
))
3262 printf("%s=%s \"%s\"\n", name
, strempty(a
), strempty(b
));
3270 case DBUS_TYPE_ARRAY
:
3272 if (dbus_message_iter_get_element_type(iter
) == DBUS_TYPE_STRUCT
&& streq(name
, "EnvironmentFiles")) {
3273 DBusMessageIter sub
, sub2
;
3275 dbus_message_iter_recurse(iter
, &sub
);
3276 while (dbus_message_iter_get_arg_type(&sub
) == DBUS_TYPE_STRUCT
) {
3280 dbus_message_iter_recurse(&sub
, &sub2
);
3282 if (bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &path
, true) >= 0 &&
3283 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_BOOLEAN
, &ignore
, false) >= 0)
3284 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path
, yes_no(ignore
));
3286 dbus_message_iter_next(&sub
);
3291 } else if (dbus_message_iter_get_element_type(iter
) == DBUS_TYPE_STRUCT
&& streq(name
, "Paths")) {
3292 DBusMessageIter sub
, sub2
;
3294 dbus_message_iter_recurse(iter
, &sub
);
3296 while (dbus_message_iter_get_arg_type(&sub
) == DBUS_TYPE_STRUCT
) {
3297 const char *type
, *path
;
3299 dbus_message_iter_recurse(&sub
, &sub2
);
3301 if (bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &type
, true) >= 0 &&
3302 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &path
, false) >= 0)
3303 printf("%s=%s\n", type
, path
);
3305 dbus_message_iter_next(&sub
);
3310 } else if (dbus_message_iter_get_element_type(iter
) == DBUS_TYPE_STRUCT
&& streq(name
, "Listen")) {
3311 DBusMessageIter sub
, sub2
;
3313 dbus_message_iter_recurse(iter
, &sub
);
3314 while (dbus_message_iter_get_arg_type(&sub
) == DBUS_TYPE_STRUCT
) {
3315 const char *type
, *path
;
3317 dbus_message_iter_recurse(&sub
, &sub2
);
3319 if (bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &type
, true) >= 0 &&
3320 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &path
, false) >= 0)
3321 printf("Listen%s=%s\n", type
, path
);
3323 dbus_message_iter_next(&sub
);
3328 } else if (dbus_message_iter_get_element_type(iter
) == DBUS_TYPE_STRUCT
&& streq(name
, "Timers")) {
3329 DBusMessageIter sub
, sub2
;
3331 dbus_message_iter_recurse(iter
, &sub
);
3332 while (dbus_message_iter_get_arg_type(&sub
) == DBUS_TYPE_STRUCT
) {
3334 uint64_t value
, next_elapse
;
3336 dbus_message_iter_recurse(&sub
, &sub2
);
3338 if (bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &base
, true) >= 0 &&
3339 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_UINT64
, &value
, true) >= 0 &&
3340 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_UINT64
, &next_elapse
, false) >= 0) {
3341 char timespan1
[FORMAT_TIMESPAN_MAX
], timespan2
[FORMAT_TIMESPAN_MAX
];
3343 printf("%s={ value=%s ; next_elapse=%s }\n",
3345 format_timespan(timespan1
, sizeof(timespan1
), value
, 0),
3346 format_timespan(timespan2
, sizeof(timespan2
), next_elapse
, 0));
3349 dbus_message_iter_next(&sub
);
3354 } else if (dbus_message_iter_get_element_type(iter
) == DBUS_TYPE_STRUCT
&& streq(name
, "ControlGroupAttributes")) {
3355 DBusMessageIter sub
, sub2
;
3357 dbus_message_iter_recurse(iter
, &sub
);
3358 while (dbus_message_iter_get_arg_type(&sub
) == DBUS_TYPE_STRUCT
) {
3359 const char *controller
, *attr
, *value
;
3361 dbus_message_iter_recurse(&sub
, &sub2
);
3363 if (bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &controller
, true) >= 0 &&
3364 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &attr
, true) >= 0 &&
3365 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &value
, false) >= 0) {
3367 printf("ControlGroupAttributes={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
3373 dbus_message_iter_next(&sub
);
3378 } else if (dbus_message_iter_get_element_type(iter
) == DBUS_TYPE_STRUCT
&& startswith(name
, "Exec")) {
3379 DBusMessageIter sub
;
3381 dbus_message_iter_recurse(iter
, &sub
);
3382 while (dbus_message_iter_get_arg_type(&sub
) == DBUS_TYPE_STRUCT
) {
3383 ExecStatusInfo info
= {};
3385 if (exec_status_info_deserialize(&sub
, &info
) >= 0) {
3386 char timestamp1
[FORMAT_TIMESTAMP_MAX
], timestamp2
[FORMAT_TIMESTAMP_MAX
];
3387 _cleanup_free_
char *t
;
3389 t
= strv_join(info
.argv
, " ");
3391 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3395 yes_no(info
.ignore
),
3396 strna(format_timestamp(timestamp1
, sizeof(timestamp1
), info
.start_timestamp
)),
3397 strna(format_timestamp(timestamp2
, sizeof(timestamp2
), info
.exit_timestamp
)),
3398 (unsigned) info
. pid
,
3399 sigchld_code_to_string(info
.code
),
3401 info
.code
== CLD_EXITED
? "" : "/",
3402 strempty(info
.code
== CLD_EXITED
? NULL
: signal_to_string(info
.status
)));
3406 strv_free(info
.argv
);
3408 dbus_message_iter_next(&sub
);
3417 if (generic_print_property(name
, iter
, arg_all
) > 0)
3421 printf("%s=[unprintable]\n", name
);
3426 static int show_one(const char *verb
, DBusConnection
*bus
, const char *path
, bool show_properties
, bool *new_line
) {
3427 _cleanup_free_ DBusMessage
*reply
= NULL
;
3428 const char *interface
= "";
3430 DBusMessageIter iter
, sub
, sub2
, sub3
;
3431 UnitStatusInfo info
= {};
3437 r
= bus_method_call_with_reply(
3439 "org.freedesktop.systemd1",
3441 "org.freedesktop.DBus.Properties",
3445 DBUS_TYPE_STRING
, &interface
,
3450 if (!dbus_message_iter_init(reply
, &iter
) ||
3451 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_ARRAY
||
3452 dbus_message_iter_get_element_type(&iter
) != DBUS_TYPE_DICT_ENTRY
) {
3453 log_error("Failed to parse reply.");
3457 dbus_message_iter_recurse(&iter
, &sub
);
3464 while (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_INVALID
) {
3467 assert(dbus_message_iter_get_arg_type(&sub
) == DBUS_TYPE_DICT_ENTRY
);
3468 dbus_message_iter_recurse(&sub
, &sub2
);
3470 if (bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &name
, true) < 0 ||
3471 dbus_message_iter_get_arg_type(&sub2
) != DBUS_TYPE_VARIANT
) {
3472 log_error("Failed to parse reply.");
3476 dbus_message_iter_recurse(&sub2
, &sub3
);
3478 if (show_properties
)
3479 r
= print_property(name
, &sub3
);
3481 r
= status_property(name
, &sub3
, &info
);
3483 log_error("Failed to parse reply.");
3487 dbus_message_iter_next(&sub
);
3492 if (!show_properties
) {
3493 if (streq(verb
, "help"))
3494 show_unit_help(&info
);
3496 print_status_info(&info
);
3499 strv_free(info
.documentation
);
3500 strv_free(info
.dropin_paths
);
3501 strv_free(info
.listen
);
3503 if (!streq_ptr(info
.active_state
, "active") &&
3504 !streq_ptr(info
.active_state
, "reloading") &&
3505 streq(verb
, "status"))
3506 /* According to LSB: "program not running" */
3509 while ((p
= info
.exec
)) {
3510 LIST_REMOVE(ExecStatusInfo
, exec
, info
.exec
, p
);
3511 exec_status_info_free(p
);
3517 static int show_one_by_pid(const char *verb
, DBusConnection
*bus
, uint32_t pid
, bool *new_line
) {
3518 _cleanup_dbus_message_unref_ DBusMessage
*reply
= NULL
;
3519 const char *path
= NULL
;
3520 _cleanup_dbus_error_free_ DBusError error
;
3523 dbus_error_init(&error
);
3525 r
= bus_method_call_with_reply(
3527 "org.freedesktop.systemd1",
3528 "/org/freedesktop/systemd1",
3529 "org.freedesktop.systemd1.Manager",
3533 DBUS_TYPE_UINT32
, &pid
,
3538 if (!dbus_message_get_args(reply
, &error
,
3539 DBUS_TYPE_OBJECT_PATH
, &path
,
3540 DBUS_TYPE_INVALID
)) {
3541 log_error("Failed to parse reply: %s", bus_error_message(&error
));
3545 r
= show_one(verb
, bus
, path
, false, new_line
);
3549 static int show_all(const char* verb
, DBusConnection
*bus
, bool show_properties
, bool *new_line
) {
3550 _cleanup_dbus_message_unref_ DBusMessage
*reply
= NULL
;
3551 _cleanup_free_
struct unit_info
*unit_infos
= NULL
;
3553 const struct unit_info
*u
;
3556 r
= get_unit_list(bus
, &reply
, &unit_infos
, &c
);
3560 qsort(unit_infos
, c
, sizeof(struct unit_info
), compare_unit_info
);
3562 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
3563 _cleanup_free_
char *p
= NULL
;
3565 if (!output_show_unit(u
))
3568 p
= unit_dbus_path_from_name(u
->id
);
3572 printf("%s -> '%s'\n", u
->id
, p
);
3574 r
= show_one(verb
, bus
, p
, show_properties
, new_line
);
3582 static int show(DBusConnection
*bus
, char **args
) {
3584 bool show_properties
, show_status
, new_line
= false;
3590 show_properties
= streq(args
[0], "show");
3591 show_status
= streq(args
[0], "status");
3593 if (show_properties
)
3594 pager_open_if_enabled();
3596 /* If no argument is specified inspect the manager itself */
3598 if (show_properties
&& strv_length(args
) <= 1)
3599 return show_one(args
[0], bus
, "/org/freedesktop/systemd1", show_properties
, &new_line
);
3601 if (show_status
&& strv_length(args
) <= 1)
3602 return show_all(args
[0], bus
, false, &new_line
);
3604 STRV_FOREACH(name
, args
+1) {
3607 if (safe_atou32(*name
, &id
) < 0) {
3608 _cleanup_free_
char *p
= NULL
, *n
= NULL
;
3609 /* Interpret as unit name */
3611 n
= unit_name_mangle(*name
);
3615 p
= unit_dbus_path_from_name(n
);
3619 r
= show_one(args
[0], bus
, p
, show_properties
, &new_line
);
3623 } else if (show_properties
) {
3624 _cleanup_free_
char *p
= NULL
;
3626 /* Interpret as job id */
3627 if (asprintf(&p
, "/org/freedesktop/systemd1/job/%u", id
) < 0)
3630 r
= show_one(args
[0], bus
, p
, show_properties
, &new_line
);
3635 /* Interpret as PID */
3636 r
= show_one_by_pid(args
[0], bus
, id
, &new_line
);
3645 static int dump(DBusConnection
*bus
, char **args
) {
3646 _cleanup_free_ DBusMessage
*reply
= NULL
;
3651 dbus_error_init(&error
);
3653 pager_open_if_enabled();
3655 r
= bus_method_call_with_reply(
3657 "org.freedesktop.systemd1",
3658 "/org/freedesktop/systemd1",
3659 "org.freedesktop.systemd1.Manager",
3667 if (!dbus_message_get_args(reply
, &error
,
3668 DBUS_TYPE_STRING
, &text
,
3669 DBUS_TYPE_INVALID
)) {
3670 log_error("Failed to parse reply: %s", bus_error_message(&error
));
3671 dbus_error_free(&error
);
3675 fputs(text
, stdout
);
3679 static int snapshot(DBusConnection
*bus
, char **args
) {
3680 _cleanup_dbus_message_unref_ DBusMessage
*reply
= NULL
;
3683 dbus_bool_t cleanup
= FALSE
;
3684 DBusMessageIter iter
, sub
;
3687 *interface
= "org.freedesktop.systemd1.Unit",
3689 _cleanup_free_
char *n
= NULL
;
3691 dbus_error_init(&error
);
3693 if (strv_length(args
) > 1)
3694 n
= snapshot_name_mangle(args
[1]);
3700 r
= bus_method_call_with_reply (
3702 "org.freedesktop.systemd1",
3703 "/org/freedesktop/systemd1",
3704 "org.freedesktop.systemd1.Manager",
3708 DBUS_TYPE_STRING
, &n
,
3709 DBUS_TYPE_BOOLEAN
, &cleanup
,
3714 if (!dbus_message_get_args(reply
, &error
,
3715 DBUS_TYPE_OBJECT_PATH
, &path
,
3716 DBUS_TYPE_INVALID
)) {
3717 log_error("Failed to parse reply: %s", bus_error_message(&error
));
3718 dbus_error_free(&error
);
3722 dbus_message_unref(reply
);
3725 r
= bus_method_call_with_reply (
3727 "org.freedesktop.systemd1",
3729 "org.freedesktop.DBus.Properties",
3733 DBUS_TYPE_STRING
, &interface
,
3734 DBUS_TYPE_STRING
, &property
,
3739 if (!dbus_message_iter_init(reply
, &iter
) ||
3740 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_VARIANT
) {
3741 log_error("Failed to parse reply.");
3745 dbus_message_iter_recurse(&iter
, &sub
);
3747 if (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_STRING
) {
3748 log_error("Failed to parse reply.");
3752 dbus_message_iter_get_basic(&sub
, &id
);
3760 static int delete_snapshot(DBusConnection
*bus
, char **args
) {
3765 STRV_FOREACH(name
, args
+1) {
3766 _cleanup_free_
char *n
= NULL
;
3769 n
= snapshot_name_mangle(*name
);
3773 r
= bus_method_call_with_reply(
3775 "org.freedesktop.systemd1",
3776 "/org/freedesktop/systemd1",
3777 "org.freedesktop.systemd1.Manager",
3781 DBUS_TYPE_STRING
, &n
,
3790 static int daemon_reload(DBusConnection
*bus
, char **args
) {
3795 if (arg_action
== ACTION_RELOAD
)
3797 else if (arg_action
== ACTION_REEXEC
)
3798 method
= "Reexecute";
3800 assert(arg_action
== ACTION_SYSTEMCTL
);
3803 streq(args
[0], "clear-jobs") ||
3804 streq(args
[0], "cancel") ? "ClearJobs" :
3805 streq(args
[0], "daemon-reexec") ? "Reexecute" :
3806 streq(args
[0], "reset-failed") ? "ResetFailed" :
3807 streq(args
[0], "halt") ? "Halt" :
3808 streq(args
[0], "poweroff") ? "PowerOff" :
3809 streq(args
[0], "reboot") ? "Reboot" :
3810 streq(args
[0], "kexec") ? "KExec" :
3811 streq(args
[0], "exit") ? "Exit" :
3812 /* "daemon-reload" */ "Reload";
3815 r
= bus_method_call_with_reply(
3817 "org.freedesktop.systemd1",
3818 "/org/freedesktop/systemd1",
3819 "org.freedesktop.systemd1.Manager",
3825 if (r
== -ENOENT
&& arg_action
!= ACTION_SYSTEMCTL
)
3826 /* There's always a fallback possible for
3827 * legacy actions. */
3829 else if (r
== -ETIMEDOUT
&& streq(method
, "Reexecute"))
3830 /* On reexecution, we expect a disconnect, not
3834 log_error("Failed to issue method call: %s", bus_error_message(&error
));
3836 dbus_error_free(&error
);
3840 static int reset_failed(DBusConnection
*bus
, char **args
) {
3844 if (strv_length(args
) <= 1)
3845 return daemon_reload(bus
, args
);
3847 STRV_FOREACH(name
, args
+1) {
3848 _cleanup_free_
char *n
;
3850 n
= unit_name_mangle(*name
);
3854 r
= bus_method_call_with_reply(
3856 "org.freedesktop.systemd1",
3857 "/org/freedesktop/systemd1",
3858 "org.freedesktop.systemd1.Manager",
3862 DBUS_TYPE_STRING
, &n
,
3871 static int show_enviroment(DBusConnection
*bus
, char **args
) {
3872 _cleanup_dbus_message_unref_ DBusMessage
*reply
= NULL
;
3873 DBusMessageIter iter
, sub
, sub2
;
3876 *interface
= "org.freedesktop.systemd1.Manager",
3877 *property
= "Environment";
3879 pager_open_if_enabled();
3881 r
= bus_method_call_with_reply(
3883 "org.freedesktop.systemd1",
3884 "/org/freedesktop/systemd1",
3885 "org.freedesktop.DBus.Properties",
3889 DBUS_TYPE_STRING
, &interface
,
3890 DBUS_TYPE_STRING
, &property
,
3895 if (!dbus_message_iter_init(reply
, &iter
) ||
3896 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_VARIANT
) {
3897 log_error("Failed to parse reply.");
3901 dbus_message_iter_recurse(&iter
, &sub
);
3903 if (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_ARRAY
||
3904 dbus_message_iter_get_element_type(&sub
) != DBUS_TYPE_STRING
) {
3905 log_error("Failed to parse reply.");
3909 dbus_message_iter_recurse(&sub
, &sub2
);
3911 while (dbus_message_iter_get_arg_type(&sub2
) != DBUS_TYPE_INVALID
) {
3914 if (dbus_message_iter_get_arg_type(&sub2
) != DBUS_TYPE_STRING
) {
3915 log_error("Failed to parse reply.");
3919 dbus_message_iter_get_basic(&sub2
, &text
);
3922 dbus_message_iter_next(&sub2
);
3928 static int switch_root(DBusConnection
*bus
, char **args
) {
3931 _cleanup_free_
char *init
= NULL
;
3933 l
= strv_length(args
);
3934 if (l
< 2 || l
> 3) {
3935 log_error("Wrong number of arguments.");
3942 init
= strdup(args
[2]);
3944 parse_env_file("/proc/cmdline", WHITESPACE
,
3954 log_debug("switching root - root: %s; init: %s", root
, init
);
3956 return bus_method_call_with_reply(
3958 "org.freedesktop.systemd1",
3959 "/org/freedesktop/systemd1",
3960 "org.freedesktop.systemd1.Manager",
3964 DBUS_TYPE_STRING
, &root
,
3965 DBUS_TYPE_STRING
, &init
,
3969 static int set_environment(DBusConnection
*bus
, char **args
) {
3970 _cleanup_dbus_message_unref_ DBusMessage
*m
= NULL
, *reply
= NULL
;
3973 DBusMessageIter iter
;
3979 dbus_error_init(&error
);
3981 method
= streq(args
[0], "set-environment")
3983 : "UnsetEnvironment";
3985 m
= dbus_message_new_method_call(
3986 "org.freedesktop.systemd1",
3987 "/org/freedesktop/systemd1",
3988 "org.freedesktop.systemd1.Manager",
3993 dbus_message_iter_init_append(m
, &iter
);
3995 r
= bus_append_strv_iter(&iter
, args
+ 1);
3999 reply
= dbus_connection_send_with_reply_and_block(bus
, m
, -1, &error
);
4001 log_error("Failed to issue method call: %s", bus_error_message(&error
));
4002 dbus_error_free(&error
);
4009 static int enable_sysv_units(char **args
) {
4012 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4013 const char *verb
= args
[0];
4014 unsigned f
= 1, t
= 1;
4015 LookupPaths paths
= {};
4017 if (arg_scope
!= UNIT_FILE_SYSTEM
)
4020 if (!streq(verb
, "enable") &&
4021 !streq(verb
, "disable") &&
4022 !streq(verb
, "is-enabled"))
4025 /* Processes all SysV units, and reshuffles the array so that
4026 * afterwards only the native units remain */
4028 r
= lookup_paths_init(&paths
, SYSTEMD_SYSTEM
, false, NULL
, NULL
, NULL
);
4033 for (f
= 1; args
[f
]; f
++) {
4035 _cleanup_free_
char *p
= NULL
, *q
= NULL
;
4036 bool found_native
= false, found_sysv
;
4038 const char *argv
[6] = { "/sbin/chkconfig", NULL
, NULL
, NULL
, NULL
};
4046 if (!endswith(name
, ".service"))
4049 if (path_is_absolute(name
))
4052 STRV_FOREACH(k
, paths
.unit_path
) {
4053 if (!isempty(arg_root
))
4054 asprintf(&p
, "%s/%s/%s", arg_root
, *k
, name
);
4056 asprintf(&p
, "%s/%s", *k
, name
);
4063 found_native
= access(p
, F_OK
) >= 0;
4074 if (!isempty(arg_root
))
4075 asprintf(&p
, "%s/" SYSTEM_SYSVINIT_PATH
"/%s", arg_root
, name
);
4077 asprintf(&p
, SYSTEM_SYSVINIT_PATH
"/%s", name
);
4083 p
[strlen(p
) - sizeof(".service") + 1] = 0;
4084 found_sysv
= access(p
, F_OK
) >= 0;
4089 /* Mark this entry, so that we don't try enabling it as native unit */
4090 args
[f
] = (char*) "";
4092 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name
);
4094 if (!isempty(arg_root
))
4095 argv
[c
++] = q
= strappend("--root=", arg_root
);
4097 argv
[c
++] = path_get_file_name(p
);
4099 streq(verb
, "enable") ? "on" :
4100 streq(verb
, "disable") ? "off" : "--level=5";
4103 l
= strv_join((char**)argv
, " ");
4109 log_info("Executing %s", l
);
4114 log_error("Failed to fork: %m");
4117 } else if (pid
== 0) {
4120 execv(argv
[0], (char**) argv
);
4121 _exit(EXIT_FAILURE
);
4124 j
= wait_for_terminate(pid
, &status
);
4126 log_error("Failed to wait for child: %s", strerror(-r
));
4131 if (status
.si_code
== CLD_EXITED
) {
4132 if (streq(verb
, "is-enabled")) {
4133 if (status
.si_status
== 0) {
4142 } else if (status
.si_status
!= 0) {
4153 lookup_paths_free(&paths
);
4155 /* Drop all SysV units */
4156 for (f
= 1, t
= 1; args
[f
]; f
++) {
4158 if (isempty(args
[f
]))
4161 args
[t
++] = args
[f
];
4170 static int mangle_names(char **original_names
, char ***mangled_names
) {
4171 char **i
, **l
, **name
;
4173 l
= new(char*, strv_length(original_names
) + 1);
4178 STRV_FOREACH(name
, original_names
) {
4180 /* When enabling units qualified path names are OK,
4181 * too, hence allow them explicitly. */
4186 *i
= unit_name_mangle(*name
);
4202 static int enable_unit(DBusConnection
*bus
, char **args
) {
4203 const char *verb
= args
[0];
4204 UnitFileChange
*changes
= NULL
;
4205 unsigned n_changes
= 0, i
;
4206 int carries_install_info
= -1;
4207 _cleanup_dbus_message_unref_ DBusMessage
*m
= NULL
, *reply
= NULL
;
4209 _cleanup_dbus_error_free_ DBusError error
;
4210 _cleanup_strv_free_
char **mangled_names
= NULL
;
4212 dbus_error_init(&error
);
4214 r
= enable_sysv_units(args
);
4221 if (!bus
|| avoid_bus()) {
4222 if (streq(verb
, "enable")) {
4223 r
= unit_file_enable(arg_scope
, arg_runtime
, arg_root
, args
+1, arg_force
, &changes
, &n_changes
);
4224 carries_install_info
= r
;
4225 } else if (streq(verb
, "disable"))
4226 r
= unit_file_disable(arg_scope
, arg_runtime
, arg_root
, args
+1, &changes
, &n_changes
);
4227 else if (streq(verb
, "reenable")) {
4228 r
= unit_file_reenable(arg_scope
, arg_runtime
, arg_root
, args
+1, arg_force
, &changes
, &n_changes
);
4229 carries_install_info
= r
;
4230 } else if (streq(verb
, "link"))
4231 r
= unit_file_link(arg_scope
, arg_runtime
, arg_root
, args
+1, arg_force
, &changes
, &n_changes
);
4232 else if (streq(verb
, "preset")) {
4233 r
= unit_file_preset(arg_scope
, arg_runtime
, arg_root
, args
+1, arg_force
, &changes
, &n_changes
);
4234 carries_install_info
= r
;
4235 } else if (streq(verb
, "mask"))
4236 r
= unit_file_mask(arg_scope
, arg_runtime
, arg_root
, args
+1, arg_force
, &changes
, &n_changes
);
4237 else if (streq(verb
, "unmask"))
4238 r
= unit_file_unmask(arg_scope
, arg_runtime
, arg_root
, args
+1, &changes
, &n_changes
);
4240 assert_not_reached("Unknown verb");
4243 log_error("Operation failed: %s", strerror(-r
));
4248 for (i
= 0; i
< n_changes
; i
++) {
4249 if (changes
[i
].type
== UNIT_FILE_SYMLINK
)
4250 log_info("ln -s '%s' '%s'", changes
[i
].source
, changes
[i
].path
);
4252 log_info("rm '%s'", changes
[i
].path
);
4259 bool send_force
= true, expect_carries_install_info
= false;
4261 DBusMessageIter iter
, sub
, sub2
;
4263 if (streq(verb
, "enable")) {
4264 method
= "EnableUnitFiles";
4265 expect_carries_install_info
= true;
4266 } else if (streq(verb
, "disable")) {
4267 method
= "DisableUnitFiles";
4269 } else if (streq(verb
, "reenable")) {
4270 method
= "ReenableUnitFiles";
4271 expect_carries_install_info
= true;
4272 } else if (streq(verb
, "link"))
4273 method
= "LinkUnitFiles";
4274 else if (streq(verb
, "preset")) {
4275 method
= "PresetUnitFiles";
4276 expect_carries_install_info
= true;
4277 } else if (streq(verb
, "mask"))
4278 method
= "MaskUnitFiles";
4279 else if (streq(verb
, "unmask")) {
4280 method
= "UnmaskUnitFiles";
4283 assert_not_reached("Unknown verb");
4285 m
= dbus_message_new_method_call(
4286 "org.freedesktop.systemd1",
4287 "/org/freedesktop/systemd1",
4288 "org.freedesktop.systemd1.Manager",
4295 dbus_message_iter_init_append(m
, &iter
);
4297 r
= mangle_names(args
+1, &mangled_names
);
4301 r
= bus_append_strv_iter(&iter
, mangled_names
);
4303 log_error("Failed to append unit files.");
4308 if (!dbus_message_iter_append_basic(&iter
, DBUS_TYPE_BOOLEAN
, &a
)) {
4309 log_error("Failed to append runtime boolean.");
4317 if (!dbus_message_iter_append_basic(&iter
, DBUS_TYPE_BOOLEAN
, &b
)) {
4318 log_error("Failed to append force boolean.");
4324 reply
= dbus_connection_send_with_reply_and_block(bus
, m
, -1, &error
);
4326 log_error("Failed to issue method call: %s", bus_error_message(&error
));
4331 if (!dbus_message_iter_init(reply
, &iter
)) {
4332 log_error("Failed to initialize iterator.");
4336 if (expect_carries_install_info
) {
4337 r
= bus_iter_get_basic_and_next(&iter
, DBUS_TYPE_BOOLEAN
, &b
, true);
4339 log_error("Failed to parse reply.");
4343 carries_install_info
= b
;
4346 if (dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_ARRAY
||
4347 dbus_message_iter_get_element_type(&iter
) != DBUS_TYPE_STRUCT
) {
4348 log_error("Failed to parse reply.");
4353 dbus_message_iter_recurse(&iter
, &sub
);
4354 while (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_INVALID
) {
4355 const char *type
, *path
, *source
;
4357 if (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_STRUCT
) {
4358 log_error("Failed to parse reply.");
4363 dbus_message_iter_recurse(&sub
, &sub2
);
4365 if (bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &type
, true) < 0 ||
4366 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &path
, true) < 0 ||
4367 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &source
, false) < 0) {
4368 log_error("Failed to parse reply.");
4374 if (streq(type
, "symlink"))
4375 log_info("ln -s '%s' '%s'", source
, path
);
4377 log_info("rm '%s'", path
);
4380 dbus_message_iter_next(&sub
);
4383 /* Try to reload if enabeld */
4385 r
= daemon_reload(bus
, args
);
4388 if (carries_install_info
== 0)
4389 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
4390 "using systemctl.\n"
4391 "Possible reasons for having this kind of units are:\n"
4392 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4393 " .wants/ or .requires/ directory.\n"
4394 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4395 " a requirement dependency on it.\n"
4396 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4397 " D-Bus, udev, scripted systemctl call, ...).\n");
4400 unit_file_changes_free(changes
, n_changes
);
4405 static int unit_is_enabled(DBusConnection
*bus
, char **args
) {
4406 _cleanup_dbus_error_free_ DBusError error
;
4408 _cleanup_dbus_message_unref_ DBusMessage
*reply
= NULL
;
4413 dbus_error_init(&error
);
4415 r
= enable_sysv_units(args
);
4421 if (!bus
|| avoid_bus()) {
4423 STRV_FOREACH(name
, args
+1) {
4424 UnitFileState state
;
4426 n
= unit_name_mangle(*name
);
4430 state
= unit_file_get_state(arg_scope
, arg_root
, n
);
4437 if (state
== UNIT_FILE_ENABLED
||
4438 state
== UNIT_FILE_ENABLED_RUNTIME
||
4439 state
== UNIT_FILE_STATIC
)
4443 puts(unit_file_state_to_string(state
));
4447 STRV_FOREACH(name
, args
+1) {
4450 n
= unit_name_mangle(*name
);
4454 r
= bus_method_call_with_reply (
4456 "org.freedesktop.systemd1",
4457 "/org/freedesktop/systemd1",
4458 "org.freedesktop.systemd1.Manager",
4462 DBUS_TYPE_STRING
, &n
,
4470 if (!dbus_message_get_args(reply
, &error
,
4471 DBUS_TYPE_STRING
, &s
,
4472 DBUS_TYPE_INVALID
)) {
4473 log_error("Failed to parse reply: %s", bus_error_message(&error
));
4477 dbus_message_unref(reply
);
4480 if (streq(s
, "enabled") ||
4481 streq(s
, "enabled-runtime") ||
4490 return enabled
? 0 : 1;
4493 static int systemctl_help(void) {
4495 pager_open_if_enabled();
4497 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4498 "Query or send control commands to the systemd manager.\n\n"
4499 " -h --help Show this help\n"
4500 " --version Show package version\n"
4501 " -t --type=TYPE List only units of a particular type\n"
4502 " -p --property=NAME Show only properties by this name\n"
4503 " -a --all Show all loaded units/properties, including dead/empty\n"
4504 " ones. To list all units installed on the system, use\n"
4505 " the 'list-unit-files' command instead.\n"
4506 " --reverse Show reverse dependencies with 'list-dependencies'\n"
4507 " --failed Show only failed units\n"
4508 " --full Don't ellipsize unit names on output\n"
4509 " --fail When queueing a new job, fail if conflicting jobs are\n"
4511 " --irreversible Create jobs which cannot be implicitly cancelled\n"
4512 " --show-types When showing sockets, explicitly show their type\n"
4513 " --ignore-dependencies\n"
4514 " When queueing a new job, ignore all its dependencies\n"
4515 " -i --ignore-inhibitors\n"
4516 " When shutting down or sleeping, ignore inhibitors\n"
4517 " --kill-who=WHO Who to send signal to\n"
4518 " -s --signal=SIGNAL Which signal to send\n"
4519 " -H --host=[USER@]HOST\n"
4520 " Show information for remote host\n"
4521 " -P --privileged Acquire privileges before execution\n"
4522 " -q --quiet Suppress output\n"
4523 " --no-block Do not wait until operation finished\n"
4524 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4525 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4527 " --no-legend Do not print a legend (column headers and hints)\n"
4528 " --no-pager Do not pipe output into a pager\n"
4529 " --no-ask-password\n"
4530 " Do not ask for system passwords\n"
4531 " --system Connect to system manager\n"
4532 " --user Connect to user service manager\n"
4533 " --global Enable/disable unit files globally\n"
4534 " -f --force When enabling unit files, override existing symlinks\n"
4535 " When shutting down, execute action immediately\n"
4536 " --root=PATH Enable unit files in the specified root directory\n"
4537 " --runtime Enable unit files only temporarily until next reboot\n"
4538 " -n --lines=INTEGER Journal entries to show\n"
4539 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4540 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4542 " list-units List loaded units\n"
4543 " start [NAME...] Start (activate) one or more units\n"
4544 " stop [NAME...] Stop (deactivate) one or more units\n"
4545 " reload [NAME...] Reload one or more units\n"
4546 " restart [NAME...] Start or restart one or more units\n"
4547 " try-restart [NAME...] Restart one or more units if active\n"
4548 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4549 " otherwise start or restart\n"
4550 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4551 " otherwise restart if active\n"
4552 " isolate [NAME] Start one unit and stop all others\n"
4553 " kill [NAME...] Send signal to processes of a unit\n"
4554 " is-active [NAME...] Check whether units are active\n"
4555 " is-failed [NAME...] Check whether units are failed\n"
4556 " status [NAME...|PID...] Show runtime status of one or more units\n"
4557 " show [NAME...|JOB...] Show properties of one or more\n"
4558 " units/jobs or the manager\n"
4559 " help [NAME...|PID...] Show manual for one or more units\n"
4560 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4562 " get-cgroup-attr [NAME] [ATTR] ...\n"
4563 " Get control group attrubute\n"
4564 " set-cgroup-attr [NAME] [ATTR] [VALUE] ...\n"
4565 " Set control group attribute\n"
4566 " unset-cgroup-attr [NAME] [ATTR...]\n"
4567 " Unset control group attribute\n"
4568 " set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
4569 " unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
4570 " load [NAME...] Load one or more units\n"
4571 " list-dependencies [NAME] Recursively show units which are required\n"
4572 " or wanted by this unit or by which this\n"
4573 " unit is required or wanted\n\n"
4574 "Unit File Commands:\n"
4575 " list-unit-files List installed unit files\n"
4576 " enable [NAME...] Enable one or more unit files\n"
4577 " disable [NAME...] Disable one or more unit files\n"
4578 " reenable [NAME...] Reenable one or more unit files\n"
4579 " preset [NAME...] Enable/disable one or more unit files\n"
4580 " based on preset configuration\n"
4581 " mask [NAME...] Mask one or more units\n"
4582 " unmask [NAME...] Unmask one or more units\n"
4583 " link [PATH...] Link one or more units files into\n"
4584 " the search path\n"
4585 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4587 " list-jobs List jobs\n"
4588 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4589 "Status Commands:\n"
4590 " dump Dump server status\n"
4591 "Snapshot Commands:\n"
4592 " snapshot [NAME] Create a snapshot\n"
4593 " delete [NAME...] Remove one or more snapshots\n\n"
4594 "Environment Commands:\n"
4595 " show-environment Dump environment\n"
4596 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4597 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4598 "Manager Lifecycle Commands:\n"
4599 " daemon-reload Reload systemd manager configuration\n"
4600 " daemon-reexec Reexecute systemd manager\n\n"
4601 "System Commands:\n"
4602 " default Enter system default mode\n"
4603 " rescue Enter system rescue mode\n"
4604 " emergency Enter system emergency mode\n"
4605 " halt Shut down and halt the system\n"
4606 " poweroff Shut down and power-off the system\n"
4607 " reboot Shut down and reboot the system\n"
4608 " kexec Shut down and reboot the system with kexec\n"
4609 " exit Request user instance exit\n"
4610 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4611 " suspend Suspend the system\n"
4612 " hibernate Hibernate the system\n"
4613 " hybrid-sleep Hibernate and suspend the system\n",
4614 program_invocation_short_name
);
4619 static int halt_help(void) {
4621 printf("%s [OPTIONS...]\n\n"
4622 "%s the system.\n\n"
4623 " --help Show this help\n"
4624 " --halt Halt the machine\n"
4625 " -p --poweroff Switch off the machine\n"
4626 " --reboot Reboot the machine\n"
4627 " -f --force Force immediate halt/power-off/reboot\n"
4628 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4629 " -d --no-wtmp Don't write wtmp record\n"
4630 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4631 program_invocation_short_name
,
4632 arg_action
== ACTION_REBOOT
? "Reboot" :
4633 arg_action
== ACTION_POWEROFF
? "Power off" :
4639 static int shutdown_help(void) {
4641 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4642 "Shut down the system.\n\n"
4643 " --help Show this help\n"
4644 " -H --halt Halt the machine\n"
4645 " -P --poweroff Power-off the machine\n"
4646 " -r --reboot Reboot the machine\n"
4647 " -h Equivalent to --poweroff, overridden by --halt\n"
4648 " -k Don't halt/power-off/reboot, just send warnings\n"
4649 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4650 " -c Cancel a pending shutdown\n",
4651 program_invocation_short_name
);
4656 static int telinit_help(void) {
4658 printf("%s [OPTIONS...] {COMMAND}\n\n"
4659 "Send control commands to the init daemon.\n\n"
4660 " --help Show this help\n"
4661 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4663 " 0 Power-off the machine\n"
4664 " 6 Reboot the machine\n"
4665 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4666 " 1, s, S Enter rescue mode\n"
4667 " q, Q Reload init daemon configuration\n"
4668 " u, U Reexecute init daemon\n",
4669 program_invocation_short_name
);
4674 static int runlevel_help(void) {
4676 printf("%s [OPTIONS...]\n\n"
4677 "Prints the previous and current runlevel of the init system.\n\n"
4678 " --help Show this help\n",
4679 program_invocation_short_name
);
4684 static int help_types(void) {
4688 puts("Available unit types:");
4689 for(i
= 0; i
< _UNIT_TYPE_MAX
; i
++) {
4690 t
= unit_type_to_string(i
);
4695 puts("\nAvailable unit load states: ");
4696 for(i
= 0; i
< _UNIT_LOAD_STATE_MAX
; i
++) {
4697 t
= unit_load_state_to_string(i
);
4705 static int systemctl_parse_argv(int argc
, char *argv
[]) {
4714 ARG_IGNORE_DEPENDENCIES
,
4727 ARG_NO_ASK_PASSWORD
,
4734 static const struct option options
[] = {
4735 { "help", no_argument
, NULL
, 'h' },
4736 { "version", no_argument
, NULL
, ARG_VERSION
},
4737 { "type", required_argument
, NULL
, 't' },
4738 { "property", required_argument
, NULL
, 'p' },
4739 { "all", no_argument
, NULL
, 'a' },
4740 { "reverse", no_argument
, NULL
, ARG_REVERSE
},
4741 { "after", no_argument
, NULL
, ARG_AFTER
},
4742 { "before", no_argument
, NULL
, ARG_BEFORE
},
4743 { "show-types", no_argument
, NULL
, ARG_SHOW_TYPES
},
4744 { "failed", no_argument
, NULL
, ARG_FAILED
},
4745 { "full", no_argument
, NULL
, ARG_FULL
},
4746 { "fail", no_argument
, NULL
, ARG_FAIL
},
4747 { "irreversible", no_argument
, NULL
, ARG_IRREVERSIBLE
},
4748 { "ignore-dependencies", no_argument
, NULL
, ARG_IGNORE_DEPENDENCIES
},
4749 { "ignore-inhibitors", no_argument
, NULL
, 'i' },
4750 { "user", no_argument
, NULL
, ARG_USER
},
4751 { "system", no_argument
, NULL
, ARG_SYSTEM
},
4752 { "global", no_argument
, NULL
, ARG_GLOBAL
},
4753 { "no-block", no_argument
, NULL
, ARG_NO_BLOCK
},
4754 { "no-legend", no_argument
, NULL
, ARG_NO_LEGEND
},
4755 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
4756 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
4757 { "quiet", no_argument
, NULL
, 'q' },
4758 { "root", required_argument
, NULL
, ARG_ROOT
},
4759 { "force", no_argument
, NULL
, ARG_FORCE
},
4760 { "no-reload", no_argument
, NULL
, ARG_NO_RELOAD
},
4761 { "kill-who", required_argument
, NULL
, ARG_KILL_WHO
},
4762 { "signal", required_argument
, NULL
, 's' },
4763 { "no-ask-password", no_argument
, NULL
, ARG_NO_ASK_PASSWORD
},
4764 { "host", required_argument
, NULL
, 'H' },
4765 { "privileged",no_argument
, NULL
, 'P' },
4766 { "runtime", no_argument
, NULL
, ARG_RUNTIME
},
4767 { "lines", required_argument
, NULL
, 'n' },
4768 { "output", required_argument
, NULL
, 'o' },
4769 { "plain", no_argument
, NULL
, ARG_PLAIN
},
4770 { NULL
, 0, NULL
, 0 }
4778 while ((c
= getopt_long(argc
, argv
, "ht:p:aqfs:H:Pn:o:i", options
, NULL
)) >= 0) {
4787 puts(PACKAGE_STRING
);
4788 puts(SYSTEMD_FEATURES
);
4795 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
4796 _cleanup_free_
char *type
;
4798 type
= strndup(word
, size
);
4802 if (streq(type
, "help")) {
4807 if (unit_type_from_string(type
) >= 0) {
4808 if (strv_push(&arg_types
, type
))
4814 if (unit_load_state_from_string(optarg
) >= 0) {
4815 if (strv_push(&arg_load_states
, type
))
4821 log_error("Unknown unit type or load state '%s'.", type
);
4822 log_info("Use -t help to see a list of allowed values.");
4830 /* Make sure that if the empty property list
4831 was specified, we won't show any properties. */
4832 if (isempty(optarg
) && !arg_properties
) {
4833 arg_properties
= strv_new(NULL
, NULL
);
4834 if (!arg_properties
)
4840 FOREACH_WORD_SEPARATOR(word
, size
, optarg
, ",", state
) {
4843 prop
= strndup(word
, size
);
4847 if (strv_push(&arg_properties
, prop
)) {
4854 /* If the user asked for a particular
4855 * property, show it to him, even if it is
4867 arg_dependency
= DEPENDENCY_REVERSE
;
4871 arg_dependency
= DEPENDENCY_AFTER
;
4875 arg_dependency
= DEPENDENCY_BEFORE
;
4878 case ARG_SHOW_TYPES
:
4879 arg_show_types
= true;
4883 arg_job_mode
= "fail";
4886 case ARG_IRREVERSIBLE
:
4887 arg_job_mode
= "replace-irreversibly";
4890 case ARG_IGNORE_DEPENDENCIES
:
4891 arg_job_mode
= "ignore-dependencies";
4895 arg_scope
= UNIT_FILE_USER
;
4899 arg_scope
= UNIT_FILE_SYSTEM
;
4903 arg_scope
= UNIT_FILE_GLOBAL
;
4907 arg_no_block
= true;
4911 arg_no_legend
= true;
4915 arg_no_pager
= true;
4947 arg_no_reload
= true;
4951 arg_kill_who
= optarg
;
4955 if ((arg_signal
= signal_from_string_try_harder(optarg
)) < 0) {
4956 log_error("Failed to parse signal string %s.", optarg
);
4961 case ARG_NO_ASK_PASSWORD
:
4962 arg_ask_password
= false;
4966 arg_transport
= TRANSPORT_POLKIT
;
4970 arg_transport
= TRANSPORT_SSH
;
4979 if (safe_atou(optarg
, &arg_lines
) < 0) {
4980 log_error("Failed to parse lines '%s'", optarg
);
4986 arg_output
= output_mode_from_string(optarg
);
4987 if (arg_output
< 0) {
4988 log_error("Unknown output '%s'.", optarg
);
4994 arg_ignore_inhibitors
= true;
5005 log_error("Unknown option code '%c'.", c
);
5010 if (arg_transport
!= TRANSPORT_NORMAL
&& arg_scope
!= UNIT_FILE_SYSTEM
) {
5011 log_error("Cannot access user instance remotely.");
5018 static int halt_parse_argv(int argc
, char *argv
[]) {
5027 static const struct option options
[] = {
5028 { "help", no_argument
, NULL
, ARG_HELP
},
5029 { "halt", no_argument
, NULL
, ARG_HALT
},
5030 { "poweroff", no_argument
, NULL
, 'p' },
5031 { "reboot", no_argument
, NULL
, ARG_REBOOT
},
5032 { "force", no_argument
, NULL
, 'f' },
5033 { "wtmp-only", no_argument
, NULL
, 'w' },
5034 { "no-wtmp", no_argument
, NULL
, 'd' },
5035 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
5036 { NULL
, 0, NULL
, 0 }
5044 if (utmp_get_runlevel(&runlevel
, NULL
) >= 0)
5045 if (runlevel
== '0' || runlevel
== '6')
5048 while ((c
= getopt_long(argc
, argv
, "pfwdnih", options
, NULL
)) >= 0) {
5056 arg_action
= ACTION_HALT
;
5060 if (arg_action
!= ACTION_REBOOT
)
5061 arg_action
= ACTION_POWEROFF
;
5065 arg_action
= ACTION_REBOOT
;
5087 /* Compatibility nops */
5094 log_error("Unknown option code '%c'.", c
);
5099 if (optind
< argc
) {
5100 log_error("Too many arguments.");
5107 static int parse_time_spec(const char *t
, usec_t
*_u
) {
5111 if (streq(t
, "now"))
5113 else if (!strchr(t
, ':')) {
5116 if (safe_atou64(t
, &u
) < 0)
5119 *_u
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
* u
;
5128 hour
= strtol(t
, &e
, 10);
5129 if (errno
> 0 || *e
!= ':' || hour
< 0 || hour
> 23)
5132 minute
= strtol(e
+1, &e
, 10);
5133 if (errno
> 0 || *e
!= 0 || minute
< 0 || minute
> 59)
5136 n
= now(CLOCK_REALTIME
);
5137 s
= (time_t) (n
/ USEC_PER_SEC
);
5139 assert_se(localtime_r(&s
, &tm
));
5141 tm
.tm_hour
= (int) hour
;
5142 tm
.tm_min
= (int) minute
;
5145 assert_se(s
= mktime(&tm
));
5147 *_u
= (usec_t
) s
* USEC_PER_SEC
;
5150 *_u
+= USEC_PER_DAY
;
5156 static int shutdown_parse_argv(int argc
, char *argv
[]) {
5163 static const struct option options
[] = {
5164 { "help", no_argument
, NULL
, ARG_HELP
},
5165 { "halt", no_argument
, NULL
, 'H' },
5166 { "poweroff", no_argument
, NULL
, 'P' },
5167 { "reboot", no_argument
, NULL
, 'r' },
5168 { "kexec", no_argument
, NULL
, 'K' }, /* not documented extension */
5169 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
5170 { NULL
, 0, NULL
, 0 }
5178 while ((c
= getopt_long(argc
, argv
, "HPrhkt:afFc", options
, NULL
)) >= 0) {
5186 arg_action
= ACTION_HALT
;
5190 arg_action
= ACTION_POWEROFF
;
5195 arg_action
= ACTION_KEXEC
;
5197 arg_action
= ACTION_REBOOT
;
5201 arg_action
= ACTION_KEXEC
;
5205 if (arg_action
!= ACTION_HALT
)
5206 arg_action
= ACTION_POWEROFF
;
5219 /* Compatibility nops */
5223 arg_action
= ACTION_CANCEL_SHUTDOWN
;
5230 log_error("Unknown option code '%c'.", c
);
5235 if (argc
> optind
&& arg_action
!= ACTION_CANCEL_SHUTDOWN
) {
5236 r
= parse_time_spec(argv
[optind
], &arg_when
);
5238 log_error("Failed to parse time specification: %s", argv
[optind
]);
5242 arg_when
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
;
5244 if (argc
> optind
&& arg_action
== ACTION_CANCEL_SHUTDOWN
)
5245 /* No time argument for shutdown cancel */
5246 arg_wall
= argv
+ optind
;
5247 else if (argc
> optind
+ 1)
5248 /* We skip the time argument */
5249 arg_wall
= argv
+ optind
+ 1;
5256 static int telinit_parse_argv(int argc
, char *argv
[]) {
5263 static const struct option options
[] = {
5264 { "help", no_argument
, NULL
, ARG_HELP
},
5265 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
5266 { NULL
, 0, NULL
, 0 }
5269 static const struct {
5273 { '0', ACTION_POWEROFF
},
5274 { '6', ACTION_REBOOT
},
5275 { '1', ACTION_RESCUE
},
5276 { '2', ACTION_RUNLEVEL2
},
5277 { '3', ACTION_RUNLEVEL3
},
5278 { '4', ACTION_RUNLEVEL4
},
5279 { '5', ACTION_RUNLEVEL5
},
5280 { 's', ACTION_RESCUE
},
5281 { 'S', ACTION_RESCUE
},
5282 { 'q', ACTION_RELOAD
},
5283 { 'Q', ACTION_RELOAD
},
5284 { 'u', ACTION_REEXEC
},
5285 { 'U', ACTION_REEXEC
}
5294 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0) {
5309 log_error("Unknown option code '%c'.", c
);
5314 if (optind
>= argc
) {
5319 if (optind
+ 1 < argc
) {
5320 log_error("Too many arguments.");
5324 if (strlen(argv
[optind
]) != 1) {
5325 log_error("Expected single character argument.");
5329 for (i
= 0; i
< ELEMENTSOF(table
); i
++)
5330 if (table
[i
].from
== argv
[optind
][0])
5333 if (i
>= ELEMENTSOF(table
)) {
5334 log_error("Unknown command '%s'.", argv
[optind
]);
5338 arg_action
= table
[i
].to
;
5345 static int runlevel_parse_argv(int argc
, char *argv
[]) {
5351 static const struct option options
[] = {
5352 { "help", no_argument
, NULL
, ARG_HELP
},
5353 { NULL
, 0, NULL
, 0 }
5361 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0) {
5372 log_error("Unknown option code '%c'.", c
);
5377 if (optind
< argc
) {
5378 log_error("Too many arguments.");
5385 static int parse_argv(int argc
, char *argv
[]) {
5389 if (program_invocation_short_name
) {
5391 if (strstr(program_invocation_short_name
, "halt")) {
5392 arg_action
= ACTION_HALT
;
5393 return halt_parse_argv(argc
, argv
);
5394 } else if (strstr(program_invocation_short_name
, "poweroff")) {
5395 arg_action
= ACTION_POWEROFF
;
5396 return halt_parse_argv(argc
, argv
);
5397 } else if (strstr(program_invocation_short_name
, "reboot")) {
5399 arg_action
= ACTION_KEXEC
;
5401 arg_action
= ACTION_REBOOT
;
5402 return halt_parse_argv(argc
, argv
);
5403 } else if (strstr(program_invocation_short_name
, "shutdown")) {
5404 arg_action
= ACTION_POWEROFF
;
5405 return shutdown_parse_argv(argc
, argv
);
5406 } else if (strstr(program_invocation_short_name
, "init")) {
5408 if (sd_booted() > 0) {
5409 arg_action
= ACTION_INVALID
;
5410 return telinit_parse_argv(argc
, argv
);
5412 /* Hmm, so some other init system is
5413 * running, we need to forward this
5414 * request to it. For now we simply
5415 * guess that it is Upstart. */
5417 execv(TELINIT
, argv
);
5419 log_error("Couldn't find an alternative telinit implementation to spawn.");
5423 } else if (strstr(program_invocation_short_name
, "runlevel")) {
5424 arg_action
= ACTION_RUNLEVEL
;
5425 return runlevel_parse_argv(argc
, argv
);
5429 arg_action
= ACTION_SYSTEMCTL
;
5430 return systemctl_parse_argv(argc
, argv
);
5433 _pure_
static int action_to_runlevel(void) {
5435 static const char table
[_ACTION_MAX
] = {
5436 [ACTION_HALT
] = '0',
5437 [ACTION_POWEROFF
] = '0',
5438 [ACTION_REBOOT
] = '6',
5439 [ACTION_RUNLEVEL2
] = '2',
5440 [ACTION_RUNLEVEL3
] = '3',
5441 [ACTION_RUNLEVEL4
] = '4',
5442 [ACTION_RUNLEVEL5
] = '5',
5443 [ACTION_RESCUE
] = '1'
5446 assert(arg_action
< _ACTION_MAX
);
5448 return table
[arg_action
];
5451 static int talk_upstart(void) {
5452 _cleanup_dbus_message_unref_ DBusMessage
*m
= NULL
, *reply
= NULL
;
5453 _cleanup_dbus_error_free_ DBusError error
;
5454 int previous
, rl
, r
;
5456 env1_buf
[] = "RUNLEVEL=X",
5457 env2_buf
[] = "PREVLEVEL=X";
5458 char *env1
= env1_buf
, *env2
= env2_buf
;
5459 const char *emit
= "runlevel";
5460 dbus_bool_t b_false
= FALSE
;
5461 DBusMessageIter iter
, sub
;
5462 DBusConnection
*bus
;
5464 dbus_error_init(&error
);
5466 if (!(rl
= action_to_runlevel()))
5469 if (utmp_get_runlevel(&previous
, NULL
) < 0)
5472 if (!(bus
= dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error
))) {
5473 if (dbus_error_has_name(&error
, DBUS_ERROR_NO_SERVER
)) {
5478 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error
));
5483 if ((r
= bus_check_peercred(bus
)) < 0) {
5484 log_error("Failed to verify owner of bus.");
5488 if (!(m
= dbus_message_new_method_call(
5489 "com.ubuntu.Upstart",
5490 "/com/ubuntu/Upstart",
5491 "com.ubuntu.Upstart0_6",
5494 log_error("Could not allocate message.");
5499 dbus_message_iter_init_append(m
, &iter
);
5501 env1_buf
[sizeof(env1_buf
)-2] = rl
;
5502 env2_buf
[sizeof(env2_buf
)-2] = previous
;
5504 if (!dbus_message_iter_append_basic(&iter
, DBUS_TYPE_STRING
, &emit
) ||
5505 !dbus_message_iter_open_container(&iter
, DBUS_TYPE_ARRAY
, "s", &sub
) ||
5506 !dbus_message_iter_append_basic(&sub
, DBUS_TYPE_STRING
, &env1
) ||
5507 !dbus_message_iter_append_basic(&sub
, DBUS_TYPE_STRING
, &env2
) ||
5508 !dbus_message_iter_close_container(&iter
, &sub
) ||
5509 !dbus_message_iter_append_basic(&iter
, DBUS_TYPE_BOOLEAN
, &b_false
)) {
5510 log_error("Could not append arguments to message.");
5515 if (!(reply
= dbus_connection_send_with_reply_and_block(bus
, m
, -1, &error
))) {
5517 if (bus_error_is_no_service(&error
)) {
5522 log_error("Failed to issue method call: %s", bus_error_message(&error
));
5531 dbus_connection_flush(bus
);
5532 dbus_connection_close(bus
);
5533 dbus_connection_unref(bus
);
5539 static int talk_initctl(void) {
5540 struct init_request request
= {};
5542 _cleanup_close_
int fd
= -1;
5545 rl
= action_to_runlevel();
5549 request
.magic
= INIT_MAGIC
;
5550 request
.sleeptime
= 0;
5551 request
.cmd
= INIT_CMD_RUNLVL
;
5552 request
.runlevel
= rl
;
5554 fd
= open(INIT_FIFO
, O_WRONLY
|O_NDELAY
|O_CLOEXEC
|O_NOCTTY
);
5556 if (errno
== ENOENT
)
5559 log_error("Failed to open "INIT_FIFO
": %m");
5564 r
= loop_write(fd
, &request
, sizeof(request
), false) != sizeof(request
);
5566 log_error("Failed to write to "INIT_FIFO
": %m");
5567 return errno
> 0 ? -errno
: -EIO
;
5573 static int systemctl_main(DBusConnection
*bus
, int argc
, char *argv
[], DBusError
*error
) {
5575 static const struct {
5583 int (* const dispatch
)(DBusConnection
*bus
, char **args
);
5585 { "list-units", LESS
, 1, list_units
},
5586 { "list-unit-files", EQUAL
, 1, list_unit_files
},
5587 { "list-sockets", LESS
, 1, list_sockets
},
5588 { "list-jobs", EQUAL
, 1, list_jobs
},
5589 { "clear-jobs", EQUAL
, 1, daemon_reload
},
5590 { "load", MORE
, 2, load_unit
},
5591 { "cancel", MORE
, 2, cancel_job
},
5592 { "start", MORE
, 2, start_unit
},
5593 { "stop", MORE
, 2, start_unit
},
5594 { "condstop", MORE
, 2, start_unit
}, /* For compatibility with ALTLinux */
5595 { "reload", MORE
, 2, start_unit
},
5596 { "restart", MORE
, 2, start_unit
},
5597 { "try-restart", MORE
, 2, start_unit
},
5598 { "reload-or-restart", MORE
, 2, start_unit
},
5599 { "reload-or-try-restart", MORE
, 2, start_unit
},
5600 { "force-reload", MORE
, 2, start_unit
}, /* For compatibility with SysV */
5601 { "condreload", MORE
, 2, start_unit
}, /* For compatibility with ALTLinux */
5602 { "condrestart", MORE
, 2, start_unit
}, /* For compatibility with RH */
5603 { "isolate", EQUAL
, 2, start_unit
},
5604 { "set-cgroup", MORE
, 3, set_cgroup
},
5605 { "unset-cgroup", MORE
, 3, set_cgroup
},
5606 { "get-cgroup-attr", MORE
, 3, get_cgroup_attr
},
5607 { "set-cgroup-attr", MORE
, 4, set_cgroup_attr
},
5608 { "unset-cgroup-attr", MORE
, 3, set_cgroup
},
5609 { "kill", MORE
, 2, kill_unit
},
5610 { "is-active", MORE
, 2, check_unit_active
},
5611 { "check", MORE
, 2, check_unit_active
},
5612 { "is-failed", MORE
, 2, check_unit_failed
},
5613 { "show", MORE
, 1, show
},
5614 { "status", MORE
, 1, show
},
5615 { "help", MORE
, 2, show
},
5616 { "dump", EQUAL
, 1, dump
},
5617 { "snapshot", LESS
, 2, snapshot
},
5618 { "delete", MORE
, 2, delete_snapshot
},
5619 { "daemon-reload", EQUAL
, 1, daemon_reload
},
5620 { "daemon-reexec", EQUAL
, 1, daemon_reload
},
5621 { "show-environment", EQUAL
, 1, show_enviroment
},
5622 { "set-environment", MORE
, 2, set_environment
},
5623 { "unset-environment", MORE
, 2, set_environment
},
5624 { "halt", EQUAL
, 1, start_special
},
5625 { "poweroff", EQUAL
, 1, start_special
},
5626 { "reboot", EQUAL
, 1, start_special
},
5627 { "kexec", EQUAL
, 1, start_special
},
5628 { "suspend", EQUAL
, 1, start_special
},
5629 { "hibernate", EQUAL
, 1, start_special
},
5630 { "hybrid-sleep", EQUAL
, 1, start_special
},
5631 { "default", EQUAL
, 1, start_special
},
5632 { "rescue", EQUAL
, 1, start_special
},
5633 { "emergency", EQUAL
, 1, start_special
},
5634 { "exit", EQUAL
, 1, start_special
},
5635 { "reset-failed", MORE
, 1, reset_failed
},
5636 { "enable", MORE
, 2, enable_unit
},
5637 { "disable", MORE
, 2, enable_unit
},
5638 { "is-enabled", MORE
, 2, unit_is_enabled
},
5639 { "reenable", MORE
, 2, enable_unit
},
5640 { "preset", MORE
, 2, enable_unit
},
5641 { "mask", MORE
, 2, enable_unit
},
5642 { "unmask", MORE
, 2, enable_unit
},
5643 { "link", MORE
, 2, enable_unit
},
5644 { "switch-root", MORE
, 2, switch_root
},
5645 { "list-dependencies", LESS
, 2, list_dependencies
},
5655 left
= argc
- optind
;
5658 /* Special rule: no arguments means "list-units" */
5661 if (streq(argv
[optind
], "help") && !argv
[optind
+1]) {
5662 log_error("This command expects one or more "
5663 "unit names. Did you mean --help?");
5667 for (i
= 0; i
< ELEMENTSOF(verbs
); i
++)
5668 if (streq(argv
[optind
], verbs
[i
].verb
))
5671 if (i
>= ELEMENTSOF(verbs
)) {
5672 log_error("Unknown operation '%s'.", argv
[optind
]);
5677 switch (verbs
[i
].argc_cmp
) {
5680 if (left
!= verbs
[i
].argc
) {
5681 log_error("Invalid number of arguments.");
5688 if (left
< verbs
[i
].argc
) {
5689 log_error("Too few arguments.");
5696 if (left
> verbs
[i
].argc
) {
5697 log_error("Too many arguments.");
5704 assert_not_reached("Unknown comparison operator.");
5707 /* Require a bus connection for all operations but
5709 if (!streq(verbs
[i
].verb
, "enable") &&
5710 !streq(verbs
[i
].verb
, "disable") &&
5711 !streq(verbs
[i
].verb
, "is-enabled") &&
5712 !streq(verbs
[i
].verb
, "list-unit-files") &&
5713 !streq(verbs
[i
].verb
, "reenable") &&
5714 !streq(verbs
[i
].verb
, "preset") &&
5715 !streq(verbs
[i
].verb
, "mask") &&
5716 !streq(verbs
[i
].verb
, "unmask") &&
5717 !streq(verbs
[i
].verb
, "link")) {
5719 if (running_in_chroot() > 0) {
5720 log_info("Running in chroot, ignoring request.");
5724 if (((!streq(verbs
[i
].verb
, "reboot") &&
5725 !streq(verbs
[i
].verb
, "halt") &&
5726 !streq(verbs
[i
].verb
, "poweroff")) || arg_force
<= 0) && !bus
) {
5727 log_error("Failed to get D-Bus connection: %s",
5728 dbus_error_is_set(error
) ? error
->message
: "No connection to service manager.");
5734 if (!bus
&& !avoid_bus()) {
5735 log_error("Failed to get D-Bus connection: %s",
5736 dbus_error_is_set(error
) ? error
->message
: "No connection to service manager.");
5741 return verbs
[i
].dispatch(bus
, argv
+ optind
);
5744 static int send_shutdownd(usec_t t
, char mode
, bool dry_run
, bool warn
, const char *message
) {
5745 _cleanup_close_
int fd
;
5746 struct sd_shutdown_command c
= {
5752 union sockaddr_union sockaddr
= {
5753 .un
.sun_family
= AF_UNIX
,
5754 .un
.sun_path
= "/run/systemd/shutdownd",
5756 struct iovec iovec
[2] = {
5757 {.iov_base
= (char*) &c
,
5758 .iov_len
= offsetof(struct sd_shutdown_command
, wall_message
),
5761 struct msghdr msghdr
= {
5762 .msg_name
= &sockaddr
,
5763 .msg_namelen
= offsetof(struct sockaddr_un
, sun_path
)
5764 + sizeof("/run/systemd/shutdownd") - 1,
5769 fd
= socket(AF_UNIX
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0);
5773 if (!isempty(message
)) {
5774 iovec
[1].iov_base
= (char*) message
;
5775 iovec
[1].iov_len
= strlen(message
);
5776 msghdr
.msg_iovlen
++;
5779 if (sendmsg(fd
, &msghdr
, MSG_NOSIGNAL
) < 0)
5785 static int reload_with_fallback(DBusConnection
*bus
) {
5788 /* First, try systemd via D-Bus. */
5789 if (daemon_reload(bus
, NULL
) >= 0)
5793 /* Nothing else worked, so let's try signals */
5794 assert(arg_action
== ACTION_RELOAD
|| arg_action
== ACTION_REEXEC
);
5796 if (kill(1, arg_action
== ACTION_RELOAD
? SIGHUP
: SIGTERM
) < 0) {
5797 log_error("kill() failed: %m");
5804 static int start_with_fallback(DBusConnection
*bus
) {
5807 /* First, try systemd via D-Bus. */
5808 if (start_unit(bus
, NULL
) >= 0)
5812 /* Hmm, talking to systemd via D-Bus didn't work. Then
5813 * let's try to talk to Upstart via D-Bus. */
5814 if (talk_upstart() > 0)
5817 /* Nothing else worked, so let's try
5819 if (talk_initctl() > 0)
5822 log_error("Failed to talk to init daemon.");
5826 warn_wall(arg_action
);
5830 static _noreturn_
void halt_now(enum action a
) {
5832 /* Make sure C-A-D is handled by the kernel from this
5834 reboot(RB_ENABLE_CAD
);
5839 log_info("Halting.");
5840 reboot(RB_HALT_SYSTEM
);
5843 case ACTION_POWEROFF
:
5844 log_info("Powering off.");
5845 reboot(RB_POWER_OFF
);
5849 log_info("Rebooting.");
5850 reboot(RB_AUTOBOOT
);
5854 assert_not_reached("Unknown halt action.");
5857 assert_not_reached("Uh? This shouldn't happen.");
5860 static int halt_main(DBusConnection
*bus
) {
5863 r
= check_inhibitors(bus
, arg_action
);
5867 if (geteuid() != 0) {
5868 /* Try logind if we are a normal user and no special
5869 * mode applies. Maybe PolicyKit allows us to shutdown
5872 if (arg_when
<= 0 &&
5875 (arg_action
== ACTION_POWEROFF
||
5876 arg_action
== ACTION_REBOOT
)) {
5877 r
= reboot_with_logind(bus
, arg_action
);
5882 log_error("Must be root.");
5887 _cleanup_free_
char *m
;
5889 m
= strv_join(arg_wall
, " ");
5890 r
= send_shutdownd(arg_when
,
5891 arg_action
== ACTION_HALT
? 'H' :
5892 arg_action
== ACTION_POWEROFF
? 'P' :
5893 arg_action
== ACTION_KEXEC
? 'K' :
5900 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r
));
5902 char date
[FORMAT_TIMESTAMP_MAX
];
5904 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5905 format_timestamp(date
, sizeof(date
), arg_when
));
5910 if (!arg_dry
&& !arg_force
)
5911 return start_with_fallback(bus
);
5914 if (sd_booted() > 0)
5915 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5917 r
= utmp_put_shutdown();
5919 log_warning("Failed to write utmp record: %s", strerror(-r
));
5926 halt_now(arg_action
);
5927 /* We should never reach this. */
5931 static int runlevel_main(void) {
5932 int r
, runlevel
, previous
;
5934 r
= utmp_get_runlevel(&runlevel
, &previous
);
5941 previous
<= 0 ? 'N' : previous
,
5942 runlevel
<= 0 ? 'N' : runlevel
);
5947 int main(int argc
, char*argv
[]) {
5948 int r
, retval
= EXIT_FAILURE
;
5949 DBusConnection
*bus
= NULL
;
5950 _cleanup_dbus_error_free_ DBusError error
;
5952 dbus_error_init(&error
);
5954 setlocale(LC_ALL
, "");
5955 log_parse_environment();
5958 r
= parse_argv(argc
, argv
);
5962 retval
= EXIT_SUCCESS
;
5966 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5967 * let's shortcut this */
5968 if (arg_action
== ACTION_RUNLEVEL
) {
5969 r
= runlevel_main();
5970 retval
= r
< 0 ? EXIT_FAILURE
: r
;
5974 if (running_in_chroot() > 0 && arg_action
!= ACTION_SYSTEMCTL
) {
5975 log_info("Running in chroot, ignoring request.");
5981 if (arg_transport
== TRANSPORT_NORMAL
)
5982 bus_connect(arg_scope
== UNIT_FILE_SYSTEM
? DBUS_BUS_SYSTEM
: DBUS_BUS_SESSION
, &bus
, &private_bus
, &error
);
5983 else if (arg_transport
== TRANSPORT_POLKIT
) {
5984 bus_connect_system_polkit(&bus
, &error
);
5985 private_bus
= false;
5986 } else if (arg_transport
== TRANSPORT_SSH
) {
5987 bus_connect_system_ssh(NULL
, arg_host
, &bus
, &error
);
5988 private_bus
= false;
5990 assert_not_reached("Uh, invalid transport...");
5993 switch (arg_action
) {
5995 case ACTION_SYSTEMCTL
:
5996 r
= systemctl_main(bus
, argc
, argv
, &error
);
6000 case ACTION_POWEROFF
:
6006 case ACTION_RUNLEVEL2
:
6007 case ACTION_RUNLEVEL3
:
6008 case ACTION_RUNLEVEL4
:
6009 case ACTION_RUNLEVEL5
:
6011 case ACTION_EMERGENCY
:
6012 case ACTION_DEFAULT
:
6013 r
= start_with_fallback(bus
);
6018 r
= reload_with_fallback(bus
);
6021 case ACTION_CANCEL_SHUTDOWN
: {
6025 m
= strv_join(arg_wall
, " ");
6027 retval
= EXIT_FAILURE
;
6031 r
= send_shutdownd(arg_when
, SD_SHUTDOWN_NONE
, false, !arg_no_wall
, m
);
6033 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r
));
6038 case ACTION_INVALID
:
6039 case ACTION_RUNLEVEL
:
6041 assert_not_reached("Unknown action");
6044 retval
= r
< 0 ? EXIT_FAILURE
: r
;
6048 dbus_connection_flush(bus
);
6049 dbus_connection_close(bus
);
6050 dbus_connection_unref(bus
);
6055 strv_free(arg_types
);
6056 strv_free(arg_load_states
);
6057 strv_free(arg_properties
);
6060 ask_password_agent_close();
6061 polkit_agent_close();