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>
28 #include <sys/ioctl.h>
32 #include <sys/socket.h>
35 #include <sys/prctl.h>
36 #include <dbus/dbus.h>
38 #include <systemd/sd-daemon.h>
39 #include <systemd/sd-shutdown.h>
45 #include "utmp-wtmp.h"
48 #include "path-util.h"
50 #include "dbus-common.h"
51 #include "cgroup-show.h"
52 #include "cgroup-util.h"
54 #include "path-lookup.h"
55 #include "conf-parser.h"
56 #include "exit-status.h"
57 #include "bus-errors.h"
59 #include "unit-name.h"
61 #include "spawn-ask-password-agent.h"
62 #include "spawn-polkit-agent.h"
64 #include "logs-show.h"
65 #include "path-util.h"
66 #include "socket-util.h"
68 static const char *arg_type
= NULL
;
69 static const char *arg_load_state
= NULL
;
70 static char **arg_property
= NULL
;
71 static bool arg_all
= false;
72 static const char *arg_job_mode
= "replace";
73 static UnitFileScope arg_scope
= UNIT_FILE_SYSTEM
;
74 static bool arg_no_block
= false;
75 static bool arg_no_legend
= false;
76 static bool arg_no_pager
= false;
77 static bool arg_no_wtmp
= false;
78 static bool arg_no_wall
= false;
79 static bool arg_no_reload
= false;
80 static bool arg_dry
= false;
81 static bool arg_quiet
= false;
82 static bool arg_full
= false;
83 static int arg_force
= 0;
84 static bool arg_ask_password
= true;
85 static bool arg_failed
= false;
86 static bool arg_runtime
= false;
87 static char **arg_wall
= NULL
;
88 static const char *arg_kill_who
= NULL
;
89 static int arg_signal
= SIGTERM
;
90 static const char *arg_root
= NULL
;
91 static usec_t arg_when
= 0;
112 ACTION_CANCEL_SHUTDOWN
,
114 } arg_action
= ACTION_SYSTEMCTL
;
120 static enum transport
{
124 } arg_transport
= TRANSPORT_NORMAL
;
125 static const char *arg_host
= NULL
;
126 static bool arg_follow
= false;
127 static unsigned arg_lines
= 10;
128 static OutputMode arg_output
= OUTPUT_SHORT
;
130 static bool private_bus
= false;
132 static int daemon_reload(DBusConnection
*bus
, char **args
);
133 static void halt_now(enum action a
);
135 static bool on_tty(void) {
138 /* Note that this is invoked relatively early, before we start
139 * the pager. That means the value we return reflects whether
140 * we originally were started on a tty, not if we currently
141 * are. But this is intended, since we want colour and so on
142 * when run in our own pager. */
144 if (_unlikely_(t
< 0))
145 t
= isatty(STDOUT_FILENO
) > 0;
150 static void pager_open_if_enabled(void) {
152 /* Cache result before we open the pager */
161 static void ask_password_agent_open_if_enabled(void) {
163 /* Open the password agent as a child process if necessary */
165 if (!arg_ask_password
)
168 if (arg_scope
!= UNIT_FILE_SYSTEM
)
171 ask_password_agent_open();
175 static void polkit_agent_open_if_enabled(void) {
177 /* Open the polkit agent as a child process if necessary */
179 if (!arg_ask_password
)
182 if (arg_scope
!= UNIT_FILE_SYSTEM
)
189 static const char *ansi_highlight_red(bool b
) {
194 return b
? ANSI_HIGHLIGHT_RED_ON
: ANSI_HIGHLIGHT_OFF
;
197 static const char *ansi_highlight_green(bool b
) {
202 return b
? ANSI_HIGHLIGHT_GREEN_ON
: ANSI_HIGHLIGHT_OFF
;
205 static int translate_bus_error_to_exit_status(int r
, const DBusError
*error
) {
208 if (!dbus_error_is_set(error
))
211 if (dbus_error_has_name(error
, DBUS_ERROR_ACCESS_DENIED
) ||
212 dbus_error_has_name(error
, BUS_ERROR_ONLY_BY_DEPENDENCY
) ||
213 dbus_error_has_name(error
, BUS_ERROR_NO_ISOLATION
) ||
214 dbus_error_has_name(error
, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE
))
215 return EXIT_NOPERMISSION
;
217 if (dbus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
))
218 return EXIT_NOTINSTALLED
;
220 if (dbus_error_has_name(error
, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE
) ||
221 dbus_error_has_name(error
, BUS_ERROR_NOT_SUPPORTED
))
222 return EXIT_NOTIMPLEMENTED
;
224 if (dbus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
))
225 return EXIT_NOTCONFIGURED
;
233 static void warn_wall(enum action a
) {
234 static const char *table
[_ACTION_MAX
] = {
235 [ACTION_HALT
] = "The system is going down for system halt NOW!",
236 [ACTION_REBOOT
] = "The system is going down for reboot NOW!",
237 [ACTION_POWEROFF
] = "The system is going down for power-off NOW!",
238 [ACTION_KEXEC
] = "The system is going down for kexec reboot NOW!",
239 [ACTION_RESCUE
] = "The system is going down to rescue mode NOW!",
240 [ACTION_EMERGENCY
] = "The system is going down to emergency mode NOW!",
241 [ACTION_CANCEL_SHUTDOWN
] = "The system shutdown has been cancelled NOW!"
250 p
= strv_join(arg_wall
, " ");
252 log_error("Failed to join strings.");
268 utmp_wall(table
[a
], NULL
);
271 static bool avoid_bus(void) {
273 if (running_in_chroot() > 0)
276 if (sd_booted() <= 0)
279 if (!isempty(arg_root
))
282 if (arg_scope
== UNIT_FILE_GLOBAL
)
290 const char *description
;
291 const char *load_state
;
292 const char *active_state
;
293 const char *sub_state
;
294 const char *following
;
295 const char *unit_path
;
297 const char *job_type
;
298 const char *job_path
;
301 static int compare_unit_info(const void *a
, const void *b
) {
303 const struct unit_info
*u
= a
, *v
= b
;
305 d1
= strrchr(u
->id
, '.');
306 d2
= strrchr(v
->id
, '.');
311 if ((r
= strcasecmp(d1
, d2
)) != 0)
315 return strcasecmp(u
->id
, v
->id
);
318 static bool output_show_unit(const struct unit_info
*u
) {
322 return streq(u
->active_state
, "failed");
324 return (!arg_type
|| ((dot
= strrchr(u
->id
, '.')) &&
325 streq(dot
+1, arg_type
))) &&
326 (!arg_load_state
|| streq(u
->load_state
, arg_load_state
)) &&
327 (arg_all
|| !(streq(u
->active_state
, "inactive")
328 || u
->following
[0]) || u
->job_id
> 0);
331 static void output_units_list(const struct unit_info
*unit_infos
, unsigned c
) {
332 unsigned id_len
, max_id_len
, active_len
, sub_len
, job_len
, desc_len
, n_shown
= 0;
333 const struct unit_info
*u
;
335 max_id_len
= sizeof("UNIT")-1;
336 active_len
= sizeof("ACTIVE")-1;
337 sub_len
= sizeof("SUB")-1;
338 job_len
= sizeof("JOB")-1;
341 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
342 if (!output_show_unit(u
))
345 max_id_len
= MAX(max_id_len
, strlen(u
->id
));
346 active_len
= MAX(active_len
, strlen(u
->active_state
));
347 sub_len
= MAX(sub_len
, strlen(u
->sub_state
));
349 job_len
= MAX(job_len
, strlen(u
->job_type
));
354 id_len
= MIN(max_id_len
, 25);
355 basic_len
= 5 + id_len
+ 6 + active_len
+ sub_len
+ job_len
;
356 if (basic_len
< (unsigned) columns()) {
357 unsigned extra_len
, incr
;
358 extra_len
= columns() - basic_len
;
359 /* Either UNIT already got 25, or is fully satisfied.
360 * Grant up to 25 to DESC now. */
361 incr
= MIN(extra_len
, 25);
364 /* split the remaining space between UNIT and DESC,
365 * but do not give UNIT more than it needs. */
367 incr
= MIN(extra_len
/ 2, max_id_len
- id_len
);
369 desc_len
+= extra_len
- incr
;
375 if (!arg_no_legend
) {
376 printf("%-*s %-6s %-*s %-*s %-*s ", id_len
, "UNIT", "LOAD",
377 active_len
, "ACTIVE", sub_len
, "SUB", job_len
, "JOB");
378 if (!arg_full
&& arg_no_pager
)
379 printf("%.*s\n", desc_len
, "DESCRIPTION");
381 printf("%s\n", "DESCRIPTION");
384 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
386 const char *on_loaded
, *off_loaded
;
387 const char *on_active
, *off_active
;
389 if (!output_show_unit(u
))
394 if (streq(u
->load_state
, "error")) {
395 on_loaded
= ansi_highlight_red(true);
396 off_loaded
= ansi_highlight_red(false);
398 on_loaded
= off_loaded
= "";
400 if (streq(u
->active_state
, "failed")) {
401 on_active
= ansi_highlight_red(true);
402 off_active
= ansi_highlight_red(false);
404 on_active
= off_active
= "";
406 e
= arg_full
? NULL
: ellipsize(u
->id
, id_len
, 33);
408 printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s ",
409 id_len
, e
? e
: u
->id
,
410 on_loaded
, u
->load_state
, off_loaded
,
411 on_active
, active_len
, u
->active_state
,
412 sub_len
, u
->sub_state
, off_active
,
413 job_len
, u
->job_id
? u
->job_type
: "");
414 if (!arg_full
&& arg_no_pager
)
415 printf("%.*s\n", desc_len
, u
->description
);
417 printf("%s\n", u
->description
);
422 if (!arg_no_legend
) {
423 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
424 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
425 "SUB = The low-level unit activation state, values depend on unit type.\n"
426 "JOB = Pending job for the unit.\n");
429 printf("\n%u loaded units listed.\n"
430 "To show all installed unit files use 'systemctl list-unit-files'.\n", n_shown
);
432 printf("\n%u loaded units listed. Pass --all to see loaded but inactive units, too.\n"
433 "To show all installed unit files use 'systemctl list-unit-files'.\n", n_shown
);
437 static int list_units(DBusConnection
*bus
, char **args
) {
438 DBusMessage
*reply
= NULL
;
440 DBusMessageIter iter
, sub
, sub2
;
441 unsigned c
= 0, n_units
= 0;
442 struct unit_info
*unit_infos
= NULL
;
444 pager_open_if_enabled();
446 r
= bus_method_call_with_reply (
448 "org.freedesktop.systemd1",
449 "/org/freedesktop/systemd1",
450 "org.freedesktop.systemd1.Manager",
458 if (!dbus_message_iter_init(reply
, &iter
) ||
459 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_ARRAY
||
460 dbus_message_iter_get_element_type(&iter
) != DBUS_TYPE_STRUCT
) {
461 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
) {
471 if (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_STRUCT
) {
472 log_error("Failed to parse reply.");
480 n_units
= MAX(2*c
, 16);
481 w
= realloc(unit_infos
, sizeof(struct unit_info
) * n_units
);
484 log_error("Failed to allocate unit array.");
494 dbus_message_iter_recurse(&sub
, &sub2
);
496 if (bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &u
->id
, true) < 0 ||
497 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &u
->description
, true) < 0 ||
498 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &u
->load_state
, true) < 0 ||
499 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &u
->active_state
, true) < 0 ||
500 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &u
->sub_state
, true) < 0 ||
501 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &u
->following
, true) < 0 ||
502 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_OBJECT_PATH
, &u
->unit_path
, true) < 0 ||
503 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_UINT32
, &u
->job_id
, true) < 0 ||
504 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &u
->job_type
, true) < 0 ||
505 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_OBJECT_PATH
, &u
->job_path
, false) < 0) {
506 log_error("Failed to parse reply.");
511 dbus_message_iter_next(&sub
);
516 qsort(unit_infos
, c
, sizeof(struct unit_info
), compare_unit_info
);
517 output_units_list(unit_infos
, c
);
522 dbus_message_unref(reply
);
529 static int compare_unit_file_list(const void *a
, const void *b
) {
531 const UnitFileList
*u
= a
, *v
= b
;
533 d1
= strrchr(u
->path
, '.');
534 d2
= strrchr(v
->path
, '.');
539 r
= strcasecmp(d1
, d2
);
544 return strcasecmp(path_get_file_name(u
->path
), path_get_file_name(v
->path
));
547 static bool output_show_unit_file(const UnitFileList
*u
) {
550 return !arg_type
|| ((dot
= strrchr(u
->path
, '.')) && streq(dot
+1, arg_type
));
553 static void output_unit_file_list(const UnitFileList
*units
, unsigned c
) {
554 unsigned max_id_len
, id_cols
, state_cols
, n_shown
= 0;
555 const UnitFileList
*u
;
557 max_id_len
= sizeof("UNIT FILE")-1;
558 state_cols
= sizeof("STATE")-1;
559 for (u
= units
; u
< units
+ c
; u
++) {
560 if (!output_show_unit_file(u
))
563 max_id_len
= MAX(max_id_len
, strlen(path_get_file_name(u
->path
)));
564 state_cols
= MAX(state_cols
, strlen(unit_file_state_to_string(u
->state
)));
569 id_cols
= MIN(max_id_len
, 25);
570 basic_cols
= 1 + id_cols
+ state_cols
;
571 if (basic_cols
< (unsigned) columns())
572 id_cols
+= MIN(columns() - basic_cols
, max_id_len
- id_cols
);
574 id_cols
= max_id_len
;
577 printf("%-*s %-*s\n", id_cols
, "UNIT FILE", state_cols
, "STATE");
579 for (u
= units
; u
< units
+ c
; u
++) {
581 const char *on
, *off
;
584 if (!output_show_unit_file(u
))
589 if (u
->state
== UNIT_FILE_MASKED
||
590 u
->state
== UNIT_FILE_MASKED_RUNTIME
||
591 u
->state
== UNIT_FILE_DISABLED
||
592 u
->state
== UNIT_FILE_INVALID
) {
593 on
= ansi_highlight_red(true);
594 off
= ansi_highlight_red(false);
595 } else if (u
->state
== UNIT_FILE_ENABLED
) {
596 on
= ansi_highlight_green(true);
597 off
= ansi_highlight_green(false);
601 id
= path_get_file_name(u
->path
);
603 e
= arg_full
? NULL
: ellipsize(id
, id_cols
, 33);
605 printf("%-*s %s%-*s%s\n",
607 on
, state_cols
, unit_file_state_to_string(u
->state
), off
);
613 printf("\n%u unit files listed.\n", n_shown
);
616 static int list_unit_files(DBusConnection
*bus
, char **args
) {
617 DBusMessage
*reply
= NULL
;
619 DBusMessageIter iter
, sub
, sub2
;
620 unsigned c
= 0, n_units
= 0;
621 UnitFileList
*units
= NULL
;
623 pager_open_if_enabled();
630 h
= hashmap_new(string_hash_func
, string_compare_func
);
634 r
= unit_file_get_list(arg_scope
, arg_root
, h
);
636 unit_file_list_free(h
);
637 log_error("Failed to get unit file list: %s", strerror(-r
));
641 n_units
= hashmap_size(h
);
642 units
= new(UnitFileList
, n_units
);
644 unit_file_list_free(h
);
648 HASHMAP_FOREACH(u
, h
, i
) {
649 memcpy(units
+ c
++, u
, sizeof(UnitFileList
));
655 r
= bus_method_call_with_reply (
657 "org.freedesktop.systemd1",
658 "/org/freedesktop/systemd1",
659 "org.freedesktop.systemd1.Manager",
667 if (!dbus_message_iter_init(reply
, &iter
) ||
668 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_ARRAY
||
669 dbus_message_iter_get_element_type(&iter
) != DBUS_TYPE_STRUCT
) {
670 log_error("Failed to parse reply.");
675 dbus_message_iter_recurse(&iter
, &sub
);
677 while (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_INVALID
) {
681 if (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_STRUCT
) {
682 log_error("Failed to parse reply.");
690 n_units
= MAX(2*c
, 16);
691 w
= realloc(units
, sizeof(struct UnitFileList
) * n_units
);
694 log_error("Failed to allocate unit array.");
704 dbus_message_iter_recurse(&sub
, &sub2
);
706 if (bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &u
->path
, true) < 0 ||
707 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &state
, false) < 0) {
708 log_error("Failed to parse reply.");
713 u
->state
= unit_file_state_from_string(state
);
715 dbus_message_iter_next(&sub
);
721 qsort(units
, c
, sizeof(UnitFileList
), compare_unit_file_list
);
722 output_unit_file_list(units
, c
);
729 dbus_message_unref(reply
);
736 static int dot_one_property(const char *name
, const char *prop
, DBusMessageIter
*iter
) {
737 static const char * const colors
[] = {
738 "Requires", "[color=\"black\"]",
739 "RequiresOverridable", "[color=\"black\"]",
740 "Requisite", "[color=\"darkblue\"]",
741 "RequisiteOverridable", "[color=\"darkblue\"]",
742 "Wants", "[color=\"grey66\"]",
743 "Conflicts", "[color=\"red\"]",
744 "ConflictedBy", "[color=\"red\"]",
745 "After", "[color=\"green\"]"
748 const char *c
= NULL
;
755 for (i
= 0; i
< ELEMENTSOF(colors
); i
+= 2)
756 if (streq(colors
[i
], prop
)) {
764 if (arg_dot
!= DOT_ALL
)
765 if ((arg_dot
== DOT_ORDER
) != streq(prop
, "After"))
768 switch (dbus_message_iter_get_arg_type(iter
)) {
770 case DBUS_TYPE_ARRAY
:
772 if (dbus_message_iter_get_element_type(iter
) == DBUS_TYPE_STRING
) {
775 dbus_message_iter_recurse(iter
, &sub
);
777 while (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_INVALID
) {
780 assert(dbus_message_iter_get_arg_type(&sub
) == DBUS_TYPE_STRING
);
781 dbus_message_iter_get_basic(&sub
, &s
);
782 printf("\t\"%s\"->\"%s\" %s;\n", name
, s
, c
);
784 dbus_message_iter_next(&sub
);
794 static int dot_one(DBusConnection
*bus
, const char *name
, const char *path
) {
795 DBusMessage
*reply
= NULL
;
796 const char *interface
= "org.freedesktop.systemd1.Unit";
798 DBusMessageIter iter
, sub
, sub2
, sub3
;
802 r
= bus_method_call_with_reply (
804 "org.freedesktop.systemd1",
806 "org.freedesktop.DBus.Properties",
810 DBUS_TYPE_STRING
, &interface
,
815 if (!dbus_message_iter_init(reply
, &iter
) ||
816 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_ARRAY
||
817 dbus_message_iter_get_element_type(&iter
) != DBUS_TYPE_DICT_ENTRY
) {
818 log_error("Failed to parse reply.");
823 dbus_message_iter_recurse(&iter
, &sub
);
825 while (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_INVALID
) {
828 if (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_DICT_ENTRY
) {
829 log_error("Failed to parse reply.");
834 dbus_message_iter_recurse(&sub
, &sub2
);
836 if (bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &prop
, true) < 0) {
837 log_error("Failed to parse reply.");
842 if (dbus_message_iter_get_arg_type(&sub2
) != DBUS_TYPE_VARIANT
) {
843 log_error("Failed to parse reply.");
848 dbus_message_iter_recurse(&sub2
, &sub3
);
850 if (dot_one_property(name
, prop
, &sub3
)) {
851 log_error("Failed to parse reply.");
856 dbus_message_iter_next(&sub
);
861 dbus_message_unref(reply
);
866 static int dot(DBusConnection
*bus
, char **args
) {
867 DBusMessage
*reply
= NULL
;
869 DBusMessageIter iter
, sub
, sub2
;
871 r
= bus_method_call_with_reply (
873 "org.freedesktop.systemd1",
874 "/org/freedesktop/systemd1",
875 "org.freedesktop.systemd1.Manager",
883 if (!dbus_message_iter_init(reply
, &iter
) ||
884 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_ARRAY
||
885 dbus_message_iter_get_element_type(&iter
) != DBUS_TYPE_STRUCT
) {
886 log_error("Failed to parse reply.");
891 printf("digraph systemd {\n");
893 dbus_message_iter_recurse(&iter
, &sub
);
894 while (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_INVALID
) {
895 const char *id
, *description
, *load_state
, *active_state
, *sub_state
, *following
, *unit_path
;
897 if (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_STRUCT
) {
898 log_error("Failed to parse reply.");
903 dbus_message_iter_recurse(&sub
, &sub2
);
905 if (bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &id
, true) < 0 ||
906 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &description
, true) < 0 ||
907 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &load_state
, true) < 0 ||
908 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &active_state
, true) < 0 ||
909 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &sub_state
, true) < 0 ||
910 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &following
, true) < 0 ||
911 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_OBJECT_PATH
, &unit_path
, true) < 0) {
912 log_error("Failed to parse reply.");
917 if ((r
= dot_one(bus
, id
, unit_path
)) < 0)
920 /* printf("\t\"%s\";\n", id); */
921 dbus_message_iter_next(&sub
);
926 log_info(" Color legend: black = Requires\n"
927 " dark blue = Requisite\n"
928 " dark grey = Wants\n"
933 log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
934 "-- Try a shell pipeline like 'systemctl dot | dot -Tsvg > systemd.svg'!\n");
940 dbus_message_unref(reply
);
945 static int list_jobs(DBusConnection
*bus
, char **args
) {
946 DBusMessage
*reply
= NULL
;
948 DBusMessageIter iter
, sub
, sub2
;
951 pager_open_if_enabled();
953 r
= bus_method_call_with_reply (
955 "org.freedesktop.systemd1",
956 "/org/freedesktop/systemd1",
957 "org.freedesktop.systemd1.Manager",
965 if (!dbus_message_iter_init(reply
, &iter
) ||
966 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_ARRAY
||
967 dbus_message_iter_get_element_type(&iter
) != DBUS_TYPE_STRUCT
) {
968 log_error("Failed to parse reply.");
973 dbus_message_iter_recurse(&iter
, &sub
);
976 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
978 while (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_INVALID
) {
979 const char *name
, *type
, *state
, *job_path
, *unit_path
;
983 if (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_STRUCT
) {
984 log_error("Failed to parse reply.");
989 dbus_message_iter_recurse(&sub
, &sub2
);
991 if (bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_UINT32
, &id
, true) < 0 ||
992 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &name
, true) < 0 ||
993 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &type
, true) < 0 ||
994 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &state
, true) < 0 ||
995 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_OBJECT_PATH
, &job_path
, true) < 0 ||
996 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_OBJECT_PATH
, &unit_path
, false) < 0) {
997 log_error("Failed to parse reply.");
1002 e
= arg_full
? NULL
: ellipsize(name
, 25, 33);
1003 printf("%4u %-25s %-15s %-7s\n", id
, e
? e
: name
, type
, state
);
1008 dbus_message_iter_next(&sub
);
1012 printf("\n%u jobs listed.\n", k
);
1018 dbus_message_unref(reply
);
1023 static int load_unit(DBusConnection
*bus
, char **args
) {
1029 STRV_FOREACH(name
, args
+1) {
1030 n
= unit_name_mangle(*name
);
1031 r
= bus_method_call_with_reply (
1033 "org.freedesktop.systemd1",
1034 "/org/freedesktop/systemd1",
1035 "org.freedesktop.systemd1.Manager",
1039 DBUS_TYPE_STRING
, n
? &n
: name
,
1050 static int cancel_job(DBusConnection
*bus
, char **args
) {
1051 DBusMessage
*reply
= NULL
;
1057 if (strv_length(args
) <= 1)
1058 return daemon_reload(bus
, args
);
1060 STRV_FOREACH(name
, args
+1) {
1064 r
= safe_atou(*name
, &id
);
1066 log_error("Failed to parse job id: %s", strerror(-r
));
1069 assert_cc(sizeof(uint32_t) == sizeof(id
));
1071 r
= bus_method_call_with_reply (
1073 "org.freedesktop.systemd1",
1074 "/org/freedesktop/systemd1",
1075 "org.freedesktop.systemd1.Manager",
1079 DBUS_TYPE_UINT32
, &id
,
1084 if (!dbus_message_get_args(reply
, NULL
,
1085 DBUS_TYPE_OBJECT_PATH
, &path
,
1086 DBUS_TYPE_INVALID
)) {
1087 log_error("Failed to parse reply");
1088 dbus_message_unref(reply
);
1092 dbus_message_unref(reply
);
1094 r
= bus_method_call_with_reply (
1096 "org.freedesktop.systemd1",
1098 "org.freedesktop.systemd1.Job",
1111 static bool need_daemon_reload(DBusConnection
*bus
, const char *unit
) {
1112 DBusMessage
*reply
= NULL
;
1113 dbus_bool_t b
= FALSE
;
1114 DBusMessageIter iter
, sub
;
1116 *interface
= "org.freedesktop.systemd1.Unit",
1117 *property
= "NeedDaemonReload",
1122 /* We ignore all errors here, since this is used to show a warning only */
1124 n
= unit_name_mangle(unit
);
1125 r
= bus_method_call_with_reply (
1127 "org.freedesktop.systemd1",
1128 "/org/freedesktop/systemd1",
1129 "org.freedesktop.systemd1.Manager",
1133 DBUS_TYPE_STRING
, n
? (const char**) &n
: &unit
,
1139 if (!dbus_message_get_args(reply
, NULL
,
1140 DBUS_TYPE_OBJECT_PATH
, &path
,
1144 dbus_message_unref(reply
);
1145 r
= bus_method_call_with_reply (
1147 "org.freedesktop.systemd1",
1149 "org.freedesktop.DBus.Properties",
1153 DBUS_TYPE_STRING
, &interface
,
1154 DBUS_TYPE_STRING
, &property
,
1159 if (!dbus_message_iter_init(reply
, &iter
) ||
1160 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_VARIANT
)
1163 dbus_message_iter_recurse(&iter
, &sub
);
1165 if (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_BOOLEAN
)
1168 dbus_message_iter_get_basic(&sub
, &b
);
1172 dbus_message_unref(reply
);
1177 typedef struct WaitData
{
1184 static DBusHandlerResult
wait_filter(DBusConnection
*connection
, DBusMessage
*message
, void *data
) {
1192 dbus_error_init(&error
);
1194 log_debug("Got D-Bus request: %s.%s() on %s",
1195 dbus_message_get_interface(message
),
1196 dbus_message_get_member(message
),
1197 dbus_message_get_path(message
));
1199 if (dbus_message_is_signal(message
, DBUS_INTERFACE_LOCAL
, "Disconnected")) {
1200 log_error("Warning! D-Bus connection terminated.");
1201 dbus_connection_close(connection
);
1203 } else if (dbus_message_is_signal(message
, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1205 const char *path
, *result
, *unit
;
1206 dbus_bool_t success
= true;
1208 if (dbus_message_get_args(message
, &error
,
1209 DBUS_TYPE_UINT32
, &id
,
1210 DBUS_TYPE_OBJECT_PATH
, &path
,
1211 DBUS_TYPE_STRING
, &unit
,
1212 DBUS_TYPE_STRING
, &result
,
1213 DBUS_TYPE_INVALID
)) {
1216 p
= set_remove(d
->set
, (char*) path
);
1219 if (!isempty(result
))
1220 d
->result
= strdup(result
);
1223 d
->name
= strdup(unit
);
1228 dbus_error_free(&error
);
1229 if (dbus_message_get_args(message
, &error
,
1230 DBUS_TYPE_UINT32
, &id
,
1231 DBUS_TYPE_OBJECT_PATH
, &path
,
1232 DBUS_TYPE_STRING
, &result
,
1233 DBUS_TYPE_INVALID
)) {
1236 /* Compatibility with older systemd versions <
1237 * 183 during upgrades. This should be dropped
1239 p
= set_remove(d
->set
, (char*) path
);
1243 d
->result
= strdup(result
);
1248 dbus_error_free(&error
);
1249 if (dbus_message_get_args(message
, &error
,
1250 DBUS_TYPE_UINT32
, &id
,
1251 DBUS_TYPE_OBJECT_PATH
, &path
,
1252 DBUS_TYPE_BOOLEAN
, &success
,
1253 DBUS_TYPE_INVALID
)) {
1256 /* Compatibility with older systemd versions <
1257 * 19 during upgrades. This should be dropped
1260 p
= set_remove(d
->set
, (char*) path
);
1264 d
->result
= strdup("failed");
1270 log_error("Failed to parse message: %s", bus_error_message(&error
));
1274 dbus_error_free(&error
);
1275 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED
;
1278 static int enable_wait_for_jobs(DBusConnection
*bus
) {
1286 dbus_error_init(&error
);
1287 dbus_bus_add_match(bus
,
1289 "sender='org.freedesktop.systemd1',"
1290 "interface='org.freedesktop.systemd1.Manager',"
1291 "member='JobRemoved',"
1292 "path='/org/freedesktop/systemd1'",
1295 if (dbus_error_is_set(&error
)) {
1296 log_error("Failed to add match: %s", bus_error_message(&error
));
1297 dbus_error_free(&error
);
1301 /* This is slightly dirty, since we don't undo the match registrations. */
1305 static int wait_for_jobs(DBusConnection
*bus
, Set
*s
) {
1315 if (!dbus_connection_add_filter(bus
, wait_filter
, &d
, NULL
))
1318 while (!set_isempty(s
)) {
1320 if (!dbus_connection_read_write_dispatch(bus
, -1)) {
1321 log_error("Disconnected from bus.");
1322 return -ECONNREFUSED
;
1325 if (!arg_quiet
&& d
.result
) {
1326 if (streq(d
.result
, "timeout"))
1327 log_error("Job for %s timed out.", strna(d
.name
));
1328 else if (streq(d
.result
, "canceled"))
1329 log_error("Job for %s canceled.", strna(d
.name
));
1330 else if (streq(d
.result
, "dependency"))
1331 log_error("A dependency job for %s failed. See 'journalctl' for details.", strna(d
.name
));
1332 else if (!streq(d
.result
, "done") && !streq(d
.result
, "skipped"))
1333 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl' for details.", strna(d
.name
), strna(d
.name
));
1336 if (streq_ptr(d
.result
, "timeout"))
1338 else if (streq_ptr(d
.result
, "canceled"))
1340 else if (!streq_ptr(d
.result
, "done") && !streq_ptr(d
.result
, "skipped"))
1350 /* This is slightly dirty, since we don't undo the filter registration. */
1354 static int check_one_unit(DBusConnection
*bus
, char *name
, bool quiet
) {
1355 DBusMessage
*reply
= NULL
;
1356 DBusMessageIter iter
, sub
;
1358 *interface
= "org.freedesktop.systemd1.Unit",
1359 *property
= "ActiveState";
1360 const char *path
= NULL
;
1367 n
= unit_name_mangle(name
);
1368 r
= bus_method_call_with_reply (
1370 "org.freedesktop.systemd1",
1371 "/org/freedesktop/systemd1",
1372 "org.freedesktop.systemd1.Manager",
1376 DBUS_TYPE_STRING
, n
? &n
: &name
,
1380 if ((r
!= -ENOMEM
) && (!quiet
))
1385 if (!dbus_message_get_args(reply
, NULL
,
1386 DBUS_TYPE_OBJECT_PATH
, &path
,
1387 DBUS_TYPE_INVALID
)) {
1388 log_error("Failed to parse reply.");
1393 dbus_message_unref(reply
);
1394 r
= bus_method_call_with_reply (
1396 "org.freedesktop.systemd1",
1398 "org.freedesktop.DBus.Properties",
1402 DBUS_TYPE_STRING
, &interface
,
1403 DBUS_TYPE_STRING
, &property
,
1408 if (!dbus_message_iter_init(reply
, &iter
) ||
1409 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_VARIANT
) {
1410 log_error("Failed to parse reply.");
1415 dbus_message_iter_recurse(&iter
, &sub
);
1417 if (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_STRING
) {
1418 log_error("Failed to parse reply.");
1423 dbus_message_iter_get_basic(&sub
, &state
);
1428 if (streq(state
, "active") || streq(state
, "reloading"))
1431 r
= 3; /* According to LSB: "program is not running" */
1435 dbus_message_unref(reply
);
1440 static void check_triggering_units(
1441 DBusConnection
*bus
,
1442 const char *unit_name
) {
1444 DBusMessage
*reply
= NULL
;
1445 DBusMessageIter iter
, sub
;
1446 char *service_trigger
= NULL
;
1447 const char *interface
= "org.freedesktop.systemd1.Unit",
1448 *triggered_by_property
= "TriggeredBy";
1450 char *unit_path
= NULL
, *n
= NULL
;
1451 bool print_warning_label
= true;
1454 n
= unit_name_mangle(unit_name
);
1455 unit_path
= unit_dbus_path_from_name(n
? n
: unit_name
);
1458 log_error("Could not allocate dbus path.");
1462 r
= bus_method_call_with_reply (
1464 "org.freedesktop.systemd1",
1466 "org.freedesktop.DBus.Properties",
1470 DBUS_TYPE_STRING
, &interface
,
1471 DBUS_TYPE_STRING
, &triggered_by_property
,
1476 if (!dbus_message_iter_init(reply
, &iter
) ||
1477 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_VARIANT
) {
1478 log_error("Failed to parse reply.");
1483 dbus_message_iter_recurse(&iter
, &sub
);
1484 dbus_message_iter_recurse(&sub
, &iter
);
1487 while (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_INVALID
) {
1489 if (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_STRING
) {
1490 log_error("Failed to parse reply.");
1494 dbus_message_iter_get_basic(&sub
, &service_trigger
);
1496 r
= check_one_unit(bus
, service_trigger
, true);
1500 if (print_warning_label
) {
1501 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name
);
1502 print_warning_label
= false;
1504 log_warning(" %s", service_trigger
);
1507 dbus_message_iter_next(&sub
);
1511 dbus_message_unref(reply
);
1516 static int start_unit_one(
1517 DBusConnection
*bus
,
1524 DBusMessage
*reply
= NULL
;
1527 _cleanup_free_
char *n
, *p
= NULL
;
1534 n
= unit_name_mangle(name
);
1538 r
= bus_method_call_with_reply(
1540 "org.freedesktop.systemd1",
1541 "/org/freedesktop/systemd1",
1542 "org.freedesktop.systemd1.Manager",
1546 DBUS_TYPE_STRING
, &n
,
1547 DBUS_TYPE_STRING
, &mode
,
1550 if (r
== -ENOENT
&& arg_action
!= ACTION_SYSTEMCTL
)
1551 /* There's always a fallback possible for
1552 * legacy actions. */
1555 log_error("Failed to issue method call: %s", bus_error_message(error
));
1560 if (!dbus_message_get_args(reply
, error
,
1561 DBUS_TYPE_OBJECT_PATH
, &path
,
1562 DBUS_TYPE_INVALID
)) {
1563 log_error("Failed to parse reply: %s", bus_error_message(error
));
1568 if (need_daemon_reload(bus
, n
))
1569 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1570 n
, arg_scope
== UNIT_FILE_SYSTEM
? "--system" : "--user");
1581 log_error("Failed to add path to set.");
1588 /* When stopping a unit warn if it can still be triggered by
1589 * another active unit (socket, path, timer) */
1590 if (!arg_quiet
&& streq(method
, "StopUnit"))
1591 check_triggering_units(bus
, name
);
1597 dbus_message_unref(reply
);
1602 static enum action
verb_to_action(const char *verb
) {
1603 if (streq(verb
, "halt"))
1605 else if (streq(verb
, "poweroff"))
1606 return ACTION_POWEROFF
;
1607 else if (streq(verb
, "reboot"))
1608 return ACTION_REBOOT
;
1609 else if (streq(verb
, "kexec"))
1610 return ACTION_KEXEC
;
1611 else if (streq(verb
, "rescue"))
1612 return ACTION_RESCUE
;
1613 else if (streq(verb
, "emergency"))
1614 return ACTION_EMERGENCY
;
1615 else if (streq(verb
, "default"))
1616 return ACTION_DEFAULT
;
1617 else if (streq(verb
, "exit"))
1619 else if (streq(verb
, "suspend"))
1620 return ACTION_SUSPEND
;
1621 else if (streq(verb
, "hibernate"))
1622 return ACTION_HIBERNATE
;
1624 return ACTION_INVALID
;
1627 static int start_unit(DBusConnection
*bus
, char **args
) {
1629 static const char * const table
[_ACTION_MAX
] = {
1630 [ACTION_HALT
] = SPECIAL_HALT_TARGET
,
1631 [ACTION_POWEROFF
] = SPECIAL_POWEROFF_TARGET
,
1632 [ACTION_REBOOT
] = SPECIAL_REBOOT_TARGET
,
1633 [ACTION_KEXEC
] = SPECIAL_KEXEC_TARGET
,
1634 [ACTION_RUNLEVEL2
] = SPECIAL_RUNLEVEL2_TARGET
,
1635 [ACTION_RUNLEVEL3
] = SPECIAL_RUNLEVEL3_TARGET
,
1636 [ACTION_RUNLEVEL4
] = SPECIAL_RUNLEVEL4_TARGET
,
1637 [ACTION_RUNLEVEL5
] = SPECIAL_RUNLEVEL5_TARGET
,
1638 [ACTION_RESCUE
] = SPECIAL_RESCUE_TARGET
,
1639 [ACTION_EMERGENCY
] = SPECIAL_EMERGENCY_TARGET
,
1640 [ACTION_DEFAULT
] = SPECIAL_DEFAULT_TARGET
,
1641 [ACTION_EXIT
] = SPECIAL_EXIT_TARGET
,
1642 [ACTION_SUSPEND
] = SPECIAL_SUSPEND_TARGET
,
1643 [ACTION_HIBERNATE
] = SPECIAL_HIBERNATE_TARGET
1647 const char *method
, *mode
, *one_name
;
1652 dbus_error_init(&error
);
1656 ask_password_agent_open_if_enabled();
1658 if (arg_action
== ACTION_SYSTEMCTL
) {
1660 streq(args
[0], "stop") ||
1661 streq(args
[0], "condstop") ? "StopUnit" :
1662 streq(args
[0], "reload") ? "ReloadUnit" :
1663 streq(args
[0], "restart") ? "RestartUnit" :
1665 streq(args
[0], "try-restart") ||
1666 streq(args
[0], "condrestart") ? "TryRestartUnit" :
1668 streq(args
[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1670 streq(args
[0], "reload-or-try-restart") ||
1671 streq(args
[0], "condreload") ||
1673 streq(args
[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1677 (streq(args
[0], "isolate") ||
1678 streq(args
[0], "rescue") ||
1679 streq(args
[0], "emergency")) ? "isolate" : arg_job_mode
;
1681 one_name
= table
[verb_to_action(args
[0])];
1684 assert(arg_action
< ELEMENTSOF(table
));
1685 assert(table
[arg_action
]);
1687 method
= "StartUnit";
1689 mode
= (arg_action
== ACTION_EMERGENCY
||
1690 arg_action
== ACTION_RESCUE
||
1691 arg_action
== ACTION_RUNLEVEL2
||
1692 arg_action
== ACTION_RUNLEVEL3
||
1693 arg_action
== ACTION_RUNLEVEL4
||
1694 arg_action
== ACTION_RUNLEVEL5
) ? "isolate" : "replace";
1696 one_name
= table
[arg_action
];
1699 if (!arg_no_block
) {
1700 ret
= enable_wait_for_jobs(bus
);
1702 log_error("Could not watch jobs: %s", strerror(-ret
));
1706 s
= set_new(string_hash_func
, string_compare_func
);
1714 ret
= start_unit_one(bus
, method
, one_name
, mode
, &error
, s
);
1716 ret
= translate_bus_error_to_exit_status(ret
, &error
);
1718 STRV_FOREACH(name
, args
+1) {
1719 r
= start_unit_one(bus
, method
, *name
, mode
, &error
, s
);
1721 ret
= translate_bus_error_to_exit_status(r
, &error
);
1722 dbus_error_free(&error
);
1727 if (!arg_no_block
) {
1728 r
= wait_for_jobs(bus
, s
);
1737 dbus_error_free(&error
);
1742 /* Ask systemd-logind, which might grant access to unprivileged users
1743 * through PolicyKit */
1744 static int reboot_with_logind(DBusConnection
*bus
, enum action a
) {
1747 dbus_bool_t interactive
= true;
1749 polkit_agent_open_if_enabled();
1757 case ACTION_POWEROFF
:
1758 method
= "PowerOff";
1761 case ACTION_SUSPEND
:
1765 case ACTION_HIBERNATE
:
1766 method
= "Hibernate";
1773 return bus_method_call_with_reply (
1775 "org.freedesktop.login1",
1776 "/org/freedesktop/login1",
1777 "org.freedesktop.login1.Manager",
1781 DBUS_TYPE_BOOLEAN
, &interactive
,
1788 static int start_special(DBusConnection
*bus
, char **args
) {
1794 a
= verb_to_action(args
[0]);
1796 if (arg_force
>= 2 && geteuid() != 0) {
1797 log_error("Must be root.");
1801 if (arg_force
>= 2 &&
1802 (a
== ACTION_HALT
||
1803 a
== ACTION_POWEROFF
||
1804 a
== ACTION_REBOOT
))
1807 if (arg_force
>= 1 &&
1808 (a
== ACTION_HALT
||
1809 a
== ACTION_POWEROFF
||
1810 a
== ACTION_REBOOT
||
1811 a
== ACTION_KEXEC
||
1813 return daemon_reload(bus
, args
);
1815 /* first try logind, to allow authentication with polkit */
1816 if (geteuid() != 0 &&
1817 (a
== ACTION_POWEROFF
||
1818 a
== ACTION_REBOOT
||
1819 a
== ACTION_SUSPEND
||
1820 a
== ACTION_HIBERNATE
)) {
1821 r
= reboot_with_logind(bus
, a
);
1826 r
= start_unit(bus
, args
);
1833 static int check_unit(DBusConnection
*bus
, char **args
) {
1835 int r
= 3; /* According to LSB: "program is not running" */
1840 STRV_FOREACH(name
, args
+1) {
1841 int state
= check_one_unit(bus
, *name
, arg_quiet
);
1851 static int kill_unit(DBusConnection
*bus
, char **args
) {
1858 arg_kill_who
= "all";
1860 STRV_FOREACH(name
, args
+1) {
1861 n
= unit_name_mangle(*name
);
1862 r
= bus_method_call_with_reply (
1864 "org.freedesktop.systemd1",
1865 "/org/freedesktop/systemd1",
1866 "org.freedesktop.systemd1.Manager",
1870 DBUS_TYPE_STRING
, n
? &n
: name
,
1871 DBUS_TYPE_STRING
, &arg_kill_who
,
1872 DBUS_TYPE_INT32
, &arg_signal
,
1881 typedef struct ExecStatusInfo
{
1889 usec_t start_timestamp
;
1890 usec_t exit_timestamp
;
1895 LIST_FIELDS(struct ExecStatusInfo
, exec
);
1898 static void exec_status_info_free(ExecStatusInfo
*i
) {
1907 static int exec_status_info_deserialize(DBusMessageIter
*sub
, ExecStatusInfo
*i
) {
1908 uint64_t start_timestamp
, exit_timestamp
, start_timestamp_monotonic
, exit_timestamp_monotonic
;
1909 DBusMessageIter sub2
, sub3
;
1913 int32_t code
, status
;
1919 if (dbus_message_iter_get_arg_type(sub
) != DBUS_TYPE_STRUCT
)
1922 dbus_message_iter_recurse(sub
, &sub2
);
1924 if (bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &path
, true) < 0)
1927 if (!(i
->path
= strdup(path
)))
1930 if (dbus_message_iter_get_arg_type(&sub2
) != DBUS_TYPE_ARRAY
||
1931 dbus_message_iter_get_element_type(&sub2
) != DBUS_TYPE_STRING
)
1935 dbus_message_iter_recurse(&sub2
, &sub3
);
1936 while (dbus_message_iter_get_arg_type(&sub3
) != DBUS_TYPE_INVALID
) {
1937 assert(dbus_message_iter_get_arg_type(&sub3
) == DBUS_TYPE_STRING
);
1938 dbus_message_iter_next(&sub3
);
1943 if (!(i
->argv
= new0(char*, n
+1)))
1947 dbus_message_iter_recurse(&sub2
, &sub3
);
1948 while (dbus_message_iter_get_arg_type(&sub3
) != DBUS_TYPE_INVALID
) {
1951 assert(dbus_message_iter_get_arg_type(&sub3
) == DBUS_TYPE_STRING
);
1952 dbus_message_iter_get_basic(&sub3
, &s
);
1953 dbus_message_iter_next(&sub3
);
1955 if (!(i
->argv
[n
++] = strdup(s
)))
1959 if (!dbus_message_iter_next(&sub2
) ||
1960 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_BOOLEAN
, &ignore
, true) < 0 ||
1961 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_UINT64
, &start_timestamp
, true) < 0 ||
1962 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_UINT64
, &start_timestamp_monotonic
, true) < 0 ||
1963 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_UINT64
, &exit_timestamp
, true) < 0 ||
1964 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_UINT64
, &exit_timestamp_monotonic
, true) < 0 ||
1965 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_UINT32
, &pid
, true) < 0 ||
1966 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_INT32
, &code
, true) < 0 ||
1967 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_INT32
, &status
, false) < 0)
1971 i
->start_timestamp
= (usec_t
) start_timestamp
;
1972 i
->exit_timestamp
= (usec_t
) exit_timestamp
;
1973 i
->pid
= (pid_t
) pid
;
1980 typedef struct UnitStatusInfo
{
1982 const char *load_state
;
1983 const char *active_state
;
1984 const char *sub_state
;
1985 const char *unit_file_state
;
1987 const char *description
;
1988 const char *following
;
1990 char **documentation
;
1992 const char *fragment_path
;
1993 const char *source_path
;
1994 const char *default_control_group
;
1996 const char *load_error
;
1999 usec_t inactive_exit_timestamp
;
2000 usec_t inactive_exit_timestamp_monotonic
;
2001 usec_t active_enter_timestamp
;
2002 usec_t active_exit_timestamp
;
2003 usec_t inactive_enter_timestamp
;
2005 bool need_daemon_reload
;
2010 const char *status_text
;
2013 usec_t start_timestamp
;
2014 usec_t exit_timestamp
;
2016 int exit_code
, exit_status
;
2018 usec_t condition_timestamp
;
2019 bool condition_result
;
2022 unsigned n_accepted
;
2023 unsigned n_connections
;
2027 const char *sysfs_path
;
2029 /* Mount, Automount */
2035 LIST_HEAD(ExecStatusInfo
, exec
);
2038 static void print_status_info(UnitStatusInfo
*i
) {
2040 const char *on
, *off
, *ss
;
2042 char since1
[FORMAT_TIMESTAMP_PRETTY_MAX
], *s1
;
2043 char since2
[FORMAT_TIMESTAMP_MAX
], *s2
;
2048 /* This shows pretty information about a unit. See
2049 * print_property() for a low-level property printer */
2051 printf("%s", strna(i
->id
));
2053 if (i
->description
&& !streq_ptr(i
->id
, i
->description
))
2054 printf(" - %s", i
->description
);
2059 printf("\t Follow: unit currently follows state of %s\n", i
->following
);
2061 if (streq_ptr(i
->load_state
, "error")) {
2062 on
= ansi_highlight_red(true);
2063 off
= ansi_highlight_red(false);
2067 path
= i
->source_path
? i
->source_path
: i
->fragment_path
;
2070 printf("\t Loaded: %s%s%s (Reason: %s)\n", on
, strna(i
->load_state
), off
, i
->load_error
);
2071 else if (path
&& i
->unit_file_state
)
2072 printf("\t Loaded: %s%s%s (%s; %s)\n", on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
);
2074 printf("\t Loaded: %s%s%s (%s)\n", on
, strna(i
->load_state
), off
, path
);
2076 printf("\t Loaded: %s%s%s\n", on
, strna(i
->load_state
), off
);
2078 ss
= streq_ptr(i
->active_state
, i
->sub_state
) ? NULL
: i
->sub_state
;
2080 if (streq_ptr(i
->active_state
, "failed")) {
2081 on
= ansi_highlight_red(true);
2082 off
= ansi_highlight_red(false);
2083 } else if (streq_ptr(i
->active_state
, "active") || streq_ptr(i
->active_state
, "reloading")) {
2084 on
= ansi_highlight_green(true);
2085 off
= ansi_highlight_green(false);
2090 printf("\t Active: %s%s (%s)%s",
2092 strna(i
->active_state
),
2096 printf("\t Active: %s%s%s",
2098 strna(i
->active_state
),
2101 if (!isempty(i
->result
) && !streq(i
->result
, "success"))
2102 printf(" (Result: %s)", i
->result
);
2104 timestamp
= (streq_ptr(i
->active_state
, "active") ||
2105 streq_ptr(i
->active_state
, "reloading")) ? i
->active_enter_timestamp
:
2106 (streq_ptr(i
->active_state
, "inactive") ||
2107 streq_ptr(i
->active_state
, "failed")) ? i
->inactive_enter_timestamp
:
2108 streq_ptr(i
->active_state
, "activating") ? i
->inactive_exit_timestamp
:
2109 i
->active_exit_timestamp
;
2111 s1
= format_timestamp_pretty(since1
, sizeof(since1
), timestamp
);
2112 s2
= format_timestamp(since2
, sizeof(since2
), timestamp
);
2115 printf(" since %s; %s\n", s2
, s1
);
2117 printf(" since %s\n", s2
);
2121 if (!i
->condition_result
&& i
->condition_timestamp
> 0) {
2122 s1
= format_timestamp_pretty(since1
, sizeof(since1
), i
->condition_timestamp
);
2123 s2
= format_timestamp(since2
, sizeof(since2
), i
->condition_timestamp
);
2126 printf("\t start condition failed at %s; %s\n", s2
, s1
);
2128 printf("\t start condition failed at %s\n", s2
);
2132 printf("\t Device: %s\n", i
->sysfs_path
);
2134 printf("\t Where: %s\n", i
->where
);
2136 printf("\t What: %s\n", i
->what
);
2138 if (!strv_isempty(i
->documentation
)) {
2142 STRV_FOREACH(t
, i
->documentation
) {
2144 printf("\t Docs: %s\n", *t
);
2147 printf("\t %s\n", *t
);
2152 printf("\tAccepted: %u; Connected: %u\n", i
->n_accepted
, i
->n_connections
);
2154 LIST_FOREACH(exec
, p
, i
->exec
) {
2158 /* Only show exited processes here */
2162 t
= strv_join(p
->argv
, " ");
2163 printf("\t Process: %u %s=%s ", p
->pid
, p
->name
, strna(t
));
2166 good
= is_clean_exit_lsb(p
->code
, p
->status
, NULL
);
2168 on
= ansi_highlight_red(true);
2169 off
= ansi_highlight_red(false);
2173 printf("%s(code=%s, ", on
, sigchld_code_to_string(p
->code
));
2175 if (p
->code
== CLD_EXITED
) {
2178 printf("status=%i", p
->status
);
2180 c
= exit_status_to_string(p
->status
, EXIT_STATUS_SYSTEMD
);
2185 printf("signal=%s", signal_to_string(p
->status
));
2187 printf(")%s\n", off
);
2189 if (i
->main_pid
== p
->pid
&&
2190 i
->start_timestamp
== p
->start_timestamp
&&
2191 i
->exit_timestamp
== p
->start_timestamp
)
2192 /* Let's not show this twice */
2195 if (p
->pid
== i
->control_pid
)
2199 if (i
->main_pid
> 0 || i
->control_pid
> 0) {
2202 if (i
->main_pid
> 0) {
2203 printf("Main PID: %u", (unsigned) i
->main_pid
);
2207 get_process_comm(i
->main_pid
, &t
);
2212 } else if (i
->exit_code
> 0) {
2213 printf(" (code=%s, ", sigchld_code_to_string(i
->exit_code
));
2215 if (i
->exit_code
== CLD_EXITED
) {
2218 printf("status=%i", i
->exit_status
);
2220 c
= exit_status_to_string(i
->exit_status
, EXIT_STATUS_SYSTEMD
);
2225 printf("signal=%s", signal_to_string(i
->exit_status
));
2230 if (i
->main_pid
> 0 && i
->control_pid
> 0)
2233 if (i
->control_pid
> 0) {
2236 printf(" Control: %u", (unsigned) i
->control_pid
);
2238 get_process_comm(i
->control_pid
, &t
);
2249 printf("\t Status: \"%s\"\n", i
->status_text
);
2251 if (i
->default_control_group
) {
2254 printf("\t CGroup: %s\n", i
->default_control_group
);
2256 if (arg_transport
!= TRANSPORT_SSH
) {
2266 if (i
->main_pid
> 0)
2267 extra
[k
++] = i
->main_pid
;
2269 if (i
->control_pid
> 0)
2270 extra
[k
++] = i
->control_pid
;
2272 show_cgroup_and_extra_by_spec(i
->default_control_group
, "\t\t ", c
, false, arg_all
, extra
, k
);
2276 if (i
->id
&& arg_transport
!= TRANSPORT_SSH
) {
2278 arg_all
* OUTPUT_SHOW_ALL
|
2279 arg_follow
* OUTPUT_FOLLOW
|
2280 !arg_quiet
* OUTPUT_WARN_CUTOFF
|
2281 on_tty() * OUTPUT_COLOR
;
2284 show_journal_by_unit(i
->id
, arg_output
, 0,
2285 i
->inactive_exit_timestamp_monotonic
,
2289 if (i
->need_daemon_reload
)
2290 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2291 ansi_highlight_red(true),
2292 ansi_highlight_red(false),
2293 arg_scope
== UNIT_FILE_SYSTEM
? "--system" : "--user");
2296 static void show_unit_help(UnitStatusInfo
*i
) {
2301 if (!i
->documentation
) {
2302 log_info("Documentation for %s not known.", i
->id
);
2306 STRV_FOREACH(p
, i
->documentation
) {
2308 if (startswith(*p
, "man:")) {
2311 char *page
= NULL
, *section
= NULL
;
2312 const char *args
[4] = { "man", NULL
, NULL
, NULL
};
2317 if ((*p
)[k
-1] == ')')
2318 e
= strrchr(*p
, '(');
2321 page
= strndup((*p
) + 4, e
- *p
- 4);
2327 section
= strndup(e
+ 1, *p
+ k
- e
- 2);
2341 log_error("Failed to fork: %m");
2349 execvp(args
[0], (char**) args
);
2350 log_error("Failed to execute man: %m");
2351 _exit(EXIT_FAILURE
);
2357 wait_for_terminate(pid
, NULL
);
2359 log_info("Can't show: %s", *p
);
2363 static int status_property(const char *name
, DBusMessageIter
*iter
, UnitStatusInfo
*i
) {
2369 switch (dbus_message_iter_get_arg_type(iter
)) {
2371 case DBUS_TYPE_STRING
: {
2374 dbus_message_iter_get_basic(iter
, &s
);
2377 if (streq(name
, "Id"))
2379 else if (streq(name
, "LoadState"))
2381 else if (streq(name
, "ActiveState"))
2382 i
->active_state
= s
;
2383 else if (streq(name
, "SubState"))
2385 else if (streq(name
, "Description"))
2387 else if (streq(name
, "FragmentPath"))
2388 i
->fragment_path
= s
;
2389 else if (streq(name
, "SourcePath"))
2391 else if (streq(name
, "DefaultControlGroup"))
2392 i
->default_control_group
= s
;
2393 else if (streq(name
, "StatusText"))
2395 else if (streq(name
, "SysFSPath"))
2397 else if (streq(name
, "Where"))
2399 else if (streq(name
, "What"))
2401 else if (streq(name
, "Following"))
2403 else if (streq(name
, "UnitFileState"))
2404 i
->unit_file_state
= s
;
2405 else if (streq(name
, "Result"))
2412 case DBUS_TYPE_BOOLEAN
: {
2415 dbus_message_iter_get_basic(iter
, &b
);
2417 if (streq(name
, "Accept"))
2419 else if (streq(name
, "NeedDaemonReload"))
2420 i
->need_daemon_reload
= b
;
2421 else if (streq(name
, "ConditionResult"))
2422 i
->condition_result
= b
;
2427 case DBUS_TYPE_UINT32
: {
2430 dbus_message_iter_get_basic(iter
, &u
);
2432 if (streq(name
, "MainPID")) {
2434 i
->main_pid
= (pid_t
) u
;
2437 } else if (streq(name
, "ControlPID"))
2438 i
->control_pid
= (pid_t
) u
;
2439 else if (streq(name
, "ExecMainPID")) {
2441 i
->main_pid
= (pid_t
) u
;
2442 } else if (streq(name
, "NAccepted"))
2444 else if (streq(name
, "NConnections"))
2445 i
->n_connections
= u
;
2450 case DBUS_TYPE_INT32
: {
2453 dbus_message_iter_get_basic(iter
, &j
);
2455 if (streq(name
, "ExecMainCode"))
2456 i
->exit_code
= (int) j
;
2457 else if (streq(name
, "ExecMainStatus"))
2458 i
->exit_status
= (int) j
;
2463 case DBUS_TYPE_UINT64
: {
2466 dbus_message_iter_get_basic(iter
, &u
);
2468 if (streq(name
, "ExecMainStartTimestamp"))
2469 i
->start_timestamp
= (usec_t
) u
;
2470 else if (streq(name
, "ExecMainExitTimestamp"))
2471 i
->exit_timestamp
= (usec_t
) u
;
2472 else if (streq(name
, "ActiveEnterTimestamp"))
2473 i
->active_enter_timestamp
= (usec_t
) u
;
2474 else if (streq(name
, "InactiveEnterTimestamp"))
2475 i
->inactive_enter_timestamp
= (usec_t
) u
;
2476 else if (streq(name
, "InactiveExitTimestamp"))
2477 i
->inactive_exit_timestamp
= (usec_t
) u
;
2478 else if (streq(name
, "InactiveExitTimestampMonotonic"))
2479 i
->inactive_exit_timestamp_monotonic
= (usec_t
) u
;
2480 else if (streq(name
, "ActiveExitTimestamp"))
2481 i
->active_exit_timestamp
= (usec_t
) u
;
2482 else if (streq(name
, "ConditionTimestamp"))
2483 i
->condition_timestamp
= (usec_t
) u
;
2488 case DBUS_TYPE_ARRAY
: {
2490 if (dbus_message_iter_get_element_type(iter
) == DBUS_TYPE_STRUCT
&&
2491 startswith(name
, "Exec")) {
2492 DBusMessageIter sub
;
2494 dbus_message_iter_recurse(iter
, &sub
);
2495 while (dbus_message_iter_get_arg_type(&sub
) == DBUS_TYPE_STRUCT
) {
2496 ExecStatusInfo
*info
;
2499 if (!(info
= new0(ExecStatusInfo
, 1)))
2502 if (!(info
->name
= strdup(name
))) {
2507 if ((r
= exec_status_info_deserialize(&sub
, info
)) < 0) {
2512 LIST_PREPEND(ExecStatusInfo
, exec
, i
->exec
, info
);
2514 dbus_message_iter_next(&sub
);
2516 } else if (dbus_message_iter_get_element_type(iter
) == DBUS_TYPE_STRING
&&
2517 streq(name
, "Documentation")) {
2519 DBusMessageIter sub
;
2521 dbus_message_iter_recurse(iter
, &sub
);
2522 while (dbus_message_iter_get_arg_type(&sub
) == DBUS_TYPE_STRING
) {
2526 dbus_message_iter_get_basic(&sub
, &s
);
2528 l
= strv_append(i
->documentation
, s
);
2532 strv_free(i
->documentation
);
2533 i
->documentation
= l
;
2535 dbus_message_iter_next(&sub
);
2542 case DBUS_TYPE_STRUCT
: {
2544 if (streq(name
, "LoadError")) {
2545 DBusMessageIter sub
;
2546 const char *n
, *message
;
2549 dbus_message_iter_recurse(iter
, &sub
);
2551 r
= bus_iter_get_basic_and_next(&sub
, DBUS_TYPE_STRING
, &n
, true);
2555 r
= bus_iter_get_basic_and_next(&sub
, DBUS_TYPE_STRING
, &message
, false);
2559 if (!isempty(message
))
2560 i
->load_error
= message
;
2570 static int print_property(const char *name
, DBusMessageIter
*iter
) {
2574 /* This is a low-level property printer, see
2575 * print_status_info() for the nicer output */
2577 if (arg_property
&& !strv_find(arg_property
, name
))
2580 switch (dbus_message_iter_get_arg_type(iter
)) {
2582 case DBUS_TYPE_STRUCT
: {
2583 DBusMessageIter sub
;
2584 dbus_message_iter_recurse(iter
, &sub
);
2586 if (dbus_message_iter_get_arg_type(&sub
) == DBUS_TYPE_UINT32
&& streq(name
, "Job")) {
2589 dbus_message_iter_get_basic(&sub
, &u
);
2592 printf("%s=%u\n", name
, (unsigned) u
);
2594 printf("%s=\n", name
);
2597 } else if (dbus_message_iter_get_arg_type(&sub
) == DBUS_TYPE_STRING
&& streq(name
, "Unit")) {
2600 dbus_message_iter_get_basic(&sub
, &s
);
2602 if (arg_all
|| s
[0])
2603 printf("%s=%s\n", name
, s
);
2606 } else if (dbus_message_iter_get_arg_type(&sub
) == DBUS_TYPE_STRING
&& streq(name
, "LoadError")) {
2607 const char *a
= NULL
, *b
= NULL
;
2609 if (bus_iter_get_basic_and_next(&sub
, DBUS_TYPE_STRING
, &a
, true) >= 0)
2610 bus_iter_get_basic_and_next(&sub
, DBUS_TYPE_STRING
, &b
, false);
2612 if (arg_all
|| !isempty(a
) || !isempty(b
))
2613 printf("%s=%s \"%s\"\n", name
, strempty(a
), strempty(b
));
2621 case DBUS_TYPE_ARRAY
:
2623 if (dbus_message_iter_get_element_type(iter
) == DBUS_TYPE_STRUCT
&& streq(name
, "EnvironmentFiles")) {
2624 DBusMessageIter sub
, sub2
;
2626 dbus_message_iter_recurse(iter
, &sub
);
2627 while (dbus_message_iter_get_arg_type(&sub
) == DBUS_TYPE_STRUCT
) {
2631 dbus_message_iter_recurse(&sub
, &sub2
);
2633 if (bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &path
, true) >= 0 &&
2634 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_BOOLEAN
, &ignore
, false) >= 0)
2635 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path
, yes_no(ignore
));
2637 dbus_message_iter_next(&sub
);
2642 } else if (dbus_message_iter_get_element_type(iter
) == DBUS_TYPE_STRUCT
&& streq(name
, "Paths")) {
2643 DBusMessageIter sub
, sub2
;
2645 dbus_message_iter_recurse(iter
, &sub
);
2646 while (dbus_message_iter_get_arg_type(&sub
) == DBUS_TYPE_STRUCT
) {
2647 const char *type
, *path
;
2649 dbus_message_iter_recurse(&sub
, &sub2
);
2651 if (bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &type
, true) >= 0 &&
2652 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &path
, false) >= 0)
2653 printf("%s=%s\n", type
, path
);
2655 dbus_message_iter_next(&sub
);
2660 } else if (dbus_message_iter_get_element_type(iter
) == DBUS_TYPE_STRUCT
&& streq(name
, "Timers")) {
2661 DBusMessageIter sub
, sub2
;
2663 dbus_message_iter_recurse(iter
, &sub
);
2664 while (dbus_message_iter_get_arg_type(&sub
) == DBUS_TYPE_STRUCT
) {
2666 uint64_t value
, next_elapse
;
2668 dbus_message_iter_recurse(&sub
, &sub2
);
2670 if (bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &base
, true) >= 0 &&
2671 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_UINT64
, &value
, true) >= 0 &&
2672 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_UINT64
, &next_elapse
, false) >= 0) {
2673 char timespan1
[FORMAT_TIMESPAN_MAX
], timespan2
[FORMAT_TIMESPAN_MAX
];
2675 printf("%s={ value=%s ; next_elapse=%s }\n",
2677 format_timespan(timespan1
, sizeof(timespan1
), value
),
2678 format_timespan(timespan2
, sizeof(timespan2
), next_elapse
));
2681 dbus_message_iter_next(&sub
);
2686 } else if (dbus_message_iter_get_element_type(iter
) == DBUS_TYPE_STRUCT
&& streq(name
, "ControlGroupAttributes")) {
2687 DBusMessageIter sub
, sub2
;
2689 dbus_message_iter_recurse(iter
, &sub
);
2690 while (dbus_message_iter_get_arg_type(&sub
) == DBUS_TYPE_STRUCT
) {
2691 const char *controller
, *attr
, *value
;
2693 dbus_message_iter_recurse(&sub
, &sub2
);
2695 if (bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &controller
, true) >= 0 &&
2696 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &attr
, true) >= 0 &&
2697 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &value
, false) >= 0) {
2699 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2705 dbus_message_iter_next(&sub
);
2710 } else if (dbus_message_iter_get_element_type(iter
) == DBUS_TYPE_STRUCT
&& startswith(name
, "Exec")) {
2711 DBusMessageIter sub
;
2713 dbus_message_iter_recurse(iter
, &sub
);
2714 while (dbus_message_iter_get_arg_type(&sub
) == DBUS_TYPE_STRUCT
) {
2715 ExecStatusInfo info
;
2718 if (exec_status_info_deserialize(&sub
, &info
) >= 0) {
2719 char timestamp1
[FORMAT_TIMESTAMP_MAX
], timestamp2
[FORMAT_TIMESTAMP_MAX
];
2722 t
= strv_join(info
.argv
, " ");
2724 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2728 yes_no(info
.ignore
),
2729 strna(format_timestamp(timestamp1
, sizeof(timestamp1
), info
.start_timestamp
)),
2730 strna(format_timestamp(timestamp2
, sizeof(timestamp2
), info
.exit_timestamp
)),
2731 (unsigned) info
. pid
,
2732 sigchld_code_to_string(info
.code
),
2734 info
.code
== CLD_EXITED
? "" : "/",
2735 strempty(info
.code
== CLD_EXITED
? NULL
: signal_to_string(info
.status
)));
2741 strv_free(info
.argv
);
2743 dbus_message_iter_next(&sub
);
2752 if (generic_print_property(name
, iter
, arg_all
) > 0)
2756 printf("%s=[unprintable]\n", name
);
2761 static int show_one(const char *verb
, DBusConnection
*bus
, const char *path
, bool show_properties
, bool *new_line
) {
2762 DBusMessage
*reply
= NULL
;
2763 const char *interface
= "";
2765 DBusMessageIter iter
, sub
, sub2
, sub3
;
2766 UnitStatusInfo info
;
2774 r
= bus_method_call_with_reply (
2776 "org.freedesktop.systemd1",
2778 "org.freedesktop.DBus.Properties",
2782 DBUS_TYPE_STRING
, &interface
,
2787 if (!dbus_message_iter_init(reply
, &iter
) ||
2788 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_ARRAY
||
2789 dbus_message_iter_get_element_type(&iter
) != DBUS_TYPE_DICT_ENTRY
) {
2790 log_error("Failed to parse reply.");
2795 dbus_message_iter_recurse(&iter
, &sub
);
2802 while (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_INVALID
) {
2805 if (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_DICT_ENTRY
) {
2806 log_error("Failed to parse reply.");
2811 dbus_message_iter_recurse(&sub
, &sub2
);
2813 if (bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &name
, true) < 0) {
2814 log_error("Failed to parse reply.");
2819 if (dbus_message_iter_get_arg_type(&sub2
) != DBUS_TYPE_VARIANT
) {
2820 log_error("Failed to parse reply.");
2825 dbus_message_iter_recurse(&sub2
, &sub3
);
2827 if (show_properties
)
2828 r
= print_property(name
, &sub3
);
2830 r
= status_property(name
, &sub3
, &info
);
2833 log_error("Failed to parse reply.");
2838 dbus_message_iter_next(&sub
);
2843 if (!show_properties
) {
2844 if (streq(verb
, "help"))
2845 show_unit_help(&info
);
2847 print_status_info(&info
);
2850 strv_free(info
.documentation
);
2852 if (!streq_ptr(info
.active_state
, "active") &&
2853 !streq_ptr(info
.active_state
, "reloading") &&
2854 streq(verb
, "status"))
2855 /* According to LSB: "program not running" */
2858 while ((p
= info
.exec
)) {
2859 LIST_REMOVE(ExecStatusInfo
, exec
, info
.exec
, p
);
2860 exec_status_info_free(p
);
2865 dbus_message_unref(reply
);
2870 static int show_one_by_pid(const char *verb
, DBusConnection
*bus
, uint32_t pid
, bool *new_line
) {
2871 DBusMessage
*reply
= NULL
;
2872 const char *path
= NULL
;
2876 dbus_error_init(&error
);
2878 r
= bus_method_call_with_reply (
2880 "org.freedesktop.systemd1",
2881 "/org/freedesktop/systemd1",
2882 "org.freedesktop.systemd1.Manager",
2886 DBUS_TYPE_UINT32
, &pid
,
2891 if (!dbus_message_get_args(reply
, &error
,
2892 DBUS_TYPE_OBJECT_PATH
, &path
,
2893 DBUS_TYPE_INVALID
)) {
2894 log_error("Failed to parse reply: %s", bus_error_message(&error
));
2899 r
= show_one(verb
, bus
, path
, false, new_line
);
2903 dbus_message_unref(reply
);
2905 dbus_error_free(&error
);
2910 static int show(DBusConnection
*bus
, char **args
) {
2912 bool show_properties
, new_line
= false;
2918 show_properties
= streq(args
[0], "show");
2920 if (show_properties
)
2921 pager_open_if_enabled();
2923 if (show_properties
&& strv_length(args
) <= 1) {
2924 /* If not argument is specified inspect the manager
2927 return show_one(args
[0], bus
, "/org/freedesktop/systemd1", show_properties
, &new_line
);
2930 STRV_FOREACH(name
, args
+1) {
2933 if (safe_atou32(*name
, &id
) < 0) {
2935 /* Interpret as unit name */
2937 n
= unit_name_mangle(*name
);
2938 p
= unit_dbus_path_from_name(n
? n
: *name
);
2943 r
= show_one(args
[0], bus
, p
, show_properties
, &new_line
);
2949 } else if (show_properties
) {
2951 /* Interpret as job id */
2954 if (asprintf(&p
, "/org/freedesktop/systemd1/job/%u", id
) < 0)
2957 r
= show_one(args
[0], bus
, p
, show_properties
, &new_line
);
2965 /* Interpret as PID */
2967 r
= show_one_by_pid(args
[0], bus
, id
, &new_line
);
2976 static int dump(DBusConnection
*bus
, char **args
) {
2977 DBusMessage
*reply
= NULL
;
2982 dbus_error_init(&error
);
2984 pager_open_if_enabled();
2986 r
= bus_method_call_with_reply (
2988 "org.freedesktop.systemd1",
2989 "/org/freedesktop/systemd1",
2990 "org.freedesktop.systemd1.Manager",
2998 if (!dbus_message_get_args(reply
, &error
,
2999 DBUS_TYPE_STRING
, &text
,
3000 DBUS_TYPE_INVALID
)) {
3001 log_error("Failed to parse reply: %s", bus_error_message(&error
));
3006 fputs(text
, stdout
);
3010 dbus_message_unref(reply
);
3012 dbus_error_free(&error
);
3017 static int snapshot(DBusConnection
*bus
, char **args
) {
3018 DBusMessage
*reply
= NULL
;
3021 dbus_bool_t cleanup
= FALSE
;
3022 DBusMessageIter iter
, sub
;
3024 *name
= "", *path
, *id
,
3025 *interface
= "org.freedesktop.systemd1.Unit",
3029 dbus_error_init(&error
);
3031 if (strv_length(args
) > 1)
3034 n
= unit_name_mangle(name
);
3035 r
= bus_method_call_with_reply (
3037 "org.freedesktop.systemd1",
3038 "/org/freedesktop/systemd1",
3039 "org.freedesktop.systemd1.Manager",
3043 DBUS_TYPE_STRING
, n
? (const char**) &n
: &name
,
3044 DBUS_TYPE_BOOLEAN
, &cleanup
,
3050 if (!dbus_message_get_args(reply
, &error
,
3051 DBUS_TYPE_OBJECT_PATH
, &path
,
3052 DBUS_TYPE_INVALID
)) {
3053 log_error("Failed to parse reply: %s", bus_error_message(&error
));
3058 dbus_message_unref(reply
);
3059 r
= bus_method_call_with_reply (
3061 "org.freedesktop.systemd1",
3063 "org.freedesktop.DBus.Properties",
3067 DBUS_TYPE_STRING
, &interface
,
3068 DBUS_TYPE_STRING
, &property
,
3073 if (!dbus_message_iter_init(reply
, &iter
) ||
3074 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_VARIANT
) {
3075 log_error("Failed to parse reply.");
3080 dbus_message_iter_recurse(&iter
, &sub
);
3082 if (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_STRING
) {
3083 log_error("Failed to parse reply.");
3088 dbus_message_iter_get_basic(&sub
, &id
);
3095 dbus_message_unref(reply
);
3097 dbus_error_free(&error
);
3102 static int delete_snapshot(DBusConnection
*bus
, char **args
) {
3103 DBusMessage
*reply
= NULL
;
3110 dbus_error_init(&error
);
3112 STRV_FOREACH(name
, args
+1) {
3113 const char *path
= NULL
;
3116 n
= unit_name_mangle(*name
);
3117 r
= bus_method_call_with_reply (
3119 "org.freedesktop.systemd1",
3120 "/org/freedesktop/systemd1",
3121 "org.freedesktop.systemd1.Manager",
3125 DBUS_TYPE_STRING
, n
? &n
: name
,
3131 if (!dbus_message_get_args(reply
, &error
,
3132 DBUS_TYPE_OBJECT_PATH
, &path
,
3133 DBUS_TYPE_INVALID
)) {
3134 log_error("Failed to parse reply: %s", bus_error_message(&error
));
3136 dbus_message_unref(reply
);
3137 dbus_error_free(&error
);
3140 dbus_message_unref(reply
);
3142 r
= bus_method_call_with_reply (
3144 "org.freedesktop.systemd1",
3146 "org.freedesktop.systemd1.Snapshot",
3159 static int daemon_reload(DBusConnection
*bus
, char **args
) {
3164 if (arg_action
== ACTION_RELOAD
)
3166 else if (arg_action
== ACTION_REEXEC
)
3167 method
= "Reexecute";
3169 assert(arg_action
== ACTION_SYSTEMCTL
);
3172 streq(args
[0], "clear-jobs") ||
3173 streq(args
[0], "cancel") ? "ClearJobs" :
3174 streq(args
[0], "daemon-reexec") ? "Reexecute" :
3175 streq(args
[0], "reset-failed") ? "ResetFailed" :
3176 streq(args
[0], "halt") ? "Halt" :
3177 streq(args
[0], "poweroff") ? "PowerOff" :
3178 streq(args
[0], "reboot") ? "Reboot" :
3179 streq(args
[0], "kexec") ? "KExec" :
3180 streq(args
[0], "exit") ? "Exit" :
3181 /* "daemon-reload" */ "Reload";
3184 r
= bus_method_call_with_reply (
3186 "org.freedesktop.systemd1",
3187 "/org/freedesktop/systemd1",
3188 "org.freedesktop.systemd1.Manager",
3194 if (r
== -ENOENT
&& arg_action
!= ACTION_SYSTEMCTL
)
3195 /* There's always a fallback possible for
3196 * legacy actions. */
3198 else if (r
== -ETIMEDOUT
&& streq(method
, "Reexecute"))
3199 /* On reexecution, we expect a disconnect, not
3203 log_error("Failed to issue method call: %s", bus_error_message(&error
));
3204 dbus_error_free(&error
);
3209 static int reset_failed(DBusConnection
*bus
, char **args
) {
3213 if (strv_length(args
) <= 1)
3214 return daemon_reload(bus
, args
);
3216 STRV_FOREACH(name
, args
+1) {
3217 n
= unit_name_mangle(*name
);
3218 r
= bus_method_call_with_reply (
3220 "org.freedesktop.systemd1",
3221 "/org/freedesktop/systemd1",
3222 "org.freedesktop.systemd1.Manager",
3226 DBUS_TYPE_STRING
, n
? &n
: name
,
3237 static int show_enviroment(DBusConnection
*bus
, char **args
) {
3238 DBusMessage
*reply
= NULL
;
3239 DBusMessageIter iter
, sub
, sub2
;
3242 *interface
= "org.freedesktop.systemd1.Manager",
3243 *property
= "Environment";
3245 pager_open_if_enabled();
3247 r
= bus_method_call_with_reply (
3249 "org.freedesktop.systemd1",
3250 "/org/freedesktop/systemd1",
3251 "org.freedesktop.DBus.Properties",
3255 DBUS_TYPE_STRING
, &interface
,
3256 DBUS_TYPE_STRING
, &property
,
3261 if (!dbus_message_iter_init(reply
, &iter
) ||
3262 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_VARIANT
) {
3263 log_error("Failed to parse reply.");
3268 dbus_message_iter_recurse(&iter
, &sub
);
3270 if (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_ARRAY
||
3271 dbus_message_iter_get_element_type(&sub
) != DBUS_TYPE_STRING
) {
3272 log_error("Failed to parse reply.");
3277 dbus_message_iter_recurse(&sub
, &sub2
);
3279 while (dbus_message_iter_get_arg_type(&sub2
) != DBUS_TYPE_INVALID
) {
3282 if (dbus_message_iter_get_arg_type(&sub2
) != DBUS_TYPE_STRING
) {
3283 log_error("Failed to parse reply.");
3288 dbus_message_iter_get_basic(&sub2
, &text
);
3289 printf("%s\n", text
);
3291 dbus_message_iter_next(&sub2
);
3298 dbus_message_unref(reply
);
3303 static int switch_root(DBusConnection
*bus
, char **args
) {
3305 const char *root
, *init
;
3307 l
= strv_length(args
);
3308 if (l
< 2 || l
> 3) {
3309 log_error("Wrong number of arguments.");
3314 init
= l
>= 3 ? args
[2] : "";
3316 return bus_method_call_with_reply (
3318 "org.freedesktop.systemd1",
3319 "/org/freedesktop/systemd1",
3320 "org.freedesktop.systemd1.Manager",
3324 DBUS_TYPE_STRING
, &root
,
3325 DBUS_TYPE_STRING
, &init
,
3329 static int set_environment(DBusConnection
*bus
, char **args
) {
3330 DBusMessage
*m
= NULL
, *reply
= NULL
;
3334 DBusMessageIter iter
, sub
;
3337 dbus_error_init(&error
);
3339 method
= streq(args
[0], "set-environment")
3341 : "UnsetEnvironment";
3343 if (!(m
= dbus_message_new_method_call(
3344 "org.freedesktop.systemd1",
3345 "/org/freedesktop/systemd1",
3346 "org.freedesktop.systemd1.Manager",
3349 log_error("Could not allocate message.");
3353 dbus_message_iter_init_append(m
, &iter
);
3355 if (!dbus_message_iter_open_container(&iter
, DBUS_TYPE_ARRAY
, "s", &sub
)) {
3356 log_error("Could not append arguments to message.");
3361 STRV_FOREACH(name
, args
+1)
3362 if (!dbus_message_iter_append_basic(&sub
, DBUS_TYPE_STRING
, name
)) {
3363 log_error("Could not append arguments to message.");
3368 if (!dbus_message_iter_close_container(&iter
, &sub
)) {
3369 log_error("Could not append arguments to message.");
3374 if (!(reply
= dbus_connection_send_with_reply_and_block(bus
, m
, -1, &error
))) {
3375 log_error("Failed to issue method call: %s", bus_error_message(&error
));
3384 dbus_message_unref(m
);
3387 dbus_message_unref(reply
);
3389 dbus_error_free(&error
);
3394 static int enable_sysv_units(char **args
) {
3397 #if defined (HAVE_SYSV_COMPAT) && (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_SUSE) || defined(TARGET_ALTLINUX) || defined(TARGET_MAGEIA))
3398 const char *verb
= args
[0];
3399 unsigned f
= 1, t
= 1;
3402 if (arg_scope
!= UNIT_FILE_SYSTEM
)
3405 if (!streq(verb
, "enable") &&
3406 !streq(verb
, "disable") &&
3407 !streq(verb
, "is-enabled"))
3410 /* Processes all SysV units, and reshuffles the array so that
3411 * afterwards only the native units remain */
3414 r
= lookup_paths_init(&paths
, SYSTEMD_SYSTEM
, false, NULL
, NULL
, NULL
);
3419 for (f
= 1; args
[f
]; f
++) {
3422 bool found_native
= false, found_sysv
;
3424 const char *argv
[6] = { "/sbin/chkconfig", NULL
, NULL
, NULL
, NULL
};
3425 char **k
, *l
, *q
= NULL
;
3432 if (!endswith(name
, ".service"))
3435 if (path_is_absolute(name
))
3438 STRV_FOREACH(k
, paths
.unit_path
) {
3441 if (!isempty(arg_root
))
3442 asprintf(&p
, "%s/%s/%s", arg_root
, *k
, name
);
3444 asprintf(&p
, "%s/%s", *k
, name
);
3451 found_native
= access(p
, F_OK
) >= 0;
3462 if (!isempty(arg_root
))
3463 asprintf(&p
, "%s/" SYSTEM_SYSVINIT_PATH
"/%s", arg_root
, name
);
3465 asprintf(&p
, SYSTEM_SYSVINIT_PATH
"/%s", name
);
3471 p
[strlen(p
) - sizeof(".service") + 1] = 0;
3472 found_sysv
= access(p
, F_OK
) >= 0;
3479 /* Mark this entry, so that we don't try enabling it as native unit */
3480 args
[f
] = (char*) "";
3482 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name
);
3484 if (!isempty(arg_root
))
3485 argv
[c
++] = q
= strappend("--root=", arg_root
);
3487 argv
[c
++] = path_get_file_name(p
);
3489 streq(verb
, "enable") ? "on" :
3490 streq(verb
, "disable") ? "off" : "--level=5";
3493 l
= strv_join((char**)argv
, " ");
3501 log_info("Executing %s", l
);
3506 log_error("Failed to fork: %m");
3511 } else if (pid
== 0) {
3514 execv(argv
[0], (char**) argv
);
3515 _exit(EXIT_FAILURE
);
3521 j
= wait_for_terminate(pid
, &status
);
3523 log_error("Failed to wait for child: %s", strerror(-r
));
3528 if (status
.si_code
== CLD_EXITED
) {
3529 if (streq(verb
, "is-enabled")) {
3530 if (status
.si_status
== 0) {
3539 } else if (status
.si_status
!= 0) {
3550 lookup_paths_free(&paths
);
3552 /* Drop all SysV units */
3553 for (f
= 1, t
= 1; args
[f
]; f
++) {
3555 if (isempty(args
[f
]))
3558 args
[t
++] = args
[f
];
3567 static int mangle_names(char **original_names
, char ***mangled_names
) {
3568 char **i
, **l
, **name
;
3570 l
= new(char*, strv_length(original_names
) + 1);
3575 STRV_FOREACH(name
, original_names
) {
3576 *i
= unit_name_mangle(*name
);
3591 static int enable_unit(DBusConnection
*bus
, char **args
) {
3592 const char *verb
= args
[0];
3593 UnitFileChange
*changes
= NULL
;
3594 unsigned n_changes
= 0, i
;
3595 int carries_install_info
= -1;
3596 DBusMessage
*m
= NULL
, *reply
= NULL
;
3599 char **mangled_names
= NULL
;
3601 r
= enable_sysv_units(args
);
3608 dbus_error_init(&error
);
3610 if (!bus
|| avoid_bus()) {
3611 if (streq(verb
, "enable")) {
3612 r
= unit_file_enable(arg_scope
, arg_runtime
, arg_root
, args
+1, arg_force
, &changes
, &n_changes
);
3613 carries_install_info
= r
;
3614 } else if (streq(verb
, "disable"))
3615 r
= unit_file_disable(arg_scope
, arg_runtime
, arg_root
, args
+1, &changes
, &n_changes
);
3616 else if (streq(verb
, "reenable")) {
3617 r
= unit_file_reenable(arg_scope
, arg_runtime
, arg_root
, args
+1, arg_force
, &changes
, &n_changes
);
3618 carries_install_info
= r
;
3619 } else if (streq(verb
, "link"))
3620 r
= unit_file_link(arg_scope
, arg_runtime
, arg_root
, args
+1, arg_force
, &changes
, &n_changes
);
3621 else if (streq(verb
, "preset")) {
3622 r
= unit_file_preset(arg_scope
, arg_runtime
, arg_root
, args
+1, arg_force
, &changes
, &n_changes
);
3623 carries_install_info
= r
;
3624 } else if (streq(verb
, "mask"))
3625 r
= unit_file_mask(arg_scope
, arg_runtime
, arg_root
, args
+1, arg_force
, &changes
, &n_changes
);
3626 else if (streq(verb
, "unmask"))
3627 r
= unit_file_unmask(arg_scope
, arg_runtime
, arg_root
, args
+1, &changes
, &n_changes
);
3629 assert_not_reached("Unknown verb");
3632 log_error("Operation failed: %s", strerror(-r
));
3637 for (i
= 0; i
< n_changes
; i
++) {
3638 if (changes
[i
].type
== UNIT_FILE_SYMLINK
)
3639 log_info("ln -s '%s' '%s'", changes
[i
].source
, changes
[i
].path
);
3641 log_info("rm '%s'", changes
[i
].path
);
3647 bool send_force
= true, expect_carries_install_info
= false;
3649 DBusMessageIter iter
, sub
, sub2
;
3651 if (streq(verb
, "enable")) {
3652 method
= "EnableUnitFiles";
3653 expect_carries_install_info
= true;
3654 } else if (streq(verb
, "disable")) {
3655 method
= "DisableUnitFiles";
3657 } else if (streq(verb
, "reenable")) {
3658 method
= "ReenableUnitFiles";
3659 expect_carries_install_info
= true;
3660 } else if (streq(verb
, "link"))
3661 method
= "LinkUnitFiles";
3662 else if (streq(verb
, "preset")) {
3663 method
= "PresetUnitFiles";
3664 expect_carries_install_info
= true;
3665 } else if (streq(verb
, "mask"))
3666 method
= "MaskUnitFiles";
3667 else if (streq(verb
, "unmask")) {
3668 method
= "UnmaskUnitFiles";
3671 assert_not_reached("Unknown verb");
3673 m
= dbus_message_new_method_call(
3674 "org.freedesktop.systemd1",
3675 "/org/freedesktop/systemd1",
3676 "org.freedesktop.systemd1.Manager",
3683 dbus_message_iter_init_append(m
, &iter
);
3685 r
= mangle_names(args
+1, &mangled_names
);
3689 r
= bus_append_strv_iter(&iter
, mangled_names
);
3691 log_error("Failed to append unit files.");
3696 if (!dbus_message_iter_append_basic(&iter
, DBUS_TYPE_BOOLEAN
, &a
)) {
3697 log_error("Failed to append runtime boolean.");
3705 if (!dbus_message_iter_append_basic(&iter
, DBUS_TYPE_BOOLEAN
, &b
)) {
3706 log_error("Failed to append force boolean.");
3712 reply
= dbus_connection_send_with_reply_and_block(bus
, m
, -1, &error
);
3714 log_error("Failed to issue method call: %s", bus_error_message(&error
));
3719 if (!dbus_message_iter_init(reply
, &iter
)) {
3720 log_error("Failed to initialize iterator.");
3724 if (expect_carries_install_info
) {
3725 r
= bus_iter_get_basic_and_next(&iter
, DBUS_TYPE_BOOLEAN
, &b
, true);
3727 log_error("Failed to parse reply.");
3731 carries_install_info
= b
;
3734 if (dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_ARRAY
||
3735 dbus_message_iter_get_element_type(&iter
) != DBUS_TYPE_STRUCT
) {
3736 log_error("Failed to parse reply.");
3741 dbus_message_iter_recurse(&iter
, &sub
);
3742 while (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_INVALID
) {
3743 const char *type
, *path
, *source
;
3745 if (dbus_message_iter_get_arg_type(&sub
) != DBUS_TYPE_STRUCT
) {
3746 log_error("Failed to parse reply.");
3751 dbus_message_iter_recurse(&sub
, &sub2
);
3753 if (bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &type
, true) < 0 ||
3754 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &path
, true) < 0 ||
3755 bus_iter_get_basic_and_next(&sub2
, DBUS_TYPE_STRING
, &source
, false) < 0) {
3756 log_error("Failed to parse reply.");
3762 if (streq(type
, "symlink"))
3763 log_info("ln -s '%s' '%s'", source
, path
);
3765 log_info("rm '%s'", path
);
3768 dbus_message_iter_next(&sub
);
3771 /* Try to reload if enabeld */
3773 r
= daemon_reload(bus
, args
);
3776 if (carries_install_info
== 0)
3777 log_warning("The unit files have no [Install] section. They are not meant to be enabled using systemctl.");
3781 dbus_message_unref(m
);
3784 dbus_message_unref(reply
);
3786 unit_file_changes_free(changes
, n_changes
);
3788 dbus_error_free(&error
);
3790 strv_free(mangled_names
);
3795 static int unit_is_enabled(DBusConnection
*bus
, char **args
) {
3798 DBusMessage
*reply
= NULL
;
3802 dbus_error_init(&error
);
3804 r
= enable_sysv_units(args
);
3810 if (!bus
|| avoid_bus()) {
3812 STRV_FOREACH(name
, args
+1) {
3813 UnitFileState state
;
3815 state
= unit_file_get_state(arg_scope
, arg_root
, *name
);
3821 if (state
== UNIT_FILE_ENABLED
||
3822 state
== UNIT_FILE_ENABLED_RUNTIME
||
3823 state
== UNIT_FILE_STATIC
)
3827 puts(unit_file_state_to_string(state
));
3831 STRV_FOREACH(name
, args
+1) {
3834 r
= bus_method_call_with_reply (
3836 "org.freedesktop.systemd1",
3837 "/org/freedesktop/systemd1",
3838 "org.freedesktop.systemd1.Manager",
3842 DBUS_TYPE_STRING
, name
,
3847 if (!dbus_message_get_args(reply
, &error
,
3848 DBUS_TYPE_STRING
, &s
,
3849 DBUS_TYPE_INVALID
)) {
3850 log_error("Failed to parse reply: %s", bus_error_message(&error
));
3855 dbus_message_unref(reply
);
3858 if (streq(s
, "enabled") ||
3859 streq(s
, "enabled-runtime") ||
3868 r
= enabled
? 0 : 1;
3872 dbus_message_unref(reply
);
3874 dbus_error_free(&error
);
3878 static int systemctl_help(void) {
3880 pager_open_if_enabled();
3882 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
3883 "Query or send control commands to the systemd manager.\n\n"
3884 " -h --help Show this help\n"
3885 " --version Show package version\n"
3886 " -t --type=TYPE List only units of a particular type\n"
3887 " -p --property=NAME Show only properties by this name\n"
3888 " -a --all Show all units/properties, including dead/empty ones\n"
3889 " --failed Show only failed units\n"
3890 " --full Don't ellipsize unit names on output\n"
3891 " --fail When queueing a new job, fail if conflicting jobs are\n"
3893 " --ignore-dependencies\n"
3894 " When queueing a new job, ignore all its dependencies\n"
3895 " --kill-who=WHO Who to send signal to\n"
3896 " -s --signal=SIGNAL Which signal to send\n"
3897 " -H --host=[USER@]HOST\n"
3898 " Show information for remote host\n"
3899 " -P --privileged Acquire privileges before execution\n"
3900 " -q --quiet Suppress output\n"
3901 " --no-block Do not wait until operation finished\n"
3902 " --no-wall Don't send wall message before halt/power-off/reboot\n"
3903 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
3905 " --no-legend Do not print a legend (column headers and hints)\n"
3906 " --no-pager Do not pipe output into a pager\n"
3907 " --no-ask-password\n"
3908 " Do not ask for system passwords\n"
3909 " --order When generating graph for dot, show only order\n"
3910 " --require When generating graph for dot, show only requirement\n"
3911 " --system Connect to system manager\n"
3912 " --user Connect to user service manager\n"
3913 " --global Enable/disable unit files globally\n"
3914 " -f --force When enabling unit files, override existing symlinks\n"
3915 " When shutting down, execute action immediately\n"
3916 " --root=PATH Enable unit files in the specified root directory\n"
3917 " --runtime Enable unit files only temporarily until next reboot\n"
3918 " -n --lines=INTEGER Journal entries to show\n"
3919 " --follow Follow journal\n"
3920 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
3921 " verbose, export, json, json-pretty, cat)\n\n"
3923 " list-units List loaded units\n"
3924 " start [NAME...] Start (activate) one or more units\n"
3925 " stop [NAME...] Stop (deactivate) one or more units\n"
3926 " reload [NAME...] Reload one or more units\n"
3927 " restart [NAME...] Start or restart one or more units\n"
3928 " try-restart [NAME...] Restart one or more units if active\n"
3929 " reload-or-restart [NAME...] Reload one or more units is possible,\n"
3930 " otherwise start or restart\n"
3931 " reload-or-try-restart [NAME...] Reload one or more units is possible,\n"
3932 " otherwise restart if active\n"
3933 " isolate [NAME] Start one unit and stop all others\n"
3934 " kill [NAME...] Send signal to processes of a unit\n"
3935 " is-active [NAME...] Check whether units are active\n"
3936 " status [NAME...|PID...] Show runtime status of one or more units\n"
3937 " show [NAME...|JOB...] Show properties of one or more\n"
3938 " units/jobs or the manager\n"
3939 " help [NAME...|PID...] Show manual for one or more units\n"
3940 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
3942 " load [NAME...] Load one or more units\n\n"
3943 "Unit File Commands:\n"
3944 " list-unit-files List installed unit files\n"
3945 " enable [NAME...] Enable one or more unit files\n"
3946 " disable [NAME...] Disable one or more unit files\n"
3947 " reenable [NAME...] Reenable one or more unit files\n"
3948 " preset [NAME...] Enable/disable one or more unit files\n"
3949 " based on preset configuration\n"
3950 " mask [NAME...] Mask one or more units\n"
3951 " unmask [NAME...] Unmask one or more units\n"
3952 " link [PATH...] Link one or more units files into\n"
3953 " the search path\n"
3954 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
3956 " list-jobs List jobs\n"
3957 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
3958 "Status Commands:\n"
3959 " dump Dump server status\n"
3960 " dot Dump dependency graph for dot(1)\n\n"
3961 "Snapshot Commands:\n"
3962 " snapshot [NAME] Create a snapshot\n"
3963 " delete [NAME...] Remove one or more snapshots\n\n"
3964 "Environment Commands:\n"
3965 " show-environment Dump environment\n"
3966 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
3967 " unset-environment [NAME...] Unset one or more environment variables\n\n"
3968 "Manager Lifecycle Commands:\n"
3969 " daemon-reload Reload systemd manager configuration\n"
3970 " daemon-reexec Reexecute systemd manager\n\n"
3971 "System Commands:\n"
3972 " default Enter system default mode\n"
3973 " rescue Enter system rescue mode\n"
3974 " emergency Enter system emergency mode\n"
3975 " halt Shut down and halt the system\n"
3976 " poweroff Shut down and power-off the system\n"
3977 " reboot Shut down and reboot the system\n"
3978 " kexec Shut down and reboot the system with kexec\n"
3979 " exit Request user instance exit\n"
3980 " switch-root [ROOT] [INIT] Change to a different root file system\n"
3981 " suspend Suspend the system\n"
3982 " hibernate Hibernate the system\n",
3983 program_invocation_short_name
);
3988 static int halt_help(void) {
3990 printf("%s [OPTIONS...]\n\n"
3991 "%s the system.\n\n"
3992 " --help Show this help\n"
3993 " --halt Halt the machine\n"
3994 " -p --poweroff Switch off the machine\n"
3995 " --reboot Reboot the machine\n"
3996 " -f --force Force immediate halt/power-off/reboot\n"
3997 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
3998 " -d --no-wtmp Don't write wtmp record\n"
3999 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4000 program_invocation_short_name
,
4001 arg_action
== ACTION_REBOOT
? "Reboot" :
4002 arg_action
== ACTION_POWEROFF
? "Power off" :
4008 static int shutdown_help(void) {
4010 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4011 "Shut down the system.\n\n"
4012 " --help Show this help\n"
4013 " -H --halt Halt the machine\n"
4014 " -P --poweroff Power-off the machine\n"
4015 " -r --reboot Reboot the machine\n"
4016 " -h Equivalent to --poweroff, overridden by --halt\n"
4017 " -k Don't halt/power-off/reboot, just send warnings\n"
4018 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4019 " -c Cancel a pending shutdown\n",
4020 program_invocation_short_name
);
4025 static int telinit_help(void) {
4027 printf("%s [OPTIONS...] {COMMAND}\n\n"
4028 "Send control commands to the init daemon.\n\n"
4029 " --help Show this help\n"
4030 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4032 " 0 Power-off the machine\n"
4033 " 6 Reboot the machine\n"
4034 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4035 " 1, s, S Enter rescue mode\n"
4036 " q, Q Reload init daemon configuration\n"
4037 " u, U Reexecute init daemon\n",
4038 program_invocation_short_name
);
4043 static int runlevel_help(void) {
4045 printf("%s [OPTIONS...]\n\n"
4046 "Prints the previous and current runlevel of the init system.\n\n"
4047 " --help Show this help\n",
4048 program_invocation_short_name
);
4053 static int systemctl_parse_argv(int argc
, char *argv
[]) {
4057 ARG_IGNORE_DEPENDENCIES
,
4072 ARG_NO_ASK_PASSWORD
,
4079 static const struct option options
[] = {
4080 { "help", no_argument
, NULL
, 'h' },
4081 { "version", no_argument
, NULL
, ARG_VERSION
},
4082 { "type", required_argument
, NULL
, 't' },
4083 { "property", required_argument
, NULL
, 'p' },
4084 { "all", no_argument
, NULL
, 'a' },
4085 { "failed", no_argument
, NULL
, ARG_FAILED
},
4086 { "full", no_argument
, NULL
, ARG_FULL
},
4087 { "fail", no_argument
, NULL
, ARG_FAIL
},
4088 { "ignore-dependencies", no_argument
, NULL
, ARG_IGNORE_DEPENDENCIES
},
4089 { "user", no_argument
, NULL
, ARG_USER
},
4090 { "system", no_argument
, NULL
, ARG_SYSTEM
},
4091 { "global", no_argument
, NULL
, ARG_GLOBAL
},
4092 { "no-block", no_argument
, NULL
, ARG_NO_BLOCK
},
4093 { "no-legend", no_argument
, NULL
, ARG_NO_LEGEND
},
4094 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
4095 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
4096 { "quiet", no_argument
, NULL
, 'q' },
4097 { "order", no_argument
, NULL
, ARG_ORDER
},
4098 { "require", no_argument
, NULL
, ARG_REQUIRE
},
4099 { "root", required_argument
, NULL
, ARG_ROOT
},
4100 { "force", no_argument
, NULL
, ARG_FORCE
},
4101 { "no-reload", no_argument
, NULL
, ARG_NO_RELOAD
},
4102 { "kill-who", required_argument
, NULL
, ARG_KILL_WHO
},
4103 { "signal", required_argument
, NULL
, 's' },
4104 { "no-ask-password", no_argument
, NULL
, ARG_NO_ASK_PASSWORD
},
4105 { "host", required_argument
, NULL
, 'H' },
4106 { "privileged",no_argument
, NULL
, 'P' },
4107 { "runtime", no_argument
, NULL
, ARG_RUNTIME
},
4108 { "lines", required_argument
, NULL
, 'n' },
4109 { "follow", no_argument
, NULL
, ARG_FOLLOW
},
4110 { "output", required_argument
, NULL
, 'o' },
4111 { NULL
, 0, NULL
, 0 }
4119 while ((c
= getopt_long(argc
, argv
, "ht:p:aqfs:H:Pn:o:", options
, NULL
)) >= 0) {
4128 puts(PACKAGE_STRING
);
4130 puts(SYSTEMD_FEATURES
);
4134 if (unit_type_from_string(optarg
) >= 0) {
4138 if (unit_load_state_from_string(optarg
) >= 0) {
4139 arg_load_state
= optarg
;
4142 log_error("Unkown unit type or load state '%s'.",
4148 if (!(l
= strv_append(arg_property
, optarg
)))
4151 strv_free(arg_property
);
4154 /* If the user asked for a particular
4155 * property, show it to him, even if it is
4166 arg_job_mode
= "fail";
4169 case ARG_IGNORE_DEPENDENCIES
:
4170 arg_job_mode
= "ignore-dependencies";
4174 arg_scope
= UNIT_FILE_USER
;
4178 arg_scope
= UNIT_FILE_SYSTEM
;
4182 arg_scope
= UNIT_FILE_GLOBAL
;
4186 arg_no_block
= true;
4190 arg_no_legend
= true;
4194 arg_no_pager
= true;
4202 arg_dot
= DOT_ORDER
;
4206 arg_dot
= DOT_REQUIRE
;
4234 /* -f is short for both --follow and --force! */
4240 arg_no_reload
= true;
4244 arg_kill_who
= optarg
;
4248 if ((arg_signal
= signal_from_string_try_harder(optarg
)) < 0) {
4249 log_error("Failed to parse signal string %s.", optarg
);
4254 case ARG_NO_ASK_PASSWORD
:
4255 arg_ask_password
= false;
4259 arg_transport
= TRANSPORT_POLKIT
;
4263 arg_transport
= TRANSPORT_SSH
;
4272 if (safe_atou(optarg
, &arg_lines
) < 0) {
4273 log_error("Failed to parse lines '%s'", optarg
);
4279 arg_output
= output_mode_from_string(optarg
);
4280 if (arg_output
< 0) {
4281 log_error("Unknown output '%s'.", optarg
);
4290 log_error("Unknown option code '%c'.", c
);
4295 if (arg_transport
!= TRANSPORT_NORMAL
&& arg_scope
!= UNIT_FILE_SYSTEM
) {
4296 log_error("Cannot access user instance remotely.");
4303 static int halt_parse_argv(int argc
, char *argv
[]) {
4312 static const struct option options
[] = {
4313 { "help", no_argument
, NULL
, ARG_HELP
},
4314 { "halt", no_argument
, NULL
, ARG_HALT
},
4315 { "poweroff", no_argument
, NULL
, 'p' },
4316 { "reboot", no_argument
, NULL
, ARG_REBOOT
},
4317 { "force", no_argument
, NULL
, 'f' },
4318 { "wtmp-only", no_argument
, NULL
, 'w' },
4319 { "no-wtmp", no_argument
, NULL
, 'd' },
4320 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
4321 { NULL
, 0, NULL
, 0 }
4329 if (utmp_get_runlevel(&runlevel
, NULL
) >= 0)
4330 if (runlevel
== '0' || runlevel
== '6')
4333 while ((c
= getopt_long(argc
, argv
, "pfwdnih", options
, NULL
)) >= 0) {
4341 arg_action
= ACTION_HALT
;
4345 if (arg_action
!= ACTION_REBOOT
)
4346 arg_action
= ACTION_POWEROFF
;
4350 arg_action
= ACTION_REBOOT
;
4372 /* Compatibility nops */
4379 log_error("Unknown option code '%c'.", c
);
4384 if (optind
< argc
) {
4385 log_error("Too many arguments.");
4392 static int parse_time_spec(const char *t
, usec_t
*_u
) {
4396 if (streq(t
, "now"))
4398 else if (!strchr(t
, ':')) {
4401 if (safe_atou64(t
, &u
) < 0)
4404 *_u
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
* u
;
4413 hour
= strtol(t
, &e
, 10);
4414 if (errno
!= 0 || *e
!= ':' || hour
< 0 || hour
> 23)
4417 minute
= strtol(e
+1, &e
, 10);
4418 if (errno
!= 0 || *e
!= 0 || minute
< 0 || minute
> 59)
4421 n
= now(CLOCK_REALTIME
);
4422 s
= (time_t) (n
/ USEC_PER_SEC
);
4425 assert_se(localtime_r(&s
, &tm
));
4427 tm
.tm_hour
= (int) hour
;
4428 tm
.tm_min
= (int) minute
;
4431 assert_se(s
= mktime(&tm
));
4433 *_u
= (usec_t
) s
* USEC_PER_SEC
;
4436 *_u
+= USEC_PER_DAY
;
4442 static int shutdown_parse_argv(int argc
, char *argv
[]) {
4449 static const struct option options
[] = {
4450 { "help", no_argument
, NULL
, ARG_HELP
},
4451 { "halt", no_argument
, NULL
, 'H' },
4452 { "poweroff", no_argument
, NULL
, 'P' },
4453 { "reboot", no_argument
, NULL
, 'r' },
4454 { "kexec", no_argument
, NULL
, 'K' }, /* not documented extension */
4455 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
4456 { NULL
, 0, NULL
, 0 }
4464 while ((c
= getopt_long(argc
, argv
, "HPrhkt:afFc", options
, NULL
)) >= 0) {
4472 arg_action
= ACTION_HALT
;
4476 arg_action
= ACTION_POWEROFF
;
4481 arg_action
= ACTION_KEXEC
;
4483 arg_action
= ACTION_REBOOT
;
4487 arg_action
= ACTION_KEXEC
;
4491 if (arg_action
!= ACTION_HALT
)
4492 arg_action
= ACTION_POWEROFF
;
4505 /* Compatibility nops */
4509 arg_action
= ACTION_CANCEL_SHUTDOWN
;
4516 log_error("Unknown option code '%c'.", c
);
4521 if (argc
> optind
&& arg_action
!= ACTION_CANCEL_SHUTDOWN
) {
4522 r
= parse_time_spec(argv
[optind
], &arg_when
);
4524 log_error("Failed to parse time specification: %s", argv
[optind
]);
4528 arg_when
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
;
4530 if (argc
> optind
&& arg_action
== ACTION_CANCEL_SHUTDOWN
)
4531 /* No time argument for shutdown cancel */
4532 arg_wall
= argv
+ optind
;
4533 else if (argc
> optind
+ 1)
4534 /* We skip the time argument */
4535 arg_wall
= argv
+ optind
+ 1;
4542 static int telinit_parse_argv(int argc
, char *argv
[]) {
4549 static const struct option options
[] = {
4550 { "help", no_argument
, NULL
, ARG_HELP
},
4551 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
4552 { NULL
, 0, NULL
, 0 }
4555 static const struct {
4559 { '0', ACTION_POWEROFF
},
4560 { '6', ACTION_REBOOT
},
4561 { '1', ACTION_RESCUE
},
4562 { '2', ACTION_RUNLEVEL2
},
4563 { '3', ACTION_RUNLEVEL3
},
4564 { '4', ACTION_RUNLEVEL4
},
4565 { '5', ACTION_RUNLEVEL5
},
4566 { 's', ACTION_RESCUE
},
4567 { 'S', ACTION_RESCUE
},
4568 { 'q', ACTION_RELOAD
},
4569 { 'Q', ACTION_RELOAD
},
4570 { 'u', ACTION_REEXEC
},
4571 { 'U', ACTION_REEXEC
}
4580 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0) {
4595 log_error("Unknown option code '%c'.", c
);
4600 if (optind
>= argc
) {
4605 if (optind
+ 1 < argc
) {
4606 log_error("Too many arguments.");
4610 if (strlen(argv
[optind
]) != 1) {
4611 log_error("Expected single character argument.");
4615 for (i
= 0; i
< ELEMENTSOF(table
); i
++)
4616 if (table
[i
].from
== argv
[optind
][0])
4619 if (i
>= ELEMENTSOF(table
)) {
4620 log_error("Unknown command '%s'.", argv
[optind
]);
4624 arg_action
= table
[i
].to
;
4631 static int runlevel_parse_argv(int argc
, char *argv
[]) {
4637 static const struct option options
[] = {
4638 { "help", no_argument
, NULL
, ARG_HELP
},
4639 { NULL
, 0, NULL
, 0 }
4647 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0) {
4658 log_error("Unknown option code '%c'.", c
);
4663 if (optind
< argc
) {
4664 log_error("Too many arguments.");
4671 static int parse_argv(int argc
, char *argv
[]) {
4675 if (program_invocation_short_name
) {
4677 if (strstr(program_invocation_short_name
, "halt")) {
4678 arg_action
= ACTION_HALT
;
4679 return halt_parse_argv(argc
, argv
);
4680 } else if (strstr(program_invocation_short_name
, "poweroff")) {
4681 arg_action
= ACTION_POWEROFF
;
4682 return halt_parse_argv(argc
, argv
);
4683 } else if (strstr(program_invocation_short_name
, "reboot")) {
4685 arg_action
= ACTION_KEXEC
;
4687 arg_action
= ACTION_REBOOT
;
4688 return halt_parse_argv(argc
, argv
);
4689 } else if (strstr(program_invocation_short_name
, "shutdown")) {
4690 arg_action
= ACTION_POWEROFF
;
4691 return shutdown_parse_argv(argc
, argv
);
4692 } else if (strstr(program_invocation_short_name
, "init")) {
4694 if (sd_booted() > 0) {
4695 arg_action
= ACTION_INVALID
;
4696 return telinit_parse_argv(argc
, argv
);
4698 /* Hmm, so some other init system is
4699 * running, we need to forward this
4700 * request to it. For now we simply
4701 * guess that it is Upstart. */
4703 execv("/lib/upstart/telinit", argv
);
4705 log_error("Couldn't find an alternative telinit implementation to spawn.");
4709 } else if (strstr(program_invocation_short_name
, "runlevel")) {
4710 arg_action
= ACTION_RUNLEVEL
;
4711 return runlevel_parse_argv(argc
, argv
);
4715 arg_action
= ACTION_SYSTEMCTL
;
4716 return systemctl_parse_argv(argc
, argv
);
4719 static int action_to_runlevel(void) {
4721 static const char table
[_ACTION_MAX
] = {
4722 [ACTION_HALT
] = '0',
4723 [ACTION_POWEROFF
] = '0',
4724 [ACTION_REBOOT
] = '6',
4725 [ACTION_RUNLEVEL2
] = '2',
4726 [ACTION_RUNLEVEL3
] = '3',
4727 [ACTION_RUNLEVEL4
] = '4',
4728 [ACTION_RUNLEVEL5
] = '5',
4729 [ACTION_RESCUE
] = '1'
4732 assert(arg_action
< _ACTION_MAX
);
4734 return table
[arg_action
];
4737 static int talk_upstart(void) {
4738 DBusMessage
*m
= NULL
, *reply
= NULL
;
4740 int previous
, rl
, r
;
4742 env1_buf
[] = "RUNLEVEL=X",
4743 env2_buf
[] = "PREVLEVEL=X";
4744 char *env1
= env1_buf
, *env2
= env2_buf
;
4745 const char *emit
= "runlevel";
4746 dbus_bool_t b_false
= FALSE
;
4747 DBusMessageIter iter
, sub
;
4748 DBusConnection
*bus
;
4750 dbus_error_init(&error
);
4752 if (!(rl
= action_to_runlevel()))
4755 if (utmp_get_runlevel(&previous
, NULL
) < 0)
4758 if (!(bus
= dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error
))) {
4759 if (dbus_error_has_name(&error
, DBUS_ERROR_NO_SERVER
)) {
4764 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error
));
4769 if ((r
= bus_check_peercred(bus
)) < 0) {
4770 log_error("Failed to verify owner of bus.");
4774 if (!(m
= dbus_message_new_method_call(
4775 "com.ubuntu.Upstart",
4776 "/com/ubuntu/Upstart",
4777 "com.ubuntu.Upstart0_6",
4780 log_error("Could not allocate message.");
4785 dbus_message_iter_init_append(m
, &iter
);
4787 env1_buf
[sizeof(env1_buf
)-2] = rl
;
4788 env2_buf
[sizeof(env2_buf
)-2] = previous
;
4790 if (!dbus_message_iter_append_basic(&iter
, DBUS_TYPE_STRING
, &emit
) ||
4791 !dbus_message_iter_open_container(&iter
, DBUS_TYPE_ARRAY
, "s", &sub
) ||
4792 !dbus_message_iter_append_basic(&sub
, DBUS_TYPE_STRING
, &env1
) ||
4793 !dbus_message_iter_append_basic(&sub
, DBUS_TYPE_STRING
, &env2
) ||
4794 !dbus_message_iter_close_container(&iter
, &sub
) ||
4795 !dbus_message_iter_append_basic(&iter
, DBUS_TYPE_BOOLEAN
, &b_false
)) {
4796 log_error("Could not append arguments to message.");
4801 if (!(reply
= dbus_connection_send_with_reply_and_block(bus
, m
, -1, &error
))) {
4803 if (bus_error_is_no_service(&error
)) {
4808 log_error("Failed to issue method call: %s", bus_error_message(&error
));
4817 dbus_message_unref(m
);
4820 dbus_message_unref(reply
);
4823 dbus_connection_flush(bus
);
4824 dbus_connection_close(bus
);
4825 dbus_connection_unref(bus
);
4828 dbus_error_free(&error
);
4833 static int talk_initctl(void) {
4834 struct init_request request
;
4838 if (!(rl
= action_to_runlevel()))
4842 request
.magic
= INIT_MAGIC
;
4843 request
.sleeptime
= 0;
4844 request
.cmd
= INIT_CMD_RUNLVL
;
4845 request
.runlevel
= rl
;
4847 if ((fd
= open(INIT_FIFO
, O_WRONLY
|O_NDELAY
|O_CLOEXEC
|O_NOCTTY
)) < 0) {
4849 if (errno
== ENOENT
)
4852 log_error("Failed to open "INIT_FIFO
": %m");
4857 r
= loop_write(fd
, &request
, sizeof(request
), false) != sizeof(request
);
4858 close_nointr_nofail(fd
);
4861 log_error("Failed to write to "INIT_FIFO
": %m");
4862 return errno
? -errno
: -EIO
;
4868 static int systemctl_main(DBusConnection
*bus
, int argc
, char *argv
[], DBusError
*error
) {
4870 static const struct {
4878 int (* const dispatch
)(DBusConnection
*bus
, char **args
);
4880 { "list-units", LESS
, 1, list_units
},
4881 { "list-unit-files", EQUAL
, 1, list_unit_files
},
4882 { "list-jobs", EQUAL
, 1, list_jobs
},
4883 { "clear-jobs", EQUAL
, 1, daemon_reload
},
4884 { "load", MORE
, 2, load_unit
},
4885 { "cancel", MORE
, 2, cancel_job
},
4886 { "start", MORE
, 2, start_unit
},
4887 { "stop", MORE
, 2, start_unit
},
4888 { "condstop", MORE
, 2, start_unit
}, /* For compatibility with ALTLinux */
4889 { "reload", MORE
, 2, start_unit
},
4890 { "restart", MORE
, 2, start_unit
},
4891 { "try-restart", MORE
, 2, start_unit
},
4892 { "reload-or-restart", MORE
, 2, start_unit
},
4893 { "reload-or-try-restart", MORE
, 2, start_unit
},
4894 { "force-reload", MORE
, 2, start_unit
}, /* For compatibility with SysV */
4895 { "condreload", MORE
, 2, start_unit
}, /* For compatibility with ALTLinux */
4896 { "condrestart", MORE
, 2, start_unit
}, /* For compatibility with RH */
4897 { "isolate", EQUAL
, 2, start_unit
},
4898 { "kill", MORE
, 2, kill_unit
},
4899 { "is-active", MORE
, 2, check_unit
},
4900 { "check", MORE
, 2, check_unit
},
4901 { "show", MORE
, 1, show
},
4902 { "status", MORE
, 2, show
},
4903 { "help", MORE
, 2, show
},
4904 { "dump", EQUAL
, 1, dump
},
4905 { "dot", EQUAL
, 1, dot
},
4906 { "snapshot", LESS
, 2, snapshot
},
4907 { "delete", MORE
, 2, delete_snapshot
},
4908 { "daemon-reload", EQUAL
, 1, daemon_reload
},
4909 { "daemon-reexec", EQUAL
, 1, daemon_reload
},
4910 { "show-environment", EQUAL
, 1, show_enviroment
},
4911 { "set-environment", MORE
, 2, set_environment
},
4912 { "unset-environment", MORE
, 2, set_environment
},
4913 { "halt", EQUAL
, 1, start_special
},
4914 { "poweroff", EQUAL
, 1, start_special
},
4915 { "reboot", EQUAL
, 1, start_special
},
4916 { "kexec", EQUAL
, 1, start_special
},
4917 { "suspend", EQUAL
, 1, start_special
},
4918 { "hibernate", EQUAL
, 1, start_special
},
4919 { "default", EQUAL
, 1, start_special
},
4920 { "rescue", EQUAL
, 1, start_special
},
4921 { "emergency", EQUAL
, 1, start_special
},
4922 { "exit", EQUAL
, 1, start_special
},
4923 { "reset-failed", MORE
, 1, reset_failed
},
4924 { "enable", MORE
, 2, enable_unit
},
4925 { "disable", MORE
, 2, enable_unit
},
4926 { "is-enabled", MORE
, 2, unit_is_enabled
},
4927 { "reenable", MORE
, 2, enable_unit
},
4928 { "preset", MORE
, 2, enable_unit
},
4929 { "mask", MORE
, 2, enable_unit
},
4930 { "unmask", MORE
, 2, enable_unit
},
4931 { "link", MORE
, 2, enable_unit
},
4932 { "switch-root", MORE
, 2, switch_root
},
4942 left
= argc
- optind
;
4945 /* Special rule: no arguments means "list-units" */
4948 if (streq(argv
[optind
], "help") && !argv
[optind
+1]) {
4949 log_error("This command expects one or more "
4950 "unit names. Did you mean --help?");
4954 for (i
= 0; i
< ELEMENTSOF(verbs
); i
++)
4955 if (streq(argv
[optind
], verbs
[i
].verb
))
4958 if (i
>= ELEMENTSOF(verbs
)) {
4959 log_error("Unknown operation '%s'.", argv
[optind
]);
4964 switch (verbs
[i
].argc_cmp
) {
4967 if (left
!= verbs
[i
].argc
) {
4968 log_error("Invalid number of arguments.");
4975 if (left
< verbs
[i
].argc
) {
4976 log_error("Too few arguments.");
4983 if (left
> verbs
[i
].argc
) {
4984 log_error("Too many arguments.");
4991 assert_not_reached("Unknown comparison operator.");
4994 /* Require a bus connection for all operations but
4996 if (!streq(verbs
[i
].verb
, "enable") &&
4997 !streq(verbs
[i
].verb
, "disable") &&
4998 !streq(verbs
[i
].verb
, "is-enabled") &&
4999 !streq(verbs
[i
].verb
, "list-unit-files") &&
5000 !streq(verbs
[i
].verb
, "reenable") &&
5001 !streq(verbs
[i
].verb
, "preset") &&
5002 !streq(verbs
[i
].verb
, "mask") &&
5003 !streq(verbs
[i
].verb
, "unmask") &&
5004 !streq(verbs
[i
].verb
, "link")) {
5006 if (running_in_chroot() > 0) {
5007 log_info("Running in chroot, ignoring request.");
5011 if (((!streq(verbs
[i
].verb
, "reboot") &&
5012 !streq(verbs
[i
].verb
, "halt") &&
5013 !streq(verbs
[i
].verb
, "poweroff")) || arg_force
<= 0) && !bus
) {
5014 log_error("Failed to get D-Bus connection: %s",
5015 dbus_error_is_set(error
) ? error
->message
: "No connection to service manager.");
5021 if (!bus
&& !avoid_bus()) {
5022 log_error("Failed to get D-Bus connection: %s",
5023 dbus_error_is_set(error
) ? error
->message
: "No connection to service manager.");
5028 return verbs
[i
].dispatch(bus
, argv
+ optind
);
5031 static int send_shutdownd(usec_t t
, char mode
, bool dry_run
, bool warn
, const char *message
) {
5033 struct msghdr msghdr
;
5034 struct iovec iovec
[2];
5035 union sockaddr_union sockaddr
;
5036 struct sd_shutdown_command c
;
5038 fd
= socket(AF_UNIX
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0);
5045 c
.dry_run
= dry_run
;
5049 sockaddr
.sa
.sa_family
= AF_UNIX
;
5050 strncpy(sockaddr
.un
.sun_path
, "/run/systemd/shutdownd", sizeof(sockaddr
.un
.sun_path
));
5053 msghdr
.msg_name
= &sockaddr
;
5054 msghdr
.msg_namelen
= offsetof(struct sockaddr_un
, sun_path
) + sizeof("/run/systemd/shutdownd") - 1;
5057 iovec
[0].iov_base
= (char*) &c
;
5058 iovec
[0].iov_len
= offsetof(struct sd_shutdown_command
, wall_message
);
5060 if (isempty(message
))
5061 msghdr
.msg_iovlen
= 1;
5063 iovec
[1].iov_base
= (char*) message
;
5064 iovec
[1].iov_len
= strlen(message
);
5065 msghdr
.msg_iovlen
= 2;
5067 msghdr
.msg_iov
= iovec
;
5069 if (sendmsg(fd
, &msghdr
, MSG_NOSIGNAL
) < 0) {
5070 close_nointr_nofail(fd
);
5074 close_nointr_nofail(fd
);
5078 static int reload_with_fallback(DBusConnection
*bus
) {
5081 /* First, try systemd via D-Bus. */
5082 if (daemon_reload(bus
, NULL
) >= 0)
5086 /* Nothing else worked, so let's try signals */
5087 assert(arg_action
== ACTION_RELOAD
|| arg_action
== ACTION_REEXEC
);
5089 if (kill(1, arg_action
== ACTION_RELOAD
? SIGHUP
: SIGTERM
) < 0) {
5090 log_error("kill() failed: %m");
5097 static int start_with_fallback(DBusConnection
*bus
) {
5100 /* First, try systemd via D-Bus. */
5101 if (start_unit(bus
, NULL
) >= 0)
5105 /* Hmm, talking to systemd via D-Bus didn't work. Then
5106 * let's try to talk to Upstart via D-Bus. */
5107 if (talk_upstart() > 0)
5110 /* Nothing else worked, so let's try
5112 if (talk_initctl() > 0)
5115 log_error("Failed to talk to init daemon.");
5119 warn_wall(arg_action
);
5123 static _noreturn_
void halt_now(enum action a
) {
5125 /* Make sure C-A-D is handled by the kernel from this
5127 reboot(RB_ENABLE_CAD
);
5132 log_info("Halting.");
5133 reboot(RB_HALT_SYSTEM
);
5136 case ACTION_POWEROFF
:
5137 log_info("Powering off.");
5138 reboot(RB_POWER_OFF
);
5142 log_info("Rebooting.");
5143 reboot(RB_AUTOBOOT
);
5147 assert_not_reached("Unknown halt action.");
5150 assert_not_reached("Uh? This shouldn't happen.");
5153 static int halt_main(DBusConnection
*bus
) {
5156 if (geteuid() != 0) {
5157 /* Try logind if we are a normal user and no special
5158 * mode applies. Maybe PolicyKit allows us to shutdown
5161 if (arg_when
<= 0 &&
5164 (arg_action
== ACTION_POWEROFF
||
5165 arg_action
== ACTION_REBOOT
)) {
5166 r
= reboot_with_logind(bus
, arg_action
);
5171 log_error("Must be root.");
5178 m
= strv_join(arg_wall
, " ");
5179 r
= send_shutdownd(arg_when
,
5180 arg_action
== ACTION_HALT
? 'H' :
5181 arg_action
== ACTION_POWEROFF
? 'P' :
5182 arg_action
== ACTION_KEXEC
? 'K' :
5190 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r
));
5192 char date
[FORMAT_TIMESTAMP_MAX
];
5194 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5195 format_timestamp(date
, sizeof(date
), arg_when
));
5200 if (!arg_dry
&& !arg_force
)
5201 return start_with_fallback(bus
);
5204 if (sd_booted() > 0)
5205 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5207 r
= utmp_put_shutdown();
5209 log_warning("Failed to write utmp record: %s", strerror(-r
));
5216 halt_now(arg_action
);
5217 /* We should never reach this. */
5221 static int runlevel_main(void) {
5222 int r
, runlevel
, previous
;
5224 r
= utmp_get_runlevel(&runlevel
, &previous
);
5231 previous
<= 0 ? 'N' : previous
,
5232 runlevel
<= 0 ? 'N' : runlevel
);
5237 int main(int argc
, char*argv
[]) {
5238 int r
, retval
= EXIT_FAILURE
;
5239 DBusConnection
*bus
= NULL
;
5242 dbus_error_init(&error
);
5244 log_parse_environment();
5247 r
= parse_argv(argc
, argv
);
5251 retval
= EXIT_SUCCESS
;
5255 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5256 * let's shortcut this */
5257 if (arg_action
== ACTION_RUNLEVEL
) {
5258 r
= runlevel_main();
5259 retval
= r
< 0 ? EXIT_FAILURE
: r
;
5263 if (running_in_chroot() > 0 && arg_action
!= ACTION_SYSTEMCTL
) {
5264 log_info("Running in chroot, ignoring request.");
5270 if (arg_transport
== TRANSPORT_NORMAL
)
5271 bus_connect(arg_scope
== UNIT_FILE_SYSTEM
? DBUS_BUS_SYSTEM
: DBUS_BUS_SESSION
, &bus
, &private_bus
, &error
);
5272 else if (arg_transport
== TRANSPORT_POLKIT
) {
5273 bus_connect_system_polkit(&bus
, &error
);
5274 private_bus
= false;
5275 } else if (arg_transport
== TRANSPORT_SSH
) {
5276 bus_connect_system_ssh(NULL
, arg_host
, &bus
, &error
);
5277 private_bus
= false;
5279 assert_not_reached("Uh, invalid transport...");
5282 switch (arg_action
) {
5284 case ACTION_SYSTEMCTL
:
5285 r
= systemctl_main(bus
, argc
, argv
, &error
);
5289 case ACTION_POWEROFF
:
5295 case ACTION_RUNLEVEL2
:
5296 case ACTION_RUNLEVEL3
:
5297 case ACTION_RUNLEVEL4
:
5298 case ACTION_RUNLEVEL5
:
5300 case ACTION_EMERGENCY
:
5301 case ACTION_DEFAULT
:
5302 r
= start_with_fallback(bus
);
5307 r
= reload_with_fallback(bus
);
5310 case ACTION_CANCEL_SHUTDOWN
: {
5314 m
= strv_join(arg_wall
, " ");
5316 retval
= EXIT_FAILURE
;
5320 r
= send_shutdownd(arg_when
, SD_SHUTDOWN_NONE
, false, !arg_no_wall
, m
);
5322 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r
));
5327 case ACTION_INVALID
:
5328 case ACTION_RUNLEVEL
:
5330 assert_not_reached("Unknown action");
5333 retval
= r
< 0 ? EXIT_FAILURE
: r
;
5337 dbus_connection_flush(bus
);
5338 dbus_connection_close(bus
);
5339 dbus_connection_unref(bus
);
5342 dbus_error_free(&error
);
5346 strv_free(arg_property
);
5349 ask_password_agent_close();
5350 polkit_agent_close();